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