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 } 2185