ReactOS  0.4.14-dev-49-gfb4591c
tmarshal.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2006 Robert Shearman for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  */
19 
20 #include <math.h>
21 
22 #define COBJMACROS
23 #define CONST_VTABLE
24 
25 #include <windows.h>
26 #include <ocidl.h>
27 #include <stdio.h>
28 
29 #include "wine/test.h"
30 
31 #include "tmarshal.h"
32 
34 
35 
36 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
37 static inline void release_iface_(unsigned int line, void *iface)
38 {
39  ULONG ref = IUnknown_Release((IUnknown *)iface);
40  ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
41  if (ref == 1) IUnknown_Release((IUnknown *)iface);
42 }
43 #define release_iface(a) release_iface_(__LINE__, a)
44 
45 /* ULL suffix is not portable */
46 #define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
47 
48 static const WCHAR test_bstr1[] = {'f','o','o',0,'b','a','r'};
49 static const WCHAR test_bstr2[] = {'t','e','s','t',0};
50 static const WCHAR test_bstr3[] = {'q','u','x',0};
51 static const WCHAR test_bstr4[] = {'a','b','c',0};
52 
53 static const MYSTRUCT test_mystruct1 = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432), {0,1,2,3,4,5,6,7}};
54 static const MYSTRUCT test_mystruct2 = {0x91827364, ULL_CONST(0x88776655, 0x44332211), {3,6,1,4,0,1,3,0}};
55 static const MYSTRUCT test_mystruct3 = {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415), {9,2,4,5,6,5,1,3}};
56 static const MYSTRUCT test_mystruct4 = {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425), {0,4,6,7,3,6,7,4}};
57 static const MYSTRUCT test_mystruct5 = {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435), {1,6,7,3,8,4,6,5}};
58 static const MYSTRUCT test_mystruct6 = {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445), {3,6,5,3,4,8,0,9}};
59 static const MYSTRUCT test_mystruct7 = {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455), {1,8,4,4,4,2,3,1}};
60 
61 static const struct thin test_thin_struct = {-456, 78};
62 
63 static const RECT test_rect1 = {1,2,3,4};
64 static const RECT test_rect2 = {5,6,7,8};
65 static const RECT test_rect3 = {9,10,11,12};
66 static const RECT test_rect4 = {13,14,15,16};
67 static const RECT test_rect5 = {17,18,19,20};
68 static const RECT test_rect6 = {21,22,23,24};
69 static const RECT test_rect7 = {25,26,27,28};
70 
71 static const array_t test_array1 = {1,2,3,4};
72 static const array_t test_array2 = {5,6,7,8};
73 static const array_t test_array3 = {9,10,11,12};
74 static const array_t test_array4 = {13,14,15,16};
75 static const array_t test_array5 = {17,18,19,20};
76 static const array_t test_array6 = {21,22,23,24};
77 
78 #define RELEASEMARSHALDATA WM_USER
79 
80 struct host_object_data
81 {
82  IStream *stream;
83  IID iid;
85  MSHLFLAGS marshal_flags;
88 };
89 
91 {
92  struct host_object_data *data = p;
93  HRESULT hr;
94  MSG msg;
95 
97 
98  if (data->filter)
99  {
100  IMessageFilter * prev_filter = NULL;
101  hr = CoRegisterMessageFilter(data->filter, &prev_filter);
102  if (prev_filter) IMessageFilter_Release(prev_filter);
104  }
105 
106  hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
108 
109  /* force the message queue to be created before signaling parent thread */
111 
112  SetEvent(data->marshal_event);
113 
114  while (GetMessageA(&msg, NULL, 0, 0))
115  {
116  if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
117  {
118  trace("releasing marshal data\n");
119  CoReleaseMarshalData(data->stream);
120  SetEvent((HANDLE)msg.lParam);
121  }
122  else
124  }
125 
127 
128  CoUninitialize();
129 
130  return hr;
131 }
132 
134 {
135  DWORD tid = 0;
137  struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
138 
139  data->stream = stream;
140  data->iid = *riid;
141  data->object = object;
142  data->marshal_flags = marshal_flags;
143  data->marshal_event = marshal_event;
144  data->filter = filter;
145 
147 
148  /* wait for marshaling to complete before returning */
151 
152  return tid;
153 }
154 
156 {
158 }
159 
160 #if 0 /* not used */
161 /* asks thread to release the marshal data because it has to be done by the
162  * same thread that marshaled the interface in the first place. */
163 static void release_host_object(DWORD tid)
164 {
165  HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
169 }
170 #endif
171 
173 {
175  ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
176  /* be careful of races - don't return until hosting thread has terminated */
179 }
180 
183 
185 {
186  ok(0, "unexpected call\n");
187  *ppv = NULL;
188  return E_NOINTERFACE;
189 }
190 
192 {
193  return 2;
194 }
195 
197 {
198  return 1;
199 }
200 
202 {
203  trace("add connection\n");
204 
205  ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
206  ok(!reserved, "reserved = %x\n", reserved);
207  return ++external_connections;
208 }
209 
211  DWORD reserved, BOOL fLastReleaseCloses)
212 {
213  trace("release connection\n");
214 
215  ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
216  ok(!reserved, "reserved = %x\n", reserved);
217 
218  ok(fLastReleaseCloses == expect_last_release_closes, "fLastReleaseCloses = %x, expected %x\n",
219  fLastReleaseCloses, expect_last_release_closes);
220  return --external_connections;
221 }
222 
223 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
229 };
230 
232 
233 static ItestDual TestDual, TestDualDisp;
234 
235 static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
236 {
237  return ItestDual_QueryInterface(&TestDual, riid, ppv);
238 }
239 
240 static ULONG WINAPI TestSecondIface_AddRef(ITestSecondIface *iface)
241 {
242  return 2;
243 }
244 
245 static ULONG WINAPI TestSecondIface_Release(ITestSecondIface *iface)
246 {
247  return 1;
248 }
249 
250 static HRESULT WINAPI TestSecondIface_test(ITestSecondIface *iface)
251 {
252  return 1;
253 }
254 
255 static const ITestSecondIfaceVtbl TestSecondIfaceVtbl = {
260 };
261 
262 static ITestSecondIface TestSecondIface = { &TestSecondIfaceVtbl };
263 
264 static HRESULT WINAPI TestSecondDisp_QueryInterface(ITestSecondDisp *iface, REFIID riid, void **ppv)
265 {
266  return ItestDual_QueryInterface(&TestDual, riid, ppv);
267 }
268 
269 static ULONG WINAPI TestSecondDisp_AddRef(ITestSecondDisp *iface)
270 {
271  return 2;
272 }
273 
274 static ULONG WINAPI TestSecondDisp_Release(ITestSecondDisp *iface)
275 {
276  return 1;
277 }
278 
279 static HRESULT WINAPI TestSecondDisp_GetTypeInfoCount(ITestSecondDisp *iface, UINT *pctinfo)
280 {
281  ok(0, "unexpected call\n");
282  return E_NOTIMPL;
283 }
284 
285 static HRESULT WINAPI TestSecondDisp_GetTypeInfo(ITestSecondDisp *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
286 {
287  ok(0, "unexpected call\n");
288  return E_NOTIMPL;
289 }
290 
291 static HRESULT WINAPI TestSecondDisp_GetIDsOfNames(ITestSecondDisp *iface, REFIID riid, LPOLESTR *rgszNames,
292  UINT cNames, LCID lcid, DISPID *rgDispId)
293 {
294  ok(0, "unexpected call\n");
295  return E_NOTIMPL;
296 }
297 
298 static HRESULT WINAPI TestSecondDisp_Invoke(ITestSecondDisp *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
299  WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
300  UINT *puArgErr)
301 {
302  ok(0, "unexpected call\n");
303  return E_NOTIMPL;
304 }
305 
306 static HRESULT WINAPI TestSecondDisp_test(ITestSecondDisp *iface)
307 {
308  ok(0, "unexpected call\n");
309  return E_NOTIMPL;
310 }
311 
312 static ITestSecondDispVtbl TestSecondDispVtbl = {
321 };
322 
323 static ITestSecondDisp TestSecondDisp = { &TestSecondDispVtbl };
324 
325 static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, void **ppvObject)
326 {
329  return S_OK;
330  }else if(IsEqualGUID(riid, &IID_ItestDual)) {
331  *ppvObject = &TestDual;
332  return S_OK;
333  }else if(IsEqualGUID(riid, &IID_ITestSecondIface)) {
335  return S_OK;
336  }else if(IsEqualGUID(riid, &IID_ITestSecondDisp)) {
338  return S_OK;
339  }else if (IsEqualGUID(riid, &IID_IExternalConnection)) {
340  trace("QI external connection\n");
342  return S_OK;
343  }
344 
345  *ppvObject = NULL;
346  return E_NOINTERFACE;
347 }
348 
349 static ULONG WINAPI TestDual_AddRef(ItestDual *iface)
350 {
351  return 2;
352 }
353 
354 static ULONG WINAPI TestDual_Release(ItestDual *iface)
355 {
356  return 1;
357 }
358 
359 static HRESULT WINAPI TestDual_GetTypeInfoCount(ItestDual *iface, UINT *pctinfo)
360 {
361  ok(0, "unexpected call\n");
362  return E_NOTIMPL;
363 }
364 
365 static HRESULT WINAPI TestDual_GetTypeInfo(ItestDual *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
366 {
367  ok(0, "unexpected call\n");
368  return E_NOTIMPL;
369 }
370 
371 static HRESULT WINAPI TestDual_GetIDsOfNames(ItestDual *iface, REFIID riid, LPOLESTR *rgszNames,
372  UINT cNames, LCID lcid, DISPID *rgDispId)
373 {
374  ok(0, "unexpected call\n");
375  return E_NOTIMPL;
376 }
377 
378 static HRESULT WINAPI TestDual_Invoke(ItestDual *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
379  WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
380  UINT *puArgErr)
381 {
382  ok(0, "unexpected call\n");
383  return E_NOTIMPL;
384 }
385 
386 static ItestDualVtbl TestDualVtbl = {
394 };
395 
396 static ItestDual TestDual = { &TestDualVtbl };
397 static ItestDual TestDualDisp = { &TestDualVtbl };
398 
399 struct disp_obj
400 {
401  ISomethingFromDispatch ISomethingFromDispatch_iface;
403 };
404 
405 static inline struct disp_obj *impl_from_ISomethingFromDispatch(ISomethingFromDispatch *iface)
406 {
408 }
409 
410 static HRESULT WINAPI disp_obj_QueryInterface(ISomethingFromDispatch *iface, REFIID iid, void **out)
411 {
413  || IsEqualGUID(iid, &IID_ISomethingFromDispatch))
414  {
415  *out = iface;
416  ISomethingFromDispatch_AddRef(iface);
417  return S_OK;
418  }
419 
420  *out = NULL;
421  return E_NOINTERFACE;
422 }
423 
424 static ULONG WINAPI disp_obj_AddRef(ISomethingFromDispatch *iface)
425 {
427  return ++obj->ref;
428 }
429 
430 static ULONG WINAPI disp_obj_Release(ISomethingFromDispatch *iface)
431 {
433  LONG ref = --obj->ref;
434  if (!ref)
436  return ref;
437 }
438 
439 static HRESULT WINAPI disp_obj_GetTypeInfoCount(ISomethingFromDispatch *iface, UINT *count)
440 {
441  ok(0, "unexpected call\n");
442  return E_NOTIMPL;
443 }
444 
445 static HRESULT WINAPI disp_obj_GetTypeInfo(ISomethingFromDispatch *iface,
446  UINT index, LCID lcid, ITypeInfo **typeinfo)
447 {
448  ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
449  return 0xbeefdead;
450 }
451 
452 static HRESULT WINAPI disp_obj_GetIDsOfNames(ISomethingFromDispatch *iface,
453  REFIID iid, LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
454 {
455  ok(0, "unexpected call\n");
456  return E_NOTIMPL;
457 }
458 
459 static HRESULT WINAPI disp_obj_Invoke(ISomethingFromDispatch *iface, DISPID id, REFIID iid, LCID lcid,
460  WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
461 {
462  ok(0, "unexpected call\n");
463  return E_NOTIMPL;
464 }
465 
466 static HRESULT WINAPI disp_obj_anotherfn(ISomethingFromDispatch *iface)
467 {
468  return 0x01234567;
469 }
470 
471 static const ISomethingFromDispatchVtbl disp_obj_vtbl =
472 {
481 };
482 
483 static ISomethingFromDispatch *create_disp_obj(void)
484 {
485  struct disp_obj *obj = CoTaskMemAlloc(sizeof(*obj));
486  obj->ISomethingFromDispatch_iface.lpVtbl = &disp_obj_vtbl;
487  obj->ref = 1;
488  return &obj->ISomethingFromDispatch_iface;
489 }
490 
492 {
493  ICoclass1 ICoclass1_iface;
494  ICoclass2 ICoclass2_iface;
496 };
497 
498 static inline struct coclass_obj *impl_from_ICoclass1(ICoclass1 *iface)
499 {
500  return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass1_iface);
501 }
502 
503 static inline struct coclass_obj *impl_from_ICoclass2(ICoclass2 *iface)
504 {
505  return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass2_iface);
506 }
507 
508 static HRESULT WINAPI coclass1_QueryInterface(ICoclass1 *iface, REFIID iid, void **out)
509 {
510  struct coclass_obj *obj = impl_from_ICoclass1(iface);
511 
512  if (IsEqualGUID(iid, &IID_IUnknown)
513  || IsEqualGUID(iid, &IID_IDispatch)
514  || IsEqualGUID(iid, &IID_ICoclass1))
515  {
516  *out = iface;
517  ICoclass1_AddRef(iface);
518  return S_OK;
519  }
520  else if (IsEqualGUID(iid, &IID_ICoclass2))
521  {
522  *out = &obj->ICoclass2_iface;
523  ICoclass2_AddRef(*out);
524  return S_OK;
525  }
526 
527  *out = NULL;
528  return E_NOINTERFACE;
529 }
530 
531 static ULONG WINAPI coclass1_AddRef(ICoclass1 *iface)
532 {
533  struct coclass_obj *obj = impl_from_ICoclass1(iface);
534  return ++obj->ref;
535 }
536 
537 static ULONG WINAPI coclass1_Release(ICoclass1 *iface)
538 {
539  struct coclass_obj *obj = impl_from_ICoclass1(iface);
540  LONG ref = --obj->ref;
541  if (!ref)
543  return ref;
544 }
545 
547 {
548  ok(0, "unexpected call\n");
549  return E_NOTIMPL;
550 }
551 
552 static HRESULT WINAPI coclass1_GetTypeInfo(ICoclass1 *iface, UINT index,
553  LCID lcid, ITypeInfo **typeinfo)
554 {
555  ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
556  return 0xbeefdead;
557 }
558 
559 static HRESULT WINAPI coclass1_GetIDsOfNames(ICoclass1 *iface, REFIID iid,
560  LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
561 {
562  ok(0, "unexpected call\n");
563  return E_NOTIMPL;
564 }
565 
566 static HRESULT WINAPI coclass1_Invoke(ICoclass1 *iface, DISPID id, REFIID iid, LCID lcid,
567  WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
568 {
569  ok(0, "unexpected call\n");
570  return E_NOTIMPL;
571 }
572 
573 static HRESULT WINAPI coclass1_test(ICoclass1 *iface)
574 {
575  return 1;
576 }
577 
578 static HRESULT WINAPI coclass2_QueryInterface(ICoclass2 *iface, REFIID iid, void **out)
579 {
580  struct coclass_obj *obj = impl_from_ICoclass2(iface);
581  return ICoclass1_QueryInterface(&obj->ICoclass1_iface, iid, out);
582 }
583 
584 static ULONG WINAPI coclass2_AddRef(ICoclass2 *iface)
585 {
586  struct coclass_obj *obj = impl_from_ICoclass2(iface);
587  return ICoclass1_AddRef(&obj->ICoclass1_iface);
588 }
589 
590 static ULONG WINAPI coclass2_Release(ICoclass2 *iface)
591 {
592  struct coclass_obj *obj = impl_from_ICoclass2(iface);
593  return ICoclass1_Release(&obj->ICoclass1_iface);
594 }
595 
597 {
598  ok(0, "unexpected call\n");
599  return E_NOTIMPL;
600 }
601 
602 static HRESULT WINAPI coclass2_GetTypeInfo(ICoclass2 *iface, UINT index,
603  LCID lcid, ITypeInfo **typeinfo)
604 {
605  ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
606  return 0xbeefdead;
607 }
608 
609 static HRESULT WINAPI coclass2_GetIDsOfNames(ICoclass2 *iface, REFIID iid,
610  LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
611 {
612  ok(0, "unexpected call\n");
613  return E_NOTIMPL;
614 }
615 
616 static HRESULT WINAPI coclass2_Invoke(ICoclass2 *iface, DISPID id, REFIID iid, LCID lcid,
617  WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
618 {
619  ok(0, "unexpected call\n");
620  return E_NOTIMPL;
621 }
622 
623 static HRESULT WINAPI coclass2_test(ICoclass2 *iface)
624 {
625  return 2;
626 }
627 
628 static const ICoclass1Vtbl coclass1_vtbl =
629 {
638 };
639 
640 static const ICoclass2Vtbl coclass2_vtbl =
641 {
650 };
651 
652 static struct coclass_obj *create_coclass_obj(void)
653 {
654  struct coclass_obj *obj = CoTaskMemAlloc(sizeof(*obj));
655  obj->ICoclass1_iface.lpVtbl = &coclass1_vtbl;
656  obj->ICoclass2_iface.lpVtbl = &coclass2_vtbl;
657  obj->ref = 1;
658  return obj;
659 };
660 
661 static int testmode;
662 
663 typedef struct Widget
664 {
665  IWidget IWidget_iface;
668 } Widget;
669 
670 static inline Widget *impl_from_IWidget(IWidget *iface)
671 {
672  return CONTAINING_RECORD(iface, Widget, IWidget_iface);
673 }
674 
676  IWidget *iface,
677  /* [in] */ REFIID riid,
678  /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
679 {
680  if (IsEqualIID(riid, &IID_IWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
681  {
682  IWidget_AddRef(iface);
683  *ppvObject = iface;
684  return S_OK;
685  }
686  else
687  {
688  *ppvObject = NULL;
689  return E_NOINTERFACE;
690  }
691 }
692 
694  IWidget *iface)
695 {
696  Widget *This = impl_from_IWidget(iface);
697 
698  return InterlockedIncrement(&This->refs);
699 }
700 
702  IWidget *iface)
703 {
704  Widget *This = impl_from_IWidget(iface);
705  ULONG refs = InterlockedDecrement(&This->refs);
706  if (!refs)
707  {
708  IUnknown_Release(This->pDispatchUnknown);
709  memset(This, 0xcc, sizeof(*This));
711  trace("Widget destroyed!\n");
712  }
713 
714  return refs;
715 }
716 
718  IWidget *iface,
719  /* [out] */ UINT __RPC_FAR *pctinfo)
720 {
721  Widget *This = impl_from_IWidget(iface);
722  IDispatch *pDispatch;
723  HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
724  if (SUCCEEDED(hr))
725  {
726  hr = IDispatch_GetTypeInfoCount(pDispatch, pctinfo);
727  IDispatch_Release(pDispatch);
728  }
729  return hr;
730 }
731 
733  IWidget __RPC_FAR * iface,
734  /* [in] */ UINT iTInfo,
735  /* [in] */ LCID lcid,
736  /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
737 {
738  Widget *This = impl_from_IWidget(iface);
739  IDispatch *pDispatch;
740  HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
741  if (SUCCEEDED(hr))
742  {
743  hr = IDispatch_GetTypeInfo(pDispatch, iTInfo, lcid, ppTInfo);
744  IDispatch_Release(pDispatch);
745  }
746  return hr;
747 }
748 
750  IWidget __RPC_FAR * iface,
751  /* [in] */ REFIID riid,
752  /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
753  /* [in] */ UINT cNames,
754  /* [in] */ LCID lcid,
755  /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
756 {
757  Widget *This = impl_from_IWidget(iface);
758  IDispatch *pDispatch;
759  HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
760  if (SUCCEEDED(hr))
761  {
762  hr = IDispatch_GetIDsOfNames(pDispatch, riid, rgszNames, cNames, lcid, rgDispId);
763  IDispatch_Release(pDispatch);
764  }
765  return hr;
766 }
767 
769  IWidget __RPC_FAR * iface,
770  /* [in] */ DISPID dispIdMember,
771  /* [in] */ REFIID riid,
772  /* [in] */ LCID lcid,
773  /* [in] */ WORD wFlags,
774  /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
775  /* [out] */ VARIANT __RPC_FAR *pVarResult,
776  /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
777  /* [out] */ UINT __RPC_FAR *puArgErr)
778 {
779  Widget *This = impl_from_IWidget(iface);
780  IDispatch *pDispatch;
781  HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
782  if (SUCCEEDED(hr))
783  {
784  hr = IDispatch_Invoke(pDispatch, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
785  IDispatch_Release(pDispatch);
786  }
787  return hr;
788 }
789 
791  IWidget __RPC_FAR * iface,
792  /* [in] */ BSTR name)
793 {
794  trace("put_Name(%s)\n", wine_dbgstr_w(name));
795  return S_OK;
796 }
797 
799  IWidget __RPC_FAR * iface,
800  /* [out] */ BSTR __RPC_FAR *name)
801 {
802  static const WCHAR szCat[] = { 'C','a','t',0 };
803  trace("get_Name()\n");
804  *name = SysAllocString(szCat);
805  return S_OK;
806 }
807 
809  IWidget __RPC_FAR * iface,
810  /* [in] */ double number,
811  /* [out] */ BSTR *str1,
812  /* [defaultvalue][in] */ BSTR str2,
813  /* [optional][in] */ VARIANT __RPC_FAR *opt)
814 {
815  static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
816  trace("DoSomething()\n");
817 
818  ok(number == 3.141, "number(%f) != 3.141\n", number);
819  ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
820  ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt));
821  ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08x\n", V_ERROR(opt));
822  *str1 = SysAllocString(szString);
823 
824  return S_FALSE;
825 }
826 
828  IWidget __RPC_FAR * iface,
829  /* [retval][out] */ STATE __RPC_FAR *state)
830 {
831  trace("get_State() = STATE_WIDGETIFIED\n");
833  return S_OK;
834 }
835 
837  IWidget __RPC_FAR * iface,
838  /* [in] */ STATE state)
839 {
840  trace("put_State(%d)\n", state);
841  return S_OK;
842 }
843 
845  IWidget * iface,
846  BSTR bstrId,
847  BSTR *sValue)
848 {
849  trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId), sValue);
850  *sValue = SysAllocString(bstrId);
851  return S_OK;
852 }
853 
855  IWidget * iface,
856  OLE_COLOR val)
857 {
858  trace("SetOleColor(0x%x)\n", val);
859  return S_OK;
860 }
861 
863  IWidget * iface,
864  OLE_COLOR *pVal)
865 {
866  trace("GetOleColor() = 0x8000000f\n");
867  *pVal = 0x8000000f;
868  return S_FALSE;
869 }
870 
872  IWidget *iface,
873  IWidget **ppVal)
874 {
875  trace("Clone()\n");
876  return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
877 }
878 
880  IWidget *iface,
881  IDispatch **ppVal)
882 {
883  trace("CloneDispatch()\n");
884  return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
885 }
886 
888  IWidget *iface,
889  ApplicationObject2 **ppVal)
890 {
891  trace("CloneCoclass()\n");
892  return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
893 }
894 
896  IWidget __RPC_FAR * iface,
897  VARIANT *value,
898  VARIANT *retval)
899 {
900  trace("Value(%p, %p)\n", value, retval);
901  ok(V_VT(value) == VT_I2, "V_VT(value) was %d instead of VT_I2\n", V_VT(value));
902  ok(V_I2(value) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value));
903  V_VT(retval) = VT_I2;
904  V_I2(retval) = 1234;
905  return S_OK;
906 }
907 
909  IWidget * iface,
910  SAFEARRAY ** values)
911 {
912  trace("VariantArrayPtr(%p)\n", values);
913  return S_OK;
914 }
915 
917  IWidget * iface,
918  int numexpect,
919  SAFEARRAY * values)
920 {
921  LONG lbound, ubound, i;
922  VARIANT * data;
923  HRESULT hr;
924 
925  trace("VarArg(%p)\n", values);
926 
927  hr = SafeArrayGetLBound(values, 1, &lbound);
928  ok(hr == S_OK, "SafeArrayGetLBound failed with %x\n", hr);
929  ok(lbound == 0, "SafeArrayGetLBound returned %d\n", lbound);
930 
931  hr = SafeArrayGetUBound(values, 1, &ubound);
932  ok(hr == S_OK, "SafeArrayGetUBound failed with %x\n", hr);
933  ok(ubound == numexpect-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound, numexpect-1);
934 
936  ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
937 
938  for (i=0; i<=ubound-lbound; i++)
939  {
940  ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%d]) was %d\n", i, V_VT(&data[i]));
941  ok(V_I4(&data[i]) == i, "V_I4(&data[%d]) was %d\n", i, V_I4(&data[i]));
942  }
943 
945  ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr);
946 
947  return S_OK;
948 }
949 
951  IWidget __RPC_FAR * iface)
952 {
953  trace("Error()\n");
954  return E_NOTIMPL;
955 }
956 
958  IWidget __RPC_FAR * iface,
959  ISomethingFromDispatch **ppVal)
960 {
961  trace("CloneInterface()\n");
962  *ppVal = 0;
963  return S_OK;
964 }
965 
967  IWidget* iface, LONG lcid, INT i)
968 {
969  trace("put_prop_with_lcid(%08x, %x)\n", lcid, i);
970  ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
971  ok(i == 0xcafe, "got %08x\n", i);
972  return S_OK;
973 }
974 
976  IWidget* iface, LONG lcid, INT *i)
977 {
978  trace("get_prop_with_lcid(%08x, %p)\n", lcid, i);
979  ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
980  *i = lcid;
981  return S_OK;
982 }
983 
985  IWidget* iface, INT *i)
986 {
987  trace("get_prop_int(%p)\n", i);
988  *i = -13;
989  return S_OK;
990 }
991 
993  IWidget* iface, UINT *i)
994 {
995  trace("get_prop_uint(%p)\n", i);
996  *i = 42;
997  return S_OK;
998 }
999 
1001  IWidget* iface, UINT *i)
1002 {
1003  *i = 42;
1004  return S_OK;
1005 }
1006 
1008  IWidget* iface, INT opt, INT i)
1009 {
1010  trace("put_prop_opt_arg(%08x, %08x)\n", opt, i);
1011  todo_wine ok(opt == 0, "got opt=%08x\n", opt);
1012  ok(i == 0xcafe, "got i=%08x\n", i);
1013  return S_OK;
1014 }
1015 
1017  IWidget* iface, INT req, INT i)
1018 {
1019  trace("put_prop_req_arg(%08x, %08x)\n", req, i);
1020  ok(req == 0x5678, "got req=%08x\n", req);
1021  ok(i == 0x1234, "got i=%08x\n", i);
1022  return S_OK;
1023 }
1024 
1025 static HRESULT WINAPI Widget_pos_restrict(IWidget* iface, INT *i)
1026 {
1027  trace("restrict\n");
1029  return S_OK;
1030 }
1031 
1032 static HRESULT WINAPI Widget_neg_restrict(IWidget* iface, INT *i)
1033 {
1034  trace("neg_restrict\n");
1036  return S_OK;
1037 }
1038 
1040  IWidget *iface, BSTR name, SAFEARRAY *params, VARIANT *result)
1041 {
1042  static const WCHAR catW[] = { 'C','a','t',0 };
1043  static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1044  LONG bound;
1045  VARIANT *var;
1046  BSTR bstr;
1047  HRESULT hr;
1048 
1049  trace("VarArg_Run(%p,%p,%p)\n", name, params, result);
1050 
1051  ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1052 
1053  hr = SafeArrayGetLBound(params, 1, &bound);
1054  ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
1055  ok(bound == 0, "expected 0, got %d\n", bound);
1056 
1057  hr = SafeArrayGetUBound(params, 1, &bound);
1058  ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
1059  ok(bound == 0, "expected 0, got %d\n", bound);
1060 
1061  hr = SafeArrayAccessData(params, (void **)&var);
1062  ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
1063 
1064  ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1065  bstr = V_BSTR(&var[0]);
1066  ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1067 
1069  ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
1070 
1071  return S_OK;
1072 }
1073 
1075  IWidget *iface, BSTR name, SAFEARRAY **params, VARIANT *result)
1076 {
1077  static const WCHAR catW[] = { 'C','a','t',0 };
1078  static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1079  LONG bound;
1080  VARIANT *var;
1081  BSTR bstr;
1082  HRESULT hr;
1083 
1084  trace("VarArg_Ref_Run(%p,%p,%p)\n", name, params, result);
1085 
1086  ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1087 
1088  hr = SafeArrayGetLBound(*params, 1, &bound);
1089  ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
1090  ok(bound == 0, "expected 0, got %d\n", bound);
1091 
1092  hr = SafeArrayGetUBound(*params, 1, &bound);
1093  ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
1094  ok(bound == 0, "expected 0, got %d\n", bound);
1095 
1096  hr = SafeArrayAccessData(*params, (void **)&var);
1097  ok(hr == S_OK, "SafeArrayAccessData error %#x\n", hr);
1098 
1099  ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1100  bstr = V_BSTR(&var[0]);
1101  ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1102 
1104  ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
1105 
1106  return S_OK;
1107 }
1108 
1109 static HRESULT WINAPI Widget_basetypes_in(IWidget *iface, signed char c, short s, int i, hyper h,
1110  unsigned char uc, unsigned short us, unsigned int ui, MIDL_uhyper uh,
1111  float f, double d, STATE st)
1112 {
1113  ok(c == 5, "Got char %d.\n", c);
1114  ok(s == -123, "Got short %d.\n", s);
1115  ok(i == -100000, "Got int %d.\n", i);
1116  ok(h == (LONGLONG)-100000 * 1000000, "Got hyper %s.\n", wine_dbgstr_longlong(h));
1117  ok(uc == 0, "Got unsigned char %u.\n", uc);
1118  ok(us == 456, "Got unsigned short %u.\n", us);
1119  ok(ui == 0xdeadbeef, "Got unsigned int %i.\n", ui);
1120  ok(uh == (ULONGLONG)1234567890 * 9876543210, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
1121  ok(f == (float)M_PI, "Got float %f.\n", f);
1122  ok(d == M_E, "Got double %f.\n", d);
1123  ok(st == STATE_WIDGETIFIED, "Got state %u.\n", st);
1124 
1125  return S_OK;
1126 }
1127 
1128 static HRESULT WINAPI Widget_basetypes_out(IWidget *iface, signed char *c, short *s, int *i, hyper *h,
1129  unsigned char *uc, unsigned short *us, unsigned int *ui, MIDL_uhyper *uh,
1130  float *f, double *d, STATE *st)
1131 {
1132  *c = 10;
1133  *s = -321;
1134  *i = -200000;
1135  *h = (LONGLONG)-200000 * 1000000;
1136  *uc = 254;
1137  *us = 256;
1138  *ui = 0xf00dfade;
1139  *uh = (((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789;
1140  *f = M_LN2;
1141  *d = M_LN10;
1142  *st = STATE_UNWIDGETIFIED;
1143 
1144  return S_OK;
1145 }
1146 
1147 static HRESULT WINAPI Widget_float_abi(IWidget *iface, float f, double d, int i, float f2, double d2)
1148 {
1149  ok(f == 1.0f, "Got float %f.\n", f);
1150  ok(d == 2.0, "Got double %f.\n", d);
1151  ok(i == 3, "Got int %d.\n", i);
1152  ok(f2 == 4.0f, "Got float %f.\n", f2);
1153  ok(d2 == 5.0, "Got double %f.\n", d2);
1154 
1155  return S_OK;
1156 }
1157 
1158 static HRESULT WINAPI Widget_int_ptr(IWidget *iface, int *in, int *out, int *in_out)
1159 {
1160  ok(*in == 123, "Got [in] %d.\n", *in);
1161  if (testmode == 0) /* Invoke() */
1162  ok(*out == 456, "Got [out] %d.\n", *out);
1163  else if (testmode == 1)
1164  ok(!*out, "Got [out] %d.\n", *out);
1165  ok(*in_out == 789, "Got [in, out] %d.\n", *in_out);
1166 
1167  *in = 987;
1168  *out = 654;
1169  *in_out = 321;
1170 
1171  return S_OK;
1172 }
1173 
1174 static HRESULT WINAPI Widget_int_ptr_ptr(IWidget *iface, int **in, int **out, int **in_out)
1175 {
1176  ok(!*out, "Got [out] %p.\n", *out);
1177  if (testmode == 0)
1178  {
1179  ok(!*in, "Got [in] %p.\n", *in);
1180  ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1181  }
1182  else if (testmode == 1)
1183  {
1184  ok(!*in, "Got [in] %p.\n", *in);
1185  ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1186 
1187  *out = CoTaskMemAlloc(sizeof(int));
1188  **out = 654;
1189  *in_out = CoTaskMemAlloc(sizeof(int));
1190  **in_out = 321;
1191  }
1192  else if (testmode == 2)
1193  {
1194  ok(**in == 123, "Got [in] %d.\n", **in);
1195  ok(**in_out == 789, "Got [in, out] %d.\n", **in_out);
1196 
1197  *out = CoTaskMemAlloc(sizeof(int));
1198  **out = 654;
1199  **in_out = 321;
1200  }
1201  else if (testmode == 3)
1202  {
1203  ok(**in_out == 789, "Got [in, out] %d.\n", **in_out);
1204  *in_out = NULL;
1205  }
1206 
1207  return S_OK;
1208 }
1209 
1210 /* Call methods to check that we have valid proxies to each interface. */
1211 static void check_iface_marshal(IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1212 {
1213  ISomethingFromDispatch *sfd2;
1215  HRESULT hr;
1216 
1217  hr = IUnknown_QueryInterface(unk, &IID_ISomethingFromDispatch, (void **)&sfd2);
1218  ok(hr == S_OK, "Got hr %#x.\n", hr);
1219  ISomethingFromDispatch_Release(sfd2);
1220 
1221  hr = IDispatch_GetTypeInfo(disp, 0xdeadbeef, 0, &typeinfo);
1222  ok(hr == 0xbeefdead, "Got hr %#x.\n", hr);
1223 
1224  hr = ISomethingFromDispatch_anotherfn(sfd);
1225  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1226 }
1227 
1228 static HRESULT WINAPI Widget_iface_in(IWidget *iface, IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1229 {
1230  if (testmode == 0)
1231  check_iface_marshal(unk, disp, sfd);
1232  else if (testmode == 1)
1233  {
1234  ok(!unk, "Got iface %p.\n", unk);
1235  ok(!disp, "Got iface %p.\n", disp);
1236  ok(!sfd, "Got iface %p.\n", sfd);
1237  }
1238  return S_OK;
1239 }
1240 
1241 static HRESULT WINAPI Widget_iface_out(IWidget *iface, IUnknown **unk, IDispatch **disp, ISomethingFromDispatch **sfd)
1242 {
1243  ok(!*unk, "Got iface %p.\n", *unk);
1244  ok(!*disp, "Got iface %p.\n", *disp);
1245  ok(!*sfd, "Got iface %p.\n", *sfd);
1246 
1247  if (testmode == 0)
1248  {
1249  *unk = (IUnknown *)create_disp_obj();
1250  *disp = (IDispatch *)create_disp_obj();
1251  *sfd = create_disp_obj();
1252  }
1253  return S_OK;
1254 }
1255 
1256 static HRESULT WINAPI Widget_iface_ptr(IWidget *iface, ISomethingFromDispatch **in,
1257  ISomethingFromDispatch **out, ISomethingFromDispatch **in_out)
1258 {
1259  HRESULT hr;
1260 
1261  ok(!*out, "Got [out] %p.\n", *out);
1262  if (testmode == 0 || testmode == 1)
1263  {
1264  hr = ISomethingFromDispatch_anotherfn(*in);
1265  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1266  hr = ISomethingFromDispatch_anotherfn(*in_out);
1267  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1268  }
1269 
1270  if (testmode == 1)
1271  {
1272  *out = create_disp_obj();
1273  ISomethingFromDispatch_Release(*in_out);
1274  *in_out = create_disp_obj();
1275  }
1276  else if (testmode == 2)
1277  {
1278  ok(!*in, "Got [in] %p.\n", *in);
1279  ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1280  *in_out = create_disp_obj();
1281  }
1282  else if (testmode == 3)
1283  {
1284  hr = ISomethingFromDispatch_anotherfn(*in_out);
1285  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1286  ISomethingFromDispatch_Release(*in_out);
1287  *in_out = NULL;
1288  }
1289 
1290  return S_OK;
1291 }
1292 
1293 static HRESULT WINAPI Widget_bstr(IWidget *iface, BSTR in, BSTR *out, BSTR *in_ptr, BSTR *in_out)
1294 {
1295  UINT len;
1296 
1297  if (testmode == 0)
1298  {
1299  len = SysStringByteLen(in);
1300  ok(len == sizeof(test_bstr1), "Got wrong length %u.\n", len);
1301  ok(!memcmp(in, test_bstr1, len), "Got string %s.\n", wine_dbgstr_wn(in, len / sizeof(WCHAR)));
1302  ok(!*out, "Got unexpected output %p.\n", *out);
1303  len = SysStringLen(*in_ptr);
1304  ok(len == lstrlenW(test_bstr2), "Got wrong length %u.\n", len);
1305  ok(!memcmp(*in_ptr, test_bstr2, len), "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1306  len = SysStringLen(*in_out);
1307  ok(len == lstrlenW(test_bstr3), "Got wrong length %u.\n", len);
1308  ok(!memcmp(*in_out, test_bstr3, len), "Got string %s.\n", wine_dbgstr_w(*in_out));
1309 
1311  in[1] = (*in_ptr)[1] = (*in_out)[1] = 'X';
1312  }
1313  else if (testmode == 1)
1314  {
1315  ok(!in, "Got string %s.\n", wine_dbgstr_w(in));
1316  ok(!*out, "Got string %s.\n", wine_dbgstr_w(*out));
1317  ok(!*in_ptr, "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1318  ok(!*in_out, "Got string %s.\n", wine_dbgstr_w(*in_out));
1319  }
1320  return S_OK;
1321 }
1322 
1323 static HRESULT WINAPI Widget_variant(IWidget *iface, VARIANT in, VARIANT *out, VARIANT *in_ptr, VARIANT *in_out)
1324 {
1325  ok(V_VT(&in) == VT_CY, "Got wrong type %#x.\n", V_VT(&in));
1326  ok(V_CY(&in).Hi == 0xdababe && V_CY(&in).Lo == 0xdeadbeef,
1327  "Got wrong value %s.\n", wine_dbgstr_longlong(V_CY(&in).int64));
1328  if (testmode == 0)
1329  {
1330  ok(V_VT(out) == VT_I4, "Got wrong type %u.\n", V_VT(out));
1331  ok(V_I4(out) == 1, "Got wrong value %d.\n", V_I4(out));
1332  }
1333  else
1334  ok(V_VT(out) == VT_EMPTY, "Got wrong type %u.\n", V_VT(out));
1335  ok(V_VT(in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(in_ptr));
1336  ok(V_I4(in_ptr) == -1, "Got wrong value %d.\n", V_I4(in_ptr));
1337  ok(V_VT(in_out) == VT_BSTR, "Got wrong type %u.\n", V_VT(in_out));
1338  ok(!lstrcmpW(V_BSTR(in_out), test_bstr2), "Got wrong value %s.\n",
1339  wine_dbgstr_w(V_BSTR(in_out)));
1340 
1341  V_VT(&in) = VT_I4;
1342  V_I4(&in) = 2;
1343  V_VT(out) = VT_UI1;
1344  V_UI1(out) = 3;
1345  V_VT(in_ptr) = VT_I2;
1346  V_I2(in_ptr) = 4;
1347  VariantClear(in_out);
1348  V_VT(in_out) = VT_I1;
1349  V_I1(in_out) = 5;
1350  return S_OK;
1351 }
1352 
1354 {
1356  int i, *data;
1357 
1358  SafeArrayAccessData(sa, (void **)&data);
1359  for (i = 0; i < len; ++i)
1360  data[i] = len + i;
1362 
1363  return sa;
1364 }
1365 
1367 {
1368  LONG len, i, *data;
1369  HRESULT hr;
1370 
1371  hr = SafeArrayGetUBound(sa, 1, &len);
1372  len++;
1373  ok(hr == S_OK, "Got hr %#x.\n", hr);
1374  ok(len == expect, "Expected len %d, got %d.\n", expect, len);
1375 
1376  hr = SafeArrayAccessData(sa, (void **)&data);
1377  ok(hr == S_OK, "Got hr %#x.\n", hr);
1378 
1379  for (i = 0; i < len; ++i)
1380  ok(data[i] == len + i, "Expected data %d at %d, got %d.\n", len + i, i, data[i]);
1381 
1383 }
1384 
1385 static HRESULT WINAPI Widget_safearray(IWidget *iface, SAFEARRAY *in, SAFEARRAY **out, SAFEARRAY **in_ptr, SAFEARRAY **in_out)
1386 {
1387  HRESULT hr;
1388 
1389  check_safearray(in, 3);
1390  ok(!*out, "Got array %p.\n", *out);
1391  check_safearray(*in_ptr, 7);
1392  check_safearray(*in_out, 9);
1393 
1394  hr = SafeArrayDestroy(*in_out);
1395  ok(hr == S_OK, "Got hr %#x.\n", hr);
1396 
1397  *out = make_safearray(4);
1398  *in_out = make_safearray(6);
1399 
1400  return S_OK;
1401 }
1402 
1403 static HRESULT WINAPI Widget_mystruct(IWidget *iface, MYSTRUCT in, MYSTRUCT *out, MYSTRUCT *in_ptr, MYSTRUCT *in_out)
1404 {
1405  static const MYSTRUCT empty = {0};
1406  ok(!memcmp(&in, &test_mystruct1, sizeof(in)), "Structs didn't match.\n");
1407  ok(!memcmp(out, &empty, sizeof(*out)), "Structs didn't match.\n");
1408  ok(!memcmp(in_ptr, &test_mystruct3, sizeof(*in_ptr)), "Structs didn't match.\n");
1409  ok(!memcmp(in_out, &test_mystruct4, sizeof(*in_out)), "Structs didn't match.\n");
1410 
1411  memcpy(out, &test_mystruct5, sizeof(*out));
1412  memcpy(in_ptr, &test_mystruct6, sizeof(*in_ptr));
1413  memcpy(in_out, &test_mystruct7, sizeof(*in_out));
1414  return S_OK;
1415 }
1416 
1418 {
1419  ok(!memcmp(*in, &test_mystruct1, sizeof(**in)), "Structs didn't match.\n");
1420  return S_OK;
1421 }
1422 
1423 static HRESULT WINAPI Widget_thin_struct(IWidget *iface, struct thin in)
1424 {
1425  ok(!memcmp(&in, &test_thin_struct, sizeof(in)), "Structs didn't match.\n");
1426  return S_OK;
1427 }
1428 
1429 static HRESULT WINAPI Widget_rect(IWidget *iface, RECT in, RECT *out, RECT *in_ptr, RECT *in_out)
1430 {
1431  static const RECT empty = {0};
1432  ok(EqualRect(&in, &test_rect1), "Rects didn't match.\n");
1433  ok(EqualRect(out, &empty), "Rects didn't match.\n");
1434  ok(EqualRect(in_ptr, &test_rect3), "Rects didn't match.\n");
1435  ok(EqualRect(in_out, &test_rect4), "Rects didn't match.\n");
1436 
1437  *out = test_rect5;
1438  *in_ptr = test_rect6;
1439  *in_out = test_rect7;
1440  return S_OK;
1441 }
1442 
1443 static HRESULT WINAPI Widget_array(IWidget *iface, array_t in, array_t out, array_t in_out)
1444 {
1445  static const array_t empty = {0};
1446  ok(!memcmp(in, test_array1, sizeof(array_t)), "Arrays didn't match.\n");
1447  ok(!memcmp(out, empty, sizeof(array_t)), "Arrays didn't match.\n");
1448  ok(!memcmp(in_out, test_array3, sizeof(array_t)), "Arrays didn't match.\n");
1449 
1450  memcpy(in, test_array4, sizeof(array_t));
1451  memcpy(out, test_array5, sizeof(array_t));
1452  memcpy(in_out, test_array6, sizeof(array_t));
1453 
1454  return S_OK;
1455 }
1456 
1457 static HRESULT WINAPI Widget_variant_array(IWidget *iface, VARIANT in[2], VARIANT out[2], VARIANT in_out[2])
1458 {
1459  ok(V_VT(&in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in[0]));
1460  ok(V_I4(&in[0]) == 1, "Got wrong value %d.\n", V_I4(&in[0]));
1461  ok(V_VT(&in[1]) == VT_I4, "Got wrong type %u.\n", V_VT(&in[1]));
1462  ok(V_I4(&in[1]) == 2, "Got wrong value %d.\n", V_I4(&in[1]));
1463  ok(V_VT(&out[0]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[0]));
1464  ok(V_VT(&out[1]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[1]));
1465  ok(V_VT(&in_out[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in_out[0]));
1466  ok(V_I4(&in_out[0]) == 5, "Got wrong type %u.\n", V_VT(&in_out[0]));
1467  ok(V_VT(&in_out[1]) == VT_I4, "Got wrong type %u.\n", V_VT(&in_out[1]));
1468  ok(V_I4(&in_out[1]) == 6, "Got wrong type %u.\n", V_VT(&in_out[1]));
1469 
1470  V_VT(&in[0]) = VT_I1; V_I1(&in[0]) = 7;
1471  V_VT(&in[1]) = VT_I1; V_I1(&in[1]) = 8;
1472  V_VT(&out[0]) = VT_I1; V_I1(&out[0]) = 9;
1473  V_VT(&out[1]) = VT_I1; V_I1(&out[1]) = 10;
1474  V_VT(&in_out[0]) = VT_I1; V_I1(&in_out[0]) = 11;
1475  V_VT(&in_out[1]) = VT_I1; V_I1(&in_out[1]) = 12;
1476 
1477  return S_OK;
1478 }
1479 
1480 static HRESULT WINAPI Widget_mystruct_array(IWidget *iface, MYSTRUCT in[2])
1481 {
1482  ok(!memcmp(&in[0], &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1483  ok(!memcmp(&in[1], &test_mystruct2, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1484  return S_OK;
1485 }
1486 
1487 static HRESULT WINAPI Widget_myint(IWidget *iface, myint_t val, myint_t *ptr, myint_t **ptr_ptr)
1488 {
1489  ok(val == 123, "Got value %d.\n", val);
1490  ok(*ptr == 456, "Got single ptr ref %d.\n", *ptr);
1491  ok(**ptr_ptr == 789, "Got double ptr ref %d.\n", **ptr_ptr);
1492  return S_OK;
1493 }
1494 
1495 static HRESULT WINAPI Widget_Coclass(IWidget *iface, Coclass1 *class1, Coclass2 *class2, Coclass3 *class3)
1496 {
1497  HRESULT hr;
1498 
1499  hr = ICoclass1_test((ICoclass1 *)class1);
1500  ok(hr == 1, "Got hr %#x.\n", hr);
1501 
1502  hr = ICoclass2_test((ICoclass2 *)class2);
1503  ok(hr == 2, "Got hr %#x.\n", hr);
1504 
1505  hr = ICoclass1_test((ICoclass1 *)class3);
1506  ok(hr == 1, "Got hr %#x.\n", hr);
1507 
1508  return S_OK;
1509 }
1510 
1511 static HRESULT WINAPI Widget_Coclass_ptr(IWidget *iface, Coclass1 **in, Coclass1 **out, Coclass1 **in_out)
1512 {
1513  struct coclass_obj *obj;
1514  HRESULT hr;
1515 
1516  ok(!*out, "Got [out] %p.\n", *out);
1517  if (testmode == 0 || testmode == 1)
1518  {
1519  hr = ICoclass1_test((ICoclass1 *)*in);
1520  ok(hr == 1, "Got hr %#x.\n", hr);
1521  hr = ICoclass1_test((ICoclass1 *)*in_out);
1522  ok(hr == 1, "Got hr %#x.\n", hr);
1523  }
1524 
1525  if (testmode == 1)
1526  {
1527  obj = create_coclass_obj();
1528  *out = (Coclass1 *)&obj->ICoclass1_iface;
1529 
1530  ICoclass1_Release((ICoclass1 *)*in_out);
1531  obj = create_coclass_obj();
1532  *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1533  }
1534  else if (testmode == 2)
1535  {
1536  ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1537  obj = create_coclass_obj();
1538  *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1539  }
1540  else if (testmode == 3)
1541  {
1542  hr = ICoclass1_test((ICoclass1 *)*in_out);
1543  ok(hr == 1, "Got hr %#x.\n", hr);
1544  ICoclass1_Release((ICoclass1 *)*in_out);
1545  *in_out = NULL;
1546  }
1547 
1548  return S_OK;
1549 }
1550 
1551 static const struct IWidgetVtbl Widget_VTable =
1552 {
1554  Widget_AddRef,
1559  Widget_Invoke,
1565  Widget_Map,
1568  Widget_Clone,
1571  Widget_Value,
1573  Widget_VarArg,
1574  Widget_Error,
1595  Widget_bstr,
1601  Widget_rect,
1602  Widget_array,
1605  Widget_myint,
1608 };
1609 
1610 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
1611 {
1612  if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
1613  {
1614  IStaticWidget_AddRef(iface);
1615  *ppvObject = iface;
1616  return S_OK;
1617  }
1618 
1619  *ppvObject = NULL;
1620  return E_NOINTERFACE;
1621 }
1622 
1623 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
1624 {
1625  return 2;
1626 }
1627 
1628 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
1629 {
1630  return 1;
1631 }
1632 
1633 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
1634 {
1635  ok(0, "unexpected call\n");
1636  return E_NOTIMPL;
1637 }
1638 
1639 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
1640  ITypeInfo **ppTInfo)
1641 {
1642  ok(0, "unexpected call\n");
1643  return E_NOTIMPL;
1644 }
1645 
1646 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
1647  UINT cNames, LCID lcid, DISPID *rgDispId)
1648 {
1649  ok(0, "unexpected call\n");
1650  return E_NOTIMPL;
1651 }
1652 
1653 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
1654  LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1655  UINT *puArgErr)
1656 {
1657  ok(0, "unexpected call\n");
1658  return E_NOTIMPL;
1659 }
1660 
1661 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
1662 {
1663  trace("TestDual()\n");
1664  ok(p == &TestDual, "wrong ItestDual\n");
1665  return S_OK;
1666 }
1667 
1668 static HRESULT WINAPI StaticWidget_TestSecondIface(IStaticWidget *iface, ITestSecondIface *p)
1669 {
1670  trace("TestSecondIface()\n");
1671  ok(p == &TestSecondIface, "wrong ItestSecondIface\n");
1672  return S_OK;
1673 }
1674 
1675 static const IStaticWidgetVtbl StaticWidgetVtbl = {
1685 };
1686 
1687 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
1688 
1689 typedef struct KindaEnum
1690 {
1691  IKindaEnumWidget IKindaEnumWidget_iface;
1693 } KindaEnum;
1694 
1695 static inline KindaEnum *impl_from_IKindaEnumWidget(IKindaEnumWidget *iface)
1696 {
1697  return CONTAINING_RECORD(iface, KindaEnum, IKindaEnumWidget_iface);
1698 }
1699 
1701 {
1702  WCHAR path[MAX_PATH];
1703  CHAR pathA[MAX_PATH];
1704  HRESULT hr;
1705  ITypeLib *typelib;
1706 
1709 
1710  hr = LoadTypeLib(path, &typelib);
1711  if (SUCCEEDED(hr))
1712  {
1714  ITypeLib_Release(typelib);
1715  }
1716  return hr;
1717 }
1718 
1720 {
1721  ITypeInfo *pTypeInfo;
1722  ITypeLib *pTypeLib;
1723  HRESULT hr;
1724 
1725  hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1727  if (FAILED(hr))
1728  return NULL;
1729 
1730  hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
1731  ITypeLib_Release(pTypeLib);
1732  ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1733  if (FAILED(hr))
1734  return NULL;
1735 
1736  return pTypeInfo;
1737 }
1738 
1739 static IWidget *Widget_Create(void)
1740 {
1741  Widget *This;
1742  ITypeInfo *pTypeInfo;
1743  HRESULT hr = E_FAIL;
1744 
1745  pTypeInfo = get_type_info(&IID_IWidget);
1746  if(!pTypeInfo)
1747  return NULL;
1748 
1749  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1750  This->IWidget_iface.lpVtbl = &Widget_VTable;
1751  This->refs = 1;
1752  This->pDispatchUnknown = NULL;
1753 
1754  hr = CreateStdDispatch((IUnknown *)&This->IWidget_iface, This, pTypeInfo,
1755  &This->pDispatchUnknown);
1757  ITypeInfo_Release(pTypeInfo);
1758 
1759  if (SUCCEEDED(hr))
1760  return &This->IWidget_iface;
1761  else
1762  {
1763  HeapFree(GetProcessHeap(), 0, This);
1764  return NULL;
1765  }
1766 }
1767 
1769  IKindaEnumWidget *iface,
1770  /* [in] */ REFIID riid,
1771  /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
1772 {
1773  if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
1774  {
1775  IKindaEnumWidget_AddRef(iface);
1776  *ppvObject = iface;
1777  return S_OK;
1778  }
1779  else
1780  {
1781  *ppvObject = NULL;
1782  return E_NOINTERFACE;
1783  }
1784 }
1785 
1787  IKindaEnumWidget *iface)
1788 {
1790 
1791  return InterlockedIncrement(&This->refs);
1792 }
1793 
1795  IKindaEnumWidget *iface)
1796 {
1798  ULONG refs = InterlockedDecrement(&This->refs);
1799  if (!refs)
1800  {
1801  memset(This, 0xcc, sizeof(*This));
1802  HeapFree(GetProcessHeap(), 0, This);
1803  trace("KindaEnumWidget destroyed!\n");
1804  }
1805 
1806  return refs;
1807 }
1808 
1810  IKindaEnumWidget *iface,
1811  /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
1812 {
1813  *widget = Widget_Create();
1814  if (*widget)
1815  return S_OK;
1816  else
1817  return E_OUTOFMEMORY;
1818 }
1819 
1821  IKindaEnumWidget *iface,
1822  /* [out] */ ULONG __RPC_FAR *count)
1823 {
1824  return E_NOTIMPL;
1825 }
1826 
1828  IKindaEnumWidget *iface)
1829 {
1830  return E_NOTIMPL;
1831 }
1832 
1834  IKindaEnumWidget *iface,
1835  /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
1836 {
1837  return E_NOTIMPL;
1838 }
1839 
1840 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
1841 {
1849 };
1850 
1851 static IKindaEnumWidget *KindaEnumWidget_Create(void)
1852 {
1853  KindaEnum *This;
1854 
1855  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1856  if (!This) return NULL;
1857  This->IKindaEnumWidget_iface.lpVtbl = &KindaEnumWidget_VTable;
1858  This->refs = 1;
1859  return &This->IKindaEnumWidget_iface;
1860 }
1861 
1862 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
1863 {
1864  if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
1865  {
1866  *(INonOleAutomation **)ppv = iface;
1867  return S_OK;
1868  }
1869  *ppv = NULL;
1870  return E_NOINTERFACE;
1871 }
1872 
1873 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
1874 {
1875  return 2;
1876 }
1877 
1878 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
1879 {
1880  return 1;
1881 }
1882 
1883 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
1884 {
1885  static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1886  return SysAllocString(wszTestString);
1887 }
1888 
1889 static HRESULT WINAPI NonOleAutomation_Error(INonOleAutomation *iface)
1890 {
1891  return E_NOTIMPL;
1892 }
1893 
1894 static INonOleAutomationVtbl NonOleAutomation_VTable =
1895 {
1901 };
1902 
1903 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
1904 
1906 {
1907  ITypeLib *pTypeLib;
1908  HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1910  if (SUCCEEDED(hr))
1911  {
1912  ITypeInfo *pTypeInfo;
1913  hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
1914  ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1915  ITypeLib_Release(pTypeLib);
1916  return pTypeInfo;
1917  }
1918  return NULL;
1919 }
1920 
1921 static void test_marshal_basetypes(IWidget *widget, IDispatch *disp)
1922 {
1923  VARIANTARG arg[11];
1924  DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
1925  HRESULT hr;
1926 
1927  signed char c;
1928  short s;
1929  int i, i2, *pi;
1930  hyper h;
1931  unsigned char uc;
1932  unsigned short us;
1933  unsigned int ui;
1934  MIDL_uhyper uh;
1935  float f;
1936  double d;
1937  STATE st;
1938 
1939  V_VT(&arg[10]) = VT_I1; V_I1(&arg[10]) = 5;
1940  V_VT(&arg[9]) = VT_I2; V_I2(&arg[9]) = -123;
1941  V_VT(&arg[8]) = VT_I4; V_I4(&arg[8]) = -100000;
1942  V_VT(&arg[7]) = VT_I8; V_I8(&arg[7]) = (LONGLONG)-100000 * 1000000;
1943  V_VT(&arg[6]) = VT_UI1; V_UI1(&arg[6]) = 0;
1944  V_VT(&arg[5]) = VT_UI2; V_UI2(&arg[5]) = 456;
1945  V_VT(&arg[4]) = VT_UI4; V_UI4(&arg[4]) = 0xdeadbeef;
1946  V_VT(&arg[3]) = VT_UI8; V_UI8(&arg[3]) = (ULONGLONG)1234567890 * 9876543210;
1947  V_VT(&arg[2]) = VT_R4; V_R4(&arg[2]) = M_PI;
1948  V_VT(&arg[1]) = VT_R8; V_R8(&arg[1]) = M_E;
1949  V_VT(&arg[0]) = VT_I4; V_I4(&arg[0]) = STATE_WIDGETIFIED;
1950  hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_IN, &IID_NULL, LOCALE_NEUTRAL,
1951  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1952  ok(hr == S_OK, "Got hr %#x.\n", hr);
1953 
1954  hr = IWidget_basetypes_in(widget, 5, -123, -100000, (LONGLONG)-100000 * 1000000, 0, 456,
1955  0xdeadbeef, (ULONGLONG)1234567890 * 9876543210, M_PI, M_E, STATE_WIDGETIFIED);
1956  ok(hr == S_OK, "Got hr %#x.\n", hr);
1957 
1958  c = s = i = h = uc = us = ui = uh = f = d = st = 0;
1959 
1960  V_VT(&arg[10]) = VT_BYREF|VT_I1; V_I1REF(&arg[10]) = &c;
1961  V_VT(&arg[9]) = VT_BYREF|VT_I2; V_I2REF(&arg[9]) = &s;
1962  V_VT(&arg[8]) = VT_BYREF|VT_I4; V_I4REF(&arg[8]) = &i;
1963  V_VT(&arg[7]) = VT_BYREF|VT_I8; V_I8REF(&arg[7]) = &h;
1964  V_VT(&arg[6]) = VT_BYREF|VT_UI1; V_UI1REF(&arg[6]) = &uc;
1965  V_VT(&arg[5]) = VT_BYREF|VT_UI2; V_UI2REF(&arg[5]) = &us;
1966  V_VT(&arg[4]) = VT_BYREF|VT_UI4; V_UI4REF(&arg[4]) = &ui;
1967  V_VT(&arg[3]) = VT_BYREF|VT_UI8; V_UI8REF(&arg[3]) = &uh;
1968  V_VT(&arg[2]) = VT_BYREF|VT_R4; V_R4REF(&arg[2]) = &f;
1969  V_VT(&arg[1]) = VT_BYREF|VT_R8; V_R8REF(&arg[1]) = &d;
1970  V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = (int *)&st;
1971  hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_OUT, &IID_NULL, LOCALE_NEUTRAL,
1972  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1973  ok(hr == S_OK, "Got hr %#x.\n", hr);
1974  ok(c == 10, "Got char %d.\n", c);
1975  ok(s == -321, "Got short %d.\n", s);
1976  ok(i == -200000, "Got int %d.\n", i);
1977  ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
1978  ok(uc == 254, "Got unsigned char %u.\n", uc);
1979  ok(us == 256, "Got unsigned short %u.\n", us);
1980  ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui);
1981  ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789),
1982  "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
1983  ok(f == (float)M_LN2, "Got float %f.\n", f);
1984  ok(d == M_LN10, "Got double %f.\n", d);
1985  ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
1986 
1987  c = s = i = h = uc = us = ui = uh = f = d = st = 0;
1988 
1989  hr = IWidget_basetypes_out(widget, &c, &s, &i, &h, &uc, &us, &ui, &uh, &f, &d, &st);
1990  ok(hr == S_OK, "Got hr %#x.\n", hr);
1991  ok(c == 10, "Got char %d.\n", c);
1992  ok(s == -321, "Got short %d.\n", s);
1993  ok(i == -200000, "Got int %d.\n", i);
1994  ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
1995  ok(uc == 254, "Got unsigned char %u.\n", uc);
1996  ok(us == 256, "Got unsigned short %u.\n", us);
1997  ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui);
1998  ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789),
1999  "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
2000  ok(f == (float)M_LN2, "Got float %f.\n", f);
2001  ok(d == M_LN10, "Got double %f.\n", d);
2002  ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
2003 
2004  /* Test marshalling of public typedefs. */
2005 
2006  i = 456;
2007  i2 = 789;
2008  pi = &i2;
2009  hr = IWidget_myint(widget, 123, &i, &pi);
2010  ok(hr == S_OK, "Got hr %#x.\n", hr);
2011 
2012  /* Test that different float ABIs are correctly handled. */
2013 
2014  hr = IWidget_float_abi(widget, 1.0f, 2.0, 3, 4.0f, 5.0);
2015  ok(hr == S_OK, "Got hr %#x.\n", hr);
2016 }
2017 
2018 static void test_marshal_pointer(IWidget *widget, IDispatch *disp)
2019 {
2020  VARIANTARG arg[3];
2021  DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2022  int in, out, in_out, *in_ptr, *out_ptr, *in_out_ptr;
2023  HRESULT hr;
2024 
2025  testmode = 0;
2026 
2027  in = 123;
2028  out = 456;
2029  in_out = 789;
2030  V_VT(&arg[2]) = VT_BYREF|VT_I4; V_I4REF(&arg[2]) = &in;
2031  V_VT(&arg[1]) = VT_BYREF|VT_I4; V_I4REF(&arg[1]) = &out;
2032  V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = &in_out;
2033  hr = IDispatch_Invoke(disp, DISPID_TM_INT_PTR, &IID_NULL, LOCALE_NEUTRAL,
2034  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2035  ok(hr == S_OK, "Got hr %#x.\n", hr);
2036  ok(in == 987, "Got [in] %d.\n", in);
2037  ok(out == 654, "Got [out] %d.\n", out);
2038  ok(in_out == 321, "Got [in, out] %d.\n", in_out);
2039 
2040  testmode = 1;
2041 
2042  in = 123;
2043  out = 456;
2044  in_out = 789;
2045  hr = IWidget_int_ptr(widget, &in, &out, &in_out);
2046  ok(hr == S_OK, "Got hr %#x.\n", hr);
2047  ok(in == 123, "Got [in] %d.\n", in);
2048  ok(out == 654, "Got [out] %d.\n", out);
2049  ok(in_out == 321, "Got [in, out] %d.\n", in_out);
2050 
2051  out = in_out = -1;
2052  hr = IWidget_int_ptr(widget, NULL, &out, &in_out);
2053  ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2054  ok(!out, "[out] parameter should have been cleared.\n");
2055  ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2056 
2057  in = in_out = -1;
2058  hr = IWidget_int_ptr(widget, &in, NULL, &in_out);
2059  ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2060  ok(in == -1, "[in] parameter should not have been cleared.\n");
2061  ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2062 
2063  in = out = -1;
2064  hr = IWidget_int_ptr(widget, &in, &out, NULL);
2065  ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2066  ok(in == -1, "[in] parameter should not have been cleared.\n");
2067  ok(!out, "[out] parameter should have been cleared.\n");
2068 
2069  /* We can't test Invoke() with double pointers, as it is not possible to fit
2070  * more than one level of indirection into a VARIANTARG. */
2071 
2072  testmode = 0;
2073  in_ptr = out_ptr = in_out_ptr = NULL;
2074  hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2075  ok(hr == S_OK, "Got hr %#x\n", hr);
2076  ok(!in_ptr, "Got [in] %p.\n", in_ptr);
2077  ok(!out_ptr, "Got [out] %p.\n", out_ptr);
2078  ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2079 
2080  testmode = 1;
2081  hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2082  ok(hr == S_OK, "Got hr %#x\n", hr);
2083  ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr);
2084  ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr);
2085  CoTaskMemFree(out_ptr);
2086  CoTaskMemFree(in_out_ptr);
2087 
2088  testmode = 2;
2089  in = 123;
2090  out = 456;
2091  in_out = 789;
2092  in_ptr = &in;
2093  out_ptr = &out;
2094  in_out_ptr = &in_out;
2095  hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2096  ok(hr == S_OK, "Got hr %#x.\n", hr);
2097  ok(out_ptr != &out, "[out] ptr should have changed.\n");
2098  ok(in_out_ptr == &in_out, "[in, out] ptr should not have changed.\n");
2099  ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr);
2100  ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr);
2101 
2102  testmode = 3;
2103  in_ptr = out_ptr = NULL;
2104  in_out = 789;
2105  in_out_ptr = &in_out;
2106  hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2107  ok(hr == S_OK, "Got hr %#x.\n", hr);
2108  ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2109 
2110  out_ptr = &out;
2111  in_out_ptr = &in_out;
2112  hr = IWidget_int_ptr_ptr(widget, NULL, &out_ptr, &in_out_ptr);
2113  ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2114  ok(!out_ptr, "[out] parameter should have been cleared.\n");
2115  ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2116 
2117  in_ptr = &in;
2118  in_out_ptr = &in_out;
2119  hr = IWidget_int_ptr_ptr(widget, &in_ptr, NULL, &in_out_ptr);
2120  ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2121  ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2122  ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2123 
2124  in_ptr = &in;
2125  out_ptr = &out;
2126  hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, NULL);
2127  ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2128  ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2129  ok(!out_ptr, "[out] parameter should have been cleared.\n");
2130 }
2131 
2132 static void test_marshal_iface(IWidget *widget, IDispatch *disp)
2133 {
2134  VARIANTARG arg[3];
2135  DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2136  ISomethingFromDispatch *sfd1, *sfd2, *sfd3, *proxy_sfd, *sfd_in, *sfd_out, *sfd_in_out;
2137  IUnknown *proxy_unk, *proxy_unk2, *unk_in, *unk_out, *unk_in_out;
2138  IDispatch *proxy_disp;
2139  HRESULT hr;
2140 
2141  testmode = 0;
2142  sfd1 = create_disp_obj();
2143  sfd2 = create_disp_obj();
2144  sfd3 = create_disp_obj();
2145  hr = IWidget_iface_in(widget, (IUnknown *)sfd1,
2146  (IDispatch *)sfd2, sfd3);
2147  ok(hr == S_OK, "Got hr %#x.\n", hr);
2148  release_iface(sfd1);
2149  release_iface(sfd2);
2150  release_iface(sfd3);
2151 
2152  testmode = 1;
2153  hr = IWidget_iface_in(widget, NULL, NULL, NULL);
2154  ok(hr == S_OK, "Got hr %#x.\n", hr);
2155 
2156  testmode = 0;
2157  proxy_unk = (IUnknown *)0xdeadbeef;
2158  proxy_disp = (IDispatch *)0xdeadbeef;
2159  proxy_sfd = (ISomethingFromDispatch *)0xdeadbeef;
2160  hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2161  ok(hr == S_OK, "Got hr %#x.\n", hr);
2162  check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2163  release_iface(proxy_unk);
2164  release_iface(proxy_disp);
2165  release_iface(proxy_sfd);
2166 
2167  testmode = 1;
2168  hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2169  ok(hr == S_OK, "Got hr %#x.\n", hr);
2170  ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2171  ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2172  ok(!proxy_sfd, "Got unexpected proxy %p.\n", proxy_sfd);
2173 
2174  testmode = 0;
2175  sfd_in = sfd1 = create_disp_obj();
2176  sfd_out = sfd2 = create_disp_obj();
2177  sfd_in_out = sfd3 = create_disp_obj();
2178  hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2179  ok(hr == S_OK, "Got hr %#x.\n", hr);
2180  ok(sfd_in == sfd1, "[in] parameter should not have changed.\n");
2181  ok(!sfd_out, "[out] parameter should have been cleared.\n");
2182  ok(sfd_in_out == sfd3, "[in, out] parameter should not have changed.\n");
2183  release_iface(sfd1);
2184  release_iface(sfd2);
2185  release_iface(sfd3);
2186 
2187  testmode = 1;
2188  sfd_in = sfd1 = create_disp_obj();
2189  sfd_in_out = sfd3 = create_disp_obj();
2190  ISomethingFromDispatch_AddRef(sfd_in_out);
2191  hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2192  ok(hr == S_OK, "Got hr %#x.\n", hr);
2193  hr = ISomethingFromDispatch_anotherfn(sfd_out);
2194  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2195  ok(sfd_in_out != sfd3, "[in, out] parameter should have changed.\n");
2196  hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2197  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2198  release_iface(sfd_out);
2199  release_iface(sfd_in_out);
2200  release_iface(sfd1);
2201  release_iface(sfd3);
2202 
2203  testmode = 2;
2204  sfd_in = sfd_out = sfd_in_out = NULL;
2205  hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2206  ok(hr == S_OK, "Got hr %#x.\n", hr);
2207  ok(!sfd_out, "[out] parameter should not have been set.\n");
2208  hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2209  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2210  release_iface(sfd_in_out);
2211 
2212  testmode = 3;
2213  sfd_in = sfd_out = NULL;
2214  sfd_in_out = sfd3 = create_disp_obj();
2215  ISomethingFromDispatch_AddRef(sfd_in_out);
2216  hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2217  ok(hr == S_OK, "Got hr %#x.\n", hr);
2218  ok(!sfd_in_out, "Got [in, out] %p.\n", sfd_in_out);
2219  release_iface(sfd3);
2220 
2221  /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2222  * interface back, but rather an IUnknown. */
2223 
2224  testmode = 0;
2225  sfd1 = create_disp_obj();
2226  sfd2 = create_disp_obj();
2227  sfd3 = create_disp_obj();
2228 
2229  V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)sfd1;
2230  V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)sfd2;
2231  V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)sfd3;
2232  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2233  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2234  ok(hr == S_OK, "Got hr %#x.\n", hr);
2235 
2236  V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)sfd1;
2237  V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)sfd2;
2238  V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)sfd3;
2239  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2240  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2241  ok(hr == S_OK, "Got hr %#x.\n", hr);
2242 
2243  release_iface(sfd1);
2244  release_iface(sfd2);
2245  release_iface(sfd3);
2246 
2247  testmode = 1;
2248  V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = NULL;
2249  V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = NULL;
2250  V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = NULL;
2251  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2252  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2253  ok(hr == S_OK, "Got hr %#x.\n", hr);
2254 
2255  testmode = 0;
2256  proxy_unk = proxy_unk2 = NULL;
2257  proxy_disp = NULL;
2258  V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &proxy_unk;
2259  V_VT(&arg[1]) = VT_DISPATCH|VT_BYREF; V_DISPATCHREF(&arg[1]) = &proxy_disp;
2260  V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &proxy_unk2;
2261  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2262  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2263 todo_wine
2264  ok(hr == S_OK, "Got hr %#x.\n", hr);
2265 if (hr == S_OK) {
2266  hr = IUnknown_QueryInterface(proxy_unk2, &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
2267  ok(hr == S_OK, "Got hr %#x.\n", hr);
2268  check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2269  ISomethingFromDispatch_Release(proxy_sfd);
2270  release_iface(proxy_unk);
2271  release_iface(proxy_disp);
2272  release_iface(proxy_unk2);
2273 }
2274 
2275  testmode = 1;
2276  proxy_unk = proxy_unk2 = NULL;
2277  proxy_disp = NULL;
2278  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2279  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2280 todo_wine
2281  ok(hr == S_OK, "Got hr %#x.\n", hr);
2282  ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2283  ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2284  ok(!proxy_unk2, "Got unexpected proxy %p.\n", proxy_unk2);
2285 
2286  testmode = 0;
2287  sfd1 = create_disp_obj();
2288  sfd3 = create_disp_obj();
2289  unk_in = (IUnknown *)sfd1;
2290  unk_out = NULL;
2291  unk_in_out = (IUnknown *)sfd3;
2292  V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &unk_in;
2294  V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2295  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2296  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2297 todo_wine
2298  ok(hr == S_OK, "Got hr %#x.\n", hr);
2299  ok(unk_in == (IUnknown *)sfd1, "[in] parameter should not have changed.\n");
2300  ok(!unk_out, "[out] parameter should have been cleared.\n");
2301  ok(unk_in_out == (IUnknown *)sfd3, "[in, out] parameter should not have changed.\n");
2302  release_iface(sfd1);
2303  release_iface(sfd3);
2304 
2305  testmode = 1;
2306  sfd1 = create_disp_obj();
2307  sfd3 = create_disp_obj();
2308  unk_in = (IUnknown *)sfd1;
2309  unk_out = NULL;
2310  unk_in_out = (IUnknown *)sfd3;
2311  IUnknown_AddRef(unk_in_out);
2312  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2313  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2314 todo_wine
2315  ok(hr == S_OK, "Got hr %#x.\n", hr);
2316 
2317 if (hr == S_OK) {
2318  hr = IUnknown_QueryInterface(unk_out, &IID_ISomethingFromDispatch, (void **)&sfd_out);
2319  ok(hr == S_OK, "Got hr %#x.\n", hr);
2320  hr = ISomethingFromDispatch_anotherfn(sfd_out);
2321  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2322  ISomethingFromDispatch_Release(sfd_out);
2323 
2324  ok(unk_in_out != (IUnknown *)sfd3, "[in, out] parameter should have changed.\n");
2325  hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2326  ok(hr == S_OK, "Got hr %#x.\n", hr);
2327  hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2328  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2329  ISomethingFromDispatch_Release(sfd_in_out);
2330 
2332  release_iface(unk_in_out);
2333 }
2334  release_iface(sfd1);
2335 todo_wine
2336  release_iface(sfd3);
2337 
2338  testmode = 2;
2339  unk_in = unk_out = unk_in_out = NULL;
2340  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2341  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2342 todo_wine
2343  ok(hr == S_OK, "Got hr %#x.\n", hr);
2344 
2345  ok(!unk_out, "[out] parameter should not have been set.\n");
2346 if (hr == S_OK) {
2347  hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2348  ok(hr == S_OK, "Got hr %#x.\n", hr);
2349  hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2350  ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2351  ISomethingFromDispatch_Release(sfd_in_out);
2352 
2353  release_iface(unk_in_out);
2354 }
2355 
2356  testmode = 3;
2357  unk_in = unk_out = NULL;
2358  sfd3 = create_disp_obj();
2359  unk_in_out = (IUnknown *)sfd3;
2360  IUnknown_AddRef(unk_in_out);
2361  hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2362  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2363 todo_wine {
2364  ok(hr == S_OK, "Got hr %#x.\n", hr);
2365  ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2366  release_iface(sfd3);
2367 }
2368 }
2369 
2370 static void test_marshal_bstr(IWidget *widget, IDispatch *disp)
2371 {
2372  VARIANTARG arg[4];
2373  DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2374  BSTR in, out, in_ptr, in_out;
2375  HRESULT hr;
2376  UINT len;
2377 
2378  testmode = 0;
2380  out = NULL;
2381  in_ptr = SysAllocString(test_bstr2);
2382  in_out = SysAllocString(test_bstr3);
2383 
2384  V_VT(&arg[3]) = VT_BSTR; V_BSTR(&arg[3]) = in;
2385  V_VT(&arg[2]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[2]) = &out;
2386  V_VT(&arg[1]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[1]) = &in_ptr;
2387  V_VT(&arg[0]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[0]) = &in_out;
2388  hr = IDispatch_Invoke(disp, DISPID_TM_BSTR, &IID_NULL, LOCALE_NEUTRAL,
2389  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2390  ok(hr == S_OK, "Got hr %#x.\n", hr);
2391  ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2392  ok(in_ptr[1] == 'X', "[in] pointer should be changed.\n");
2393  ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2394  len = SysStringLen(out);
2395  ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2396  ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2397 
2398  in[1] = test_bstr1[1];
2399  in_ptr[1] = test_bstr2[1];
2400  in_out[1] = test_bstr3[1];
2401  SysFreeString(out);
2402  out = (BSTR)0xdeadbeef;
2403  hr = IWidget_bstr(widget, in, &out, &in_ptr, &in_out);
2404  ok(hr == S_OK, "Got hr %#x.\n", hr);
2405  ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2406  ok(in_ptr[1] == test_bstr2[1], "[in] pointer should not be changed.\n");
2407  ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2408  len = SysStringLen(out);
2409  ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2410  ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2411  SysFreeString(in);
2412  SysFreeString(out);
2413  SysFreeString(in_ptr);
2414  SysFreeString(in_out);
2415 
2416  testmode = 1;
2417  out = in_ptr = in_out = NULL;
2418  hr = IWidget_bstr(widget, NULL, &out, &in_ptr, &in_out);
2419  ok(hr == S_OK, "Got hr %#x.\n", hr);
2420 }
2421 
2422 static void test_marshal_variant(IWidget *widget, IDispatch *disp)
2423 {
2424  VARIANTARG arg[4];
2425  DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2426  VARIANT out, in_ptr, in_out;
2427  HRESULT hr;
2428  BSTR bstr;
2429 
2430  testmode = 0;
2431  V_VT(&out) = VT_I4;
2432  V_I4(&out) = 1;
2433  V_VT(&in_ptr) = VT_I4;
2434  V_I4(&in_ptr) = -1;
2435  V_VT(&in_out) = VT_BSTR;
2436  V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2437 
2438  V_VT(&arg[3]) = VT_CY;
2439  V_CY(&arg[3]).Hi = 0xdababe;
2440  V_CY(&arg[3]).Lo = 0xdeadbeef;
2441  V_VT(&arg[2]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[2]) = &out;
2442  V_VT(&arg[1]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[1]) = &in_ptr;
2443  V_VT(&arg[0]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[0]) = &in_out;
2444  hr = IDispatch_Invoke(disp, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL,
2445  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2446  ok(hr == S_OK, "Got hr %#x.\n", hr);
2447  ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2448  ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2449  ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2450  VariantClear(&out);
2451  ok(V_VT(&in_ptr) == VT_I2, "Got wrong type %u.\n", V_VT(&in_ptr));
2452  ok(V_I2(&in_ptr) == 4, "Got wrong value %d.\n", V_I1(&in_ptr));
2453  ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2454  ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2455 
2456  testmode = 1;
2457  V_VT(&out) = VT_I4;
2458  V_I4(&out) = 1;
2459  V_VT(&in_ptr) = VT_I4;
2460  V_I4(&in_ptr) = -1;
2461  V_VT(&in_out) = VT_BSTR;
2462  V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2463  hr = IWidget_variant(widget, arg[3], &out, &in_ptr, &in_out);
2464  ok(hr == S_OK, "Got hr %#x.\n", hr);
2465  ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2466  ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2467  ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2468  ok(V_VT(&in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(&in_ptr));
2469  ok(V_I2(&in_ptr) == -1, "Got wrong value %d.\n", V_I1(&in_ptr));
2470  ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2471  ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2472 }
2473 
2474 static void test_marshal_safearray(IWidget *widget, IDispatch *disp)
2475 {
2476  SAFEARRAY *in, *out, *out2, *in_ptr, *in_out;
2477  HRESULT hr;
2478 
2479  in = make_safearray(3);
2480  out = out2 = make_safearray(5);
2481  in_ptr = make_safearray(7);
2482  in_out = make_safearray(9);
2483  hr = IWidget_safearray(widget, in, &out, &in_ptr, &in_out);
2484  ok(hr == S_OK, "Got hr %#x.\n", hr);
2485  check_safearray(in, 3);
2486  check_safearray(out, 4);
2487  check_safearray(out2, 5);
2488  check_safearray(in_ptr, 7);
2489  check_safearray(in_out, 6);
2490 
2493  SafeArrayDestroy(out2);
2494  SafeArrayDestroy(in_ptr);
2495  SafeArrayDestroy(in_out);
2496 }
2497 
2498 static void test_marshal_struct(IWidget *widget, IDispatch *disp)
2499 {
2500  MYSTRUCT out, in_ptr, in_out, *in_ptr_ptr;
2501  RECT rect_out, rect_in_ptr, rect_in_out;
2502  HRESULT hr;
2503 
2504  memcpy(&out, &test_mystruct2, sizeof(MYSTRUCT));
2505  memcpy(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT));
2506  memcpy(&in_out, &test_mystruct4, sizeof(MYSTRUCT));
2507  hr = IWidget_mystruct(widget, test_mystruct1, &out, &in_ptr, &in_out);
2508  ok(hr == S_OK, "Got hr %#x.\n", hr);
2509  ok(!memcmp(&out, &test_mystruct5, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2510  ok(!memcmp(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2511  ok(!memcmp(&in_out, &test_mystruct7, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2512 
2513  memcpy(&in_ptr, &test_mystruct1, sizeof(MYSTRUCT));
2514  in_ptr_ptr = &in_ptr;
2515  hr = IWidget_mystruct_ptr_ptr(widget, &in_ptr_ptr);
2516  ok(hr == S_OK, "Got hr %#x.\n", hr);
2517 
2518  /* Make sure that "thin" structs (<=8 bytes) are handled correctly in x86-64. */
2519 
2520  hr = IWidget_thin_struct(widget, test_thin_struct);
2521  ok(hr == S_OK, "Got hr %#x.\n", hr);
2522 
2523  /* Make sure we can handle an imported type. */
2524 
2525  rect_out = test_rect2;
2526  rect_in_ptr = test_rect3;
2527  rect_in_out = test_rect4;
2528  hr = IWidget_rect(widget, test_rect1, &rect_out, &rect_in_ptr, &rect_in_out);
2529  ok(hr == S_OK, "Got hr %#x.\n", hr);
2530  ok(EqualRect(&rect_out, &test_rect5), "Rects didn't match.\n");
2531  ok(EqualRect(&rect_in_ptr, &test_rect3), "Rects didn't match.\n");
2532  ok(EqualRect(&rect_in_out, &test_rect7), "Rects didn't match.\n");
2533 }
2534 
2535 static void test_marshal_array(IWidget *widget, IDispatch *disp)
2536 {
2537  VARIANT var_in[2], var_out[2], var_in_out[2];
2538  array_t in, out, in_out;
2539  MYSTRUCT struct_in[2];
2540  HRESULT hr;
2541 
2542  memcpy(in, test_array1, sizeof(array_t));
2543  memcpy(out, test_array2, sizeof(array_t));
2544  memcpy(in_out, test_array3, sizeof(array_t));
2545  hr = IWidget_array(widget, in, out, in_out);
2546  ok(hr == S_OK, "Got hr %#x.\n", hr);
2547  ok(!memcmp(&in, &test_array1, sizeof(array_t)), "Arrays didn't match.\n");
2548  ok(!memcmp(&out, &test_array5, sizeof(array_t)), "Arrays didn't match.\n");
2549  ok(!memcmp(&in_out, &test_array6, sizeof(array_t)), "Arrays didn't match.\n");
2550 
2551  V_VT(&var_in[0]) = VT_I4; V_I4(&var_in[0]) = 1;
2552  V_VT(&var_in[1]) = VT_I4; V_I4(&var_in[1]) = 2;
2553  V_VT(&var_out[0]) = VT_I4; V_I4(&var_out[0]) = 3;
2554  V_VT(&var_out[1]) = VT_I4; V_I4(&var_out[1]) = 4;
2555  V_VT(&var_in_out[0]) = VT_I4; V_I4(&var_in_out[0]) = 5;
2556  V_VT(&var_in_out[1]) = VT_I4; V_I4(&var_in_out[1]) = 6;
2557  hr = IWidget_variant_array(widget, var_in, var_out, var_in_out);
2558  ok(hr == S_OK, "Got hr %#x.\n", hr);
2559  ok(V_VT(&var_in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[0]));
2560  ok(V_I4(&var_in[0]) == 1, "Got wrong value %d.\n", V_I4(&var_in[0]));
2561  ok(V_VT(&var_in[1]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[1]));
2562  ok(V_I4(&var_in[1]) == 2, "Got wrong value %d.\n", V_I4(&var_in[1]));
2563  ok(V_VT(&var_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[0]));
2564  ok(V_I1(&var_out[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out[0]));
2565  ok(V_VT(&var_out[1]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[1]));
2566  ok(V_I1(&var_out[1]) == 10, "Got wrong value %u.\n", V_VT(&var_out[1]));
2567  ok(V_VT(&var_in_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[0]));
2568  ok(V_I1(&var_in_out[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out[0]));
2569  ok(V_VT(&var_in_out[1]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[1]));
2570  ok(V_I1(&var_in_out[1]) == 12, "Got wrong value %u.\n", V_VT(&var_in_out[1]));
2571 
2572  memcpy(&struct_in[0], &test_mystruct1, sizeof(MYSTRUCT));
2573  memcpy(&struct_in[1], &test_mystruct2, sizeof(MYSTRUCT));
2574  hr = IWidget_mystruct_array(widget, struct_in);
2575  ok(hr == S_OK, "Got hr %#x.\n", hr);
2576 }
2577 
2578 static void test_marshal_coclass(IWidget *widget, IDispatch *disp)
2579 {
2580  VARIANTARG arg[3];
2581  DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2582  struct coclass_obj *class1, *class2, *class3;
2583  IUnknown *unk_in, *unk_out, *unk_in_out;
2584  ICoclass1 *in, *out, *in_out;
2585  HRESULT hr;
2586 
2587  class1 = create_coclass_obj();
2588  class2 = create_coclass_obj();
2589  class3 = create_coclass_obj();
2590 
2591  hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass1_iface,
2592  (Coclass2 *)&class2->ICoclass1_iface, (Coclass3 *)&class3->ICoclass1_iface);
2593  ok(hr == S_OK, "Got hr %#x.\n", hr);
2594 
2595  hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass2_iface,
2596  (Coclass2 *)&class2->ICoclass2_iface, (Coclass3 *)&class3->ICoclass2_iface);
2597  ok(hr == S_OK, "Got hr %#x.\n", hr);
2598 
2599  release_iface(&class1->ICoclass1_iface);
2600  release_iface(&class2->ICoclass1_iface);
2601  release_iface(&class3->ICoclass1_iface);
2602 
2603  testmode = 0;
2604  class1 = create_coclass_obj();
2605  class2 = create_coclass_obj();
2606  class3 = create_coclass_obj();
2607  in = &class1->ICoclass1_iface;
2608  out = &class2->ICoclass1_iface;
2609  in_out = &class3->ICoclass1_iface;
2610  hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in, (Coclass1 **)&out, (Coclass1 **)&in_out);
2611  ok(hr == S_OK, "Got hr %#x.\n", hr);
2612  ok(in == &class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2613  ok(!out, "[out] parameter should have been cleared.\n");
2614  ok(in_out == &class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2615  release_iface(&class1->ICoclass1_iface);
2616  release_iface(&class2->ICoclass1_iface);
2617  release_iface(&class3->ICoclass1_iface);
2618 
2619  testmode = 1;
2620  class1 = create_coclass_obj();
2621  class3 = create_coclass_obj();
2622  in = &class1->ICoclass1_iface;
2623  in_out = &class3->ICoclass1_iface;
2624  ICoclass1_AddRef(in_out);
2625  hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2626  (Coclass1 **)&out, (Coclass1 **)&in_out);
2627  ok(hr == S_OK, "Got hr %#x.\n", hr);
2628  hr = ICoclass1_test(out);
2629  ok(hr == 1, "Got hr %#x.\n", hr);
2630  ok(in_out != &class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2631  hr = ICoclass1_test(in_out);
2632  ok(hr == 1, "Got hr %#x.\n", hr);
2633  release_iface(out);
2634  release_iface(in_out);
2635  release_iface(&class1->ICoclass1_iface);
2636  release_iface(&class3->ICoclass1_iface);
2637 
2638  testmode = 2;
2639  in = out = in_out = NULL;
2640  hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2641  (Coclass1 **)&out, (Coclass1 **)&in_out);
2642  ok(hr == S_OK, "Got hr %#x.\n", hr);
2643  hr = ICoclass1_test(in_out);
2644  ok(hr == 1, "Got hr %#x.\n", hr);
2645  release_iface(in_out);
2646 
2647  testmode = 3;
2648  in = out = NULL;
2649  class3 = create_coclass_obj();
2650  in_out = &class3->ICoclass1_iface;
2651  hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2652  (Coclass1 **)&out, (Coclass1 **)&in_out);
2653  ok(hr == S_OK, "Got hr %#x.\n", hr);
2654  ok(!in_out, "Got [in, out] %p.\n", in_out);
2655 
2656  /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2657  * interface back, but rather an IUnknown. */
2658 
2659  class1 = create_coclass_obj();
2660  class2 = create_coclass_obj();
2661  class3 = create_coclass_obj();
2662 
2663  V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass1_iface;
2664  V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass1_iface;
2665  V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass1_iface;
2666  hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2667  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2668  ok(hr == S_OK, "Got hr %#x.\n", hr);
2669 
2670  V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass2_iface;
2671  V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass2_iface;
2672  V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass2_iface;
2673  hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2674  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2675  ok(hr == S_OK, "Got hr %#x.\n", hr);
2676 
2677  V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)&class1->ICoclass1_iface;
2678  V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)&class2->ICoclass1_iface;
2679  V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)&class3->ICoclass1_iface;
2680  hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2681  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2682  ok(hr == S_OK, "Got hr %#x.\n", hr);
2683 
2684  release_iface(&class1->ICoclass1_iface);
2685  release_iface(&class2->ICoclass1_iface);
2686  release_iface(&class3->ICoclass1_iface);
2687 
2688  testmode = 0;
2689  class1 = create_coclass_obj();
2690  class3 = create_coclass_obj();
2691  unk_in = (IUnknown *)&class1->ICoclass1_iface;
2692  unk_out = NULL;
2693  unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2694  V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &unk_in;
2696  V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2697  hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2698  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2699 todo_wine
2700  ok(hr == S_OK, "Got hr %#x.\n", hr);
2701  ok(unk_in == (IUnknown *)&class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2702  ok(!unk_out, "[out] parameter should have been cleared.\n");
2703  ok(unk_in_out == (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2704  release_iface(&class1->ICoclass1_iface);
2705  release_iface(&class3->ICoclass1_iface);
2706 
2707  testmode = 1;
2708  class1 = create_coclass_obj();
2709  class3 = create_coclass_obj();
2710  unk_in = (IUnknown *)&class1->ICoclass1_iface;
2711  unk_out = NULL;
2712  unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2713  IUnknown_AddRef(unk_in_out);
2714  hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2715  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2716 todo_wine
2717  ok(hr == S_OK, "Got hr %#x.\n", hr);
2718 
2719 if (hr == S_OK) {
2720  hr = IUnknown_QueryInterface(unk_out, &IID_ICoclass1, (void **)&out);
2721  ok(hr == S_OK, "Got hr %#x.\n", hr);
2722  hr = ICoclass1_test(out);
2723  ok(hr == 1, "Got hr %#x.\n", hr);
2724  ICoclass1_Release(out);
2725 
2726  ok(unk_in_out != (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2727  hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2728  ok(hr == S_OK, "Got hr %#x.\n", hr);
2729  hr = ICoclass1_test(in_out);
2730  ok(hr == 1, "Got hr %#x.\n", hr);
2731  ICoclass1_Release(in_out);
2732 
2734  release_iface(unk_in_out);
2735 }
2736  release_iface(&class1->ICoclass1_iface);
2737 todo_wine
2738  release_iface(&class3->ICoclass1_iface);
2739 
2740  testmode = 2;
2741  unk_in = unk_out = unk_in_out = NULL;
2742  hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2743  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2744 todo_wine
2745  ok(hr == S_OK, "Got hr %#x.\n", hr);
2746 
2747  ok(!unk_out, "[out] parameter should not have been set.\n");
2748 if (hr == S_OK) {
2749  hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2750  ok(hr == S_OK, "Got hr %#x.\n", hr);
2751  hr = ICoclass1_test(in_out);
2752  ok(hr == 1, "Got hr %#x.\n", hr);
2753  ICoclass1_Release(in_out);
2754 
2755  release_iface(unk_in_out);
2756 }
2757 
2758  testmode = 3;
2759  unk_in = unk_out = NULL;
2760  class3 = create_coclass_obj();
2761  unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2762  IUnknown_AddRef(unk_in_out);
2763  hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2764  DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2765 todo_wine
2766  ok(hr == S_OK, "Got hr %#x.\n", hr);
2767 todo_wine
2768  ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2769 
2770 todo_wine
2771  release_iface(&class3->ICoclass1_iface);
2772 }
2773 
2774 static void test_typelibmarshal(void)
2775 {
2776  static const WCHAR szCat[] = { 'C','a','t',0 };
2777  static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
2778  static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
2779  HRESULT hr;
2780  IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
2781  IWidget *pWidget;
2782  IStream *pStream;
2783  IDispatch *pDispatch;
2784  static const LARGE_INTEGER ullZero;
2786  VARIANT varresult;
2787  DISPID dispidNamed = DISPID_PROPERTYPUT;
2788  DISPPARAMS dispparams;
2789  VARIANTARG vararg[4];
2790  STATE the_state;
2791  HANDLE thread;
2792  DWORD tid;
2793  BSTR bstr;
2794  ITypeInfo *pTypeInfo;
2795  UINT uval;
2796 
2797  ok(pKEW != NULL, "Widget creation failed\n");
2798 
2799  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2801  tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
2802  IKindaEnumWidget_Release(pKEW);
2803 
2804  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2805  hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
2807  IStream_Release(pStream);
2808  if (FAILED(hr))
2809  {
2811  return;
2812  }
2813 
2814  hr = IKindaEnumWidget_Next(pKEW, &pWidget);
2815  ok_ole_success(hr, IKindaEnumWidget_Next);
2816 
2817  IKindaEnumWidget_Release(pKEW);
2818 
2819  /* call GetTypeInfoCount (direct) */
2820  hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2821  ok_ole_success(hr, IWidget_GetTypeInfoCount);
2822  hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2823  ok_ole_success(hr, IWidget_GetTypeInfoCount);
2824 
2825  hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
2826  ok_ole_success(hr, IWidget_QueryInterface);
2827 
2828  /* call put_Name */
2829  VariantInit(&vararg[0]);
2830  dispparams.cNamedArgs = 1;
2831  dispparams.rgdispidNamedArgs = &dispidNamed;
2832  dispparams.cArgs = 1;
2833  dispparams.rgvarg = vararg;
2834  VariantInit(&varresult);
2835  hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
2836  ok_ole_success(hr, IDispatch_Invoke);
2837  ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
2838  "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2839  excepinfo.wCode, excepinfo.scode);
2840  VariantClear(&varresult);
2841 
2842  /* call put_Name (direct) */
2843  bstr = SysAllocString(szSuperman);
2844  hr = IWidget_put_Name(pWidget, bstr);
2845  ok_ole_success(hr, IWidget_put_Name);
2846  SysFreeString(bstr);
2847 
2848  /* call get_Name */
2849  dispparams.cNamedArgs = 0;
2850  dispparams.rgdispidNamedArgs = NULL;
2851  dispparams.cArgs = 0;
2852  dispparams.rgvarg = NULL;
2853  VariantInit(&varresult);
2854  hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
2855  ok_ole_success(hr, IDispatch_Invoke);
2856  ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
2857  "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2858  excepinfo.wCode, excepinfo.scode);
2859  trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
2860  VariantClear(&varresult);
2861 
2862  /* call get_Name (direct) */
2863  bstr = (void *)0xdeadbeef;
2864  hr = IWidget_get_Name(pWidget, &bstr);
2865  ok_ole_success(hr, IWidget_get_Name);
2866  ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
2867  SysFreeString(bstr);
2868 
2869  /* call DoSomething without optional arguments */
2870  VariantInit(&vararg[0]);
2871  VariantInit(&vararg[1]);
2872  V_VT(&vararg[1]) = VT_R8;
2873  V_R8(&vararg[1]) = 3.141;
2874  dispparams.cNamedArgs = 0;
2875  dispparams.cArgs = 2;
2876  dispparams.rgdispidNamedArgs = NULL;
2877  dispparams.rgvarg = vararg;
2878  VariantInit(&varresult);
2879  hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2880  ok_ole_success(hr, IDispatch_Invoke);
2881  ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
2882  VariantClear(&varresult);
2883 
2884  /* call DoSomething with optional argument set to VT_EMPTY */
2885  VariantInit(&vararg[0]);
2886  VariantInit(&vararg[1]);
2887  VariantInit(&vararg[2]);
2888  V_VT(&vararg[2]) = VT_R8;
2889  V_R8(&vararg[2]) = 3.141;
2890  dispparams.cNamedArgs = 0;
2891  dispparams.cArgs = 3;
2892  dispparams.rgdispidNamedArgs = NULL;
2893  dispparams.rgvarg = vararg;
2894  VariantInit(&varresult);
2895  hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2896  ok_ole_success(hr, IDispatch_Invoke);
2897  ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
2898  VariantClear(&varresult);
2899 
2900  /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
2901  VariantInit(&vararg[0]);
2902  VariantInit(&vararg[1]);
2903  VariantInit(&vararg[2]);
2904  VariantInit(&vararg[3]);
2905  V_VT(&vararg[3]) = VT_R8;
2906  V_R8(&vararg[3]) = 3.141;
2907  V_VT(&vararg[1]) = VT_ERROR;
2908  V_ERROR(&vararg[1]) = DISP_E_PARAMNOTFOUND;
2909  V_VT(&vararg[0]) = VT_ERROR;
2910  V_ERROR(&vararg[0]) = DISP_E_PARAMNOTFOUND;
2911  dispparams.cNamedArgs = 0;
2912  dispparams.cArgs = 4;
2913  dispparams.rgdispidNamedArgs = NULL;
2914  dispparams.rgvarg = vararg;
2915  VariantInit(&varresult);
2916  hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2917  ok_ole_success(hr, IDispatch_Invoke);
2918  ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
2919  VariantClear(&varresult);
2920 
2921  /* call get_State */
2922  dispparams.cNamedArgs = 0;
2923  dispparams.cArgs = 0;
2924  dispparams.rgdispidNamedArgs = NULL;
2925  dispparams.rgvarg = NULL;
2926  hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
2927  ok_ole_success(hr, IDispatch_Invoke);
2928  ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
2929 
2930  /* call get_State (direct) */
2931  hr = IWidget_get_State(pWidget, &the_state);
2932  ok_ole_success(hr, IWidget_get_state);
2933  ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
2934 
2935  /* call put_State */
2936  the_state = STATE_WIDGETIFIED;
2937  VariantInit(&vararg[0]);
2938  V_VT(&vararg[0]) = VT_BYREF|VT_I4;
2939  V_I4REF(&vararg[0]) = (int *)&the_state;
2940  dispparams.cNamedArgs = 1;
2941  dispparams.cArgs = 1;
2942  dispparams.rgdispidNamedArgs = &dispidNamed;
2943  dispparams.rgvarg = vararg;
2944  hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
2945  ok_ole_success(hr, IDispatch_Invoke);
2946 
2947  /* call Map */
2948  bstr = SysAllocString(szTestTest);
2949  VariantInit(&vararg[0]);
2950  V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
2951  V_BSTRREF(&vararg[0]) = &bstr;
2952  dispparams.cNamedArgs = 0;
2953  dispparams.cArgs = 1;
2954  dispparams.rgdispidNamedArgs = NULL;
2955  dispparams.rgvarg = vararg;
2956  VariantInit(&varresult);
2957  hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2958  ok_ole_success(hr, IDispatch_Invoke);
2959  ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
2960  ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
2961  VariantClear(&varresult);
2962  SysFreeString(bstr);
2963 
2964  /* call SetOleColor with large negative VT_I4 param */
2965  VariantInit(&vararg[0]);
2966  V_VT(&vararg[0]) = VT_I4;
2967  V_I4(&vararg[0]) = 0x80000005;
2968  dispparams.cNamedArgs = 0;
2969  dispparams.cArgs = 1;
2970  dispparams.rgdispidNamedArgs = NULL;
2971  dispparams.rgvarg = vararg;
2972  hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
2973  ok_ole_success(hr, IDispatch_Invoke);
2974 
2975  /* call GetOleColor */
2976  dispparams.cNamedArgs = 0;
2977  dispparams.cArgs = 0;
2978  dispparams.rgdispidNamedArgs = NULL;
2979  dispparams.rgvarg = NULL;
2980  VariantInit(&varresult);
2981  hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2982  ok_ole_success(hr, IDispatch_Invoke);
2983  VariantClear(&varresult);
2984 
2985  /* call Clone */
2986  dispparams.cNamedArgs = 0;
2987  dispparams.cArgs = 0;
2988  dispparams.rgdispidNamedArgs = NULL;
2989  dispparams.rgvarg = NULL;
2990  VariantInit(&varresult);
2991  hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
2992  ok_ole_success(hr, IDispatch_Invoke);
2993  ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
2994  VariantClear(&varresult);
2995 
2996  /* call CloneInterface */
2997  dispparams.cNamedArgs = 0;
2998  dispparams.cArgs = 0;
2999  dispparams.rgdispidNamedArgs = NULL;
3000  dispparams.rgvarg = NULL;
3001  VariantInit(&varresult);
3002  hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3003  ok_ole_success(hr, IDispatch_Invoke);
3004  ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
3005  VariantClear(&varresult);
3006 
3007  /* call CloneDispatch with automatic value getting */
3008  V_VT(&vararg[0]) = VT_I2;
3009  V_I2(&vararg[0]) = 1;
3010  dispparams.cNamedArgs = 0;
3011  dispparams.rgdispidNamedArgs = NULL;
3012  dispparams.cArgs = 1;
3013  dispparams.rgvarg = vararg;
3014  VariantInit(&varresult);
3015  hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3016  ok_ole_success(hr, IDispatch_Invoke);
3017 
3018  ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3019  "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3020  excepinfo.wCode, excepinfo.scode);
3021 
3022  ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3023  ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3024  VariantClear(&varresult);
3025 
3026  /* call CloneCoclass */
3027  dispparams.cNamedArgs = 0;
3028  dispparams.cArgs = 0;
3029  dispparams.rgdispidNamedArgs = NULL;
3030  dispparams.rgvarg = NULL;
3031  VariantInit(&varresult);
3032  hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3033  ok_ole_success(hr, IDispatch_Invoke);
3034 
3035  ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3036  "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3037  excepinfo.wCode, excepinfo.scode);
3038 
3039  ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
3040  ok(V_DISPATCH(&varresult) != NULL, "expected V_DISPATCH(&varresult) != NULL\n");
3041 
3042  /* call Value with a VT_VARIANT|VT_BYREF type */
3043  V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
3044  V_VARIANTREF(&vararg[0]) = &vararg[1];
3045  V_VT(&vararg[1]) = VT_I2;
3046  V_I2(&vararg[1]) = 1;
3047  dispparams.cNamedArgs = 0;
3048  dispparams.rgdispidNamedArgs = NULL;
3049  dispparams.cArgs = 1;
3050  dispparams.rgvarg = vararg;
3051  VariantInit(&varresult);
3052  hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3053  ok_ole_success(hr, IDispatch_Invoke);
3054 
3055  ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3056  "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3057  excepinfo.wCode, excepinfo.scode);
3058 
3059  ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3060  ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3061  VariantClear(&varresult);
3062 
3063  /* call Array with BSTR argument - type mismatch */
3064  VariantInit(&vararg[0]);
3065  V_VT(&vararg[0]) = VT_BSTR;
3066  V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3067  dispparams.cNamedArgs = 0;
3068  dispparams.cArgs = 1;
3069  dispparams.rgdispidNamedArgs = NULL;
3070  dispparams.rgvarg = vararg;
3071  hr = IDispatch_Invoke(pDispatch, DISPID_TM_ARRAY, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3072  ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
3073  SysFreeString(V_BSTR(&vararg[0]));
3074 
3075  /* call ArrayPtr with BSTR argument - type mismatch */
3076  VariantInit(&vararg[0]);
3077  V_VT(&vararg[0]) = VT_BSTR;
3078  V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3079  dispparams.cNamedArgs = 0;
3080  dispparams.cArgs = 1;
3081  dispparams.rgdispidNamedArgs = NULL;
3082  dispparams.rgvarg = vararg;
3083  hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARRAYPTR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3084  ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
3085  SysFreeString(V_BSTR(&vararg[0]));
3086 
3087  /* call VarArg */
3088  VariantInit(&vararg[3]);
3089  V_VT(&vararg[3]) = VT_I4;
3090  V_I4(&vararg[3]) = 3;
3091  VariantInit(&vararg[2]);
3092  V_VT(&vararg[2]) = VT_I4;
3093  V_I4(&vararg[2]) = 0;
3094  VariantInit(&vararg[1]);
3095  V_VT(&vararg[1]) = VT_I4;
3096  V_I4(&vararg[1]) = 1;
3097  VariantInit(&vararg[0]);
3098  V_VT(&vararg[0]) = VT_I4;
3099  V_I4(&vararg[0]) = 2;
3100  dispparams.cNamedArgs = 0;
3101  dispparams.cArgs = 4;
3102  dispparams.rgdispidNamedArgs = NULL;
3103  dispparams.rgvarg = vararg;
3104  hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3105  ok_ole_success(hr, IDispatch_Invoke);
3106 
3107  /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
3108  dispidNamed = 0;
3109  dispparams.cNamedArgs = 1;
3110  dispparams.rgdispidNamedArgs = &dispidNamed;
3111  hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3112  ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
3113  dispidNamed = DISPID_PROPERTYPUT;
3114 
3115  /* call VarArg_Run */
3116  VariantInit(&vararg[1]);
3117  V_VT(&vararg[1]) = VT_BSTR;
3118  V_BSTR(&vararg[1]) = SysAllocString(szCat);
3119  VariantInit(&vararg[0]);
3120  V_VT(&vararg[0]) = VT_BSTR;
3121  V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3122  dispparams.cNamedArgs = 0;
3123  dispparams.cArgs = 2;
3124  dispparams.rgdispidNamedArgs = NULL;
3125  dispparams.rgvarg = vararg;
3126  hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3127  ok_ole_success(hr, IDispatch_Invoke);
3128  SysFreeString(V_BSTR(&vararg[1]));
3129  SysFreeString(V_BSTR(&vararg[0]));
3130 
3131  /* call VarArg_Ref_Run */
3132  VariantInit(&vararg[1]);
3133  V_VT(&vararg[1]) = VT_BSTR;
3134  V_BSTR(&vararg[1]) = SysAllocString(szCat);
3135  VariantInit(&vararg[0]);
3136  V_VT(&vararg[0]) = VT_BSTR;
3137  V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3138  dispparams.cNamedArgs = 0;
3139  dispparams.cArgs = 2;
3140  dispparams.rgdispidNamedArgs = NULL;
3141  dispparams.rgvarg = vararg;
3142  hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_REF_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3143  ok_ole_success(hr, IDispatch_Invoke);
3144  SysFreeString(V_BSTR(&vararg[1]));
3145  SysFreeString(V_BSTR(&vararg[0]));
3146 
3147  /* call Error */
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_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
3154  ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
3155  ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3156  "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3157  excepinfo.wCode, excepinfo.scode);
3158  VariantClear(&varresult);
3159 
3160  /* call BstrRet */
3161  pTypeInfo = NonOleAutomation_GetTypeInfo();
3162  dispparams.cNamedArgs = 0;
3163  dispparams.cArgs = 0;
3164  dispparams.rgdispidNamedArgs = NULL;
3165  dispparams.rgvarg = NULL;
3166  VariantInit(&varresult);
3167  hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3168  ok_ole_success(hr, ITypeInfo_Invoke);
3169  ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
3170  ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
3171 
3172  VariantClear(&varresult);
3173 
3174  dispparams.cNamedArgs = 0;
3175  dispparams.cArgs = 0;
3176  dispparams.rgdispidNamedArgs = NULL;
3177  dispparams.rgvarg = NULL;
3178  hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_ERROR, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3179  ok(hr == DISP_E_EXCEPTION, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
3180  ok(V_VT(&varresult) == VT_EMPTY, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult));
3181  ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3182  "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3183  excepinfo.wCode, excepinfo.scode);
3184  VariantClear(&varresult);
3185 
3186  ITypeInfo_Release(pTypeInfo);
3187 
3188  /* tests call put_Name without named arg */
3189  VariantInit(&vararg[0]);
3190  dispparams.cNamedArgs = 0;
3191  dispparams.rgdispidNamedArgs = NULL;
3192  dispparams.cArgs = 1;
3193  dispparams.rgvarg = vararg;
3194  VariantInit(&varresult);
3195  hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3196  ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
3197  VariantClear(&varresult);
3198 
3199  /* tests param type that cannot be coerced */
3200  VariantInit(&vararg[0]);
3201  V_VT(&vararg[0]) = VT_UNKNOWN;
3202  V_UNKNOWN(&vararg[0]) = NULL;
3203  dispparams.cNamedArgs = 1;
3204  dispparams.rgdispidNamedArgs = &dispidNamed;
3205  dispparams.cArgs = 1;
3206  dispparams.rgvarg = vararg;
3207  VariantInit(&varresult);
3208  hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3209  ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
3210  VariantClear(&varresult);
3211 
3212  /* tests bad param type */
3213  VariantInit(&vararg[0]);
3214  V_VT(&vararg[0]) = VT_CLSID;
3215  V_BYREF(&vararg[0]) = NULL;
3216  dispparams.cNamedArgs = 1;
3217  dispparams.rgdispidNamedArgs = &dispidNamed;
3218  dispparams.cArgs = 1;
3219  dispparams.rgvarg = vararg;
3220  VariantInit(&varresult);
3221  hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3222  ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
3223  VariantClear(&varresult);
3224 
3225  /* tests too small param count */
3226  dispparams.cNamedArgs = 0;
3227  dispparams.rgdispidNamedArgs = NULL;
3228  dispparams.cArgs = 0;
3229  dispparams.rgvarg = NULL;
3230  VariantInit(&varresult);
3231  hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3232  ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
3233  VariantClear(&varresult);
3234 
3235  /* tests propget function with large param count */
3236  VariantInit(&vararg[0]);
3237  V_VT(&vararg[0]) = VT_BSTR;
3238  V_BSTR(&vararg[0]) = NULL;
3239  V_VT(&vararg[1]) = VT_I4;
3240  V_I4(&vararg[1]) = 1;
3241  dispparams.cNamedArgs = 0;
3242  dispparams.cArgs = 2;
3243  dispparams.rgdispidNamedArgs = NULL;
3244  dispparams.rgvarg = vararg;
3245  hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3246  ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
3247 
3248  /* test propput with lcid */
3249 
3250  /* the lcid passed to the function is the first lcid in the typelib header.
3251  Since we don't explicitly set an lcid in the idl, it'll default to US English. */
3252  VariantInit(&vararg[0]);
3253  V_VT(&vararg[0]) = VT_I4;
3254  V_I4(&vararg[0]) = 0xcafe;
3255  dispparams.cNamedArgs = 1;
3256  dispparams.rgdispidNamedArgs = &dispidNamed;
3257  dispparams.cArgs = 1;
3258  dispparams.rgvarg = vararg;
3259  VariantInit(&varresult);
3260  hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3261  ok_ole_success(hr, ITypeInfo_Invoke);
3262  VariantClear(&varresult);
3263 
3264  /* test propget with lcid */
3265  dispparams.cNamedArgs = 0;
3266  dispparams.cArgs = 0;
3267  dispparams.rgvarg = NULL;
3268  dispparams.rgdispidNamedArgs = NULL;
3269  hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3270  ok_ole_success(hr, ITypeInfo_Invoke);
3271  ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3272  ok(V_I4(&varresult) == 0x409, "got %x\n", V_I4(&varresult));
3273  VariantClear(&varresult);
3274 
3275  /* test propget of INT value */
3276  dispparams.cNamedArgs = 0;
3277  dispparams.cArgs = 0;
3278  dispparams.rgvarg = NULL;
3279  dispparams.rgdispidNamedArgs = NULL;
3280  hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_INT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3281  ok_ole_success(hr, ITypeInfo_Invoke);
3282  ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3283  ok(V_I4(&varresult) == -13, "got %x\n", V_I4(&varresult));
3284  VariantClear(&varresult);
3285 
3286  /* test propget of INT value */
3287  dispparams.cNamedArgs = 0;
3288  dispparams.cArgs = 0;
3289  dispparams.rgvarg = NULL;
3290  dispparams.rgdispidNamedArgs = NULL;
3291  hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_UINT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3292  ok_ole_success(hr, ITypeInfo_Invoke);
3293  ok(V_VT(&varresult) == VT_UI4, "got %x\n", V_VT(&varresult));
3294  ok(V_UI4(&varresult) == 42, "got %x\n", V_UI4(&varresult));
3295  VariantClear(&varresult);
3296 
3297  /* test byref marshalling */
3298  uval = 666;
3299  VariantInit(&vararg[0]);
3300  V_VT(&vararg[0]) = VT_UI4|VT_BYREF;
3301  V_UI4REF(&vararg[0]) = &uval;
3302  dispparams.cNamedArgs = 0;
3303  dispparams.cArgs = 1;
3304  dispparams.rgvarg = vararg;
3305  dispparams.rgdispidNamedArgs = NULL;
3306  hr = IDispatch_Invoke(pDispatch, DISPID_TM_BYREF_UINT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3307  ok_ole_success(hr, ITypeInfo_Invoke);
3308  ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
3309  ok(V_VT(&vararg[0]) == (VT_UI4|VT_BYREF), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg[0]));
3310  ok(V_UI4REF(&vararg[0]) == &uval, "Byref pointer not preserved: %p/%p\n", &uval, V_UI4REF(&vararg[0]));
3311  ok(*V_UI4REF(&vararg[0]) == 42, "Expected 42 to be returned instead of %u\n", *V_UI4REF(&vararg[0]));
3312  VariantClear(&varresult);
3313  VariantClear(&vararg[0]);
3314 
3315  /* test propput with optional argument. */
3316  VariantInit(&vararg[0]);
3317  V_VT(&vararg[0]) = VT_I4;
3318  V_I4(&vararg[0]) = 0xcafe;
3319  dispparams.cNamedArgs = 1;
3320  dispparams.rgdispidNamedArgs = &dispidNamed;
3321  dispparams.cArgs = 1;
3322  dispparams.rgvarg = vararg;
3323  VariantInit(&varresult);
3324  hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_OPT_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3325  ok_ole_success(hr, ITypeInfo_Invoke);
3326  VariantClear(&varresult);
3327 
3328  /* test propput with required argument. */
3329  VariantInit(&vararg[0]);
3330  VariantInit(&vararg[1]);
3331  V_VT(&vararg[0]) = VT_I4;
3332  V_I4(&vararg[0]) = 0x1234;
3333  V_VT(&vararg[1]) = VT_I4;
3334  V_I4(&vararg[1]) = 0x5678;
3335  dispparams.cNamedArgs = 1;
3336  dispparams.rgdispidNamedArgs = &dispidNamed;
3337  dispparams.cArgs = 2;
3338  dispparams.rgvarg = vararg;
3339  VariantInit(&varresult);
3340  hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_REQ_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3341  ok_ole_success(hr, ITypeInfo_Invoke);
3342  VariantClear(&varresult);
3343 
3344  /* restricted member */
3345  dispparams.cNamedArgs = 0;
3346  dispparams.rgdispidNamedArgs = NULL;
3347  dispparams.cArgs = 0;
3348  dispparams.rgvarg = NULL;
3349  VariantInit(&varresult);
3350  hr = IDispatch_Invoke(pDispatch, DISPID_TM_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3351  ok( hr == DISP_E_MEMBERNOTFOUND, "got %08x\n", hr );
3352  VariantClear(&varresult);
3353 
3354  /* restricted member with -ve memid (not restricted) */
3355  dispparams.cNamedArgs = 0;
3356  dispparams.rgdispidNamedArgs = NULL;
3357  dispparams.cArgs = 0;
3358  dispparams.rgvarg = NULL;
3359  VariantInit(&varresult);
3360  hr = IDispatch_Invoke(pDispatch, DISPID_TM_NEG_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3361  ok( hr == S_OK, "got %08x\n", hr );
3362  ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3363  ok(V_I4(&varresult) == DISPID_TM_NEG_RESTRICTED, "got %x\n", V_I4(&varresult));
3364  VariantClear(&varresult);
3365 
3366  test_marshal_basetypes(pWidget, pDispatch);
3367  test_marshal_pointer(pWidget, pDispatch);
3368  test_marshal_iface(pWidget, pDispatch);
3369  test_marshal_bstr(pWidget, pDispatch);
3370  test_marshal_variant(pWidget, pDispatch);
3371  test_marshal_safearray(pWidget, pDispatch);
3372  test_marshal_struct(pWidget, pDispatch);
3373  test_marshal_array(pWidget, pDispatch);
3374  test_marshal_coclass(pWidget, pDispatch);
3375 
3376  IDispatch_Release(pDispatch);
3377  IWidget_Release(pWidget);
3378 
3379  trace("calling end_host_object\n");
3381 }
3382 
3383 static void test_DispCallFunc(void)
3384 {
3385  static const WCHAR szEmpty[] = { 0 };
3386  VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
3387  VARIANTARG vararg[4];
3388  VARIANTARG varref;
3389  VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
3390  VARIANTARG varresult;
3391  HRESULT hr;
3392  IWidget *pWidget = Widget_Create();
3393  V_VT(&vararg[0]) = VT_R8;
3394  V_R8(&vararg[0]) = 3.141;
3395  V_VT(&vararg[1]) = VT_BSTR;
3396  V_BSTRREF(&vararg[1]) = CoTaskMemAlloc(sizeof(BSTR));
3397  V_VT(&vararg[2]) = VT_BSTR;
3398  V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
3399  V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
3400  V_VARIANTREF(&vararg[3]) = &varref;
3401  V_VT(&varref) = VT_ERROR;
3402  V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
3403  VariantInit(&varresult);
3404  hr = DispCallFunc(pWidget, 9*sizeof(void*), CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
3406  VariantClear(&varresult);
3407  SysFreeString(*V_BSTRREF(&vararg[1]));
3408  CoTaskMemFree(V_BSTRREF(&vararg[1]));
3409  VariantClear(&vararg[2]);
3410  IWidget_Release(pWidget);
3411 }
3412 
3413 static void test_StaticWidget(void)
3414 {
3416  DISPPARAMS dispparams;
3417  VARIANTARG vararg[4];
3419  VARIANT varresult;
3420  HRESULT hr;
3421 
3422  type_info = get_type_info(&IID_IStaticWidget);
3423 
3424  /* call TestDual */
3425  dispparams.cNamedArgs = 0;
3426  dispparams.cArgs = 1;
3427  dispparams.rgdispidNamedArgs = NULL;
3428  dispparams.rgvarg = vararg;
3429  V_VT(vararg) = VT_DISPATCH;
3430  V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
3431  VariantInit(&varresult);
3433  &dispparams, &varresult, &excepinfo, NULL);
3434  ok_ole_success(hr, IDispatch_Invoke);
3435  ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
3436  VariantClear(&varresult);
3437 
3438  /* call TestSecondIface */
3439  dispparams.cNamedArgs = 0;
3440  dispparams.cArgs = 1;
3441  dispparams.rgdispidNamedArgs = NULL;
3442  dispparams.rgvarg = vararg;
3443  V_VT(vararg) = VT_DISPATCH;
3444  V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
3445  VariantInit(&varresult);
3447  &dispparams, &varresult, &excepinfo, NULL);
3448  ok_ole_success(hr, IDispatch_Invoke);
3449  ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
3450  VariantClear(&varresult);
3451 
3452  ITypeInfo_Release(type_info);
3453 }
3454 
3455 static void test_libattr(void)
3456 {
3457  ITypeLib *pTypeLib;
3458  HRESULT hr;
3459  TLIBATTR *pattr;
3460 
3461  hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
3463  if (FAILED(hr))
3464  return;
3465 
3466  hr = ITypeLib_GetLibAttr(pTypeLib, &pattr);
3467  ok_ole_success(hr, GetLibAttr);
3468  if (SUCCEEDED(hr))
3469  {
3470  ok(pattr->lcid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "lcid %x\n", pattr->lcid);
3471 
3472  ITypeLib_ReleaseTLibAttr(pTypeLib, pattr);
3473  }
3474 
3475  ITypeLib_Release(pTypeLib);
3476 }
3477 
3478 static void test_external_connection(void)
3479 {
3480  IStream *stream, *stream2;
3481  ITestSecondDisp *second;
3482  ItestDual *iface;
3483  HANDLE thread;
3484  DWORD tid;
3485  HRESULT hres;
3486 
3487  static const LARGE_INTEGER zero;
3488 
3489  trace("Testing IExternalConnection...\n");
3490 
3492 
3493  /* Marshaling an interface increases external connection count. */
3496  ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3497  tid = start_host_object(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHLFLAGS_NORMAL, &thread);
3498  ok(external_connections == 1, "external_connections = %d\n", external_connections);
3499 
3500  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3501  hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
3502  ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
3503  if (FAILED(hres))
3504  {
3506  IStream_Release(stream);
3507  return;
3508  }
3509  ok(external_connections == 1, "external_connections = %d\n", external_connections);
3510 
3511  IStream_Release(stream);
3512  ok(external_connections == 1, "external_connections = %d\n", external_connections);
3513 
3514  /* Creating a stub for new iface causes new external connection. */
3515  hres = ItestDual_QueryInterface(iface, &IID_ITestSecondDisp, (void**)&second);
3516  ok(hres == S_OK, "Could not get ITestSecondDisp iface: %08x\n", hres);
3517  todo_wine
3518  ok(external_connections == 2, "external_connections = %d\n", external_connections);
3519 
3520  ITestSecondDisp_Release(second);
3521  todo_wine
3522  ok(external_connections == 2, "external_connections = %d\n", external_connections);
3523 
3525  ItestDual_Release(iface);
3526  ok(external_connections == 0, "external_connections = %d\n", external_connections);
3527 
3529 
3530  /* A test with direct CoMarshalInterface call. */
3532  ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3533 
3535  hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3536  ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3537  ok(external_connections == 1, "external_connections = %d\n", external_connections);
3538 
3540  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3542  ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3543  ok(external_connections == 0, "external_connections = %d\n", external_connections);
3544 
3545  /* Two separated marshal data are still one external connection. */
3546  hres = CreateStreamOnHGlobal(NULL, TRUE, &stream2);
3547  ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3548 
3550  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3551  hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3552  ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3553  ok(external_connections == 1, "external_connections = %d\n", external_connections);
3554 
3555  hres = CoMarshalInterface(stream2, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3556  ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3557  ok(external_connections == 1, "external_connections = %d\n", external_connections);
3558 
3559  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3561  ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3562  ok(external_connections == 1, "external_connections = %d\n", external_connections);
3563 
3565  IStream_Seek(stream2, zero, STREAM_SEEK_SET, NULL);
3566  hres = CoReleaseMarshalData(stream2);
3567  ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3568  ok(external_connections == 0, "external_connections = %d\n", external_connections);
3569 
3570  IStream_Release(stream);
3571  IStream_Release(stream2);
3572 
3573  /* Weak table marshaling does not increment external connections */
3575  ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
3576 
3577  hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
3578  ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
3579  ok(external_connections == 0, "external_connections = %d\n", external_connections);
3580 
3581  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3582  hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
3583  ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
3584  ok(external_connections == 0, "external_connections = %d\n", external_connections);
3585  ItestDual_Release(iface);
3586 
3587  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
3589  ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
3590  ok(external_connections == 0, "external_connections = %d\n", external_connections);
3591 
3592  IStream_Release(stream);
3593 }
3594 
3595 START_TEST(tmarshal)
3596 {
3597  HRESULT hr;
3598  HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll");
3599  pVarAdd = (void*)GetProcAddress(hOleaut32, "VarAdd");
3600 
3602 
3604  if (FAILED(hr))
3605  {
3606  CoUninitialize();
3607  win_skip("Registration of the test typelib failed, skipping tests\n");
3608  return;
3609  }
3610 
3614  test_libattr();
3616 
3617  hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
3618  sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
3620 
3621  CoUninitialize();
3622 }
static ULONG WINAPI coclass1_AddRef(ICoclass1 *iface)
Definition: tmarshal.c:531
HRESULT WINAPI CoReleaseMarshalData(IStream *pStream)
Definition: marshal.c:2056
static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
Definition: tmarshal.c:235
#define DISP_E_EXCEPTION
Definition: winerror.h:2518
static SAFEARRAY * make_safearray(ULONG len)
Definition: tmarshal.c:1353
static HRESULT WINAPI Widget_neg_restrict(IWidget *iface, INT *i)
Definition: tmarshal.c:1032
Definition:</