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