4bd172e7967b3b1e7ab226d20fa4b4c6657a1409
[reactos.git] / modules / rostests / winetests / oleaut32 / tmarshal.c
1 /*
2 * Copyright (C) 2005-2006 Robert Shearman for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 */
19
20 #define COBJMACROS
21 #define CONST_VTABLE
22
23 #include <windows.h>
24 #include <ocidl.h>
25 #include <stdio.h>
26
27 #include "wine/test.h"
28
29 #include "tmarshal.h"
30 #include "tmarshal_dispids.h"
31
32 static HRESULT (WINAPI *pVarAdd)(LPVARIANT,LPVARIANT,LPVARIANT);
33
34
35 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
36
37 #ifdef __i386__
38 static const int tmarshal_todo = 0;
39 #else
40 static const int tmarshal_todo = 1;
41 #endif
42
43 /* ULL suffix is not portable */
44 #define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
45
46 const MYSTRUCT MYSTRUCT_BYVAL = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432), {0,1,2,3,4,5,6,7}};
47 const MYSTRUCT MYSTRUCT_BYPTR = {0x91827364, ULL_CONST(0x88776655, 0x44332211), {0,1,2,3,4,5,6,7}};
48 const MYSTRUCT MYSTRUCT_ARRAY[5] = {
49 {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415), {0,1,2,3,4,5,6,7}},
50 {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425), {0,1,2,3,4,5,6,7}},
51 {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435), {0,1,2,3,4,5,6,7}},
52 {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445), {0,1,2,3,4,5,6,7}},
53 {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455), {0,1,2,3,4,5,6,7}},
54 };
55
56
57 #define RELEASEMARSHALDATA WM_USER
58
59 struct host_object_data
60 {
61 IStream *stream;
62 IID iid;
63 IUnknown *object;
64 MSHLFLAGS marshal_flags;
65 HANDLE marshal_event;
66 IMessageFilter *filter;
67 };
68
69 static DWORD CALLBACK host_object_proc(LPVOID p)
70 {
71 struct host_object_data *data = p;
72 HRESULT hr;
73 MSG msg;
74
75 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
76
77 if (data->filter)
78 {
79 IMessageFilter * prev_filter = NULL;
80 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
81 if (prev_filter) IMessageFilter_Release(prev_filter);
82 ok_ole_success(hr, CoRegisterMessageFilter);
83 }
84
85 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
86 ok_ole_success(hr, CoMarshalInterface);
87
88 /* force the message queue to be created before signaling parent thread */
89 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
90
91 SetEvent(data->marshal_event);
92
93 while (GetMessageA(&msg, NULL, 0, 0))
94 {
95 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
96 {
97 trace("releasing marshal data\n");
98 CoReleaseMarshalData(data->stream);
99 SetEvent((HANDLE)msg.lParam);
100 }
101 else
102 DispatchMessageA(&msg);
103 }
104
105 HeapFree(GetProcessHeap(), 0, data);
106
107 CoUninitialize();
108
109 return hr;
110 }
111
112 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
113 {
114 DWORD tid = 0;
115 HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
116 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
117
118 data->stream = stream;
119 data->iid = *riid;
120 data->object = object;
121 data->marshal_flags = marshal_flags;
122 data->marshal_event = marshal_event;
123 data->filter = filter;
124
125 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
126
127 /* wait for marshaling to complete before returning */
128 WaitForSingleObject(marshal_event, INFINITE);
129 CloseHandle(marshal_event);
130
131 return tid;
132 }
133
134 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
135 {
136 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
137 }
138
139 #if 0 /* not used */
140 /* asks thread to release the marshal data because it has to be done by the
141 * same thread that marshaled the interface in the first place. */
142 static void release_host_object(DWORD tid)
143 {
144 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
145 PostThreadMessageA(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
146 WaitForSingleObject(event, INFINITE);
147 CloseHandle(event);
148 }
149 #endif
150
151 static void end_host_object(DWORD tid, HANDLE thread)
152 {
153 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
154 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
155 /* be careful of races - don't return until hosting thread has terminated */
156 WaitForSingleObject(thread, INFINITE);
157 CloseHandle(thread);
158 }
159
160 static int external_connections;
161 static BOOL expect_last_release_closes;
162
163 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
164 {
165 ok(0, "unexpected call\n");
166 *ppv = NULL;
167 return E_NOINTERFACE;
168 }
169
170 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
171 {
172 return 2;
173 }
174
175 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
176 {
177 return 1;
178 }
179
180 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
181 {
182 trace("add connection\n");
183
184 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
185 ok(!reserved, "reserved = %x\n", reserved);
186 return ++external_connections;
187 }
188
189 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
190 DWORD reserved, BOOL fLastReleaseCloses)
191 {
192 trace("release connection\n");
193
194 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
195 ok(!reserved, "reserved = %x\n", reserved);
196
197 ok(fLastReleaseCloses == expect_last_release_closes, "fLastReleaseCloses = %x, expected %x\n",
198 fLastReleaseCloses, expect_last_release_closes);
199 return --external_connections;
200 }
201
202 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
203 ExternalConnection_QueryInterface,
204 ExternalConnection_AddRef,
205 ExternalConnection_Release,
206 ExternalConnection_AddConnection,
207 ExternalConnection_ReleaseConnection
208 };
209
210 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
211
212 static ItestDual TestDual, TestDualDisp;
213
214 static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
215 {
216 return ItestDual_QueryInterface(&TestDual, riid, ppv);
217 }
218
219 static ULONG WINAPI TestSecondIface_AddRef(ITestSecondIface *iface)
220 {
221 return 2;
222 }
223
224 static ULONG WINAPI TestSecondIface_Release(ITestSecondIface *iface)
225 {
226 return 1;
227 }
228
229 static HRESULT WINAPI TestSecondIface_test(ITestSecondIface *iface)
230 {
231 return 1;
232 }
233
234 static const ITestSecondIfaceVtbl TestSecondIfaceVtbl = {
235 TestSecondIface_QueryInterface,
236 TestSecondIface_AddRef,
237 TestSecondIface_Release,
238 TestSecondIface_test
239 };
240
241 static ITestSecondIface TestSecondIface = { &TestSecondIfaceVtbl };
242
243 static HRESULT WINAPI TestSecondDisp_QueryInterface(ITestSecondDisp *iface, REFIID riid, void **ppv)
244 {
245 return ItestDual_QueryInterface(&TestDual, riid, ppv);
246 }
247
248 static ULONG WINAPI TestSecondDisp_AddRef(ITestSecondDisp *iface)
249 {
250 return 2;
251 }
252
253 static ULONG WINAPI TestSecondDisp_Release(ITestSecondDisp *iface)
254 {
255 return 1;
256 }
257
258 static HRESULT WINAPI TestSecondDisp_GetTypeInfoCount(ITestSecondDisp *iface, UINT *pctinfo)
259 {
260 ok(0, "unexpected call\n");
261 return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI TestSecondDisp_GetTypeInfo(ITestSecondDisp *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
265 {
266 ok(0, "unexpected call\n");
267 return E_NOTIMPL;
268 }
269
270 static HRESULT WINAPI TestSecondDisp_GetIDsOfNames(ITestSecondDisp *iface, REFIID riid, LPOLESTR *rgszNames,
271 UINT cNames, LCID lcid, DISPID *rgDispId)
272 {
273 ok(0, "unexpected call\n");
274 return E_NOTIMPL;
275 }
276
277 static HRESULT WINAPI TestSecondDisp_Invoke(ITestSecondDisp *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
278 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
279 UINT *puArgErr)
280 {
281 ok(0, "unexpected call\n");
282 return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI TestSecondDisp_test(ITestSecondDisp *iface)
286 {
287 ok(0, "unexpected call\n");
288 return E_NOTIMPL;
289 }
290
291 static ITestSecondDispVtbl TestSecondDispVtbl = {
292 TestSecondDisp_QueryInterface,
293 TestSecondDisp_AddRef,
294 TestSecondDisp_Release,
295 TestSecondDisp_GetTypeInfoCount,
296 TestSecondDisp_GetTypeInfo,
297 TestSecondDisp_GetIDsOfNames,
298 TestSecondDisp_Invoke,
299 TestSecondDisp_test
300 };
301
302 static ITestSecondDisp TestSecondDisp = { &TestSecondDispVtbl };
303
304 static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, void **ppvObject)
305 {
306 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) {
307 *ppvObject = &TestDualDisp;
308 return S_OK;
309 }else if(IsEqualGUID(riid, &IID_ItestDual)) {
310 *ppvObject = &TestDual;
311 return S_OK;
312 }else if(IsEqualGUID(riid, &IID_ITestSecondIface)) {
313 *ppvObject = &TestSecondIface;
314 return S_OK;
315 }else if(IsEqualGUID(riid, &IID_ITestSecondDisp)) {
316 *ppvObject = &TestSecondDisp;
317 return S_OK;
318 }else if (IsEqualGUID(riid, &IID_IExternalConnection)) {
319 trace("QI external connection\n");
320 *ppvObject = &ExternalConnection;
321 return S_OK;
322 }
323
324 *ppvObject = NULL;
325 return E_NOINTERFACE;
326 }
327
328 static ULONG WINAPI TestDual_AddRef(ItestDual *iface)
329 {
330 return 2;
331 }
332
333 static ULONG WINAPI TestDual_Release(ItestDual *iface)
334 {
335 return 1;
336 }
337
338 static HRESULT WINAPI TestDual_GetTypeInfoCount(ItestDual *iface, UINT *pctinfo)
339 {
340 ok(0, "unexpected call\n");
341 return E_NOTIMPL;
342 }
343
344 static HRESULT WINAPI TestDual_GetTypeInfo(ItestDual *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
345 {
346 ok(0, "unexpected call\n");
347 return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI TestDual_GetIDsOfNames(ItestDual *iface, REFIID riid, LPOLESTR *rgszNames,
351 UINT cNames, LCID lcid, DISPID *rgDispId)
352 {
353 ok(0, "unexpected call\n");
354 return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI TestDual_Invoke(ItestDual *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
358 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
359 UINT *puArgErr)
360 {
361 ok(0, "unexpected call\n");
362 return E_NOTIMPL;
363 }
364
365 static ItestDualVtbl TestDualVtbl = {
366 TestDual_QueryInterface,
367 TestDual_AddRef,
368 TestDual_Release,
369 TestDual_GetTypeInfoCount,
370 TestDual_GetTypeInfo,
371 TestDual_GetIDsOfNames,
372 TestDual_Invoke
373 };
374
375 static ItestDual TestDual = { &TestDualVtbl };
376 static ItestDual TestDualDisp = { &TestDualVtbl };
377
378 typedef struct Widget
379 {
380 IWidget IWidget_iface;
381 LONG refs;
382 IUnknown *pDispatchUnknown;
383 } Widget;
384
385 static inline Widget *impl_from_IWidget(IWidget *iface)
386 {
387 return CONTAINING_RECORD(iface, Widget, IWidget_iface);
388 }
389
390 static HRESULT WINAPI Widget_QueryInterface(
391 IWidget *iface,
392 /* [in] */ REFIID riid,
393 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
394 {
395 if (IsEqualIID(riid, &IID_IWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
396 {
397 IWidget_AddRef(iface);
398 *ppvObject = iface;
399 return S_OK;
400 }
401 else
402 {
403 *ppvObject = NULL;
404 return E_NOINTERFACE;
405 }
406 }
407
408 static ULONG WINAPI Widget_AddRef(
409 IWidget *iface)
410 {
411 Widget *This = impl_from_IWidget(iface);
412
413 return InterlockedIncrement(&This->refs);
414 }
415
416 static ULONG WINAPI Widget_Release(
417 IWidget *iface)
418 {
419 Widget *This = impl_from_IWidget(iface);
420 ULONG refs = InterlockedDecrement(&This->refs);
421 if (!refs)
422 {
423 IUnknown_Release(This->pDispatchUnknown);
424 memset(This, 0xcc, sizeof(*This));
425 HeapFree(GetProcessHeap(), 0, This);
426 trace("Widget destroyed!\n");
427 }
428
429 return refs;
430 }
431
432 static HRESULT WINAPI Widget_GetTypeInfoCount(
433 IWidget *iface,
434 /* [out] */ UINT __RPC_FAR *pctinfo)
435 {
436 Widget *This = impl_from_IWidget(iface);
437 IDispatch *pDispatch;
438 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
439 if (SUCCEEDED(hr))
440 {
441 hr = IDispatch_GetTypeInfoCount(pDispatch, pctinfo);
442 IDispatch_Release(pDispatch);
443 }
444 return hr;
445 }
446
447 static HRESULT WINAPI Widget_GetTypeInfo(
448 IWidget __RPC_FAR * iface,
449 /* [in] */ UINT iTInfo,
450 /* [in] */ LCID lcid,
451 /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
452 {
453 Widget *This = impl_from_IWidget(iface);
454 IDispatch *pDispatch;
455 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
456 if (SUCCEEDED(hr))
457 {
458 hr = IDispatch_GetTypeInfo(pDispatch, iTInfo, lcid, ppTInfo);
459 IDispatch_Release(pDispatch);
460 }
461 return hr;
462 }
463
464 static HRESULT WINAPI Widget_GetIDsOfNames(
465 IWidget __RPC_FAR * iface,
466 /* [in] */ REFIID riid,
467 /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
468 /* [in] */ UINT cNames,
469 /* [in] */ LCID lcid,
470 /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
471 {
472 Widget *This = impl_from_IWidget(iface);
473 IDispatch *pDispatch;
474 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
475 if (SUCCEEDED(hr))
476 {
477 hr = IDispatch_GetIDsOfNames(pDispatch, riid, rgszNames, cNames, lcid, rgDispId);
478 IDispatch_Release(pDispatch);
479 }
480 return hr;
481 }
482
483 static HRESULT WINAPI Widget_Invoke(
484 IWidget __RPC_FAR * iface,
485 /* [in] */ DISPID dispIdMember,
486 /* [in] */ REFIID riid,
487 /* [in] */ LCID lcid,
488 /* [in] */ WORD wFlags,
489 /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
490 /* [out] */ VARIANT __RPC_FAR *pVarResult,
491 /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
492 /* [out] */ UINT __RPC_FAR *puArgErr)
493 {
494 Widget *This = impl_from_IWidget(iface);
495 IDispatch *pDispatch;
496 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
497 if (SUCCEEDED(hr))
498 {
499 hr = IDispatch_Invoke(pDispatch, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
500 IDispatch_Release(pDispatch);
501 }
502 return hr;
503 }
504
505 static HRESULT WINAPI Widget_put_Name(
506 IWidget __RPC_FAR * iface,
507 /* [in] */ BSTR name)
508 {
509 trace("put_Name(%s)\n", wine_dbgstr_w(name));
510 return S_OK;
511 }
512
513 static HRESULT WINAPI Widget_get_Name(
514 IWidget __RPC_FAR * iface,
515 /* [out] */ BSTR __RPC_FAR *name)
516 {
517 static const WCHAR szCat[] = { 'C','a','t',0 };
518 trace("get_Name()\n");
519 *name = SysAllocString(szCat);
520 return S_OK;
521 }
522
523 static HRESULT WINAPI Widget_DoSomething(
524 IWidget __RPC_FAR * iface,
525 /* [in] */ double number,
526 /* [out] */ BSTR *str1,
527 /* [defaultvalue][in] */ BSTR str2,
528 /* [optional][in] */ VARIANT __RPC_FAR *opt)
529 {
530 static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
531 trace("DoSomething()\n");
532
533 ok(number == 3.141, "number(%f) != 3.141\n", number);
534 ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
535 ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt));
536 ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08x\n", V_ERROR(opt));
537 *str1 = SysAllocString(szString);
538
539 return S_FALSE;
540 }
541
542 static HRESULT WINAPI Widget_get_State(
543 IWidget __RPC_FAR * iface,
544 /* [retval][out] */ STATE __RPC_FAR *state)
545 {
546 trace("get_State() = STATE_WIDGETIFIED\n");
547 *state = STATE_WIDGETIFIED;
548 return S_OK;
549 }
550
551 static HRESULT WINAPI Widget_put_State(
552 IWidget __RPC_FAR * iface,
553 /* [in] */ STATE state)
554 {
555 trace("put_State(%d)\n", state);
556 return S_OK;
557 }
558
559 static HRESULT WINAPI Widget_Map(
560 IWidget * iface,
561 BSTR bstrId,
562 BSTR *sValue)
563 {
564 trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId), sValue);
565 *sValue = SysAllocString(bstrId);
566 return S_OK;
567 }
568
569 static HRESULT WINAPI Widget_SetOleColor(
570 IWidget * iface,
571 OLE_COLOR val)
572 {
573 trace("SetOleColor(0x%x)\n", val);
574 return S_OK;
575 }
576
577 static HRESULT WINAPI Widget_GetOleColor(
578 IWidget * iface,
579 OLE_COLOR *pVal)
580 {
581 trace("GetOleColor() = 0x8000000f\n");
582 *pVal = 0x8000000f;
583 return S_FALSE;
584 }
585
586 static HRESULT WINAPI Widget_Clone(
587 IWidget *iface,
588 IWidget **ppVal)
589 {
590 trace("Clone()\n");
591 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
592 }
593
594 static HRESULT WINAPI Widget_CloneDispatch(
595 IWidget *iface,
596 IDispatch **ppVal)
597 {
598 trace("CloneDispatch()\n");
599 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
600 }
601
602 static HRESULT WINAPI Widget_CloneCoclass(
603 IWidget *iface,
604 ApplicationObject2 **ppVal)
605 {
606 trace("CloneCoclass()\n");
607 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
608 }
609
610 static HRESULT WINAPI Widget_Value(
611 IWidget __RPC_FAR * iface,
612 VARIANT *value,
613 VARIANT *retval)
614 {
615 trace("Value(%p, %p)\n", value, retval);
616 ok(V_VT(value) == VT_I2, "V_VT(value) was %d instead of VT_I2\n", V_VT(value));
617 ok(V_I2(value) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value));
618 V_VT(retval) = VT_I2;
619 V_I2(retval) = 1234;
620 return S_OK;
621 }
622
623 static HRESULT WINAPI Widget_Array(
624 IWidget * iface,
625 SAFEARRAY * values)
626 {
627 trace("Array(%p)\n", values);
628 return S_OK;
629 }
630
631 static HRESULT WINAPI Widget_VariantArrayPtr(
632 IWidget * iface,
633 SAFEARRAY ** values)
634 {
635 trace("VariantArrayPtr(%p)\n", values);
636 return S_OK;
637 }
638
639 static HRESULT WINAPI Widget_VariantCArray(
640 IWidget * iface,
641 ULONG count,
642 VARIANT values[])
643 {
644 ULONG i;
645
646 trace("VariantCArray(%u,%p)\n", count, values);
647
648 ok(count == 2, "count is %d\n", count);
649 for (i = 0; i < count; i++)
650 ok(V_VT(&values[i]) == VT_I4, "values[%d] is not VT_I4\n", i);
651
652 if (pVarAdd)
653 {
654 VARIANT inc, res;
655 HRESULT hr;
656
657 V_VT(&inc) = VT_I4;
658 V_I4(&inc) = 1;
659 for (i = 0; i < count; i++) {
660 VariantInit(&res);
661 hr = pVarAdd(&values[i], &inc, &res);
662 if (FAILED(hr)) {
663 ok(0, "VarAdd failed at %u with error 0x%x\n", i, hr);
664 return hr;
665 }
666 hr = VariantCopy(&values[i], &res);
667 if (FAILED(hr)) {
668 ok(0, "VariantCopy failed at %u with error 0x%x\n", i, hr);
669 return hr;
670 }
671 }
672 }
673 else
674 win_skip("VarAdd is not available\n");
675
676 return S_OK;
677 }
678
679 static HRESULT WINAPI Widget_Variant(
680 IWidget __RPC_FAR * iface,
681 VARIANT var)
682 {
683 trace("Variant()\n");
684 ok(V_VT(&var) == VT_CY, "V_VT(&var) was %d\n", V_VT(&var));
685 ok(S(V_CY(&var)).Hi == 0xdababe, "V_CY(&var).Hi was 0x%x\n", S(V_CY(&var)).Hi);
686 ok(S(V_CY(&var)).Lo == 0xdeadbeef, "V_CY(&var).Lo was 0x%x\n", S(V_CY(&var)).Lo);
687 return S_OK;
688 }
689
690 static HRESULT WINAPI Widget_VarArg(
691 IWidget * iface,
692 int numexpect,
693 SAFEARRAY * values)
694 {
695 LONG lbound, ubound, i;
696 VARIANT * data;
697 HRESULT hr;
698
699 trace("VarArg(%p)\n", values);
700
701 hr = SafeArrayGetLBound(values, 1, &lbound);
702 ok(hr == S_OK, "SafeArrayGetLBound failed with %x\n", hr);
703 ok(lbound == 0, "SafeArrayGetLBound returned %d\n", lbound);
704
705 hr = SafeArrayGetUBound(values, 1, &ubound);
706 ok(hr == S_OK, "SafeArrayGetUBound failed with %x\n", hr);
707 ok(ubound == numexpect-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound, numexpect-1);
708
709 hr = SafeArrayAccessData(values, (LPVOID)&data);
710 ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
711
712 for (i=0; i<=ubound-lbound; i++)
713 {
714 ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%d]) was %d\n", i, V_VT(&data[i]));
715 ok(V_I4(&data[i]) == i, "V_I4(&data[%d]) was %d\n", i, V_I4(&data[i]));
716 }
717
718 hr = SafeArrayUnaccessData(values);
719 ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr);
720
721 return S_OK;
722 }
723
724
725 static BOOL mystruct_uint_ordered(MYSTRUCT *mystruct)
726 {
727 int i;
728 for (i = 0; i < sizeof(mystruct->uarr)/sizeof(mystruct->uarr[0]); i++)
729 if (mystruct->uarr[i] != i)
730 return FALSE;
731 return TRUE;
732 }
733
734 static HRESULT WINAPI Widget_StructArgs(
735 IWidget * iface,
736 MYSTRUCT byval,
737 MYSTRUCT *byptr,
738 MYSTRUCT arr[5])
739 {
740 int i, diff = 0;
741 ok(byval.field1 == MYSTRUCT_BYVAL.field1 &&
742 byval.field2 == MYSTRUCT_BYVAL.field2 &&
743 mystruct_uint_ordered(&byval),
744 "Struct parameter passed by value corrupted\n");
745 ok(byptr->field1 == MYSTRUCT_BYPTR.field1 &&
746 byptr->field2 == MYSTRUCT_BYPTR.field2 &&
747 mystruct_uint_ordered(byptr),
748 "Struct parameter passed by pointer corrupted\n");
749 for (i = 0; i < 5; i++)
750 if (arr[i].field1 != MYSTRUCT_ARRAY[i].field1 ||
751 arr[i].field2 != MYSTRUCT_ARRAY[i].field2 ||
752 ! mystruct_uint_ordered(&arr[i]))
753 diff++;
754 ok(diff == 0, "Array of structs corrupted\n");
755 return S_OK;
756 }
757
758
759 static HRESULT WINAPI Widget_Error(
760 IWidget __RPC_FAR * iface)
761 {
762 trace("Error()\n");
763 return E_NOTIMPL;
764 }
765
766 static HRESULT WINAPI Widget_CloneInterface(
767 IWidget __RPC_FAR * iface,
768 ISomethingFromDispatch **ppVal)
769 {
770 trace("CloneInterface()\n");
771 *ppVal = 0;
772 return S_OK;
773 }
774
775 static HRESULT WINAPI Widget_put_prop_with_lcid(
776 IWidget* iface, LONG lcid, INT i)
777 {
778 trace("put_prop_with_lcid(%08x, %x)\n", lcid, i);
779 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
780 ok(i == 0xcafe, "got %08x\n", i);
781 return S_OK;
782 }
783
784 static HRESULT WINAPI Widget_get_prop_with_lcid(
785 IWidget* iface, LONG lcid, INT *i)
786 {
787 trace("get_prop_with_lcid(%08x, %p)\n", lcid, i);
788 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
789 *i = lcid;
790 return S_OK;
791 }
792
793 static HRESULT WINAPI Widget_get_prop_int(
794 IWidget* iface, INT *i)
795 {
796 trace("get_prop_int(%p)\n", i);
797 *i = -13;
798 return S_OK;
799 }
800
801 static HRESULT WINAPI Widget_get_prop_uint(
802 IWidget* iface, UINT *i)
803 {
804 trace("get_prop_uint(%p)\n", i);
805 *i = 42;
806 return S_OK;
807 }
808
809 static HRESULT WINAPI Widget_ByRefUInt(
810 IWidget* iface, UINT *i)
811 {
812 *i = 42;
813 return S_OK;
814 }
815
816 static HRESULT WINAPI Widget_put_prop_opt_arg(
817 IWidget* iface, INT opt, INT i)
818 {
819 trace("put_prop_opt_arg(%08x, %08x)\n", opt, i);
820 todo_wine ok(opt == 0, "got opt=%08x\n", opt);
821 ok(i == 0xcafe, "got i=%08x\n", i);
822 return S_OK;
823 }
824
825 static HRESULT WINAPI Widget_put_prop_req_arg(
826 IWidget* iface, INT req, INT i)
827 {
828 trace("put_prop_req_arg(%08x, %08x)\n", req, i);
829 ok(req == 0x5678, "got req=%08x\n", req);
830 ok(i == 0x1234, "got i=%08x\n", i);
831 return S_OK;
832 }
833
834 static HRESULT WINAPI Widget_pos_restrict(IWidget* iface, INT *i)
835 {
836 trace("restrict\n");
837 *i = DISPID_TM_RESTRICTED;
838 return S_OK;
839 }
840
841 static HRESULT WINAPI Widget_neg_restrict(IWidget* iface, INT *i)
842 {
843 trace("neg_restrict\n");
844 *i = DISPID_TM_NEG_RESTRICTED;
845 return S_OK;
846 }
847
848 static HRESULT WINAPI Widget_VarArg_Run(
849 IWidget *iface, BSTR name, SAFEARRAY *params, VARIANT *result)
850 {
851 static const WCHAR catW[] = { 'C','a','t',0 };
852 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
853 LONG bound;
854 VARIANT *var;
855 BSTR bstr;
856 HRESULT hr;
857
858 trace("VarArg_Run(%p,%p,%p)\n", name, params, result);
859
860 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
861
862 hr = SafeArrayGetLBound(params, 1, &bound);
863 ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
864 ok(bound == 0, "expected 0, got %d\n", bound);
865
866 hr = SafeArrayGetUBound(params, 1, &bound);
867 ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
868 ok(bound == 0, "expected 0, got %d\n", bound);
869
870 hr = SafeArrayAccessData(params, (void **)&var);
871 ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
872
873 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
874 bstr = V_BSTR(&var[0]);
875 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
876
877 hr = SafeArrayUnaccessData(params);
878 ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
879
880 return S_OK;
881 }
882
883 static HRESULT WINAPI Widget_VarArg_Ref_Run(
884 IWidget *iface, BSTR name, SAFEARRAY **params, VARIANT *result)
885 {
886 static const WCHAR catW[] = { 'C','a','t',0 };
887 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
888 LONG bound;
889 VARIANT *var;
890 BSTR bstr;
891 HRESULT hr;
892
893 trace("VarArg_Ref_Run(%p,%p,%p)\n", name, params, result);
894
895 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
896
897 hr = SafeArrayGetLBound(*params, 1, &bound);
898 ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
899 ok(bound == 0, "expected 0, got %d\n", bound);
900
901 hr = SafeArrayGetUBound(*params, 1, &bound);
902 ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
903 ok(bound == 0, "expected 0, got %d\n", bound);
904
905 hr = SafeArrayAccessData(*params, (void **)&var);
906 ok(hr == S_OK, "SafeArrayAccessData error %#x\n", hr);
907
908 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
909 bstr = V_BSTR(&var[0]);
910 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
911
912 hr = SafeArrayUnaccessData(*params);
913 ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
914
915 return S_OK;
916 }
917
918 static HRESULT WINAPI Widget_Coclass(
919 IWidget *iface, ApplicationObject2 *param)
920 {
921 trace("Coclass(%p)\n", param);
922 ok(param == (ApplicationObject2 *)iface, "expected param == %p, got %p\n", iface, param);
923 return S_OK;
924 }
925
926 static const struct IWidgetVtbl Widget_VTable =
927 {
928 Widget_QueryInterface,
929 Widget_AddRef,
930 Widget_Release,
931 Widget_GetTypeInfoCount,
932 Widget_GetTypeInfo,
933 Widget_GetIDsOfNames,
934 Widget_Invoke,
935 Widget_put_Name,
936 Widget_get_Name,
937 Widget_DoSomething,
938 Widget_get_State,
939 Widget_put_State,
940 Widget_Map,
941 Widget_SetOleColor,
942 Widget_GetOleColor,
943 Widget_Clone,
944 Widget_CloneDispatch,
945 Widget_CloneCoclass,
946 Widget_Value,
947 Widget_Array,
948 Widget_VariantArrayPtr,
949 Widget_VariantCArray,
950 Widget_Variant,
951 Widget_VarArg,
952 Widget_StructArgs,
953 Widget_Error,
954 Widget_CloneInterface,
955 Widget_put_prop_with_lcid,
956 Widget_get_prop_with_lcid,
957 Widget_get_prop_int,
958 Widget_get_prop_uint,
959 Widget_ByRefUInt,
960 Widget_put_prop_opt_arg,
961 Widget_put_prop_req_arg,
962 Widget_pos_restrict,
963 Widget_neg_restrict,
964 Widget_VarArg_Run,
965 Widget_VarArg_Ref_Run,
966 Widget_Coclass,
967 };
968
969 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
970 {
971 if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
972 {
973 IStaticWidget_AddRef(iface);
974 *ppvObject = iface;
975 return S_OK;
976 }
977
978 *ppvObject = NULL;
979 return E_NOINTERFACE;
980 }
981
982 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
983 {
984 return 2;
985 }
986
987 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
988 {
989 return 1;
990 }
991
992 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
993 {
994 ok(0, "unexpected call\n");
995 return E_NOTIMPL;
996 }
997
998 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
999 ITypeInfo **ppTInfo)
1000 {
1001 ok(0, "unexpected call\n");
1002 return E_NOTIMPL;
1003 }
1004
1005 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
1006 UINT cNames, LCID lcid, DISPID *rgDispId)
1007 {
1008 ok(0, "unexpected call\n");
1009 return E_NOTIMPL;
1010 }
1011
1012 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
1013 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1014 UINT *puArgErr)
1015 {
1016 ok(0, "unexpected call\n");
1017 return E_NOTIMPL;
1018 }
1019
1020 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
1021 {
1022 trace("TestDual()\n");
1023 ok(p == &TestDual, "wrong ItestDual\n");
1024 return S_OK;
1025 }
1026
1027 static HRESULT WINAPI StaticWidget_TestSecondIface(IStaticWidget *iface, ITestSecondIface *p)
1028 {
1029 trace("TestSecondIface()\n");
1030 ok(p == &TestSecondIface, "wrong ItestSecondIface\n");
1031 return S_OK;
1032 }
1033
1034 static const IStaticWidgetVtbl StaticWidgetVtbl = {
1035 StaticWidget_QueryInterface,
1036 StaticWidget_AddRef,
1037 StaticWidget_Release,
1038 StaticWidget_GetTypeInfoCount,
1039 StaticWidget_GetTypeInfo,
1040 StaticWidget_GetIDsOfNames,
1041 StaticWidget_Invoke,
1042 StaticWidget_TestDual,
1043 StaticWidget_TestSecondIface
1044 };
1045
1046 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
1047
1048 typedef struct KindaEnum
1049 {
1050 IKindaEnumWidget IKindaEnumWidget_iface;
1051 LONG refs;
1052 } KindaEnum;
1053
1054 static inline KindaEnum *impl_from_IKindaEnumWidget(IKindaEnumWidget *iface)
1055 {
1056 return CONTAINING_RECORD(iface, KindaEnum, IKindaEnumWidget_iface);
1057 }
1058
1059 static HRESULT register_current_module_typelib(void)
1060 {
1061 WCHAR path[MAX_PATH];
1062 CHAR pathA[MAX_PATH];
1063 HRESULT hr;
1064 ITypeLib *typelib;
1065
1066 GetModuleFileNameA(NULL, pathA, MAX_PATH);
1067 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
1068
1069 hr = LoadTypeLib(path, &typelib);
1070 if (SUCCEEDED(hr))
1071 {
1072 hr = RegisterTypeLib(typelib, path, NULL);
1073 ITypeLib_Release(typelib);
1074 }
1075 return hr;
1076 }
1077
1078 static ITypeInfo *get_type_info(REFIID riid)
1079 {
1080 ITypeInfo *pTypeInfo;
1081 ITypeLib *pTypeLib;
1082 HRESULT hr;
1083
1084 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1085 ok_ole_success(hr, LoadRegTypeLib);
1086 if (FAILED(hr))
1087 return NULL;
1088
1089 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
1090 ITypeLib_Release(pTypeLib);
1091 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1092 if (FAILED(hr))
1093 return NULL;
1094
1095 return pTypeInfo;
1096 }
1097
1098 static IWidget *Widget_Create(void)
1099 {
1100 Widget *This;
1101 ITypeInfo *pTypeInfo;
1102 HRESULT hr = E_FAIL;
1103
1104 pTypeInfo = get_type_info(&IID_IWidget);
1105 if(!pTypeInfo)
1106 return NULL;
1107
1108 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1109 This->IWidget_iface.lpVtbl = &Widget_VTable;
1110 This->refs = 1;
1111 This->pDispatchUnknown = NULL;
1112
1113 hr = CreateStdDispatch((IUnknown *)&This->IWidget_iface, This, pTypeInfo,
1114 &This->pDispatchUnknown);
1115 ok_ole_success(hr, CreateStdDispatch);
1116 ITypeInfo_Release(pTypeInfo);
1117
1118 if (SUCCEEDED(hr))
1119 return &This->IWidget_iface;
1120 else
1121 {
1122 HeapFree(GetProcessHeap(), 0, This);
1123 return NULL;
1124 }
1125 }
1126
1127 static HRESULT WINAPI KindaEnum_QueryInterface(
1128 IKindaEnumWidget *iface,
1129 /* [in] */ REFIID riid,
1130 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
1131 {
1132 if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
1133 {
1134 IKindaEnumWidget_AddRef(iface);
1135 *ppvObject = iface;
1136 return S_OK;
1137 }
1138 else
1139 {
1140 *ppvObject = NULL;
1141 return E_NOINTERFACE;
1142 }
1143 }
1144
1145 static ULONG WINAPI KindaEnum_AddRef(
1146 IKindaEnumWidget *iface)
1147 {
1148 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1149
1150 return InterlockedIncrement(&This->refs);
1151 }
1152
1153 static ULONG WINAPI KindaEnum_Release(
1154 IKindaEnumWidget *iface)
1155 {
1156 KindaEnum *This = impl_from_IKindaEnumWidget(iface);
1157 ULONG refs = InterlockedDecrement(&This->refs);
1158 if (!refs)
1159 {
1160 memset(This, 0xcc, sizeof(*This));
1161 HeapFree(GetProcessHeap(), 0, This);
1162 trace("KindaEnumWidget destroyed!\n");
1163 }
1164
1165 return refs;
1166 }
1167
1168 static HRESULT WINAPI KindaEnum_Next(
1169 IKindaEnumWidget *iface,
1170 /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
1171 {
1172 *widget = Widget_Create();
1173 if (*widget)
1174 return S_OK;
1175 else
1176 return E_OUTOFMEMORY;
1177 }
1178
1179 static HRESULT WINAPI KindaEnum_Count(
1180 IKindaEnumWidget *iface,
1181 /* [out] */ ULONG __RPC_FAR *count)
1182 {
1183 return E_NOTIMPL;
1184 }
1185
1186 static HRESULT WINAPI KindaEnum_Reset(
1187 IKindaEnumWidget *iface)
1188 {
1189 return E_NOTIMPL;
1190 }
1191
1192 static HRESULT WINAPI KindaEnum_Clone(
1193 IKindaEnumWidget *iface,
1194 /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
1195 {
1196 return E_NOTIMPL;
1197 }
1198
1199 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
1200 {
1201 KindaEnum_QueryInterface,
1202 KindaEnum_AddRef,
1203 KindaEnum_Release,
1204 KindaEnum_Next,
1205 KindaEnum_Count,
1206 KindaEnum_Reset,
1207 KindaEnum_Clone
1208 };
1209
1210 static IKindaEnumWidget *KindaEnumWidget_Create(void)
1211 {
1212 KindaEnum *This;
1213
1214 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1215 if (!This) return NULL;
1216 This->IKindaEnumWidget_iface.lpVtbl = &KindaEnumWidget_VTable;
1217 This->refs = 1;
1218 return &This->IKindaEnumWidget_iface;
1219 }
1220
1221 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
1222 {
1223 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
1224 {
1225 *(INonOleAutomation **)ppv = iface;
1226 return S_OK;
1227 }
1228 *ppv = NULL;
1229 return E_NOINTERFACE;
1230 }
1231
1232 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
1233 {
1234 return 2;
1235 }
1236
1237 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
1238 {
1239 return 1;
1240 }
1241
1242 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
1243 {
1244 static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1245 return SysAllocString(wszTestString);
1246 }
1247
1248 static HRESULT WINAPI NonOleAutomation_Error(INonOleAutomation *iface)
1249 {
1250 return E_NOTIMPL;
1251 }
1252
1253 static INonOleAutomationVtbl NonOleAutomation_VTable =
1254 {
1255 NonOleAutomation_QueryInterface,
1256 NonOleAutomation_AddRef,
1257 NonOleAutomation_Release,
1258 NonOleAutomation_BstrRet,
1259 NonOleAutomation_Error
1260 };
1261
1262 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
1263
1264 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
1265 {
1266 ITypeLib *pTypeLib;
1267 HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1268 ok_ole_success(hr, LoadRegTypeLib);
1269 if (SUCCEEDED(hr))
1270 {
1271 ITypeInfo *pTypeInfo;
1272 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
1273 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1274 ITypeLib_Release(pTypeLib);
1275 return pTypeInfo;
1276 }
1277 return NULL;
1278 }
1279
1280 static void test_typelibmarshal(void)
1281 {
1282 static const WCHAR szCat[] = { 'C','a','t',0 };
1283 static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
1284 static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
1285 HRESULT hr;
1286 IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
1287 IWidget *pWidget;
1288 IStream *pStream;
1289 IDispatch *pDispatch;
1290 static const LARGE_INTEGER ullZero;
1291 EXCEPINFO excepinfo;
1292 VARIANT varresult;
1293 DISPID dispidNamed = DISPID_PROPERTYPUT;
1294 DISPPARAMS dispparams;
1295 VARIANTARG vararg[4];
1296 STATE the_state;
1297 HANDLE thread;
1298 DWORD tid;
1299 BSTR bstr;
1300 ITypeInfo *pTypeInfo;
1301 MYSTRUCT mystruct;
1302 MYSTRUCT mystructArray[5];
1303 UINT uval;
1304
1305 ok(pKEW != NULL, "Widget creation failed\n");
1306
1307 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1308 ok_ole_success(hr, CreateStreamOnHGlobal);
1309 tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
1310 IKindaEnumWidget_Release(pKEW);
1311
1312 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1313 hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
1314 todo_wine_if(tmarshal_todo)
1315 ok_ole_success(hr, CoUnmarshalInterface);
1316 IStream_Release(pStream);
1317
1318 hr = IKindaEnumWidget_Next(pKEW, &pWidget);
1319 ok_ole_success(hr, IKindaEnumWidget_Next);
1320
1321 IKindaEnumWidget_Release(pKEW);
1322
1323 /* call GetTypeInfoCount (direct) */
1324 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
1325 ok_ole_success(hr, IWidget_GetTypeInfoCount);
1326 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
1327 ok_ole_success(hr, IWidget_GetTypeInfoCount);
1328
1329 hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
1330 ok_ole_success(hr, IWidget_QueryInterface);
1331
1332 /* call put_Name */
1333 VariantInit(&vararg[0]);
1334 dispparams.cNamedArgs = 1;
1335 dispparams.rgdispidNamedArgs = &dispidNamed;
1336 dispparams.cArgs = 1;
1337 dispparams.rgvarg = vararg;
1338 VariantInit(&varresult);
1339 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1340 ok_ole_success(hr, IDispatch_Invoke);
1341 todo_wine_if(tmarshal_todo)
1342 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1343 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1344 excepinfo.wCode, excepinfo.scode);
1345 VariantClear(&varresult);
1346
1347 /* call put_Name (direct) */
1348 bstr = SysAllocString(szSuperman);
1349 hr = IWidget_put_Name(pWidget, bstr);
1350 ok_ole_success(hr, IWidget_put_Name);
1351 SysFreeString(bstr);
1352
1353 /* call get_Name */
1354 dispparams.cNamedArgs = 0;
1355 dispparams.rgdispidNamedArgs = NULL;
1356 dispparams.cArgs = 0;
1357 dispparams.rgvarg = NULL;
1358 VariantInit(&varresult);
1359 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1360 ok_ole_success(hr, IDispatch_Invoke);
1361 todo_wine_if(tmarshal_todo)
1362 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1363 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1364 excepinfo.wCode, excepinfo.scode);
1365 trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1366 VariantClear(&varresult);
1367
1368 /* call get_Name (direct) */
1369 bstr = (void *)0xdeadbeef;
1370 hr = IWidget_get_Name(pWidget, &bstr);
1371 ok_ole_success(hr, IWidget_get_Name);
1372 ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
1373 SysFreeString(bstr);
1374
1375 /* call DoSomething without optional arguments */
1376 VariantInit(&vararg[0]);
1377 VariantInit(&vararg[1]);
1378 V_VT(&vararg[1]) = VT_R8;
1379 V_R8(&vararg[1]) = 3.141;
1380 dispparams.cNamedArgs = 0;
1381 dispparams.cArgs = 2;
1382 dispparams.rgdispidNamedArgs = NULL;
1383 dispparams.rgvarg = vararg;
1384 VariantInit(&varresult);
1385 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1386 ok_ole_success(hr, IDispatch_Invoke);
1387 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1388 VariantClear(&varresult);
1389
1390 /* call DoSomething with optional argument set to VT_EMPTY */
1391 VariantInit(&vararg[0]);
1392 VariantInit(&vararg[1]);
1393 VariantInit(&vararg[2]);
1394 V_VT(&vararg[2]) = VT_R8;
1395 V_R8(&vararg[2]) = 3.141;
1396 dispparams.cNamedArgs = 0;
1397 dispparams.cArgs = 3;
1398 dispparams.rgdispidNamedArgs = NULL;
1399 dispparams.rgvarg = vararg;
1400 VariantInit(&varresult);
1401 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1402 ok_ole_success(hr, IDispatch_Invoke);
1403 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1404 VariantClear(&varresult);
1405
1406 /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
1407 VariantInit(&vararg[0]);
1408 VariantInit(&vararg[1]);
1409 VariantInit(&vararg[2]);
1410 VariantInit(&vararg[3]);
1411 V_VT(&vararg[3]) = VT_R8;
1412 V_R8(&vararg[3]) = 3.141;
1413 V_VT(&vararg[1]) = VT_ERROR;
1414 V_ERROR(&vararg[1]) = DISP_E_PARAMNOTFOUND;
1415 V_VT(&vararg[0]) = VT_ERROR;
1416 V_ERROR(&vararg[0]) = DISP_E_PARAMNOTFOUND;
1417 dispparams.cNamedArgs = 0;
1418 dispparams.cArgs = 4;
1419 dispparams.rgdispidNamedArgs = NULL;
1420 dispparams.rgvarg = vararg;
1421 VariantInit(&varresult);
1422 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1423 ok_ole_success(hr, IDispatch_Invoke);
1424 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1425 VariantClear(&varresult);
1426
1427 /* call get_State */
1428 dispparams.cNamedArgs = 0;
1429 dispparams.cArgs = 0;
1430 dispparams.rgdispidNamedArgs = NULL;
1431 dispparams.rgvarg = NULL;
1432 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1433 ok_ole_success(hr, IDispatch_Invoke);
1434 ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
1435
1436 /* call get_State (direct) */
1437 hr = IWidget_get_State(pWidget, &the_state);
1438 ok_ole_success(hr, IWidget_get_state);
1439 ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
1440
1441 /* call put_State */
1442 the_state = STATE_WIDGETIFIED;
1443 VariantInit(&vararg[0]);
1444 V_VT(&vararg[0]) = VT_BYREF|VT_I4;
1445 V_I4REF(&vararg[0]) = (int *)&the_state;
1446 dispparams.cNamedArgs = 1;
1447 dispparams.cArgs = 1;
1448 dispparams.rgdispidNamedArgs = &dispidNamed;
1449 dispparams.rgvarg = vararg;
1450 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1451 ok_ole_success(hr, IDispatch_Invoke);
1452
1453 /* call Map */
1454 bstr = SysAllocString(szTestTest);
1455 VariantInit(&vararg[0]);
1456 V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
1457 V_BSTRREF(&vararg[0]) = &bstr;
1458 dispparams.cNamedArgs = 0;
1459 dispparams.cArgs = 1;
1460 dispparams.rgdispidNamedArgs = NULL;
1461 dispparams.rgvarg = vararg;
1462 VariantInit(&varresult);
1463 hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1464 ok_ole_success(hr, IDispatch_Invoke);
1465 ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
1466 ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1467 VariantClear(&varresult);
1468 SysFreeString(bstr);
1469
1470 /* call SetOleColor with large negative VT_I4 param */
1471 VariantInit(&vararg[0]);
1472 V_VT(&vararg[0]) = VT_I4;
1473 V_I4(&vararg[0]) = 0x80000005;
1474 dispparams.cNamedArgs = 0;
1475 dispparams.cArgs = 1;
1476 dispparams.rgdispidNamedArgs = NULL;
1477 dispparams.rgvarg = vararg;
1478 hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1479 ok_ole_success(hr, IDispatch_Invoke);
1480
1481 /* call GetOleColor */
1482 dispparams.cNamedArgs = 0;
1483 dispparams.cArgs = 0;
1484 dispparams.rgdispidNamedArgs = NULL;
1485 dispparams.rgvarg = NULL;
1486 VariantInit(&varresult);
1487 hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1488 ok_ole_success(hr, IDispatch_Invoke);
1489 VariantClear(&varresult);
1490
1491 /* call StructArgs (direct) */
1492 mystruct = MYSTRUCT_BYPTR;
1493 memcpy(mystructArray, MYSTRUCT_ARRAY, sizeof(mystructArray));
1494 hr = IWidget_StructArgs(pWidget, MYSTRUCT_BYVAL, &mystruct, mystructArray);
1495 ok_ole_success(hr, IWidget_StructArgs);
1496
1497 /* call Clone */
1498 dispparams.cNamedArgs = 0;
1499 dispparams.cArgs = 0;
1500 dispparams.rgdispidNamedArgs = NULL;
1501 dispparams.rgvarg = NULL;
1502 VariantInit(&varresult);
1503 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1504 ok_ole_success(hr, IDispatch_Invoke);
1505 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1506 VariantClear(&varresult);
1507
1508 /* call CloneInterface */
1509 dispparams.cNamedArgs = 0;
1510 dispparams.cArgs = 0;
1511 dispparams.rgdispidNamedArgs = NULL;
1512 dispparams.rgvarg = NULL;
1513 VariantInit(&varresult);
1514 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1515 ok_ole_success(hr, IDispatch_Invoke);
1516 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1517 VariantClear(&varresult);
1518
1519 /* call CloneDispatch with automatic value getting */
1520 V_VT(&vararg[0]) = VT_I2;
1521 V_I2(&vararg[0]) = 1;
1522 dispparams.cNamedArgs = 0;
1523 dispparams.rgdispidNamedArgs = NULL;
1524 dispparams.cArgs = 1;
1525 dispparams.rgvarg = vararg;
1526 VariantInit(&varresult);
1527 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1528 ok_ole_success(hr, IDispatch_Invoke);
1529
1530 todo_wine_if(tmarshal_todo)
1531 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1532 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1533 excepinfo.wCode, excepinfo.scode);
1534
1535 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1536 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1537 VariantClear(&varresult);
1538
1539 /* call CloneCoclass */
1540 dispparams.cNamedArgs = 0;
1541 dispparams.cArgs = 0;
1542 dispparams.rgdispidNamedArgs = NULL;
1543 dispparams.rgvarg = NULL;
1544 VariantInit(&varresult);
1545 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1546 ok_ole_success(hr, IDispatch_Invoke);
1547
1548 todo_wine_if(tmarshal_todo)
1549 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1550 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1551 excepinfo.wCode, excepinfo.scode);
1552
1553 ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
1554 ok(V_DISPATCH(&varresult) != NULL, "expected V_DISPATCH(&varresult) != NULL\n");
1555
1556 /* call Coclass with VT_DISPATCH type */
1557 vararg[0] = varresult;
1558 dispparams.cNamedArgs = 0;
1559 dispparams.rgdispidNamedArgs = NULL;
1560 dispparams.cArgs = 1;
1561 dispparams.rgvarg = vararg;
1562 VariantInit(&varresult);
1563 hr = IDispatch_Invoke(pDispatch, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1564 ok_ole_success(hr, IDispatch_Invoke);
1565 todo_wine_if(tmarshal_todo)
1566 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1567 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1568 excepinfo.wCode, excepinfo.scode);
1569 VariantClear(&varresult);
1570
1571 /* call CoClass (direct) */
1572 hr = IWidget_Coclass(pWidget, (void *)V_DISPATCH(&vararg[0]));
1573 ok_ole_success(hr, IWidget_Coclass);
1574 VariantClear(&vararg[0]);
1575
1576 /* call Value with a VT_VARIANT|VT_BYREF type */
1577 V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
1578 V_VARIANTREF(&vararg[0]) = &vararg[1];
1579 V_VT(&vararg[1]) = VT_I2;
1580 V_I2(&vararg[1]) = 1;
1581 dispparams.cNamedArgs = 0;
1582 dispparams.rgdispidNamedArgs = NULL;
1583 dispparams.cArgs = 1;
1584 dispparams.rgvarg = vararg;
1585 VariantInit(&varresult);
1586 hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1587 ok_ole_success(hr, IDispatch_Invoke);
1588
1589 todo_wine_if(tmarshal_todo)
1590 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1591 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1592 excepinfo.wCode, excepinfo.scode);
1593
1594 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1595 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1596 VariantClear(&varresult);
1597
1598 /* call Variant - exercises variant copying in ITypeInfo::Invoke and
1599 * handling of void return types */
1600 /* use a big type to ensure that the variant was properly copied into the
1601 * destination function's args */
1602 V_VT(&vararg[0]) = VT_CY;
1603 S(V_CY(&vararg[0])).Hi = 0xdababe;
1604 S(V_CY(&vararg[0])).Lo = 0xdeadbeef;
1605 dispparams.cNamedArgs = 0;
1606 dispparams.cArgs = 1;
1607 dispparams.rgdispidNamedArgs = NULL;
1608 dispparams.rgvarg = vararg;
1609 VariantInit(&varresult);
1610 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1611 ok_ole_success(hr, IDispatch_Invoke);
1612 VariantClear(&varresult);
1613
1614 /* call Array with BSTR argument - type mismatch */
1615 VariantInit(&vararg[0]);
1616 V_VT(&vararg[0]) = VT_BSTR;
1617 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1618 dispparams.cNamedArgs = 0;
1619 dispparams.cArgs = 1;
1620 dispparams.rgdispidNamedArgs = NULL;
1621 dispparams.rgvarg = vararg;
1622 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ARRAY, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1623 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
1624 SysFreeString(V_BSTR(&vararg[0]));
1625
1626 /* call ArrayPtr with BSTR argument - type mismatch */
1627 VariantInit(&vararg[0]);
1628 V_VT(&vararg[0]) = VT_BSTR;
1629 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1630 dispparams.cNamedArgs = 0;
1631 dispparams.cArgs = 1;
1632 dispparams.rgdispidNamedArgs = NULL;
1633 dispparams.rgvarg = vararg;
1634 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARRAYPTR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1635 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
1636 SysFreeString(V_BSTR(&vararg[0]));
1637
1638 /* call VariantCArray - test marshaling of variant arrays */
1639 V_VT(&vararg[0]) = VT_I4;
1640 V_I4(&vararg[0]) = 1;
1641 V_VT(&vararg[1]) = VT_I4;
1642 V_I4(&vararg[1]) = 2;
1643 hr = IWidget_VariantCArray(pWidget, 2, vararg);
1644 ok_ole_success(hr, IWidget_VariantCArray);
1645 todo_wine_if(!tmarshal_todo)
1646 ok(V_VT(&vararg[0]) == VT_I4 && V_I4(&vararg[0]) == 2, "vararg[0] = %d[%d]\n", V_VT(&vararg[0]), V_I4(&vararg[0]));
1647 todo_wine_if(!tmarshal_todo)
1648 ok(V_VT(&vararg[1]) == VT_I4 && V_I4(&vararg[1]) == 3, "vararg[1] = %d[%d]\n", V_VT(&vararg[1]), V_I4(&vararg[1]));
1649
1650 /* call VarArg */
1651 VariantInit(&vararg[3]);
1652 V_VT(&vararg[3]) = VT_I4;
1653 V_I4(&vararg[3]) = 3;
1654 VariantInit(&vararg[2]);
1655 V_VT(&vararg[2]) = VT_I4;
1656 V_I4(&vararg[2]) = 0;
1657 VariantInit(&vararg[1]);
1658 V_VT(&vararg[1]) = VT_I4;
1659 V_I4(&vararg[1]) = 1;
1660 VariantInit(&vararg[0]);
1661 V_VT(&vararg[0]) = VT_I4;
1662 V_I4(&vararg[0]) = 2;
1663 dispparams.cNamedArgs = 0;
1664 dispparams.cArgs = 4;
1665 dispparams.rgdispidNamedArgs = NULL;
1666 dispparams.rgvarg = vararg;
1667 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1668 ok_ole_success(hr, IDispatch_Invoke);
1669
1670 /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
1671 dispidNamed = 0;
1672 dispparams.cNamedArgs = 1;
1673 dispparams.rgdispidNamedArgs = &dispidNamed;
1674 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1675 ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
1676 dispidNamed = DISPID_PROPERTYPUT;
1677
1678 /* call VarArg_Run */
1679 VariantInit(&vararg[1]);
1680 V_VT(&vararg[1]) = VT_BSTR;
1681 V_BSTR(&vararg[1]) = SysAllocString(szCat);
1682 VariantInit(&vararg[0]);
1683 V_VT(&vararg[0]) = VT_BSTR;
1684 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1685 dispparams.cNamedArgs = 0;
1686 dispparams.cArgs = 2;
1687 dispparams.rgdispidNamedArgs = NULL;
1688 dispparams.rgvarg = vararg;
1689 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1690 ok_ole_success(hr, IDispatch_Invoke);
1691 SysFreeString(V_BSTR(&vararg[1]));
1692 SysFreeString(V_BSTR(&vararg[0]));
1693
1694 /* call VarArg_Ref_Run */
1695 VariantInit(&vararg[1]);
1696 V_VT(&vararg[1]) = VT_BSTR;
1697 V_BSTR(&vararg[1]) = SysAllocString(szCat);
1698 VariantInit(&vararg[0]);
1699 V_VT(&vararg[0]) = VT_BSTR;
1700 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
1701 dispparams.cNamedArgs = 0;
1702 dispparams.cArgs = 2;
1703 dispparams.rgdispidNamedArgs = NULL;
1704 dispparams.rgvarg = vararg;
1705 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_REF_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1706 ok_ole_success(hr, IDispatch_Invoke);
1707 SysFreeString(V_BSTR(&vararg[1]));
1708 SysFreeString(V_BSTR(&vararg[0]));
1709
1710 /* call Error */
1711 dispparams.cNamedArgs = 0;
1712 dispparams.cArgs = 0;
1713 dispparams.rgdispidNamedArgs = NULL;
1714 dispparams.rgvarg = NULL;
1715 VariantInit(&varresult);
1716 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1717 ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1718 todo_wine_if(tmarshal_todo)
1719 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1720 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1721 excepinfo.wCode, excepinfo.scode);
1722 VariantClear(&varresult);
1723
1724 /* call BstrRet */
1725 pTypeInfo = NonOleAutomation_GetTypeInfo();
1726 dispparams.cNamedArgs = 0;
1727 dispparams.cArgs = 0;
1728 dispparams.rgdispidNamedArgs = NULL;
1729 dispparams.rgvarg = NULL;
1730 VariantInit(&varresult);
1731 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1732 ok_ole_success(hr, ITypeInfo_Invoke);
1733 ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
1734 ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
1735
1736 VariantClear(&varresult);
1737
1738 dispparams.cNamedArgs = 0;
1739 dispparams.cArgs = 0;
1740 dispparams.rgdispidNamedArgs = NULL;
1741 dispparams.rgvarg = NULL;
1742 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_ERROR, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1743 ok(hr == DISP_E_EXCEPTION, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1744 ok(V_VT(&varresult) == VT_EMPTY, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult));
1745 todo_wine_if(tmarshal_todo)
1746 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1747 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1748 excepinfo.wCode, excepinfo.scode);
1749 VariantClear(&varresult);
1750
1751 ITypeInfo_Release(pTypeInfo);
1752
1753 /* tests call put_Name without named arg */
1754 VariantInit(&vararg[0]);
1755 dispparams.cNamedArgs = 0;
1756 dispparams.rgdispidNamedArgs = NULL;
1757 dispparams.cArgs = 1;
1758 dispparams.rgvarg = vararg;
1759 VariantInit(&varresult);
1760 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1761 ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
1762 VariantClear(&varresult);
1763
1764 /* tests param type that cannot be coerced */
1765 VariantInit(&vararg[0]);
1766 V_VT(&vararg[0]) = VT_UNKNOWN;
1767 V_UNKNOWN(&vararg[0]) = NULL;
1768 dispparams.cNamedArgs = 1;
1769 dispparams.rgdispidNamedArgs = &dispidNamed;
1770 dispparams.cArgs = 1;
1771 dispparams.rgvarg = vararg;
1772 VariantInit(&varresult);
1773 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1774 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
1775 VariantClear(&varresult);
1776
1777 /* tests bad param type */
1778 VariantInit(&vararg[0]);
1779 V_VT(&vararg[0]) = VT_CLSID;
1780 V_BYREF(&vararg[0]) = NULL;
1781 dispparams.cNamedArgs = 1;
1782 dispparams.rgdispidNamedArgs = &dispidNamed;
1783 dispparams.cArgs = 1;
1784 dispparams.rgvarg = vararg;
1785 VariantInit(&varresult);
1786 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1787 ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
1788 VariantClear(&varresult);
1789
1790 /* tests too small param count */
1791 dispparams.cNamedArgs = 0;
1792 dispparams.rgdispidNamedArgs = NULL;
1793 dispparams.cArgs = 0;
1794 dispparams.rgvarg = NULL;
1795 VariantInit(&varresult);
1796 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1797 ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
1798 VariantClear(&varresult);
1799
1800 /* tests propget function with large param count */
1801 VariantInit(&vararg[0]);
1802 V_VT(&vararg[0]) = VT_BSTR;
1803 V_BSTR(&vararg[0]) = NULL;
1804 V_VT(&vararg[1]) = VT_I4;
1805 V_I4(&vararg[1]) = 1;
1806 dispparams.cNamedArgs = 0;
1807 dispparams.cArgs = 2;
1808 dispparams.rgdispidNamedArgs = NULL;
1809 dispparams.rgvarg = vararg;
1810 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1811 ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
1812
1813 /* test propput with lcid */
1814
1815 /* the lcid passed to the function is the first lcid in the typelib header.
1816 Since we don't explicitly set an lcid in the idl, it'll default to US English. */
1817 VariantInit(&vararg[0]);
1818 V_VT(&vararg[0]) = VT_I4;
1819 V_I4(&vararg[0]) = 0xcafe;
1820 dispparams.cNamedArgs = 1;
1821 dispparams.rgdispidNamedArgs = &dispidNamed;
1822 dispparams.cArgs = 1;
1823 dispparams.rgvarg = vararg;
1824 VariantInit(&varresult);
1825 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1826 ok_ole_success(hr, ITypeInfo_Invoke);
1827 VariantClear(&varresult);
1828
1829 /* test propget with lcid */
1830 dispparams.cNamedArgs = 0;
1831 dispparams.cArgs = 0;
1832 dispparams.rgvarg = NULL;
1833 dispparams.rgdispidNamedArgs = NULL;
1834 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1835 ok_ole_success(hr, ITypeInfo_Invoke);
1836 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1837 ok(V_I4(&varresult) == 0x409, "got %x\n", V_I4(&varresult));
1838 VariantClear(&varresult);
1839
1840 /* test propget of INT value */
1841 dispparams.cNamedArgs = 0;
1842 dispparams.cArgs = 0;
1843 dispparams.rgvarg = NULL;
1844 dispparams.rgdispidNamedArgs = NULL;
1845 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_INT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1846 ok_ole_success(hr, ITypeInfo_Invoke);
1847 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1848 ok(V_I4(&varresult) == -13, "got %x\n", V_I4(&varresult));
1849 VariantClear(&varresult);
1850
1851 /* test propget of INT value */
1852 dispparams.cNamedArgs = 0;
1853 dispparams.cArgs = 0;
1854 dispparams.rgvarg = NULL;
1855 dispparams.rgdispidNamedArgs = NULL;
1856 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_UINT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1857 ok_ole_success(hr, ITypeInfo_Invoke);
1858 ok(V_VT(&varresult) == VT_UI4, "got %x\n", V_VT(&varresult));
1859 ok(V_UI4(&varresult) == 42, "got %x\n", V_UI4(&varresult));
1860 VariantClear(&varresult);
1861
1862 /* test byref marshalling */
1863 uval = 666;
1864 VariantInit(&vararg[0]);
1865 V_VT(&vararg[0]) = VT_UI4|VT_BYREF;
1866 V_UI4REF(&vararg[0]) = &uval;
1867 dispparams.cNamedArgs = 0;
1868 dispparams.cArgs = 1;
1869 dispparams.rgvarg = vararg;
1870 dispparams.rgdispidNamedArgs = NULL;
1871 hr = IDispatch_Invoke(pDispatch, DISPID_TM_BYREF_UINT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1872 ok_ole_success(hr, ITypeInfo_Invoke);
1873 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1874 ok(V_VT(&vararg[0]) == (VT_UI4|VT_BYREF), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg[0]));
1875 ok(V_UI4REF(&vararg[0]) == &uval, "Byref pointer not preserved: %p/%p\n", &uval, V_UI4REF(&vararg[0]));
1876 ok(*V_UI4REF(&vararg[0]) == 42, "Expected 42 to be returned instead of %u\n", *V_UI4REF(&vararg[0]));
1877 VariantClear(&varresult);
1878 VariantClear(&vararg[0]);
1879
1880 /* test propput with optional argument. */
1881 VariantInit(&vararg[0]);
1882 V_VT(&vararg[0]) = VT_I4;
1883 V_I4(&vararg[0]) = 0xcafe;
1884 dispparams.cNamedArgs = 1;
1885 dispparams.rgdispidNamedArgs = &dispidNamed;
1886 dispparams.cArgs = 1;
1887 dispparams.rgvarg = vararg;
1888 VariantInit(&varresult);
1889 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_OPT_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1890 ok_ole_success(hr, ITypeInfo_Invoke);
1891 VariantClear(&varresult);
1892
1893 /* test propput with required argument. */
1894 VariantInit(&vararg[0]);
1895 VariantInit(&vararg[1]);
1896 V_VT(&vararg[0]) = VT_I4;
1897 V_I4(&vararg[0]) = 0x1234;
1898 V_VT(&vararg[1]) = VT_I4;
1899 V_I4(&vararg[1]) = 0x5678;
1900 dispparams.cNamedArgs = 1;
1901 dispparams.rgdispidNamedArgs = &dispidNamed;
1902 dispparams.cArgs = 2;
1903 dispparams.rgvarg = vararg;
1904 VariantInit(&varresult);
1905 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_REQ_ARG, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1906 ok_ole_success(hr, ITypeInfo_Invoke);
1907 VariantClear(&varresult);
1908
1909 /* restricted member */
1910 dispparams.cNamedArgs = 0;
1911 dispparams.rgdispidNamedArgs = NULL;
1912 dispparams.cArgs = 0;
1913 dispparams.rgvarg = NULL;
1914 VariantInit(&varresult);
1915 hr = IDispatch_Invoke(pDispatch, DISPID_TM_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1916 ok( hr == DISP_E_MEMBERNOTFOUND, "got %08x\n", hr );
1917 VariantClear(&varresult);
1918
1919 /* restricted member with -ve memid (not restricted) */
1920 dispparams.cNamedArgs = 0;
1921 dispparams.rgdispidNamedArgs = NULL;
1922 dispparams.cArgs = 0;
1923 dispparams.rgvarg = NULL;
1924 VariantInit(&varresult);
1925 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NEG_RESTRICTED, &IID_NULL, 0x40c, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1926 ok( hr == S_OK, "got %08x\n", hr );
1927 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
1928 ok(V_I4(&varresult) == DISPID_TM_NEG_RESTRICTED, "got %x\n", V_I4(&varresult));
1929 VariantClear(&varresult);
1930
1931 IDispatch_Release(pDispatch);
1932 IWidget_Release(pWidget);
1933
1934 trace("calling end_host_object\n");
1935 end_host_object(tid, thread);
1936 }
1937
1938 static void test_DispCallFunc(void)
1939 {
1940 static const WCHAR szEmpty[] = { 0 };
1941 VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
1942 VARIANTARG vararg[4];
1943 VARIANTARG varref;
1944 VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
1945 VARIANTARG varresult;
1946 HRESULT hr;
1947 IWidget *pWidget = Widget_Create();
1948 V_VT(&vararg[0]) = VT_R8;
1949 V_R8(&vararg[0]) = 3.141;
1950 V_VT(&vararg[1]) = VT_BSTR;
1951 V_BSTRREF(&vararg[1]) = CoTaskMemAlloc(sizeof(BSTR));
1952 V_VT(&vararg[2]) = VT_BSTR;
1953 V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
1954 V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
1955 V_VARIANTREF(&vararg[3]) = &varref;
1956 V_VT(&varref) = VT_ERROR;
1957 V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
1958 VariantInit(&varresult);
1959 hr = DispCallFunc(pWidget, 9*sizeof(void*), CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
1960 ok_ole_success(hr, DispCallFunc);
1961 VariantClear(&varresult);
1962 SysFreeString(*V_BSTRREF(&vararg[1]));
1963 CoTaskMemFree(V_BSTRREF(&vararg[1]));
1964 VariantClear(&vararg[2]);
1965 IWidget_Release(pWidget);
1966 }
1967
1968 static void test_StaticWidget(void)
1969 {
1970 ITypeInfo *type_info;
1971 DISPPARAMS dispparams;
1972 VARIANTARG vararg[4];
1973 EXCEPINFO excepinfo;
1974 VARIANT varresult;
1975 HRESULT hr;
1976
1977 type_info = get_type_info(&IID_IStaticWidget);
1978
1979 /* call TestDual */
1980 dispparams.cNamedArgs = 0;
1981 dispparams.cArgs = 1;
1982 dispparams.rgdispidNamedArgs = NULL;
1983 dispparams.rgvarg = vararg;
1984 V_VT(vararg) = VT_DISPATCH;
1985 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
1986 VariantInit(&varresult);
1987 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTDUAL, DISPATCH_METHOD,
1988 &dispparams, &varresult, &excepinfo, NULL);
1989 ok_ole_success(hr, IDispatch_Invoke);
1990 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
1991 VariantClear(&varresult);
1992
1993 /* call TestSecondIface */
1994 dispparams.cNamedArgs = 0;
1995 dispparams.cArgs = 1;
1996 dispparams.rgdispidNamedArgs = NULL;
1997 dispparams.rgvarg = vararg;
1998 V_VT(vararg) = VT_DISPATCH;
1999 V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
2000 VariantInit(&varresult);
2001 hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTSECONDIFACE, DISPATCH_METHOD,
2002 &dispparams, &varresult, &excepinfo, NULL);
2003 ok_ole_success(hr, IDispatch_Invoke);
2004 ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
2005 VariantClear(&varresult);
2006
2007 ITypeInfo_Release(type_info);
2008 }
2009
2010 static void test_libattr(void)
2011 {
2012 ITypeLib *pTypeLib;
2013 HRESULT hr;
2014 TLIBATTR *pattr;
2015
2016 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
2017 ok_ole_success(hr, LoadRegTypeLib);
2018 if (FAILED(hr))
2019 return;
2020
2021 hr = ITypeLib_GetLibAttr(pTypeLib, &pattr);
2022 ok_ole_success(hr, GetLibAttr);
2023 if (SUCCEEDED(hr))
2024 {
2025 ok(pattr->lcid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "lcid %x\n", pattr->lcid);
2026
2027 ITypeLib_ReleaseTLibAttr(pTypeLib, pattr);
2028 }
2029
2030 ITypeLib_Release(pTypeLib);
2031 }
2032
2033 static void test_external_connection(void)
2034 {
2035 IStream *stream, *stream2;
2036 ITestSecondDisp *second;
2037 ItestDual *iface;
2038 HANDLE thread;
2039 DWORD tid;
2040 HRESULT hres;
2041
2042 static const LARGE_INTEGER zero;
2043
2044 trace("Testing IExternalConnection...\n");
2045
2046 external_connections = 0;
2047
2048 /* Marshaling an interface increases external connection count. */
2049 expect_last_release_closes = FALSE;
2050 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2051 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2052 tid = start_host_object(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHLFLAGS_NORMAL, &thread);
2053 ok(external_connections == 1, "external_connections = %d\n", external_connections);
2054
2055 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2056 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
2057 todo_wine_if(tmarshal_todo)
2058 ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
2059 ok(external_connections == 1, "external_connections = %d\n", external_connections);
2060
2061 IStream_Release(stream);
2062 ok(external_connections == 1, "external_connections = %d\n", external_connections);
2063
2064 /* Creating a stub for new iface causes new external connection. */
2065 hres = ItestDual_QueryInterface(iface, &IID_ITestSecondDisp, (void**)&second);
2066 todo_wine_if(tmarshal_todo)
2067 ok(hres == S_OK, "Could not get ITestSecondDisp iface: %08x\n", hres);
2068 todo_wine
2069 ok(external_connections == 2, "external_connections = %d\n", external_connections);
2070
2071 if (hres == S_OK)
2072 ITestSecondDisp_Release(second);
2073 todo_wine
2074 ok(external_connections == 2, "external_connections = %d\n", external_connections);
2075
2076 expect_last_release_closes = TRUE;
2077 ItestDual_Release(iface);
2078 todo_wine_if(tmarshal_todo)
2079 ok(external_connections == 0, "external_connections = %d\n", external_connections);
2080
2081 end_host_object(tid, thread);
2082
2083 /* A test with direct CoMarshalInterface call. */
2084 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2085 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2086
2087 expect_last_release_closes = FALSE;
2088 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2089 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2090 todo_wine_if(tmarshal_todo)
2091 ok(external_connections == 1, "external_connections = %d\n", external_connections);
2092
2093 expect_last_release_closes = TRUE;
2094 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2095 hres = CoReleaseMarshalData(stream);
2096 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2097 todo_wine_if(tmarshal_todo)
2098 ok(external_connections == 0, "external_connections = %d\n", external_connections);
2099
2100 /* Two separated marshal data are still one external connection. */
2101 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream2);
2102 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2103
2104 expect_last_release_closes = FALSE;
2105 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2106 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2107 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2108 todo_wine_if(tmarshal_todo)
2109 ok(external_connections == 1, "external_connections = %d\n", external_connections);
2110
2111 hres = CoMarshalInterface(stream2, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2112 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2113 todo_wine_if(tmarshal_todo)
2114 ok(external_connections == 1, "external_connections = %d\n", external_connections);
2115
2116 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2117 hres = CoReleaseMarshalData(stream);
2118 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2119 todo_wine_if(tmarshal_todo)
2120 ok(external_connections == 1, "external_connections = %d\n", external_connections);
2121
2122 expect_last_release_closes = TRUE;
2123 IStream_Seek(stream2, zero, STREAM_SEEK_SET, NULL);
2124 hres = CoReleaseMarshalData(stream2);
2125 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2126 todo_wine_if(tmarshal_todo)
2127 ok(external_connections == 0, "external_connections = %d\n", external_connections);
2128
2129 IStream_Release(stream);
2130 IStream_Release(stream2);
2131
2132 /* Weak table marshaling does not increment external connections */
2133 hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2134 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
2135
2136 hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
2137 ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
2138 todo_wine_if(tmarshal_todo)
2139 ok(external_connections == 0, "external_connections = %d\n", external_connections);
2140
2141 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2142 hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
2143 ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
2144 todo_wine_if(tmarshal_todo)
2145 ok(external_connections == 0, "external_connections = %d\n", external_connections);
2146 ItestDual_Release(iface);
2147
2148 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
2149 hres = CoReleaseMarshalData(stream);
2150 ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
2151 todo_wine_if(tmarshal_todo)
2152 ok(external_connections == 0, "external_connections = %d\n", external_connections);
2153
2154 IStream_Release(stream);
2155 }
2156
2157 START_TEST(tmarshal)
2158 {
2159 HRESULT hr;
2160 HANDLE hOleaut32 = GetModuleHandleA("oleaut32.dll");
2161 pVarAdd = (void*)GetProcAddress(hOleaut32, "VarAdd");
2162
2163 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2164
2165 hr = register_current_module_typelib();
2166 if (FAILED(hr))
2167 {
2168 CoUninitialize();
2169 win_skip("Registration of the test typelib failed, skipping tests\n");
2170 return;
2171 }
2172
2173 test_typelibmarshal();
2174 test_DispCallFunc();
2175 test_StaticWidget();
2176 test_libattr();
2177 test_external_connection();
2178
2179 hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
2180 sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
2181 ok_ole_success(hr, UnRegisterTypeLib);
2182
2183 CoUninitialize();
2184 }