include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / oleaut32 / tests / tmarshal.c
blob4bcc15628f7a109345a7b15bad6be13cb62c46b1
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 <stdbool.h>
21 #include <math.h>
23 #define COBJMACROS
24 #define CONST_VTABLE
26 #include <windows.h>
27 #include <ocidl.h>
28 #include <stdio.h>
30 #include "wine/test.h"
32 #include "tmarshal.h"
34 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error %#08lx\n", hr)
35 static inline void release_iface_(unsigned int line, void *iface)
37 ULONG ref = IUnknown_Release((IUnknown *)iface);
38 ok_(__FILE__, line)(!ref, "Got outstanding refcount %ld.\n", ref);
39 if (ref == 1) IUnknown_Release((IUnknown *)iface);
41 #define release_iface(a) release_iface_(__LINE__, a)
43 static const WCHAR test_bstr1[] = {'f','o','o',0,'b','a','r'};
44 static const WCHAR test_bstr2[] = {'t','e','s','t',0};
45 static const WCHAR test_bstr3[] = {'q','u','x',0};
46 static const WCHAR test_bstr4[] = {'a','b','c',0};
48 static const MYSTRUCT test_mystruct1 = {0x12345678, 0xdeadbeef98765432ull, {0,1,2,3,4,5,6,7}};
49 static const MYSTRUCT test_mystruct2 = {0x91827364, 0x8877665544332211ull, {3,6,1,4,0,1,3,0}};
50 static const MYSTRUCT test_mystruct3 = {0x1a1b1c1d, 0x1e1f101112131415ull, {9,2,4,5,6,5,1,3}};
51 static const MYSTRUCT test_mystruct4 = {0x2a2b2c2d, 0x2e2f202122232425ull, {0,4,6,7,3,6,7,4}};
52 static const MYSTRUCT test_mystruct5 = {0x3a3b3c3d, 0x3e3f303132333435ull, {1,6,7,3,8,4,6,5}};
53 static const MYSTRUCT test_mystruct6 = {0x4a4b4c4d, 0x4e4f404142434445ull, {3,6,5,3,4,8,0,9}};
54 static const MYSTRUCT test_mystruct7 = {0x5a5b5c5d, 0x5e5f505152535455ull, {1,8,4,4,4,2,3,1}};
56 static const struct thin test_thin_struct = {-456, 78};
58 static const RECT test_rect1 = {1,2,3,4};
59 static const RECT test_rect2 = {5,6,7,8};
60 static const RECT test_rect3 = {9,10,11,12};
61 static const RECT test_rect4 = {13,14,15,16};
62 static const RECT test_rect5 = {17,18,19,20};
63 static const RECT test_rect6 = {21,22,23,24};
64 static const RECT test_rect7 = {25,26,27,28};
66 static const array_t test_array1 = {1,2,3,4};
67 static const array_t test_array2 = {5,6,7,8};
68 static const array_t test_array3 = {9,10,11,12};
69 static const array_t test_array4 = {13,14,15,16};
70 static const array_t test_array5 = {17,18,19,20};
71 static const array_t test_array6 = {21,22,23,24};
73 #define RELEASEMARSHALDATA WM_USER
75 struct host_object_data
77 IStream *stream;
78 IID iid;
79 IUnknown *object;
80 MSHLFLAGS marshal_flags;
81 HANDLE marshal_event;
82 IMessageFilter *filter;
85 static DWORD CALLBACK host_object_proc(LPVOID p)
87 struct host_object_data *data = p;
88 HRESULT hr;
89 MSG msg;
91 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
93 if (data->filter)
95 IMessageFilter * prev_filter = NULL;
96 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
97 if (prev_filter) IMessageFilter_Release(prev_filter);
98 ok_ole_success(hr, CoRegisterMessageFilter);
101 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
102 ok_ole_success(hr, CoMarshalInterface);
104 /* force the message queue to be created before signaling parent thread */
105 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
107 SetEvent(data->marshal_event);
109 while (GetMessageA(&msg, NULL, 0, 0))
111 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
113 trace("releasing marshal data\n");
114 CoReleaseMarshalData(data->stream);
115 SetEvent((HANDLE)msg.lParam);
117 else
118 DispatchMessageA(&msg);
121 HeapFree(GetProcessHeap(), 0, data);
123 CoUninitialize();
125 return hr;
128 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
130 DWORD tid = 0;
131 HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
132 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
134 data->stream = stream;
135 data->iid = *riid;
136 data->object = object;
137 data->marshal_flags = marshal_flags;
138 data->marshal_event = marshal_event;
139 data->filter = filter;
141 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
143 /* wait for marshaling to complete before returning */
144 WaitForSingleObject(marshal_event, INFINITE);
145 CloseHandle(marshal_event);
147 return tid;
150 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
152 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
155 #if 0 /* not used */
156 /* asks thread to release the marshal data because it has to be done by the
157 * same thread that marshaled the interface in the first place. */
158 static void release_host_object(DWORD tid)
160 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
161 PostThreadMessageA(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
162 WaitForSingleObject(event, INFINITE);
163 CloseHandle(event);
165 #endif
167 static void end_host_object(DWORD tid, HANDLE thread)
169 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
170 ok(ret, "PostThreadMessage failed with error %ld\n", GetLastError());
171 /* be careful of races - don't return until hosting thread has terminated */
172 WaitForSingleObject(thread, INFINITE);
173 CloseHandle(thread);
176 static int external_connections;
177 static BOOL expect_last_release_closes;
179 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
181 ok(0, "unexpected call\n");
182 *ppv = NULL;
183 return E_NOINTERFACE;
186 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
188 return 2;
191 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
193 return 1;
196 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
198 trace("add connection\n");
200 ok(extconn == EXTCONN_STRONG, "extconn = %ld\n", extconn);
201 ok(!reserved, "reserved = %lx\n", reserved);
202 return ++external_connections;
205 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
206 DWORD reserved, BOOL fLastReleaseCloses)
208 trace("release connection\n");
210 ok(extconn == EXTCONN_STRONG, "extconn = %ld\n", extconn);
211 ok(!reserved, "reserved = %lx\n", reserved);
213 ok(fLastReleaseCloses == expect_last_release_closes, "fLastReleaseCloses = %x, expected %x\n",
214 fLastReleaseCloses, expect_last_release_closes);
215 return --external_connections;
218 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
219 ExternalConnection_QueryInterface,
220 ExternalConnection_AddRef,
221 ExternalConnection_Release,
222 ExternalConnection_AddConnection,
223 ExternalConnection_ReleaseConnection
226 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
228 static ItestDual TestDual, TestDualDisp;
230 static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
232 return ItestDual_QueryInterface(&TestDual, riid, ppv);
235 static ULONG WINAPI TestSecondIface_AddRef(ITestSecondIface *iface)
237 return 2;
240 static ULONG WINAPI TestSecondIface_Release(ITestSecondIface *iface)
242 return 1;
245 static HRESULT WINAPI TestSecondIface_test(ITestSecondIface *iface)
247 return 1;
250 static const ITestSecondIfaceVtbl TestSecondIfaceVtbl = {
251 TestSecondIface_QueryInterface,
252 TestSecondIface_AddRef,
253 TestSecondIface_Release,
254 TestSecondIface_test
257 static ITestSecondIface TestSecondIface = { &TestSecondIfaceVtbl };
259 static HRESULT WINAPI TestSecondDisp_QueryInterface(ITestSecondDisp *iface, REFIID riid, void **ppv)
261 return ItestDual_QueryInterface(&TestDual, riid, ppv);
264 static ULONG WINAPI TestSecondDisp_AddRef(ITestSecondDisp *iface)
266 return 2;
269 static ULONG WINAPI TestSecondDisp_Release(ITestSecondDisp *iface)
271 return 1;
274 static HRESULT WINAPI TestSecondDisp_GetTypeInfoCount(ITestSecondDisp *iface, UINT *pctinfo)
276 ok(0, "unexpected call\n");
277 return E_NOTIMPL;
280 static HRESULT WINAPI TestSecondDisp_GetTypeInfo(ITestSecondDisp *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
282 ok(0, "unexpected call\n");
283 return E_NOTIMPL;
286 static HRESULT WINAPI TestSecondDisp_GetIDsOfNames(ITestSecondDisp *iface, REFIID riid, LPOLESTR *rgszNames,
287 UINT cNames, LCID lcid, DISPID *rgDispId)
289 ok(0, "unexpected call\n");
290 return E_NOTIMPL;
293 static HRESULT WINAPI TestSecondDisp_Invoke(ITestSecondDisp *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
294 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
295 UINT *puArgErr)
297 ok(0, "unexpected call\n");
298 return E_NOTIMPL;
301 static HRESULT WINAPI TestSecondDisp_test(ITestSecondDisp *iface)
303 ok(0, "unexpected call\n");
304 return E_NOTIMPL;
307 static ITestSecondDispVtbl TestSecondDispVtbl = {
308 TestSecondDisp_QueryInterface,
309 TestSecondDisp_AddRef,
310 TestSecondDisp_Release,
311 TestSecondDisp_GetTypeInfoCount,
312 TestSecondDisp_GetTypeInfo,
313 TestSecondDisp_GetIDsOfNames,
314 TestSecondDisp_Invoke,
315 TestSecondDisp_test
318 static ITestSecondDisp TestSecondDisp = { &TestSecondDispVtbl };
320 static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, void **ppvObject)
322 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) {
323 *ppvObject = &TestDualDisp;
324 return S_OK;
325 }else if(IsEqualGUID(riid, &IID_ItestDual)) {
326 *ppvObject = &TestDual;
327 return S_OK;
328 }else if(IsEqualGUID(riid, &IID_ITestSecondIface)) {
329 *ppvObject = &TestSecondIface;
330 return S_OK;
331 }else if(IsEqualGUID(riid, &IID_ITestSecondDisp)) {
332 *ppvObject = &TestSecondDisp;
333 return S_OK;
334 }else if (IsEqualGUID(riid, &IID_IExternalConnection)) {
335 trace("QI external connection\n");
336 *ppvObject = &ExternalConnection;
337 return S_OK;
340 *ppvObject = NULL;
341 return E_NOINTERFACE;
344 static ULONG WINAPI TestDual_AddRef(ItestDual *iface)
346 return 2;
349 static ULONG WINAPI TestDual_Release(ItestDual *iface)
351 return 1;
354 static HRESULT WINAPI TestDual_GetTypeInfoCount(ItestDual *iface, UINT *pctinfo)
356 ok(0, "unexpected call\n");
357 return E_NOTIMPL;
360 static HRESULT WINAPI TestDual_GetTypeInfo(ItestDual *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
362 ok(0, "unexpected call\n");
363 return E_NOTIMPL;
366 static HRESULT WINAPI TestDual_GetIDsOfNames(ItestDual *iface, REFIID riid, LPOLESTR *rgszNames,
367 UINT cNames, LCID lcid, DISPID *rgDispId)
369 ok(0, "unexpected call\n");
370 return E_NOTIMPL;
373 static HRESULT WINAPI TestDual_Invoke(ItestDual *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
374 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
375 UINT *puArgErr)
377 ok(0, "unexpected call\n");
378 return E_NOTIMPL;
381 static ItestDualVtbl TestDualVtbl = {
382 TestDual_QueryInterface,
383 TestDual_AddRef,
384 TestDual_Release,
385 TestDual_GetTypeInfoCount,
386 TestDual_GetTypeInfo,
387 TestDual_GetIDsOfNames,
388 TestDual_Invoke
391 static ItestDual TestDual = { &TestDualVtbl };
392 static ItestDual TestDualDisp = { &TestDualVtbl };
394 struct disp_obj
396 ISomethingFromDispatch ISomethingFromDispatch_iface;
397 LONG ref;
398 bool support_idispatch;
401 static inline struct disp_obj *impl_from_ISomethingFromDispatch(ISomethingFromDispatch *iface)
403 return CONTAINING_RECORD(iface, struct disp_obj, ISomethingFromDispatch_iface);
406 static HRESULT WINAPI disp_obj_QueryInterface(ISomethingFromDispatch *iface, REFIID iid, void **out)
408 struct disp_obj *obj = impl_from_ISomethingFromDispatch(iface);
410 if (!obj->support_idispatch)
411 ok(!IsEqualGUID(iid, &IID_IDispatch), "Expected no query for IDispatch.\n");
413 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IDispatch)
414 || IsEqualGUID(iid, &IID_ISomethingFromDispatch)
415 || IsEqualGUID(iid, &DIID_ItestIF4))
417 *out = iface;
418 ISomethingFromDispatch_AddRef(iface);
419 return S_OK;
422 *out = NULL;
423 return E_NOINTERFACE;
426 static ULONG WINAPI disp_obj_AddRef(ISomethingFromDispatch *iface)
428 struct disp_obj *obj = impl_from_ISomethingFromDispatch(iface);
429 return ++obj->ref;
432 static ULONG WINAPI disp_obj_Release(ISomethingFromDispatch *iface)
434 struct disp_obj *obj = impl_from_ISomethingFromDispatch(iface);
435 LONG ref = --obj->ref;
436 if (!ref)
437 CoTaskMemFree(obj);
438 return ref;
441 static HRESULT WINAPI disp_obj_GetTypeInfoCount(ISomethingFromDispatch *iface, UINT *count)
443 ok(0, "unexpected call\n");
444 return E_NOTIMPL;
447 static HRESULT WINAPI disp_obj_GetTypeInfo(ISomethingFromDispatch *iface,
448 UINT index, LCID lcid, ITypeInfo **typeinfo)
450 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
451 return 0xbeefdead;
454 static HRESULT WINAPI disp_obj_GetIDsOfNames(ISomethingFromDispatch *iface,
455 REFIID iid, LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
457 ok(0, "unexpected call\n");
458 return E_NOTIMPL;
461 static HRESULT WINAPI disp_obj_Invoke(ISomethingFromDispatch *iface, DISPID id, REFIID iid, LCID lcid,
462 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
464 ok(0, "unexpected call\n");
465 return E_NOTIMPL;
468 static HRESULT WINAPI disp_obj_anotherfn(ISomethingFromDispatch *iface)
470 return 0x01234567;
473 static const ISomethingFromDispatchVtbl disp_obj_vtbl =
475 disp_obj_QueryInterface,
476 disp_obj_AddRef,
477 disp_obj_Release,
478 disp_obj_GetTypeInfoCount,
479 disp_obj_GetTypeInfo,
480 disp_obj_GetIDsOfNames,
481 disp_obj_Invoke,
482 disp_obj_anotherfn,
485 static ISomethingFromDispatch *create_disp_obj2(bool support_idispatch)
487 struct disp_obj *obj = CoTaskMemAlloc(sizeof(*obj));
488 obj->ISomethingFromDispatch_iface.lpVtbl = &disp_obj_vtbl;
489 obj->ref = 1;
490 obj->support_idispatch = support_idispatch;
491 return &obj->ISomethingFromDispatch_iface;
494 static ISomethingFromDispatch *create_disp_obj(void)
496 return create_disp_obj2(true);
499 struct coclass_obj
501 ICoclass1 ICoclass1_iface;
502 ICoclass2 ICoclass2_iface;
503 LONG ref;
506 static inline struct coclass_obj *impl_from_ICoclass1(ICoclass1 *iface)
508 return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass1_iface);
511 static inline struct coclass_obj *impl_from_ICoclass2(ICoclass2 *iface)
513 return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass2_iface);
516 static HRESULT WINAPI coclass1_QueryInterface(ICoclass1 *iface, REFIID iid, void **out)
518 struct coclass_obj *obj = impl_from_ICoclass1(iface);
520 if (IsEqualGUID(iid, &IID_IUnknown)
521 || IsEqualGUID(iid, &IID_IDispatch)
522 || IsEqualGUID(iid, &IID_ICoclass1))
524 *out = iface;
525 ICoclass1_AddRef(iface);
526 return S_OK;
528 else if (IsEqualGUID(iid, &IID_ICoclass2))
530 *out = &obj->ICoclass2_iface;
531 ICoclass2_AddRef(*out);
532 return S_OK;
535 *out = NULL;
536 return E_NOINTERFACE;
539 static ULONG WINAPI coclass1_AddRef(ICoclass1 *iface)
541 struct coclass_obj *obj = impl_from_ICoclass1(iface);
542 return ++obj->ref;
545 static ULONG WINAPI coclass1_Release(ICoclass1 *iface)
547 struct coclass_obj *obj = impl_from_ICoclass1(iface);
548 LONG ref = --obj->ref;
549 if (!ref)
550 CoTaskMemFree(obj);
551 return ref;
554 static HRESULT WINAPI coclass1_GetTypeInfoCount(ICoclass1 *iface, UINT *count)
556 ok(0, "unexpected call\n");
557 return E_NOTIMPL;
560 static HRESULT WINAPI coclass1_GetTypeInfo(ICoclass1 *iface, UINT index,
561 LCID lcid, ITypeInfo **typeinfo)
563 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
564 return 0xbeefdead;
567 static HRESULT WINAPI coclass1_GetIDsOfNames(ICoclass1 *iface, REFIID iid,
568 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
570 ok(0, "unexpected call\n");
571 return E_NOTIMPL;
574 static HRESULT WINAPI coclass1_Invoke(ICoclass1 *iface, DISPID id, REFIID iid, LCID lcid,
575 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
577 ok(0, "unexpected call\n");
578 return E_NOTIMPL;
581 static HRESULT WINAPI coclass1_test(ICoclass1 *iface)
583 return 1;
586 static HRESULT WINAPI coclass2_QueryInterface(ICoclass2 *iface, REFIID iid, void **out)
588 struct coclass_obj *obj = impl_from_ICoclass2(iface);
589 return ICoclass1_QueryInterface(&obj->ICoclass1_iface, iid, out);
592 static ULONG WINAPI coclass2_AddRef(ICoclass2 *iface)
594 struct coclass_obj *obj = impl_from_ICoclass2(iface);
595 return ICoclass1_AddRef(&obj->ICoclass1_iface);
598 static ULONG WINAPI coclass2_Release(ICoclass2 *iface)
600 struct coclass_obj *obj = impl_from_ICoclass2(iface);
601 return ICoclass1_Release(&obj->ICoclass1_iface);
604 static HRESULT WINAPI coclass2_GetTypeInfoCount(ICoclass2 *iface, UINT *count)
606 ok(0, "unexpected call\n");
607 return E_NOTIMPL;
610 static HRESULT WINAPI coclass2_GetTypeInfo(ICoclass2 *iface, UINT index,
611 LCID lcid, ITypeInfo **typeinfo)
613 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
614 return 0xbeefdead;
617 static HRESULT WINAPI coclass2_GetIDsOfNames(ICoclass2 *iface, REFIID iid,
618 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
620 ok(0, "unexpected call\n");
621 return E_NOTIMPL;
624 static HRESULT WINAPI coclass2_Invoke(ICoclass2 *iface, DISPID id, REFIID iid, LCID lcid,
625 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
627 ok(0, "unexpected call\n");
628 return E_NOTIMPL;
631 static HRESULT WINAPI coclass2_test(ICoclass2 *iface)
633 return 2;
636 static const ICoclass1Vtbl coclass1_vtbl =
638 coclass1_QueryInterface,
639 coclass1_AddRef,
640 coclass1_Release,
641 coclass1_GetTypeInfoCount,
642 coclass1_GetTypeInfo,
643 coclass1_GetIDsOfNames,
644 coclass1_Invoke,
645 coclass1_test,
648 static const ICoclass2Vtbl coclass2_vtbl =
650 coclass2_QueryInterface,
651 coclass2_AddRef,
652 coclass2_Release,
653 coclass2_GetTypeInfoCount,
654 coclass2_GetTypeInfo,
655 coclass2_GetIDsOfNames,
656 coclass2_Invoke,
657 coclass2_test,
660 static struct coclass_obj *create_coclass_obj(void)
662 struct coclass_obj *obj = CoTaskMemAlloc(sizeof(*obj));
663 obj->ICoclass1_iface.lpVtbl = &coclass1_vtbl;
664 obj->ICoclass2_iface.lpVtbl = &coclass2_vtbl;
665 obj->ref = 1;
666 return obj;
669 static int testmode;
671 typedef struct Widget
673 IWidget IWidget_iface;
674 LONG refs;
675 IUnknown *pDispatchUnknown;
676 } Widget;
678 static inline Widget *impl_from_IWidget(IWidget *iface)
680 return CONTAINING_RECORD(iface, Widget, IWidget_iface);
683 static HRESULT WINAPI Widget_QueryInterface(
684 IWidget *iface,
685 /* [in] */ REFIID riid,
686 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
688 if (IsEqualIID(riid, &IID_IWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
690 IWidget_AddRef(iface);
691 *ppvObject = iface;
692 return S_OK;
694 else
696 *ppvObject = NULL;
697 return E_NOINTERFACE;
701 static ULONG WINAPI Widget_AddRef(
702 IWidget *iface)
704 Widget *This = impl_from_IWidget(iface);
706 return InterlockedIncrement(&This->refs);
709 static ULONG WINAPI Widget_Release(
710 IWidget *iface)
712 Widget *This = impl_from_IWidget(iface);
713 ULONG refs = InterlockedDecrement(&This->refs);
714 if (!refs)
716 IUnknown_Release(This->pDispatchUnknown);
717 memset(This, 0xcc, sizeof(*This));
718 HeapFree(GetProcessHeap(), 0, This);
719 trace("Widget destroyed!\n");
722 return refs;
725 static HRESULT WINAPI Widget_GetTypeInfoCount(
726 IWidget *iface,
727 /* [out] */ UINT __RPC_FAR *pctinfo)
729 Widget *This = impl_from_IWidget(iface);
730 IDispatch *pDispatch;
731 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
732 if (SUCCEEDED(hr))
734 hr = IDispatch_GetTypeInfoCount(pDispatch, pctinfo);
735 IDispatch_Release(pDispatch);
737 return hr;
740 static HRESULT WINAPI Widget_GetTypeInfo(
741 IWidget __RPC_FAR * iface,
742 /* [in] */ UINT iTInfo,
743 /* [in] */ LCID lcid,
744 /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
746 Widget *This = impl_from_IWidget(iface);
747 IDispatch *pDispatch;
748 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
749 if (SUCCEEDED(hr))
751 hr = IDispatch_GetTypeInfo(pDispatch, iTInfo, lcid, ppTInfo);
752 IDispatch_Release(pDispatch);
754 return hr;
757 static HRESULT WINAPI Widget_GetIDsOfNames(
758 IWidget __RPC_FAR * iface,
759 /* [in] */ REFIID riid,
760 /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
761 /* [in] */ UINT cNames,
762 /* [in] */ LCID lcid,
763 /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
765 Widget *This = impl_from_IWidget(iface);
766 IDispatch *pDispatch;
767 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
768 if (SUCCEEDED(hr))
770 hr = IDispatch_GetIDsOfNames(pDispatch, riid, rgszNames, cNames, lcid, rgDispId);
771 IDispatch_Release(pDispatch);
773 return hr;
776 static HRESULT WINAPI Widget_Invoke(
777 IWidget __RPC_FAR * iface,
778 /* [in] */ DISPID dispIdMember,
779 /* [in] */ REFIID riid,
780 /* [in] */ LCID lcid,
781 /* [in] */ WORD wFlags,
782 /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
783 /* [out] */ VARIANT __RPC_FAR *pVarResult,
784 /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
785 /* [out] */ UINT __RPC_FAR *puArgErr)
787 Widget *This = impl_from_IWidget(iface);
788 IDispatch *pDispatch;
789 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
790 if (SUCCEEDED(hr))
792 hr = IDispatch_Invoke(pDispatch, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
793 IDispatch_Release(pDispatch);
795 return hr;
798 static HRESULT WINAPI Widget_put_Name(
799 IWidget __RPC_FAR * iface,
800 /* [in] */ BSTR name)
802 trace("put_Name(%s)\n", wine_dbgstr_w(name));
803 return S_OK;
806 static HRESULT WINAPI Widget_get_Name(
807 IWidget __RPC_FAR * iface,
808 /* [out] */ BSTR __RPC_FAR *name)
810 static const WCHAR szCat[] = { 'C','a','t',0 };
811 trace("get_Name()\n");
812 *name = SysAllocString(szCat);
813 return S_OK;
816 static HRESULT WINAPI Widget_DoSomething(
817 IWidget __RPC_FAR * iface,
818 /* [in] */ double number,
819 /* [out] */ BSTR *str1,
820 /* [defaultvalue][in] */ BSTR str2,
821 /* [optional][in] */ VARIANT __RPC_FAR *opt)
823 static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
824 trace("DoSomething()\n");
826 ok(number == 3.141, "number(%f) != 3.141\n", number);
827 ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
828 ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt));
829 ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08lx\n", V_ERROR(opt));
830 *str1 = SysAllocString(szString);
832 return S_FALSE;
835 static HRESULT WINAPI Widget_get_State(
836 IWidget __RPC_FAR * iface,
837 /* [retval][out] */ STATE __RPC_FAR *state)
839 trace("get_State() = STATE_WIDGETIFIED\n");
840 *state = STATE_WIDGETIFIED;
841 return S_OK;
844 static HRESULT WINAPI Widget_put_State(
845 IWidget __RPC_FAR * iface,
846 /* [in] */ STATE state)
848 trace("put_State(%d)\n", state);
849 return S_OK;
852 static HRESULT WINAPI Widget_Map(
853 IWidget * iface,
854 BSTR bstrId,
855 BSTR *sValue)
857 trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId), sValue);
858 *sValue = SysAllocString(bstrId);
859 return S_OK;
862 static HRESULT WINAPI Widget_SetOleColor(
863 IWidget * iface,
864 OLE_COLOR val)
866 trace("SetOleColor(0x%lx)\n", val);
867 return S_OK;
870 static HRESULT WINAPI Widget_GetOleColor(
871 IWidget * iface,
872 OLE_COLOR *pVal)
874 trace("GetOleColor() = 0x8000000f\n");
875 *pVal = 0x8000000f;
876 return S_FALSE;
879 static HRESULT WINAPI Widget_Clone(
880 IWidget *iface,
881 IWidget **ppVal)
883 trace("Clone()\n");
884 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
887 static HRESULT WINAPI Widget_CloneDispatch(
888 IWidget *iface,
889 IDispatch **ppVal)
891 trace("CloneDispatch()\n");
892 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
895 static HRESULT WINAPI Widget_CloneCoclass(
896 IWidget *iface,
897 ApplicationObject2 **ppVal)
899 trace("CloneCoclass()\n");
900 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
903 static HRESULT WINAPI Widget_Value(
904 IWidget __RPC_FAR * iface,
905 VARIANT *value,
906 VARIANT *retval)
908 trace("Value(%p, %p)\n", value, retval);
909 ok(V_VT(value) == VT_I2, "V_VT(value) was %d instead of VT_I2\n", V_VT(value));
910 ok(V_I2(value) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value));
911 V_VT(retval) = VT_I2;
912 V_I2(retval) = 1234;
913 return S_OK;
916 static HRESULT WINAPI Widget_VariantArrayPtr(
917 IWidget * iface,
918 SAFEARRAY ** values)
920 trace("VariantArrayPtr(%p)\n", values);
921 return S_OK;
924 static HRESULT WINAPI Widget_VarArg(
925 IWidget * iface,
926 int numexpect,
927 SAFEARRAY * values)
929 LONG lbound, ubound, i;
930 VARIANT * data;
931 HRESULT hr;
933 trace("VarArg(%p)\n", values);
935 ok( values->cDims == 1, "wrong cDims %u\n", values->cDims );
936 ok( values->cbElements == (numexpect ? sizeof(VARIANT) : 0),
937 "wrong cbElements %lu\n", values->cbElements );
939 hr = SafeArrayGetLBound(values, 1, &lbound);
940 ok(hr == S_OK, "SafeArrayGetLBound failed with %lx\n", hr);
941 ok(lbound == 0, "SafeArrayGetLBound returned %ld\n", lbound);
943 hr = SafeArrayGetUBound(values, 1, &ubound);
944 ok(hr == S_OK, "SafeArrayGetUBound failed with %lx\n", hr);
945 ok(ubound == numexpect-1, "SafeArrayGetUBound returned %ld, but expected %d\n", ubound, numexpect-1);
947 hr = SafeArrayAccessData(values, (LPVOID)&data);
948 ok(hr == S_OK, "SafeArrayAccessData failed with %lx\n", hr);
950 for (i=0; i<=ubound-lbound; i++)
952 ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%ld]) was %d\n", i, V_VT(&data[i]));
953 ok(V_I4(&data[i]) == i, "V_I4(&data[%ld]) was %ld\n", i, V_I4(&data[i]));
956 hr = SafeArrayUnaccessData(values);
957 ok(hr == S_OK, "SafeArrayUnaccessData failed with %lx\n", hr);
959 return S_OK;
962 static HRESULT WINAPI Widget_Error(
963 IWidget __RPC_FAR * iface)
965 trace("Error()\n");
966 return E_NOTIMPL;
969 static HRESULT WINAPI Widget_CloneInterface(
970 IWidget __RPC_FAR * iface,
971 ISomethingFromDispatch **ppVal)
973 trace("CloneInterface()\n");
974 *ppVal = 0;
975 return S_OK;
978 static HRESULT WINAPI Widget_put_prop_with_lcid(
979 IWidget* iface, LONG lcid, INT i)
981 trace("put_prop_with_lcid(%08lx, %x)\n", lcid, i);
982 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08lx\n", lcid);
983 ok(i == 0xcafe, "got %08x\n", i);
984 return S_OK;
987 static HRESULT WINAPI Widget_get_prop_with_lcid(
988 IWidget* iface, LONG lcid, INT *i)
990 trace("get_prop_with_lcid(%08lx, %p)\n", lcid, i);
991 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08lx\n", lcid);
992 *i = lcid;
993 return S_OK;
996 static HRESULT WINAPI Widget_get_prop_int(
997 IWidget* iface, INT *i)
999 trace("get_prop_int(%p)\n", i);
1000 *i = -13;
1001 return S_OK;
1004 static HRESULT WINAPI Widget_get_prop_uint(
1005 IWidget* iface, UINT *i)
1007 trace("get_prop_uint(%p)\n", i);
1008 *i = 42;
1009 return S_OK;
1012 static HRESULT WINAPI Widget_ByRefUInt(
1013 IWidget* iface, UINT *i)
1015 *i = 42;
1016 return S_OK;
1019 static HRESULT WINAPI Widget_put_prop_opt_arg(
1020 IWidget* iface, INT opt, INT i)
1022 trace("put_prop_opt_arg(%08x, %08x)\n", opt, i);
1023 todo_wine ok(opt == 0, "got opt=%08x\n", opt);
1024 ok(i == 0xcafe, "got i=%08x\n", i);
1025 return S_OK;
1028 static HRESULT WINAPI Widget_put_prop_req_arg(
1029 IWidget* iface, INT req, INT i)
1031 trace("put_prop_req_arg(%08x, %08x)\n", req, i);
1032 ok(req == 0x5678, "got req=%08x\n", req);
1033 ok(i == 0x1234, "got i=%08x\n", i);
1034 return S_OK;
1037 static HRESULT WINAPI Widget_pos_restrict(IWidget* iface, INT *i)
1039 trace("restrict\n");
1040 *i = DISPID_TM_RESTRICTED;
1041 return S_OK;
1044 static HRESULT WINAPI Widget_neg_restrict(IWidget* iface, INT *i)
1046 trace("neg_restrict\n");
1047 *i = DISPID_TM_NEG_RESTRICTED;
1048 return S_OK;
1051 static HRESULT WINAPI Widget_VarArg_Run(
1052 IWidget *iface, BSTR name, SAFEARRAY *params, VARIANT *result)
1054 static const WCHAR catW[] = { 'C','a','t',0 };
1055 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1056 LONG bound;
1057 VARIANT *var;
1058 BSTR bstr;
1059 HRESULT hr;
1061 trace("VarArg_Run(%p,%p,%p)\n", name, params, result);
1063 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1065 if (!params->cbElements) /* no varargs */
1067 hr = SafeArrayGetUBound(params, 1, &bound);
1068 ok(hr == S_OK, "SafeArrayGetUBound error %#lx\n", hr);
1069 ok(bound == -1, "expected -1, got %ld\n", bound);
1070 return S_OK;
1073 ok( params->cbElements == sizeof(VARIANT), "wrong cbElements %lu\n", params->cbElements );
1075 hr = SafeArrayGetLBound(params, 1, &bound);
1076 ok(hr == S_OK, "SafeArrayGetLBound error %#lx\n", hr);
1077 ok(bound == 0, "expected 0, got %ld\n", bound);
1079 hr = SafeArrayGetUBound(params, 1, &bound);
1080 ok(hr == S_OK, "SafeArrayGetUBound error %#lx\n", hr);
1081 ok(bound == 0, "expected 0, got %ld\n", bound);
1083 hr = SafeArrayAccessData(params, (void **)&var);
1084 ok(hr == S_OK, "SafeArrayAccessData failed with %lx\n", hr);
1086 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1087 bstr = V_BSTR(&var[0]);
1088 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1090 hr = SafeArrayUnaccessData(params);
1091 ok(hr == S_OK, "SafeArrayUnaccessData error %#lx\n", hr);
1093 return S_OK;
1096 static HRESULT WINAPI Widget_VarArg_Ref_Run(
1097 IWidget *iface, BSTR name, SAFEARRAY **params, VARIANT *result)
1099 static const WCHAR catW[] = { 'C','a','t',0 };
1100 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1101 LONG bound;
1102 VARIANT *var;
1103 BSTR bstr;
1104 HRESULT hr;
1106 trace("VarArg_Ref_Run(%p,%p,%p)\n", name, params, result);
1108 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1110 if (!(*params)->cbElements) /* no varargs */
1112 hr = SafeArrayGetUBound(*params, 1, &bound);
1113 ok(hr == S_OK, "SafeArrayGetUBound error %#lx\n", hr);
1114 ok(bound == -1, "expected -1, got %ld\n", bound);
1115 return S_OK;
1118 ok( (*params)->cbElements == sizeof(VARIANT), "wrong cbElements %lu\n", (*params)->cbElements );
1120 hr = SafeArrayGetLBound(*params, 1, &bound);
1121 ok(hr == S_OK, "SafeArrayGetLBound error %#lx\n", hr);
1122 ok(bound == 0, "expected 0, got %ld\n", bound);
1124 hr = SafeArrayGetUBound(*params, 1, &bound);
1125 ok(hr == S_OK, "SafeArrayGetUBound error %#lx\n", hr);
1126 ok(bound == 0, "expected 0, got %ld\n", bound);
1128 hr = SafeArrayAccessData(*params, (void **)&var);
1129 ok(hr == S_OK, "SafeArrayAccessData error %#lx\n", hr);
1131 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1132 bstr = V_BSTR(&var[0]);
1133 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1135 hr = SafeArrayUnaccessData(*params);
1136 ok(hr == S_OK, "SafeArrayUnaccessData error %#lx\n", hr);
1138 return S_OK;
1141 static HRESULT WINAPI Widget_basetypes_in(IWidget *iface, signed char c, short s, LONG l, hyper h,
1142 unsigned char uc, unsigned short us, ULONG ul, MIDL_uhyper uh,
1143 float f, double d, STATE st)
1145 ok(c == 5, "Got char %d.\n", c);
1146 ok(s == -123, "Got short %d.\n", s);
1147 ok(l == -100000, "Got int %ld.\n", l);
1148 ok(h == (LONGLONG)-100000 * 1000000, "Got hyper %s.\n", wine_dbgstr_longlong(h));
1149 ok(uc == 0, "Got unsigned char %u.\n", uc);
1150 ok(us == 456, "Got unsigned short %u.\n", us);
1151 ok(ul == 0xdeadbeef, "Got unsigned int %lu.\n", ul);
1152 ok(uh == (ULONGLONG)1234567890 * 9876543210, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
1153 ok(f == (float)M_PI, "Got float %f.\n", f);
1154 ok(d == M_E, "Got double %f.\n", d);
1155 ok(st == STATE_WIDGETIFIED, "Got state %u.\n", st);
1157 return S_OK;
1160 static HRESULT WINAPI Widget_basetypes_out(IWidget *iface, signed char *c, short *s, LONG *l, hyper *h,
1161 unsigned char *uc, unsigned short *us, ULONG *ul, MIDL_uhyper *uh,
1162 float *f, double *d, STATE *st)
1164 *c = 10;
1165 *s = -321;
1166 *l = -200000;
1167 *h = (LONGLONG)-200000 * 1000000;
1168 *uc = 254;
1169 *us = 256;
1170 *ul = 0xf00dfade;
1171 *uh = 0xabcdef0123456789ull;
1172 *f = M_LN2;
1173 *d = M_LN10;
1174 *st = STATE_UNWIDGETIFIED;
1176 return S_OK;
1179 static HRESULT WINAPI Widget_float_abi(IWidget *iface, float f, double d, int i, float f2, double d2)
1181 ok(f == 1.0f, "Got float %f.\n", f);
1182 ok(d == 2.0, "Got double %f.\n", d);
1183 ok(i == 3, "Got int %d.\n", i);
1184 ok(f2 == 4.0f, "Got float %f.\n", f2);
1185 ok(d2 == 5.0, "Got double %f.\n", d2);
1187 return S_OK;
1190 static HRESULT WINAPI Widget_long_ptr(IWidget *iface, LONG *in, LONG *out, LONG *in_out)
1192 ok(*in == 123, "Got [in] %ld.\n", *in);
1193 if (testmode == 0) /* Invoke() */
1194 ok(*out == 456, "Got [out] %ld.\n", *out);
1195 else if (testmode == 1)
1196 ok(!*out, "Got [out] %ld.\n", *out);
1197 ok(*in_out == 789, "Got [in, out] %ld.\n", *in_out);
1199 *in = 987;
1200 *out = 654;
1201 *in_out = 321;
1203 return S_OK;
1206 static HRESULT WINAPI Widget_long_ptr_ptr(IWidget *iface, LONG **in, LONG **out, LONG **in_out)
1208 ok(!*out, "Got [out] %p.\n", *out);
1209 if (testmode == 0)
1211 ok(!*in, "Got [in] %p.\n", *in);
1212 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1214 else if (testmode == 1)
1216 ok(!*in, "Got [in] %p.\n", *in);
1217 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1219 *out = CoTaskMemAlloc(sizeof(int));
1220 **out = 654;
1221 *in_out = CoTaskMemAlloc(sizeof(int));
1222 **in_out = 321;
1224 else if (testmode == 2)
1226 ok(**in == 123, "Got [in] %ld.\n", **in);
1227 ok(**in_out == 789, "Got [in, out] %ld.\n", **in_out);
1229 *out = CoTaskMemAlloc(sizeof(int));
1230 **out = 654;
1231 **in_out = 321;
1233 else if (testmode == 3)
1235 ok(**in_out == 789, "Got [in, out] %ld.\n", **in_out);
1236 *in_out = NULL;
1239 return S_OK;
1242 /* Call methods to check that we have valid proxies to each interface. */
1243 static void check_iface_marshal(IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1245 ISomethingFromDispatch *sfd2;
1246 ITypeInfo *typeinfo;
1247 HRESULT hr;
1249 hr = IUnknown_QueryInterface(unk, &IID_ISomethingFromDispatch, (void **)&sfd2);
1250 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1251 ISomethingFromDispatch_Release(sfd2);
1253 hr = IDispatch_GetTypeInfo(disp, 0xdeadbeef, 0, &typeinfo);
1254 ok(hr == 0xbeefdead, "Got hr %#lx.\n", hr);
1256 hr = ISomethingFromDispatch_anotherfn(sfd);
1257 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
1260 static HRESULT WINAPI Widget_iface_in(IWidget *iface, IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1262 if (testmode == 0)
1263 check_iface_marshal(unk, disp, sfd);
1264 else if (testmode == 1)
1266 ok(!unk, "Got iface %p.\n", unk);
1267 ok(!disp, "Got iface %p.\n", disp);
1268 ok(!sfd, "Got iface %p.\n", sfd);
1270 return S_OK;
1273 static HRESULT WINAPI Widget_iface_out(IWidget *iface, IUnknown **unk, IDispatch **disp, ISomethingFromDispatch **sfd)
1275 ok(!*unk, "Got iface %p.\n", *unk);
1276 ok(!*disp, "Got iface %p.\n", *disp);
1277 ok(!*sfd, "Got iface %p.\n", *sfd);
1279 if (testmode == 0)
1281 *unk = (IUnknown *)create_disp_obj();
1282 *disp = (IDispatch *)create_disp_obj();
1283 *sfd = create_disp_obj();
1285 return S_OK;
1288 static HRESULT WINAPI Widget_iface_ptr(IWidget *iface, ISomethingFromDispatch **in,
1289 ISomethingFromDispatch **out, ISomethingFromDispatch **in_out)
1291 HRESULT hr;
1293 ok(!*out, "Got [out] %p.\n", *out);
1294 if (testmode == 0 || testmode == 1)
1296 hr = ISomethingFromDispatch_anotherfn(*in);
1297 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
1298 hr = ISomethingFromDispatch_anotherfn(*in_out);
1299 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
1302 if (testmode == 1)
1304 *out = create_disp_obj();
1305 ISomethingFromDispatch_Release(*in_out);
1306 *in_out = create_disp_obj();
1308 else if (testmode == 2)
1310 ok(!*in, "Got [in] %p.\n", *in);
1311 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1312 *in_out = create_disp_obj();
1314 else if (testmode == 3)
1316 hr = ISomethingFromDispatch_anotherfn(*in_out);
1317 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
1318 ISomethingFromDispatch_Release(*in_out);
1319 *in_out = NULL;
1322 return S_OK;
1325 static HRESULT WINAPI Widget_iface_noptr(IWidget *iface, IUnknown unk, IDispatch disp, ISomethingFromDispatch sfd)
1327 check_iface_marshal((IUnknown *)unk.lpVtbl, (IDispatch *)disp.lpVtbl, (ISomethingFromDispatch *)sfd.lpVtbl);
1328 return S_OK;
1331 static HRESULT WINAPI Widget_bstr(IWidget *iface, BSTR in, BSTR *out, BSTR *in_ptr, BSTR *in_out)
1333 UINT len;
1335 if (testmode == 0)
1337 len = SysStringByteLen(in);
1338 ok(len == sizeof(test_bstr1), "Got wrong length %u.\n", len);
1339 ok(!memcmp(in, test_bstr1, len), "Got string %s.\n", wine_dbgstr_wn(in, len / sizeof(WCHAR)));
1340 ok(!*out, "Got unexpected output %p.\n", *out);
1341 len = SysStringLen(*in_ptr);
1342 ok(len == lstrlenW(test_bstr2), "Got wrong length %u.\n", len);
1343 ok(!memcmp(*in_ptr, test_bstr2, len), "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1344 len = SysStringLen(*in_out);
1345 ok(len == lstrlenW(test_bstr3), "Got wrong length %u.\n", len);
1346 ok(!memcmp(*in_out, test_bstr3, len), "Got string %s.\n", wine_dbgstr_w(*in_out));
1348 *out = SysAllocString(test_bstr4);
1349 in[1] = (*in_ptr)[1] = (*in_out)[1] = 'X';
1351 else if (testmode == 1)
1353 ok(!in, "Got string %s.\n", wine_dbgstr_w(in));
1354 ok(!*out, "Got string %s.\n", wine_dbgstr_w(*out));
1355 ok(!*in_ptr, "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1356 ok(!*in_out, "Got string %s.\n", wine_dbgstr_w(*in_out));
1358 return S_OK;
1361 static HRESULT WINAPI Widget_variant(IWidget *iface, VARIANT in, VARIANT *out, VARIANT *in_ptr, VARIANT *in_out)
1363 ok(V_VT(&in) == VT_CY, "Got wrong type %#x.\n", V_VT(&in));
1364 ok(V_CY(&in).Hi == 0xdababe && V_CY(&in).Lo == 0xdeadbeef,
1365 "Got wrong value %s.\n", wine_dbgstr_longlong(V_CY(&in).int64));
1366 if (testmode == 0)
1368 ok(V_VT(out) == VT_I4, "Got wrong type %u.\n", V_VT(out));
1369 ok(V_I4(out) == 1, "Got wrong value %ld.\n", V_I4(out));
1371 else
1372 ok(V_VT(out) == VT_EMPTY, "Got wrong type %u.\n", V_VT(out));
1373 ok(V_VT(in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(in_ptr));
1374 ok(V_I4(in_ptr) == -1, "Got wrong value %ld.\n", V_I4(in_ptr));
1375 ok(V_VT(in_out) == VT_BSTR, "Got wrong type %u.\n", V_VT(in_out));
1376 ok(!lstrcmpW(V_BSTR(in_out), test_bstr2), "Got wrong value %s.\n",
1377 wine_dbgstr_w(V_BSTR(in_out)));
1379 V_VT(&in) = VT_I4;
1380 V_I4(&in) = 2;
1381 V_VT(out) = VT_UI1;
1382 V_UI1(out) = 3;
1383 V_VT(in_ptr) = VT_I2;
1384 V_I2(in_ptr) = 4;
1385 VariantClear(in_out);
1386 V_VT(in_out) = VT_I1;
1387 V_I1(in_out) = 5;
1388 return S_OK;
1391 static SAFEARRAY *make_safearray(ULONG len)
1393 SAFEARRAY *sa = SafeArrayCreateVector(VT_I4, 0, len);
1394 int i, *data;
1396 SafeArrayAccessData(sa, (void **)&data);
1397 for (i = 0; i < len; ++i)
1398 data[i] = len + i;
1399 SafeArrayUnaccessData(sa);
1401 return sa;
1404 static void check_safearray(SAFEARRAY *sa, LONG expect)
1406 LONG len, i, *data;
1407 HRESULT hr;
1409 hr = SafeArrayGetUBound(sa, 1, &len);
1410 len++;
1411 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1412 ok(len == expect, "Expected len %ld, got %ld.\n", expect, len);
1414 hr = SafeArrayAccessData(sa, (void **)&data);
1415 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1417 for (i = 0; i < len; ++i)
1418 ok(data[i] == len + i, "Expected data %ld at %ld, got %ld.\n", len + i, i, data[i]);
1420 SafeArrayUnaccessData(sa);
1423 static HRESULT WINAPI Widget_safearray(IWidget *iface, SAFEARRAY *in, SAFEARRAY **out, SAFEARRAY **in_ptr, SAFEARRAY **in_out)
1425 HRESULT hr;
1427 check_safearray(in, 3);
1428 ok(!*out, "Got array %p.\n", *out);
1429 check_safearray(*in_ptr, 7);
1430 check_safearray(*in_out, 9);
1432 hr = SafeArrayDestroy(*in_out);
1433 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1435 *out = make_safearray(4);
1436 *in_out = make_safearray(6);
1438 return S_OK;
1441 static HRESULT WINAPI Widget_mystruct(IWidget *iface, MYSTRUCT in, MYSTRUCT *out, MYSTRUCT *in_ptr, MYSTRUCT *in_out)
1443 static const MYSTRUCT empty = {0};
1444 ok(!memcmp(&in, &test_mystruct1, sizeof(in)), "Structs didn't match.\n");
1445 ok(!memcmp(out, &empty, sizeof(*out)), "Structs didn't match.\n");
1446 ok(!memcmp(in_ptr, &test_mystruct3, sizeof(*in_ptr)), "Structs didn't match.\n");
1447 ok(!memcmp(in_out, &test_mystruct4, sizeof(*in_out)), "Structs didn't match.\n");
1449 memcpy(out, &test_mystruct5, sizeof(*out));
1450 memcpy(in_ptr, &test_mystruct6, sizeof(*in_ptr));
1451 memcpy(in_out, &test_mystruct7, sizeof(*in_out));
1452 return S_OK;
1455 static HRESULT WINAPI Widget_mystruct_ptr_ptr(IWidget *iface, MYSTRUCT **in)
1457 ok(!memcmp(*in, &test_mystruct1, sizeof(**in)), "Structs didn't match.\n");
1458 return S_OK;
1461 static HRESULT WINAPI Widget_thin_struct(IWidget *iface, struct thin in)
1463 ok(!memcmp(&in, &test_thin_struct, sizeof(in)), "Structs didn't match.\n");
1464 return S_OK;
1467 static HRESULT WINAPI Widget_rect(IWidget *iface, RECT in, RECT *out, RECT *in_ptr, RECT *in_out)
1469 static const RECT empty = {0};
1470 ok(EqualRect(&in, &test_rect1), "Rects didn't match.\n");
1471 ok(EqualRect(out, &empty), "Rects didn't match.\n");
1472 ok(EqualRect(in_ptr, &test_rect3), "Rects didn't match.\n");
1473 ok(EqualRect(in_out, &test_rect4), "Rects didn't match.\n");
1475 *out = test_rect5;
1476 *in_ptr = test_rect6;
1477 *in_out = test_rect7;
1478 return S_OK;
1481 static HRESULT WINAPI Widget_complex_struct(IWidget *iface, struct complex in)
1483 HRESULT hr;
1485 ok(in.c == 98, "Got char %d.\n", in.c);
1486 ok(in.i == 76543, "Got int %d.\n", in.i);
1487 ok(*in.pi == 2, "Got int pointer %d.\n", *in.pi);
1488 ok(**in.ppi == 10, "Got int double pointer %d.\n", **in.ppi);
1489 hr = ISomethingFromDispatch_anotherfn(in.iface);
1490 ok(hr == 0x01234567, "Got wrong hr %#lx.\n", hr);
1491 hr = ISomethingFromDispatch_anotherfn(*in.iface_ptr);
1492 ok(hr == 0x01234567, "Got wrong hr %#lx.\n", hr);
1493 ok(!lstrcmpW(in.bstr, test_bstr2), "Got string %s.\n", wine_dbgstr_w(in.bstr));
1494 ok(V_VT(&in.var) == VT_I4, "Got wrong type %u.\n", V_VT(&in.var));
1495 ok(V_I4(&in.var) == 123, "Got wrong value %ld.\n", V_I4(&in.var));
1496 ok(!memcmp(&in.mystruct, &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1497 ok(!memcmp(in.arr, test_array1, sizeof(array_t)), "Arrays didn't match.\n");
1498 ok(in.myint == 456, "Got int %d.\n", in.myint);
1500 return S_OK;
1503 static HRESULT WINAPI Widget_array(IWidget *iface, array_t in, array_t out, array_t in_out)
1505 static const array_t empty = {0};
1506 ok(!memcmp(in, test_array1, sizeof(array_t)), "Arrays didn't match.\n");
1507 ok(!memcmp(out, empty, sizeof(array_t)), "Arrays didn't match.\n");
1508 ok(!memcmp(in_out, test_array3, sizeof(array_t)), "Arrays didn't match.\n");
1510 memcpy(in, test_array4, sizeof(array_t));
1511 memcpy(out, test_array5, sizeof(array_t));
1512 memcpy(in_out, test_array6, sizeof(array_t));
1514 return S_OK;
1517 static HRESULT WINAPI Widget_variant_array(IWidget *iface, VARIANT in[2], VARIANT out[2], VARIANT in_out[2])
1519 ok(V_VT(&in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in[0]));
1520 ok(V_I4(&in[0]) == 1, "Got wrong value %ld.\n", V_I4(&in[0]));
1521 ok(V_VT(&in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&in[1]));
1522 ok(*V_I4REF(&in[1]) == 2, "Got wrong value %ld.\n", *V_I4REF(&in[1]));
1523 ok(V_VT(&out[0]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[0]));
1524 ok(V_VT(&out[1]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[1]));
1525 ok(V_VT(&in_out[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in_out[0]));
1526 ok(V_I4(&in_out[0]) == 5, "Got wrong type %u.\n", V_VT(&in_out[0]));
1527 ok(V_VT(&in_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&in_out[1]));
1528 ok(!lstrcmpW(V_BSTR(&in_out[1]), test_bstr1), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&in[1])));
1530 V_VT(&in[0]) = VT_I1; V_I1(&in[0]) = 7;
1531 V_VT(&in[1]) = VT_I1; V_I1(&in[1]) = 8;
1532 V_VT(&out[0]) = VT_I1; V_I1(&out[0]) = 9;
1533 V_VT(&out[1]) = VT_BSTR; V_BSTR(&out[1]) = SysAllocString(test_bstr2);
1534 V_VT(&in_out[0]) = VT_I1; V_I1(&in_out[0]) = 11;
1535 V_VT(&in_out[1]) = VT_UNKNOWN; V_UNKNOWN(&in_out[1]) = (IUnknown *)create_disp_obj();
1537 return S_OK;
1540 static HRESULT WINAPI Widget_mystruct_array(IWidget *iface, MYSTRUCT in[2])
1542 ok(!memcmp(&in[0], &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1543 ok(!memcmp(&in[1], &test_mystruct2, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1544 return S_OK;
1547 static HRESULT WINAPI Widget_myint(IWidget *iface, myint_t val, myint_t *ptr, myint_t **ptr_ptr)
1549 ok(val == 123, "Got value %d.\n", val);
1550 ok(*ptr == 456, "Got single ptr ref %d.\n", *ptr);
1551 ok(**ptr_ptr == 789, "Got double ptr ref %d.\n", **ptr_ptr);
1552 return S_OK;
1555 static HRESULT WINAPI Widget_Coclass(IWidget *iface, Coclass1 *class1, Coclass2 *class2, Coclass3 *class3)
1557 HRESULT hr;
1559 hr = ICoclass1_test((ICoclass1 *)class1);
1560 ok(hr == 1, "Got hr %#lx.\n", hr);
1562 hr = ICoclass2_test((ICoclass2 *)class2);
1563 ok(hr == 2, "Got hr %#lx.\n", hr);
1565 hr = ICoclass1_test((ICoclass1 *)class3);
1566 ok(hr == 1, "Got hr %#lx.\n", hr);
1568 return S_OK;
1571 static HRESULT WINAPI Widget_Coclass_ptr(IWidget *iface, Coclass1 **in, Coclass1 **out, Coclass1 **in_out)
1573 struct coclass_obj *obj;
1574 HRESULT hr;
1576 ok(!*out, "Got [out] %p.\n", *out);
1577 if (testmode == 0 || testmode == 1)
1579 hr = ICoclass1_test((ICoclass1 *)*in);
1580 ok(hr == 1, "Got hr %#lx.\n", hr);
1581 hr = ICoclass1_test((ICoclass1 *)*in_out);
1582 ok(hr == 1, "Got hr %#lx.\n", hr);
1585 if (testmode == 1)
1587 obj = create_coclass_obj();
1588 *out = (Coclass1 *)&obj->ICoclass1_iface;
1590 ICoclass1_Release((ICoclass1 *)*in_out);
1591 obj = create_coclass_obj();
1592 *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1594 else if (testmode == 2)
1596 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1597 obj = create_coclass_obj();
1598 *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1600 else if (testmode == 3)
1602 hr = ICoclass1_test((ICoclass1 *)*in_out);
1603 ok(hr == 1, "Got hr %#lx.\n", hr);
1604 ICoclass1_Release((ICoclass1 *)*in_out);
1605 *in_out = NULL;
1608 return S_OK;
1611 static HRESULT WINAPI Widget_Coclass_noptr(IWidget *iface, Coclass1 class1, Coclass2 class2, Coclass3 class3)
1613 HRESULT hr;
1615 hr = ICoclass1_test(class1.iface);
1616 ok(hr == 1, "Got hr %#lx.\n", hr);
1618 hr = ICoclass2_test(class2.iface);
1619 ok(hr == 2, "Got hr %#lx.\n", hr);
1621 hr = ICoclass1_test(class3.iface);
1622 ok(hr == 1, "Got hr %#lx.\n", hr);
1624 return S_OK;
1627 static HRESULT WINAPI Widget_no_in_out(IWidget *iface, BSTR str, int i)
1629 ok(SysStringLen(str) == 4, "unexpected len\n");
1630 ok(!lstrcmpW(str, L"test"), "unexpected str %s\n", wine_dbgstr_w(str));
1631 ok(i == 5, "i = %d\n", i);
1632 return S_OK;
1635 static const struct IWidgetVtbl Widget_VTable =
1637 Widget_QueryInterface,
1638 Widget_AddRef,
1639 Widget_Release,
1640 Widget_GetTypeInfoCount,
1641 Widget_GetTypeInfo,
1642 Widget_GetIDsOfNames,
1643 Widget_Invoke,
1644 Widget_put_Name,
1645 Widget_get_Name,
1646 Widget_DoSomething,
1647 Widget_get_State,
1648 Widget_put_State,
1649 Widget_Map,
1650 Widget_SetOleColor,
1651 Widget_GetOleColor,
1652 Widget_Clone,
1653 Widget_CloneDispatch,
1654 Widget_CloneCoclass,
1655 Widget_Value,
1656 Widget_VariantArrayPtr,
1657 Widget_VarArg,
1658 Widget_Error,
1659 Widget_CloneInterface,
1660 Widget_put_prop_with_lcid,
1661 Widget_get_prop_with_lcid,
1662 Widget_get_prop_int,
1663 Widget_get_prop_uint,
1664 Widget_ByRefUInt,
1665 Widget_put_prop_opt_arg,
1666 Widget_put_prop_req_arg,
1667 Widget_pos_restrict,
1668 Widget_neg_restrict,
1669 Widget_VarArg_Run,
1670 Widget_VarArg_Ref_Run,
1671 Widget_basetypes_in,
1672 Widget_basetypes_out,
1673 Widget_float_abi,
1674 Widget_long_ptr,
1675 Widget_long_ptr_ptr,
1676 Widget_iface_in,
1677 Widget_iface_out,
1678 Widget_iface_ptr,
1679 Widget_iface_noptr,
1680 Widget_bstr,
1681 Widget_variant,
1682 Widget_safearray,
1683 Widget_mystruct,
1684 Widget_mystruct_ptr_ptr,
1685 Widget_thin_struct,
1686 Widget_rect,
1687 Widget_complex_struct,
1688 Widget_array,
1689 Widget_variant_array,
1690 Widget_mystruct_array,
1691 Widget_myint,
1692 Widget_Coclass,
1693 Widget_Coclass_ptr,
1694 Widget_Coclass_noptr,
1695 Widget_no_in_out,
1698 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
1700 if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
1702 IStaticWidget_AddRef(iface);
1703 *ppvObject = iface;
1704 return S_OK;
1707 *ppvObject = NULL;
1708 return E_NOINTERFACE;
1711 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
1713 return 2;
1716 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
1718 return 1;
1721 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
1723 ok(0, "unexpected call\n");
1724 return E_NOTIMPL;
1727 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
1728 ITypeInfo **ppTInfo)
1730 ok(0, "unexpected call\n");
1731 return E_NOTIMPL;
1734 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
1735 UINT cNames, LCID lcid, DISPID *rgDispId)
1737 ok(0, "unexpected call\n");
1738 return E_NOTIMPL;
1741 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
1742 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1743 UINT *puArgErr)
1745 ok(0, "unexpected call\n");
1746 return E_NOTIMPL;
1749 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
1751 trace("TestDual()\n");
1752 ok(p == &TestDual, "wrong ItestDual\n");
1753 return S_OK;
1756 static HRESULT WINAPI StaticWidget_TestSecondIface(IStaticWidget *iface, ITestSecondIface *p)
1758 trace("TestSecondIface()\n");
1759 ok(p == &TestSecondIface, "wrong ItestSecondIface\n");
1760 return S_OK;
1763 static const IStaticWidgetVtbl StaticWidgetVtbl = {
1764 StaticWidget_QueryInterface,
1765 StaticWidget_AddRef,
1766 StaticWidget_Release,
1767 StaticWidget_GetTypeInfoCount,
1768 StaticWidget_GetTypeInfo,
1769 StaticWidget_GetIDsOfNames,
1770 StaticWidget_Invoke,
1771 StaticWidget_TestDual,
1772 StaticWidget_TestSecondIface
1775 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
1777 typedef struct KindaEnum
1779 IKindaEnumWidget IKindaEnumWidget_iface;
1780 LONG refs;
1781 } KindaEnum;
1783 static inline KindaEnum *impl_from_IKindaEnumWidget(IKindaEnumWidget *iface)
1785 return CONTAINING_RECORD(iface, KindaEnum, IKindaEnumWidget_iface);
1788 static HRESULT register_current_module_typelib(void)
1790 WCHAR path[MAX_PATH];
1791 CHAR pathA[MAX_PATH];
1792 HRESULT hr;
1793 ITypeLib *typelib;
1795 GetModuleFileNameA(NULL, pathA, MAX_PATH);
1796 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
1798 hr = LoadTypeLib(path, &typelib);
1799 if (SUCCEEDED(hr))
1801 hr = RegisterTypeLib(typelib, path, NULL);
1802 ITypeLib_Release(typelib);
1804 return hr;
1807 static ITypeInfo *get_type_info(REFIID riid)
1809 ITypeInfo *pTypeInfo;
1810 ITypeLib *pTypeLib;
1811 HRESULT hr;
1813 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1814 ok_ole_success(hr, LoadRegTypeLib);
1815 if (FAILED(hr))
1816 return NULL;
1818 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
1819 ITypeLib_Release(pTypeLib);
1820 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1821 if (FAILED(hr))
1822 return NULL;
1824 return pTypeInfo;
1827 static IWidget *Widget_Create(void)
1829 Widget *This;
1830 ITypeInfo *pTypeInfo;
1831 HRESULT hr = E_FAIL;
1833 pTypeInfo = get_type_info(&IID_IWidget);
1834 if(!pTypeInfo)
1835 return NULL;
1837 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1838 This->IWidget_iface.lpVtbl = &Widget_VTable;
1839 This->refs = 1;
1840 This->pDispatchUnknown = NULL;
1842 hr = CreateStdDispatch((IUnknown *)&This->IWidget_iface, This, pTypeInfo,
1843 &This->pDispatchUnknown);
1844 ok_ole_success(hr, CreateStdDispatch);
1845 ITypeInfo_Release(pTypeInfo);
1847 if (SUCCEEDED(hr))
1848 return &This->IWidget_iface;
1849 else
1851 HeapFree(GetProcessHeap(), 0, This);
1852 return NULL;
1856 static HRESULT WINAPI KindaEnum_QueryInterface(
1857 IKindaEnumWidget *iface,
1858 /* [in] */ REFIID riid,
1859 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
1861 if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
1863 IKindaEnumWidget_AddRef(iface);
1864 *ppvObject = iface;
1865 return S_OK;
1867 else
1869 *ppvObject = NULL;
1870 return E_NOINTERFACE;
1874 static ULONG WINAPI KindaEnum_AddRef(
1875 IKindaEnumWidget *iface)
1877 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1879 return InterlockedIncrement(&This->refs);
1882 static ULONG WINAPI KindaEnum_Release(
1883 IKindaEnumWidget *iface)
1885 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1886 ULONG refs = InterlockedDecrement(&This->refs);
1887 if (!refs)
1889 memset(This, 0xcc, sizeof(*This));
1890 HeapFree(GetProcessHeap(), 0, This);
1891 trace("KindaEnumWidget destroyed!\n");
1894 return refs;
1897 static HRESULT WINAPI KindaEnum_Next(
1898 IKindaEnumWidget *iface,
1899 /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
1901 *widget = Widget_Create();
1902 if (*widget)
1903 return S_OK;
1904 else
1905 return E_OUTOFMEMORY;
1908 static HRESULT WINAPI KindaEnum_Count(
1909 IKindaEnumWidget *iface,
1910 /* [out] */ ULONG __RPC_FAR *count)
1912 return E_NOTIMPL;
1915 static HRESULT WINAPI KindaEnum_Reset(
1916 IKindaEnumWidget *iface)
1918 return E_NOTIMPL;
1921 static HRESULT WINAPI KindaEnum_Clone(
1922 IKindaEnumWidget *iface,
1923 /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
1925 return E_NOTIMPL;
1928 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
1930 KindaEnum_QueryInterface,
1931 KindaEnum_AddRef,
1932 KindaEnum_Release,
1933 KindaEnum_Next,
1934 KindaEnum_Count,
1935 KindaEnum_Reset,
1936 KindaEnum_Clone
1939 static IKindaEnumWidget *KindaEnumWidget_Create(void)
1941 KindaEnum *This;
1943 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1944 if (!This) return NULL;
1945 This->IKindaEnumWidget_iface.lpVtbl = &KindaEnumWidget_VTable;
1946 This->refs = 1;
1947 return &This->IKindaEnumWidget_iface;
1950 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
1952 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
1954 *(INonOleAutomation **)ppv = iface;
1955 return S_OK;
1957 *ppv = NULL;
1958 return E_NOINTERFACE;
1961 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
1963 return 2;
1966 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
1968 return 1;
1971 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
1973 static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1974 return SysAllocString(wszTestString);
1977 static HRESULT WINAPI NonOleAutomation_Error(INonOleAutomation *iface)
1979 return E_NOTIMPL;
1982 static INonOleAutomationVtbl NonOleAutomation_VTable =
1984 NonOleAutomation_QueryInterface,
1985 NonOleAutomation_AddRef,
1986 NonOleAutomation_Release,
1987 NonOleAutomation_BstrRet,
1988 NonOleAutomation_Error
1991 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
1993 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
1995 ITypeLib *pTypeLib;
1996 HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1997 ok_ole_success(hr, LoadRegTypeLib);
1998 if (SUCCEEDED(hr))
2000 ITypeInfo *pTypeInfo;
2001 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
2002 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
2003 ITypeLib_Release(pTypeLib);
2004 return pTypeInfo;
2006 return NULL;
2009 static void test_marshal_basetypes(IWidget *widget, IDispatch *disp)
2011 VARIANTARG arg[11];
2012 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2013 HRESULT hr;
2015 signed char c;
2016 short s;
2017 LONG l;
2018 int i, i2, *pi;
2019 hyper h;
2020 unsigned char uc;
2021 unsigned short us;
2022 ULONG ul;
2023 MIDL_uhyper uh;
2024 float f;
2025 double d;
2026 STATE st;
2028 V_VT(&arg[10]) = VT_I1; V_I1(&arg[10]) = 5;
2029 V_VT(&arg[9]) = VT_I2; V_I2(&arg[9]) = -123;
2030 V_VT(&arg[8]) = VT_I4; V_I4(&arg[8]) = -100000;
2031 V_VT(&arg[7]) = VT_I8; V_I8(&arg[7]) = (LONGLONG)-100000 * 1000000;
2032 V_VT(&arg[6]) = VT_UI1; V_UI1(&arg[6]) = 0;
2033 V_VT(&arg[5]) = VT_UI2; V_UI2(&arg[5]) = 456;
2034 V_VT(&arg[4]) = VT_UI4; V_UI4(&arg[4]) = 0xdeadbeef;
2035 V_VT(&arg[3]) = VT_UI8; V_UI8(&arg[3]) = (ULONGLONG)1234567890 * 9876543210;
2036 V_VT(&arg[2]) = VT_R4; V_R4(&arg[2]) = M_PI;
2037 V_VT(&arg[1]) = VT_R8; V_R8(&arg[1]) = M_E;
2038 V_VT(&arg[0]) = VT_I4; V_I4(&arg[0]) = STATE_WIDGETIFIED;
2039 hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_IN, &IID_NULL, LOCALE_NEUTRAL,
2040 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2041 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2043 hr = IWidget_basetypes_in(widget, 5, -123, -100000, (LONGLONG)-100000 * 1000000, 0, 456,
2044 0xdeadbeef, (ULONGLONG)1234567890 * 9876543210, M_PI, M_E, STATE_WIDGETIFIED);
2045 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2047 c = s = l = h = uc = us = ul = uh = f = d = st = 0;
2049 V_VT(&arg[10]) = VT_BYREF|VT_I1; V_I1REF(&arg[10]) = &c;
2050 V_VT(&arg[9]) = VT_BYREF|VT_I2; V_I2REF(&arg[9]) = &s;
2051 V_VT(&arg[8]) = VT_BYREF|VT_I4; V_I4REF(&arg[8]) = &l;
2052 V_VT(&arg[7]) = VT_BYREF|VT_I8; V_I8REF(&arg[7]) = &h;
2053 V_VT(&arg[6]) = VT_BYREF|VT_UI1; V_UI1REF(&arg[6]) = &uc;
2054 V_VT(&arg[5]) = VT_BYREF|VT_UI2; V_UI2REF(&arg[5]) = &us;
2055 V_VT(&arg[4]) = VT_BYREF|VT_UI4; V_UI4REF(&arg[4]) = &ul;
2056 V_VT(&arg[3]) = VT_BYREF|VT_UI8; V_UI8REF(&arg[3]) = &uh;
2057 V_VT(&arg[2]) = VT_BYREF|VT_R4; V_R4REF(&arg[2]) = &f;
2058 V_VT(&arg[1]) = VT_BYREF|VT_R8; V_R8REF(&arg[1]) = &d;
2059 V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = (LONG *)&st;
2060 hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_OUT, &IID_NULL, LOCALE_NEUTRAL,
2061 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2062 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2063 ok(c == 10, "Got char %d.\n", c);
2064 ok(s == -321, "Got short %d.\n", s);
2065 ok(l == -200000, "Got int %ld.\n", l);
2066 ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
2067 ok(uc == 254, "Got unsigned char %u.\n", uc);
2068 ok(us == 256, "Got unsigned short %u.\n", us);
2069 ok(ul == 0xf00dfade, "Got unsigned int %li.\n", ul);
2070 ok(uh == 0xabcdef0123456789ull, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
2071 ok(f == (float)M_LN2, "Got float %f.\n", f);
2072 ok(d == M_LN10, "Got double %f.\n", d);
2073 ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
2075 c = s = l = h = uc = us = ul = uh = f = d = st = 0;
2077 hr = IWidget_basetypes_out(widget, &c, &s, &l, &h, &uc, &us, &ul, &uh, &f, &d, &st);
2078 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2079 ok(c == 10, "Got char %d.\n", c);
2080 ok(s == -321, "Got short %d.\n", s);
2081 ok(l == -200000, "Got int %ld.\n", l);
2082 ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
2083 ok(uc == 254, "Got unsigned char %u.\n", uc);
2084 ok(us == 256, "Got unsigned short %u.\n", us);
2085 ok(ul == 0xf00dfade, "Got unsigned int %li.\n", ul);
2086 ok(uh == 0xabcdef0123456789ull, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
2087 ok(f == (float)M_LN2, "Got float %f.\n", f);
2088 ok(d == M_LN10, "Got double %f.\n", d);
2089 ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
2091 /* Test marshalling of public typedefs. */
2093 i = 456;
2094 i2 = 789;
2095 pi = &i2;
2096 hr = IWidget_myint(widget, 123, &i, &pi);
2097 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2099 /* Test that different float ABIs are correctly handled. */
2101 hr = IWidget_float_abi(widget, 1.0f, 2.0, 3, 4.0f, 5.0);
2102 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2105 static void test_marshal_pointer(IWidget *widget, IDispatch *disp)
2107 VARIANTARG arg[3];
2108 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2109 LONG in, out, in_out, *in_ptr, *out_ptr, *in_out_ptr;
2110 HRESULT hr;
2112 testmode = 0;
2114 in = 123;
2115 out = 456;
2116 in_out = 789;
2117 V_VT(&arg[2]) = VT_BYREF|VT_I4; V_I4REF(&arg[2]) = &in;
2118 V_VT(&arg[1]) = VT_BYREF|VT_I4; V_I4REF(&arg[1]) = &out;
2119 V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = &in_out;
2120 hr = IDispatch_Invoke(disp, DISPID_TM_INT_PTR, &IID_NULL, LOCALE_NEUTRAL,
2121 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2122 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2123 ok(in == 987, "Got [in] %ld.\n", in);
2124 ok(out == 654, "Got [out] %ld.\n", out);
2125 ok(in_out == 321, "Got [in, out] %ld.\n", in_out);
2127 testmode = 1;
2129 in = 123;
2130 out = 456;
2131 in_out = 789;
2132 hr = IWidget_long_ptr(widget, &in, &out, &in_out);
2133 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2134 ok(in == 123, "Got [in] %ld.\n", in);
2135 ok(out == 654, "Got [out] %ld.\n", out);
2136 ok(in_out == 321, "Got [in, out] %ld.\n", in_out);
2138 out = in_out = -1;
2139 hr = IWidget_long_ptr(widget, NULL, &out, &in_out);
2140 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#lx.\n", hr);
2141 ok(!out, "[out] parameter should have been cleared.\n");
2142 ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2144 in = in_out = -1;
2145 hr = IWidget_long_ptr(widget, &in, NULL, &in_out);
2146 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#lx.\n", hr);
2147 ok(in == -1, "[in] parameter should not have been cleared.\n");
2148 ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2150 in = out = -1;
2151 hr = IWidget_long_ptr(widget, &in, &out, NULL);
2152 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#lx.\n", hr);
2153 ok(in == -1, "[in] parameter should not have been cleared.\n");
2154 ok(!out, "[out] parameter should have been cleared.\n");
2156 /* We can't test Invoke() with double pointers, as it is not possible to fit
2157 * more than one level of indirection into a VARIANTARG. */
2159 testmode = 0;
2160 in_ptr = out_ptr = in_out_ptr = NULL;
2161 hr = IWidget_long_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2162 ok(hr == S_OK, "Got hr %#lx\n", hr);
2163 ok(!in_ptr, "Got [in] %p.\n", in_ptr);
2164 ok(!out_ptr, "Got [out] %p.\n", out_ptr);
2165 ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2167 testmode = 1;
2168 hr = IWidget_long_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2169 ok(hr == S_OK, "Got hr %#lx\n", hr);
2170 ok(*out_ptr == 654, "Got [out] %ld.\n", *out_ptr);
2171 ok(*in_out_ptr == 321, "Got [in, out] %ld.\n", *in_out_ptr);
2172 CoTaskMemFree(out_ptr);
2173 CoTaskMemFree(in_out_ptr);
2175 testmode = 2;
2176 in = 123;
2177 out = 456;
2178 in_out = 789;
2179 in_ptr = &in;
2180 out_ptr = &out;
2181 in_out_ptr = &in_out;
2182 hr = IWidget_long_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2183 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2184 ok(out_ptr != &out, "[out] ptr should have changed.\n");
2185 ok(in_out_ptr == &in_out, "[in, out] ptr should not have changed.\n");
2186 ok(*out_ptr == 654, "Got [out] %ld.\n", *out_ptr);
2187 ok(*in_out_ptr == 321, "Got [in, out] %ld.\n", *in_out_ptr);
2189 testmode = 3;
2190 in_ptr = out_ptr = NULL;
2191 in_out = 789;
2192 in_out_ptr = &in_out;
2193 hr = IWidget_long_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2194 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2195 ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2197 out_ptr = &out;
2198 in_out_ptr = &in_out;
2199 hr = IWidget_long_ptr_ptr(widget, NULL, &out_ptr, &in_out_ptr);
2200 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#lx.\n", hr);
2201 ok(!out_ptr, "[out] parameter should have been cleared.\n");
2202 ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2204 in_ptr = &in;
2205 in_out_ptr = &in_out;
2206 hr = IWidget_long_ptr_ptr(widget, &in_ptr, NULL, &in_out_ptr);
2207 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#lx.\n", hr);
2208 ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2209 ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2211 in_ptr = &in;
2212 out_ptr = &out;
2213 hr = IWidget_long_ptr_ptr(widget, &in_ptr, &out_ptr, NULL);
2214 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#lx.\n", hr);
2215 ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2216 ok(!out_ptr, "[out] parameter should have been cleared.\n");
2219 static void test_marshal_iface(IWidget *widget, IDispatch *disp)
2221 VARIANTARG arg[3];
2222 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2223 ISomethingFromDispatch *sfd1, *sfd2, *sfd3, *proxy_sfd, *sfd_in, *sfd_out, *sfd_in_out;
2224 IUnknown *proxy_unk, *proxy_unk2, *unk_in, *unk_out, *unk_in_out;
2225 IDispatch *proxy_disp;
2226 IUnknown unk_noptr;
2227 IDispatch disp_noptr;
2228 ISomethingFromDispatch sfd_noptr;
2229 HRESULT hr;
2231 testmode = 0;
2232 sfd1 = create_disp_obj();
2233 sfd2 = create_disp_obj();
2234 sfd3 = create_disp_obj();
2235 hr = IWidget_iface_in(widget, (IUnknown *)sfd1,
2236 (IDispatch *)sfd2, sfd3);
2237 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2238 release_iface(sfd1);
2239 release_iface(sfd2);
2240 release_iface(sfd3);
2242 testmode = 1;
2243 hr = IWidget_iface_in(widget, NULL, NULL, NULL);
2244 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2246 testmode = 0;
2247 proxy_unk = (IUnknown *)0xdeadbeef;
2248 proxy_disp = (IDispatch *)0xdeadbeef;
2249 proxy_sfd = (ISomethingFromDispatch *)0xdeadbeef;
2250 hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2251 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2252 check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2253 release_iface(proxy_unk);
2254 release_iface(proxy_disp);
2255 release_iface(proxy_sfd);
2257 testmode = 1;
2258 hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2259 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2260 ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2261 ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2262 ok(!proxy_sfd, "Got unexpected proxy %p.\n", proxy_sfd);
2264 testmode = 0;
2265 sfd_in = sfd1 = create_disp_obj();
2266 sfd_out = sfd2 = create_disp_obj();
2267 sfd_in_out = sfd3 = create_disp_obj();
2268 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2269 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2270 ok(sfd_in == sfd1, "[in] parameter should not have changed.\n");
2271 ok(!sfd_out, "[out] parameter should have been cleared.\n");
2272 ok(sfd_in_out == sfd3, "[in, out] parameter should not have changed.\n");
2273 release_iface(sfd1);
2274 release_iface(sfd2);
2275 release_iface(sfd3);
2277 testmode = 1;
2278 sfd_in = sfd1 = create_disp_obj();
2279 sfd_in_out = sfd3 = create_disp_obj();
2280 ISomethingFromDispatch_AddRef(sfd_in_out);
2281 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2282 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2283 hr = ISomethingFromDispatch_anotherfn(sfd_out);
2284 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
2285 ok(sfd_in_out != sfd3, "[in, out] parameter should have changed.\n");
2286 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2287 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
2288 release_iface(sfd_out);
2289 release_iface(sfd_in_out);
2290 release_iface(sfd1);
2291 release_iface(sfd3);
2293 testmode = 2;
2294 sfd_in = sfd_out = sfd_in_out = NULL;
2295 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2296 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2297 ok(!sfd_out, "[out] parameter should not have been set.\n");
2298 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2299 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
2300 release_iface(sfd_in_out);
2302 testmode = 3;
2303 sfd_in = sfd_out = NULL;
2304 sfd_in_out = sfd3 = create_disp_obj();
2305 ISomethingFromDispatch_AddRef(sfd_in_out);
2306 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2307 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2308 ok(!sfd_in_out, "Got [in, out] %p.\n", sfd_in_out);
2309 release_iface(sfd3);
2311 sfd1 = create_disp_obj();
2312 sfd2 = create_disp_obj();
2313 sfd3 = create_disp_obj();
2314 unk_noptr.lpVtbl = (IUnknownVtbl *)sfd1;
2315 disp_noptr.lpVtbl = (IDispatchVtbl *)sfd2;
2316 sfd_noptr.lpVtbl = (ISomethingFromDispatchVtbl *)sfd3;
2317 hr = IWidget_iface_noptr(widget, unk_noptr, disp_noptr, sfd_noptr);
2318 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2319 release_iface(sfd1);
2320 release_iface(sfd2);
2321 release_iface(sfd3);
2323 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2324 * interface back, but rather an IUnknown. */
2326 testmode = 0;
2327 sfd1 = create_disp_obj();
2328 sfd2 = create_disp_obj();
2329 sfd3 = create_disp_obj();
2331 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)sfd1;
2332 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)sfd2;
2333 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)sfd3;
2334 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2335 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2336 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2338 V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)sfd1;
2339 V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)sfd2;
2340 V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)sfd3;
2341 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2342 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2343 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2345 release_iface(sfd1);
2346 release_iface(sfd2);
2347 release_iface(sfd3);
2349 testmode = 1;
2350 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = NULL;
2351 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = NULL;
2352 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = NULL;
2353 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2354 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2355 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2357 testmode = 0;
2358 proxy_unk = proxy_unk2 = NULL;
2359 proxy_disp = NULL;
2360 V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &proxy_unk;
2361 V_VT(&arg[1]) = VT_DISPATCH|VT_BYREF; V_DISPATCHREF(&arg[1]) = &proxy_disp;
2362 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &proxy_unk2;
2363 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2364 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2365 todo_wine
2366 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2367 if (hr == S_OK) {
2368 hr = IUnknown_QueryInterface(proxy_unk2, &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
2369 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2370 check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2371 ISomethingFromDispatch_Release(proxy_sfd);
2372 release_iface(proxy_unk);
2373 release_iface(proxy_disp);
2374 release_iface(proxy_unk2);
2377 testmode = 1;
2378 proxy_unk = proxy_unk2 = NULL;
2379 proxy_disp = NULL;
2380 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2381 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2382 todo_wine
2383 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2384 ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2385 ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2386 ok(!proxy_unk2, "Got unexpected proxy %p.\n", proxy_unk2);
2388 testmode = 0;
2389 sfd1 = create_disp_obj();
2390 sfd3 = create_disp_obj();
2391 unk_in = (IUnknown *)sfd1;
2392 unk_out = NULL;
2393 unk_in_out = (IUnknown *)sfd3;
2394 V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &unk_in;
2395 V_VT(&arg[1]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[1]) = &unk_out;
2396 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2397 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2398 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2399 todo_wine
2400 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2401 ok(unk_in == (IUnknown *)sfd1, "[in] parameter should not have changed.\n");
2402 ok(!unk_out, "[out] parameter should have been cleared.\n");
2403 ok(unk_in_out == (IUnknown *)sfd3, "[in, out] parameter should not have changed.\n");
2404 release_iface(sfd1);
2405 release_iface(sfd3);
2407 testmode = 1;
2408 sfd1 = create_disp_obj();
2409 sfd3 = create_disp_obj();
2410 unk_in = (IUnknown *)sfd1;
2411 unk_out = NULL;
2412 unk_in_out = (IUnknown *)sfd3;
2413 IUnknown_AddRef(unk_in_out);
2414 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2415 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2416 todo_wine
2417 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2419 if (hr == S_OK) {
2420 hr = IUnknown_QueryInterface(unk_out, &IID_ISomethingFromDispatch, (void **)&sfd_out);
2421 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2422 hr = ISomethingFromDispatch_anotherfn(sfd_out);
2423 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
2424 ISomethingFromDispatch_Release(sfd_out);
2426 ok(unk_in_out != (IUnknown *)sfd3, "[in, out] parameter should have changed.\n");
2427 hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2428 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2429 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2430 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
2431 ISomethingFromDispatch_Release(sfd_in_out);
2433 release_iface(unk_out);
2434 release_iface(unk_in_out);
2436 release_iface(sfd1);
2437 todo_wine
2438 release_iface(sfd3);
2440 testmode = 2;
2441 unk_in = unk_out = unk_in_out = NULL;
2442 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2443 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2444 todo_wine
2445 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2447 ok(!unk_out, "[out] parameter should not have been set.\n");
2448 if (hr == S_OK) {
2449 hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2450 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2451 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2452 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
2453 ISomethingFromDispatch_Release(sfd_in_out);
2455 release_iface(unk_in_out);
2458 testmode = 3;
2459 unk_in = unk_out = NULL;
2460 sfd3 = create_disp_obj();
2461 unk_in_out = (IUnknown *)sfd3;
2462 IUnknown_AddRef(unk_in_out);
2463 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2464 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2465 todo_wine {
2466 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2467 ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2468 release_iface(sfd3);
2472 static void test_marshal_bstr(IWidget *widget, IDispatch *disp)
2474 VARIANTARG arg[4];
2475 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2476 BSTR in, out, in_ptr, in_out;
2477 HRESULT hr;
2478 UINT len;
2480 testmode = 0;
2481 in = SysAllocStringLen(test_bstr1, ARRAY_SIZE(test_bstr1));
2482 out = NULL;
2483 in_ptr = SysAllocString(test_bstr2);
2484 in_out = SysAllocString(test_bstr3);
2486 V_VT(&arg[3]) = VT_BSTR; V_BSTR(&arg[3]) = in;
2487 V_VT(&arg[2]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[2]) = &out;
2488 V_VT(&arg[1]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[1]) = &in_ptr;
2489 V_VT(&arg[0]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[0]) = &in_out;
2490 hr = IDispatch_Invoke(disp, DISPID_TM_BSTR, &IID_NULL, LOCALE_NEUTRAL,
2491 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2492 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2493 ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2494 ok(in_ptr[1] == 'X', "[in] pointer should be changed.\n");
2495 ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2496 len = SysStringLen(out);
2497 ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2498 ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2500 in[1] = test_bstr1[1];
2501 in_ptr[1] = test_bstr2[1];
2502 in_out[1] = test_bstr3[1];
2503 SysFreeString(out);
2504 out = (BSTR)0xdeadbeef;
2505 hr = IWidget_bstr(widget, in, &out, &in_ptr, &in_out);
2506 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2507 ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2508 ok(in_ptr[1] == test_bstr2[1], "[in] pointer should not be changed.\n");
2509 ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2510 len = SysStringLen(out);
2511 ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2512 ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2513 SysFreeString(in);
2514 SysFreeString(out);
2515 SysFreeString(in_ptr);
2516 SysFreeString(in_out);
2518 testmode = 1;
2519 out = in_ptr = in_out = NULL;
2520 hr = IWidget_bstr(widget, NULL, &out, &in_ptr, &in_out);
2521 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2523 in = SysAllocString(L"test");
2524 hr = IWidget_no_in_out(widget, in, 5);
2525 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2528 static void test_marshal_variant(IWidget *widget, IDispatch *disp)
2530 VARIANTARG arg[4];
2531 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2532 VARIANT out, in_ptr, in_out;
2533 HRESULT hr;
2534 BSTR bstr;
2536 testmode = 0;
2537 V_VT(&out) = VT_I4;
2538 V_I4(&out) = 1;
2539 V_VT(&in_ptr) = VT_I4;
2540 V_I4(&in_ptr) = -1;
2541 V_VT(&in_out) = VT_BSTR;
2542 V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2544 V_VT(&arg[3]) = VT_CY;
2545 V_CY(&arg[3]).Hi = 0xdababe;
2546 V_CY(&arg[3]).Lo = 0xdeadbeef;
2547 V_VT(&arg[2]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[2]) = &out;
2548 V_VT(&arg[1]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[1]) = &in_ptr;
2549 V_VT(&arg[0]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[0]) = &in_out;
2550 hr = IDispatch_Invoke(disp, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL,
2551 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2552 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2553 ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2554 ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2555 ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2556 VariantClear(&out);
2557 ok(V_VT(&in_ptr) == VT_I2, "Got wrong type %u.\n", V_VT(&in_ptr));
2558 ok(V_I2(&in_ptr) == 4, "Got wrong value %d.\n", V_I1(&in_ptr));
2559 ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2560 ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2562 testmode = 1;
2563 V_VT(&out) = VT_I4;
2564 V_I4(&out) = 1;
2565 V_VT(&in_ptr) = VT_I4;
2566 V_I4(&in_ptr) = -1;
2567 V_VT(&in_out) = VT_BSTR;
2568 V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2569 hr = IWidget_variant(widget, arg[3], &out, &in_ptr, &in_out);
2570 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2571 ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2572 ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2573 ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2574 ok(V_VT(&in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(&in_ptr));
2575 ok(V_I2(&in_ptr) == -1, "Got wrong value %d.\n", V_I1(&in_ptr));
2576 ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2577 ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2580 static void test_marshal_safearray(IWidget *widget, IDispatch *disp)
2582 SAFEARRAY *in, *out, *out2, *in_ptr, *in_out;
2583 HRESULT hr;
2585 in = make_safearray(3);
2586 out = out2 = make_safearray(5);
2587 in_ptr = make_safearray(7);
2588 in_out = make_safearray(9);
2589 hr = IWidget_safearray(widget, in, &out, &in_ptr, &in_out);
2590 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2591 check_safearray(in, 3);
2592 check_safearray(out, 4);
2593 check_safearray(out2, 5);
2594 check_safearray(in_ptr, 7);
2595 check_safearray(in_out, 6);
2597 SafeArrayDestroy(in);
2598 SafeArrayDestroy(out);
2599 SafeArrayDestroy(out2);
2600 SafeArrayDestroy(in_ptr);
2601 SafeArrayDestroy(in_out);
2604 static void test_marshal_struct(IWidget *widget, IDispatch *disp)
2606 MYSTRUCT out, in_ptr, in_out, *in_ptr_ptr;
2607 RECT rect_out, rect_in_ptr, rect_in_out;
2608 ISomethingFromDispatch *sfd;
2609 struct complex complex;
2610 int i, i2, *pi = &i2;
2611 HRESULT hr;
2613 memcpy(&out, &test_mystruct2, sizeof(MYSTRUCT));
2614 memcpy(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT));
2615 memcpy(&in_out, &test_mystruct4, sizeof(MYSTRUCT));
2616 hr = IWidget_mystruct(widget, test_mystruct1, &out, &in_ptr, &in_out);
2617 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2618 ok(!memcmp(&out, &test_mystruct5, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2619 ok(!memcmp(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2620 ok(!memcmp(&in_out, &test_mystruct7, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2622 memcpy(&in_ptr, &test_mystruct1, sizeof(MYSTRUCT));
2623 in_ptr_ptr = &in_ptr;
2624 hr = IWidget_mystruct_ptr_ptr(widget, &in_ptr_ptr);
2625 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2627 /* Make sure that "thin" structs (<=8 bytes) are handled correctly in x86-64. */
2629 hr = IWidget_thin_struct(widget, test_thin_struct);
2630 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2632 /* Make sure we can handle an imported type. */
2634 rect_out = test_rect2;
2635 rect_in_ptr = test_rect3;
2636 rect_in_out = test_rect4;
2637 hr = IWidget_rect(widget, test_rect1, &rect_out, &rect_in_ptr, &rect_in_out);
2638 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2639 ok(EqualRect(&rect_out, &test_rect5), "Rects didn't match.\n");
2640 ok(EqualRect(&rect_in_ptr, &test_rect3), "Rects didn't match.\n");
2641 ok(EqualRect(&rect_in_out, &test_rect7), "Rects didn't match.\n");
2643 /* Test complex structs. */
2644 complex.c = 98;
2645 complex.i = 76543;
2646 i = 2;
2647 complex.pi = &i;
2648 i2 = 10;
2649 complex.ppi = &pi;
2650 complex.iface = create_disp_obj();
2651 sfd = create_disp_obj();
2652 complex.iface_ptr = &sfd;
2653 complex.bstr = SysAllocString(test_bstr2);
2654 V_VT(&complex.var) = VT_I4;
2655 V_I4(&complex.var) = 123;
2656 memcpy(&complex.mystruct, &test_mystruct1, sizeof(MYSTRUCT));
2657 memcpy(complex.arr, test_array1, sizeof(array_t));
2658 complex.myint = 456;
2659 hr = IWidget_complex_struct(widget, complex);
2660 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2663 static void test_marshal_array(IWidget *widget, IDispatch *disp)
2665 VARIANT var_in[2], var_out[2], var_in_out[2];
2666 ISomethingFromDispatch *proxy_sfd;
2667 array_t in, out, in_out;
2668 MYSTRUCT struct_in[2];
2669 HRESULT hr;
2670 LONG l = 2;
2672 memcpy(in, test_array1, sizeof(array_t));
2673 memcpy(out, test_array2, sizeof(array_t));
2674 memcpy(in_out, test_array3, sizeof(array_t));
2675 hr = IWidget_array(widget, in, out, in_out);
2676 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2677 ok(!memcmp(&in, &test_array1, sizeof(array_t)), "Arrays didn't match.\n");
2678 ok(!memcmp(&out, &test_array5, sizeof(array_t)), "Arrays didn't match.\n");
2679 ok(!memcmp(&in_out, &test_array6, sizeof(array_t)), "Arrays didn't match.\n");
2681 V_VT(&var_in[0]) = VT_I4; V_I4(&var_in[0]) = 1;
2682 V_VT(&var_in[1]) = VT_BYREF|VT_I4; V_I4REF(&var_in[1]) = &l;
2683 V_VT(&var_out[0]) = VT_I4; V_I4(&var_out[0]) = 3;
2684 V_VT(&var_out[1]) = VT_I4; V_I4(&var_out[1]) = 4;
2685 V_VT(&var_in_out[0]) = VT_I4; V_I4(&var_in_out[0]) = 5;
2686 V_VT(&var_in_out[1]) = VT_BSTR; V_BSTR(&var_in_out[1]) = SysAllocString(test_bstr1);
2687 hr = IWidget_variant_array(widget, var_in, var_out, var_in_out);
2688 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2689 ok(V_VT(&var_in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[0]));
2690 ok(V_I4(&var_in[0]) == 1, "Got wrong value %ld.\n", V_I4(&var_in[0]));
2691 ok(V_VT(&var_in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&var_in[1]));
2692 ok(V_I4REF(&var_in[1]) == &l, "Got wrong value %p.\n", V_I4REF(&var_in[1]));
2693 ok(l == 2, "Got wrong value %ld.\n", l);
2694 ok(V_VT(&var_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[0]));
2695 ok(V_I1(&var_out[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out[0]));
2696 ok(V_VT(&var_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&var_out[1]));
2697 ok(!lstrcmpW(V_BSTR(&var_out[1]), test_bstr2), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&var_out[1])));
2698 ok(V_VT(&var_in_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[0]));
2699 ok(V_I1(&var_in_out[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out[0]));
2700 ok(V_VT(&var_in_out[1]) == VT_UNKNOWN, "Got wrong type %u.\n", V_VT(&var_in_out[1]));
2701 hr = IUnknown_QueryInterface(V_UNKNOWN(&var_in_out[1]), &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
2702 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2703 hr = ISomethingFromDispatch_anotherfn(proxy_sfd);
2704 ok(hr == 0x01234567, "Got hr %#lx.\n", hr);
2705 ISomethingFromDispatch_Release(proxy_sfd);
2706 release_iface(V_UNKNOWN(&var_in_out[1]));
2708 memcpy(&struct_in[0], &test_mystruct1, sizeof(MYSTRUCT));
2709 memcpy(&struct_in[1], &test_mystruct2, sizeof(MYSTRUCT));
2710 hr = IWidget_mystruct_array(widget, struct_in);
2711 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2714 static void test_marshal_coclass(IWidget *widget, IDispatch *disp)
2716 VARIANTARG arg[3];
2717 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2718 struct coclass_obj *class1, *class2, *class3;
2719 IUnknown *unk_in, *unk_out, *unk_in_out;
2720 ICoclass1 *in, *out, *in_out;
2721 Coclass1 class1_noptr;
2722 Coclass2 class2_noptr;
2723 Coclass3 class3_noptr;
2724 HRESULT hr;
2726 class1 = create_coclass_obj();
2727 class2 = create_coclass_obj();
2728 class3 = create_coclass_obj();
2730 hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass1_iface,
2731 (Coclass2 *)&class2->ICoclass1_iface, (Coclass3 *)&class3->ICoclass1_iface);
2732 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2734 hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass2_iface,
2735 (Coclass2 *)&class2->ICoclass2_iface, (Coclass3 *)&class3->ICoclass2_iface);
2736 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2738 release_iface(&class1->ICoclass1_iface);
2739 release_iface(&class2->ICoclass1_iface);
2740 release_iface(&class3->ICoclass1_iface);
2742 testmode = 0;
2743 class1 = create_coclass_obj();
2744 class2 = create_coclass_obj();
2745 class3 = create_coclass_obj();
2746 in = &class1->ICoclass1_iface;
2747 out = &class2->ICoclass1_iface;
2748 in_out = &class3->ICoclass1_iface;
2749 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in, (Coclass1 **)&out, (Coclass1 **)&in_out);
2750 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2751 ok(in == &class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2752 ok(!out, "[out] parameter should have been cleared.\n");
2753 ok(in_out == &class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2754 release_iface(&class1->ICoclass1_iface);
2755 release_iface(&class2->ICoclass1_iface);
2756 release_iface(&class3->ICoclass1_iface);
2758 testmode = 1;
2759 class1 = create_coclass_obj();
2760 class3 = create_coclass_obj();
2761 in = &class1->ICoclass1_iface;
2762 in_out = &class3->ICoclass1_iface;
2763 ICoclass1_AddRef(in_out);
2764 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2765 (Coclass1 **)&out, (Coclass1 **)&in_out);
2766 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2767 hr = ICoclass1_test(out);
2768 ok(hr == 1, "Got hr %#lx.\n", hr);
2769 ok(in_out != &class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2770 hr = ICoclass1_test(in_out);
2771 ok(hr == 1, "Got hr %#lx.\n", hr);
2772 release_iface(out);
2773 release_iface(in_out);
2774 release_iface(&class1->ICoclass1_iface);
2775 release_iface(&class3->ICoclass1_iface);
2777 testmode = 2;
2778 in = out = in_out = NULL;
2779 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2780 (Coclass1 **)&out, (Coclass1 **)&in_out);
2781 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2782 hr = ICoclass1_test(in_out);
2783 ok(hr == 1, "Got hr %#lx.\n", hr);
2784 release_iface(in_out);
2786 testmode = 3;
2787 in = out = NULL;
2788 class3 = create_coclass_obj();
2789 in_out = &class3->ICoclass1_iface;
2790 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2791 (Coclass1 **)&out, (Coclass1 **)&in_out);
2792 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2793 ok(!in_out, "Got [in, out] %p.\n", in_out);
2795 class1 = create_coclass_obj();
2796 class2 = create_coclass_obj();
2797 class3 = create_coclass_obj();
2798 class1_noptr.iface = &class1->ICoclass1_iface;
2799 class2_noptr.iface = &class2->ICoclass2_iface;
2800 class3_noptr.iface = &class3->ICoclass1_iface;
2801 hr = IWidget_Coclass_noptr(widget, class1_noptr, class2_noptr, class3_noptr);
2802 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2803 release_iface(&class1->ICoclass1_iface);
2804 release_iface(&class2->ICoclass1_iface);
2805 release_iface(&class3->ICoclass1_iface);
2807 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2808 * interface back, but rather an IUnknown. */
2810 class1 = create_coclass_obj();
2811 class2 = create_coclass_obj();
2812 class3 = create_coclass_obj();
2814 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass1_iface;
2815 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass1_iface;
2816 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass1_iface;
2817 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2818 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2819 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2821 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass2_iface;
2822 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass2_iface;
2823 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass2_iface;
2824 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2825 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2826 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2828 V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)&class1->ICoclass1_iface;
2829 V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)&class2->ICoclass1_iface;
2830 V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)&class3->ICoclass1_iface;
2831 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2832 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2833 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2835 release_iface(&class1->ICoclass1_iface);
2836 release_iface(&class2->ICoclass1_iface);
2837 release_iface(&class3->ICoclass1_iface);
2839 testmode = 0;
2840 class1 = create_coclass_obj();
2841 class3 = create_coclass_obj();
2842 unk_in = (IUnknown *)&class1->ICoclass1_iface;
2843 unk_out = NULL;
2844 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2845 V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &unk_in;
2846 V_VT(&arg[1]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[1]) = &unk_out;
2847 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2848 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2849 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2850 todo_wine
2851 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2852 ok(unk_in == (IUnknown *)&class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2853 ok(!unk_out, "[out] parameter should have been cleared.\n");
2854 ok(unk_in_out == (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2855 release_iface(&class1->ICoclass1_iface);
2856 release_iface(&class3->ICoclass1_iface);
2858 testmode = 1;
2859 class1 = create_coclass_obj();
2860 class3 = create_coclass_obj();
2861 unk_in = (IUnknown *)&class1->ICoclass1_iface;
2862 unk_out = NULL;
2863 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2864 IUnknown_AddRef(unk_in_out);
2865 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2866 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2867 todo_wine
2868 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2870 if (hr == S_OK) {
2871 hr = IUnknown_QueryInterface(unk_out, &IID_ICoclass1, (void **)&out);
2872 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2873 hr = ICoclass1_test(out);
2874 ok(hr == 1, "Got hr %#lx.\n", hr);
2875 ICoclass1_Release(out);
2877 ok(unk_in_out != (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2878 hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2879 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2880 hr = ICoclass1_test(in_out);
2881 ok(hr == 1, "Got hr %#lx.\n", hr);
2882 ICoclass1_Release(in_out);
2884 release_iface(unk_out);
2885 release_iface(unk_in_out);
2887 release_iface(&class1->ICoclass1_iface);
2888 todo_wine
2889 release_iface(&class3->ICoclass1_iface);
2891 testmode = 2;
2892 unk_in = unk_out = unk_in_out = NULL;
2893 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2894 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2895 todo_wine
2896 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2898 ok(!unk_out, "[out] parameter should not have been set.\n");
2899 if (hr == S_OK) {
2900 hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2901 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2902 hr = ICoclass1_test(in_out);
2903 ok(hr == 1, "Got hr %#lx.\n", hr);
2904 ICoclass1_Release(in_out);
2906 release_iface(unk_in_out);
2909 testmode = 3;
2910 unk_in = unk_out = NULL;
2911 class3 = create_coclass_obj();
2912 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2913 IUnknown_AddRef(unk_in_out);
2914 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2915 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2916 todo_wine
2917 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2918 todo_wine
2919 ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2921 todo_wine
2922 release_iface(&class3->ICoclass1_iface);
2925 static void test_typelibmarshal(void)
2927 static const WCHAR szCat[] = { 'C','a','t',0 };
2928 static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
2929 static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
2930 HRESULT hr;
2931 IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
2932 IWidget *pWidget;
2933 IStream *pStream;
2934 IDispatch *pDispatch;
2935 static const LARGE_INTEGER ullZero;
2936 EXCEPINFO excepinfo;
2937 VARIANT varresult;
2938 DISPID dispidNamed = DISPID_PROPERTYPUT;
2939 DISPPARAMS dispparams;
2940 VARIANTARG vararg[4];
2941 STATE the_state;
2942 HANDLE thread;
2943 DWORD tid;
2944 BSTR bstr;
2945 ITypeInfo *pTypeInfo;
2946 UINT uval;
2948 ok(pKEW != NULL, "Widget creation failed\n");
2950 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2951 ok_ole_success(hr, CreateStreamOnHGlobal);
2952 tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
2953 IKindaEnumWidget_Release(pKEW);
2955 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2956 hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
2957 ok_ole_success(hr, CoUnmarshalInterface);
2958 IStream_Release(pStream);
2959 if (FAILED(hr))
2961 end_host_object(tid, thread);
2962 return;
2965 hr = IKindaEnumWidget_Next(pKEW, &pWidget);
2966 ok_ole_success(hr, IKindaEnumWidget_Next);
2968 IKindaEnumWidget_Release(pKEW);
2970 /* call GetTypeInfoCount (direct) */
2971 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2972 ok_ole_success(hr, IWidget_GetTypeInfoCount);
2973 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2974 ok_ole_success(hr, IWidget_GetTypeInfoCount);
2976 hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
2977 ok_ole_success(hr, IWidget_QueryInterface);
2979 /* call put_Name */
2980 VariantInit(&vararg[0]);
2981 dispparams.cNamedArgs = 1;
2982 dispparams.rgdispidNamedArgs = &dispidNamed;
2983 dispparams.cArgs = 1;
2984 dispparams.rgvarg = vararg;
2985 VariantInit(&varresult);
2986 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
2987 ok_ole_success(hr, IDispatch_Invoke);
2988 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
2989 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
2990 excepinfo.wCode, excepinfo.scode);
2991 VariantClear(&varresult);
2993 /* call put_Name (direct) */
2994 bstr = SysAllocString(szSuperman);
2995 hr = IWidget_put_Name(pWidget, bstr);
2996 ok_ole_success(hr, IWidget_put_Name);
2997 SysFreeString(bstr);
2999 /* call get_Name */
3000 dispparams.cNamedArgs = 0;
3001 dispparams.rgdispidNamedArgs = NULL;
3002 dispparams.cArgs = 0;
3003 dispparams.rgvarg = NULL;
3004 VariantInit(&varresult);
3005 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3006 ok_ole_success(hr, IDispatch_Invoke);
3007 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3008 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3009 excepinfo.wCode, excepinfo.scode);
3010 trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
3011 VariantClear(&varresult);
3013 /* call get_Name (direct) */
3014 bstr = (void *)0xdeadbeef;
3015 hr = IWidget_get_Name(pWidget, &bstr);
3016 ok_ole_success(hr, IWidget_get_Name);
3017 ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
3018 SysFreeString(bstr);
3020 /* call DoSomething without optional arguments */
3021 VariantInit(&vararg[0]);
3022 VariantInit(&vararg[1]);
3023 V_VT(&vararg[1]) = VT_R8;
3024 V_R8(&vararg[1]) = 3.141;
3025 dispparams.cNamedArgs = 0;
3026 dispparams.cArgs = 2;
3027 dispparams.rgdispidNamedArgs = NULL;
3028 dispparams.rgvarg = vararg;
3029 VariantInit(&varresult);
3030 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3031 ok_ole_success(hr, IDispatch_Invoke);
3032 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3033 VariantClear(&varresult);
3035 /* call DoSomething with optional argument set to VT_EMPTY */
3036 VariantInit(&vararg[0]);
3037 VariantInit(&vararg[1]);
3038 VariantInit(&vararg[2]);
3039 V_VT(&vararg[2]) = VT_R8;
3040 V_R8(&vararg[2]) = 3.141;
3041 dispparams.cNamedArgs = 0;
3042 dispparams.cArgs = 3;
3043 dispparams.rgdispidNamedArgs = NULL;
3044 dispparams.rgvarg = vararg;
3045 VariantInit(&varresult);
3046 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3047 ok_ole_success(hr, IDispatch_Invoke);
3048 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3049 VariantClear(&varresult);
3051 /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
3052 VariantInit(&vararg[0]);
3053 VariantInit(&vararg[1]);
3054 VariantInit(&vararg[2]);
3055 VariantInit(&vararg[3]);
3056 V_VT(&vararg[3]) = VT_R8;
3057 V_R8(&vararg[3]) = 3.141;
3058 V_VT(&vararg[1]) = VT_ERROR;
3059 V_ERROR(&vararg[1]) = DISP_E_PARAMNOTFOUND;
3060 V_VT(&vararg[0]) = VT_ERROR;
3061 V_ERROR(&vararg[0]) = DISP_E_PARAMNOTFOUND;
3062 dispparams.cNamedArgs = 0;
3063 dispparams.cArgs = 4;
3064 dispparams.rgdispidNamedArgs = NULL;
3065 dispparams.rgvarg = vararg;
3066 VariantInit(&varresult);
3067 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3068 ok_ole_success(hr, IDispatch_Invoke);
3069 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3070 VariantClear(&varresult);
3072 /* call get_State */
3073 dispparams.cNamedArgs = 0;
3074 dispparams.cArgs = 0;
3075 dispparams.rgdispidNamedArgs = NULL;
3076 dispparams.rgvarg = NULL;
3077 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3078 ok_ole_success(hr, IDispatch_Invoke);
3079 ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
3081 /* call get_State (direct) */
3082 hr = IWidget_get_State(pWidget, &the_state);
3083 ok_ole_success(hr, IWidget_get_state);
3084 ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
3086 /* call put_State */
3087 the_state = STATE_WIDGETIFIED;
3088 VariantInit(&vararg[0]);
3089 V_VT(&vararg[0]) = VT_BYREF|VT_I4;
3090 V_I4REF(&vararg[0]) = (LONG *)&the_state;
3091 dispparams.cNamedArgs = 1;
3092 dispparams.cArgs = 1;
3093 dispparams.rgdispidNamedArgs = &dispidNamed;
3094 dispparams.rgvarg = vararg;
3095 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3096 ok_ole_success(hr, IDispatch_Invoke);
3098 /* call Map */
3099 bstr = SysAllocString(szTestTest);
3100 VariantInit(&vararg[0]);
3101 V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
3102 V_BSTRREF(&vararg[0]) = &bstr;
3103 dispparams.cNamedArgs = 0;
3104 dispparams.cArgs = 1;
3105 dispparams.rgdispidNamedArgs = NULL;
3106 dispparams.rgvarg = vararg;
3107 VariantInit(&varresult);
3108 hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3109 ok_ole_success(hr, IDispatch_Invoke);
3110 ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
3111 ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
3112 VariantClear(&varresult);
3113 SysFreeString(bstr);
3115 /* call SetOleColor with large negative VT_I4 param */
3116 VariantInit(&vararg[0]);
3117 V_VT(&vararg[0]) = VT_I4;
3118 V_I4(&vararg[0]) = 0x80000005;
3119 dispparams.cNamedArgs = 0;
3120 dispparams.cArgs = 1;
3121 dispparams.rgdispidNamedArgs = NULL;
3122 dispparams.rgvarg = vararg;
3123 hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
3124 ok_ole_success(hr, IDispatch_Invoke);
3126 /* call GetOleColor */
3127 dispparams.cNamedArgs = 0;
3128 dispparams.cArgs = 0;
3129 dispparams.rgdispidNamedArgs = NULL;
3130 dispparams.rgvarg = NULL;
3131 VariantInit(&varresult);
3132 hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3133 ok_ole_success(hr, IDispatch_Invoke);
3134 VariantClear(&varresult);
3136 /* call Clone */
3137 dispparams.cNamedArgs = 0;
3138 dispparams.cArgs = 0;
3139 dispparams.rgdispidNamedArgs = NULL;
3140 dispparams.rgvarg = NULL;
3141 VariantInit(&varresult);
3142 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3143 ok_ole_success(hr, IDispatch_Invoke);
3144 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
3145 VariantClear(&varresult);
3147 /* call CloneInterface */
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_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3154 ok_ole_success(hr, IDispatch_Invoke);
3155 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
3156 VariantClear(&varresult);
3158 /* call CloneDispatch with automatic value getting */
3159 V_VT(&vararg[0]) = VT_I2;
3160 V_I2(&vararg[0]) = 1;
3161 dispparams.cNamedArgs = 0;
3162 dispparams.rgdispidNamedArgs = NULL;
3163 dispparams.cArgs = 1;
3164 dispparams.rgvarg = vararg;
3165 VariantInit(&varresult);
3166 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3167 ok_ole_success(hr, IDispatch_Invoke);
3169 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3170 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3171 excepinfo.wCode, excepinfo.scode);
3173 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3174 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3175 VariantClear(&varresult);
3177 /* call CloneCoclass */
3178 dispparams.cNamedArgs = 0;
3179 dispparams.cArgs = 0;
3180 dispparams.rgdispidNamedArgs = NULL;
3181 dispparams.rgvarg = NULL;
3182 VariantInit(&varresult);
3183 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3184 ok_ole_success(hr, IDispatch_Invoke);
3186 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3187 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3188 excepinfo.wCode, excepinfo.scode);
3190 ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
3191 ok(V_DISPATCH(&varresult) != NULL, "expected V_DISPATCH(&varresult) != NULL\n");
3193 /* call Value with a VT_VARIANT|VT_BYREF type */
3194 V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
3195 V_VARIANTREF(&vararg[0]) = &vararg[1];
3196 V_VT(&vararg[1]) = VT_I2;
3197 V_I2(&vararg[1]) = 1;
3198 dispparams.cNamedArgs = 0;
3199 dispparams.rgdispidNamedArgs = NULL;
3200 dispparams.cArgs = 1;
3201 dispparams.rgvarg = vararg;
3202 VariantInit(&varresult);
3203 hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3204 ok_ole_success(hr, IDispatch_Invoke);
3206 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3207 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3208 excepinfo.wCode, excepinfo.scode);
3210 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3211 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3212 VariantClear(&varresult);
3214 /* call Array with BSTR argument - type mismatch */
3215 VariantInit(&vararg[0]);
3216 V_VT(&vararg[0]) = VT_BSTR;
3217 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3218 dispparams.cNamedArgs = 0;
3219 dispparams.cArgs = 1;
3220 dispparams.rgdispidNamedArgs = NULL;
3221 dispparams.rgvarg = vararg;
3222 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ARRAY, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3223 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#lx\n", hr);
3224 SysFreeString(V_BSTR(&vararg[0]));
3226 /* call ArrayPtr with BSTR argument - type mismatch */
3227 VariantInit(&vararg[0]);
3228 V_VT(&vararg[0]) = VT_BSTR;
3229 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3230 dispparams.cNamedArgs = 0;
3231 dispparams.cArgs = 1;
3232 dispparams.rgdispidNamedArgs = NULL;
3233 dispparams.rgvarg = vararg;
3234 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARRAYPTR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3235 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#lx\n", hr);
3236 SysFreeString(V_BSTR(&vararg[0]));
3238 /* call VarArg */
3239 VariantInit(&vararg[3]);
3240 V_VT(&vararg[3]) = VT_I4;
3241 V_I4(&vararg[3]) = 3;
3242 VariantInit(&vararg[2]);
3243 V_VT(&vararg[2]) = VT_I4;
3244 V_I4(&vararg[2]) = 0;
3245 VariantInit(&vararg[1]);
3246 V_VT(&vararg[1]) = VT_I4;
3247 V_I4(&vararg[1]) = 1;
3248 VariantInit(&vararg[0]);
3249 V_VT(&vararg[0]) = VT_I4;
3250 V_I4(&vararg[0]) = 2;
3251 dispparams.cNamedArgs = 0;
3252 dispparams.cArgs = 4;
3253 dispparams.rgdispidNamedArgs = NULL;
3254 dispparams.rgvarg = vararg;
3255 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3256 ok_ole_success(hr, IDispatch_Invoke);
3258 /* without any varargs */
3259 dispparams.cArgs = 1;
3260 V_I4(&vararg[0]) = 0;
3261 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3262 ok_ole_success(hr, IDispatch_Invoke);
3264 /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
3265 dispidNamed = 0;
3266 dispparams.cNamedArgs = 1;
3267 dispparams.rgdispidNamedArgs = &dispidNamed;
3268 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3269 ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08lx\n", hr);
3270 dispidNamed = DISPID_PROPERTYPUT;
3272 /* call VarArg_Run */
3273 VariantInit(&vararg[1]);
3274 V_VT(&vararg[1]) = VT_BSTR;
3275 V_BSTR(&vararg[1]) = SysAllocString(szCat);
3276 VariantInit(&vararg[0]);
3277 V_VT(&vararg[0]) = VT_BSTR;
3278 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3279 dispparams.cNamedArgs = 0;
3280 dispparams.cArgs = 2;
3281 dispparams.rgdispidNamedArgs = NULL;
3282 dispparams.rgvarg = vararg;
3283 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3284 ok_ole_success(hr, IDispatch_Invoke);
3285 /* without any varargs */
3286 dispparams.cArgs = 1;
3287 dispparams.rgvarg = vararg + 1;
3288 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3289 ok_ole_success(hr, IDispatch_Invoke);
3290 SysFreeString(V_BSTR(&vararg[1]));
3291 SysFreeString(V_BSTR(&vararg[0]));
3293 /* call VarArg_Ref_Run */
3294 VariantInit(&vararg[1]);
3295 V_VT(&vararg[1]) = VT_BSTR;
3296 V_BSTR(&vararg[1]) = SysAllocString(szCat);
3297 VariantInit(&vararg[0]);
3298 V_VT(&vararg[0]) = VT_BSTR;
3299 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3300 dispparams.cNamedArgs = 0;
3301 dispparams.cArgs = 2;
3302 dispparams.rgdispidNamedArgs = NULL;
3303 dispparams.rgvarg = vararg;
3304 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_REF_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3305 ok_ole_success(hr, IDispatch_Invoke);
3306 /* without any varargs */
3307 dispparams.cArgs = 1;
3308 dispparams.rgvarg = vararg + 1;
3309 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_REF_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3310 ok_ole_success(hr, IDispatch_Invoke);
3311 SysFreeString(V_BSTR(&vararg[1]));
3312 SysFreeString(V_BSTR(&vararg[0]));
3314 /* call Error */
3315 dispparams.cNamedArgs = 0;
3316 dispparams.cArgs = 0;
3317 dispparams.rgdispidNamedArgs = NULL;
3318 dispparams.rgvarg = NULL;
3319 VariantInit(&varresult);
3320 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
3321 ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08lx\n", hr);
3322 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3323 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3324 excepinfo.wCode, excepinfo.scode);
3325 VariantClear(&varresult);
3327 /* call BstrRet */
3328 pTypeInfo = NonOleAutomation_GetTypeInfo();
3329 dispparams.cNamedArgs = 0;
3330 dispparams.cArgs = 0;
3331 dispparams.rgdispidNamedArgs = NULL;
3332 dispparams.rgvarg = NULL;
3333 VariantInit(&varresult);
3334 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3335 ok_ole_success(hr, ITypeInfo_Invoke);
3336 ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
3337 ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
3339 VariantClear(&varresult);
3341 dispparams.cNamedArgs = 0;
3342 dispparams.cArgs = 0;
3343 dispparams.rgdispidNamedArgs = NULL;
3344 dispparams.rgvarg = NULL;
3345 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_ERROR, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3346 ok(hr == DISP_E_EXCEPTION, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08lx\n", hr);
3347 ok(V_VT(&varresult) == VT_EMPTY, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult));
3348 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3349 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3350 excepinfo.wCode, excepinfo.scode);
3351 VariantClear(&varresult);
3353 ITypeInfo_Release(pTypeInfo);
3355 /* tests call put_Name without named arg */
3356 VariantInit(&vararg[0]);
3357 dispparams.cNamedArgs = 0;
3358 dispparams.rgdispidNamedArgs = NULL;
3359 dispparams.cArgs = 1;
3360 dispparams.rgvarg = vararg;
3361 VariantInit(&varresult);
3362 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3363 ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08lx\n", hr);
3364 VariantClear(&varresult);
3366 /* tests param type that cannot be coerced */
3367 VariantInit(&vararg[0]);
3368 V_VT(&vararg[0]) = VT_UNKNOWN;
3369 V_UNKNOWN(&vararg[0]) = NULL;
3370 dispparams.cNamedArgs = 1;
3371 dispparams.rgdispidNamedArgs = &dispidNamed;
3372 dispparams.cArgs = 1;
3373 dispparams.rgvarg = vararg;
3374 VariantInit(&varresult);
3375 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3376 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08lx\n", hr);
3377 VariantClear(&varresult);
3379 /* tests bad param type */
3380 VariantInit(&vararg[0]);
3381 V_VT(&vararg[0]) = VT_CLSID;
3382 V_BYREF(&vararg[0]) = NULL;
3383 dispparams.cNamedArgs = 1;
3384 dispparams.rgdispidNamedArgs = &dispidNamed;
3385 dispparams.cArgs = 1;
3386 dispparams.rgvarg = vararg;
3387 VariantInit(&varresult);
3388 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3389 ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08lx\n", hr);
3390 VariantClear(&varresult);
3392 /* tests too small param count */
3393 dispparams.cNamedArgs = 0;
3394 dispparams.rgdispidNamedArgs = NULL;
3395 dispparams.cArgs = 0;
3396 dispparams.rgvarg = NULL;
3397 VariantInit(&varresult);
3398 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3399 ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08lx\n", hr);
3400 VariantClear(&varresult);
3402 /* tests propget function with large param count */
3403 VariantInit(&vararg[0]);
3404 V_VT(&vararg[0]) = VT_BSTR;
3405 V_BSTR(&vararg[0]) = NULL;
3406 V_VT(&vararg[1]) = VT_I4;
3407 V_I4(&vararg[1]) = 1;
3408 dispparams.cNamedArgs = 0;
3409 dispparams.cArgs = 2;
3410 dispparams.rgdispidNamedArgs = NULL;
3411 dispparams.rgvarg = vararg;
3412 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3413 ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08lx\n", hr);
3415 /* test propput with lcid */
3417 /* the lcid passed to the function is the first lcid in the typelib header.
3418 Since we don't explicitly set an lcid in the idl, it'll default to US English. */
3419 VariantInit(&vararg[0]);
3420 V_VT(&vararg[0]) = VT_I4;
3421 V_I4(&vararg[0]) = 0xcafe;
3422 dispparams.cNamedArgs = 1;
3423 dispparams.rgdispidNamedArgs = &dispidNamed;
3424 dispparams.cArgs = 1;
3425 dispparams.rgvarg = vararg;
3426 VariantInit(&varresult);
3427 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3428 ok_ole_success(hr, ITypeInfo_Invoke);
3429 VariantClear(&varresult);
3431 /* test propget with lcid */
3432 dispparams.cNamedArgs = 0;
3433 dispparams.cArgs = 0;
3434 dispparams.rgvarg = NULL;
3435 dispparams.rgdispidNamedArgs = NULL;
3436 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3437 ok_ole_success(hr, ITypeInfo_Invoke);
3438 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3439 ok(V_I4(&varresult) == 0x409, "got %lx\n", V_I4(&varresult));
3440 VariantClear(&varresult);
3442 /* test propget of INT value */
3443 dispparams.cNamedArgs = 0;
3444 dispparams.cArgs = 0;
3445 dispparams.rgvarg = NULL;
3446 dispparams.rgdispidNamedArgs = NULL;
3447 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_INT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3448 ok_ole_success(hr, ITypeInfo_Invoke);
3449 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3450 ok(V_I4(&varresult) == -13, "got %lx\n", V_I4(&varresult));
3451 VariantClear(&varresult);
3453 /* test propget of INT value */
3454 dispparams.cNamedArgs = 0;
3455 dispparams.cArgs = 0;
3456 dispparams.rgvarg = NULL;
3457 dispparams.rgdispidNamedArgs = NULL;
3458 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_UINT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3459 ok_ole_success(hr, ITypeInfo_Invoke);
3460 ok(V_VT(&varresult) == VT_UI4, "got %x\n", V_VT(&varresult));
3461 ok(V_UI4(&varresult) == 42, "got %lx\n", V_UI4(&varresult));
3462 VariantClear(&varresult);
3464 /* test byref marshalling */
3465 uval = 666;
3466 VariantInit(&vararg[0]);
3467 V_VT(&vararg[0]) = VT_UI4|VT_BYREF;
3468 V_UI4REF(&vararg[0]) = (ULONG *)&uval;
3469 dispparams.cNamedArgs = 0;
3470 dispparams.cArgs = 1;
3471 dispparams.rgvarg = vararg;
3472 dispparams.rgdispidNamedArgs = NULL;
3473 hr = IDispatch_Invoke(pDispatch, DISPID_TM_BYREF_UINT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3474 ok_ole_success(hr, ITypeInfo_Invoke);
3475 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3476 ok(V_VT(&vararg[0]) == (VT_UI4|VT_BYREF), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg[0]));
3477 ok(V_UI4REF(&vararg[0]) == (ULONG *)&uval, "Byref pointer not preserved: %p/%p\n", &uval, V_UI4REF(&vararg[0]));
3478 ok(*V_UI4REF(&vararg[0]) == 42, "Expected 42 to be returned instead of %lu\n", *V_UI4REF(&vararg[0]));
3479 VariantClear(&varresult);
3480 VariantClear(&vararg[0]);
3482 /* test propput with optional argument. */
3483 VariantInit(&vararg[0]);
3484 V_VT(&vararg[0]) = VT_I4;
3485 V_I4(&vararg[0]) = 0xcafe;
3486 dispparams.cNamedArgs = 1;
3487 dispparams.rgdispidNamedArgs = &dispidNamed;
3488 dispparams.cArgs = 1;
3489 dispparams.rgvarg = vararg;
3490 VariantInit(&varresult);
3491 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_OPT_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3492 ok_ole_success(hr, ITypeInfo_Invoke);
3493 VariantClear(&varresult);
3495 /* test propput with required argument. */
3496 VariantInit(&vararg[0]);
3497 VariantInit(&vararg[1]);
3498 V_VT(&vararg[0]) = VT_I4;
3499 V_I4(&vararg[0]) = 0x1234;
3500 V_VT(&vararg[1]) = VT_I4;
3501 V_I4(&vararg[1]) = 0x5678;
3502 dispparams.cNamedArgs = 1;
3503 dispparams.rgdispidNamedArgs = &dispidNamed;
3504 dispparams.cArgs = 2;
3505 dispparams.rgvarg = vararg;
3506 VariantInit(&varresult);
3507 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_REQ_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3508 ok_ole_success(hr, ITypeInfo_Invoke);
3509 VariantClear(&varresult);
3511 /* restricted member */
3512 dispparams.cNamedArgs = 0;
3513 dispparams.rgdispidNamedArgs = NULL;
3514 dispparams.cArgs = 0;
3515 dispparams.rgvarg = NULL;
3516 VariantInit(&varresult);
3517 hr = IDispatch_Invoke(pDispatch, DISPID_TM_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3518 ok( hr == DISP_E_MEMBERNOTFOUND, "got %08lx\n", hr );
3519 VariantClear(&varresult);
3521 /* restricted member with -ve memid (not restricted) */
3522 dispparams.cNamedArgs = 0;
3523 dispparams.rgdispidNamedArgs = NULL;
3524 dispparams.cArgs = 0;
3525 dispparams.rgvarg = NULL;
3526 VariantInit(&varresult);
3527 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NEG_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3528 ok( hr == S_OK, "got %08lx\n", hr );
3529 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3530 ok(V_I4(&varresult) == DISPID_TM_NEG_RESTRICTED, "got %lx\n", V_I4(&varresult));
3531 VariantClear(&varresult);
3533 test_marshal_basetypes(pWidget, pDispatch);
3534 test_marshal_pointer(pWidget, pDispatch);
3535 test_marshal_iface(pWidget, pDispatch);
3536 test_marshal_bstr(pWidget, pDispatch);
3537 test_marshal_variant(pWidget, pDispatch);
3538 test_marshal_safearray(pWidget, pDispatch);
3539 test_marshal_struct(pWidget, pDispatch);
3540 test_marshal_array(pWidget, pDispatch);
3541 test_marshal_coclass(pWidget, pDispatch);
3543 IDispatch_Release(pDispatch);
3544 IWidget_Release(pWidget);
3546 trace("calling end_host_object\n");
3547 end_host_object(tid, thread);
3550 static void test_DispCallFunc(void)
3552 static const WCHAR szEmpty[] = { 0 };
3553 VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
3554 VARIANTARG vararg[4];
3555 VARIANTARG varref;
3556 VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
3557 VARIANTARG varresult;
3558 HRESULT hr;
3559 IWidget *pWidget = Widget_Create();
3560 V_VT(&vararg[0]) = VT_R8;
3561 V_R8(&vararg[0]) = 3.141;
3562 V_VT(&vararg[1]) = VT_BSTR;
3563 V_BSTRREF(&vararg[1]) = CoTaskMemAlloc(sizeof(BSTR));
3564 V_VT(&vararg[2]) = VT_BSTR;
3565 V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
3566 V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
3567 V_VARIANTREF(&vararg[3]) = &varref;
3568 V_VT(&varref) = VT_ERROR;
3569 V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
3570 VariantInit(&varresult);
3571 hr = DispCallFunc(pWidget, 9*sizeof(void*), CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
3572 ok_ole_success(hr, DispCallFunc);
3573 VariantClear(&varresult);
3574 SysFreeString(*V_BSTRREF(&vararg[1]));
3575 CoTaskMemFree(V_BSTRREF(&vararg[1]));
3576 VariantClear(&vararg[2]);
3577 IWidget_Release(pWidget);
3580 static void test_StaticWidget(void)
3582 ITypeInfo *type_info;
3583 DISPPARAMS dispparams;
3584 VARIANTARG vararg[4];
3585 EXCEPINFO excepinfo;
3586 VARIANT varresult;
3587 HRESULT hr;
3589 type_info = get_type_info(&IID_IStaticWidget);
3591 /* call TestDual */
3592 dispparams.cNamedArgs = 0;
3593 dispparams.cArgs = 1;
3594 dispparams.rgdispidNamedArgs = NULL;
3595 dispparams.rgvarg = vararg;
3596 V_VT(vararg) = VT_DISPATCH;
3597 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
3598 VariantInit(&varresult);
3599 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTDUAL, DISPATCH_METHOD,
3600 &dispparams, &varresult, &excepinfo, NULL);
3601 ok_ole_success(hr, IDispatch_Invoke);
3602 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
3603 VariantClear(&varresult);
3605 /* call TestSecondIface */
3606 dispparams.cNamedArgs = 0;
3607 dispparams.cArgs = 1;
3608 dispparams.rgdispidNamedArgs = NULL;
3609 dispparams.rgvarg = vararg;
3610 V_VT(vararg) = VT_DISPATCH;
3611 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
3612 VariantInit(&varresult);
3613 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTSECONDIFACE, DISPATCH_METHOD,
3614 &dispparams, &varresult, &excepinfo, NULL);
3615 ok_ole_success(hr, IDispatch_Invoke);
3616 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
3617 VariantClear(&varresult);
3619 ITypeInfo_Release(type_info);
3622 static void test_libattr(void)
3624 ITypeLib *pTypeLib;
3625 HRESULT hr;
3626 TLIBATTR *pattr;
3628 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
3629 ok_ole_success(hr, LoadRegTypeLib);
3630 if (FAILED(hr))
3631 return;
3633 hr = ITypeLib_GetLibAttr(pTypeLib, &pattr);
3634 ok_ole_success(hr, GetLibAttr);
3635 if (SUCCEEDED(hr))
3637 ok(pattr->lcid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "lcid %lx\n", pattr->lcid);
3639 ITypeLib_ReleaseTLibAttr(pTypeLib, pattr);
3642 ITypeLib_Release(pTypeLib);
3645 static void test_external_connection(void)
3647 IStream *stream, *stream2;
3648 ITestSecondDisp *second;
3649 ItestDual *iface;
3650 HANDLE thread;
3651 DWORD tid;
3652 HRESULT hres;
3654 static const LARGE_INTEGER zero;
3656 trace("Testing IExternalConnection...\n");
3658 external_connections = 0;
3660 /* Marshaling an interface increases external connection count. */
3661 expect_last_release_closes = FALSE;
3662 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3663 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08lx\n", hres);
3664 tid = start_host_object(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHLFLAGS_NORMAL, &thread);
3665 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3667 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3668 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
3669 ok(hres == S_OK, "CoUnmarshalInterface failed: %08lx\n", hres);
3670 if (FAILED(hres))
3672 end_host_object(tid, thread);
3673 IStream_Release(stream);
3674 return;
3676 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3678 IStream_Release(stream);
3679 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3681 /* Creating a stub for new iface causes new external connection. */
3682 hres = ItestDual_QueryInterface(iface, &IID_ITestSecondDisp, (void**)&second);
3683 ok(hres == S_OK, "Could not get ITestSecondDisp iface: %08lx\n", hres);
3684 todo_wine
3685 ok(external_connections == 2, "external_connections = %d\n", external_connections);
3687 ITestSecondDisp_Release(second);
3688 todo_wine
3689 ok(external_connections == 2, "external_connections = %d\n", external_connections);
3691 expect_last_release_closes = TRUE;
3692 ItestDual_Release(iface);
3693 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3695 end_host_object(tid, thread);
3697 /* A test with direct CoMarshalInterface call. */
3698 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3699 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08lx\n", hres);
3701 expect_last_release_closes = FALSE;
3702 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3703 ok(hres == S_OK, "CoMarshalInterface failed: %08lx\n", hres);
3704 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3706 expect_last_release_closes = TRUE;
3707 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3708 hres = CoReleaseMarshalData(stream);
3709 ok(hres == S_OK, "CoReleaseMarshalData failed: %08lx\n", hres);
3710 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3712 /* Two separated marshal data are still one external connection. */
3713 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream2);
3714 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08lx\n", hres);
3716 expect_last_release_closes = FALSE;
3717 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3718 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3719 ok(hres == S_OK, "CoMarshalInterface failed: %08lx\n", hres);
3720 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3722 hres = CoMarshalInterface(stream2, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3723 ok(hres == S_OK, "CoMarshalInterface failed: %08lx\n", hres);
3724 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3726 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3727 hres = CoReleaseMarshalData(stream);
3728 ok(hres == S_OK, "CoReleaseMarshalData failed: %08lx\n", hres);
3729 ok(external_connections == 1, "external_connections = %d\n", external_connections);
3731 expect_last_release_closes = TRUE;
3732 IStream_Seek(stream2, zero, STREAM_SEEK_SET, NULL);
3733 hres = CoReleaseMarshalData(stream2);
3734 ok(hres == S_OK, "CoReleaseMarshalData failed: %08lx\n", hres);
3735 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3737 IStream_Release(stream);
3738 IStream_Release(stream2);
3740 /* Weak table marshaling does not increment external connections */
3741 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3742 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08lx\n", hres);
3744 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
3745 ok(hres == S_OK, "CoMarshalInterface failed: %08lx\n", hres);
3746 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3748 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3749 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
3750 ok(hres == S_OK, "CoUnmarshalInterface failed: %08lx\n", hres);
3751 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3752 ItestDual_Release(iface);
3754 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3755 hres = CoReleaseMarshalData(stream);
3756 ok(hres == S_OK, "CoReleaseMarshalData failed: %08lx\n", hres);
3757 ok(external_connections == 0, "external_connections = %d\n", external_connections);
3759 IStream_Release(stream);
3762 static void test_marshal_dispinterface(void)
3764 static const LARGE_INTEGER zero;
3766 ISomethingFromDispatch *disp_obj = create_disp_obj2(false);
3767 ITypeInfo *typeinfo = NULL;
3768 IDispatch *proxy_disp;
3769 IStream *stream;
3770 HANDLE thread;
3771 HRESULT hr;
3772 ULONG ref;
3773 DWORD tid;
3775 CreateStreamOnHGlobal(NULL, TRUE, &stream);
3776 tid = start_host_object(stream, &DIID_ItestIF4, (IUnknown *)disp_obj, MSHLFLAGS_NORMAL, &thread);
3777 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3778 hr = CoUnmarshalInterface(stream, &DIID_ItestIF4, (void **)&proxy_disp);
3779 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3781 hr = IDispatch_GetTypeInfo(proxy_disp, 0xdeadbeef, 0, &typeinfo);
3782 ok(hr == 0xbeefdead, "Got hr %#lx.\n", hr);
3784 ref = IDispatch_Release(proxy_disp);
3785 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3786 ref = IStream_Release(stream);
3787 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3788 end_host_object(tid, thread);
3789 ref = ISomethingFromDispatch_Release(disp_obj);
3790 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3793 START_TEST(tmarshal)
3795 HRESULT hr;
3797 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3799 hr = register_current_module_typelib();
3800 if (FAILED(hr))
3802 CoUninitialize();
3803 win_skip("Registration of the test typelib failed, skipping tests\n");
3804 return;
3807 test_typelibmarshal();
3808 test_DispCallFunc();
3809 test_StaticWidget();
3810 test_libattr();
3811 test_external_connection();
3812 test_marshal_dispinterface();
3814 hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
3815 sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
3816 ok_ole_success(hr, UnRegisterTypeLib);
3818 CoUninitialize();