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