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