winex11.drv: Support multiple adapter display settings in registry.
[wine.git] / dlls / oleaut32 / tests / tmarshal.c
blob4e9a8baeca045ec12727eaccb395a768ae2e7f31
1 /*
2 * Copyright (C) 2005-2006 Robert Shearman for CodeWeavers
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.
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.
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
20 #include <math.h>
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include <windows.h>
26 #include <ocidl.h>
27 #include <stdio.h>
29 #include "wine/test.h"
31 #include "tmarshal.h"
33 static HRESULT (WINAPI *pVarAdd)(LPVARIANT,LPVARIANT,LPVARIANT);
36 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
37 static inline void release_iface_(unsigned int line, void *iface)
39 ULONG ref = IUnknown_Release((IUnknown *)iface);
40 ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
41 if (ref == 1) IUnknown_Release((IUnknown *)iface);
43 #define release_iface(a) release_iface_(__LINE__, a)
45 /* ULL suffix is not portable */
46 #define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
48 static const WCHAR test_bstr1[] = {'f','o','o',0,'b','a','r'};
49 static const WCHAR test_bstr2[] = {'t','e','s','t',0};
50 static const WCHAR test_bstr3[] = {'q','u','x',0};
51 static const WCHAR test_bstr4[] = {'a','b','c',0};
53 static const MYSTRUCT test_mystruct1 = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432), {0,1,2,3,4,5,6,7}};
54 static const MYSTRUCT test_mystruct2 = {0x91827364, ULL_CONST(0x88776655, 0x44332211), {3,6,1,4,0,1,3,0}};
55 static const MYSTRUCT test_mystruct3 = {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415), {9,2,4,5,6,5,1,3}};
56 static const MYSTRUCT test_mystruct4 = {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425), {0,4,6,7,3,6,7,4}};
57 static const MYSTRUCT test_mystruct5 = {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435), {1,6,7,3,8,4,6,5}};
58 static const MYSTRUCT test_mystruct6 = {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445), {3,6,5,3,4,8,0,9}};
59 static const MYSTRUCT test_mystruct7 = {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455), {1,8,4,4,4,2,3,1}};
61 static const struct thin test_thin_struct = {-456, 78};
63 static const RECT test_rect1 = {1,2,3,4};
64 static const RECT test_rect2 = {5,6,7,8};
65 static const RECT test_rect3 = {9,10,11,12};
66 static const RECT test_rect4 = {13,14,15,16};
67 static const RECT test_rect5 = {17,18,19,20};
68 static const RECT test_rect6 = {21,22,23,24};
69 static const RECT test_rect7 = {25,26,27,28};
71 static const array_t test_array1 = {1,2,3,4};
72 static const array_t test_array2 = {5,6,7,8};
73 static const array_t test_array3 = {9,10,11,12};
74 static const array_t test_array4 = {13,14,15,16};
75 static const array_t test_array5 = {17,18,19,20};
76 static const array_t test_array6 = {21,22,23,24};
78 #define RELEASEMARSHALDATA WM_USER
80 struct host_object_data
82 IStream *stream;
83 IID iid;
84 IUnknown *object;
85 MSHLFLAGS marshal_flags;
86 HANDLE marshal_event;
87 IMessageFilter *filter;
90 static DWORD CALLBACK host_object_proc(LPVOID p)
92 struct host_object_data *data = p;
93 HRESULT hr;
94 MSG msg;
96 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
98 if (data->filter)
100 IMessageFilter * prev_filter = NULL;
101 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
102 if (prev_filter) IMessageFilter_Release(prev_filter);
103 ok_ole_success(hr, CoRegisterMessageFilter);
106 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
107 ok_ole_success(hr, CoMarshalInterface);
109 /* force the message queue to be created before signaling parent thread */
110 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
112 SetEvent(data->marshal_event);
114 while (GetMessageA(&msg, NULL, 0, 0))
116 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
118 trace("releasing marshal data\n");
119 CoReleaseMarshalData(data->stream);
120 SetEvent((HANDLE)msg.lParam);
122 else
123 DispatchMessageA(&msg);
126 HeapFree(GetProcessHeap(), 0, data);
128 CoUninitialize();
130 return hr;
133 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
135 DWORD tid = 0;
136 HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
137 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
139 data->stream = stream;
140 data->iid = *riid;
141 data->object = object;
142 data->marshal_flags = marshal_flags;
143 data->marshal_event = marshal_event;
144 data->filter = filter;
146 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
148 /* wait for marshaling to complete before returning */
149 WaitForSingleObject(marshal_event, INFINITE);
150 CloseHandle(marshal_event);
152 return tid;
155 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
157 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
160 #if 0 /* not used */
161 /* asks thread to release the marshal data because it has to be done by the
162 * same thread that marshaled the interface in the first place. */
163 static void release_host_object(DWORD tid)
165 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
166 PostThreadMessageA(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
167 WaitForSingleObject(event, INFINITE);
168 CloseHandle(event);
170 #endif
172 static void end_host_object(DWORD tid, HANDLE thread)
174 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
175 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
176 /* be careful of races - don't return until hosting thread has terminated */
177 WaitForSingleObject(thread, INFINITE);
178 CloseHandle(thread);
181 static int external_connections;
182 static BOOL expect_last_release_closes;
184 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
186 ok(0, "unexpected call\n");
187 *ppv = NULL;
188 return E_NOINTERFACE;
191 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
193 return 2;
196 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
198 return 1;
201 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
203 trace("add connection\n");
205 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
206 ok(!reserved, "reserved = %x\n", reserved);
207 return ++external_connections;
210 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
211 DWORD reserved, BOOL fLastReleaseCloses)
213 trace("release connection\n");
215 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
216 ok(!reserved, "reserved = %x\n", reserved);
218 ok(fLastReleaseCloses == expect_last_release_closes, "fLastReleaseCloses = %x, expected %x\n",
219 fLastReleaseCloses, expect_last_release_closes);
220 return --external_connections;
223 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
224 ExternalConnection_QueryInterface,
225 ExternalConnection_AddRef,
226 ExternalConnection_Release,
227 ExternalConnection_AddConnection,
228 ExternalConnection_ReleaseConnection
231 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
233 static ItestDual TestDual, TestDualDisp;
235 static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
237 return ItestDual_QueryInterface(&TestDual, riid, ppv);
240 static ULONG WINAPI TestSecondIface_AddRef(ITestSecondIface *iface)
242 return 2;
245 static ULONG WINAPI TestSecondIface_Release(ITestSecondIface *iface)
247 return 1;
250 static HRESULT WINAPI TestSecondIface_test(ITestSecondIface *iface)
252 return 1;
255 static const ITestSecondIfaceVtbl TestSecondIfaceVtbl = {
256 TestSecondIface_QueryInterface,
257 TestSecondIface_AddRef,
258 TestSecondIface_Release,
259 TestSecondIface_test
262 static ITestSecondIface TestSecondIface = { &TestSecondIfaceVtbl };
264 static HRESULT WINAPI TestSecondDisp_QueryInterface(ITestSecondDisp *iface, REFIID riid, void **ppv)
266 return ItestDual_QueryInterface(&TestDual, riid, ppv);
269 static ULONG WINAPI TestSecondDisp_AddRef(ITestSecondDisp *iface)
271 return 2;
274 static ULONG WINAPI TestSecondDisp_Release(ITestSecondDisp *iface)
276 return 1;
279 static HRESULT WINAPI TestSecondDisp_GetTypeInfoCount(ITestSecondDisp *iface, UINT *pctinfo)
281 ok(0, "unexpected call\n");
282 return E_NOTIMPL;
285 static HRESULT WINAPI TestSecondDisp_GetTypeInfo(ITestSecondDisp *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
287 ok(0, "unexpected call\n");
288 return E_NOTIMPL;
291 static HRESULT WINAPI TestSecondDisp_GetIDsOfNames(ITestSecondDisp *iface, REFIID riid, LPOLESTR *rgszNames,
292 UINT cNames, LCID lcid, DISPID *rgDispId)
294 ok(0, "unexpected call\n");
295 return E_NOTIMPL;
298 static HRESULT WINAPI TestSecondDisp_Invoke(ITestSecondDisp *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
299 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
300 UINT *puArgErr)
302 ok(0, "unexpected call\n");
303 return E_NOTIMPL;
306 static HRESULT WINAPI TestSecondDisp_test(ITestSecondDisp *iface)
308 ok(0, "unexpected call\n");
309 return E_NOTIMPL;
312 static ITestSecondDispVtbl TestSecondDispVtbl = {
313 TestSecondDisp_QueryInterface,
314 TestSecondDisp_AddRef,
315 TestSecondDisp_Release,
316 TestSecondDisp_GetTypeInfoCount,
317 TestSecondDisp_GetTypeInfo,
318 TestSecondDisp_GetIDsOfNames,
319 TestSecondDisp_Invoke,
320 TestSecondDisp_test
323 static ITestSecondDisp TestSecondDisp = { &TestSecondDispVtbl };
325 static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, void **ppvObject)
327 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) {
328 *ppvObject = &TestDualDisp;
329 return S_OK;
330 }else if(IsEqualGUID(riid, &IID_ItestDual)) {
331 *ppvObject = &TestDual;
332 return S_OK;
333 }else if(IsEqualGUID(riid, &IID_ITestSecondIface)) {
334 *ppvObject = &TestSecondIface;
335 return S_OK;
336 }else if(IsEqualGUID(riid, &IID_ITestSecondDisp)) {
337 *ppvObject = &TestSecondDisp;
338 return S_OK;
339 }else if (IsEqualGUID(riid, &IID_IExternalConnection)) {
340 trace("QI external connection\n");
341 *ppvObject = &ExternalConnection;
342 return S_OK;
345 *ppvObject = NULL;
346 return E_NOINTERFACE;
349 static ULONG WINAPI TestDual_AddRef(ItestDual *iface)
351 return 2;
354 static ULONG WINAPI TestDual_Release(ItestDual *iface)
356 return 1;
359 static HRESULT WINAPI TestDual_GetTypeInfoCount(ItestDual *iface, UINT *pctinfo)
361 ok(0, "unexpected call\n");
362 return E_NOTIMPL;
365 static HRESULT WINAPI TestDual_GetTypeInfo(ItestDual *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
367 ok(0, "unexpected call\n");
368 return E_NOTIMPL;
371 static HRESULT WINAPI TestDual_GetIDsOfNames(ItestDual *iface, REFIID riid, LPOLESTR *rgszNames,
372 UINT cNames, LCID lcid, DISPID *rgDispId)
374 ok(0, "unexpected call\n");
375 return E_NOTIMPL;
378 static HRESULT WINAPI TestDual_Invoke(ItestDual *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
379 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
380 UINT *puArgErr)
382 ok(0, "unexpected call\n");
383 return E_NOTIMPL;
386 static ItestDualVtbl TestDualVtbl = {
387 TestDual_QueryInterface,
388 TestDual_AddRef,
389 TestDual_Release,
390 TestDual_GetTypeInfoCount,
391 TestDual_GetTypeInfo,
392 TestDual_GetIDsOfNames,
393 TestDual_Invoke
396 static ItestDual TestDual = { &TestDualVtbl };
397 static ItestDual TestDualDisp = { &TestDualVtbl };
399 struct disp_obj
401 ISomethingFromDispatch ISomethingFromDispatch_iface;
402 LONG ref;
405 static inline struct disp_obj *impl_from_ISomethingFromDispatch(ISomethingFromDispatch *iface)
407 return CONTAINING_RECORD(iface, struct disp_obj, ISomethingFromDispatch_iface);
410 static HRESULT WINAPI disp_obj_QueryInterface(ISomethingFromDispatch *iface, REFIID iid, void **out)
412 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IDispatch)
413 || IsEqualGUID(iid, &IID_ISomethingFromDispatch)
414 || IsEqualGUID(iid, &DIID_ItestIF4))
416 *out = iface;
417 ISomethingFromDispatch_AddRef(iface);
418 return S_OK;
421 *out = NULL;
422 return E_NOINTERFACE;
425 static ULONG WINAPI disp_obj_AddRef(ISomethingFromDispatch *iface)
427 struct disp_obj *obj = impl_from_ISomethingFromDispatch(iface);
428 return ++obj->ref;
431 static ULONG WINAPI disp_obj_Release(ISomethingFromDispatch *iface)
433 struct disp_obj *obj = impl_from_ISomethingFromDispatch(iface);
434 LONG ref = --obj->ref;
435 if (!ref)
436 CoTaskMemFree(obj);
437 return ref;
440 static HRESULT WINAPI disp_obj_GetTypeInfoCount(ISomethingFromDispatch *iface, UINT *count)
442 ok(0, "unexpected call\n");
443 return E_NOTIMPL;
446 static HRESULT WINAPI disp_obj_GetTypeInfo(ISomethingFromDispatch *iface,
447 UINT index, LCID lcid, ITypeInfo **typeinfo)
449 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
450 return 0xbeefdead;
453 static HRESULT WINAPI disp_obj_GetIDsOfNames(ISomethingFromDispatch *iface,
454 REFIID iid, LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
456 ok(0, "unexpected call\n");
457 return E_NOTIMPL;
460 static HRESULT WINAPI disp_obj_Invoke(ISomethingFromDispatch *iface, DISPID id, REFIID iid, LCID lcid,
461 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
463 ok(0, "unexpected call\n");
464 return E_NOTIMPL;
467 static HRESULT WINAPI disp_obj_anotherfn(ISomethingFromDispatch *iface)
469 return 0x01234567;
472 static const ISomethingFromDispatchVtbl disp_obj_vtbl =
474 disp_obj_QueryInterface,
475 disp_obj_AddRef,
476 disp_obj_Release,
477 disp_obj_GetTypeInfoCount,
478 disp_obj_GetTypeInfo,
479 disp_obj_GetIDsOfNames,
480 disp_obj_Invoke,
481 disp_obj_anotherfn,
484 static ISomethingFromDispatch *create_disp_obj(void)
486 struct disp_obj *obj = CoTaskMemAlloc(sizeof(*obj));
487 obj->ISomethingFromDispatch_iface.lpVtbl = &disp_obj_vtbl;
488 obj->ref = 1;
489 return &obj->ISomethingFromDispatch_iface;
492 struct coclass_obj
494 ICoclass1 ICoclass1_iface;
495 ICoclass2 ICoclass2_iface;
496 LONG ref;
499 static inline struct coclass_obj *impl_from_ICoclass1(ICoclass1 *iface)
501 return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass1_iface);
504 static inline struct coclass_obj *impl_from_ICoclass2(ICoclass2 *iface)
506 return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass2_iface);
509 static HRESULT WINAPI coclass1_QueryInterface(ICoclass1 *iface, REFIID iid, void **out)
511 struct coclass_obj *obj = impl_from_ICoclass1(iface);
513 if (IsEqualGUID(iid, &IID_IUnknown)
514 || IsEqualGUID(iid, &IID_IDispatch)
515 || IsEqualGUID(iid, &IID_ICoclass1))
517 *out = iface;
518 ICoclass1_AddRef(iface);
519 return S_OK;
521 else if (IsEqualGUID(iid, &IID_ICoclass2))
523 *out = &obj->ICoclass2_iface;
524 ICoclass2_AddRef(*out);
525 return S_OK;
528 *out = NULL;
529 return E_NOINTERFACE;
532 static ULONG WINAPI coclass1_AddRef(ICoclass1 *iface)
534 struct coclass_obj *obj = impl_from_ICoclass1(iface);
535 return ++obj->ref;
538 static ULONG WINAPI coclass1_Release(ICoclass1 *iface)
540 struct coclass_obj *obj = impl_from_ICoclass1(iface);
541 LONG ref = --obj->ref;
542 if (!ref)
543 CoTaskMemFree(obj);
544 return ref;
547 static HRESULT WINAPI coclass1_GetTypeInfoCount(ICoclass1 *iface, UINT *count)
549 ok(0, "unexpected call\n");
550 return E_NOTIMPL;
553 static HRESULT WINAPI coclass1_GetTypeInfo(ICoclass1 *iface, UINT index,
554 LCID lcid, ITypeInfo **typeinfo)
556 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
557 return 0xbeefdead;
560 static HRESULT WINAPI coclass1_GetIDsOfNames(ICoclass1 *iface, REFIID iid,
561 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
563 ok(0, "unexpected call\n");
564 return E_NOTIMPL;
567 static HRESULT WINAPI coclass1_Invoke(ICoclass1 *iface, DISPID id, REFIID iid, LCID lcid,
568 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
570 ok(0, "unexpected call\n");
571 return E_NOTIMPL;
574 static HRESULT WINAPI coclass1_test(ICoclass1 *iface)
576 return 1;
579 static HRESULT WINAPI coclass2_QueryInterface(ICoclass2 *iface, REFIID iid, void **out)
581 struct coclass_obj *obj = impl_from_ICoclass2(iface);
582 return ICoclass1_QueryInterface(&obj->ICoclass1_iface, iid, out);
585 static ULONG WINAPI coclass2_AddRef(ICoclass2 *iface)
587 struct coclass_obj *obj = impl_from_ICoclass2(iface);
588 return ICoclass1_AddRef(&obj->ICoclass1_iface);
591 static ULONG WINAPI coclass2_Release(ICoclass2 *iface)
593 struct coclass_obj *obj = impl_from_ICoclass2(iface);
594 return ICoclass1_Release(&obj->ICoclass1_iface);
597 static HRESULT WINAPI coclass2_GetTypeInfoCount(ICoclass2 *iface, UINT *count)
599 ok(0, "unexpected call\n");
600 return E_NOTIMPL;
603 static HRESULT WINAPI coclass2_GetTypeInfo(ICoclass2 *iface, UINT index,
604 LCID lcid, ITypeInfo **typeinfo)
606 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
607 return 0xbeefdead;
610 static HRESULT WINAPI coclass2_GetIDsOfNames(ICoclass2 *iface, REFIID iid,
611 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
613 ok(0, "unexpected call\n");
614 return E_NOTIMPL;
617 static HRESULT WINAPI coclass2_Invoke(ICoclass2 *iface, DISPID id, REFIID iid, LCID lcid,
618 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
620 ok(0, "unexpected call\n");
621 return E_NOTIMPL;
624 static HRESULT WINAPI coclass2_test(ICoclass2 *iface)
626 return 2;
629 static const ICoclass1Vtbl coclass1_vtbl =
631 coclass1_QueryInterface,
632 coclass1_AddRef,
633 coclass1_Release,
634 coclass1_GetTypeInfoCount,
635 coclass1_GetTypeInfo,
636 coclass1_GetIDsOfNames,
637 coclass1_Invoke,
638 coclass1_test,
641 static const ICoclass2Vtbl coclass2_vtbl =
643 coclass2_QueryInterface,
644 coclass2_AddRef,
645 coclass2_Release,
646 coclass2_GetTypeInfoCount,
647 coclass2_GetTypeInfo,
648 coclass2_GetIDsOfNames,
649 coclass2_Invoke,
650 coclass2_test,
653 static struct coclass_obj *create_coclass_obj(void)
655 struct coclass_obj *obj = CoTaskMemAlloc(sizeof(*obj));
656 obj->ICoclass1_iface.lpVtbl = &coclass1_vtbl;
657 obj->ICoclass2_iface.lpVtbl = &coclass2_vtbl;
658 obj->ref = 1;
659 return obj;
662 static int testmode;
664 typedef struct Widget
666 IWidget IWidget_iface;
667 LONG refs;
668 IUnknown *pDispatchUnknown;
669 } Widget;
671 static inline Widget *impl_from_IWidget(IWidget *iface)
673 return CONTAINING_RECORD(iface, Widget, IWidget_iface);
676 static HRESULT WINAPI Widget_QueryInterface(
677 IWidget *iface,
678 /* [in] */ REFIID riid,
679 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
681 if (IsEqualIID(riid, &IID_IWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
683 IWidget_AddRef(iface);
684 *ppvObject = iface;
685 return S_OK;
687 else
689 *ppvObject = NULL;
690 return E_NOINTERFACE;
694 static ULONG WINAPI Widget_AddRef(
695 IWidget *iface)
697 Widget *This = impl_from_IWidget(iface);
699 return InterlockedIncrement(&This->refs);
702 static ULONG WINAPI Widget_Release(
703 IWidget *iface)
705 Widget *This = impl_from_IWidget(iface);
706 ULONG refs = InterlockedDecrement(&This->refs);
707 if (!refs)
709 IUnknown_Release(This->pDispatchUnknown);
710 memset(This, 0xcc, sizeof(*This));
711 HeapFree(GetProcessHeap(), 0, This);
712 trace("Widget destroyed!\n");
715 return refs;
718 static HRESULT WINAPI Widget_GetTypeInfoCount(
719 IWidget *iface,
720 /* [out] */ UINT __RPC_FAR *pctinfo)
722 Widget *This = impl_from_IWidget(iface);
723 IDispatch *pDispatch;
724 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
725 if (SUCCEEDED(hr))
727 hr = IDispatch_GetTypeInfoCount(pDispatch, pctinfo);
728 IDispatch_Release(pDispatch);
730 return hr;
733 static HRESULT WINAPI Widget_GetTypeInfo(
734 IWidget __RPC_FAR * iface,
735 /* [in] */ UINT iTInfo,
736 /* [in] */ LCID lcid,
737 /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
739 Widget *This = impl_from_IWidget(iface);
740 IDispatch *pDispatch;
741 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
742 if (SUCCEEDED(hr))
744 hr = IDispatch_GetTypeInfo(pDispatch, iTInfo, lcid, ppTInfo);
745 IDispatch_Release(pDispatch);
747 return hr;
750 static HRESULT WINAPI Widget_GetIDsOfNames(
751 IWidget __RPC_FAR * iface,
752 /* [in] */ REFIID riid,
753 /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
754 /* [in] */ UINT cNames,
755 /* [in] */ LCID lcid,
756 /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
758 Widget *This = impl_from_IWidget(iface);
759 IDispatch *pDispatch;
760 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
761 if (SUCCEEDED(hr))
763 hr = IDispatch_GetIDsOfNames(pDispatch, riid, rgszNames, cNames, lcid, rgDispId);
764 IDispatch_Release(pDispatch);
766 return hr;
769 static HRESULT WINAPI Widget_Invoke(
770 IWidget __RPC_FAR * iface,
771 /* [in] */ DISPID dispIdMember,
772 /* [in] */ REFIID riid,
773 /* [in] */ LCID lcid,
774 /* [in] */ WORD wFlags,
775 /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
776 /* [out] */ VARIANT __RPC_FAR *pVarResult,
777 /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
778 /* [out] */ UINT __RPC_FAR *puArgErr)
780 Widget *This = impl_from_IWidget(iface);
781 IDispatch *pDispatch;
782 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
783 if (SUCCEEDED(hr))
785 hr = IDispatch_Invoke(pDispatch, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
786 IDispatch_Release(pDispatch);
788 return hr;
791 static HRESULT WINAPI Widget_put_Name(
792 IWidget __RPC_FAR * iface,
793 /* [in] */ BSTR name)
795 trace("put_Name(%s)\n", wine_dbgstr_w(name));
796 return S_OK;
799 static HRESULT WINAPI Widget_get_Name(
800 IWidget __RPC_FAR * iface,
801 /* [out] */ BSTR __RPC_FAR *name)
803 static const WCHAR szCat[] = { 'C','a','t',0 };
804 trace("get_Name()\n");
805 *name = SysAllocString(szCat);
806 return S_OK;
809 static HRESULT WINAPI Widget_DoSomething(
810 IWidget __RPC_FAR * iface,
811 /* [in] */ double number,
812 /* [out] */ BSTR *str1,
813 /* [defaultvalue][in] */ BSTR str2,
814 /* [optional][in] */ VARIANT __RPC_FAR *opt)
816 static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
817 trace("DoSomething()\n");
819 ok(number == 3.141, "number(%f) != 3.141\n", number);
820 ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
821 ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt));
822 ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08x\n", V_ERROR(opt));
823 *str1 = SysAllocString(szString);
825 return S_FALSE;
828 static HRESULT WINAPI Widget_get_State(
829 IWidget __RPC_FAR * iface,
830 /* [retval][out] */ STATE __RPC_FAR *state)
832 trace("get_State() = STATE_WIDGETIFIED\n");
833 *state = STATE_WIDGETIFIED;
834 return S_OK;
837 static HRESULT WINAPI Widget_put_State(
838 IWidget __RPC_FAR * iface,
839 /* [in] */ STATE state)
841 trace("put_State(%d)\n", state);
842 return S_OK;
845 static HRESULT WINAPI Widget_Map(
846 IWidget * iface,
847 BSTR bstrId,
848 BSTR *sValue)
850 trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId), sValue);
851 *sValue = SysAllocString(bstrId);
852 return S_OK;
855 static HRESULT WINAPI Widget_SetOleColor(
856 IWidget * iface,
857 OLE_COLOR val)
859 trace("SetOleColor(0x%x)\n", val);
860 return S_OK;
863 static HRESULT WINAPI Widget_GetOleColor(
864 IWidget * iface,
865 OLE_COLOR *pVal)
867 trace("GetOleColor() = 0x8000000f\n");
868 *pVal = 0x8000000f;
869 return S_FALSE;
872 static HRESULT WINAPI Widget_Clone(
873 IWidget *iface,
874 IWidget **ppVal)
876 trace("Clone()\n");
877 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
880 static HRESULT WINAPI Widget_CloneDispatch(
881 IWidget *iface,
882 IDispatch **ppVal)
884 trace("CloneDispatch()\n");
885 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
888 static HRESULT WINAPI Widget_CloneCoclass(
889 IWidget *iface,
890 ApplicationObject2 **ppVal)
892 trace("CloneCoclass()\n");
893 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
896 static HRESULT WINAPI Widget_Value(
897 IWidget __RPC_FAR * iface,
898 VARIANT *value,
899 VARIANT *retval)
901 trace("Value(%p, %p)\n", value, retval);
902 ok(V_VT(value) == VT_I2, "V_VT(value) was %d instead of VT_I2\n", V_VT(value));
903 ok(V_I2(value) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value));
904 V_VT(retval) = VT_I2;
905 V_I2(retval) = 1234;
906 return S_OK;
909 static HRESULT WINAPI Widget_VariantArrayPtr(
910 IWidget * iface,
911 SAFEARRAY ** values)
913 trace("VariantArrayPtr(%p)\n", values);
914 return S_OK;
917 static HRESULT WINAPI Widget_VarArg(
918 IWidget * iface,
919 int numexpect,
920 SAFEARRAY * values)
922 LONG lbound, ubound, i;
923 VARIANT * data;
924 HRESULT hr;
926 trace("VarArg(%p)\n", values);
928 hr = SafeArrayGetLBound(values, 1, &lbound);
929 ok(hr == S_OK, "SafeArrayGetLBound failed with %x\n", hr);
930 ok(lbound == 0, "SafeArrayGetLBound returned %d\n", lbound);
932 hr = SafeArrayGetUBound(values, 1, &ubound);
933 ok(hr == S_OK, "SafeArrayGetUBound failed with %x\n", hr);
934 ok(ubound == numexpect-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound, numexpect-1);
936 hr = SafeArrayAccessData(values, (LPVOID)&data);
937 ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
939 for (i=0; i<=ubound-lbound; i++)
941 ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%d]) was %d\n", i, V_VT(&data[i]));
942 ok(V_I4(&data[i]) == i, "V_I4(&data[%d]) was %d\n", i, V_I4(&data[i]));
945 hr = SafeArrayUnaccessData(values);
946 ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr);
948 return S_OK;
951 static HRESULT WINAPI Widget_Error(
952 IWidget __RPC_FAR * iface)
954 trace("Error()\n");
955 return E_NOTIMPL;
958 static HRESULT WINAPI Widget_CloneInterface(
959 IWidget __RPC_FAR * iface,
960 ISomethingFromDispatch **ppVal)
962 trace("CloneInterface()\n");
963 *ppVal = 0;
964 return S_OK;
967 static HRESULT WINAPI Widget_put_prop_with_lcid(
968 IWidget* iface, LONG lcid, INT i)
970 trace("put_prop_with_lcid(%08x, %x)\n", lcid, i);
971 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
972 ok(i == 0xcafe, "got %08x\n", i);
973 return S_OK;
976 static HRESULT WINAPI Widget_get_prop_with_lcid(
977 IWidget* iface, LONG lcid, INT *i)
979 trace("get_prop_with_lcid(%08x, %p)\n", lcid, i);
980 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
981 *i = lcid;
982 return S_OK;
985 static HRESULT WINAPI Widget_get_prop_int(
986 IWidget* iface, INT *i)
988 trace("get_prop_int(%p)\n", i);
989 *i = -13;
990 return S_OK;
993 static HRESULT WINAPI Widget_get_prop_uint(
994 IWidget* iface, UINT *i)
996 trace("get_prop_uint(%p)\n", i);
997 *i = 42;
998 return S_OK;
1001 static HRESULT WINAPI Widget_ByRefUInt(
1002 IWidget* iface, UINT *i)
1004 *i = 42;
1005 return S_OK;
1008 static HRESULT WINAPI Widget_put_prop_opt_arg(
1009 IWidget* iface, INT opt, INT i)
1011 trace("put_prop_opt_arg(%08x, %08x)\n", opt, i);
1012 todo_wine ok(opt == 0, "got opt=%08x\n", opt);
1013 ok(i == 0xcafe, "got i=%08x\n", i);
1014 return S_OK;
1017 static HRESULT WINAPI Widget_put_prop_req_arg(
1018 IWidget* iface, INT req, INT i)
1020 trace("put_prop_req_arg(%08x, %08x)\n", req, i);
1021 ok(req == 0x5678, "got req=%08x\n", req);
1022 ok(i == 0x1234, "got i=%08x\n", i);
1023 return S_OK;
1026 static HRESULT WINAPI Widget_pos_restrict(IWidget* iface, INT *i)
1028 trace("restrict\n");
1029 *i = DISPID_TM_RESTRICTED;
1030 return S_OK;
1033 static HRESULT WINAPI Widget_neg_restrict(IWidget* iface, INT *i)
1035 trace("neg_restrict\n");
1036 *i = DISPID_TM_NEG_RESTRICTED;
1037 return S_OK;
1040 static HRESULT WINAPI Widget_VarArg_Run(
1041 IWidget *iface, BSTR name, SAFEARRAY *params, VARIANT *result)
1043 static const WCHAR catW[] = { 'C','a','t',0 };
1044 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1045 LONG bound;
1046 VARIANT *var;
1047 BSTR bstr;
1048 HRESULT hr;
1050 trace("VarArg_Run(%p,%p,%p)\n", name, params, result);
1052 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1054 hr = SafeArrayGetLBound(params, 1, &bound);
1055 ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
1056 ok(bound == 0, "expected 0, got %d\n", bound);
1058 hr = SafeArrayGetUBound(params, 1, &bound);
1059 ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
1060 ok(bound == 0, "expected 0, got %d\n", bound);
1062 hr = SafeArrayAccessData(params, (void **)&var);
1063 ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
1065 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1066 bstr = V_BSTR(&var[0]);
1067 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1069 hr = SafeArrayUnaccessData(params);
1070 ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
1072 return S_OK;
1075 static HRESULT WINAPI Widget_VarArg_Ref_Run(
1076 IWidget *iface, BSTR name, SAFEARRAY **params, VARIANT *result)
1078 static const WCHAR catW[] = { 'C','a','t',0 };
1079 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1080 LONG bound;
1081 VARIANT *var;
1082 BSTR bstr;
1083 HRESULT hr;
1085 trace("VarArg_Ref_Run(%p,%p,%p)\n", name, params, result);
1087 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1089 hr = SafeArrayGetLBound(*params, 1, &bound);
1090 ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
1091 ok(bound == 0, "expected 0, got %d\n", bound);
1093 hr = SafeArrayGetUBound(*params, 1, &bound);
1094 ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
1095 ok(bound == 0, "expected 0, got %d\n", bound);
1097 hr = SafeArrayAccessData(*params, (void **)&var);
1098 ok(hr == S_OK, "SafeArrayAccessData error %#x\n", hr);
1100 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1101 bstr = V_BSTR(&var[0]);
1102 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1104 hr = SafeArrayUnaccessData(*params);
1105 ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
1107 return S_OK;
1110 static HRESULT WINAPI Widget_basetypes_in(IWidget *iface, signed char c, short s, int i, hyper h,
1111 unsigned char uc, unsigned short us, unsigned int ui, MIDL_uhyper uh,
1112 float f, double d, STATE st)
1114 ok(c == 5, "Got char %d.\n", c);
1115 ok(s == -123, "Got short %d.\n", s);
1116 ok(i == -100000, "Got int %d.\n", i);
1117 ok(h == (LONGLONG)-100000 * 1000000, "Got hyper %s.\n", wine_dbgstr_longlong(h));
1118 ok(uc == 0, "Got unsigned char %u.\n", uc);
1119 ok(us == 456, "Got unsigned short %u.\n", us);
1120 ok(ui == 0xdeadbeef, "Got unsigned int %i.\n", ui);
1121 ok(uh == (ULONGLONG)1234567890 * 9876543210, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
1122 ok(f == (float)M_PI, "Got float %f.\n", f);
1123 ok(d == M_E, "Got double %f.\n", d);
1124 ok(st == STATE_WIDGETIFIED, "Got state %u.\n", st);
1126 return S_OK;
1129 static HRESULT WINAPI Widget_basetypes_out(IWidget *iface, signed char *c, short *s, int *i, hyper *h,
1130 unsigned char *uc, unsigned short *us, unsigned int *ui, MIDL_uhyper *uh,
1131 float *f, double *d, STATE *st)
1133 *c = 10;
1134 *s = -321;
1135 *i = -200000;
1136 *h = (LONGLONG)-200000 * 1000000;
1137 *uc = 254;
1138 *us = 256;
1139 *ui = 0xf00dfade;
1140 *uh = (((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789;
1141 *f = M_LN2;
1142 *d = M_LN10;
1143 *st = STATE_UNWIDGETIFIED;
1145 return S_OK;
1148 static HRESULT WINAPI Widget_float_abi(IWidget *iface, float f, double d, int i, float f2, double d2)
1150 ok(f == 1.0f, "Got float %f.\n", f);
1151 ok(d == 2.0, "Got double %f.\n", d);
1152 ok(i == 3, "Got int %d.\n", i);
1153 ok(f2 == 4.0f, "Got float %f.\n", f2);
1154 ok(d2 == 5.0, "Got double %f.\n", d2);
1156 return S_OK;
1159 static HRESULT WINAPI Widget_int_ptr(IWidget *iface, int *in, int *out, int *in_out)
1161 ok(*in == 123, "Got [in] %d.\n", *in);
1162 if (testmode == 0) /* Invoke() */
1163 ok(*out == 456, "Got [out] %d.\n", *out);
1164 else if (testmode == 1)
1165 ok(!*out, "Got [out] %d.\n", *out);
1166 ok(*in_out == 789, "Got [in, out] %d.\n", *in_out);
1168 *in = 987;
1169 *out = 654;
1170 *in_out = 321;
1172 return S_OK;
1175 static HRESULT WINAPI Widget_int_ptr_ptr(IWidget *iface, int **in, int **out, int **in_out)
1177 ok(!*out, "Got [out] %p.\n", *out);
1178 if (testmode == 0)
1180 ok(!*in, "Got [in] %p.\n", *in);
1181 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1183 else if (testmode == 1)
1185 ok(!*in, "Got [in] %p.\n", *in);
1186 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1188 *out = CoTaskMemAlloc(sizeof(int));
1189 **out = 654;
1190 *in_out = CoTaskMemAlloc(sizeof(int));
1191 **in_out = 321;
1193 else if (testmode == 2)
1195 ok(**in == 123, "Got [in] %d.\n", **in);
1196 ok(**in_out == 789, "Got [in, out] %d.\n", **in_out);
1198 *out = CoTaskMemAlloc(sizeof(int));
1199 **out = 654;
1200 **in_out = 321;
1202 else if (testmode == 3)
1204 ok(**in_out == 789, "Got [in, out] %d.\n", **in_out);
1205 *in_out = NULL;
1208 return S_OK;
1211 /* Call methods to check that we have valid proxies to each interface. */
1212 static void check_iface_marshal(IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1214 ISomethingFromDispatch *sfd2;
1215 ITypeInfo *typeinfo;
1216 HRESULT hr;
1218 hr = IUnknown_QueryInterface(unk, &IID_ISomethingFromDispatch, (void **)&sfd2);
1219 ok(hr == S_OK, "Got hr %#x.\n", hr);
1220 ISomethingFromDispatch_Release(sfd2);
1222 hr = IDispatch_GetTypeInfo(disp, 0xdeadbeef, 0, &typeinfo);
1223 ok(hr == 0xbeefdead, "Got hr %#x.\n", hr);
1225 hr = ISomethingFromDispatch_anotherfn(sfd);
1226 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1229 static HRESULT WINAPI Widget_iface_in(IWidget *iface, IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1231 if (testmode == 0)
1232 check_iface_marshal(unk, disp, sfd);
1233 else if (testmode == 1)
1235 ok(!unk, "Got iface %p.\n", unk);
1236 ok(!disp, "Got iface %p.\n", disp);
1237 ok(!sfd, "Got iface %p.\n", sfd);
1239 return S_OK;
1242 static HRESULT WINAPI Widget_iface_out(IWidget *iface, IUnknown **unk, IDispatch **disp, ISomethingFromDispatch **sfd)
1244 ok(!*unk, "Got iface %p.\n", *unk);
1245 ok(!*disp, "Got iface %p.\n", *disp);
1246 ok(!*sfd, "Got iface %p.\n", *sfd);
1248 if (testmode == 0)
1250 *unk = (IUnknown *)create_disp_obj();
1251 *disp = (IDispatch *)create_disp_obj();
1252 *sfd = create_disp_obj();
1254 return S_OK;
1257 static HRESULT WINAPI Widget_iface_ptr(IWidget *iface, ISomethingFromDispatch **in,
1258 ISomethingFromDispatch **out, ISomethingFromDispatch **in_out)
1260 HRESULT hr;
1262 ok(!*out, "Got [out] %p.\n", *out);
1263 if (testmode == 0 || testmode == 1)
1265 hr = ISomethingFromDispatch_anotherfn(*in);
1266 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1267 hr = ISomethingFromDispatch_anotherfn(*in_out);
1268 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1271 if (testmode == 1)
1273 *out = create_disp_obj();
1274 ISomethingFromDispatch_Release(*in_out);
1275 *in_out = create_disp_obj();
1277 else if (testmode == 2)
1279 ok(!*in, "Got [in] %p.\n", *in);
1280 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1281 *in_out = create_disp_obj();
1283 else if (testmode == 3)
1285 hr = ISomethingFromDispatch_anotherfn(*in_out);
1286 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1287 ISomethingFromDispatch_Release(*in_out);
1288 *in_out = NULL;
1291 return S_OK;
1294 static HRESULT WINAPI Widget_iface_noptr(IWidget *iface, IUnknown unk, IDispatch disp, ISomethingFromDispatch sfd)
1296 check_iface_marshal((IUnknown *)unk.lpVtbl, (IDispatch *)disp.lpVtbl, (ISomethingFromDispatch *)sfd.lpVtbl);
1297 return S_OK;
1300 static HRESULT WINAPI Widget_bstr(IWidget *iface, BSTR in, BSTR *out, BSTR *in_ptr, BSTR *in_out)
1302 UINT len;
1304 if (testmode == 0)
1306 len = SysStringByteLen(in);
1307 ok(len == sizeof(test_bstr1), "Got wrong length %u.\n", len);
1308 ok(!memcmp(in, test_bstr1, len), "Got string %s.\n", wine_dbgstr_wn(in, len / sizeof(WCHAR)));
1309 ok(!*out, "Got unexpected output %p.\n", *out);
1310 len = SysStringLen(*in_ptr);
1311 ok(len == lstrlenW(test_bstr2), "Got wrong length %u.\n", len);
1312 ok(!memcmp(*in_ptr, test_bstr2, len), "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1313 len = SysStringLen(*in_out);
1314 ok(len == lstrlenW(test_bstr3), "Got wrong length %u.\n", len);
1315 ok(!memcmp(*in_out, test_bstr3, len), "Got string %s.\n", wine_dbgstr_w(*in_out));
1317 *out = SysAllocString(test_bstr4);
1318 in[1] = (*in_ptr)[1] = (*in_out)[1] = 'X';
1320 else if (testmode == 1)
1322 ok(!in, "Got string %s.\n", wine_dbgstr_w(in));
1323 ok(!*out, "Got string %s.\n", wine_dbgstr_w(*out));
1324 ok(!*in_ptr, "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1325 ok(!*in_out, "Got string %s.\n", wine_dbgstr_w(*in_out));
1327 return S_OK;
1330 static HRESULT WINAPI Widget_variant(IWidget *iface, VARIANT in, VARIANT *out, VARIANT *in_ptr, VARIANT *in_out)
1332 ok(V_VT(&in) == VT_CY, "Got wrong type %#x.\n", V_VT(&in));
1333 ok(V_CY(&in).Hi == 0xdababe && V_CY(&in).Lo == 0xdeadbeef,
1334 "Got wrong value %s.\n", wine_dbgstr_longlong(V_CY(&in).int64));
1335 if (testmode == 0)
1337 ok(V_VT(out) == VT_I4, "Got wrong type %u.\n", V_VT(out));
1338 ok(V_I4(out) == 1, "Got wrong value %d.\n", V_I4(out));
1340 else
1341 ok(V_VT(out) == VT_EMPTY, "Got wrong type %u.\n", V_VT(out));
1342 ok(V_VT(in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(in_ptr));
1343 ok(V_I4(in_ptr) == -1, "Got wrong value %d.\n", V_I4(in_ptr));
1344 ok(V_VT(in_out) == VT_BSTR, "Got wrong type %u.\n", V_VT(in_out));
1345 ok(!lstrcmpW(V_BSTR(in_out), test_bstr2), "Got wrong value %s.\n",
1346 wine_dbgstr_w(V_BSTR(in_out)));
1348 V_VT(&in) = VT_I4;
1349 V_I4(&in) = 2;
1350 V_VT(out) = VT_UI1;
1351 V_UI1(out) = 3;
1352 V_VT(in_ptr) = VT_I2;
1353 V_I2(in_ptr) = 4;
1354 VariantClear(in_out);
1355 V_VT(in_out) = VT_I1;
1356 V_I1(in_out) = 5;
1357 return S_OK;
1360 static SAFEARRAY *make_safearray(ULONG len)
1362 SAFEARRAY *sa = SafeArrayCreateVector(VT_I4, 0, len);
1363 int i, *data;
1365 SafeArrayAccessData(sa, (void **)&data);
1366 for (i = 0; i < len; ++i)
1367 data[i] = len + i;
1368 SafeArrayUnaccessData(sa);
1370 return sa;
1373 static void check_safearray(SAFEARRAY *sa, LONG expect)
1375 LONG len, i, *data;
1376 HRESULT hr;
1378 hr = SafeArrayGetUBound(sa, 1, &len);
1379 len++;
1380 ok(hr == S_OK, "Got hr %#x.\n", hr);
1381 ok(len == expect, "Expected len %d, got %d.\n", expect, len);
1383 hr = SafeArrayAccessData(sa, (void **)&data);
1384 ok(hr == S_OK, "Got hr %#x.\n", hr);
1386 for (i = 0; i < len; ++i)
1387 ok(data[i] == len + i, "Expected data %d at %d, got %d.\n", len + i, i, data[i]);
1389 SafeArrayUnaccessData(sa);
1392 static HRESULT WINAPI Widget_safearray(IWidget *iface, SAFEARRAY *in, SAFEARRAY **out, SAFEARRAY **in_ptr, SAFEARRAY **in_out)
1394 HRESULT hr;
1396 check_safearray(in, 3);
1397 ok(!*out, "Got array %p.\n", *out);
1398 check_safearray(*in_ptr, 7);
1399 check_safearray(*in_out, 9);
1401 hr = SafeArrayDestroy(*in_out);
1402 ok(hr == S_OK, "Got hr %#x.\n", hr);
1404 *out = make_safearray(4);
1405 *in_out = make_safearray(6);
1407 return S_OK;
1410 static HRESULT WINAPI Widget_mystruct(IWidget *iface, MYSTRUCT in, MYSTRUCT *out, MYSTRUCT *in_ptr, MYSTRUCT *in_out)
1412 static const MYSTRUCT empty = {0};
1413 ok(!memcmp(&in, &test_mystruct1, sizeof(in)), "Structs didn't match.\n");
1414 ok(!memcmp(out, &empty, sizeof(*out)), "Structs didn't match.\n");
1415 ok(!memcmp(in_ptr, &test_mystruct3, sizeof(*in_ptr)), "Structs didn't match.\n");
1416 ok(!memcmp(in_out, &test_mystruct4, sizeof(*in_out)), "Structs didn't match.\n");
1418 memcpy(out, &test_mystruct5, sizeof(*out));
1419 memcpy(in_ptr, &test_mystruct6, sizeof(*in_ptr));
1420 memcpy(in_out, &test_mystruct7, sizeof(*in_out));
1421 return S_OK;
1424 static HRESULT WINAPI Widget_mystruct_ptr_ptr(IWidget *iface, MYSTRUCT **in)
1426 ok(!memcmp(*in, &test_mystruct1, sizeof(**in)), "Structs didn't match.\n");
1427 return S_OK;
1430 static HRESULT WINAPI Widget_thin_struct(IWidget *iface, struct thin in)
1432 ok(!memcmp(&in, &test_thin_struct, sizeof(in)), "Structs didn't match.\n");
1433 return S_OK;
1436 static HRESULT WINAPI Widget_rect(IWidget *iface, RECT in, RECT *out, RECT *in_ptr, RECT *in_out)
1438 static const RECT empty = {0};
1439 ok(EqualRect(&in, &test_rect1), "Rects didn't match.\n");
1440 ok(EqualRect(out, &empty), "Rects didn't match.\n");
1441 ok(EqualRect(in_ptr, &test_rect3), "Rects didn't match.\n");
1442 ok(EqualRect(in_out, &test_rect4), "Rects didn't match.\n");
1444 *out = test_rect5;
1445 *in_ptr = test_rect6;
1446 *in_out = test_rect7;
1447 return S_OK;
1450 static HRESULT WINAPI Widget_complex_struct(IWidget *iface, struct complex in)
1452 HRESULT hr;
1454 ok(in.c == 98, "Got char %d.\n", in.c);
1455 ok(in.i == 76543, "Got int %d.\n", in.i);
1456 ok(*in.pi == 2, "Got int pointer %d.\n", *in.pi);
1457 ok(**in.ppi == 10, "Got int double pointer %d.\n", **in.ppi);
1458 hr = ISomethingFromDispatch_anotherfn(in.iface);
1459 ok(hr == 0x01234567, "Got wrong hr %#x.\n", hr);
1460 hr = ISomethingFromDispatch_anotherfn(*in.iface_ptr);
1461 ok(hr == 0x01234567, "Got wrong hr %#x.\n", hr);
1462 ok(!lstrcmpW(in.bstr, test_bstr2), "Got string %s.\n", wine_dbgstr_w(in.bstr));
1463 ok(V_VT(&in.var) == VT_I4, "Got wrong type %u.\n", V_VT(&in.var));
1464 ok(V_I4(&in.var) == 123, "Got wrong value %d.\n", V_I4(&in.var));
1465 ok(!memcmp(&in.mystruct, &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1466 ok(!memcmp(in.arr, test_array1, sizeof(array_t)), "Arrays didn't match.\n");
1467 ok(in.myint == 456, "Got int %d.\n", in.myint);
1469 return S_OK;
1472 static HRESULT WINAPI Widget_array(IWidget *iface, array_t in, array_t out, array_t in_out)
1474 static const array_t empty = {0};
1475 ok(!memcmp(in, test_array1, sizeof(array_t)), "Arrays didn't match.\n");
1476 ok(!memcmp(out, empty, sizeof(array_t)), "Arrays didn't match.\n");
1477 ok(!memcmp(in_out, test_array3, sizeof(array_t)), "Arrays didn't match.\n");
1479 memcpy(in, test_array4, sizeof(array_t));
1480 memcpy(out, test_array5, sizeof(array_t));
1481 memcpy(in_out, test_array6, sizeof(array_t));
1483 return S_OK;
1486 static HRESULT WINAPI Widget_variant_array(IWidget *iface, VARIANT in[2], VARIANT out[2], VARIANT in_out[2])
1488 ok(V_VT(&in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in[0]));
1489 ok(V_I4(&in[0]) == 1, "Got wrong value %d.\n", V_I4(&in[0]));
1490 ok(V_VT(&in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&in[1]));
1491 ok(*V_I4REF(&in[1]) == 2, "Got wrong value %d.\n", *V_I4REF(&in[1]));
1492 ok(V_VT(&out[0]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[0]));
1493 ok(V_VT(&out[1]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[1]));
1494 ok(V_VT(&in_out[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in_out[0]));
1495 ok(V_I4(&in_out[0]) == 5, "Got wrong type %u.\n", V_VT(&in_out[0]));
1496 ok(V_VT(&in_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&in_out[1]));
1497 ok(!lstrcmpW(V_BSTR(&in_out[1]), test_bstr1), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&in[1])));
1499 V_VT(&in[0]) = VT_I1; V_I1(&in[0]) = 7;
1500 V_VT(&in[1]) = VT_I1; V_I1(&in[1]) = 8;
1501 V_VT(&out[0]) = VT_I1; V_I1(&out[0]) = 9;
1502 V_VT(&out[1]) = VT_BSTR; V_BSTR(&out[1]) = SysAllocString(test_bstr2);
1503 V_VT(&in_out[0]) = VT_I1; V_I1(&in_out[0]) = 11;
1504 V_VT(&in_out[1]) = VT_UNKNOWN; V_UNKNOWN(&in_out[1]) = (IUnknown *)create_disp_obj();
1506 return S_OK;
1509 static HRESULT WINAPI Widget_mystruct_array(IWidget *iface, MYSTRUCT in[2])
1511 ok(!memcmp(&in[0], &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1512 ok(!memcmp(&in[1], &test_mystruct2, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1513 return S_OK;
1516 static HRESULT WINAPI Widget_myint(IWidget *iface, myint_t val, myint_t *ptr, myint_t **ptr_ptr)
1518 ok(val == 123, "Got value %d.\n", val);
1519 ok(*ptr == 456, "Got single ptr ref %d.\n", *ptr);
1520 ok(**ptr_ptr == 789, "Got double ptr ref %d.\n", **ptr_ptr);
1521 return S_OK;
1524 static HRESULT WINAPI Widget_Coclass(IWidget *iface, Coclass1 *class1, Coclass2 *class2, Coclass3 *class3)
1526 HRESULT hr;
1528 hr = ICoclass1_test((ICoclass1 *)class1);
1529 ok(hr == 1, "Got hr %#x.\n", hr);
1531 hr = ICoclass2_test((ICoclass2 *)class2);
1532 ok(hr == 2, "Got hr %#x.\n", hr);
1534 hr = ICoclass1_test((ICoclass1 *)class3);
1535 ok(hr == 1, "Got hr %#x.\n", hr);
1537 return S_OK;
1540 static HRESULT WINAPI Widget_Coclass_ptr(IWidget *iface, Coclass1 **in, Coclass1 **out, Coclass1 **in_out)
1542 struct coclass_obj *obj;
1543 HRESULT hr;
1545 ok(!*out, "Got [out] %p.\n", *out);
1546 if (testmode == 0 || testmode == 1)
1548 hr = ICoclass1_test((ICoclass1 *)*in);
1549 ok(hr == 1, "Got hr %#x.\n", hr);
1550 hr = ICoclass1_test((ICoclass1 *)*in_out);
1551 ok(hr == 1, "Got hr %#x.\n", hr);
1554 if (testmode == 1)
1556 obj = create_coclass_obj();
1557 *out = (Coclass1 *)&obj->ICoclass1_iface;
1559 ICoclass1_Release((ICoclass1 *)*in_out);
1560 obj = create_coclass_obj();
1561 *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1563 else if (testmode == 2)
1565 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1566 obj = create_coclass_obj();
1567 *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1569 else if (testmode == 3)
1571 hr = ICoclass1_test((ICoclass1 *)*in_out);
1572 ok(hr == 1, "Got hr %#x.\n", hr);
1573 ICoclass1_Release((ICoclass1 *)*in_out);
1574 *in_out = NULL;
1577 return S_OK;
1580 static HRESULT WINAPI Widget_Coclass_noptr(IWidget *iface, Coclass1 class1, Coclass2 class2, Coclass3 class3)
1582 HRESULT hr;
1584 hr = ICoclass1_test(class1.iface);
1585 ok(hr == 1, "Got hr %#x.\n", hr);
1587 hr = ICoclass2_test(class2.iface);
1588 ok(hr == 2, "Got hr %#x.\n", hr);
1590 hr = ICoclass1_test(class3.iface);
1591 ok(hr == 1, "Got hr %#x.\n", hr);
1593 return S_OK;
1596 static HRESULT WINAPI Widget_no_in_out(IWidget *iface, BSTR str, int i)
1598 ok(SysStringLen(str) == 4, "unexpected len\n");
1599 ok(!lstrcmpW(str, L"test"), "unexpected str %s\n", wine_dbgstr_w(str));
1600 ok(i == 5, "i = %d\n", i);
1601 return S_OK;
1604 static const struct IWidgetVtbl Widget_VTable =
1606 Widget_QueryInterface,
1607 Widget_AddRef,
1608 Widget_Release,
1609 Widget_GetTypeInfoCount,
1610 Widget_GetTypeInfo,
1611 Widget_GetIDsOfNames,
1612 Widget_Invoke,
1613 Widget_put_Name,
1614 Widget_get_Name,
1615 Widget_DoSomething,
1616 Widget_get_State,
1617 Widget_put_State,
1618 Widget_Map,
1619 Widget_SetOleColor,
1620 Widget_GetOleColor,
1621 Widget_Clone,
1622 Widget_CloneDispatch,
1623 Widget_CloneCoclass,
1624 Widget_Value,
1625 Widget_VariantArrayPtr,
1626 Widget_VarArg,
1627 Widget_Error,
1628 Widget_CloneInterface,
1629 Widget_put_prop_with_lcid,
1630 Widget_get_prop_with_lcid,
1631 Widget_get_prop_int,
1632 Widget_get_prop_uint,
1633 Widget_ByRefUInt,
1634 Widget_put_prop_opt_arg,
1635 Widget_put_prop_req_arg,
1636 Widget_pos_restrict,
1637 Widget_neg_restrict,
1638 Widget_VarArg_Run,
1639 Widget_VarArg_Ref_Run,
1640 Widget_basetypes_in,
1641 Widget_basetypes_out,
1642 Widget_float_abi,
1643 Widget_int_ptr,
1644 Widget_int_ptr_ptr,
1645 Widget_iface_in,
1646 Widget_iface_out,
1647 Widget_iface_ptr,
1648 Widget_iface_noptr,
1649 Widget_bstr,
1650 Widget_variant,
1651 Widget_safearray,
1652 Widget_mystruct,
1653 Widget_mystruct_ptr_ptr,
1654 Widget_thin_struct,
1655 Widget_rect,
1656 Widget_complex_struct,
1657 Widget_array,
1658 Widget_variant_array,
1659 Widget_mystruct_array,
1660 Widget_myint,
1661 Widget_Coclass,
1662 Widget_Coclass_ptr,
1663 Widget_Coclass_noptr,
1664 Widget_no_in_out,
1667 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
1669 if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
1671 IStaticWidget_AddRef(iface);
1672 *ppvObject = iface;
1673 return S_OK;
1676 *ppvObject = NULL;
1677 return E_NOINTERFACE;
1680 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
1682 return 2;
1685 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
1687 return 1;
1690 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
1692 ok(0, "unexpected call\n");
1693 return E_NOTIMPL;
1696 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
1697 ITypeInfo **ppTInfo)
1699 ok(0, "unexpected call\n");
1700 return E_NOTIMPL;
1703 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
1704 UINT cNames, LCID lcid, DISPID *rgDispId)
1706 ok(0, "unexpected call\n");
1707 return E_NOTIMPL;
1710 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
1711 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1712 UINT *puArgErr)
1714 ok(0, "unexpected call\n");
1715 return E_NOTIMPL;
1718 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
1720 trace("TestDual()\n");
1721 ok(p == &TestDual, "wrong ItestDual\n");
1722 return S_OK;
1725 static HRESULT WINAPI StaticWidget_TestSecondIface(IStaticWidget *iface, ITestSecondIface *p)
1727 trace("TestSecondIface()\n");
1728 ok(p == &TestSecondIface, "wrong ItestSecondIface\n");
1729 return S_OK;
1732 static const IStaticWidgetVtbl StaticWidgetVtbl = {
1733 StaticWidget_QueryInterface,
1734 StaticWidget_AddRef,
1735 StaticWidget_Release,
1736 StaticWidget_GetTypeInfoCount,
1737 StaticWidget_GetTypeInfo,
1738 StaticWidget_GetIDsOfNames,
1739 StaticWidget_Invoke,
1740 StaticWidget_TestDual,
1741 StaticWidget_TestSecondIface
1744 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
1746 typedef struct KindaEnum
1748 IKindaEnumWidget IKindaEnumWidget_iface;
1749 LONG refs;
1750 } KindaEnum;
1752 static inline KindaEnum *impl_from_IKindaEnumWidget(IKindaEnumWidget *iface)
1754 return CONTAINING_RECORD(iface, KindaEnum, IKindaEnumWidget_iface);
1757 static HRESULT register_current_module_typelib(void)
1759 WCHAR path[MAX_PATH];
1760 CHAR pathA[MAX_PATH];
1761 HRESULT hr;
1762 ITypeLib *typelib;
1764 GetModuleFileNameA(NULL, pathA, MAX_PATH);
1765 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
1767 hr = LoadTypeLib(path, &typelib);
1768 if (SUCCEEDED(hr))
1770 hr = RegisterTypeLib(typelib, path, NULL);
1771 ITypeLib_Release(typelib);
1773 return hr;
1776 static ITypeInfo *get_type_info(REFIID riid)
1778 ITypeInfo *pTypeInfo;
1779 ITypeLib *pTypeLib;
1780 HRESULT hr;
1782 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1783 ok_ole_success(hr, LoadRegTypeLib);
1784 if (FAILED(hr))
1785 return NULL;
1787 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
1788 ITypeLib_Release(pTypeLib);
1789 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1790 if (FAILED(hr))
1791 return NULL;
1793 return pTypeInfo;
1796 static IWidget *Widget_Create(void)
1798 Widget *This;
1799 ITypeInfo *pTypeInfo;
1800 HRESULT hr = E_FAIL;
1802 pTypeInfo = get_type_info(&IID_IWidget);
1803 if(!pTypeInfo)
1804 return NULL;
1806 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1807 This->IWidget_iface.lpVtbl = &Widget_VTable;
1808 This->refs = 1;
1809 This->pDispatchUnknown = NULL;
1811 hr = CreateStdDispatch((IUnknown *)&This->IWidget_iface, This, pTypeInfo,
1812 &This->pDispatchUnknown);
1813 ok_ole_success(hr, CreateStdDispatch);
1814 ITypeInfo_Release(pTypeInfo);
1816 if (SUCCEEDED(hr))
1817 return &This->IWidget_iface;
1818 else
1820 HeapFree(GetProcessHeap(), 0, This);
1821 return NULL;
1825 static HRESULT WINAPI KindaEnum_QueryInterface(
1826 IKindaEnumWidget *iface,
1827 /* [in] */ REFIID riid,
1828 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
1830 if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
1832 IKindaEnumWidget_AddRef(iface);
1833 *ppvObject = iface;
1834 return S_OK;
1836 else
1838 *ppvObject = NULL;
1839 return E_NOINTERFACE;
1843 static ULONG WINAPI KindaEnum_AddRef(
1844 IKindaEnumWidget *iface)
1846 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1848 return InterlockedIncrement(&This->refs);
1851 static ULONG WINAPI KindaEnum_Release(
1852 IKindaEnumWidget *iface)
1854 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1855 ULONG refs = InterlockedDecrement(&This->refs);
1856 if (!refs)
1858 memset(This, 0xcc, sizeof(*This));
1859 HeapFree(GetProcessHeap(), 0, This);
1860 trace("KindaEnumWidget destroyed!\n");
1863 return refs;
1866 static HRESULT WINAPI KindaEnum_Next(
1867 IKindaEnumWidget *iface,
1868 /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
1870 *widget = Widget_Create();
1871 if (*widget)
1872 return S_OK;
1873 else
1874 return E_OUTOFMEMORY;
1877 static HRESULT WINAPI KindaEnum_Count(
1878 IKindaEnumWidget *iface,
1879 /* [out] */ ULONG __RPC_FAR *count)
1881 return E_NOTIMPL;
1884 static HRESULT WINAPI KindaEnum_Reset(
1885 IKindaEnumWidget *iface)
1887 return E_NOTIMPL;
1890 static HRESULT WINAPI KindaEnum_Clone(
1891 IKindaEnumWidget *iface,
1892 /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
1894 return E_NOTIMPL;
1897 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
1899 KindaEnum_QueryInterface,
1900 KindaEnum_AddRef,
1901 KindaEnum_Release,
1902 KindaEnum_Next,
1903 KindaEnum_Count,
1904 KindaEnum_Reset,
1905 KindaEnum_Clone
1908 static IKindaEnumWidget *KindaEnumWidget_Create(void)
1910 KindaEnum *This;
1912 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1913 if (!This) return NULL;
1914 This->IKindaEnumWidget_iface.lpVtbl = &KindaEnumWidget_VTable;
1915 This->refs = 1;
1916 return &This->IKindaEnumWidget_iface;
1919 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
1921 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
1923 *(INonOleAutomation **)ppv = iface;
1924 return S_OK;
1926 *ppv = NULL;
1927 return E_NOINTERFACE;
1930 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
1932 return 2;
1935 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
1937 return 1;
1940 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
1942 static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1943 return SysAllocString(wszTestString);
1946 static HRESULT WINAPI NonOleAutomation_Error(INonOleAutomation *iface)
1948 return E_NOTIMPL;
1951 static INonOleAutomationVtbl NonOleAutomation_VTable =
1953 NonOleAutomation_QueryInterface,
1954 NonOleAutomation_AddRef,
1955 NonOleAutomation_Release,
1956 NonOleAutomation_BstrRet,
1957 NonOleAutomation_Error
1960 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
1962 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
1964 ITypeLib *pTypeLib;
1965 HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1966 ok_ole_success(hr, LoadRegTypeLib);
1967 if (SUCCEEDED(hr))
1969 ITypeInfo *pTypeInfo;
1970 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
1971 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1972 ITypeLib_Release(pTypeLib);
1973 return pTypeInfo;
1975 return NULL;
1978 static void test_marshal_basetypes(IWidget *widget, IDispatch *disp)
1980 VARIANTARG arg[11];
1981 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
1982 HRESULT hr;
1984 signed char c;
1985 short s;
1986 int i, i2, *pi;
1987 hyper h;
1988 unsigned char uc;
1989 unsigned short us;
1990 unsigned int ui;
1991 MIDL_uhyper uh;
1992 float f;
1993 double d;
1994 STATE st;
1996 V_VT(&arg[10]) = VT_I1; V_I1(&arg[10]) = 5;
1997 V_VT(&arg[9]) = VT_I2; V_I2(&arg[9]) = -123;
1998 V_VT(&arg[8]) = VT_I4; V_I4(&arg[8]) = -100000;
1999 V_VT(&arg[7]) = VT_I8; V_I8(&arg[7]) = (LONGLONG)-100000 * 1000000;
2000 V_VT(&arg[6]) = VT_UI1; V_UI1(&arg[6]) = 0;
2001 V_VT(&arg[5]) = VT_UI2; V_UI2(&arg[5]) = 456;
2002 V_VT(&arg[4]) = VT_UI4; V_UI4(&arg[4]) = 0xdeadbeef;
2003 V_VT(&arg[3]) = VT_UI8; V_UI8(&arg[3]) = (ULONGLONG)1234567890 * 9876543210;
2004 V_VT(&arg[2]) = VT_R4; V_R4(&arg[2]) = M_PI;
2005 V_VT(&arg[1]) = VT_R8; V_R8(&arg[1]) = M_E;
2006 V_VT(&arg[0]) = VT_I4; V_I4(&arg[0]) = STATE_WIDGETIFIED;
2007 hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_IN, &IID_NULL, LOCALE_NEUTRAL,
2008 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2009 ok(hr == S_OK, "Got hr %#x.\n", hr);
2011 hr = IWidget_basetypes_in(widget, 5, -123, -100000, (LONGLONG)-100000 * 1000000, 0, 456,
2012 0xdeadbeef, (ULONGLONG)1234567890 * 9876543210, M_PI, M_E, STATE_WIDGETIFIED);
2013 ok(hr == S_OK, "Got hr %#x.\n", hr);
2015 c = s = i = h = uc = us = ui = uh = f = d = st = 0;
2017 V_VT(&arg[10]) = VT_BYREF|VT_I1; V_I1REF(&arg[10]) = &c;
2018 V_VT(&arg[9]) = VT_BYREF|VT_I2; V_I2REF(&arg[9]) = &s;
2019 V_VT(&arg[8]) = VT_BYREF|VT_I4; V_I4REF(&arg[8]) = &i;
2020 V_VT(&arg[7]) = VT_BYREF|VT_I8; V_I8REF(&arg[7]) = &h;
2021 V_VT(&arg[6]) = VT_BYREF|VT_UI1; V_UI1REF(&arg[6]) = &uc;
2022 V_VT(&arg[5]) = VT_BYREF|VT_UI2; V_UI2REF(&arg[5]) = &us;
2023 V_VT(&arg[4]) = VT_BYREF|VT_UI4; V_UI4REF(&arg[4]) = &ui;
2024 V_VT(&arg[3]) = VT_BYREF|VT_UI8; V_UI8REF(&arg[3]) = &uh;
2025 V_VT(&arg[2]) = VT_BYREF|VT_R4; V_R4REF(&arg[2]) = &f;
2026 V_VT(&arg[1]) = VT_BYREF|VT_R8; V_R8REF(&arg[1]) = &d;
2027 V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = (int *)&st;
2028 hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_OUT, &IID_NULL, LOCALE_NEUTRAL,
2029 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2030 ok(hr == S_OK, "Got hr %#x.\n", hr);
2031 ok(c == 10, "Got char %d.\n", c);
2032 ok(s == -321, "Got short %d.\n", s);
2033 ok(i == -200000, "Got int %d.\n", i);
2034 ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
2035 ok(uc == 254, "Got unsigned char %u.\n", uc);
2036 ok(us == 256, "Got unsigned short %u.\n", us);
2037 ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui);
2038 ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789),
2039 "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
2040 ok(f == (float)M_LN2, "Got float %f.\n", f);
2041 ok(d == M_LN10, "Got double %f.\n", d);
2042 ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
2044 c = s = i = h = uc = us = ui = uh = f = d = st = 0;
2046 hr = IWidget_basetypes_out(widget, &c, &s, &i, &h, &uc, &us, &ui, &uh, &f, &d, &st);
2047 ok(hr == S_OK, "Got hr %#x.\n", hr);
2048 ok(c == 10, "Got char %d.\n", c);
2049 ok(s == -321, "Got short %d.\n", s);
2050 ok(i == -200000, "Got int %d.\n", i);
2051 ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
2052 ok(uc == 254, "Got unsigned char %u.\n", uc);
2053 ok(us == 256, "Got unsigned short %u.\n", us);
2054 ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui);
2055 ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789),
2056 "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
2057 ok(f == (float)M_LN2, "Got float %f.\n", f);
2058 ok(d == M_LN10, "Got double %f.\n", d);
2059 ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
2061 /* Test marshalling of public typedefs. */
2063 i = 456;
2064 i2 = 789;
2065 pi = &i2;
2066 hr = IWidget_myint(widget, 123, &i, &pi);
2067 ok(hr == S_OK, "Got hr %#x.\n", hr);
2069 /* Test that different float ABIs are correctly handled. */
2071 hr = IWidget_float_abi(widget, 1.0f, 2.0, 3, 4.0f, 5.0);
2072 ok(hr == S_OK, "Got hr %#x.\n", hr);
2075 static void test_marshal_pointer(IWidget *widget, IDispatch *disp)
2077 VARIANTARG arg[3];
2078 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2079 int in, out, in_out, *in_ptr, *out_ptr, *in_out_ptr;
2080 HRESULT hr;
2082 testmode = 0;
2084 in = 123;
2085 out = 456;
2086 in_out = 789;
2087 V_VT(&arg[2]) = VT_BYREF|VT_I4; V_I4REF(&arg[2]) = &in;
2088 V_VT(&arg[1]) = VT_BYREF|VT_I4; V_I4REF(&arg[1]) = &out;
2089 V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = &in_out;
2090 hr = IDispatch_Invoke(disp, DISPID_TM_INT_PTR, &IID_NULL, LOCALE_NEUTRAL,
2091 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2092 ok(hr == S_OK, "Got hr %#x.\n", hr);
2093 ok(in == 987, "Got [in] %d.\n", in);
2094 ok(out == 654, "Got [out] %d.\n", out);
2095 ok(in_out == 321, "Got [in, out] %d.\n", in_out);
2097 testmode = 1;
2099 in = 123;
2100 out = 456;
2101 in_out = 789;
2102 hr = IWidget_int_ptr(widget, &in, &out, &in_out);
2103 ok(hr == S_OK, "Got hr %#x.\n", hr);
2104 ok(in == 123, "Got [in] %d.\n", in);
2105 ok(out == 654, "Got [out] %d.\n", out);
2106 ok(in_out == 321, "Got [in, out] %d.\n", in_out);
2108 out = in_out = -1;
2109 hr = IWidget_int_ptr(widget, NULL, &out, &in_out);
2110 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2111 ok(!out, "[out] parameter should have been cleared.\n");
2112 ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2114 in = in_out = -1;
2115 hr = IWidget_int_ptr(widget, &in, NULL, &in_out);
2116 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2117 ok(in == -1, "[in] parameter should not have been cleared.\n");
2118 ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2120 in = out = -1;
2121 hr = IWidget_int_ptr(widget, &in, &out, NULL);
2122 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2123 ok(in == -1, "[in] parameter should not have been cleared.\n");
2124 ok(!out, "[out] parameter should have been cleared.\n");
2126 /* We can't test Invoke() with double pointers, as it is not possible to fit
2127 * more than one level of indirection into a VARIANTARG. */
2129 testmode = 0;
2130 in_ptr = out_ptr = in_out_ptr = NULL;
2131 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2132 ok(hr == S_OK, "Got hr %#x\n", hr);
2133 ok(!in_ptr, "Got [in] %p.\n", in_ptr);
2134 ok(!out_ptr, "Got [out] %p.\n", out_ptr);
2135 ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2137 testmode = 1;
2138 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2139 ok(hr == S_OK, "Got hr %#x\n", hr);
2140 ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr);
2141 ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr);
2142 CoTaskMemFree(out_ptr);
2143 CoTaskMemFree(in_out_ptr);
2145 testmode = 2;
2146 in = 123;
2147 out = 456;
2148 in_out = 789;
2149 in_ptr = &in;
2150 out_ptr = &out;
2151 in_out_ptr = &in_out;
2152 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2153 ok(hr == S_OK, "Got hr %#x.\n", hr);
2154 ok(out_ptr != &out, "[out] ptr should have changed.\n");
2155 ok(in_out_ptr == &in_out, "[in, out] ptr should not have changed.\n");
2156 ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr);
2157 ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr);
2159 testmode = 3;
2160 in_ptr = out_ptr = NULL;
2161 in_out = 789;
2162 in_out_ptr = &in_out;
2163 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2164 ok(hr == S_OK, "Got hr %#x.\n", hr);
2165 ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2167 out_ptr = &out;
2168 in_out_ptr = &in_out;
2169 hr = IWidget_int_ptr_ptr(widget, NULL, &out_ptr, &in_out_ptr);
2170 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2171 ok(!out_ptr, "[out] parameter should have been cleared.\n");
2172 ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2174 in_ptr = &in;
2175 in_out_ptr = &in_out;
2176 hr = IWidget_int_ptr_ptr(widget, &in_ptr, NULL, &in_out_ptr);
2177 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2178 ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2179 ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2181 in_ptr = &in;
2182 out_ptr = &out;
2183 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, NULL);
2184 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2185 ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2186 ok(!out_ptr, "[out] parameter should have been cleared.\n");
2189 static void test_marshal_iface(IWidget *widget, IDispatch *disp)
2191 VARIANTARG arg[3];
2192 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2193 ISomethingFromDispatch *sfd1, *sfd2, *sfd3, *proxy_sfd, *sfd_in, *sfd_out, *sfd_in_out;
2194 IUnknown *proxy_unk, *proxy_unk2, *unk_in, *unk_out, *unk_in_out;
2195 IDispatch *proxy_disp;
2196 IUnknown unk_noptr;
2197 IDispatch disp_noptr;
2198 ISomethingFromDispatch sfd_noptr;
2199 HRESULT hr;
2201 testmode = 0;
2202 sfd1 = create_disp_obj();
2203 sfd2 = create_disp_obj();
2204 sfd3 = create_disp_obj();
2205 hr = IWidget_iface_in(widget, (IUnknown *)sfd1,
2206 (IDispatch *)sfd2, sfd3);
2207 ok(hr == S_OK, "Got hr %#x.\n", hr);
2208 release_iface(sfd1);
2209 release_iface(sfd2);
2210 release_iface(sfd3);
2212 testmode = 1;
2213 hr = IWidget_iface_in(widget, NULL, NULL, NULL);
2214 ok(hr == S_OK, "Got hr %#x.\n", hr);
2216 testmode = 0;
2217 proxy_unk = (IUnknown *)0xdeadbeef;
2218 proxy_disp = (IDispatch *)0xdeadbeef;
2219 proxy_sfd = (ISomethingFromDispatch *)0xdeadbeef;
2220 hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2221 ok(hr == S_OK, "Got hr %#x.\n", hr);
2222 check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2223 release_iface(proxy_unk);
2224 release_iface(proxy_disp);
2225 release_iface(proxy_sfd);
2227 testmode = 1;
2228 hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2229 ok(hr == S_OK, "Got hr %#x.\n", hr);
2230 ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2231 ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2232 ok(!proxy_sfd, "Got unexpected proxy %p.\n", proxy_sfd);
2234 testmode = 0;
2235 sfd_in = sfd1 = create_disp_obj();
2236 sfd_out = sfd2 = create_disp_obj();
2237 sfd_in_out = sfd3 = create_disp_obj();
2238 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2239 ok(hr == S_OK, "Got hr %#x.\n", hr);
2240 ok(sfd_in == sfd1, "[in] parameter should not have changed.\n");
2241 ok(!sfd_out, "[out] parameter should have been cleared.\n");
2242 ok(sfd_in_out == sfd3, "[in, out] parameter should not have changed.\n");
2243 release_iface(sfd1);
2244 release_iface(sfd2);
2245 release_iface(sfd3);
2247 testmode = 1;
2248 sfd_in = sfd1 = create_disp_obj();
2249 sfd_in_out = sfd3 = create_disp_obj();
2250 ISomethingFromDispatch_AddRef(sfd_in_out);
2251 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2252 ok(hr == S_OK, "Got hr %#x.\n", hr);
2253 hr = ISomethingFromDispatch_anotherfn(sfd_out);
2254 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2255 ok(sfd_in_out != sfd3, "[in, out] parameter should have changed.\n");
2256 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2257 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2258 release_iface(sfd_out);
2259 release_iface(sfd_in_out);
2260 release_iface(sfd1);
2261 release_iface(sfd3);
2263 testmode = 2;
2264 sfd_in = sfd_out = sfd_in_out = NULL;
2265 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2266 ok(hr == S_OK, "Got hr %#x.\n", hr);
2267 ok(!sfd_out, "[out] parameter should not have been set.\n");
2268 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2269 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2270 release_iface(sfd_in_out);
2272 testmode = 3;
2273 sfd_in = sfd_out = NULL;
2274 sfd_in_out = sfd3 = create_disp_obj();
2275 ISomethingFromDispatch_AddRef(sfd_in_out);
2276 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2277 ok(hr == S_OK, "Got hr %#x.\n", hr);
2278 ok(!sfd_in_out, "Got [in, out] %p.\n", sfd_in_out);
2279 release_iface(sfd3);
2281 sfd1 = create_disp_obj();
2282 sfd2 = create_disp_obj();
2283 sfd3 = create_disp_obj();
2284 unk_noptr.lpVtbl = (IUnknownVtbl *)sfd1;
2285 disp_noptr.lpVtbl = (IDispatchVtbl *)sfd2;
2286 sfd_noptr.lpVtbl = (ISomethingFromDispatchVtbl *)sfd3;
2287 hr = IWidget_iface_noptr(widget, unk_noptr, disp_noptr, sfd_noptr);
2288 ok(hr == S_OK, "Got hr %#x.\n", hr);
2289 release_iface(sfd1);
2290 release_iface(sfd2);
2291 release_iface(sfd3);
2293 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2294 * interface back, but rather an IUnknown. */
2296 testmode = 0;
2297 sfd1 = create_disp_obj();
2298 sfd2 = create_disp_obj();
2299 sfd3 = create_disp_obj();
2301 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)sfd1;
2302 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)sfd2;
2303 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)sfd3;
2304 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2305 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2306 ok(hr == S_OK, "Got hr %#x.\n", hr);
2308 V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)sfd1;
2309 V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)sfd2;
2310 V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)sfd3;
2311 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2312 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2313 ok(hr == S_OK, "Got hr %#x.\n", hr);
2315 release_iface(sfd1);
2316 release_iface(sfd2);
2317 release_iface(sfd3);
2319 testmode = 1;
2320 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = NULL;
2321 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = NULL;
2322 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = NULL;
2323 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2324 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2325 ok(hr == S_OK, "Got hr %#x.\n", hr);
2327 testmode = 0;
2328 proxy_unk = proxy_unk2 = NULL;
2329 proxy_disp = NULL;
2330 V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &proxy_unk;
2331 V_VT(&arg[1]) = VT_DISPATCH|VT_BYREF; V_DISPATCHREF(&arg[1]) = &proxy_disp;
2332 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &proxy_unk2;
2333 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2334 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2335 todo_wine
2336 ok(hr == S_OK, "Got hr %#x.\n", hr);
2337 if (hr == S_OK) {
2338 hr = IUnknown_QueryInterface(proxy_unk2, &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
2339 ok(hr == S_OK, "Got hr %#x.\n", hr);
2340 check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2341 ISomethingFromDispatch_Release(proxy_sfd);
2342 release_iface(proxy_unk);
2343 release_iface(proxy_disp);
2344 release_iface(proxy_unk2);
2347 testmode = 1;
2348 proxy_unk = proxy_unk2 = NULL;
2349 proxy_disp = NULL;
2350 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2351 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2352 todo_wine
2353 ok(hr == S_OK, "Got hr %#x.\n", hr);
2354 ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2355 ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2356 ok(!proxy_unk2, "Got unexpected proxy %p.\n", proxy_unk2);
2358 testmode = 0;
2359 sfd1 = create_disp_obj();
2360 sfd3 = create_disp_obj();
2361 unk_in = (IUnknown *)sfd1;
2362 unk_out = NULL;
2363 unk_in_out = (IUnknown *)sfd3;
2364 V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &unk_in;
2365 V_VT(&arg[1]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[1]) = &unk_out;
2366 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2367 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2368 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2369 todo_wine
2370 ok(hr == S_OK, "Got hr %#x.\n", hr);
2371 ok(unk_in == (IUnknown *)sfd1, "[in] parameter should not have changed.\n");
2372 ok(!unk_out, "[out] parameter should have been cleared.\n");
2373 ok(unk_in_out == (IUnknown *)sfd3, "[in, out] parameter should not have changed.\n");
2374 release_iface(sfd1);
2375 release_iface(sfd3);
2377 testmode = 1;
2378 sfd1 = create_disp_obj();
2379 sfd3 = create_disp_obj();
2380 unk_in = (IUnknown *)sfd1;
2381 unk_out = NULL;
2382 unk_in_out = (IUnknown *)sfd3;
2383 IUnknown_AddRef(unk_in_out);
2384 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2385 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2386 todo_wine
2387 ok(hr == S_OK, "Got hr %#x.\n", hr);
2389 if (hr == S_OK) {
2390 hr = IUnknown_QueryInterface(unk_out, &IID_ISomethingFromDispatch, (void **)&sfd_out);
2391 ok(hr == S_OK, "Got hr %#x.\n", hr);
2392 hr = ISomethingFromDispatch_anotherfn(sfd_out);
2393 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2394 ISomethingFromDispatch_Release(sfd_out);
2396 ok(unk_in_out != (IUnknown *)sfd3, "[in, out] parameter should have changed.\n");
2397 hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2398 ok(hr == S_OK, "Got hr %#x.\n", hr);
2399 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2400 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2401 ISomethingFromDispatch_Release(sfd_in_out);
2403 release_iface(unk_out);
2404 release_iface(unk_in_out);
2406 release_iface(sfd1);
2407 todo_wine
2408 release_iface(sfd3);
2410 testmode = 2;
2411 unk_in = unk_out = unk_in_out = NULL;
2412 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2413 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2414 todo_wine
2415 ok(hr == S_OK, "Got hr %#x.\n", hr);
2417 ok(!unk_out, "[out] parameter should not have been set.\n");
2418 if (hr == S_OK) {
2419 hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2420 ok(hr == S_OK, "Got hr %#x.\n", hr);
2421 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2422 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2423 ISomethingFromDispatch_Release(sfd_in_out);
2425 release_iface(unk_in_out);
2428 testmode = 3;
2429 unk_in = unk_out = NULL;
2430 sfd3 = create_disp_obj();
2431 unk_in_out = (IUnknown *)sfd3;
2432 IUnknown_AddRef(unk_in_out);
2433 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2434 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2435 todo_wine {
2436 ok(hr == S_OK, "Got hr %#x.\n", hr);
2437 ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2438 release_iface(sfd3);
2442 static void test_marshal_bstr(IWidget *widget, IDispatch *disp)
2444 VARIANTARG arg[4];
2445 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2446 BSTR in, out, in_ptr, in_out;
2447 HRESULT hr;
2448 UINT len;
2450 testmode = 0;
2451 in = SysAllocStringLen(test_bstr1, ARRAY_SIZE(test_bstr1));
2452 out = NULL;
2453 in_ptr = SysAllocString(test_bstr2);
2454 in_out = SysAllocString(test_bstr3);
2456 V_VT(&arg[3]) = VT_BSTR; V_BSTR(&arg[3]) = in;
2457 V_VT(&arg[2]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[2]) = &out;
2458 V_VT(&arg[1]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[1]) = &in_ptr;
2459 V_VT(&arg[0]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[0]) = &in_out;
2460 hr = IDispatch_Invoke(disp, DISPID_TM_BSTR, &IID_NULL, LOCALE_NEUTRAL,
2461 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2462 ok(hr == S_OK, "Got hr %#x.\n", hr);
2463 ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2464 ok(in_ptr[1] == 'X', "[in] pointer should be changed.\n");
2465 ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2466 len = SysStringLen(out);
2467 ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2468 ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2470 in[1] = test_bstr1[1];
2471 in_ptr[1] = test_bstr2[1];
2472 in_out[1] = test_bstr3[1];
2473 SysFreeString(out);
2474 out = (BSTR)0xdeadbeef;
2475 hr = IWidget_bstr(widget, in, &out, &in_ptr, &in_out);
2476 ok(hr == S_OK, "Got hr %#x.\n", hr);
2477 ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2478 ok(in_ptr[1] == test_bstr2[1], "[in] pointer should not be changed.\n");
2479 ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2480 len = SysStringLen(out);
2481 ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2482 ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2483 SysFreeString(in);
2484 SysFreeString(out);
2485 SysFreeString(in_ptr);
2486 SysFreeString(in_out);
2488 testmode = 1;
2489 out = in_ptr = in_out = NULL;
2490 hr = IWidget_bstr(widget, NULL, &out, &in_ptr, &in_out);
2491 ok(hr == S_OK, "Got hr %#x.\n", hr);
2493 in = SysAllocString(L"test");
2494 hr = IWidget_no_in_out(widget, in, 5);
2495 ok(hr == S_OK, "Got hr %#x.\n", hr);
2498 static void test_marshal_variant(IWidget *widget, IDispatch *disp)
2500 VARIANTARG arg[4];
2501 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2502 VARIANT out, in_ptr, in_out;
2503 HRESULT hr;
2504 BSTR bstr;
2506 testmode = 0;
2507 V_VT(&out) = VT_I4;
2508 V_I4(&out) = 1;
2509 V_VT(&in_ptr) = VT_I4;
2510 V_I4(&in_ptr) = -1;
2511 V_VT(&in_out) = VT_BSTR;
2512 V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2514 V_VT(&arg[3]) = VT_CY;
2515 V_CY(&arg[3]).Hi = 0xdababe;
2516 V_CY(&arg[3]).Lo = 0xdeadbeef;
2517 V_VT(&arg[2]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[2]) = &out;
2518 V_VT(&arg[1]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[1]) = &in_ptr;
2519 V_VT(&arg[0]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[0]) = &in_out;
2520 hr = IDispatch_Invoke(disp, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL,
2521 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2522 ok(hr == S_OK, "Got hr %#x.\n", hr);
2523 ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2524 ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2525 ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2526 VariantClear(&out);
2527 ok(V_VT(&in_ptr) == VT_I2, "Got wrong type %u.\n", V_VT(&in_ptr));
2528 ok(V_I2(&in_ptr) == 4, "Got wrong value %d.\n", V_I1(&in_ptr));
2529 ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2530 ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2532 testmode = 1;
2533 V_VT(&out) = VT_I4;
2534 V_I4(&out) = 1;
2535 V_VT(&in_ptr) = VT_I4;
2536 V_I4(&in_ptr) = -1;
2537 V_VT(&in_out) = VT_BSTR;
2538 V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2539 hr = IWidget_variant(widget, arg[3], &out, &in_ptr, &in_out);
2540 ok(hr == S_OK, "Got hr %#x.\n", hr);
2541 ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2542 ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2543 ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2544 ok(V_VT(&in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(&in_ptr));
2545 ok(V_I2(&in_ptr) == -1, "Got wrong value %d.\n", V_I1(&in_ptr));
2546 ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2547 ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2550 static void test_marshal_safearray(IWidget *widget, IDispatch *disp)
2552 SAFEARRAY *in, *out, *out2, *in_ptr, *in_out;
2553 HRESULT hr;
2555 in = make_safearray(3);
2556 out = out2 = make_safearray(5);
2557 in_ptr = make_safearray(7);
2558 in_out = make_safearray(9);
2559 hr = IWidget_safearray(widget, in, &out, &in_ptr, &in_out);
2560 ok(hr == S_OK, "Got hr %#x.\n", hr);
2561 check_safearray(in, 3);
2562 check_safearray(out, 4);
2563 check_safearray(out2, 5);
2564 check_safearray(in_ptr, 7);
2565 check_safearray(in_out, 6);
2567 SafeArrayDestroy(in);
2568 SafeArrayDestroy(out);
2569 SafeArrayDestroy(out2);
2570 SafeArrayDestroy(in_ptr);
2571 SafeArrayDestroy(in_out);
2574 static void test_marshal_struct(IWidget *widget, IDispatch *disp)
2576 MYSTRUCT out, in_ptr, in_out, *in_ptr_ptr;
2577 RECT rect_out, rect_in_ptr, rect_in_out;
2578 ISomethingFromDispatch *sfd;
2579 struct complex complex;
2580 int i, i2, *pi = &i2;
2581 HRESULT hr;
2583 memcpy(&out, &test_mystruct2, sizeof(MYSTRUCT));
2584 memcpy(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT));
2585 memcpy(&in_out, &test_mystruct4, sizeof(MYSTRUCT));
2586 hr = IWidget_mystruct(widget, test_mystruct1, &out, &in_ptr, &in_out);
2587 ok(hr == S_OK, "Got hr %#x.\n", hr);
2588 ok(!memcmp(&out, &test_mystruct5, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2589 ok(!memcmp(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2590 ok(!memcmp(&in_out, &test_mystruct7, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2592 memcpy(&in_ptr, &test_mystruct1, sizeof(MYSTRUCT));
2593 in_ptr_ptr = &in_ptr;
2594 hr = IWidget_mystruct_ptr_ptr(widget, &in_ptr_ptr);
2595 ok(hr == S_OK, "Got hr %#x.\n", hr);
2597 /* Make sure that "thin" structs (<=8 bytes) are handled correctly in x86-64. */
2599 hr = IWidget_thin_struct(widget, test_thin_struct);
2600 ok(hr == S_OK, "Got hr %#x.\n", hr);
2602 /* Make sure we can handle an imported type. */
2604 rect_out = test_rect2;
2605 rect_in_ptr = test_rect3;
2606 rect_in_out = test_rect4;
2607 hr = IWidget_rect(widget, test_rect1, &rect_out, &rect_in_ptr, &rect_in_out);
2608 ok(hr == S_OK, "Got hr %#x.\n", hr);
2609 ok(EqualRect(&rect_out, &test_rect5), "Rects didn't match.\n");
2610 ok(EqualRect(&rect_in_ptr, &test_rect3), "Rects didn't match.\n");
2611 ok(EqualRect(&rect_in_out, &test_rect7), "Rects didn't match.\n");
2613 /* Test complex structs. */
2614 complex.c = 98;
2615 complex.i = 76543;
2616 i = 2;
2617 complex.pi = &i;
2618 i2 = 10;
2619 complex.ppi = &pi;
2620 complex.iface = create_disp_obj();
2621 sfd = create_disp_obj();
2622 complex.iface_ptr = &sfd;
2623 complex.bstr = SysAllocString(test_bstr2);
2624 V_VT(&complex.var) = VT_I4;
2625 V_I4(&complex.var) = 123;
2626 memcpy(&complex.mystruct, &test_mystruct1, sizeof(MYSTRUCT));
2627 memcpy(complex.arr, test_array1, sizeof(array_t));
2628 complex.myint = 456;
2629 hr = IWidget_complex_struct(widget, complex);
2630 ok(hr == S_OK, "Got hr %#x.\n", hr);
2633 static void test_marshal_array(IWidget *widget, IDispatch *disp)
2635 VARIANT var_in[2], var_out[2], var_in_out[2];
2636 ISomethingFromDispatch *proxy_sfd;
2637 array_t in, out, in_out;
2638 MYSTRUCT struct_in[2];
2639 HRESULT hr;
2640 int i = 2;
2642 memcpy(in, test_array1, sizeof(array_t));
2643 memcpy(out, test_array2, sizeof(array_t));
2644 memcpy(in_out, test_array3, sizeof(array_t));
2645 hr = IWidget_array(widget, in, out, in_out);
2646 ok(hr == S_OK, "Got hr %#x.\n", hr);
2647 ok(!memcmp(&in, &test_array1, sizeof(array_t)), "Arrays didn't match.\n");
2648 ok(!memcmp(&out, &test_array5, sizeof(array_t)), "Arrays didn't match.\n");
2649 ok(!memcmp(&in_out, &test_array6, sizeof(array_t)), "Arrays didn't match.\n");
2651 V_VT(&var_in[0]) = VT_I4; V_I4(&var_in[0]) = 1;
2652 V_VT(&var_in[1]) = VT_BYREF|VT_I4; V_I4REF(&var_in[1]) = &i;
2653 V_VT(&var_out[0]) = VT_I4; V_I4(&var_out[0]) = 3;
2654 V_VT(&var_out[1]) = VT_I4; V_I4(&var_out[1]) = 4;
2655 V_VT(&var_in_out[0]) = VT_I4; V_I4(&var_in_out[0]) = 5;
2656 V_VT(&var_in_out[1]) = VT_BSTR; V_BSTR(&var_in_out[1]) = SysAllocString(test_bstr1);
2657 hr = IWidget_variant_array(widget, var_in, var_out, var_in_out);
2658 ok(hr == S_OK, "Got hr %#x.\n", hr);
2659 ok(V_VT(&var_in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[0]));
2660 ok(V_I4(&var_in[0]) == 1, "Got wrong value %d.\n", V_I4(&var_in[0]));
2661 ok(V_VT(&var_in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&var_in[1]));
2662 ok(V_I4REF(&var_in[1]) == &i, "Got wrong value %p.\n", V_I4REF(&var_in[1]));
2663 ok(i == 2, "Got wrong value %d.\n", i);
2664 ok(V_VT(&var_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[0]));
2665 ok(V_I1(&var_out[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out[0]));
2666 ok(V_VT(&var_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&var_out[1]));
2667 ok(!lstrcmpW(V_BSTR(&var_out[1]), test_bstr2), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&var_out[1])));
2668 ok(V_VT(&var_in_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[0]));
2669 ok(V_I1(&var_in_out[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out[0]));
2670 ok(V_VT(&var_in_out[1]) == VT_UNKNOWN, "Got wrong type %u.\n", V_VT(&var_in_out[1]));
2671 hr = IUnknown_QueryInterface(V_UNKNOWN(&var_in_out[1]), &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
2672 ok(hr == S_OK, "Got hr %#x.\n", hr);
2673 hr = ISomethingFromDispatch_anotherfn(proxy_sfd);
2674 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2675 ISomethingFromDispatch_Release(proxy_sfd);
2676 release_iface(V_UNKNOWN(&var_in_out[1]));
2678 memcpy(&struct_in[0], &test_mystruct1, sizeof(MYSTRUCT));
2679 memcpy(&struct_in[1], &test_mystruct2, sizeof(MYSTRUCT));
2680 hr = IWidget_mystruct_array(widget, struct_in);
2681 ok(hr == S_OK, "Got hr %#x.\n", hr);
2684 static void test_marshal_coclass(IWidget *widget, IDispatch *disp)
2686 VARIANTARG arg[3];
2687 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2688 struct coclass_obj *class1, *class2, *class3;
2689 IUnknown *unk_in, *unk_out, *unk_in_out;
2690 ICoclass1 *in, *out, *in_out;
2691 Coclass1 class1_noptr;
2692 Coclass2 class2_noptr;
2693 Coclass3 class3_noptr;
2694 HRESULT hr;
2696 class1 = create_coclass_obj();
2697 class2 = create_coclass_obj();
2698 class3 = create_coclass_obj();
2700 hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass1_iface,
2701 (Coclass2 *)&class2->ICoclass1_iface, (Coclass3 *)&class3->ICoclass1_iface);
2702 ok(hr == S_OK, "Got hr %#x.\n", hr);
2704 hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass2_iface,
2705 (Coclass2 *)&class2->ICoclass2_iface, (Coclass3 *)&class3->ICoclass2_iface);
2706 ok(hr == S_OK, "Got hr %#x.\n", hr);
2708 release_iface(&class1->ICoclass1_iface);
2709 release_iface(&class2->ICoclass1_iface);
2710 release_iface(&class3->ICoclass1_iface);
2712 testmode = 0;
2713 class1 = create_coclass_obj();
2714 class2 = create_coclass_obj();
2715 class3 = create_coclass_obj();
2716 in = &class1->ICoclass1_iface;
2717 out = &class2->ICoclass1_iface;
2718 in_out = &class3->ICoclass1_iface;
2719 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in, (Coclass1 **)&out, (Coclass1 **)&in_out);
2720 ok(hr == S_OK, "Got hr %#x.\n", hr);
2721 ok(in == &class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2722 ok(!out, "[out] parameter should have been cleared.\n");
2723 ok(in_out == &class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2724 release_iface(&class1->ICoclass1_iface);
2725 release_iface(&class2->ICoclass1_iface);
2726 release_iface(&class3->ICoclass1_iface);
2728 testmode = 1;
2729 class1 = create_coclass_obj();
2730 class3 = create_coclass_obj();
2731 in = &class1->ICoclass1_iface;
2732 in_out = &class3->ICoclass1_iface;
2733 ICoclass1_AddRef(in_out);
2734 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2735 (Coclass1 **)&out, (Coclass1 **)&in_out);
2736 ok(hr == S_OK, "Got hr %#x.\n", hr);
2737 hr = ICoclass1_test(out);
2738 ok(hr == 1, "Got hr %#x.\n", hr);
2739 ok(in_out != &class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2740 hr = ICoclass1_test(in_out);
2741 ok(hr == 1, "Got hr %#x.\n", hr);
2742 release_iface(out);
2743 release_iface(in_out);
2744 release_iface(&class1->ICoclass1_iface);
2745 release_iface(&class3->ICoclass1_iface);
2747 testmode = 2;
2748 in = out = in_out = NULL;
2749 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2750 (Coclass1 **)&out, (Coclass1 **)&in_out);
2751 ok(hr == S_OK, "Got hr %#x.\n", hr);
2752 hr = ICoclass1_test(in_out);
2753 ok(hr == 1, "Got hr %#x.\n", hr);
2754 release_iface(in_out);
2756 testmode = 3;
2757 in = out = NULL;
2758 class3 = create_coclass_obj();
2759 in_out = &class3->ICoclass1_iface;
2760 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2761 (Coclass1 **)&out, (Coclass1 **)&in_out);
2762 ok(hr == S_OK, "Got hr %#x.\n", hr);
2763 ok(!in_out, "Got [in, out] %p.\n", in_out);
2765 class1 = create_coclass_obj();
2766 class2 = create_coclass_obj();
2767 class3 = create_coclass_obj();
2768 class1_noptr.iface = &class1->ICoclass1_iface;
2769 class2_noptr.iface = &class2->ICoclass2_iface;
2770 class3_noptr.iface = &class3->ICoclass1_iface;
2771 hr = IWidget_Coclass_noptr(widget, class1_noptr, class2_noptr, class3_noptr);
2772 ok(hr == S_OK, "Got hr %#x.\n", hr);
2773 release_iface(&class1->ICoclass1_iface);
2774 release_iface(&class2->ICoclass1_iface);
2775 release_iface(&class3->ICoclass1_iface);
2777 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2778 * interface back, but rather an IUnknown. */
2780 class1 = create_coclass_obj();
2781 class2 = create_coclass_obj();
2782 class3 = create_coclass_obj();
2784 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass1_iface;
2785 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass1_iface;
2786 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass1_iface;
2787 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2788 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2789 ok(hr == S_OK, "Got hr %#x.\n", hr);
2791 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass2_iface;
2792 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass2_iface;
2793 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass2_iface;
2794 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2795 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2796 ok(hr == S_OK, "Got hr %#x.\n", hr);
2798 V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)&class1->ICoclass1_iface;
2799 V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)&class2->ICoclass1_iface;
2800 V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)&class3->ICoclass1_iface;
2801 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2802 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2803 ok(hr == S_OK, "Got hr %#x.\n", hr);
2805 release_iface(&class1->ICoclass1_iface);
2806 release_iface(&class2->ICoclass1_iface);
2807 release_iface(&class3->ICoclass1_iface);
2809 testmode = 0;
2810 class1 = create_coclass_obj();
2811 class3 = create_coclass_obj();
2812 unk_in = (IUnknown *)&class1->ICoclass1_iface;
2813 unk_out = NULL;
2814 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2815 V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &unk_in;
2816 V_VT(&arg[1]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[1]) = &unk_out;
2817 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2818 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2819 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2820 todo_wine
2821 ok(hr == S_OK, "Got hr %#x.\n", hr);
2822 ok(unk_in == (IUnknown *)&class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2823 ok(!unk_out, "[out] parameter should have been cleared.\n");
2824 ok(unk_in_out == (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2825 release_iface(&class1->ICoclass1_iface);
2826 release_iface(&class3->ICoclass1_iface);
2828 testmode = 1;
2829 class1 = create_coclass_obj();
2830 class3 = create_coclass_obj();
2831 unk_in = (IUnknown *)&class1->ICoclass1_iface;
2832 unk_out = NULL;
2833 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2834 IUnknown_AddRef(unk_in_out);
2835 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2836 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2837 todo_wine
2838 ok(hr == S_OK, "Got hr %#x.\n", hr);
2840 if (hr == S_OK) {
2841 hr = IUnknown_QueryInterface(unk_out, &IID_ICoclass1, (void **)&out);
2842 ok(hr == S_OK, "Got hr %#x.\n", hr);
2843 hr = ICoclass1_test(out);
2844 ok(hr == 1, "Got hr %#x.\n", hr);
2845 ICoclass1_Release(out);
2847 ok(unk_in_out != (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2848 hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2849 ok(hr == S_OK, "Got hr %#x.\n", hr);
2850 hr = ICoclass1_test(in_out);
2851 ok(hr == 1, "Got hr %#x.\n", hr);
2852 ICoclass1_Release(in_out);
2854 release_iface(unk_out);
2855 release_iface(unk_in_out);
2857 release_iface(&class1->ICoclass1_iface);
2858 todo_wine
2859 release_iface(&class3->ICoclass1_iface);
2861 testmode = 2;
2862 unk_in = unk_out = unk_in_out = NULL;
2863 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2864 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2865 todo_wine
2866 ok(hr == S_OK, "Got hr %#x.\n", hr);
2868 ok(!unk_out, "[out] parameter should not have been set.\n");
2869 if (hr == S_OK) {
2870 hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2871 ok(hr == S_OK, "Got hr %#x.\n", hr);
2872 hr = ICoclass1_test(in_out);
2873 ok(hr == 1, "Got hr %#x.\n", hr);
2874 ICoclass1_Release(in_out);
2876 release_iface(unk_in_out);
2879 testmode = 3;
2880 unk_in = unk_out = NULL;
2881 class3 = create_coclass_obj();
2882 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2883 IUnknown_AddRef(unk_in_out);
2884 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2885 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2886 todo_wine
2887 ok(hr == S_OK, "Got hr %#x.\n", hr);
2888 todo_wine
2889 ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2891 todo_wine
2892 release_iface(&class3->ICoclass1_iface);
2895 static void test_typelibmarshal(void)
2897 static const WCHAR szCat[] = { 'C','a','t',0 };
2898 static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
2899 static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
2900 HRESULT hr;
2901 IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
2902 IWidget *pWidget;
2903 IStream *pStream;
2904 IDispatch *pDispatch;
2905 static const LARGE_INTEGER ullZero;
2906 EXCEPINFO excepinfo;
2907 VARIANT varresult;
2908 DISPID dispidNamed = DISPID_PROPERTYPUT;
2909 DISPPARAMS dispparams;
2910 VARIANTARG vararg[4];
2911 STATE the_state;
2912 HANDLE thread;
2913 DWORD tid;
2914 BSTR bstr;
2915 ITypeInfo *pTypeInfo;
2916 UINT uval;
2918 ok(pKEW != NULL, "Widget creation failed\n");
2920 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2921 ok_ole_success(hr, CreateStreamOnHGlobal);
2922 tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
2923 IKindaEnumWidget_Release(pKEW);
2925 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2926 hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
2927 ok_ole_success(hr, CoUnmarshalInterface);
2928 IStream_Release(pStream);
2929 if (FAILED(hr))
2931 end_host_object(tid, thread);
2932 return;
2935 hr = IKindaEnumWidget_Next(pKEW, &pWidget);
2936 ok_ole_success(hr, IKindaEnumWidget_Next);
2938 IKindaEnumWidget_Release(pKEW);
2940 /* call GetTypeInfoCount (direct) */
2941 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2942 ok_ole_success(hr, IWidget_GetTypeInfoCount);
2943 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2944 ok_ole_success(hr, IWidget_GetTypeInfoCount);
2946 hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
2947 ok_ole_success(hr, IWidget_QueryInterface);
2949 /* call put_Name */
2950 VariantInit(&vararg[0]);
2951 dispparams.cNamedArgs = 1;
2952 dispparams.rgdispidNamedArgs = &dispidNamed;
2953 dispparams.cArgs = 1;
2954 dispparams.rgvarg = vararg;
2955 VariantInit(&varresult);
2956 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
2957 ok_ole_success(hr, IDispatch_Invoke);
2958 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
2959 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2960 excepinfo.wCode, excepinfo.scode);
2961 VariantClear(&varresult);
2963 /* call put_Name (direct) */
2964 bstr = SysAllocString(szSuperman);
2965 hr = IWidget_put_Name(pWidget, bstr);
2966 ok_ole_success(hr, IWidget_put_Name);
2967 SysFreeString(bstr);
2969 /* call get_Name */
2970 dispparams.cNamedArgs = 0;
2971 dispparams.rgdispidNamedArgs = NULL;
2972 dispparams.cArgs = 0;
2973 dispparams.rgvarg = NULL;
2974 VariantInit(&varresult);
2975 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
2976 ok_ole_success(hr, IDispatch_Invoke);
2977 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
2978 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2979 excepinfo.wCode, excepinfo.scode);
2980 trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
2981 VariantClear(&varresult);
2983 /* call get_Name (direct) */
2984 bstr = (void *)0xdeadbeef;
2985 hr = IWidget_get_Name(pWidget, &bstr);
2986 ok_ole_success(hr, IWidget_get_Name);
2987 ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
2988 SysFreeString(bstr);
2990 /* call DoSomething without optional arguments */
2991 VariantInit(&vararg[0]);
2992 VariantInit(&vararg[1]);
2993 V_VT(&vararg[1]) = VT_R8;
2994 V_R8(&vararg[1]) = 3.141;
2995 dispparams.cNamedArgs = 0;
2996 dispparams.cArgs = 2;
2997 dispparams.rgdispidNamedArgs = NULL;
2998 dispparams.rgvarg = vararg;
2999 VariantInit(&varresult);
3000 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3001 ok_ole_success(hr, IDispatch_Invoke);
3002 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3003 VariantClear(&varresult);
3005 /* call DoSomething with optional argument set to VT_EMPTY */
3006 VariantInit(&vararg[0]);
3007 VariantInit(&vararg[1]);
3008 VariantInit(&vararg[2]);
3009 V_VT(&vararg[2]) = VT_R8;
3010 V_R8(&vararg[2]) = 3.141;
3011 dispparams.cNamedArgs = 0;
3012 dispparams.cArgs = 3;
3013 dispparams.rgdispidNamedArgs = NULL;
3014 dispparams.rgvarg = vararg;
3015 VariantInit(&varresult);
3016 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3017 ok_ole_success(hr, IDispatch_Invoke);
3018 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3019 VariantClear(&varresult);
3021 /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
3022 VariantInit(&vararg[0]);
3023 VariantInit(&vararg[1]);
3024 VariantInit(&vararg[2]);
3025 VariantInit(&vararg[3]);
3026 V_VT(&vararg[3]) = VT_R8;
3027 V_R8(&vararg[3]) = 3.141;
3028 V_VT(&vararg[1]) = VT_ERROR;
3029 V_ERROR(&vararg[1]) = DISP_E_PARAMNOTFOUND;
3030 V_VT(&vararg[0]) = VT_ERROR;
3031 V_ERROR(&vararg[0]) = DISP_E_PARAMNOTFOUND;
3032 dispparams.cNamedArgs = 0;
3033 dispparams.cArgs = 4;
3034 dispparams.rgdispidNamedArgs = NULL;
3035 dispparams.rgvarg = vararg;
3036 VariantInit(&varresult);
3037 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3038 ok_ole_success(hr, IDispatch_Invoke);
3039 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3040 VariantClear(&varresult);
3042 /* call get_State */
3043 dispparams.cNamedArgs = 0;
3044 dispparams.cArgs = 0;
3045 dispparams.rgdispidNamedArgs = NULL;
3046 dispparams.rgvarg = NULL;
3047 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3048 ok_ole_success(hr, IDispatch_Invoke);
3049 ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
3051 /* call get_State (direct) */
3052 hr = IWidget_get_State(pWidget, &the_state);
3053 ok_ole_success(hr, IWidget_get_state);
3054 ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
3056 /* call put_State */
3057 the_state = STATE_WIDGETIFIED;
3058 VariantInit(&vararg[0]);
3059 V_VT(&vararg[0]) = VT_BYREF|VT_I4;
3060 V_I4REF(&vararg[0]) = (int *)&the_state;
3061 dispparams.cNamedArgs = 1;
3062 dispparams.cArgs = 1;
3063 dispparams.rgdispidNamedArgs = &dispidNamed;
3064 dispparams.rgvarg = vararg;
3065 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3066 ok_ole_success(hr, IDispatch_Invoke);
3068 /* call Map */
3069 bstr = SysAllocString(szTestTest);
3070 VariantInit(&vararg[0]);
3071 V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
3072 V_BSTRREF(&vararg[0]) = &bstr;
3073 dispparams.cNamedArgs = 0;
3074 dispparams.cArgs = 1;
3075 dispparams.rgdispidNamedArgs = NULL;
3076 dispparams.rgvarg = vararg;
3077 VariantInit(&varresult);
3078 hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3079 ok_ole_success(hr, IDispatch_Invoke);
3080 ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
3081 ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
3082 VariantClear(&varresult);
3083 SysFreeString(bstr);
3085 /* call SetOleColor with large negative VT_I4 param */
3086 VariantInit(&vararg[0]);
3087 V_VT(&vararg[0]) = VT_I4;
3088 V_I4(&vararg[0]) = 0x80000005;
3089 dispparams.cNamedArgs = 0;
3090 dispparams.cArgs = 1;
3091 dispparams.rgdispidNamedArgs = NULL;
3092 dispparams.rgvarg = vararg;
3093 hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
3094 ok_ole_success(hr, IDispatch_Invoke);
3096 /* call GetOleColor */
3097 dispparams.cNamedArgs = 0;
3098 dispparams.cArgs = 0;
3099 dispparams.rgdispidNamedArgs = NULL;
3100 dispparams.rgvarg = NULL;
3101 VariantInit(&varresult);
3102 hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3103 ok_ole_success(hr, IDispatch_Invoke);
3104 VariantClear(&varresult);
3106 /* call Clone */
3107 dispparams.cNamedArgs = 0;
3108 dispparams.cArgs = 0;
3109 dispparams.rgdispidNamedArgs = NULL;
3110 dispparams.rgvarg = NULL;
3111 VariantInit(&varresult);
3112 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3113 ok_ole_success(hr, IDispatch_Invoke);
3114 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
3115 VariantClear(&varresult);
3117 /* call CloneInterface */
3118 dispparams.cNamedArgs = 0;
3119 dispparams.cArgs = 0;
3120 dispparams.rgdispidNamedArgs = NULL;
3121 dispparams.rgvarg = NULL;
3122 VariantInit(&varresult);
3123 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3124 ok_ole_success(hr, IDispatch_Invoke);
3125 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
3126 VariantClear(&varresult);
3128 /* call CloneDispatch with automatic value getting */
3129 V_VT(&vararg[0]) = VT_I2;
3130 V_I2(&vararg[0]) = 1;
3131 dispparams.cNamedArgs = 0;
3132 dispparams.rgdispidNamedArgs = NULL;
3133 dispparams.cArgs = 1;
3134 dispparams.rgvarg = vararg;
3135 VariantInit(&varresult);
3136 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3137 ok_ole_success(hr, IDispatch_Invoke);
3139 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3140 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3141 excepinfo.wCode, excepinfo.scode);
3143 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3144 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3145 VariantClear(&varresult);
3147 /* call CloneCoclass */
3148 dispparams.cNamedArgs = 0;
3149 dispparams.cArgs = 0;
3150 dispparams.rgdispidNamedArgs = NULL;
3151 dispparams.rgvarg = NULL;
3152 VariantInit(&varresult);
3153 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3154 ok_ole_success(hr, IDispatch_Invoke);
3156 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3157 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3158 excepinfo.wCode, excepinfo.scode);
3160 ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
3161 ok(V_DISPATCH(&varresult) != NULL, "expected V_DISPATCH(&varresult) != NULL\n");
3163 /* call Value with a VT_VARIANT|VT_BYREF type */
3164 V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
3165 V_VARIANTREF(&vararg[0]) = &vararg[1];
3166 V_VT(&vararg[1]) = VT_I2;
3167 V_I2(&vararg[1]) = 1;
3168 dispparams.cNamedArgs = 0;
3169 dispparams.rgdispidNamedArgs = NULL;
3170 dispparams.cArgs = 1;
3171 dispparams.rgvarg = vararg;
3172 VariantInit(&varresult);
3173 hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3174 ok_ole_success(hr, IDispatch_Invoke);
3176 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3177 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3178 excepinfo.wCode, excepinfo.scode);
3180 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3181 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3182 VariantClear(&varresult);
3184 /* call Array with BSTR argument - type mismatch */
3185 VariantInit(&vararg[0]);
3186 V_VT(&vararg[0]) = VT_BSTR;
3187 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3188 dispparams.cNamedArgs = 0;
3189 dispparams.cArgs = 1;
3190 dispparams.rgdispidNamedArgs = NULL;
3191 dispparams.rgvarg = vararg;
3192 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ARRAY, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3193 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
3194 SysFreeString(V_BSTR(&vararg[0]));
3196 /* call ArrayPtr with BSTR argument - type mismatch */
3197 VariantInit(&vararg[0]);
3198 V_VT(&vararg[0]) = VT_BSTR;
3199 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3200 dispparams.cNamedArgs = 0;
3201 dispparams.cArgs = 1;
3202 dispparams.rgdispidNamedArgs = NULL;
3203 dispparams.rgvarg = vararg;
3204 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARRAYPTR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3205 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
3206 SysFreeString(V_BSTR(&vararg[0]));
3208 /* call VarArg */
3209 VariantInit(&vararg[3]);
3210 V_VT(&vararg[3]) = VT_I4;
3211 V_I4(&vararg[3]) = 3;
3212 VariantInit(&vararg[2]);
3213 V_VT(&vararg[2]) = VT_I4;
3214 V_I4(&vararg[2]) = 0;
3215 VariantInit(&vararg[1]);
3216 V_VT(&vararg[1]) = VT_I4;
3217 V_I4(&vararg[1]) = 1;
3218 VariantInit(&vararg[0]);
3219 V_VT(&vararg[0]) = VT_I4;
3220 V_I4(&vararg[0]) = 2;
3221 dispparams.cNamedArgs = 0;
3222 dispparams.cArgs = 4;
3223 dispparams.rgdispidNamedArgs = NULL;
3224 dispparams.rgvarg = vararg;
3225 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3226 ok_ole_success(hr, IDispatch_Invoke);
3228 /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
3229 dispidNamed = 0;
3230 dispparams.cNamedArgs = 1;
3231 dispparams.rgdispidNamedArgs = &dispidNamed;
3232 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3233 ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
3234 dispidNamed = DISPID_PROPERTYPUT;
3236 /* call VarArg_Run */
3237 VariantInit(&vararg[1]);
3238 V_VT(&vararg[1]) = VT_BSTR;
3239 V_BSTR(&vararg[1]) = SysAllocString(szCat);
3240 VariantInit(&vararg[0]);
3241 V_VT(&vararg[0]) = VT_BSTR;
3242 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3243 dispparams.cNamedArgs = 0;
3244 dispparams.cArgs = 2;
3245 dispparams.rgdispidNamedArgs = NULL;
3246 dispparams.rgvarg = vararg;
3247 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3248 ok_ole_success(hr, IDispatch_Invoke);
3249 SysFreeString(V_BSTR(&vararg[1]));
3250 SysFreeString(V_BSTR(&vararg[0]));
3252 /* call VarArg_Ref_Run */
3253 VariantInit(&vararg[1]);
3254 V_VT(&vararg[1]) = VT_BSTR;
3255 V_BSTR(&vararg[1]) = SysAllocString(szCat);
3256 VariantInit(&vararg[0]);
3257 V_VT(&vararg[0]) = VT_BSTR;
3258 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3259 dispparams.cNamedArgs = 0;
3260 dispparams.cArgs = 2;
3261 dispparams.rgdispidNamedArgs = NULL;
3262 dispparams.rgvarg = vararg;
3263 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_REF_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3264 ok_ole_success(hr, IDispatch_Invoke);
3265 SysFreeString(V_BSTR(&vararg[1]));
3266 SysFreeString(V_BSTR(&vararg[0]));
3268 /* call Error */
3269 dispparams.cNamedArgs = 0;
3270 dispparams.cArgs = 0;
3271 dispparams.rgdispidNamedArgs = NULL;
3272 dispparams.rgvarg = NULL;
3273 VariantInit(&varresult);
3274 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
3275 ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
3276 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3277 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3278 excepinfo.wCode, excepinfo.scode);
3279 VariantClear(&varresult);
3281 /* call BstrRet */
3282 pTypeInfo = NonOleAutomation_GetTypeInfo();
3283 dispparams.cNamedArgs = 0;
3284 dispparams.cArgs = 0;
3285 dispparams.rgdispidNamedArgs = NULL;
3286 dispparams.rgvarg = NULL;
3287 VariantInit(&varresult);
3288 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3289 ok_ole_success(hr, ITypeInfo_Invoke);
3290 ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
3291 ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
3293 VariantClear(&varresult);
3295 dispparams.cNamedArgs = 0;
3296 dispparams.cArgs = 0;
3297 dispparams.rgdispidNamedArgs = NULL;
3298 dispparams.rgvarg = NULL;
3299 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_ERROR, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3300 ok(hr == DISP_E_EXCEPTION, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
3301 ok(V_VT(&varresult) == VT_EMPTY, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult));
3302 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3303 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3304 excepinfo.wCode, excepinfo.scode);
3305 VariantClear(&varresult);
3307 ITypeInfo_Release(pTypeInfo);
3309 /* tests call put_Name without named arg */
3310 VariantInit(&vararg[0]);
3311 dispparams.cNamedArgs = 0;
3312 dispparams.rgdispidNamedArgs = NULL;
3313 dispparams.cArgs = 1;
3314 dispparams.rgvarg = vararg;
3315 VariantInit(&varresult);
3316 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3317 ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
3318 VariantClear(&varresult);
3320 /* tests param type that cannot be coerced */
3321 VariantInit(&vararg[0]);
3322 V_VT(&vararg[0]) = VT_UNKNOWN;
3323 V_UNKNOWN(&vararg[0]) = NULL;
3324 dispparams.cNamedArgs = 1;
3325 dispparams.rgdispidNamedArgs = &dispidNamed;
3326 dispparams.cArgs = 1;
3327 dispparams.rgvarg = vararg;
3328 VariantInit(&varresult);
3329 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3330 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
3331 VariantClear(&varresult);
3333 /* tests bad param type */
3334 VariantInit(&vararg[0]);
3335 V_VT(&vararg[0]) = VT_CLSID;
3336 V_BYREF(&vararg[0]) = NULL;
3337 dispparams.cNamedArgs = 1;
3338 dispparams.rgdispidNamedArgs = &dispidNamed;
3339 dispparams.cArgs = 1;
3340 dispparams.rgvarg = vararg;
3341 VariantInit(&varresult);
3342 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3343 ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
3344 VariantClear(&varresult);
3346 /* tests too small param count */
3347 dispparams.cNamedArgs = 0;
3348 dispparams.rgdispidNamedArgs = NULL;
3349 dispparams.cArgs = 0;
3350 dispparams.rgvarg = NULL;
3351 VariantInit(&varresult);
3352 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3353 ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
3354 VariantClear(&varresult);
3356 /* tests propget function with large param count */
3357 VariantInit(&vararg[0]);
3358 V_VT(&vararg[0]) = VT_BSTR;
3359 V_BSTR(&vararg[0]) = NULL;
3360 V_VT(&vararg[1]) = VT_I4;
3361 V_I4(&vararg[1]) = 1;
3362 dispparams.cNamedArgs = 0;
3363 dispparams.cArgs = 2;
3364 dispparams.rgdispidNamedArgs = NULL;
3365 dispparams.rgvarg = vararg;
3366 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3367 ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
3369 /* test propput with lcid */
3371 /* the lcid passed to the function is the first lcid in the typelib header.
3372 Since we don't explicitly set an lcid in the idl, it'll default to US English. */
3373 VariantInit(&vararg[0]);
3374 V_VT(&vararg[0]) = VT_I4;
3375 V_I4(&vararg[0]) = 0xcafe;
3376 dispparams.cNamedArgs = 1;
3377 dispparams.rgdispidNamedArgs = &dispidNamed;
3378 dispparams.cArgs = 1;
3379 dispparams.rgvarg = vararg;
3380 VariantInit(&varresult);
3381 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3382 ok_ole_success(hr, ITypeInfo_Invoke);
3383 VariantClear(&varresult);
3385 /* test propget with lcid */
3386 dispparams.cNamedArgs = 0;
3387 dispparams.cArgs = 0;
3388 dispparams.rgvarg = NULL;
3389 dispparams.rgdispidNamedArgs = NULL;
3390 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3391 ok_ole_success(hr, ITypeInfo_Invoke);
3392 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3393 ok(V_I4(&varresult) == 0x409, "got %x\n", V_I4(&varresult));
3394 VariantClear(&varresult);
3396 /* test propget of INT value */
3397 dispparams.cNamedArgs = 0;
3398 dispparams.cArgs = 0;
3399 dispparams.rgvarg = NULL;
3400 dispparams.rgdispidNamedArgs = NULL;
3401 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_INT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3402 ok_ole_success(hr, ITypeInfo_Invoke);
3403 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3404 ok(V_I4(&varresult) == -13, "got %x\n", V_I4(&varresult));
3405 VariantClear(&varresult);
3407 /* test propget of INT value */
3408 dispparams.cNamedArgs = 0;
3409 dispparams.cArgs = 0;
3410 dispparams.rgvarg = NULL;
3411 dispparams.rgdispidNamedArgs = NULL;
3412 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_UINT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3413 ok_ole_success(hr, ITypeInfo_Invoke);
3414 ok(V_VT(&varresult) == VT_UI4, "got %x\n", V_VT(&varresult));
3415 ok(V_UI4(&varresult) == 42, "got %x\n", V_UI4(&varresult));
3416 VariantClear(&varresult);
3418 /* test byref marshalling */
3419 uval = 666;
3420 VariantInit(&vararg[0]);
3421 V_VT(&vararg[0]) = VT_UI4|VT_BYREF;
3422 V_UI4REF(&vararg[0]) = &uval;
3423 dispparams.cNamedArgs = 0;
3424 dispparams.cArgs = 1;
3425 dispparams.rgvarg = vararg;
3426 dispparams.rgdispidNamedArgs = NULL;
3427 hr = IDispatch_Invoke(pDispatch, DISPID_TM_BYREF_UINT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3428 ok_ole_success(hr, ITypeInfo_Invoke);
3429 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3430 ok(V_VT(&vararg[0]) == (VT_UI4|VT_BYREF), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg[0]));
3431 ok(V_UI4REF(&vararg[0]) == &uval, "Byref pointer not preserved: %p/%p\n", &uval, V_UI4REF(&vararg[0]));
3432 ok(*V_UI4REF(&vararg[0]) == 42, "Expected 42 to be returned instead of %u\n", *V_UI4REF(&vararg[0]));
3433 VariantClear(&varresult);
3434 VariantClear(&vararg[0]);
3436 /* test propput with optional argument. */
3437 VariantInit(&vararg[0]);
3438 V_VT(&vararg[0]) = VT_I4;
3439 V_I4(&vararg[0]) = 0xcafe;
3440 dispparams.cNamedArgs = 1;
3441 dispparams.rgdispidNamedArgs = &dispidNamed;
3442 dispparams.cArgs = 1;
3443 dispparams.rgvarg = vararg;
3444 VariantInit(&varresult);
3445 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_OPT_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3446 ok_ole_success(hr, ITypeInfo_Invoke);
3447 VariantClear(&varresult);
3449 /* test propput with required argument. */
3450 VariantInit(&vararg[0]);
3451 VariantInit(&vararg[1]);
3452 V_VT(&vararg[0]) = VT_I4;
3453 V_I4(&vararg[0]) = 0x1234;
3454 V_VT(&vararg[1]) = VT_I4;
3455 V_I4(&vararg[1]) = 0x5678;
3456 dispparams.cNamedArgs = 1;
3457 dispparams.rgdispidNamedArgs = &dispidNamed;
3458 dispparams.cArgs = 2;
3459 dispparams.rgvarg = vararg;
3460 VariantInit(&varresult);
3461 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_REQ_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3462 ok_ole_success(hr, ITypeInfo_Invoke);
3463 VariantClear(&varresult);
3465 /* restricted member */
3466 dispparams.cNamedArgs = 0;
3467 dispparams.rgdispidNamedArgs = NULL;
3468 dispparams.cArgs = 0;
3469 dispparams.rgvarg = NULL;
3470 VariantInit(&varresult);
3471 hr = IDispatch_Invoke(pDispatch, DISPID_TM_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3472 ok( hr == DISP_E_MEMBERNOTFOUND, "got %08x\n", hr );
3473 VariantClear(&varresult);
3475 /* restricted member with -ve memid (not restricted) */
3476 dispparams.cNamedArgs = 0;
3477 dispparams.rgdispidNamedArgs = NULL;
3478 dispparams.cArgs = 0;
3479 dispparams.rgvarg = NULL;
3480 VariantInit(&varresult);
3481 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NEG_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3482 ok( hr == S_OK, "got %08x\n", hr );
3483 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3484 ok(V_I4(&varresult) == DISPID_TM_NEG_RESTRICTED, "got %x\n", V_I4(&varresult));
3485 VariantClear(&varresult);
3487 test_marshal_basetypes(pWidget, pDispatch);
3488 test_marshal_pointer(pWidget, pDispatch);
3489 test_marshal_iface(pWidget, pDispatch);
3490 test_marshal_bstr(pWidget, pDispatch);
3491 test_marshal_variant(pWidget, pDispatch);
3492 test_marshal_safearray(pWidget, pDispatch);
3493 test_marshal_struct(pWidget, pDispatch);
3494 test_marshal_array(pWidget, pDispatch);
3495 test_marshal_coclass(pWidget, pDispatch);
3497 IDispatch_Release(pDispatch);
3498 IWidget_Release(pWidget);
3500 trace("calling end_host_object\n");
3501 end_host_object(tid, thread);
3504 static void test_DispCallFunc(void)
3506 static const WCHAR szEmpty[] = { 0 };
3507 VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
3508 VARIANTARG vararg[4];
3509 VARIANTARG varref;
3510 VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
3511 VARIANTARG varresult;
3512 HRESULT hr;
3513 IWidget *pWidget = Widget_Create();
3514 V_VT(&vararg[0]) = VT_R8;
3515 V_R8(&vararg[0]) = 3.141;
3516 V_VT(&vararg[1]) = VT_BSTR;
3517 V_BSTRREF(&vararg[1]) = CoTaskMemAlloc(sizeof(BSTR));
3518 V_VT(&vararg[2]) = VT_BSTR;
3519 V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
3520 V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
3521 V_VARIANTREF(&vararg[3]) = &varref;
3522 V_VT(&varref) = VT_ERROR;
3523 V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
3524 VariantInit(&varresult);
3525 hr = DispCallFunc(pWidget, 9*sizeof(void*), CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
3526 ok_ole_success(hr, DispCallFunc);
3527 VariantClear(&varresult);
3528 SysFreeString(*V_BSTRREF(&vararg[1]));
3529 CoTaskMemFree(V_BSTRREF(&vararg[1]));
3530 VariantClear(&vararg[2]);
3531 IWidget_Release(pWidget);
3534 static void test_StaticWidget(void)
3536 ITypeInfo *type_info;
3537 DISPPARAMS dispparams;
3538 VARIANTARG vararg[4];
3539 EXCEPINFO excepinfo;
3540 VARIANT varresult;
3541 HRESULT hr;
3543 type_info = get_type_info(&IID_IStaticWidget);
3545 /* call TestDual */
3546 dispparams.cNamedArgs = 0;
3547 dispparams.cArgs = 1;
3548 dispparams.rgdispidNamedArgs = NULL;
3549 dispparams.rgvarg = vararg;
3550 V_VT(vararg) = VT_DISPATCH;
3551 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
3552 VariantInit(&varresult);
3553 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTDUAL, DISPATCH_METHOD,
3554 &dispparams, &varresult, &excepinfo, NULL);
3555 ok_ole_success(hr, IDispatch_Invoke);
3556 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
3557 VariantClear(&varresult);
3559 /* call TestSecondIface */
3560 dispparams.cNamedArgs = 0;
3561 dispparams.cArgs = 1;
3562 dispparams.rgdispidNamedArgs = NULL;
3563 dispparams.rgvarg = vararg;
3564 V_VT(vararg) = VT_DISPATCH;
3565 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
3566 VariantInit(&varresult);
3567 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTSECONDIFACE, DISPATCH_METHOD,
3568 &dispparams, &varresult, &excepinfo, NULL);
3569 ok_ole_success(hr, IDispatch_Invoke);
3570 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
3571 VariantClear(&varresult);
3573 ITypeInfo_Release(type_info);
3576 static void test_libattr(void)
3578 ITypeLib *pTypeLib;
3579 HRESULT hr;
3580 TLIBATTR *pattr;
3582 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
3583 ok_ole_success(hr, LoadRegTypeLib);
3584 if (FAILED(hr))
3585 return;
3587 hr = ITypeLib_GetLibAttr(pTypeLib, &pattr);
3588 ok_ole_success(hr, GetLibAttr);
3589 if (SUCCEEDED(hr))
3591 ok(pattr->lcid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "lcid %x\n", pattr->lcid);
3593 ITypeLib_ReleaseTLibAttr(pTypeLib, pattr);
3596 ITypeLib_Release(pTypeLib);
3599 static void test_external_connection(void)
3601 IStream *stream, *stream2;
3602 ITestSecondDisp *second;
3603 ItestDual *iface;
3604 HANDLE thread;
3605 DWORD tid;
3606 HRESULT hres;
3608 static const LARGE_INTEGER zero;
3610 trace("Testing IExternalConnection...\n");
3612 external_connections = 0;
3614 /* Marshaling an interface increases external connection count. */
3615 expect_last_release_closes = FALSE;
3616 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3617 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3618 tid = start_host_object(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHLFLAGS_NORMAL, &thread);
3619 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3621 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3622 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
3623 ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
3624 if (FAILED(hres))
3626 end_host_object(tid, thread);
3627 IStream_Release(stream);
3628 return;
3630 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3632 IStream_Release(stream);
3633 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3635 /* Creating a stub for new iface causes new external connection. */
3636 hres = ItestDual_QueryInterface(iface, &IID_ITestSecondDisp, (void**)&second);
3637 ok(hres == S_OK, "Could not get ITestSecondDisp iface: %08x\n", hres);
3638 todo_wine
3639 ok(external_connections == 2, "external_connections = %d\n", external_connections);
3641 ITestSecondDisp_Release(second);
3642 todo_wine
3643 ok(external_connections == 2, "external_connections = %d\n", external_connections);
3645 expect_last_release_closes = TRUE;
3646 ItestDual_Release(iface);
3647 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3649 end_host_object(tid, thread);
3651 /* A test with direct CoMarshalInterface call. */
3652 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3653 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3655 expect_last_release_closes = FALSE;
3656 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3657 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3658 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3660 expect_last_release_closes = TRUE;
3661 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3662 hres = CoReleaseMarshalData(stream);
3663 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3664 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3666 /* Two separated marshal data are still one external connection. */
3667 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream2);
3668 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3670 expect_last_release_closes = FALSE;
3671 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3672 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3673 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3674 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3676 hres = CoMarshalInterface(stream2, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3677 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3678 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3680 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3681 hres = CoReleaseMarshalData(stream);
3682 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3683 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3685 expect_last_release_closes = TRUE;
3686 IStream_Seek(stream2, zero, STREAM_SEEK_SET, NULL);
3687 hres = CoReleaseMarshalData(stream2);
3688 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3689 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3691 IStream_Release(stream);
3692 IStream_Release(stream2);
3694 /* Weak table marshaling does not increment external connections */
3695 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3696 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3698 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
3699 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3700 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3702 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3703 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
3704 ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
3705 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3706 ItestDual_Release(iface);
3708 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3709 hres = CoReleaseMarshalData(stream);
3710 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3711 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3713 IStream_Release(stream);
3716 static void test_marshal_dispinterface(void)
3718 static const LARGE_INTEGER zero;
3720 ISomethingFromDispatch *disp_obj = create_disp_obj();
3721 ITypeInfo *typeinfo = NULL;
3722 IDispatch *proxy_disp;
3723 IStream *stream;
3724 HANDLE thread;
3725 HRESULT hr;
3726 ULONG ref;
3727 DWORD tid;
3729 CreateStreamOnHGlobal(NULL, TRUE, &stream);
3730 tid = start_host_object(stream, &DIID_ItestIF4, (IUnknown *)disp_obj, MSHLFLAGS_NORMAL, &thread);
3731 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3732 hr = CoUnmarshalInterface(stream, &DIID_ItestIF4, (void **)&proxy_disp);
3733 ok(hr == S_OK, "Got hr %#x.\n", hr);
3735 hr = IDispatch_GetTypeInfo(proxy_disp, 0xdeadbeef, 0, &typeinfo);
3736 ok(hr == 0xbeefdead, "Got hr %#x.\n", hr);
3738 ref = IDispatch_Release(proxy_disp);
3739 ok(!ref, "Got outstanding refcount %d.\n", ref);
3740 ref = IStream_Release(stream);
3741 ok(!ref, "Got outstanding refcount %d.\n", ref);
3742 end_host_object(tid, thread);
3743 ref = ISomethingFromDispatch_Release(disp_obj);
3744 ok(!ref, "Got outstanding refcount %d.\n", ref);
3747 START_TEST(tmarshal)
3749 HRESULT hr;
3750 HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll");
3751 pVarAdd = (void*)GetProcAddress(hOleaut32, "VarAdd");
3753 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3755 hr = register_current_module_typelib();
3756 if (FAILED(hr))
3758 CoUninitialize();
3759 win_skip("Registration of the test typelib failed, skipping tests\n");
3760 return;
3763 test_typelibmarshal();
3764 test_DispCallFunc();
3765 test_StaticWidget();
3766 test_libattr();
3767 test_external_connection();
3768 test_marshal_dispinterface();
3770 hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
3771 sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
3772 ok_ole_success(hr, UnRegisterTypeLib);
3774 CoUninitialize();