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