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