[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%08x\n", 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 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
93
94 SetEvent(data->marshal_event);
95
96 while (GetMessageA(&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 DispatchMessageA(&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 = CreateEventA(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 = CreateEventA(NULL, FALSE, FALSE, NULL);
148 PostThreadMessageA(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 = PostThreadMessageA(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 FALSE;
734 return TRUE;
735 }
736
737 static HRESULT WINAPI Widget_StructArgs(
738 IWidget * iface,
739 MYSTRUCT byval,
740 MYSTRUCT *byptr,
741 MYSTRUCT arr[5])
742 {
743 int i, diff = 0;
744 ok(byval.field1 == MYSTRUCT_BYVAL.field1 &&
745 byval.field2 == MYSTRUCT_BYVAL.field2 &&
746 mystruct_uint_ordered(&byval),
747 "Struct parameter passed by value corrupted\n");
748 ok(byptr->field1 == MYSTRUCT_BYPTR.field1 &&
749 byptr->field2 == MYSTRUCT_BYPTR.field2 &&
750 mystruct_uint_ordered(byptr),
751 "Struct parameter passed by pointer corrupted\n");
752 for (i = 0; i < 5; i++)
753 if (arr[i].field1 != MYSTRUCT_ARRAY[i].field1 ||
754 arr[i].field2 != MYSTRUCT_ARRAY[i].field2 ||
755 ! mystruct_uint_ordered(&arr[i]))
756 diff++;
757 ok(diff == 0, "Array of structs corrupted\n");
758 return S_OK;
759 }
760
761
762 static HRESULT WINAPI Widget_Error(
763 IWidget __RPC_FAR * iface)
764 {
765 trace("Error()\n");
766 return E_NOTIMPL;
767 }
768
769 static HRESULT WINAPI Widget_CloneInterface(
770 IWidget __RPC_FAR * iface,
771 ISomethingFromDispatch **ppVal)
772 {
773 trace("CloneInterface()\n");
774 *ppVal = 0;
775 return S_OK;
776 }
777
778 static HRESULT WINAPI Widget_put_prop_with_lcid(
779 IWidget* iface, LONG lcid, INT i)
780 {
781 trace("put_prop_with_lcid(%08x, %x)\n", lcid, i);
782 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
783 ok(i == 0xcafe, "got %08x\n", i);
784 return S_OK;
785 }
786
787 static HRESULT WINAPI Widget_get_prop_with_lcid(
788 IWidget* iface, LONG lcid, INT *i)
789 {
790 trace("get_prop_with_lcid(%08x, %p)\n", lcid, i);
791 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
792 *i = lcid;
793 return S_OK;
794 }
795
796 static HRESULT WINAPI Widget_get_prop_int(
797 IWidget* iface, INT *i)
798 {
799 trace("get_prop_int(%p)\n", i);
800 *i = -13;
801 return S_OK;
802 }
803
804 static HRESULT WINAPI Widget_get_prop_uint(
805 IWidget* iface, UINT *i)
806 {
807 trace("get_prop_uint(%p)\n", i);
808 *i = 42;
809 return S_OK;
810 }
811
812 static HRESULT WINAPI Widget_ByRefUInt(
813 IWidget* iface, UINT *i)
814 {
815 *i = 42;
816 return S_OK;
817 }
818
819 static HRESULT WINAPI Widget_put_prop_opt_arg(
820 IWidget* iface, INT opt, INT i)
821 {
822 trace("put_prop_opt_arg(%08x, %08x)\n", opt, i);
823 todo_wine ok(opt == 0, "got opt=%08x\n", opt);
824 ok(i == 0xcafe, "got i=%08x\n", i);
825 return S_OK;
826 }
827
828 static HRESULT WINAPI Widget_put_prop_req_arg(
829 IWidget* iface, INT req, INT i)
830 {
831 trace("put_prop_req_arg(%08x, %08x)\n", req, i);
832 ok(req == 0x5678, "got req=%08x\n", req);
833 ok(i == 0x1234, "got i=%08x\n", i);
834 return S_OK;
835 }
836
837 static HRESULT WINAPI Widget__restrict(IWidget* iface, INT *i)
838 {
839 trace("restrict\n");
840 *i = DISPID_TM_RESTRICTED;
841 return S_OK;
842 }
843
844 static HRESULT WINAPI Widget_neg_restrict(IWidget* iface, INT *i)
845 {
846 trace("neg_restrict\n");
847 *i = DISPID_TM_NEG_RESTRICTED;
848 return S_OK;
849 }
850
851 static const struct IWidgetVtbl Widget_VTable =
852 {
853 Widget_QueryInterface,
854 Widget_AddRef,
855 Widget_Release,
856 Widget_GetTypeInfoCount,
857 Widget_GetTypeInfo,
858 Widget_GetIDsOfNames,
859 Widget_Invoke,
860 Widget_put_Name,
861 Widget_get_Name,
862 Widget_DoSomething,
863 Widget_get_State,
864 Widget_put_State,
865 Widget_Map,
866 Widget_SetOleColor,
867 Widget_GetOleColor,
868 Widget_Clone,
869 Widget_CloneDispatch,
870 Widget_CloneCoclass,
871 Widget_Value,
872 Widget_Array,
873 Widget_VariantArrayPtr,
874 Widget_VariantCArray,
875 Widget_Variant,
876 Widget_VarArg,
877 Widget_StructArgs,
878 Widget_Error,
879 Widget_CloneInterface,
880 Widget_put_prop_with_lcid,
881 Widget_get_prop_with_lcid,
882 Widget_get_prop_int,
883 Widget_get_prop_uint,
884 Widget_ByRefUInt,
885 Widget_put_prop_opt_arg,
886 Widget_put_prop_req_arg,
887 Widget__restrict,
888 Widget_neg_restrict
889 };
890
891 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
892 {
893 if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
894 {
895 IStaticWidget_AddRef(iface);
896 *ppvObject = iface;
897 return S_OK;
898 }
899
900 *ppvObject = NULL;
901 return E_NOINTERFACE;
902 }
903
904 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
905 {
906 return 2;
907 }
908
909 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
910 {
911 return 1;
912 }
913
914 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
915 {
916 ok(0, "unexpected call\n");
917 return E_NOTIMPL;
918 }
919
920 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
921 ITypeInfo **ppTInfo)
922 {
923 ok(0, "unexpected call\n");
924 return E_NOTIMPL;
925 }
926
927 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
928 UINT cNames, LCID lcid, DISPID *rgDispId)
929 {
930 ok(0, "unexpected call\n");
931 return E_NOTIMPL;
932 }
933
934 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
935 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
936 UINT *puArgErr)
937 {
938 ok(0, "unexpected call\n");
939 return E_NOTIMPL;
940 }
941
942 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
943 {
944 trace("TestDual()\n");
945 ok(p == &TestDual, "wrong ItestDual\n");
946 return S_OK;
947 }
948
949 static HRESULT WINAPI StaticWidget_TestSecondIface(IStaticWidget *iface, ITestSecondIface *p)
950 {
951 trace("TestSecondIface()\n");
952 ok(p == &TestSecondIface, "wrong ItestSecondIface\n");
953 return S_OK;
954 }
955
956 static const IStaticWidgetVtbl StaticWidgetVtbl = {
957 StaticWidget_QueryInterface,
958 StaticWidget_AddRef,
959 StaticWidget_Release,
960 StaticWidget_GetTypeInfoCount,
961 StaticWidget_GetTypeInfo,
962 StaticWidget_GetIDsOfNames,
963 StaticWidget_Invoke,
964 StaticWidget_TestDual,
965 StaticWidget_TestSecondIface
966 };
967
968 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
969
970 typedef struct KindaEnum
971 {
972 IKindaEnumWidget IKindaEnumWidget_iface;
973 LONG refs;
974 } KindaEnum;
975
976 static inline KindaEnum *impl_from_IKindaEnumWidget(IKindaEnumWidget *iface)
977 {
978 return CONTAINING_RECORD(iface, KindaEnum, IKindaEnumWidget_iface);
979 }
980
981 static HRESULT register_current_module_typelib(void)
982 {
983 WCHAR path[MAX_PATH];
984 CHAR pathA[MAX_PATH];
985 HRESULT hr;
986 ITypeLib *typelib;
987
988 GetModuleFileNameA(NULL, pathA, MAX_PATH);
989 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
990
991 hr = LoadTypeLib(path, &typelib);
992 if (SUCCEEDED(hr))
993 {
994 hr = RegisterTypeLib(typelib, path, NULL);
995 ITypeLib_Release(typelib);
996 }
997 return hr;
998 }
999
1000 static ITypeInfo *get_type_info(REFIID riid)
1001 {
1002 ITypeInfo *pTypeInfo;
1003 ITypeLib *pTypeLib;
1004 HRESULT hr;
1005
1006 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1007 ok_ole_success(hr, LoadRegTypeLib);
1008 if (FAILED(hr))
1009 return NULL;
1010
1011 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
1012 ITypeLib_Release(pTypeLib);
1013 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1014 if (FAILED(hr))
1015 return NULL;
1016
1017 return pTypeInfo;
1018 }
1019
1020 static IWidget *Widget_Create(void)
1021 {
1022 Widget *This;
1023 ITypeInfo *pTypeInfo;
1024 HRESULT hr = E_FAIL;
1025
1026 pTypeInfo = get_type_info(&IID_IWidget);
1027 if(!pTypeInfo)
1028 return NULL;
1029
1030 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1031 This->IWidget_iface.lpVtbl = &Widget_VTable;
1032 This->refs = 1;
1033 This->pDispatchUnknown = NULL;
1034
1035 hr = CreateStdDispatch((IUnknown *)&This->IWidget_iface, This, pTypeInfo,
1036 &This->pDispatchUnknown);
1037 ok_ole_success(hr, CreateStdDispatch);
1038 ITypeInfo_Release(pTypeInfo);
1039
1040 if (SUCCEEDED(hr))
1041 return &This->IWidget_iface;
1042 else
1043 {
1044 HeapFree(GetProcessHeap(), 0, This);
1045 return NULL;
1046 }
1047 }
1048
1049 static HRESULT WINAPI KindaEnum_QueryInterface(
1050 IKindaEnumWidget *iface,
1051 /* [in] */ REFIID riid,
1052 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
1053 {
1054 if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
1055 {
1056 IKindaEnumWidget_AddRef(iface);
1057 *ppvObject = iface;
1058 return S_OK;
1059 }
1060 else
1061 {
1062 *ppvObject = NULL;
1063 return E_NOINTERFACE;
1064 }
1065 }
1066
1067 static ULONG WINAPI KindaEnum_AddRef(
1068 IKindaEnumWidget *iface)
1069 {
1070 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1071
1072 return InterlockedIncrement(&This->refs);
1073 }
1074
1075 static ULONG WINAPI KindaEnum_Release(
1076 IKindaEnumWidget *iface)
1077 {
1078 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1079 ULONG refs = InterlockedDecrement(&This->refs);
1080 if (!refs)
1081 {
1082 memset(This, 0xcc, sizeof(*This));
1083 HeapFree(GetProcessHeap(), 0, This);
1084 trace("KindaEnumWidget destroyed!\n");
1085 }
1086
1087 return refs;
1088 }
1089
1090 static HRESULT WINAPI KindaEnum_Next(
1091 IKindaEnumWidget *iface,
1092 /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
1093 {
1094 *widget = Widget_Create();
1095 if (*widget)
1096 return S_OK;
1097 else
1098 return E_OUTOFMEMORY;
1099 }
1100
1101 static HRESULT WINAPI KindaEnum_Count(
1102 IKindaEnumWidget *iface,
1103 /* [out] */ ULONG __RPC_FAR *count)
1104 {
1105 return E_NOTIMPL;
1106 }
1107
1108 static HRESULT WINAPI KindaEnum_Reset(
1109 IKindaEnumWidget *iface)
1110 {
1111 return E_NOTIMPL;
1112 }
1113
1114 static HRESULT WINAPI KindaEnum_Clone(
1115 IKindaEnumWidget *iface,
1116 /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
1117 {
1118 return E_NOTIMPL;
1119 }
1120
1121 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
1122 {
1123 KindaEnum_QueryInterface,
1124 KindaEnum_AddRef,
1125 KindaEnum_Release,
1126 KindaEnum_Next,
1127 KindaEnum_Count,
1128 KindaEnum_Reset,
1129 KindaEnum_Clone
1130 };
1131
1132 static IKindaEnumWidget *KindaEnumWidget_Create(void)
1133 {
1134 KindaEnum *This;
1135
1136 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1137 if (!This) return NULL;
1138 This->IKindaEnumWidget_iface.lpVtbl = &KindaEnumWidget_VTable;
1139 This->refs = 1;
1140 return &This->IKindaEnumWidget_iface;
1141 }
1142
1143 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
1144 {
1145 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
1146 {
1147 *(INonOleAutomation **)ppv = iface;
1148 return S_OK;
1149 }
1150 *ppv = NULL;
1151 return E_NOINTERFACE;
1152 }
1153
1154 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
1155 {
1156 return 2;
1157 }
1158
1159 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
1160 {
1161 return 1;
1162 }
1163
1164 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
1165 {
1166 static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1167 return SysAllocString(wszTestString);
1168 }
1169
1170 static HRESULT WINAPI NonOleAutomation_Error(INonOleAutomation *iface)
1171 {
1172 return E_NOTIMPL;
1173 }
1174
1175 static INonOleAutomationVtbl NonOleAutomation_VTable =
1176 {
1177 NonOleAutomation_QueryInterface,
1178 NonOleAutomation_AddRef,
1179 NonOleAutomation_Release,
1180 NonOleAutomation_BstrRet,
1181 NonOleAutomation_Error
1182 };
1183
1184 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
1185
1186 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
1187 {
1188 ITypeLib *pTypeLib;
1189 HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1190 ok_ole_success(hr, LoadRegTypeLib);
1191 if (SUCCEEDED(hr))
1192 {
1193 ITypeInfo *pTypeInfo;
1194 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
1195 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1196 ITypeLib_Release(pTypeLib);
1197 return pTypeInfo;
1198 }
1199 return NULL;
1200 }
1201
1202 static void test_typelibmarshal(void)
1203 {
1204 static const WCHAR szCat[] = { 'C','a','t',0 };
1205 static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
1206 static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
1207 HRESULT hr;
1208 IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
1209 IWidget *pWidget;
1210 IStream *pStream;
1211 IDispatch *pDispatch;
1212 static const LARGE_INTEGER ullZero;
1213 EXCEPINFO excepinfo;
1214 VARIANT varresult;
1215 DISPID dispidNamed = DISPID_PROPERTYPUT;
1216 DISPPARAMS dispparams;
1217 VARIANTARG vararg[4];
1218 STATE the_state;
1219 HANDLE thread;
1220 DWORD tid;
1221 BSTR bstr;
1222 ITypeInfo *pTypeInfo;
1223 MYSTRUCT mystruct;
1224 MYSTRUCT mystructArray[5];
1225 UINT uval;
1226
1227 ok(pKEW != NULL, "Widget creation failed\n");
1228
1229 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1230 ok_ole_success(hr, CreateStreamOnHGlobal);
1231 tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
1232 IKindaEnumWidget_Release(pKEW);
1233
1234 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1235 hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
1236 ok_ole_success(hr, CoUnmarshalInterface);
1237 IStream_Release(pStream);
1238
1239 hr = IKindaEnumWidget_Next(pKEW, &pWidget);
1240 ok_ole_success(hr, IKindaEnumWidget_Next);
1241
1242 IKindaEnumWidget_Release(pKEW);
1243
1244 /* call GetTypeInfoCount (direct) */
1245 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
1246 ok_ole_success(hr, IWidget_GetTypeInfoCount);
1247 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
1248 ok_ole_success(hr, IWidget_GetTypeInfoCount);
1249
1250 hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
1251 ok_ole_success(hr, IWidget_QueryInterface);
1252
1253 /* call put_Name */
1254 VariantInit(&vararg[0]);
1255 dispparams.cNamedArgs = 1;
1256 dispparams.rgdispidNamedArgs = &dispidNamed;
1257 dispparams.cArgs = 1;
1258 dispparams.rgvarg = vararg;
1259 VariantInit(&varresult);
1260 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1261 ok_ole_success(hr, IDispatch_Invoke);
1262 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1263 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1264 excepinfo.wCode, excepinfo.scode);
1265 VariantClear(&varresult);
1266
1267 /* call put_Name (direct) */
1268 bstr = SysAllocString(szSuperman);
1269 hr = IWidget_put_Name(pWidget, bstr);
1270 ok_ole_success(hr, IWidget_put_Name);
1271 SysFreeString(bstr);
1272
1273 /* call get_Name */
1274 dispparams.cNamedArgs = 0;
1275 dispparams.rgdispidNamedArgs = NULL;
1276 dispparams.cArgs = 0;
1277 dispparams.rgvarg = NULL;
1278 VariantInit(&varresult);
1279 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1280 ok_ole_success(hr, IDispatch_Invoke);
1281 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1282 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1283 excepinfo.wCode, excepinfo.scode);
1284 trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1285 VariantClear(&varresult);
1286
1287 /* call get_Name (direct) */
1288 bstr = (void *)0xdeadbeef;
1289 hr = IWidget_get_Name(pWidget, &bstr);
1290 ok_ole_success(hr, IWidget_get_Name);
1291 ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
1292 SysFreeString(bstr);
1293
1294 /* call DoSomething */
1295 VariantInit(&vararg[0]);
1296 VariantInit(&vararg[1]);
1297 V_VT(&vararg[1]) = VT_R8;
1298 V_R8(&vararg[1]) = 3.141;
1299 dispparams.cNamedArgs = 0;
1300 dispparams.cArgs = 2;
1301 dispparams.rgdispidNamedArgs = NULL;
1302 dispparams.rgvarg = vararg;
1303 VariantInit(&varresult);
1304 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1305 ok_ole_success(hr, IDispatch_Invoke);
1306 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1307 VariantClear(&varresult);
1308
1309 /* call get_State */
1310 dispparams.cNamedArgs = 0;
1311 dispparams.cArgs = 0;
1312 dispparams.rgdispidNamedArgs = NULL;
1313 dispparams.rgvarg = NULL;
1314 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1315 ok_ole_success(hr, IDispatch_Invoke);
1316 ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
1317
1318 /* call get_State (direct) */
1319 hr = IWidget_get_State(pWidget, &the_state);
1320 ok_ole_success(hr, IWidget_get_state);
1321 ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
1322
1323 /* call put_State */
1324 the_state = STATE_WIDGETIFIED;
1325 VariantInit(&vararg[0]);
1326 V_VT(&vararg[0]) = VT_BYREF|VT_I4;
1327 V_I4REF(&vararg[0]) = (int *)&the_state;
1328 dispparams.cNamedArgs = 1;
1329 dispparams.cArgs = 1;
1330 dispparams.rgdispidNamedArgs = &dispidNamed;
1331 dispparams.rgvarg = vararg;
1332 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1333 ok_ole_success(hr, IDispatch_Invoke);
1334
1335 /* call Map */
1336 bstr = SysAllocString(szTestTest);
1337 VariantInit(&vararg[0]);
1338 V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
1339 V_BSTRREF(&vararg[0]) = &bstr;
1340 dispparams.cNamedArgs = 0;
1341 dispparams.cArgs = 1;
1342 dispparams.rgdispidNamedArgs = NULL;
1343 dispparams.rgvarg = vararg;
1344 VariantInit(&varresult);
1345 hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1346 ok_ole_success(hr, IDispatch_Invoke);
1347 ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
1348 ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1349 VariantClear(&varresult);
1350 SysFreeString(bstr);
1351
1352 /* call SetOleColor with large negative VT_I4 param */
1353 VariantInit(&vararg[0]);
1354 V_VT(&vararg[0]) = VT_I4;
1355 V_I4(&vararg[0]) = 0x80000005;
1356 dispparams.cNamedArgs = 0;
1357 dispparams.cArgs = 1;
1358 dispparams.rgdispidNamedArgs = NULL;
1359 dispparams.rgvarg = vararg;
1360 hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1361 ok_ole_success(hr, IDispatch_Invoke);
1362
1363 /* call GetOleColor */
1364 dispparams.cNamedArgs = 0;
1365 dispparams.cArgs = 0;
1366 dispparams.rgdispidNamedArgs = NULL;
1367 dispparams.rgvarg = NULL;
1368 VariantInit(&varresult);
1369 hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1370 ok_ole_success(hr, IDispatch_Invoke);
1371 VariantClear(&varresult);
1372
1373 /* call StructArgs (direct) */
1374 mystruct = MYSTRUCT_BYPTR;
1375 memcpy(mystructArray, MYSTRUCT_ARRAY, sizeof(mystructArray));
1376 hr = IWidget_StructArgs(pWidget, MYSTRUCT_BYVAL, &mystruct, mystructArray);
1377 ok_ole_success(hr, IWidget_StructArgs);
1378
1379 /* call Clone */
1380 dispparams.cNamedArgs = 0;
1381 dispparams.cArgs = 0;
1382 dispparams.rgdispidNamedArgs = NULL;
1383 dispparams.rgvarg = NULL;
1384 VariantInit(&varresult);
1385 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1386 ok_ole_success(hr, IDispatch_Invoke);
1387 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1388 VariantClear(&varresult);
1389
1390 /* call CloneInterface */
1391 dispparams.cNamedArgs = 0;
1392 dispparams.cArgs = 0;
1393 dispparams.rgdispidNamedArgs = NULL;
1394 dispparams.rgvarg = NULL;
1395 VariantInit(&varresult);
1396 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1397 ok_ole_success(hr, IDispatch_Invoke);
1398 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1399 VariantClear(&varresult);
1400
1401 /* call CloneDispatch with automatic value getting */
1402 V_VT(&vararg[0]) = VT_I2;
1403 V_I2(&vararg[0]) = 1;
1404 dispparams.cNamedArgs = 0;
1405 dispparams.rgdispidNamedArgs = NULL;
1406 dispparams.cArgs = 1;
1407 dispparams.rgvarg = vararg;
1408 VariantInit(&varresult);
1409 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1410 ok_ole_success(hr, IDispatch_Invoke);
1411
1412 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1413 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1414 excepinfo.wCode, excepinfo.scode);
1415
1416 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1417 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1418 VariantClear(&varresult);
1419
1420 /* call CloneCoclass */
1421 dispparams.cNamedArgs = 0;
1422 dispparams.cArgs = 0;
1423 dispparams.rgdispidNamedArgs = NULL;
1424 dispparams.rgvarg = NULL;
1425 VariantInit(&varresult);
1426 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1427 ok_ole_success(hr, IDispatch_Invoke);
1428
1429 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1430 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1431 excepinfo.wCode, excepinfo.scode);
1432
1433 ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
1434 ok(!V_DISPATCH(&varresult), "V_DISPATCH(&varresult) should be NULL instead of %p\n", V_DISPATCH(&varresult));
1435 VariantClear(&varresult);
1436
1437 /* call Value with a VT_VARIANT|VT_BYREF type */
1438 V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
1439 V_VARIANTREF(&vararg[0]) = &vararg[1];
1440 V_VT(&vararg[1]) = VT_I2;
1441 V_I2(&vararg[1]) = 1;
1442 dispparams.cNamedArgs = 0;
1443 dispparams.rgdispidNamedArgs = NULL;
1444 dispparams.cArgs = 1;
1445 dispparams.rgvarg = vararg;
1446 VariantInit(&varresult);
1447 hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1448 ok_ole_success(hr, IDispatch_Invoke);
1449
1450 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1451 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1452 excepinfo.wCode, excepinfo.scode);
1453
1454 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1455 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1456 VariantClear(&varresult);
1457
1458 /* call Variant - exercises variant copying in ITypeInfo::Invoke and
1459 * handling of void return types */
1460 /* use a big type to ensure that the variant was properly copied into the
1461 * destination function's args */
1462 V_VT(&vararg[0]) = VT_CY;
1463 S(V_CY(&vararg[0])).Hi = 0xdababe;
1464 S(V_CY(&vararg[0])).Lo = 0xdeadbeef;
1465 dispparams.cNamedArgs = 0;
1466 dispparams.cArgs = 1;
1467 dispparams.rgdispidNamedArgs = NULL;
1468 dispparams.rgvarg = vararg;
1469 VariantInit(&varresult);
1470 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1471 ok_ole_success(hr, IDispatch_Invoke);
1472 VariantClear(&varresult);
1473
1474 /* call VariantCArray - test marshaling of variant arrays */
1475 V_VT(&vararg[0]) = VT_I4;
1476 V_I4(&vararg[0]) = 1;
1477 V_VT(&vararg[1]) = VT_I4;
1478 V_I4(&vararg[1]) = 2;
1479 hr = IWidget_VariantCArray(pWidget, 2, vararg);
1480 ok_ole_success(hr, IWidget_VariantCArray);
1481 todo_wine
1482 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]));
1483 todo_wine
1484 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]));
1485
1486 /* call VarArg */
1487 VariantInit(&vararg[3]);
1488 V_VT(&vararg[3]) = VT_I4;
1489 V_I4(&vararg[3]) = 3;
1490 VariantInit(&vararg[2]);
1491 V_VT(&vararg[2]) = VT_I4;
1492 V_I4(&vararg[2]) = 0;
1493 VariantInit(&vararg[1]);
1494 V_VT(&vararg[1]) = VT_I4;
1495 V_I4(&vararg[1]) = 1;
1496 VariantInit(&vararg[0]);
1497 V_VT(&vararg[0]) = VT_I4;
1498 V_I4(&vararg[0]) = 2;
1499 dispparams.cNamedArgs = 0;
1500 dispparams.cArgs = 4;
1501 dispparams.rgdispidNamedArgs = NULL;
1502 dispparams.rgvarg = vararg;
1503 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1504 ok_ole_success(hr, ITypeInfo_Invoke);
1505
1506 /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
1507 dispidNamed = 0;
1508 dispparams.cNamedArgs = 1;
1509 dispparams.rgdispidNamedArgs = &dispidNamed;
1510 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1511 ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
1512 dispidNamed = DISPID_PROPERTYPUT;
1513
1514 /* call Error */
1515 dispparams.cNamedArgs = 0;
1516 dispparams.cArgs = 0;
1517 dispparams.rgdispidNamedArgs = NULL;
1518 dispparams.rgvarg = NULL;
1519 VariantInit(&varresult);
1520 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1521 ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1522 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1523 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1524 excepinfo.wCode, excepinfo.scode);
1525 VariantClear(&varresult);
1526
1527 /* call BstrRet */
1528 pTypeInfo = NonOleAutomation_GetTypeInfo();
1529 dispparams.cNamedArgs = 0;
1530 dispparams.cArgs = 0;
1531 dispparams.rgdispidNamedArgs = NULL;
1532 dispparams.rgvarg = NULL;
1533 VariantInit(&varresult);
1534 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1535 ok_ole_success(hr, ITypeInfo_Invoke);
1536 ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
1537 ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
1538
1539 VariantClear(&varresult);
1540
1541 dispparams.cNamedArgs = 0;
1542 dispparams.cArgs = 0;
1543 dispparams.rgdispidNamedArgs = NULL;
1544 dispparams.rgvarg = NULL;
1545 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_ERROR, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1546 ok(hr == DISP_E_EXCEPTION, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1547 ok(V_VT(&varresult) == VT_EMPTY, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult));
1548 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1549 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1550 excepinfo.wCode, excepinfo.scode);
1551 VariantClear(&varresult);
1552
1553 ITypeInfo_Release(pTypeInfo);
1554
1555 /* tests call put_Name without named arg */
1556 VariantInit(&vararg[0]);
1557 dispparams.cNamedArgs = 0;
1558 dispparams.rgdispidNamedArgs = NULL;
1559 dispparams.cArgs = 1;
1560 dispparams.rgvarg = vararg;
1561 VariantInit(&varresult);
1562 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1563 ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
1564 VariantClear(&varresult);
1565
1566 /* tests param type that cannot be coerced */
1567 VariantInit(&vararg[0]);
1568 V_VT(&vararg[0]) = VT_UNKNOWN;
1569 V_UNKNOWN(&vararg[0]) = NULL;
1570 dispparams.cNamedArgs = 1;
1571 dispparams.rgdispidNamedArgs = &dispidNamed;
1572 dispparams.cArgs = 1;
1573 dispparams.rgvarg = vararg;
1574 VariantInit(&varresult);
1575 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1576 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
1577 VariantClear(&varresult);
1578
1579 /* tests bad param type */
1580 VariantInit(&vararg[0]);
1581 V_VT(&vararg[0]) = VT_CLSID;
1582 V_BYREF(&vararg[0]) = NULL;
1583 dispparams.cNamedArgs = 1;
1584 dispparams.rgdispidNamedArgs = &dispidNamed;
1585 dispparams.cArgs = 1;
1586 dispparams.rgvarg = vararg;
1587 VariantInit(&varresult);
1588 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1589 ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
1590 VariantClear(&varresult);
1591
1592 /* tests too small param count */
1593 dispparams.cNamedArgs = 0;
1594 dispparams.rgdispidNamedArgs = NULL;
1595 dispparams.cArgs = 0;
1596 dispparams.rgvarg = NULL;
1597 VariantInit(&varresult);
1598 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1599 ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
1600 VariantClear(&varresult);
1601
1602 /* tests propget function with large param count */
1603 VariantInit(&vararg[0]);
1604 V_VT(&vararg[0]) = VT_BSTR;
1605 V_BSTR(&vararg[0]) = NULL;
1606 V_VT(&vararg[1]) = VT_I4;
1607 V_I4(&vararg[1]) = 1;
1608 dispparams.cNamedArgs = 0;
1609 dispparams.cArgs = 2;
1610 dispparams.rgdispidNamedArgs = NULL;
1611 dispparams.rgvarg = vararg;
1612 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1613 ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
1614
1615 /* test propput with lcid */
1616
1617 /* the lcid passed to the function is the first lcid in the typelib header.
1618 Since we don't explicitly set an lcid in the idl, it'll default to US English. */
1619 VariantInit(&vararg[0]);
1620 V_VT(&vararg[0]) = VT_I4;
1621 V_I4(&vararg[0]) = 0xcafe;
1622 dispparams.cNamedArgs = 1;
1623 dispparams.rgdispidNamedArgs = &dispidNamed;
1624 dispparams.cArgs = 1;
1625 dispparams.rgvarg = vararg;
1626 VariantInit(&varresult);
1627 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1628 ok_ole_success(hr, ITypeInfo_Invoke);
1629 VariantClear(&varresult);
1630
1631 /* test propget with lcid */
1632 dispparams.cNamedArgs = 0;
1633 dispparams.cArgs = 0;
1634 dispparams.rgvarg = NULL;
1635 dispparams.rgdispidNamedArgs = NULL;
1636 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1637 ok_ole_success(hr, ITypeInfo_Invoke);
1638 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1639 ok(V_I4(&varresult) == 0x409, "got %x\n", V_I4(&varresult));
1640 VariantClear(&varresult);
1641
1642 /* test propget of INT value */
1643 dispparams.cNamedArgs = 0;
1644 dispparams.cArgs = 0;
1645 dispparams.rgvarg = NULL;
1646 dispparams.rgdispidNamedArgs = NULL;
1647 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_INT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1648 ok_ole_success(hr, ITypeInfo_Invoke);
1649 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1650 ok(V_I4(&varresult) == -13, "got %x\n", V_I4(&varresult));
1651 VariantClear(&varresult);
1652
1653 /* test propget of INT value */
1654 dispparams.cNamedArgs = 0;
1655 dispparams.cArgs = 0;
1656 dispparams.rgvarg = NULL;
1657 dispparams.rgdispidNamedArgs = NULL;
1658 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_UINT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1659 ok_ole_success(hr, ITypeInfo_Invoke);
1660 ok(V_VT(&varresult) == VT_UI4, "got %x\n", V_VT(&varresult));
1661 ok(V_UI4(&varresult) == 42, "got %x\n", V_UI4(&varresult));
1662 VariantClear(&varresult);
1663
1664 /* test byref marshalling */
1665 uval = 666;
1666 VariantInit(&vararg[0]);
1667 V_VT(&vararg[0]) = VT_UI4|VT_BYREF;
1668 V_UI4REF(&vararg[0]) = &uval;
1669 dispparams.cNamedArgs = 0;
1670 dispparams.cArgs = 1;
1671 dispparams.rgvarg = vararg;
1672 dispparams.rgdispidNamedArgs = NULL;
1673 hr = IDispatch_Invoke(pDispatch, DISPID_TM_BYREF_UINT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1674 ok_ole_success(hr, ITypeInfo_Invoke);
1675 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1676 ok(V_VT(&vararg[0]) == (VT_UI4|VT_BYREF), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg[0]));
1677 ok(V_UI4REF(&vararg[0]) == &uval, "Byref pointer not preserved: %p/%p\n", &uval, V_UI4REF(&vararg[0]));
1678 ok(*V_UI4REF(&vararg[0]) == 42, "Expected 42 to be returned instead of %u\n", *V_UI4REF(&vararg[0]));
1679 VariantClear(&varresult);
1680 VariantClear(&vararg[0]);
1681
1682 /* test propput with optional argument. */
1683 VariantInit(&vararg[0]);
1684 V_VT(&vararg[0]) = VT_I4;
1685 V_I4(&vararg[0]) = 0xcafe;
1686 dispparams.cNamedArgs = 1;
1687 dispparams.rgdispidNamedArgs = &dispidNamed;
1688 dispparams.cArgs = 1;
1689 dispparams.rgvarg = vararg;
1690 VariantInit(&varresult);
1691 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_OPT_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1692 ok_ole_success(hr, ITypeInfo_Invoke);
1693 VariantClear(&varresult);
1694
1695 /* test propput with required argument. */
1696 VariantInit(&vararg[0]);
1697 VariantInit(&vararg[1]);
1698 V_VT(&vararg[0]) = VT_I4;
1699 V_I4(&vararg[0]) = 0x1234;
1700 V_VT(&vararg[1]) = VT_I4;
1701 V_I4(&vararg[1]) = 0x5678;
1702 dispparams.cNamedArgs = 1;
1703 dispparams.rgdispidNamedArgs = &dispidNamed;
1704 dispparams.cArgs = 2;
1705 dispparams.rgvarg = vararg;
1706 VariantInit(&varresult);
1707 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_REQ_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1708 ok_ole_success(hr, ITypeInfo_Invoke);
1709 VariantClear(&varresult);
1710
1711 /* restricted member */
1712 dispparams.cNamedArgs = 0;
1713 dispparams.rgdispidNamedArgs = NULL;
1714 dispparams.cArgs = 0;
1715 dispparams.rgvarg = NULL;
1716 VariantInit(&varresult);
1717 hr = IDispatch_Invoke(pDispatch, DISPID_TM_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1718 ok( hr == DISP_E_MEMBERNOTFOUND, "got %08x\n", hr );
1719 VariantClear(&varresult);
1720
1721 /* restricted member with -ve memid (not restricted) */
1722 dispparams.cNamedArgs = 0;
1723 dispparams.rgdispidNamedArgs = NULL;
1724 dispparams.cArgs = 0;
1725 dispparams.rgvarg = NULL;
1726 VariantInit(&varresult);
1727 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NEG_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1728 ok( hr == S_OK, "got %08x\n", hr );
1729 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1730 ok(V_I4(&varresult) == DISPID_TM_NEG_RESTRICTED, "got %x\n", V_I4(&varresult));
1731 VariantClear(&varresult);
1732
1733 IDispatch_Release(pDispatch);
1734 IWidget_Release(pWidget);
1735
1736 trace("calling end_host_object\n");
1737 end_host_object(tid, thread);
1738 }
1739
1740 static void test_DispCallFunc(void)
1741 {
1742 static const WCHAR szEmpty[] = { 0 };
1743 VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
1744 VARIANTARG vararg[4];
1745 VARIANTARG varref;
1746 VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
1747 VARIANTARG varresult;
1748 HRESULT hr;
1749 IWidget *pWidget = Widget_Create();
1750 V_VT(&vararg[0]) = VT_R8;
1751 V_R8(&vararg[0]) = 3.141;
1752 V_VT(&vararg[1]) = VT_BSTR;
1753 V_BSTRREF(&vararg[1]) = CoTaskMemAlloc(sizeof(BSTR));
1754 V_VT(&vararg[2]) = VT_BSTR;
1755 V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
1756 V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
1757 V_VARIANTREF(&vararg[3]) = &varref;
1758 V_VT(&varref) = VT_ERROR;
1759 V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
1760 VariantInit(&varresult);
1761 hr = DispCallFunc(pWidget, 9*sizeof(void*), CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
1762 ok_ole_success(hr, DispCallFunc);
1763 VariantClear(&varresult);
1764 SysFreeString(*V_BSTRREF(&vararg[1]));
1765 CoTaskMemFree(V_BSTRREF(&vararg[1]));
1766 VariantClear(&vararg[2]);
1767 IWidget_Release(pWidget);
1768 }
1769
1770 static void test_StaticWidget(void)
1771 {
1772 ITypeInfo *type_info;
1773 DISPPARAMS dispparams;
1774 VARIANTARG vararg[4];
1775 EXCEPINFO excepinfo;
1776 VARIANT varresult;
1777 HRESULT hr;
1778
1779 type_info = get_type_info(&IID_IStaticWidget);
1780
1781 /* call TestDual */
1782 dispparams.cNamedArgs = 0;
1783 dispparams.cArgs = 1;
1784 dispparams.rgdispidNamedArgs = NULL;
1785 dispparams.rgvarg = vararg;
1786 V_VT(vararg) = VT_DISPATCH;
1787 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
1788 VariantInit(&varresult);
1789 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTDUAL, DISPATCH_METHOD,
1790 &dispparams, &varresult, &excepinfo, NULL);
1791 ok_ole_success(hr, IDispatch_Invoke);
1792 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
1793 VariantClear(&varresult);
1794
1795 /* call TestSecondIface */
1796 dispparams.cNamedArgs = 0;
1797 dispparams.cArgs = 1;
1798 dispparams.rgdispidNamedArgs = NULL;
1799 dispparams.rgvarg = vararg;
1800 V_VT(vararg) = VT_DISPATCH;
1801 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
1802 VariantInit(&varresult);
1803 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTSECONDIFACE, DISPATCH_METHOD,
1804 &dispparams, &varresult, &excepinfo, NULL);
1805 ok_ole_success(hr, IDispatch_Invoke);
1806 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
1807 VariantClear(&varresult);
1808
1809 ITypeInfo_Release(type_info);
1810 }
1811
1812 static void test_libattr(void)
1813 {
1814 ITypeLib *pTypeLib;
1815 HRESULT hr;
1816 TLIBATTR *pattr;
1817
1818 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1819 ok_ole_success(hr, LoadRegTypeLib);
1820 if (FAILED(hr))
1821 return;
1822
1823 hr = ITypeLib_GetLibAttr(pTypeLib, &pattr);
1824 ok_ole_success(hr, GetLibAttr);
1825 if (SUCCEEDED(hr))
1826 {
1827 ok(pattr->lcid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "lcid %x\n", pattr->lcid);
1828
1829 ITypeLib_ReleaseTLibAttr(pTypeLib, pattr);
1830 }
1831
1832 ITypeLib_Release(pTypeLib);
1833 }
1834
1835 static void test_external_connection(void)
1836 {
1837 IStream *stream, *stream2;
1838 ITestSecondDisp *second;
1839 ItestDual *iface;
1840 HANDLE thread;
1841 DWORD tid;
1842 HRESULT hres;
1843
1844 static const LARGE_INTEGER zero;
1845
1846 trace("Testing IExternalConnection...\n");
1847
1848 external_connections = 0;
1849
1850 /* Marshaling an interface increases external connection count. */
1851 expect_last_release_closes = FALSE;
1852 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1853 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
1854 tid = start_host_object(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHLFLAGS_NORMAL, &thread);
1855 ok(external_connections == 1, "external_connections = %d\n", external_connections);
1856
1857 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1858 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
1859 ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
1860 ok(external_connections == 1, "external_connections = %d\n", external_connections);
1861
1862 IStream_Release(stream);
1863 ok(external_connections == 1, "external_connections = %d\n", external_connections);
1864
1865 /* Creating a stub for new iface causes new external connection. */
1866 hres = ItestDual_QueryInterface(iface, &IID_ITestSecondDisp, (void**)&second);
1867 ok(hres == S_OK, "Could not get ITestSecondDisp iface: %08x\n", hres);
1868 todo_wine
1869 ok(external_connections == 2, "external_connections = %d\n", external_connections);
1870
1871 ITestSecondDisp_Release(second);
1872 todo_wine
1873 ok(external_connections == 2, "external_connections = %d\n", external_connections);
1874
1875 expect_last_release_closes = TRUE;
1876 ItestDual_Release(iface);
1877 ok(external_connections == 0, "external_connections = %d\n", external_connections);
1878
1879 end_host_object(tid, thread);
1880
1881 /* A test with direct CoMarshalInterface call. */
1882 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1883 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
1884
1885 expect_last_release_closes = FALSE;
1886 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1887 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
1888 ok(external_connections == 1, "external_connections = %d\n", external_connections);
1889
1890 expect_last_release_closes = TRUE;
1891 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1892 hres = CoReleaseMarshalData(stream);
1893 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
1894 ok(external_connections == 0, "external_connections = %d\n", external_connections);
1895
1896 /* Two separated marshal data are still one external connection. */
1897 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream2);
1898 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
1899
1900 expect_last_release_closes = FALSE;
1901 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1902 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1903 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
1904 ok(external_connections == 1, "external_connections = %d\n", external_connections);
1905
1906 hres = CoMarshalInterface(stream2, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1907 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
1908 ok(external_connections == 1, "external_connections = %d\n", external_connections);
1909
1910 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1911 hres = CoReleaseMarshalData(stream);
1912 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
1913 ok(external_connections == 1, "external_connections = %d\n", external_connections);
1914
1915 expect_last_release_closes = TRUE;
1916 IStream_Seek(stream2, zero, STREAM_SEEK_SET, NULL);
1917 hres = CoReleaseMarshalData(stream2);
1918 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
1919 ok(external_connections == 0, "external_connections = %d\n", external_connections);
1920
1921 /* Weak table marshaling does not increment external connections */
1922 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1923 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
1924
1925 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
1926 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
1927 ok(external_connections == 0, "external_connections = %d\n", external_connections);
1928
1929 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1930 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
1931 ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
1932 ok(external_connections == 0, "external_connections = %d\n", external_connections);
1933 ItestDual_Release(iface);
1934
1935 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1936 hres = CoReleaseMarshalData(stream);
1937 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
1938 ok(external_connections == 0, "external_connections = %d\n", external_connections);
1939 }
1940
1941 START_TEST(tmarshal)
1942 {
1943 HRESULT hr;
1944 HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll");
1945 pVarAdd = (void*)GetProcAddress(hOleaut32, "VarAdd");
1946
1947 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1948
1949 hr = register_current_module_typelib();
1950 if (FAILED(hr))
1951 {
1952 CoUninitialize();
1953 win_skip("Registration of the test typelib failed, skipping tests\n");
1954 return;
1955 }
1956
1957 test_typelibmarshal();
1958 test_DispCallFunc();
1959 test_StaticWidget();
1960 test_libattr();
1961 test_external_connection();
1962
1963 hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
1964 sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
1965 ok_ole_success(hr, UnRegisterTypeLib);
1966
1967 CoUninitialize();
1968 }