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