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]) = ∈
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 = ∈
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 = ∈
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 = ∈
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 = π
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