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%08x\n", hr)
36 
37 #ifdef __i386__
38 static const int tmarshal_todo = 0;
39 #else
40 static const int tmarshal_todo = 1;
41 #endif
42 
43 /* ULL suffix is not portable */
44 #define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
45 
46 const MYSTRUCT MYSTRUCT_BYVAL = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432), {0,1,2,3,4,5,6,7}};
47 const MYSTRUCT MYSTRUCT_BYPTR = {0x91827364, ULL_CONST(0x88776655, 0x44332211), {0,1,2,3,4,5,6,7}};
48 const MYSTRUCT MYSTRUCT_ARRAY[5] = {
49     {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415), {0,1,2,3,4,5,6,7}},
50     {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425), {0,1,2,3,4,5,6,7}},
51     {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435), {0,1,2,3,4,5,6,7}},
52     {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445), {0,1,2,3,4,5,6,7}},
53     {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455), {0,1,2,3,4,5,6,7}},
54 };
55 
56 
57 #define RELEASEMARSHALDATA WM_USER
58 
59 struct host_object_data
60 {
61     IStream *stream;
62     IID iid;
63     IUnknown *object;
64     MSHLFLAGS marshal_flags;
65     HANDLE marshal_event;
66     IMessageFilter *filter;
67 };
68 
69 static DWORD CALLBACK host_object_proc(LPVOID p)
70 {
71     struct host_object_data *data = p;
72     HRESULT hr;
73     MSG msg;
74 
75     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
76 
77     if (data->filter)
78     {
79         IMessageFilter * prev_filter = NULL;
80         hr = CoRegisterMessageFilter(data->filter, &prev_filter);
81         if (prev_filter) IMessageFilter_Release(prev_filter);
82         ok_ole_success(hr, CoRegisterMessageFilter);
83     }
84 
85     hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
86     ok_ole_success(hr, CoMarshalInterface);
87 
88     /* force the message queue to be created before signaling parent thread */
89     PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
90 
91     SetEvent(data->marshal_event);
92 
93     while (GetMessageA(&msg, NULL, 0, 0))
94     {
95         if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
96         {
97             trace("releasing marshal data\n");
98             CoReleaseMarshalData(data->stream);
99             SetEvent((HANDLE)msg.lParam);
100         }
101         else
102             DispatchMessageA(&msg);
103     }
104 
105     HeapFree(GetProcessHeap(), 0, data);
106 
107     CoUninitialize();
108 
109     return hr;
110 }
111 
112 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
113 {
114     DWORD tid = 0;
115     HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
116     struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
117 
118     data->stream = stream;
119     data->iid = *riid;
120     data->object = object;
121     data->marshal_flags = marshal_flags;
122     data->marshal_event = marshal_event;
123     data->filter = filter;
124 
125     *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
126 
127     /* wait for marshaling to complete before returning */
128     WaitForSingleObject(marshal_event, INFINITE);
129     CloseHandle(marshal_event);
130 
131     return tid;
132 }
133 
134 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
135 {
136     return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
137 }
138 
139 #if 0 /* not used */
140 /* asks thread to release the marshal data because it has to be done by the
141  * same thread that marshaled the interface in the first place. */
142 static void release_host_object(DWORD tid)
143 {
144     HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
145     PostThreadMessageA(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
146     WaitForSingleObject(event, INFINITE);
147     CloseHandle(event);
148 }
149 #endif
150 
151 static void end_host_object(DWORD tid, HANDLE thread)
152 {
153     BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
154     ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
155     /* be careful of races - don't return until hosting thread has terminated */
156     WaitForSingleObject(thread, INFINITE);
157     CloseHandle(thread);
158 }
159 
160 static int external_connections;
161 static BOOL expect_last_release_closes;
162 
163 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
164 {
165     ok(0, "unexpected call\n");
166     *ppv = NULL;
167     return E_NOINTERFACE;
168 }
169 
170 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
171 {
172     return 2;
173 }
174 
175 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
176 {
177     return 1;
178 }
179 
180 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
181 {
182     trace("add connection\n");
183 
184     ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
185     ok(!reserved, "reserved = %x\n", reserved);
186     return ++external_connections;
187 }
188 
189 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
190         DWORD reserved, BOOL fLastReleaseCloses)
191 {
192     trace("release connection\n");
193 
194     ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
195     ok(!reserved, "reserved = %x\n", reserved);
196 
197     ok(fLastReleaseCloses == expect_last_release_closes, "fLastReleaseCloses = %x, expected %x\n",
198        fLastReleaseCloses, expect_last_release_closes);
199     return --external_connections;
200 }
201 
202 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
203     ExternalConnection_QueryInterface,
204     ExternalConnection_AddRef,
205     ExternalConnection_Release,
206     ExternalConnection_AddConnection,
207     ExternalConnection_ReleaseConnection
208 };
209 
210 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
211 
212 static ItestDual TestDual, TestDualDisp;
213 
214 static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
215 {
216     return ItestDual_QueryInterface(&TestDual, riid, ppv);
217 }
218 
219 static ULONG WINAPI TestSecondIface_AddRef(ITestSecondIface *iface)
220 {
221     return 2;
222 }
223 
224 static ULONG WINAPI TestSecondIface_Release(ITestSecondIface *iface)
225 {
226     return 1;
227 }
228 
229 static HRESULT WINAPI TestSecondIface_test(ITestSecondIface *iface)
230 {
231     return 1;
232 }
233 
234 static const ITestSecondIfaceVtbl TestSecondIfaceVtbl = {
235     TestSecondIface_QueryInterface,
236     TestSecondIface_AddRef,
237     TestSecondIface_Release,
238     TestSecondIface_test
239 };
240 
241 static ITestSecondIface TestSecondIface = { &TestSecondIfaceVtbl };
242 
243 static HRESULT WINAPI TestSecondDisp_QueryInterface(ITestSecondDisp *iface, REFIID riid, void **ppv)
244 {
245     return ItestDual_QueryInterface(&TestDual, riid, ppv);
246 }
247 
248 static ULONG WINAPI TestSecondDisp_AddRef(ITestSecondDisp *iface)
249 {
250     return 2;
251 }
252 
253 static ULONG WINAPI TestSecondDisp_Release(ITestSecondDisp *iface)
254 {
255     return 1;
256 }
257 
258 static HRESULT WINAPI TestSecondDisp_GetTypeInfoCount(ITestSecondDisp *iface, UINT *pctinfo)
259 {
260     ok(0, "unexpected call\n");
261     return E_NOTIMPL;
262 }
263 
264 static HRESULT WINAPI TestSecondDisp_GetTypeInfo(ITestSecondDisp *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
265 {
266     ok(0, "unexpected call\n");
267     return E_NOTIMPL;
268 }
269 
270 static HRESULT WINAPI TestSecondDisp_GetIDsOfNames(ITestSecondDisp *iface, REFIID riid, LPOLESTR *rgszNames,
271         UINT cNames, LCID lcid, DISPID *rgDispId)
272 {
273     ok(0, "unexpected call\n");
274     return E_NOTIMPL;
275 }
276 
277 static HRESULT WINAPI TestSecondDisp_Invoke(ITestSecondDisp *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
278         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
279         UINT *puArgErr)
280 {
281     ok(0, "unexpected call\n");
282     return E_NOTIMPL;
283 }
284 
285 static HRESULT WINAPI TestSecondDisp_test(ITestSecondDisp *iface)
286 {
287     ok(0, "unexpected call\n");
288     return E_NOTIMPL;
289 }
290 
291 static ITestSecondDispVtbl TestSecondDispVtbl = {
292     TestSecondDisp_QueryInterface,
293     TestSecondDisp_AddRef,
294     TestSecondDisp_Release,
295     TestSecondDisp_GetTypeInfoCount,
296     TestSecondDisp_GetTypeInfo,
297     TestSecondDisp_GetIDsOfNames,
298     TestSecondDisp_Invoke,
299     TestSecondDisp_test
300 };
301 
302 static ITestSecondDisp TestSecondDisp = { &TestSecondDispVtbl };
303 
304 static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, void **ppvObject)
305 {
306     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) {
307         *ppvObject = &TestDualDisp;
308         return S_OK;
309     }else if(IsEqualGUID(riid, &IID_ItestDual)) {
310         *ppvObject = &TestDual;
311         return S_OK;
312     }else if(IsEqualGUID(riid, &IID_ITestSecondIface)) {
313         *ppvObject = &TestSecondIface;
314         return S_OK;
315     }else if(IsEqualGUID(riid, &IID_ITestSecondDisp)) {
316         *ppvObject = &TestSecondDisp;
317         return S_OK;
318     }else if (IsEqualGUID(riid, &IID_IExternalConnection)) {
319         trace("QI external connection\n");
320         *ppvObject = &ExternalConnection;
321         return S_OK;
322     }
323 
324     *ppvObject = NULL;
325     return E_NOINTERFACE;
326 }
327 
328 static ULONG WINAPI TestDual_AddRef(ItestDual *iface)
329 {
330     return 2;
331 }
332 
333 static ULONG WINAPI TestDual_Release(ItestDual *iface)
334 {
335     return 1;
336 }
337 
338 static HRESULT WINAPI TestDual_GetTypeInfoCount(ItestDual *iface, UINT *pctinfo)
339 {
340     ok(0, "unexpected call\n");
341     return E_NOTIMPL;
342 }
343 
344 static HRESULT WINAPI TestDual_GetTypeInfo(ItestDual *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
345 {
346     ok(0, "unexpected call\n");
347     return E_NOTIMPL;
348 }
349 
350 static HRESULT WINAPI TestDual_GetIDsOfNames(ItestDual *iface, REFIID riid, LPOLESTR *rgszNames,
351         UINT cNames, LCID lcid, DISPID *rgDispId)
352 {
353     ok(0, "unexpected call\n");
354     return E_NOTIMPL;
355 }
356 
357 static HRESULT WINAPI TestDual_Invoke(ItestDual *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
358         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
359         UINT *puArgErr)
360 {
361     ok(0, "unexpected call\n");
362     return E_NOTIMPL;
363 }
364 
365 static ItestDualVtbl TestDualVtbl = {
366     TestDual_QueryInterface,
367     TestDual_AddRef,
368     TestDual_Release,
369     TestDual_GetTypeInfoCount,
370     TestDual_GetTypeInfo,
371     TestDual_GetIDsOfNames,
372     TestDual_Invoke
373 };
374 
375 static ItestDual TestDual = { &TestDualVtbl };
376 static ItestDual TestDualDisp = { &TestDualVtbl };
377 
378 typedef struct Widget
379 {
380     IWidget IWidget_iface;
381     LONG refs;
382     IUnknown *pDispatchUnknown;
383 } Widget;
384 
385 static inline Widget *impl_from_IWidget(IWidget *iface)
386 {
387     return CONTAINING_RECORD(iface, Widget, IWidget_iface);
388 }
389 
390 static HRESULT WINAPI Widget_QueryInterface(
391     IWidget *iface,
392     /* [in] */ REFIID riid,
393     /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
394 {
395     if (IsEqualIID(riid, &IID_IWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
396     {
397         IWidget_AddRef(iface);
398         *ppvObject = iface;
399         return S_OK;
400     }
401     else
402     {
403         *ppvObject = NULL;
404         return E_NOINTERFACE;
405     }
406 }
407 
408 static ULONG WINAPI Widget_AddRef(
409     IWidget *iface)
410 {
411     Widget *This = impl_from_IWidget(iface);
412 
413     return InterlockedIncrement(&This->refs);
414 }
415 
416 static ULONG WINAPI Widget_Release(
417     IWidget *iface)
418 {
419     Widget *This = impl_from_IWidget(iface);
420     ULONG refs = InterlockedDecrement(&This->refs);
421     if (!refs)
422     {
423         IUnknown_Release(This->pDispatchUnknown);
424         memset(This, 0xcc, sizeof(*This));
425         HeapFree(GetProcessHeap(), 0, This);
426         trace("Widget destroyed!\n");
427     }
428 
429     return refs;
430 }
431 
432 static HRESULT WINAPI Widget_GetTypeInfoCount(
433     IWidget *iface,
434     /* [out] */ UINT __RPC_FAR *pctinfo)
435 {
436     Widget *This = impl_from_IWidget(iface);
437     IDispatch *pDispatch;
438     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
439     if (SUCCEEDED(hr))
440     {
441         hr = IDispatch_GetTypeInfoCount(pDispatch, pctinfo);
442         IDispatch_Release(pDispatch);
443     }
444     return hr;
445 }
446 
447 static HRESULT WINAPI Widget_GetTypeInfo(
448     IWidget __RPC_FAR * iface,
449     /* [in] */ UINT iTInfo,
450     /* [in] */ LCID lcid,
451     /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
452 {
453     Widget *This = impl_from_IWidget(iface);
454     IDispatch *pDispatch;
455     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
456     if (SUCCEEDED(hr))
457     {
458         hr = IDispatch_GetTypeInfo(pDispatch, iTInfo, lcid, ppTInfo);
459         IDispatch_Release(pDispatch);
460     }
461     return hr;
462 }
463 
464 static HRESULT WINAPI Widget_GetIDsOfNames(
465     IWidget __RPC_FAR * iface,
466     /* [in] */ REFIID riid,
467     /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
468     /* [in] */ UINT cNames,
469     /* [in] */ LCID lcid,
470     /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
471 {
472     Widget *This = impl_from_IWidget(iface);
473     IDispatch *pDispatch;
474     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
475     if (SUCCEEDED(hr))
476     {
477         hr = IDispatch_GetIDsOfNames(pDispatch, riid, rgszNames, cNames, lcid, rgDispId);
478         IDispatch_Release(pDispatch);
479     }
480     return hr;
481 }
482 
483 static HRESULT WINAPI Widget_Invoke(
484     IWidget __RPC_FAR * iface,
485     /* [in] */ DISPID dispIdMember,
486     /* [in] */ REFIID riid,
487     /* [in] */ LCID lcid,
488     /* [in] */ WORD wFlags,
489     /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
490     /* [out] */ VARIANT __RPC_FAR *pVarResult,
491     /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
492     /* [out] */ UINT __RPC_FAR *puArgErr)
493 {
494     Widget *This = impl_from_IWidget(iface);
495     IDispatch *pDispatch;
496     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
497     if (SUCCEEDED(hr))
498     {
499         hr = IDispatch_Invoke(pDispatch, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
500         IDispatch_Release(pDispatch);
501     }
502     return hr;
503 }
504 
505 static HRESULT WINAPI Widget_put_Name(
506     IWidget __RPC_FAR * iface,
507     /* [in] */ BSTR name)
508 {
509     trace("put_Name(%s)\n", wine_dbgstr_w(name));
510     return S_OK;
511 }
512 
513 static HRESULT WINAPI Widget_get_Name(
514     IWidget __RPC_FAR * iface,
515     /* [out] */ BSTR __RPC_FAR *name)
516 {
517     static const WCHAR szCat[] = { 'C','a','t',0 };
518     trace("get_Name()\n");
519     *name = SysAllocString(szCat);
520     return S_OK;
521 }
522 
523 static HRESULT WINAPI Widget_DoSomething(
524     IWidget __RPC_FAR * iface,
525     /* [in] */ double number,
526     /* [out] */ BSTR *str1,
527     /* [defaultvalue][in] */ BSTR str2,
528     /* [optional][in] */ VARIANT __RPC_FAR *opt)
529 {
530     static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
531     trace("DoSomething()\n");
532 
533     ok(number == 3.141, "number(%f) != 3.141\n", number);
534     ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
535     ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt));
536     ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08x\n", V_ERROR(opt));
537     *str1 = SysAllocString(szString);
538 
539     return S_FALSE;
540 }
541 
542 static HRESULT WINAPI Widget_get_State(
543     IWidget __RPC_FAR * iface,
544     /* [retval][out] */ STATE __RPC_FAR *state)
545 {
546     trace("get_State() = STATE_WIDGETIFIED\n");
547     *state = STATE_WIDGETIFIED;
548     return S_OK;
549 }
550 
551 static HRESULT WINAPI Widget_put_State(
552     IWidget __RPC_FAR * iface,
553     /* [in] */ STATE state)
554 {
555     trace("put_State(%d)\n", state);
556     return S_OK;
557 }
558 
559 static HRESULT WINAPI Widget_Map(
560     IWidget * iface,
561     BSTR bstrId,
562     BSTR *sValue)
563 {
564     trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId), sValue);
565     *sValue = SysAllocString(bstrId);
566     return S_OK;
567 }
568 
569 static HRESULT WINAPI Widget_SetOleColor(
570     IWidget * iface,
571     OLE_COLOR val)
572 {
573     trace("SetOleColor(0x%x)\n", val);
574     return S_OK;
575 }
576 
577 static HRESULT WINAPI Widget_GetOleColor(
578     IWidget * iface,
579     OLE_COLOR *pVal)
580 {
581     trace("GetOleColor() = 0x8000000f\n");
582     *pVal = 0x8000000f;
583     return S_FALSE;
584 }
585 
586 static HRESULT WINAPI Widget_Clone(
587     IWidget *iface,
588     IWidget **ppVal)
589 {
590     trace("Clone()\n");
591     return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
592 }
593 
594 static HRESULT WINAPI Widget_CloneDispatch(
595     IWidget *iface,
596     IDispatch **ppVal)
597 {
598     trace("CloneDispatch()\n");
599     return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
600 }
601 
602 static HRESULT WINAPI Widget_CloneCoclass(
603     IWidget *iface,
604     ApplicationObject2 **ppVal)
605 {
606     trace("CloneCoclass()\n");
607     return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
608 }
609 
610 static HRESULT WINAPI Widget_Value(
611     IWidget __RPC_FAR * iface,
612     VARIANT *value,
613     VARIANT *retval)
614 {
615     trace("Value(%p, %p)\n", value, retval);
616     ok(V_VT(value) == VT_I2, "V_VT(value) was %d instead of VT_I2\n", V_VT(value));
617     ok(V_I2(value) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value));
618     V_VT(retval) = VT_I2;
619     V_I2(retval) = 1234;
620     return S_OK;
621 }
622 
623 static HRESULT WINAPI Widget_Array(
624     IWidget * iface,
625     SAFEARRAY * values)
626 {
627     trace("Array(%p)\n", values);
628     return S_OK;
629 }
630 
631 static HRESULT WINAPI Widget_VariantArrayPtr(
632     IWidget * iface,
633     SAFEARRAY ** values)
634 {
635     trace("VariantArrayPtr(%p)\n", values);
636     return S_OK;
637 }
638 
639 static HRESULT WINAPI Widget_VariantCArray(
640     IWidget * iface,
641     ULONG count,
642     VARIANT values[])
643 {
644     ULONG i;
645 
646     trace("VariantCArray(%u,%p)\n", count, values);
647 
648     ok(count == 2, "count is %d\n", count);
649     for (i = 0; i < count; i++)
650         ok(V_VT(&values[i]) == VT_I4, "values[%d] is not VT_I4\n", i);
651 
652     if (pVarAdd)
653     {
654         VARIANT inc, res;
655         HRESULT hr;
656 
657         V_VT(&inc) = VT_I4;
658         V_I4(&inc) = 1;
659         for (i = 0; i < count; i++) {
660             VariantInit(&res);
661             hr = pVarAdd(&values[i], &inc, &res);
662             if (FAILED(hr)) {
663                 ok(0, "VarAdd failed at %u with error 0x%x\n", i, hr);
664                 return hr;
665             }
666             hr = VariantCopy(&values[i], &res);
667             if (FAILED(hr)) {
668                 ok(0, "VariantCopy failed at %u with error 0x%x\n", i, hr);
669                 return hr;
670             }
671         }
672     }
673     else
674         win_skip("VarAdd is not available\n");
675 
676     return S_OK;
677 }
678 
679 static HRESULT WINAPI Widget_Variant(
680     IWidget __RPC_FAR * iface,
681     VARIANT var)
682 {
683     trace("Variant()\n");
684     ok(V_VT(&var) == VT_CY, "V_VT(&var) was %d\n", V_VT(&var));
685     ok(S(V_CY(&var)).Hi == 0xdababe, "V_CY(&var).Hi was 0x%x\n", S(V_CY(&var)).Hi);
686     ok(S(V_CY(&var)).Lo == 0xdeadbeef, "V_CY(&var).Lo was 0x%x\n", S(V_CY(&var)).Lo);
687     return S_OK;
688 }
689 
690 static HRESULT WINAPI Widget_VarArg(
691     IWidget * iface,
692     int numexpect,
693     SAFEARRAY * values)
694 {
695     LONG lbound, ubound, i;
696     VARIANT * data;
697     HRESULT hr;
698 
699     trace("VarArg(%p)\n", values);
700 
701     hr = SafeArrayGetLBound(values, 1, &lbound);
702     ok(hr == S_OK, "SafeArrayGetLBound failed with %x\n", hr);
703     ok(lbound == 0, "SafeArrayGetLBound returned %d\n", lbound);
704 
705     hr = SafeArrayGetUBound(values, 1, &ubound);
706     ok(hr == S_OK, "SafeArrayGetUBound failed with %x\n", hr);
707     ok(ubound == numexpect-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound, numexpect-1);
708 
709     hr = SafeArrayAccessData(values, (LPVOID)&data);
710     ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
711 
712     for (i=0; i<=ubound-lbound; i++)
713     {
714         ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%d]) was %d\n", i, V_VT(&data[i]));
715         ok(V_I4(&data[i]) == i, "V_I4(&data[%d]) was %d\n", i, V_I4(&data[i]));
716     }
717 
718     hr = SafeArrayUnaccessData(values);
719     ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr);
720 
721     return S_OK;
722 }
723 
724 
725 static BOOL mystruct_uint_ordered(MYSTRUCT *mystruct)
726 {
727     int i;
728     for (i = 0; i < sizeof(mystruct->uarr)/sizeof(mystruct->uarr[0]); i++)
729         if (mystruct->uarr[i] != i)
730             return FALSE;
731     return TRUE;
732 }
733 
734 static HRESULT WINAPI Widget_StructArgs(
735     IWidget * iface,
736     MYSTRUCT byval,
737     MYSTRUCT *byptr,
738     MYSTRUCT arr[5])
739 {
740     int i, diff = 0;
741     ok(byval.field1 == MYSTRUCT_BYVAL.field1 &&
742        byval.field2 == MYSTRUCT_BYVAL.field2 &&
743        mystruct_uint_ordered(&byval),
744        "Struct parameter passed by value corrupted\n");
745     ok(byptr->field1 == MYSTRUCT_BYPTR.field1 &&
746        byptr->field2 == MYSTRUCT_BYPTR.field2 &&
747        mystruct_uint_ordered(byptr),
748        "Struct parameter passed by pointer corrupted\n");
749     for (i = 0; i < 5; i++)
750         if (arr[i].field1 != MYSTRUCT_ARRAY[i].field1 ||
751             arr[i].field2 != MYSTRUCT_ARRAY[i].field2 ||
752             ! mystruct_uint_ordered(&arr[i]))
753             diff++;
754     ok(diff == 0, "Array of structs corrupted\n");
755     return S_OK;
756 }
757 
758 
759 static HRESULT WINAPI Widget_Error(
760     IWidget __RPC_FAR * iface)
761 {
762     trace("Error()\n");
763     return E_NOTIMPL;
764 }
765 
766 static HRESULT WINAPI Widget_CloneInterface(
767     IWidget __RPC_FAR * iface,
768     ISomethingFromDispatch **ppVal)
769 {
770     trace("CloneInterface()\n");
771     *ppVal = 0;
772     return S_OK;
773 }
774 
775 static HRESULT WINAPI Widget_put_prop_with_lcid(
776     IWidget* iface, LONG lcid, INT i)
777 {
778     trace("put_prop_with_lcid(%08x, %x)\n", lcid, i);
779     ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
780     ok(i == 0xcafe, "got %08x\n", i);
781     return S_OK;
782 }
783 
784 static HRESULT WINAPI Widget_get_prop_with_lcid(
785     IWidget* iface, LONG lcid, INT *i)
786 {
787     trace("get_prop_with_lcid(%08x, %p)\n", lcid, i);
788     ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
789     *i = lcid;
790     return S_OK;
791 }
792 
793 static HRESULT WINAPI Widget_get_prop_int(
794     IWidget* iface, INT *i)
795 {
796     trace("get_prop_int(%p)\n", i);
797     *i = -13;
798     return S_OK;
799 }
800 
801 static HRESULT WINAPI Widget_get_prop_uint(
802     IWidget* iface, UINT *i)
803 {
804     trace("get_prop_uint(%p)\n", i);
805     *i = 42;
806     return S_OK;
807 }
808 
809 static HRESULT WINAPI Widget_ByRefUInt(
810     IWidget* iface, UINT *i)
811 {
812     *i = 42;
813     return S_OK;
814 }
815 
816 static HRESULT WINAPI Widget_put_prop_opt_arg(
817     IWidget* iface, INT opt, INT i)
818 {
819     trace("put_prop_opt_arg(%08x, %08x)\n", opt, i);
820     todo_wine ok(opt == 0, "got opt=%08x\n", opt);
821     ok(i == 0xcafe, "got i=%08x\n", i);
822     return S_OK;
823 }
824 
825 static HRESULT WINAPI Widget_put_prop_req_arg(
826     IWidget* iface, INT req, INT i)
827 {
828     trace("put_prop_req_arg(%08x, %08x)\n", req, i);
829     ok(req == 0x5678, "got req=%08x\n", req);
830     ok(i == 0x1234, "got i=%08x\n", i);
831     return S_OK;
832 }
833 
834 static HRESULT WINAPI Widget_pos_restrict(IWidget* iface, INT *i)
835 {
836     trace("restrict\n");
837     *i = DISPID_TM_RESTRICTED;
838     return S_OK;
839 }
840 
841 static HRESULT WINAPI Widget_neg_restrict(IWidget* iface, INT *i)
842 {
843     trace("neg_restrict\n");
844     *i = DISPID_TM_NEG_RESTRICTED;
845     return S_OK;
846 }
847 
848 static HRESULT WINAPI Widget_VarArg_Run(
849     IWidget *iface, BSTR name, SAFEARRAY *params, VARIANT *result)
850 {
851     static const WCHAR catW[] = { 'C','a','t',0 };
852     static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
853     LONG bound;
854     VARIANT *var;
855     BSTR bstr;
856     HRESULT hr;
857 
858     trace("VarArg_Run(%p,%p,%p)\n", name, params, result);
859 
860     ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
861 
862     hr = SafeArrayGetLBound(params, 1, &bound);
863     ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
864     ok(bound == 0, "expected 0, got %d\n", bound);
865 
866     hr = SafeArrayGetUBound(params, 1, &bound);
867     ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
868     ok(bound == 0, "expected 0, got %d\n", bound);
869 
870     hr = SafeArrayAccessData(params, (void **)&var);
871     ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
872 
873     ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
874     bstr = V_BSTR(&var[0]);
875     ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
876 
877     hr = SafeArrayUnaccessData(params);
878     ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
879 
880     return S_OK;
881 }
882 
883 static HRESULT WINAPI Widget_VarArg_Ref_Run(
884     IWidget *iface, BSTR name, SAFEARRAY **params, VARIANT *result)
885 {
886     static const WCHAR catW[] = { 'C','a','t',0 };
887     static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
888     LONG bound;
889     VARIANT *var;
890     BSTR bstr;
891     HRESULT hr;
892 
893     trace("VarArg_Ref_Run(%p,%p,%p)\n", name, params, result);
894 
895     ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
896 
897     hr = SafeArrayGetLBound(*params, 1, &bound);
898     ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
899     ok(bound == 0, "expected 0, got %d\n", bound);
900 
901     hr = SafeArrayGetUBound(*params, 1, &bound);
902     ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
903     ok(bound == 0, "expected 0, got %d\n", bound);
904 
905     hr = SafeArrayAccessData(*params, (void **)&var);
906     ok(hr == S_OK, "SafeArrayAccessData error %#x\n", hr);
907 
908     ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
909     bstr = V_BSTR(&var[0]);
910     ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
911 
912     hr = SafeArrayUnaccessData(*params);
913     ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
914 
915     return S_OK;
916 }
917 
918 static HRESULT WINAPI Widget_Coclass(
919     IWidget *iface, ApplicationObject2 *param)
920 {
921     trace("Coclass(%p)\n", param);
922     ok(param == (ApplicationObject2 *)iface, "expected param == %p, got %p\n", iface, param);
923     return S_OK;
924 }
925 
926 static const struct IWidgetVtbl Widget_VTable =
927 {
928     Widget_QueryInterface,
929     Widget_AddRef,
930     Widget_Release,
931     Widget_GetTypeInfoCount,
932     Widget_GetTypeInfo,
933     Widget_GetIDsOfNames,
934     Widget_Invoke,
935     Widget_put_Name,
936     Widget_get_Name,
937     Widget_DoSomething,
938     Widget_get_State,
939     Widget_put_State,
940     Widget_Map,
941     Widget_SetOleColor,
942     Widget_GetOleColor,
943     Widget_Clone,
944     Widget_CloneDispatch,
945     Widget_CloneCoclass,
946     Widget_Value,
947     Widget_Array,
948     Widget_VariantArrayPtr,
949     Widget_VariantCArray,
950     Widget_Variant,
951     Widget_VarArg,
952     Widget_StructArgs,
953     Widget_Error,
954     Widget_CloneInterface,
955     Widget_put_prop_with_lcid,
956     Widget_get_prop_with_lcid,
957     Widget_get_prop_int,
958     Widget_get_prop_uint,
959     Widget_ByRefUInt,
960     Widget_put_prop_opt_arg,
961     Widget_put_prop_req_arg,
962     Widget_pos_restrict,
963     Widget_neg_restrict,
964     Widget_VarArg_Run,
965     Widget_VarArg_Ref_Run,
966     Widget_Coclass,
967 };
968 
969 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
970 {
971     if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
972     {
973         IStaticWidget_AddRef(iface);
974         *ppvObject = iface;
975         return S_OK;
976     }
977 
978     *ppvObject = NULL;
979     return E_NOINTERFACE;
980 }
981 
982 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
983 {
984     return 2;
985 }
986 
987 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
988 {
989     return 1;
990 }
991 
992 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
993 {
994     ok(0, "unexpected call\n");
995     return E_NOTIMPL;
996 }
997 
998 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
999         ITypeInfo **ppTInfo)
1000 {
1001     ok(0, "unexpected call\n");
1002     return E_NOTIMPL;
1003 }
1004 
1005 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
1006         UINT cNames, LCID lcid, DISPID *rgDispId)
1007 {
1008     ok(0, "unexpected call\n");
1009     return E_NOTIMPL;
1010 }
1011 
1012 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
1013         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1014          UINT *puArgErr)
1015 {
1016     ok(0, "unexpected call\n");
1017     return E_NOTIMPL;
1018 }
1019 
1020 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
1021 {
1022     trace("TestDual()\n");
1023     ok(p == &TestDual, "wrong ItestDual\n");
1024     return S_OK;
1025 }
1026 
1027 static HRESULT WINAPI StaticWidget_TestSecondIface(IStaticWidget *iface, ITestSecondIface *p)
1028 {
1029     trace("TestSecondIface()\n");
1030     ok(p == &TestSecondIface, "wrong ItestSecondIface\n");
1031     return S_OK;
1032 }
1033 
1034 static const IStaticWidgetVtbl StaticWidgetVtbl = {
1035     StaticWidget_QueryInterface,
1036     StaticWidget_AddRef,
1037     StaticWidget_Release,
1038     StaticWidget_GetTypeInfoCount,
1039     StaticWidget_GetTypeInfo,
1040     StaticWidget_GetIDsOfNames,
1041     StaticWidget_Invoke,
1042     StaticWidget_TestDual,
1043     StaticWidget_TestSecondIface
1044 };
1045 
1046 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
1047 
1048 typedef struct KindaEnum
1049 {
1050     IKindaEnumWidget IKindaEnumWidget_iface;
1051     LONG refs;
1052 } KindaEnum;
1053 
1054 static inline KindaEnum *impl_from_IKindaEnumWidget(IKindaEnumWidget *iface)
1055 {
1056     return CONTAINING_RECORD(iface, KindaEnum, IKindaEnumWidget_iface);
1057 }
1058 
1059 static HRESULT register_current_module_typelib(void)
1060 {
1061     WCHAR path[MAX_PATH];
1062     CHAR pathA[MAX_PATH];
1063     HRESULT hr;
1064     ITypeLib *typelib;
1065 
1066     GetModuleFileNameA(NULL, pathA, MAX_PATH);
1067     MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
1068 
1069     hr = LoadTypeLib(path, &typelib);
1070     if (SUCCEEDED(hr))
1071     {
1072         hr = RegisterTypeLib(typelib, path, NULL);
1073         ITypeLib_Release(typelib);
1074     }
1075     return hr;
1076 }
1077 
1078 static ITypeInfo *get_type_info(REFIID riid)
1079 {
1080     ITypeInfo *pTypeInfo;
1081     ITypeLib *pTypeLib;
1082     HRESULT hr;
1083 
1084     hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1085     ok_ole_success(hr, LoadRegTypeLib);
1086     if (FAILED(hr))
1087         return NULL;
1088 
1089     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
1090     ITypeLib_Release(pTypeLib);
1091     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1092     if (FAILED(hr))
1093         return NULL;
1094 
1095     return pTypeInfo;
1096 }
1097 
1098 static IWidget *Widget_Create(void)
1099 {
1100     Widget *This;
1101     ITypeInfo *pTypeInfo;
1102     HRESULT hr = E_FAIL;
1103 
1104     pTypeInfo = get_type_info(&IID_IWidget);
1105     if(!pTypeInfo)
1106         return NULL;
1107 
1108     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1109     This->IWidget_iface.lpVtbl = &Widget_VTable;
1110     This->refs = 1;
1111     This->pDispatchUnknown = NULL;
1112 
1113     hr = CreateStdDispatch((IUnknown *)&This->IWidget_iface, This, pTypeInfo,
1114                            &This->pDispatchUnknown);
1115     ok_ole_success(hr, CreateStdDispatch);
1116     ITypeInfo_Release(pTypeInfo);
1117 
1118     if (SUCCEEDED(hr))
1119         return &This->IWidget_iface;
1120     else
1121     {
1122         HeapFree(GetProcessHeap(), 0, This);
1123         return NULL;
1124     }
1125 }
1126 
1127 static HRESULT WINAPI KindaEnum_QueryInterface(
1128     IKindaEnumWidget *iface,
1129     /* [in] */ REFIID riid,
1130     /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
1131 {
1132     if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
1133     {
1134         IKindaEnumWidget_AddRef(iface);
1135         *ppvObject = iface;
1136         return S_OK;
1137     }
1138     else
1139     {
1140         *ppvObject = NULL;
1141         return E_NOINTERFACE;
1142     }
1143 }
1144 
1145 static ULONG WINAPI KindaEnum_AddRef(
1146     IKindaEnumWidget *iface)
1147 {
1148     KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1149 
1150     return InterlockedIncrement(&This->refs);
1151 }
1152 
1153 static ULONG WINAPI KindaEnum_Release(
1154     IKindaEnumWidget *iface)
1155 {
1156     KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1157     ULONG refs = InterlockedDecrement(&This->refs);
1158     if (!refs)
1159     {
1160         memset(This, 0xcc, sizeof(*This));
1161         HeapFree(GetProcessHeap(), 0, This);
1162         trace("KindaEnumWidget destroyed!\n");
1163     }
1164 
1165     return refs;
1166 }
1167 
1168 static HRESULT WINAPI KindaEnum_Next(
1169     IKindaEnumWidget *iface,
1170     /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
1171 {
1172     *widget = Widget_Create();
1173     if (*widget)
1174         return S_OK;
1175     else
1176         return E_OUTOFMEMORY;
1177 }
1178 
1179 static HRESULT WINAPI KindaEnum_Count(
1180     IKindaEnumWidget *iface,
1181     /* [out] */ ULONG __RPC_FAR *count)
1182 {
1183     return E_NOTIMPL;
1184 }
1185 
1186 static HRESULT WINAPI KindaEnum_Reset(
1187     IKindaEnumWidget *iface)
1188 {
1189     return E_NOTIMPL;
1190 }
1191 
1192 static HRESULT WINAPI KindaEnum_Clone(
1193     IKindaEnumWidget *iface,
1194     /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
1195 {
1196     return E_NOTIMPL;
1197 }
1198 
1199 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
1200 {
1201     KindaEnum_QueryInterface,
1202     KindaEnum_AddRef,
1203     KindaEnum_Release,
1204     KindaEnum_Next,
1205     KindaEnum_Count,
1206     KindaEnum_Reset,
1207     KindaEnum_Clone
1208 };
1209 
1210 static IKindaEnumWidget *KindaEnumWidget_Create(void)
1211 {
1212     KindaEnum *This;
1213 
1214     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1215     if (!This) return NULL;
1216     This->IKindaEnumWidget_iface.lpVtbl = &KindaEnumWidget_VTable;
1217     This->refs = 1;
1218     return &This->IKindaEnumWidget_iface;
1219 }
1220 
1221 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
1222 {
1223     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
1224     {
1225         *(INonOleAutomation **)ppv = iface;
1226         return S_OK;
1227     }
1228     *ppv = NULL;
1229     return E_NOINTERFACE;
1230 }
1231 
1232 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
1233 {
1234     return 2;
1235 }
1236 
1237 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
1238 {
1239     return 1;
1240 }
1241 
1242 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
1243 {
1244     static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1245     return SysAllocString(wszTestString);
1246 }
1247 
1248 static HRESULT WINAPI NonOleAutomation_Error(INonOleAutomation *iface)
1249 {
1250     return E_NOTIMPL;
1251 }
1252 
1253 static INonOleAutomationVtbl NonOleAutomation_VTable =
1254 {
1255     NonOleAutomation_QueryInterface,
1256     NonOleAutomation_AddRef,
1257     NonOleAutomation_Release,
1258     NonOleAutomation_BstrRet,
1259     NonOleAutomation_Error
1260 };
1261 
1262 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
1263 
1264 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
1265 {
1266     ITypeLib *pTypeLib;
1267     HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1268     ok_ole_success(hr, LoadRegTypeLib);
1269     if (SUCCEEDED(hr))
1270     {
1271         ITypeInfo *pTypeInfo;
1272         hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
1273         ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1274         ITypeLib_Release(pTypeLib);
1275         return pTypeInfo;
1276     }
1277     return NULL;
1278 }
1279 
1280 static void test_typelibmarshal(void)
1281 {
1282     static const WCHAR szCat[] = { 'C','a','t',0 };
1283     static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
1284     static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
1285     HRESULT hr;
1286     IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
1287     IWidget *pWidget;
1288     IStream *pStream;
1289     IDispatch *pDispatch;
1290     static const LARGE_INTEGER ullZero;
1291     EXCEPINFO excepinfo;
1292     VARIANT varresult;
1293     DISPID dispidNamed = DISPID_PROPERTYPUT;
1294     DISPPARAMS dispparams;
1295     VARIANTARG vararg[4];
1296     STATE the_state;
1297     HANDLE thread;
1298     DWORD tid;
1299     BSTR bstr;
1300     ITypeInfo *pTypeInfo;
1301     MYSTRUCT mystruct;
1302     MYSTRUCT mystructArray[5];
1303     UINT uval;
1304 
1305     ok(pKEW != NULL, "Widget creation failed\n");
1306 
1307     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1308     ok_ole_success(hr, CreateStreamOnHGlobal);
1309     tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
1310     IKindaEnumWidget_Release(pKEW);
1311 
1312     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1313     hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
1314     todo_wine_if(tmarshal_todo)
1315     ok_ole_success(hr, CoUnmarshalInterface);
1316     IStream_Release(pStream);
1317 
1318     hr = IKindaEnumWidget_Next(pKEW, &pWidget);
1319     ok_ole_success(hr, IKindaEnumWidget_Next);
1320 
1321     IKindaEnumWidget_Release(pKEW);
1322 
1323     /* call GetTypeInfoCount (direct) */
1324     hr = IWidget_GetTypeInfoCount(pWidget, &uval);
1325     ok_ole_success(hr, IWidget_GetTypeInfoCount);
1326     hr = IWidget_GetTypeInfoCount(pWidget, &uval);
1327     ok_ole_success(hr, IWidget_GetTypeInfoCount);
1328 
1329     hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
1330     ok_ole_success(hr, IWidget_QueryInterface);
1331 
1332     /* call put_Name */
1333     VariantInit(&vararg[0]);
1334     dispparams.cNamedArgs = 1;
1335     dispparams.rgdispidNamedArgs = &dispidNamed;
1336     dispparams.cArgs = 1;
1337     dispparams.rgvarg = vararg;
1338     VariantInit(&varresult);
1339     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1340     ok_ole_success(hr, IDispatch_Invoke);
1341     todo_wine_if(tmarshal_todo)
1342     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1343         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1344         excepinfo.wCode, excepinfo.scode);
1345     VariantClear(&varresult);
1346 
1347     /* call put_Name (direct) */
1348     bstr = SysAllocString(szSuperman);
1349     hr = IWidget_put_Name(pWidget, bstr);
1350     ok_ole_success(hr, IWidget_put_Name);
1351     SysFreeString(bstr);
1352 
1353     /* call get_Name */
1354     dispparams.cNamedArgs = 0;
1355     dispparams.rgdispidNamedArgs = NULL;
1356     dispparams.cArgs = 0;
1357     dispparams.rgvarg = NULL;
1358     VariantInit(&varresult);
1359     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1360     ok_ole_success(hr, IDispatch_Invoke);
1361     todo_wine_if(tmarshal_todo)
1362     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1363         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1364         excepinfo.wCode, excepinfo.scode);
1365     trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1366     VariantClear(&varresult);
1367 
1368     /* call get_Name (direct) */
1369     bstr = (void *)0xdeadbeef;
1370     hr = IWidget_get_Name(pWidget, &bstr);
1371     ok_ole_success(hr, IWidget_get_Name);
1372     ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
1373     SysFreeString(bstr);
1374 
1375     /* call DoSomething without optional arguments */
1376     VariantInit(&vararg[0]);
1377     VariantInit(&vararg[1]);
1378     V_VT(&vararg[1]) = VT_R8;
1379     V_R8(&vararg[1]) = 3.141;
1380     dispparams.cNamedArgs = 0;
1381     dispparams.cArgs = 2;
1382     dispparams.rgdispidNamedArgs = NULL;
1383     dispparams.rgvarg = vararg;
1384     VariantInit(&varresult);
1385     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1386     ok_ole_success(hr, IDispatch_Invoke);
1387     ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1388     VariantClear(&varresult);
1389 
1390     /* call DoSomething with optional argument set to VT_EMPTY */
1391     VariantInit(&vararg[0]);
1392     VariantInit(&vararg[1]);
1393     VariantInit(&vararg[2]);
1394     V_VT(&vararg[2]) = VT_R8;
1395     V_R8(&vararg[2]) = 3.141;
1396     dispparams.cNamedArgs = 0;
1397     dispparams.cArgs = 3;
1398     dispparams.rgdispidNamedArgs = NULL;
1399     dispparams.rgvarg = vararg;
1400     VariantInit(&varresult);
1401     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1402     ok_ole_success(hr, IDispatch_Invoke);
1403     ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1404     VariantClear(&varresult);
1405 
1406     /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
1407     VariantInit(&vararg[0]);
1408     VariantInit(&vararg[1]);
1409     VariantInit(&vararg[2]);
1410     VariantInit(&vararg[3]);
1411     V_VT(&vararg[3]) = VT_R8;
1412     V_R8(&vararg[3]) = 3.141;
1413     V_VT(&vararg[1]) = VT_ERROR;
1414     V_ERROR(&vararg[1]) = DISP_E_PARAMNOTFOUND;
1415     V_VT(&vararg[0]) = VT_ERROR;
1416     V_ERROR(&vararg[0]) = DISP_E_PARAMNOTFOUND;
1417     dispparams.cNamedArgs = 0;
1418     dispparams.cArgs = 4;
1419     dispparams.rgdispidNamedArgs = NULL;
1420     dispparams.rgvarg = vararg;
1421     VariantInit(&varresult);
1422     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1423     ok_ole_success(hr, IDispatch_Invoke);
1424     ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1425     VariantClear(&varresult);
1426 
1427     /* call get_State */
1428     dispparams.cNamedArgs = 0;
1429     dispparams.cArgs = 0;
1430     dispparams.rgdispidNamedArgs = NULL;
1431     dispparams.rgvarg = NULL;
1432     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1433     ok_ole_success(hr, IDispatch_Invoke);
1434     ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
1435 
1436     /* call get_State (direct) */
1437     hr = IWidget_get_State(pWidget, &the_state);
1438     ok_ole_success(hr, IWidget_get_state);
1439     ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
1440 
1441     /* call put_State */
1442     the_state = STATE_WIDGETIFIED;
1443     VariantInit(&vararg[0]);
1444     V_VT(&vararg[0]) = VT_BYREF|VT_I4;
1445     V_I4REF(&vararg[0]) = (int *)&the_state;
1446     dispparams.cNamedArgs = 1;
1447     dispparams.cArgs = 1;
1448     dispparams.rgdispidNamedArgs = &dispidNamed;
1449     dispparams.rgvarg = vararg;
1450     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1451     ok_ole_success(hr, IDispatch_Invoke);
1452 
1453     /* call Map */
1454     bstr = SysAllocString(szTestTest);
1455     VariantInit(&vararg[0]);
1456     V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
1457     V_BSTRREF(&vararg[0]) = &bstr;
1458     dispparams.cNamedArgs = 0;
1459     dispparams.cArgs = 1;
1460     dispparams.rgdispidNamedArgs = NULL;
1461     dispparams.rgvarg = vararg;
1462     VariantInit(&varresult);
1463     hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1464     ok_ole_success(hr, IDispatch_Invoke);
1465     ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
1466     ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1467     VariantClear(&varresult);
1468     SysFreeString(bstr);
1469 
1470     /* call SetOleColor with large negative VT_I4 param */
1471     VariantInit(&vararg[0]);
1472     V_VT(&vararg[0]) = VT_I4;
1473     V_I4(&vararg[0]) = 0x80000005;
1474     dispparams.cNamedArgs = 0;
1475     dispparams.cArgs = 1;
1476     dispparams.rgdispidNamedArgs = NULL;
1477     dispparams.rgvarg = vararg;
1478     hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1479     ok_ole_success(hr, IDispatch_Invoke);
1480 
1481     /* call GetOleColor */
1482     dispparams.cNamedArgs = 0;
1483     dispparams.cArgs = 0;
1484     dispparams.rgdispidNamedArgs = NULL;
1485     dispparams.rgvarg = NULL;
1486     VariantInit(&varresult);
1487     hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1488     ok_ole_success(hr, IDispatch_Invoke);
1489     VariantClear(&varresult);
1490 
1491     /* call StructArgs (direct) */
1492     mystruct = MYSTRUCT_BYPTR;
1493     memcpy(mystructArray, MYSTRUCT_ARRAY, sizeof(mystructArray));
1494     hr = IWidget_StructArgs(pWidget, MYSTRUCT_BYVAL, &mystruct, mystructArray);
1495     ok_ole_success(hr, IWidget_StructArgs);
1496 
1497     /* call Clone */
1498     dispparams.cNamedArgs = 0;
1499     dispparams.cArgs = 0;
1500     dispparams.rgdispidNamedArgs = NULL;
1501     dispparams.rgvarg = NULL;
1502     VariantInit(&varresult);
1503     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1504     ok_ole_success(hr, IDispatch_Invoke);
1505     ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1506     VariantClear(&varresult);
1507 
1508     /* call CloneInterface */
1509     dispparams.cNamedArgs = 0;
1510     dispparams.cArgs = 0;
1511     dispparams.rgdispidNamedArgs = NULL;
1512     dispparams.rgvarg = NULL;
1513     VariantInit(&varresult);
1514     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1515     ok_ole_success(hr, IDispatch_Invoke);
1516     ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1517     VariantClear(&varresult);
1518 
1519     /* call CloneDispatch with automatic value getting */
1520     V_VT(&vararg[0]) = VT_I2;
1521     V_I2(&vararg[0]) = 1;
1522     dispparams.cNamedArgs = 0;
1523     dispparams.rgdispidNamedArgs = NULL;
1524     dispparams.cArgs = 1;
1525     dispparams.rgvarg = vararg;
1526     VariantInit(&varresult);
1527     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1528     ok_ole_success(hr, IDispatch_Invoke);
1529 
1530     todo_wine_if(tmarshal_todo)
1531     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1532         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1533         excepinfo.wCode, excepinfo.scode);
1534 
1535     ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1536     ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1537     VariantClear(&varresult);
1538 
1539     /* call CloneCoclass */
1540     dispparams.cNamedArgs = 0;
1541     dispparams.cArgs = 0;
1542     dispparams.rgdispidNamedArgs = NULL;
1543     dispparams.rgvarg = NULL;
1544     VariantInit(&varresult);
1545     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1546     ok_ole_success(hr, IDispatch_Invoke);
1547 
1548     todo_wine_if(tmarshal_todo)
1549     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1550        "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1551        excepinfo.wCode, excepinfo.scode);
1552 
1553     ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
1554     ok(V_DISPATCH(&varresult) != NULL, "expected V_DISPATCH(&varresult) != NULL\n");
1555 
1556     /* call Coclass with VT_DISPATCH type */
1557     vararg[0] = varresult;
1558     dispparams.cNamedArgs = 0;
1559     dispparams.rgdispidNamedArgs = NULL;
1560     dispparams.cArgs = 1;
1561     dispparams.rgvarg = vararg;
1562     VariantInit(&varresult);
1563     hr = IDispatch_Invoke(pDispatch, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1564     ok_ole_success(hr, IDispatch_Invoke);
1565     todo_wine_if(tmarshal_todo)
1566     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1567         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1568         excepinfo.wCode, excepinfo.scode);
1569     VariantClear(&varresult);
1570 
1571     /* call CoClass (direct) */
1572     hr = IWidget_Coclass(pWidget, (void *)V_DISPATCH(&vararg[0]));
1573     ok_ole_success(hr, IWidget_Coclass);
1574     VariantClear(&vararg[0]);
1575 
1576     /* call Value with a VT_VARIANT|VT_BYREF type */
1577     V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
1578     V_VARIANTREF(&vararg[0]) = &vararg[1];
1579     V_VT(&vararg[1]) = VT_I2;
1580     V_I2(&vararg[1]) = 1;
1581     dispparams.cNamedArgs = 0;
1582     dispparams.rgdispidNamedArgs = NULL;
1583     dispparams.cArgs = 1;
1584     dispparams.rgvarg = vararg;
1585     VariantInit(&varresult);
1586     hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1587     ok_ole_success(hr, IDispatch_Invoke);
1588 
1589     todo_wine_if(tmarshal_todo)
1590     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1591         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1592         excepinfo.wCode, excepinfo.scode);
1593 
1594     ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1595     ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1596     VariantClear(&varresult);
1597 
1598     /* call Variant - exercises variant copying in ITypeInfo::Invoke and
1599      * handling of void return types */
1600     /* use a big type to ensure that the variant was properly copied into the
1601      * destination function's args */
1602     V_VT(&vararg[0]) = VT_CY;
1603     S(V_CY(&vararg[0])).Hi = 0xdababe;
1604     S(V_CY(&vararg[0])).Lo = 0xdeadbeef;
1605     dispparams.cNamedArgs = 0;
1606     dispparams.cArgs = 1;
1607     dispparams.rgdispidNamedArgs = NULL;
1608     dispparams.rgvarg = vararg;
1609     VariantInit(&varresult);
1610     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1611     ok_ole_success(hr, IDispatch_Invoke);
1612     VariantClear(&varresult);
1613 
1614     /* call Array with BSTR argument - type mismatch */
1615     VariantInit(&vararg[0]);
1616     V_VT(&vararg[0]) = VT_BSTR;
1617     V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1618     dispparams.cNamedArgs = 0;
1619     dispparams.cArgs = 1;
1620     dispparams.rgdispidNamedArgs = NULL;
1621     dispparams.rgvarg = vararg;
1622     hr = IDispatch_Invoke(pDispatch, DISPID_TM_ARRAY, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1623     ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
1624     SysFreeString(V_BSTR(&vararg[0]));
1625 
1626     /* call ArrayPtr with BSTR argument - type mismatch */
1627     VariantInit(&vararg[0]);
1628     V_VT(&vararg[0]) = VT_BSTR;
1629     V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1630     dispparams.cNamedArgs = 0;
1631     dispparams.cArgs = 1;
1632     dispparams.rgdispidNamedArgs = NULL;
1633     dispparams.rgvarg = vararg;
1634     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARRAYPTR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1635     ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
1636     SysFreeString(V_BSTR(&vararg[0]));
1637 
1638     /* call VariantCArray - test marshaling of variant arrays */
1639     V_VT(&vararg[0]) = VT_I4;
1640     V_I4(&vararg[0]) = 1;
1641     V_VT(&vararg[1]) = VT_I4;
1642     V_I4(&vararg[1]) = 2;
1643     hr = IWidget_VariantCArray(pWidget, 2, vararg);
1644     ok_ole_success(hr, IWidget_VariantCArray);
1645     todo_wine_if(!tmarshal_todo)
1646     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]));
1647     todo_wine_if(!tmarshal_todo)
1648     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]));
1649 
1650     /* call VarArg */
1651     VariantInit(&vararg[3]);
1652     V_VT(&vararg[3]) = VT_I4;
1653     V_I4(&vararg[3]) = 3;
1654     VariantInit(&vararg[2]);
1655     V_VT(&vararg[2]) = VT_I4;
1656     V_I4(&vararg[2]) = 0;
1657     VariantInit(&vararg[1]);
1658     V_VT(&vararg[1]) = VT_I4;
1659     V_I4(&vararg[1]) = 1;
1660     VariantInit(&vararg[0]);
1661     V_VT(&vararg[0]) = VT_I4;
1662     V_I4(&vararg[0]) = 2;
1663     dispparams.cNamedArgs = 0;
1664     dispparams.cArgs = 4;
1665     dispparams.rgdispidNamedArgs = NULL;
1666     dispparams.rgvarg = vararg;
1667     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1668     ok_ole_success(hr, IDispatch_Invoke);
1669 
1670     /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
1671     dispidNamed = 0;
1672     dispparams.cNamedArgs = 1;
1673     dispparams.rgdispidNamedArgs = &dispidNamed;
1674     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1675     ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
1676     dispidNamed = DISPID_PROPERTYPUT;
1677 
1678     /* call VarArg_Run */
1679     VariantInit(&vararg[1]);
1680     V_VT(&vararg[1]) = VT_BSTR;
1681     V_BSTR(&vararg[1]) = SysAllocString(szCat);
1682     VariantInit(&vararg[0]);
1683     V_VT(&vararg[0]) = VT_BSTR;
1684     V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1685     dispparams.cNamedArgs = 0;
1686     dispparams.cArgs = 2;
1687     dispparams.rgdispidNamedArgs = NULL;
1688     dispparams.rgvarg = vararg;
1689     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1690     ok_ole_success(hr, IDispatch_Invoke);
1691     SysFreeString(V_BSTR(&vararg[1]));
1692     SysFreeString(V_BSTR(&vararg[0]));
1693 
1694     /* call VarArg_Ref_Run */
1695     VariantInit(&vararg[1]);
1696     V_VT(&vararg[1]) = VT_BSTR;
1697     V_BSTR(&vararg[1]) = SysAllocString(szCat);
1698     VariantInit(&vararg[0]);
1699     V_VT(&vararg[0]) = VT_BSTR;
1700     V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1701     dispparams.cNamedArgs = 0;
1702     dispparams.cArgs = 2;
1703     dispparams.rgdispidNamedArgs = NULL;
1704     dispparams.rgvarg = vararg;
1705     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_REF_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1706     ok_ole_success(hr, IDispatch_Invoke);
1707     SysFreeString(V_BSTR(&vararg[1]));
1708     SysFreeString(V_BSTR(&vararg[0]));
1709 
1710     /* call Error */
1711     dispparams.cNamedArgs = 0;
1712     dispparams.cArgs = 0;
1713     dispparams.rgdispidNamedArgs = NULL;
1714     dispparams.rgvarg = NULL;
1715     VariantInit(&varresult);
1716     hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1717     ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1718     todo_wine_if(tmarshal_todo)
1719     ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1720         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1721         excepinfo.wCode, excepinfo.scode);
1722     VariantClear(&varresult);
1723 
1724     /* call BstrRet */
1725     pTypeInfo = NonOleAutomation_GetTypeInfo();
1726     dispparams.cNamedArgs = 0;
1727     dispparams.cArgs = 0;
1728     dispparams.rgdispidNamedArgs = NULL;
1729     dispparams.rgvarg = NULL;
1730     VariantInit(&varresult);
1731     hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1732     ok_ole_success(hr, ITypeInfo_Invoke);
1733     ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
1734     ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
1735 
1736     VariantClear(&varresult);
1737 
1738     dispparams.cNamedArgs = 0;
1739     dispparams.cArgs = 0;
1740     dispparams.rgdispidNamedArgs = NULL;
1741     dispparams.rgvarg = NULL;
1742     hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_ERROR, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1743     ok(hr == DISP_E_EXCEPTION, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1744     ok(V_VT(&varresult) == VT_EMPTY, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult));
1745     todo_wine_if(tmarshal_todo)
1746     ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1747         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1748         excepinfo.wCode, excepinfo.scode);
1749     VariantClear(&varresult);
1750 
1751     ITypeInfo_Release(pTypeInfo);
1752 
1753     /* tests call put_Name without named arg */
1754     VariantInit(&vararg[0]);
1755     dispparams.cNamedArgs = 0;
1756     dispparams.rgdispidNamedArgs = NULL;
1757     dispparams.cArgs = 1;
1758     dispparams.rgvarg = vararg;
1759     VariantInit(&varresult);
1760     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1761     ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
1762     VariantClear(&varresult);
1763 
1764     /* tests param type that cannot be coerced */
1765     VariantInit(&vararg[0]);
1766     V_VT(&vararg[0]) = VT_UNKNOWN;
1767     V_UNKNOWN(&vararg[0]) = NULL;
1768     dispparams.cNamedArgs = 1;
1769     dispparams.rgdispidNamedArgs = &dispidNamed;
1770     dispparams.cArgs = 1;
1771     dispparams.rgvarg = vararg;
1772     VariantInit(&varresult);
1773     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1774     ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
1775     VariantClear(&varresult);
1776 
1777     /* tests bad param type */
1778     VariantInit(&vararg[0]);
1779     V_VT(&vararg[0]) = VT_CLSID;
1780     V_BYREF(&vararg[0]) = NULL;
1781     dispparams.cNamedArgs = 1;
1782     dispparams.rgdispidNamedArgs = &dispidNamed;
1783     dispparams.cArgs = 1;
1784     dispparams.rgvarg = vararg;
1785     VariantInit(&varresult);
1786     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1787     ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
1788     VariantClear(&varresult);
1789 
1790     /* tests too small param count */
1791     dispparams.cNamedArgs = 0;
1792     dispparams.rgdispidNamedArgs = NULL;
1793     dispparams.cArgs = 0;
1794     dispparams.rgvarg = NULL;
1795     VariantInit(&varresult);
1796     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1797     ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
1798     VariantClear(&varresult);
1799 
1800     /* tests propget function with large param count */
1801     VariantInit(&vararg[0]);
1802     V_VT(&vararg[0]) = VT_BSTR;
1803     V_BSTR(&vararg[0]) = NULL;
1804     V_VT(&vararg[1]) = VT_I4;
1805     V_I4(&vararg[1]) = 1;
1806     dispparams.cNamedArgs = 0;
1807     dispparams.cArgs = 2;
1808     dispparams.rgdispidNamedArgs = NULL;
1809     dispparams.rgvarg = vararg;
1810     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1811     ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
1812 
1813     /* test propput with lcid */
1814 
1815     /* the lcid passed to the function is the first lcid in the typelib header.
1816        Since we don't explicitly set an lcid in the idl, it'll default to US English. */
1817     VariantInit(&vararg[0]);
1818     V_VT(&vararg[0]) = VT_I4;
1819     V_I4(&vararg[0]) = 0xcafe;
1820     dispparams.cNamedArgs = 1;
1821     dispparams.rgdispidNamedArgs = &dispidNamed;
1822     dispparams.cArgs = 1;
1823     dispparams.rgvarg = vararg;
1824     VariantInit(&varresult);
1825     hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1826     ok_ole_success(hr, ITypeInfo_Invoke);
1827     VariantClear(&varresult);
1828 
1829     /* test propget with lcid */
1830     dispparams.cNamedArgs = 0;
1831     dispparams.cArgs = 0;
1832     dispparams.rgvarg = NULL;
1833     dispparams.rgdispidNamedArgs = NULL;
1834     hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1835     ok_ole_success(hr, ITypeInfo_Invoke);
1836     ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1837     ok(V_I4(&varresult) == 0x409, "got %x\n", V_I4(&varresult));
1838     VariantClear(&varresult);
1839 
1840     /* test propget of INT value */
1841     dispparams.cNamedArgs = 0;
1842     dispparams.cArgs = 0;
1843     dispparams.rgvarg = NULL;
1844     dispparams.rgdispidNamedArgs = NULL;
1845     hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_INT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1846     ok_ole_success(hr, ITypeInfo_Invoke);
1847     ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1848     ok(V_I4(&varresult) == -13, "got %x\n", V_I4(&varresult));
1849     VariantClear(&varresult);
1850 
1851     /* test propget of INT value */
1852     dispparams.cNamedArgs = 0;
1853     dispparams.cArgs = 0;
1854     dispparams.rgvarg = NULL;
1855     dispparams.rgdispidNamedArgs = NULL;
1856     hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_UINT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1857     ok_ole_success(hr, ITypeInfo_Invoke);
1858     ok(V_VT(&varresult) == VT_UI4, "got %x\n", V_VT(&varresult));
1859     ok(V_UI4(&varresult) == 42, "got %x\n", V_UI4(&varresult));
1860     VariantClear(&varresult);
1861 
1862     /* test byref marshalling */
1863     uval = 666;
1864     VariantInit(&vararg[0]);
1865     V_VT(&vararg[0]) = VT_UI4|VT_BYREF;
1866     V_UI4REF(&vararg[0]) = &uval;
1867     dispparams.cNamedArgs = 0;
1868     dispparams.cArgs = 1;
1869     dispparams.rgvarg = vararg;
1870     dispparams.rgdispidNamedArgs = NULL;
1871     hr = IDispatch_Invoke(pDispatch, DISPID_TM_BYREF_UINT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1872     ok_ole_success(hr, ITypeInfo_Invoke);
1873     ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1874     ok(V_VT(&vararg[0]) == (VT_UI4|VT_BYREF), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg[0]));
1875     ok(V_UI4REF(&vararg[0]) == &uval, "Byref pointer not preserved: %p/%p\n", &uval, V_UI4REF(&vararg[0]));
1876     ok(*V_UI4REF(&vararg[0]) == 42, "Expected 42 to be returned instead of %u\n", *V_UI4REF(&vararg[0]));
1877     VariantClear(&varresult);
1878     VariantClear(&vararg[0]);
1879 
1880     /* test propput with optional argument. */
1881     VariantInit(&vararg[0]);
1882     V_VT(&vararg[0]) = VT_I4;
1883     V_I4(&vararg[0]) = 0xcafe;
1884     dispparams.cNamedArgs = 1;
1885     dispparams.rgdispidNamedArgs = &dispidNamed;
1886     dispparams.cArgs = 1;
1887     dispparams.rgvarg = vararg;
1888     VariantInit(&varresult);
1889     hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_OPT_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1890     ok_ole_success(hr, ITypeInfo_Invoke);
1891     VariantClear(&varresult);
1892 
1893     /* test propput with required argument. */
1894     VariantInit(&vararg[0]);
1895     VariantInit(&vararg[1]);
1896     V_VT(&vararg[0]) = VT_I4;
1897     V_I4(&vararg[0]) = 0x1234;
1898     V_VT(&vararg[1]) = VT_I4;
1899     V_I4(&vararg[1]) = 0x5678;
1900     dispparams.cNamedArgs = 1;
1901     dispparams.rgdispidNamedArgs = &dispidNamed;
1902     dispparams.cArgs = 2;
1903     dispparams.rgvarg = vararg;
1904     VariantInit(&varresult);
1905     hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_REQ_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1906     ok_ole_success(hr, ITypeInfo_Invoke);
1907     VariantClear(&varresult);
1908 
1909     /* restricted member */
1910     dispparams.cNamedArgs = 0;
1911     dispparams.rgdispidNamedArgs = NULL;
1912     dispparams.cArgs = 0;
1913     dispparams.rgvarg = NULL;
1914     VariantInit(&varresult);
1915     hr = IDispatch_Invoke(pDispatch, DISPID_TM_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1916     ok( hr == DISP_E_MEMBERNOTFOUND, "got %08x\n", hr );
1917     VariantClear(&varresult);
1918 
1919     /* restricted member with -ve memid (not restricted) */
1920     dispparams.cNamedArgs = 0;
1921     dispparams.rgdispidNamedArgs = NULL;
1922     dispparams.cArgs = 0;
1923     dispparams.rgvarg = NULL;
1924     VariantInit(&varresult);
1925     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NEG_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1926     ok( hr == S_OK, "got %08x\n", hr );
1927     ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1928     ok(V_I4(&varresult) == DISPID_TM_NEG_RESTRICTED, "got %x\n", V_I4(&varresult));
1929     VariantClear(&varresult);
1930 
1931     IDispatch_Release(pDispatch);
1932     IWidget_Release(pWidget);
1933 
1934     trace("calling end_host_object\n");
1935     end_host_object(tid, thread);
1936 }
1937 
1938 static void test_DispCallFunc(void)
1939 {
1940     static const WCHAR szEmpty[] = { 0 };
1941     VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
1942     VARIANTARG vararg[4];
1943     VARIANTARG varref;
1944     VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
1945     VARIANTARG varresult;
1946     HRESULT hr;
1947     IWidget *pWidget = Widget_Create();
1948     V_VT(&vararg[0]) = VT_R8;
1949     V_R8(&vararg[0]) = 3.141;
1950     V_VT(&vararg[1]) = VT_BSTR;
1951     V_BSTRREF(&vararg[1]) = CoTaskMemAlloc(sizeof(BSTR));
1952     V_VT(&vararg[2]) = VT_BSTR;
1953     V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
1954     V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
1955     V_VARIANTREF(&vararg[3]) = &varref;
1956     V_VT(&varref) = VT_ERROR;
1957     V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
1958     VariantInit(&varresult);
1959     hr = DispCallFunc(pWidget, 9*sizeof(void*), CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
1960     ok_ole_success(hr, DispCallFunc);
1961     VariantClear(&varresult);
1962     SysFreeString(*V_BSTRREF(&vararg[1]));
1963     CoTaskMemFree(V_BSTRREF(&vararg[1]));
1964     VariantClear(&vararg[2]);
1965     IWidget_Release(pWidget);
1966 }
1967 
1968 static void test_StaticWidget(void)
1969 {
1970     ITypeInfo *type_info;
1971     DISPPARAMS dispparams;
1972     VARIANTARG vararg[4];
1973     EXCEPINFO excepinfo;
1974     VARIANT varresult;
1975     HRESULT hr;
1976 
1977     type_info = get_type_info(&IID_IStaticWidget);
1978 
1979     /* call TestDual */
1980     dispparams.cNamedArgs = 0;
1981     dispparams.cArgs = 1;
1982     dispparams.rgdispidNamedArgs = NULL;
1983     dispparams.rgvarg = vararg;
1984     V_VT(vararg) = VT_DISPATCH;
1985     V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
1986     VariantInit(&varresult);
1987     hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTDUAL, DISPATCH_METHOD,
1988             &dispparams, &varresult, &excepinfo, NULL);
1989     ok_ole_success(hr, IDispatch_Invoke);
1990     ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
1991     VariantClear(&varresult);
1992 
1993     /* call TestSecondIface */
1994     dispparams.cNamedArgs = 0;
1995     dispparams.cArgs = 1;
1996     dispparams.rgdispidNamedArgs = NULL;
1997     dispparams.rgvarg = vararg;
1998     V_VT(vararg) = VT_DISPATCH;
1999     V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
2000     VariantInit(&varresult);
2001     hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTSECONDIFACE, DISPATCH_METHOD,
2002             &dispparams, &varresult, &excepinfo, NULL);
2003     ok_ole_success(hr, IDispatch_Invoke);
2004     ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
2005     VariantClear(&varresult);
2006 
2007     ITypeInfo_Release(type_info);
2008 }
2009 
2010 static void test_libattr(void)
2011 {
2012     ITypeLib *pTypeLib;
2013     HRESULT hr;
2014     TLIBATTR *pattr;
2015 
2016     hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
2017     ok_ole_success(hr, LoadRegTypeLib);
2018     if (FAILED(hr))
2019         return;
2020 
2021     hr = ITypeLib_GetLibAttr(pTypeLib, &pattr);
2022     ok_ole_success(hr, GetLibAttr);
2023     if (SUCCEEDED(hr))
2024     {
2025         ok(pattr->lcid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "lcid %x\n", pattr->lcid);
2026 
2027         ITypeLib_ReleaseTLibAttr(pTypeLib, pattr);
2028     }
2029 
2030     ITypeLib_Release(pTypeLib);
2031 }
2032 
2033 static void test_external_connection(void)
2034 {
2035     IStream *stream, *stream2;
2036     ITestSecondDisp *second;
2037     ItestDual *iface;
2038     HANDLE thread;
2039     DWORD tid;
2040     HRESULT hres;
2041 
2042     static const LARGE_INTEGER zero;
2043 
2044     trace("Testing IExternalConnection...\n");
2045 
2046     external_connections = 0;
2047 
2048     /* Marshaling an interface increases external connection count. */
2049     expect_last_release_closes = FALSE;
2050     hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2051     ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2052     tid = start_host_object(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHLFLAGS_NORMAL, &thread);
2053     ok(external_connections == 1, "external_connections = %d\n", external_connections);
2054 
2055     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2056     hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
2057     todo_wine_if(tmarshal_todo)
2058     ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
2059     ok(external_connections == 1, "external_connections = %d\n", external_connections);
2060 
2061     IStream_Release(stream);
2062     ok(external_connections == 1, "external_connections = %d\n", external_connections);
2063 
2064     /* Creating a stub for new iface causes new external connection. */
2065     hres = ItestDual_QueryInterface(iface, &IID_ITestSecondDisp, (void**)&second);
2066     todo_wine_if(tmarshal_todo)
2067     ok(hres == S_OK, "Could not get ITestSecondDisp iface: %08x\n", hres);
2068     todo_wine
2069     ok(external_connections == 2, "external_connections = %d\n", external_connections);
2070 
2071     if (hres == S_OK)
2072         ITestSecondDisp_Release(second);
2073     todo_wine
2074     ok(external_connections == 2, "external_connections = %d\n", external_connections);
2075 
2076     expect_last_release_closes = TRUE;
2077     ItestDual_Release(iface);
2078     todo_wine_if(tmarshal_todo)
2079     ok(external_connections == 0, "external_connections = %d\n", external_connections);
2080 
2081     end_host_object(tid, thread);
2082 
2083     /* A test with direct CoMarshalInterface call. */
2084     hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2085     ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2086 
2087     expect_last_release_closes = FALSE;
2088     hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2089     ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2090     todo_wine_if(tmarshal_todo)
2091     ok(external_connections == 1, "external_connections = %d\n", external_connections);
2092 
2093     expect_last_release_closes = TRUE;
2094     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2095     hres = CoReleaseMarshalData(stream);
2096     ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2097     todo_wine_if(tmarshal_todo)
2098     ok(external_connections == 0, "external_connections = %d\n", external_connections);
2099 
2100     /* Two separated marshal data are still one external connection. */
2101     hres = CreateStreamOnHGlobal(NULL, TRUE, &stream2);
2102     ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2103 
2104     expect_last_release_closes = FALSE;
2105     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2106     hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2107     ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2108     todo_wine_if(tmarshal_todo)
2109     ok(external_connections == 1, "external_connections = %d\n", external_connections);
2110 
2111     hres = CoMarshalInterface(stream2, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2112     ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2113     todo_wine_if(tmarshal_todo)
2114     ok(external_connections == 1, "external_connections = %d\n", external_connections);
2115 
2116     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2117     hres = CoReleaseMarshalData(stream);
2118     ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2119     todo_wine_if(tmarshal_todo)
2120     ok(external_connections == 1, "external_connections = %d\n", external_connections);
2121 
2122     expect_last_release_closes = TRUE;
2123     IStream_Seek(stream2, zero, STREAM_SEEK_SET, NULL);
2124     hres = CoReleaseMarshalData(stream2);
2125     ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2126     todo_wine_if(tmarshal_todo)
2127     ok(external_connections == 0, "external_connections = %d\n", external_connections);
2128 
2129     IStream_Release(stream);
2130     IStream_Release(stream2);
2131 
2132     /* Weak table marshaling does not increment external connections */
2133     hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2134     ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2135 
2136     hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
2137     ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2138     todo_wine_if(tmarshal_todo)
2139     ok(external_connections == 0, "external_connections = %d\n", external_connections);
2140 
2141     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2142     hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
2143     ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
2144     todo_wine_if(tmarshal_todo)
2145     ok(external_connections == 0, "external_connections = %d\n", external_connections);
2146     ItestDual_Release(iface);
2147 
2148     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2149     hres = CoReleaseMarshalData(stream);
2150     ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2151     todo_wine_if(tmarshal_todo)
2152     ok(external_connections == 0, "external_connections = %d\n", external_connections);
2153 
2154     IStream_Release(stream);
2155 }
2156 
2157 START_TEST(tmarshal)
2158 {
2159     HRESULT hr;
2160     HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll");
2161     pVarAdd = (void*)GetProcAddress(hOleaut32, "VarAdd");
2162 
2163     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2164 
2165     hr = register_current_module_typelib();
2166     if (FAILED(hr))
2167     {
2168         CoUninitialize();
2169         win_skip("Registration of the test typelib failed, skipping tests\n");
2170         return;
2171     }
2172 
2173     test_typelibmarshal();
2174     test_DispCallFunc();
2175     test_StaticWidget();
2176     test_libattr();
2177     test_external_connection();
2178 
2179     hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
2180                            sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
2181     ok_ole_success(hr, UnRegisterTypeLib);
2182 
2183     CoUninitialize();
2184 }
2185