1 /* 2 * Misc marshalling routines 3 * 4 * Copyright 2002 Ove Kaaven 5 * Copyright 2003 Mike Hearn 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 #include <string.h> 24 25 #define COBJMACROS 26 #define NONAMELESSUNION 27 28 #include "windef.h" 29 #include "winbase.h" 30 #include "wingdi.h" 31 #include "winuser.h" 32 #include "winerror.h" 33 34 #include "ole2.h" 35 #include "oleauto.h" 36 #include "typelib.h" 37 #include "ocidl.h" 38 #include "wine/debug.h" 39 40 WINE_DEFAULT_DEBUG_CHANNEL(ole); 41 42 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align)) 43 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) 44 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) 45 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align) 46 47 /* ole32 exports those, not defined in public headers */ 48 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG*, ULONG, ULONG, IUnknown*, REFIID); 49 unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG*, ULONG, unsigned char*, IUnknown*, REFIID); 50 unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG*, unsigned char*, IUnknown**, REFIID); 51 52 static void dump_user_flags(const ULONG *pFlags) 53 { 54 if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION) 55 TRACE("MAKELONG(NDR_LOCAL_REPRESENTATION, "); 56 else 57 TRACE("MAKELONG(0x%04x, ", HIWORD(*pFlags)); 58 switch (LOWORD(*pFlags)) 59 { 60 case MSHCTX_LOCAL: TRACE("MSHCTX_LOCAL)"); break; 61 case MSHCTX_NOSHAREDMEM: TRACE("MSHCTX_NOSHAREDMEM)"); break; 62 case MSHCTX_DIFFERENTMACHINE: TRACE("MSHCTX_DIFFERENTMACHINE)"); break; 63 case MSHCTX_INPROC: TRACE("MSHCTX_INPROC)"); break; 64 default: TRACE("%d)", LOWORD(*pFlags)); 65 } 66 } 67 68 /* CLEANLOCALSTORAGE */ 69 70 #define CLS_FUNCDESC 'f' 71 #define CLS_LIBATTR 'l' 72 #define CLS_TYPEATTR 't' 73 #define CLS_VARDESC 'v' 74 75 ULONG WINAPI CLEANLOCALSTORAGE_UserSize(ULONG *pFlags, ULONG Start, CLEANLOCALSTORAGE *pstg) 76 { 77 ALIGN_LENGTH(Start, 3); 78 return Start + sizeof(DWORD); 79 } 80 81 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg) 82 { 83 ALIGN_POINTER(Buffer, 3); 84 *(DWORD*)Buffer = pstg->flags; 85 86 if (!pstg->pInterface) 87 return Buffer + sizeof(DWORD); 88 89 switch(pstg->flags) 90 { 91 case CLS_LIBATTR: 92 ITypeLib_ReleaseTLibAttr((ITypeLib*)pstg->pInterface, *(TLIBATTR**)pstg->pStorage); 93 break; 94 case CLS_TYPEATTR: 95 ITypeInfo_ReleaseTypeAttr((ITypeInfo*)pstg->pInterface, *(TYPEATTR**)pstg->pStorage); 96 break; 97 case CLS_FUNCDESC: 98 ITypeInfo_ReleaseFuncDesc((ITypeInfo*)pstg->pInterface, *(FUNCDESC**)pstg->pStorage); 99 break; 100 case CLS_VARDESC: 101 ITypeInfo_ReleaseVarDesc((ITypeInfo*)pstg->pInterface, *(VARDESC**)pstg->pStorage); 102 break; 103 104 default: 105 ERR("Unknown type %x\n", pstg->flags); 106 } 107 108 *(VOID**)pstg->pStorage = NULL; 109 IUnknown_Release(pstg->pInterface); 110 pstg->pInterface = NULL; 111 112 return Buffer + sizeof(DWORD); 113 } 114 115 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr) 116 { 117 ALIGN_POINTER(Buffer, 3); 118 pstr->flags = *(DWORD*)Buffer; 119 return Buffer + sizeof(DWORD); 120 } 121 122 void WINAPI CLEANLOCALSTORAGE_UserFree(ULONG *pFlags, CLEANLOCALSTORAGE *pstr) 123 { 124 /* Nothing to do */ 125 } 126 127 /* BSTR */ 128 129 typedef struct 130 { 131 DWORD len; /* No. of chars not including trailing '\0' */ 132 DWORD byte_len; /* len * 2 or 0xffffffff if len == 0 */ 133 DWORD len2; /* == len */ 134 } bstr_wire_t; 135 136 ULONG WINAPI BSTR_UserSize(ULONG *pFlags, ULONG Start, BSTR *pstr) 137 { 138 TRACE("(%x,%d,%p) => %p\n", *pFlags, Start, pstr, *pstr); 139 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); 140 ALIGN_LENGTH(Start, 3); 141 Start += sizeof(bstr_wire_t) + ((SysStringByteLen(*pstr) + 1) & ~1); 142 TRACE("returning %d\n", Start); 143 return Start; 144 } 145 146 unsigned char * WINAPI BSTR_UserMarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr) 147 { 148 bstr_wire_t *header; 149 DWORD len = SysStringByteLen(*pstr); 150 151 TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr); 152 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); 153 154 ALIGN_POINTER(Buffer, 3); 155 header = (bstr_wire_t*)Buffer; 156 header->len = header->len2 = (len + 1) / 2; 157 if (*pstr) 158 { 159 header->byte_len = len; 160 memcpy(header + 1, *pstr, header->len * 2); 161 } 162 else 163 header->byte_len = 0xffffffff; /* special case for a null bstr */ 164 165 return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len; 166 } 167 168 unsigned char * WINAPI BSTR_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr) 169 { 170 bstr_wire_t *header; 171 TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr); 172 173 ALIGN_POINTER(Buffer, 3); 174 header = (bstr_wire_t*)Buffer; 175 if(header->len != header->len2) 176 FIXME("len %08x != len2 %08x\n", header->len, header->len2); 177 178 if (header->byte_len == 0xffffffff) 179 { 180 SysFreeString(*pstr); 181 *pstr = NULL; 182 } 183 else SysReAllocStringLen( pstr, (OLECHAR *)(header + 1), header->len ); 184 185 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); 186 return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len; 187 } 188 189 void WINAPI BSTR_UserFree(ULONG *pFlags, BSTR *pstr) 190 { 191 TRACE("(%x,%p) => %p\n", *pFlags, pstr, *pstr); 192 SysFreeString(*pstr); 193 *pstr = NULL; 194 } 195 196 /* VARIANT */ 197 198 typedef struct 199 { 200 DWORD clSize; 201 DWORD rpcReserved; 202 USHORT vt; 203 USHORT wReserved1; 204 USHORT wReserved2; 205 USHORT wReserved3; 206 DWORD switch_is; 207 } variant_wire_t; 208 209 unsigned int get_type_size(ULONG *pFlags, VARTYPE vt) 210 { 211 if (vt & VT_ARRAY) return 4; 212 213 switch (vt & ~VT_BYREF) { 214 case VT_EMPTY: 215 case VT_NULL: 216 return 0; 217 case VT_I1: 218 case VT_UI1: 219 return sizeof(CHAR); 220 case VT_I2: 221 case VT_UI2: 222 return sizeof(SHORT); 223 case VT_I4: 224 case VT_UI4: 225 case VT_HRESULT: 226 return sizeof(LONG); 227 case VT_INT: 228 case VT_UINT: 229 return sizeof(INT); 230 case VT_R4: 231 return sizeof(FLOAT); 232 case VT_R8: 233 return sizeof(DOUBLE); 234 case VT_BOOL: 235 return sizeof(VARIANT_BOOL); 236 case VT_ERROR: 237 return sizeof(SCODE); 238 case VT_DATE: 239 return sizeof(DATE); 240 case VT_CY: 241 return sizeof(CY); 242 case VT_DECIMAL: 243 return sizeof(DECIMAL); 244 case VT_BSTR: 245 return sizeof(ULONG); 246 case VT_VARIANT: 247 return sizeof(VARIANT); 248 case VT_UNKNOWN: 249 case VT_DISPATCH: 250 case VT_RECORD: 251 return 0; 252 default: 253 FIXME("unhandled VT %d\n", vt); 254 return 0; 255 } 256 } 257 258 static unsigned int get_type_alignment(ULONG *pFlags, VARTYPE vt) 259 { 260 unsigned int size = get_type_size(pFlags, vt); 261 if(vt & VT_BYREF) return 3; 262 if(size == 0) return 0; 263 if(size <= 4) return size - 1; 264 return 7; 265 } 266 267 /* WdtpInterfacePointer_UserSize takes care of 2 additional DWORDs to store marshalling buffer size */ 268 static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *punk) 269 { 270 ULONG size = 0; 271 272 if (punk) 273 { 274 size = WdtpInterfacePointer_UserSize(pFlags, LOWORD(*pFlags), 0, punk, riid); 275 if (!size) 276 { 277 ERR("interface variant buffer size calculation failed\n"); 278 return 0; 279 } 280 } 281 size += sizeof(ULONG); 282 TRACE("wire-size extra of interface variant is %d\n", size); 283 return size; 284 } 285 286 static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar) 287 { 288 if (V_ISARRAY(pvar)) 289 { 290 if (V_ISBYREF(pvar)) 291 return LPSAFEARRAY_UserSize(pFlags, Start, V_ARRAYREF(pvar)); 292 else 293 return LPSAFEARRAY_UserSize(pFlags, Start, &V_ARRAY(pvar)); 294 } 295 296 switch (V_VT(pvar)) { 297 case VT_BSTR: 298 return BSTR_UserSize(pFlags, Start, &V_BSTR(pvar)); 299 case VT_BSTR | VT_BYREF: 300 return BSTR_UserSize(pFlags, Start, V_BSTRREF(pvar)); 301 case VT_VARIANT | VT_BYREF: 302 return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar)); 303 case VT_UNKNOWN: 304 return Start + interface_variant_size(pFlags, &IID_IUnknown, V_UNKNOWN(pvar)); 305 case VT_UNKNOWN | VT_BYREF: 306 return Start + interface_variant_size(pFlags, &IID_IUnknown, *V_UNKNOWNREF(pvar)); 307 case VT_DISPATCH: 308 return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar)); 309 case VT_DISPATCH | VT_BYREF: 310 return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar)); 311 case VT_RECORD: 312 FIXME("wire-size record\n"); 313 return Start; 314 case VT_SAFEARRAY: 315 case VT_SAFEARRAY | VT_BYREF: 316 FIXME("wire-size safearray: shouldn't be marshaling this\n"); 317 return Start; 318 default: 319 return Start; 320 } 321 } 322 323 /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer */ 324 static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer, 325 REFIID riid, IUnknown *punk) 326 { 327 TRACE("pFlags=%d, Buffer=%p, pUnk=%p\n", *pFlags, Buffer, punk); 328 329 /* first DWORD is used to store pointer itself, truncated on win64 */ 330 if(!punk) 331 { 332 memset(Buffer, 0, sizeof(ULONG)); 333 return Buffer + sizeof(ULONG); 334 } 335 else 336 { 337 *(DWORD*)Buffer = (DWORD_PTR)punk; 338 Buffer += sizeof(DWORD); 339 } 340 341 return WdtpInterfacePointer_UserMarshal(pFlags, LOWORD(*pFlags), Buffer, punk, riid); 342 } 343 344 /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer */ 345 static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer, 346 REFIID riid, IUnknown **ppunk) 347 { 348 DWORD ptr; 349 350 TRACE("pFlags=%d, Buffer=%p, ppUnk=%p\n", *pFlags, Buffer, ppunk); 351 352 /* skip pointer part itself */ 353 ptr = *(DWORD*)Buffer; 354 Buffer += sizeof(DWORD); 355 356 if(!ptr) 357 return Buffer; 358 359 return WdtpInterfacePointer_UserUnmarshal(pFlags, Buffer, ppunk, riid); 360 } 361 362 ULONG WINAPI VARIANT_UserSize(ULONG *pFlags, ULONG Start, VARIANT *pvar) 363 { 364 int align; 365 TRACE("(%x,%d,%p)\n", *pFlags, Start, pvar); 366 TRACE("vt=%04x\n", V_VT(pvar)); 367 368 ALIGN_LENGTH(Start, 7); 369 Start += sizeof(variant_wire_t); 370 if(V_VT(pvar) & VT_BYREF) 371 Start += 4; 372 373 align = get_type_alignment(pFlags, V_VT(pvar)); 374 ALIGN_LENGTH(Start, align); 375 if(V_VT(pvar) == (VT_VARIANT | VT_BYREF)) 376 Start += 4; 377 else 378 Start += get_type_size(pFlags, V_VT(pvar)); 379 Start = wire_extra_user_size(pFlags, Start, pvar); 380 381 TRACE("returning %d\n", Start); 382 return Start; 383 } 384 385 unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar) 386 { 387 variant_wire_t *header; 388 ULONG type_size; 389 int align; 390 unsigned char *Pos; 391 392 TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar); 393 TRACE("vt=%04x\n", V_VT(pvar)); 394 395 ALIGN_POINTER(Buffer, 7); 396 397 header = (variant_wire_t *)Buffer; 398 399 header->clSize = 0; /* fixed up at the end */ 400 header->rpcReserved = 0; 401 header->vt = pvar->n1.n2.vt; 402 header->wReserved1 = pvar->n1.n2.wReserved1; 403 header->wReserved2 = pvar->n1.n2.wReserved2; 404 header->wReserved3 = pvar->n1.n2.wReserved3; 405 header->switch_is = pvar->n1.n2.vt; 406 if(header->switch_is & VT_ARRAY) 407 header->switch_is &= ~VT_TYPEMASK; 408 409 Pos = (unsigned char*)(header + 1); 410 type_size = get_type_size(pFlags, V_VT(pvar)); 411 align = get_type_alignment(pFlags, V_VT(pvar)); 412 ALIGN_POINTER(Pos, align); 413 414 if(header->vt & VT_BYREF) 415 { 416 *(DWORD *)Pos = max(type_size, 4); 417 Pos += 4; 418 if((header->vt & VT_TYPEMASK) != VT_VARIANT) 419 { 420 memcpy(Pos, pvar->n1.n2.n3.byref, type_size); 421 Pos += type_size; 422 } 423 else 424 { 425 *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24; 426 Pos += 4; 427 } 428 } 429 else 430 { 431 if((header->vt & VT_TYPEMASK) == VT_DECIMAL) 432 memcpy(Pos, pvar, type_size); 433 else 434 memcpy(Pos, &pvar->n1.n2.n3, type_size); 435 Pos += type_size; 436 } 437 438 if(header->vt & VT_ARRAY) 439 { 440 if(header->vt & VT_BYREF) 441 Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar)); 442 else 443 Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar)); 444 } 445 else 446 { 447 switch (header->vt) 448 { 449 case VT_BSTR: 450 Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar)); 451 break; 452 case VT_BSTR | VT_BYREF: 453 Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar)); 454 break; 455 case VT_VARIANT | VT_BYREF: 456 Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); 457 break; 458 case VT_UNKNOWN: 459 Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar)); 460 break; 461 case VT_UNKNOWN | VT_BYREF: 462 Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar)); 463 break; 464 case VT_DISPATCH: 465 Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar)); 466 break; 467 case VT_DISPATCH | VT_BYREF: 468 Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar)); 469 break; 470 case VT_RECORD: 471 FIXME("handle BRECORD by val\n"); 472 break; 473 case VT_RECORD | VT_BYREF: 474 FIXME("handle BRECORD by ref\n"); 475 break; 476 } 477 } 478 header->clSize = ((Pos - Buffer) + 7) >> 3; 479 TRACE("marshalled size=%d\n", header->clSize); 480 return Pos; 481 } 482 483 unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar) 484 { 485 variant_wire_t *header; 486 ULONG type_size; 487 int align; 488 unsigned char *Pos; 489 490 TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar); 491 492 ALIGN_POINTER(Buffer, 7); 493 494 header = (variant_wire_t *)Buffer; 495 496 Pos = (unsigned char*)(header + 1); 497 type_size = get_type_size(pFlags, header->vt); 498 align = get_type_alignment(pFlags, header->vt); 499 ALIGN_POINTER(Pos, align); 500 501 if(header->vt & VT_BYREF) 502 { 503 ULONG mem_size; 504 Pos += 4; 505 506 switch (header->vt & ~VT_BYREF) 507 { 508 /* these types have a different memory size compared to wire size */ 509 case VT_UNKNOWN: 510 case VT_DISPATCH: 511 case VT_BSTR: 512 mem_size = sizeof(void *); 513 break; 514 default: 515 mem_size = type_size; 516 break; 517 } 518 519 if (V_VT(pvar) != header->vt) 520 { 521 VariantClear(pvar); 522 V_BYREF(pvar) = CoTaskMemAlloc(mem_size); 523 memset(V_BYREF(pvar), 0, mem_size); 524 } 525 else if (!V_BYREF(pvar)) 526 { 527 V_BYREF(pvar) = CoTaskMemAlloc(mem_size); 528 memset(V_BYREF(pvar), 0, mem_size); 529 } 530 531 if(!(header->vt & VT_ARRAY) 532 && (header->vt & VT_TYPEMASK) != VT_BSTR 533 && (header->vt & VT_TYPEMASK) != VT_VARIANT 534 && (header->vt & VT_TYPEMASK) != VT_UNKNOWN 535 && (header->vt & VT_TYPEMASK) != VT_DISPATCH 536 && (header->vt & VT_TYPEMASK) != VT_RECORD) 537 memcpy(V_BYREF(pvar), Pos, type_size); 538 539 if((header->vt & VT_TYPEMASK) != VT_VARIANT) 540 Pos += type_size; 541 else 542 Pos += 4; 543 } 544 else 545 { 546 VariantClear(pvar); 547 if(header->vt & VT_ARRAY) 548 V_ARRAY(pvar) = NULL; 549 else if((header->vt & VT_TYPEMASK) == VT_BSTR) 550 V_BSTR(pvar) = NULL; 551 else if((header->vt & VT_TYPEMASK) == VT_UNKNOWN) 552 V_UNKNOWN(pvar) = NULL; 553 else if((header->vt & VT_TYPEMASK) == VT_DISPATCH) 554 V_DISPATCH(pvar) = NULL; 555 else if((header->vt & VT_TYPEMASK) == VT_RECORD) 556 V_RECORD(pvar) = NULL; 557 else if((header->vt & VT_TYPEMASK) == VT_DECIMAL) 558 memcpy(pvar, Pos, type_size); 559 else 560 memcpy(&pvar->n1.n2.n3, Pos, type_size); 561 Pos += type_size; 562 } 563 564 pvar->n1.n2.vt = header->vt; 565 pvar->n1.n2.wReserved1 = header->wReserved1; 566 pvar->n1.n2.wReserved2 = header->wReserved2; 567 pvar->n1.n2.wReserved3 = header->wReserved3; 568 569 if(header->vt & VT_ARRAY) 570 { 571 if(header->vt & VT_BYREF) 572 Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar)); 573 else 574 Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar)); 575 } 576 else 577 { 578 switch (header->vt) 579 { 580 case VT_BSTR: 581 Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar)); 582 break; 583 case VT_BSTR | VT_BYREF: 584 Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar)); 585 break; 586 case VT_VARIANT | VT_BYREF: 587 Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar)); 588 break; 589 case VT_UNKNOWN: 590 Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar)); 591 break; 592 case VT_UNKNOWN | VT_BYREF: 593 Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar)); 594 break; 595 case VT_DISPATCH: 596 Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar)); 597 break; 598 case VT_DISPATCH | VT_BYREF: 599 Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar)); 600 break; 601 case VT_RECORD: 602 FIXME("handle BRECORD by val\n"); 603 break; 604 case VT_RECORD | VT_BYREF: 605 FIXME("handle BRECORD by ref\n"); 606 break; 607 } 608 } 609 return Pos; 610 } 611 612 void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar) 613 { 614 VARTYPE vt = V_VT(pvar); 615 PVOID ref = NULL; 616 617 TRACE("(%x,%p)\n", *pFlags, pvar); 618 TRACE("vt=%04x\n", V_VT(pvar)); 619 620 if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref; 621 622 VariantClear(pvar); 623 if (!ref) return; 624 625 if(vt & VT_ARRAY) 626 { 627 if (vt & VT_BYREF) 628 LPSAFEARRAY_UserFree(pFlags, V_ARRAYREF(pvar)); 629 else 630 LPSAFEARRAY_UserFree(pFlags, &V_ARRAY(pvar)); 631 } 632 else 633 { 634 switch (vt) 635 { 636 case VT_BSTR | VT_BYREF: 637 BSTR_UserFree(pFlags, V_BSTRREF(pvar)); 638 break; 639 case VT_VARIANT | VT_BYREF: 640 VARIANT_UserFree(pFlags, V_VARIANTREF(pvar)); 641 break; 642 case VT_RECORD | VT_BYREF: 643 FIXME("handle BRECORD by ref\n"); 644 break; 645 case VT_UNKNOWN | VT_BYREF: 646 case VT_DISPATCH | VT_BYREF: 647 IUnknown_Release(*V_UNKNOWNREF(pvar)); 648 break; 649 } 650 } 651 652 CoTaskMemFree(ref); 653 } 654 655 /* LPSAFEARRAY */ 656 657 /* Get the number of cells in a SafeArray */ 658 static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa) 659 { 660 const SAFEARRAYBOUND* psab = psa->rgsabound; 661 USHORT cCount = psa->cDims; 662 ULONG ulNumCells = 1; 663 664 while (cCount--) 665 { 666 /* This is a valid bordercase. See testcases. -Marcus */ 667 if (!psab->cElements) 668 return 0; 669 ulNumCells *= psab->cElements; 670 psab++; 671 } 672 return ulNumCells; 673 } 674 675 static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa) 676 { 677 VARTYPE vt; 678 HRESULT hr; 679 680 hr = SafeArrayGetVartype(psa, &vt); 681 if (FAILED(hr)) 682 { 683 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT; 684 685 switch(psa->cbElements) 686 { 687 case 1: vt = VT_I1; break; 688 case 2: vt = VT_I2; break; 689 case 4: vt = VT_I4; break; 690 case 8: vt = VT_I8; break; 691 default: 692 RpcRaiseException(hr); 693 } 694 } 695 696 if (psa->fFeatures & FADF_HAVEIID) 697 return SF_HAVEIID; 698 699 switch (vt) 700 { 701 case VT_I1: 702 case VT_UI1: return SF_I1; 703 case VT_BOOL: 704 case VT_I2: 705 case VT_UI2: return SF_I2; 706 case VT_INT: 707 case VT_UINT: 708 case VT_I4: 709 case VT_UI4: 710 case VT_R4: return SF_I4; 711 case VT_DATE: 712 case VT_CY: 713 case VT_R8: 714 case VT_I8: 715 case VT_UI8: return SF_I8; 716 case VT_INT_PTR: 717 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8); 718 case VT_BSTR: return SF_BSTR; 719 case VT_DISPATCH: return SF_DISPATCH; 720 case VT_VARIANT: return SF_VARIANT; 721 case VT_UNKNOWN: return SF_UNKNOWN; 722 /* Note: Return a non-zero size to indicate vt is valid. The actual size 723 * of a UDT is taken from the result of IRecordInfo_GetSize(). 724 */ 725 case VT_RECORD: return SF_RECORD; 726 default: return SF_ERROR; 727 } 728 } 729 730 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype) 731 { 732 if (sftype == SF_BSTR) 733 return sizeof(DWORD); 734 else if (sftype == SF_VARIANT) 735 return sizeof(variant_wire_t) - sizeof(DWORD); 736 else 737 return lpsa->cbElements; 738 } 739 740 static DWORD elem_mem_size(wireSAFEARRAY wiresa, SF_TYPE sftype) 741 { 742 if (sftype == SF_BSTR) 743 return sizeof(BSTR); 744 else if (sftype == SF_VARIANT) 745 return sizeof(VARIANT); 746 else 747 return wiresa->cbElements; 748 } 749 750 ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa) 751 { 752 ULONG size = StartingSize; 753 754 TRACE("("); dump_user_flags(pFlags); TRACE(", %d, %p\n", StartingSize, *ppsa); 755 756 ALIGN_LENGTH(size, 3); 757 size += sizeof(ULONG); 758 if (*ppsa) 759 { 760 SAFEARRAY *psa = *ppsa; 761 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); 762 SF_TYPE sftype; 763 HRESULT hr; 764 765 size += sizeof(ULONG); 766 size += 2 * sizeof(USHORT) + 2 * sizeof(ULONG); 767 768 sftype = SAFEARRAY_GetUnionType(psa); 769 size += sizeof(ULONG); 770 771 size += sizeof(ULONG); 772 size += sizeof(ULONG); 773 if (sftype == SF_HAVEIID) 774 size += sizeof(IID); 775 776 size += sizeof(psa->rgsabound[0]) * psa->cDims; 777 778 size += sizeof(ULONG); 779 780 switch (sftype) 781 { 782 case SF_BSTR: 783 { 784 BSTR* lpBstr; 785 786 for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++) 787 size = BSTR_UserSize(pFlags, size, lpBstr); 788 789 break; 790 } 791 case SF_DISPATCH: 792 case SF_UNKNOWN: 793 case SF_HAVEIID: 794 FIXME("size interfaces\n"); 795 break; 796 case SF_VARIANT: 797 { 798 VARIANT* lpVariant; 799 800 for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++) 801 size = VARIANT_UserSize(pFlags, size, lpVariant); 802 803 break; 804 } 805 case SF_RECORD: 806 { 807 IRecordInfo* pRecInfo = NULL; 808 809 hr = SafeArrayGetRecordInfo(psa, &pRecInfo); 810 if (FAILED(hr)) 811 RpcRaiseException(hr); 812 813 if (pRecInfo) 814 { 815 FIXME("size record info %p\n", pRecInfo); 816 817 IRecordInfo_Release(pRecInfo); 818 } 819 break; 820 } 821 case SF_I8: 822 ALIGN_LENGTH(size, 7); 823 /* fallthrough */ 824 case SF_I1: 825 case SF_I2: 826 case SF_I4: 827 size += ulCellCount * psa->cbElements; 828 break; 829 default: 830 break; 831 } 832 833 } 834 835 return size; 836 } 837 838 unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) 839 { 840 HRESULT hr; 841 842 TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa); 843 844 ALIGN_POINTER(Buffer, 3); 845 *(ULONG *)Buffer = *ppsa ? 0x1 : 0x0; 846 Buffer += sizeof(ULONG); 847 if (*ppsa) 848 { 849 VARTYPE vt; 850 SAFEARRAY *psa = *ppsa; 851 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); 852 SAFEARRAYBOUND *bound; 853 SF_TYPE sftype; 854 GUID guid; 855 INT i; 856 857 sftype = SAFEARRAY_GetUnionType(psa); 858 859 *(ULONG *)Buffer = psa->cDims; 860 Buffer += sizeof(ULONG); 861 *(USHORT *)Buffer = psa->cDims; 862 Buffer += sizeof(USHORT); 863 *(USHORT *)Buffer = psa->fFeatures; 864 Buffer += sizeof(USHORT); 865 *(ULONG *)Buffer = elem_wire_size(psa, sftype); 866 Buffer += sizeof(ULONG); 867 868 hr = SafeArrayGetVartype(psa, &vt); 869 if (FAILED(hr)) vt = 0; 870 871 *(ULONG *)Buffer = (USHORT)psa->cLocks | (vt << 16); 872 Buffer += sizeof(ULONG); 873 874 *(ULONG *)Buffer = sftype; 875 Buffer += sizeof(ULONG); 876 877 *(ULONG *)Buffer = ulCellCount; 878 Buffer += sizeof(ULONG); 879 *(ULONG *)Buffer = psa->pvData ? 0x2 : 0x0; 880 Buffer += sizeof(ULONG); 881 if (sftype == SF_HAVEIID) 882 { 883 SafeArrayGetIID(psa, &guid); 884 memcpy(Buffer, &guid, sizeof(guid)); 885 Buffer += sizeof(guid); 886 } 887 888 /* bounds are marshaled in opposite order comparing to storage layout */ 889 bound = (SAFEARRAYBOUND*)Buffer; 890 for (i = 0; i < psa->cDims; i++) 891 { 892 memcpy(bound++, &psa->rgsabound[psa->cDims-i-1], sizeof(psa->rgsabound[0])); 893 } 894 Buffer += sizeof(psa->rgsabound[0]) * psa->cDims; 895 896 *(ULONG *)Buffer = ulCellCount; 897 Buffer += sizeof(ULONG); 898 899 if (psa->pvData) 900 { 901 switch (sftype) 902 { 903 case SF_BSTR: 904 { 905 BSTR* lpBstr; 906 907 for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++) 908 Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr); 909 910 break; 911 } 912 case SF_DISPATCH: 913 case SF_UNKNOWN: 914 case SF_HAVEIID: 915 FIXME("marshal interfaces\n"); 916 break; 917 case SF_VARIANT: 918 { 919 VARIANT* lpVariant; 920 921 for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++) 922 Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant); 923 924 break; 925 } 926 case SF_RECORD: 927 { 928 IRecordInfo* pRecInfo = NULL; 929 930 hr = SafeArrayGetRecordInfo(psa, &pRecInfo); 931 if (FAILED(hr)) 932 RpcRaiseException(hr); 933 934 if (pRecInfo) 935 { 936 FIXME("write record info %p\n", pRecInfo); 937 938 IRecordInfo_Release(pRecInfo); 939 } 940 break; 941 } 942 943 case SF_I8: 944 ALIGN_POINTER(Buffer, 7); 945 /* fallthrough */ 946 case SF_I1: 947 case SF_I2: 948 case SF_I4: 949 /* Just copy the data over */ 950 memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements); 951 Buffer += ulCellCount * psa->cbElements; 952 break; 953 default: 954 break; 955 } 956 } 957 958 } 959 return Buffer; 960 } 961 962 #define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \ 963 FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \ 964 FADF_VARIANT | FADF_CREATEVECTOR) 965 966 unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) 967 { 968 ULONG ptr; 969 wireSAFEARRAY wiresa; 970 ULONG cDims; 971 HRESULT hr; 972 SF_TYPE sftype; 973 ULONG cell_count; 974 GUID guid; 975 VARTYPE vt; 976 SAFEARRAYBOUND *wiresab; 977 978 TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa); 979 980 ALIGN_POINTER(Buffer, 3); 981 ptr = *(ULONG *)Buffer; 982 Buffer += sizeof(ULONG); 983 984 if (!ptr) 985 { 986 SafeArrayDestroy(*ppsa); 987 *ppsa = NULL; 988 989 TRACE("NULL safe array unmarshaled\n"); 990 991 return Buffer; 992 } 993 994 cDims = *(ULONG *)Buffer; 995 Buffer += sizeof(ULONG); 996 997 wiresa = (wireSAFEARRAY)Buffer; 998 Buffer += 2 * sizeof(USHORT) + 2 * sizeof(ULONG); 999 1000 if (cDims != wiresa->cDims) 1001 RpcRaiseException(RPC_S_INVALID_BOUND); 1002 1003 /* FIXME: there should be a limit on how large cDims can be */ 1004 1005 vt = HIWORD(wiresa->cLocks); 1006 1007 sftype = *(ULONG *)Buffer; 1008 Buffer += sizeof(ULONG); 1009 1010 cell_count = *(ULONG *)Buffer; 1011 Buffer += sizeof(ULONG); 1012 ptr = *(ULONG *)Buffer; 1013 Buffer += sizeof(ULONG); 1014 if (sftype == SF_HAVEIID) 1015 { 1016 memcpy(&guid, Buffer, sizeof(guid)); 1017 Buffer += sizeof(guid); 1018 } 1019 1020 wiresab = (SAFEARRAYBOUND *)Buffer; 1021 Buffer += sizeof(wiresab[0]) * wiresa->cDims; 1022 1023 if(*ppsa && (*ppsa)->cDims==wiresa->cDims) 1024 { 1025 if(((*ppsa)->fFeatures & ~FADF_AUTOSETFLAGS) != (wiresa->fFeatures & ~FADF_AUTOSETFLAGS)) 1026 RpcRaiseException(DISP_E_BADCALLEE); 1027 1028 if(SAFEARRAY_GetCellCount(*ppsa)*(*ppsa)->cbElements != cell_count*elem_mem_size(wiresa, sftype)) 1029 { 1030 if((*ppsa)->fFeatures & (FADF_AUTO|FADF_STATIC|FADF_EMBEDDED|FADF_FIXEDSIZE)) 1031 RpcRaiseException(DISP_E_BADCALLEE); 1032 1033 hr = SafeArrayDestroyData(*ppsa); 1034 if(FAILED(hr)) 1035 RpcRaiseException(hr); 1036 } 1037 memcpy((*ppsa)->rgsabound, wiresab, sizeof(*wiresab)*wiresa->cDims); 1038 1039 if((*ppsa)->fFeatures & FADF_HAVEVARTYPE) 1040 ((DWORD*)(*ppsa))[-1] = vt; 1041 } 1042 else if(vt) 1043 { 1044 SafeArrayDestroy(*ppsa); 1045 *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL); 1046 if (!*ppsa) RpcRaiseException(E_OUTOFMEMORY); 1047 } 1048 else 1049 { 1050 SafeArrayDestroy(*ppsa); 1051 if (FAILED(SafeArrayAllocDescriptor(wiresa->cDims, ppsa))) 1052 RpcRaiseException(E_OUTOFMEMORY); 1053 memcpy((*ppsa)->rgsabound, wiresab, sizeof(SAFEARRAYBOUND) * wiresa->cDims); 1054 } 1055 1056 /* be careful about which flags we set since they could be a security 1057 * risk */ 1058 (*ppsa)->fFeatures &= FADF_AUTOSETFLAGS; 1059 (*ppsa)->fFeatures |= (wiresa->fFeatures & ~(FADF_AUTOSETFLAGS)); 1060 /* FIXME: there should be a limit on how large wiresa->cbElements can be */ 1061 (*ppsa)->cbElements = elem_mem_size(wiresa, sftype); 1062 1063 /* SafeArrayCreateEx allocates the data for us, but 1064 * SafeArrayAllocDescriptor doesn't */ 1065 if(!(*ppsa)->pvData) 1066 { 1067 hr = SafeArrayAllocData(*ppsa); 1068 if (FAILED(hr)) 1069 RpcRaiseException(hr); 1070 } 1071 1072 if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count)) 1073 RpcRaiseException(RPC_S_INVALID_BOUND); 1074 Buffer += sizeof(ULONG); 1075 1076 if (ptr) 1077 { 1078 switch (sftype) 1079 { 1080 case SF_BSTR: 1081 { 1082 BSTR* lpBstr; 1083 1084 for (lpBstr = (*ppsa)->pvData; cell_count; cell_count--, lpBstr++) 1085 Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr); 1086 1087 break; 1088 } 1089 case SF_DISPATCH: 1090 case SF_UNKNOWN: 1091 case SF_HAVEIID: 1092 FIXME("marshal interfaces\n"); 1093 break; 1094 case SF_VARIANT: 1095 { 1096 VARIANT* lpVariant; 1097 1098 for (lpVariant = (*ppsa)->pvData; cell_count; cell_count--, lpVariant++) 1099 Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant); 1100 1101 break; 1102 } 1103 case SF_RECORD: 1104 { 1105 FIXME("set record info\n"); 1106 1107 break; 1108 } 1109 1110 case SF_I8: 1111 ALIGN_POINTER(Buffer, 7); 1112 /* fallthrough */ 1113 case SF_I1: 1114 case SF_I2: 1115 case SF_I4: 1116 /* Just copy the data over */ 1117 memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements); 1118 Buffer += cell_count * (*ppsa)->cbElements; 1119 break; 1120 default: 1121 break; 1122 } 1123 } 1124 1125 TRACE("safe array unmarshaled: %p\n", *ppsa); 1126 1127 return Buffer; 1128 } 1129 1130 void WINAPI LPSAFEARRAY_UserFree(ULONG *pFlags, LPSAFEARRAY *ppsa) 1131 { 1132 TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa); 1133 1134 SafeArrayDestroy(*ppsa); 1135 *ppsa = NULL; 1136 } 1137 1138 1139 ULONG WINAPI HFONT_UserSize(ULONG *pFlags, ULONG Start, HFONT *phfont) 1140 { 1141 FIXME(":stub\n"); 1142 return 0; 1143 } 1144 1145 unsigned char * WINAPI HFONT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont) 1146 { 1147 FIXME(":stub\n"); 1148 return NULL; 1149 } 1150 1151 unsigned char * WINAPI HFONT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont) 1152 { 1153 FIXME(":stub\n"); 1154 return NULL; 1155 } 1156 1157 void WINAPI HFONT_UserFree(ULONG *pFlags, HFONT *phfont) 1158 { 1159 FIXME(":stub\n"); 1160 return; 1161 } 1162 1163 1164 /* IDispatch */ 1165 /* exactly how Invoke is marshalled is not very clear to me yet, 1166 * but the way I've done it seems to work for me */ 1167 1168 HRESULT CALLBACK IDispatch_Invoke_Proxy( 1169 IDispatch* This, 1170 DISPID dispIdMember, 1171 REFIID riid, 1172 LCID lcid, 1173 WORD wFlags, 1174 DISPPARAMS* pDispParams, 1175 VARIANT* pVarResult, 1176 EXCEPINFO* pExcepInfo, 1177 UINT* puArgErr) 1178 { 1179 HRESULT hr; 1180 VARIANT VarResult; 1181 UINT* rgVarRefIdx = NULL; 1182 VARIANTARG* rgVarRef = NULL; 1183 UINT u, cVarRef; 1184 UINT uArgErr; 1185 EXCEPINFO ExcepInfo; 1186 1187 TRACE("(%p)->(%d,%s,%x,%x,%p,%p,%p,%p)\n", This, 1188 dispIdMember, debugstr_guid(riid), 1189 lcid, wFlags, pDispParams, pVarResult, 1190 pExcepInfo, puArgErr); 1191 1192 /* [out] args can't be null, use dummy vars if needed */ 1193 if (!pVarResult) pVarResult = &VarResult; 1194 if (!puArgErr) puArgErr = &uArgErr; 1195 if (!pExcepInfo) pExcepInfo = &ExcepInfo; 1196 1197 /* count by-ref args */ 1198 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) { 1199 VARIANTARG* arg = &pDispParams->rgvarg[u]; 1200 if (V_ISBYREF(arg)) { 1201 cVarRef++; 1202 } 1203 } 1204 if (cVarRef) { 1205 rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef); 1206 rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef); 1207 /* make list of by-ref args */ 1208 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) { 1209 VARIANTARG* arg = &pDispParams->rgvarg[u]; 1210 if (V_ISBYREF(arg)) { 1211 rgVarRefIdx[cVarRef] = u; 1212 VariantInit(&rgVarRef[cVarRef]); 1213 VariantCopy(&rgVarRef[cVarRef], arg); 1214 VariantClear(arg); 1215 cVarRef++; 1216 } 1217 } 1218 } else { 1219 /* [out] args still can't be null, 1220 * but we can point these anywhere in this case, 1221 * since they won't be written to when cVarRef is 0 */ 1222 rgVarRefIdx = puArgErr; 1223 rgVarRef = pVarResult; 1224 } 1225 TRACE("passed by ref: %d args\n", cVarRef); 1226 hr = IDispatch_RemoteInvoke_Proxy(This, 1227 dispIdMember, 1228 riid, 1229 lcid, 1230 wFlags, 1231 pDispParams, 1232 pVarResult, 1233 pExcepInfo, 1234 puArgErr, 1235 cVarRef, 1236 rgVarRefIdx, 1237 rgVarRef); 1238 if (cVarRef) { 1239 for (u=0; u<cVarRef; u++) { 1240 unsigned i = rgVarRefIdx[u]; 1241 VariantCopy(&pDispParams->rgvarg[i], 1242 &rgVarRef[u]); 1243 VariantClear(&rgVarRef[u]); 1244 } 1245 CoTaskMemFree(rgVarRef); 1246 CoTaskMemFree(rgVarRefIdx); 1247 } 1248 1249 if(pExcepInfo == &ExcepInfo) 1250 { 1251 SysFreeString(pExcepInfo->bstrSource); 1252 SysFreeString(pExcepInfo->bstrDescription); 1253 SysFreeString(pExcepInfo->bstrHelpFile); 1254 } 1255 return hr; 1256 } 1257 1258 HRESULT __RPC_STUB IDispatch_Invoke_Stub( 1259 IDispatch* This, 1260 DISPID dispIdMember, 1261 REFIID riid, 1262 LCID lcid, 1263 DWORD dwFlags, 1264 DISPPARAMS* pDispParams, 1265 VARIANT* pVarResult, 1266 EXCEPINFO* pExcepInfo, 1267 UINT* pArgErr, 1268 UINT cVarRef, 1269 UINT* rgVarRefIdx, 1270 VARIANTARG* rgVarRef) 1271 { 1272 HRESULT hr = S_OK; 1273 VARIANTARG *rgvarg, *arg; 1274 UINT u; 1275 1276 /* initialize out parameters, so that they can be marshalled 1277 * in case the real Invoke doesn't initialize them */ 1278 VariantInit(pVarResult); 1279 memset(pExcepInfo, 0, sizeof(*pExcepInfo)); 1280 *pArgErr = 0; 1281 1282 /* let the real Invoke operate on a copy of the in parameters, 1283 * so we don't risk losing pointers to allocated memory */ 1284 rgvarg = pDispParams->rgvarg; 1285 arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs); 1286 if (!arg) return E_OUTOFMEMORY; 1287 1288 /* init all args so we can call VariantClear on all the args if the copy 1289 * below fails */ 1290 for (u = 0; u < pDispParams->cArgs; u++) 1291 VariantInit(&arg[u]); 1292 1293 for (u = 0; u < pDispParams->cArgs; u++) { 1294 hr = VariantCopy(&arg[u], &rgvarg[u]); 1295 if (FAILED(hr)) 1296 break; 1297 } 1298 1299 if (SUCCEEDED(hr)) { 1300 /* copy ref args to arg array */ 1301 for (u=0; u<cVarRef; u++) { 1302 unsigned i = rgVarRefIdx[u]; 1303 VariantCopy(&arg[i], &rgVarRef[u]); 1304 } 1305 1306 pDispParams->rgvarg = arg; 1307 1308 hr = IDispatch_Invoke(This, 1309 dispIdMember, 1310 riid, 1311 lcid, 1312 dwFlags, 1313 pDispParams, 1314 pVarResult, 1315 pExcepInfo, 1316 pArgErr); 1317 1318 /* copy ref args from arg array */ 1319 for (u=0; u<cVarRef; u++) { 1320 unsigned i = rgVarRefIdx[u]; 1321 VariantCopy(&rgVarRef[u], &arg[i]); 1322 } 1323 } 1324 1325 /* clear the duplicate argument list */ 1326 for (u=0; u<pDispParams->cArgs; u++) 1327 VariantClear(&arg[u]); 1328 1329 pDispParams->rgvarg = rgvarg; 1330 CoTaskMemFree(arg); 1331 1332 return hr; 1333 } 1334 1335 /* IEnumVARIANT */ 1336 1337 HRESULT CALLBACK IEnumVARIANT_Next_Proxy( 1338 IEnumVARIANT* This, 1339 ULONG celt, 1340 VARIANT* rgVar, 1341 ULONG* pCeltFetched) 1342 { 1343 ULONG fetched; 1344 if (!pCeltFetched) 1345 pCeltFetched = &fetched; 1346 return IEnumVARIANT_RemoteNext_Proxy(This, 1347 celt, 1348 rgVar, 1349 pCeltFetched); 1350 } 1351 1352 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub( 1353 IEnumVARIANT* This, 1354 ULONG celt, 1355 VARIANT* rgVar, 1356 ULONG* pCeltFetched) 1357 { 1358 HRESULT hr; 1359 *pCeltFetched = 0; 1360 hr = IEnumVARIANT_Next(This, 1361 celt, 1362 rgVar, 1363 pCeltFetched); 1364 if (hr == S_OK) *pCeltFetched = celt; 1365 return hr; 1366 } 1367 1368 /* TypeInfo related freers */ 1369 1370 static void free_embedded_typedesc(TYPEDESC *tdesc); 1371 static void free_embedded_arraydesc(ARRAYDESC *adesc) 1372 { 1373 switch(adesc->tdescElem.vt) 1374 { 1375 case VT_PTR: 1376 case VT_SAFEARRAY: 1377 free_embedded_typedesc(adesc->tdescElem.u.lptdesc); 1378 CoTaskMemFree(adesc->tdescElem.u.lptdesc); 1379 break; 1380 case VT_CARRAY: 1381 free_embedded_arraydesc(adesc->tdescElem.u.lpadesc); 1382 CoTaskMemFree(adesc->tdescElem.u.lpadesc); 1383 break; 1384 } 1385 } 1386 1387 static void free_embedded_typedesc(TYPEDESC *tdesc) 1388 { 1389 switch(tdesc->vt) 1390 { 1391 case VT_PTR: 1392 case VT_SAFEARRAY: 1393 free_embedded_typedesc(tdesc->u.lptdesc); 1394 CoTaskMemFree(tdesc->u.lptdesc); 1395 break; 1396 case VT_CARRAY: 1397 free_embedded_arraydesc(tdesc->u.lpadesc); 1398 CoTaskMemFree(tdesc->u.lpadesc); 1399 break; 1400 } 1401 } 1402 1403 static void free_embedded_elemdesc(ELEMDESC *edesc) 1404 { 1405 free_embedded_typedesc(&edesc->tdesc); 1406 if(edesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 1407 CoTaskMemFree(edesc->u.paramdesc.pparamdescex); 1408 } 1409 1410 /* ITypeComp */ 1411 1412 HRESULT CALLBACK ITypeComp_Bind_Proxy( 1413 ITypeComp* This, 1414 LPOLESTR name, 1415 ULONG lHashVal, 1416 WORD flags, 1417 ITypeInfo **ti, 1418 DESCKIND *desckind, 1419 BINDPTR *bindptr) 1420 { 1421 CLEANLOCALSTORAGE stg = { 0 }; 1422 ITypeComp *typecomp; 1423 FUNCDESC *funcdesc; 1424 VARDESC *vardesc; 1425 HRESULT hr; 1426 1427 TRACE("(%p, %s, %#x, %#x, %p, %p, %p)\n", This, debugstr_w(name), lHashVal, flags, ti, 1428 desckind, bindptr); 1429 1430 *desckind = DESCKIND_NONE; 1431 memset(bindptr, 0, sizeof(*bindptr)); 1432 1433 hr = ITypeComp_RemoteBind_Proxy(This, name, lHashVal, flags, ti, desckind, 1434 &funcdesc, &vardesc, &typecomp, &stg); 1435 1436 if (hr == S_OK) 1437 { 1438 switch (*desckind) 1439 { 1440 case DESCKIND_FUNCDESC: 1441 bindptr->lpfuncdesc = funcdesc; 1442 break; 1443 case DESCKIND_VARDESC: 1444 case DESCKIND_IMPLICITAPPOBJ: 1445 bindptr->lpvardesc = vardesc; 1446 break; 1447 case DESCKIND_TYPECOMP: 1448 bindptr->lptcomp = typecomp; 1449 break; 1450 default: 1451 ; 1452 } 1453 } 1454 1455 return hr; 1456 } 1457 1458 HRESULT __RPC_STUB ITypeComp_Bind_Stub( 1459 ITypeComp* This, 1460 LPOLESTR name, 1461 ULONG lHashVal, 1462 WORD flags, 1463 ITypeInfo **ti, 1464 DESCKIND *desckind, 1465 FUNCDESC **funcdesc, 1466 VARDESC **vardesc, 1467 ITypeComp **typecomp, 1468 CLEANLOCALSTORAGE *stg) 1469 { 1470 BINDPTR bindptr; 1471 HRESULT hr; 1472 1473 TRACE("(%p, %s, %#x, %#x, %p, %p, %p, %p, %p, %p)\n", This, debugstr_w(name), 1474 lHashVal, flags, ti, desckind, funcdesc, vardesc, typecomp, stg); 1475 1476 memset(stg, 0, sizeof(*stg)); 1477 memset(&bindptr, 0, sizeof(bindptr)); 1478 1479 *funcdesc = NULL; 1480 *vardesc = NULL; 1481 *typecomp = NULL; 1482 *ti = NULL; 1483 1484 hr = ITypeComp_Bind(This, name, lHashVal, flags, ti, desckind, &bindptr); 1485 if(hr != S_OK) 1486 return hr; 1487 1488 switch (*desckind) 1489 { 1490 case DESCKIND_FUNCDESC: 1491 *funcdesc = bindptr.lpfuncdesc; 1492 stg->pInterface = (IUnknown*)*ti; 1493 stg->pStorage = funcdesc; 1494 stg->flags = CLS_FUNCDESC; 1495 break; 1496 case DESCKIND_VARDESC: 1497 case DESCKIND_IMPLICITAPPOBJ: 1498 *vardesc = bindptr.lpvardesc; 1499 stg->pInterface = (IUnknown*)*ti; 1500 stg->pStorage = vardesc; 1501 stg->flags = CLS_VARDESC; 1502 break; 1503 case DESCKIND_TYPECOMP: 1504 *typecomp = bindptr.lptcomp; 1505 break; 1506 default: 1507 ; 1508 } 1509 1510 if (stg->pInterface) 1511 IUnknown_AddRef(stg->pInterface); 1512 1513 return hr; 1514 } 1515 1516 HRESULT CALLBACK ITypeComp_BindType_Proxy( 1517 ITypeComp* This, 1518 LPOLESTR name, 1519 ULONG lHashVal, 1520 ITypeInfo **ti, 1521 ITypeComp **typecomp) 1522 { 1523 HRESULT hr; 1524 1525 TRACE("(%p, %s, %#x, %p, %p)\n", This, debugstr_w(name), lHashVal, ti, typecomp); 1526 1527 hr = ITypeComp_RemoteBindType_Proxy(This, name, lHashVal, ti); 1528 if (hr == S_OK) 1529 ITypeInfo_GetTypeComp(*ti, typecomp); 1530 else if (typecomp) 1531 *typecomp = NULL; 1532 1533 return hr; 1534 } 1535 1536 HRESULT __RPC_STUB ITypeComp_BindType_Stub( 1537 ITypeComp* This, 1538 LPOLESTR name, 1539 ULONG lHashVal, 1540 ITypeInfo **ti) 1541 { 1542 ITypeComp *typecomp = NULL; 1543 HRESULT hr; 1544 1545 TRACE("(%p, %s, %#x, %p)\n", This, debugstr_w(name), lHashVal, ti); 1546 1547 hr = ITypeComp_BindType(This, name, lHashVal, ti, &typecomp); 1548 1549 if (typecomp) 1550 ITypeComp_Release(typecomp); 1551 1552 return hr; 1553 } 1554 1555 /* ITypeInfo */ 1556 1557 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy( 1558 ITypeInfo* This, 1559 TYPEATTR** ppTypeAttr) 1560 1561 { 1562 CLEANLOCALSTORAGE stg; 1563 TRACE("(%p, %p)\n", This, ppTypeAttr); 1564 1565 stg.flags = 0; 1566 stg.pStorage = NULL; 1567 stg.pInterface = NULL; 1568 1569 return ITypeInfo_RemoteGetTypeAttr_Proxy(This, ppTypeAttr, &stg); 1570 } 1571 1572 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub( 1573 ITypeInfo* This, 1574 LPTYPEATTR* ppTypeAttr, 1575 CLEANLOCALSTORAGE* pDummy) 1576 { 1577 HRESULT hr; 1578 TRACE("(%p, %p)\n", This, ppTypeAttr); 1579 1580 hr = ITypeInfo_GetTypeAttr(This, ppTypeAttr); 1581 if(hr != S_OK) 1582 return hr; 1583 1584 pDummy->flags = CLS_TYPEATTR; 1585 ITypeInfo_AddRef(This); 1586 pDummy->pInterface = (IUnknown*)This; 1587 pDummy->pStorage = ppTypeAttr; 1588 return hr; 1589 } 1590 1591 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy( 1592 ITypeInfo* This, 1593 UINT index, 1594 FUNCDESC** ppFuncDesc) 1595 { 1596 CLEANLOCALSTORAGE stg; 1597 TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc); 1598 1599 stg.flags = 0; 1600 stg.pStorage = NULL; 1601 stg.pInterface = NULL; 1602 1603 return ITypeInfo_RemoteGetFuncDesc_Proxy(This, index, ppFuncDesc, &stg); 1604 } 1605 1606 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub( 1607 ITypeInfo* This, 1608 UINT index, 1609 LPFUNCDESC* ppFuncDesc, 1610 CLEANLOCALSTORAGE* pDummy) 1611 { 1612 HRESULT hr; 1613 TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc); 1614 1615 hr = ITypeInfo_GetFuncDesc(This, index, ppFuncDesc); 1616 if(hr != S_OK) 1617 return hr; 1618 1619 pDummy->flags = CLS_FUNCDESC; 1620 ITypeInfo_AddRef(This); 1621 pDummy->pInterface = (IUnknown*)This; 1622 pDummy->pStorage = ppFuncDesc; 1623 return hr; 1624 } 1625 1626 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy( 1627 ITypeInfo* This, 1628 UINT index, 1629 VARDESC** ppVarDesc) 1630 { 1631 CLEANLOCALSTORAGE stg; 1632 TRACE("(%p, %d, %p)\n", This, index, ppVarDesc); 1633 1634 stg.flags = 0; 1635 stg.pStorage = NULL; 1636 stg.pInterface = NULL; 1637 1638 return ITypeInfo_RemoteGetVarDesc_Proxy(This, index, ppVarDesc, &stg); 1639 } 1640 1641 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub( 1642 ITypeInfo* This, 1643 UINT index, 1644 LPVARDESC* ppVarDesc, 1645 CLEANLOCALSTORAGE* pDummy) 1646 { 1647 HRESULT hr; 1648 TRACE("(%p, %d, %p)\n", This, index, ppVarDesc); 1649 1650 hr = ITypeInfo_GetVarDesc(This, index, ppVarDesc); 1651 if(hr != S_OK) 1652 return hr; 1653 1654 pDummy->flags = CLS_VARDESC; 1655 ITypeInfo_AddRef(This); 1656 pDummy->pInterface = (IUnknown*)This; 1657 pDummy->pStorage = ppVarDesc; 1658 return hr; 1659 } 1660 1661 HRESULT CALLBACK ITypeInfo_GetNames_Proxy( 1662 ITypeInfo* This, 1663 MEMBERID memid, 1664 BSTR* rgBstrNames, 1665 UINT cMaxNames, 1666 UINT* pcNames) 1667 { 1668 TRACE("(%p, %08x, %p, %d, %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames); 1669 1670 return ITypeInfo_RemoteGetNames_Proxy(This, memid, rgBstrNames, cMaxNames, pcNames); 1671 } 1672 1673 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub( 1674 ITypeInfo* This, 1675 MEMBERID memid, 1676 BSTR* rgBstrNames, 1677 UINT cMaxNames, 1678 UINT* pcNames) 1679 { 1680 TRACE("(%p, %08x, %p, %d, %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames); 1681 1682 return ITypeInfo_GetNames(This, memid, rgBstrNames, cMaxNames, pcNames); 1683 } 1684 1685 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy( 1686 ITypeInfo* This, 1687 LPOLESTR* rgszNames, 1688 UINT cNames, 1689 MEMBERID* pMemId) 1690 { 1691 FIXME("not implemented\n"); 1692 return E_FAIL; 1693 } 1694 1695 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub( 1696 ITypeInfo* This) 1697 { 1698 FIXME("not implemented\n"); 1699 return E_FAIL; 1700 } 1701 1702 HRESULT CALLBACK ITypeInfo_Invoke_Proxy( 1703 ITypeInfo* This, 1704 PVOID pvInstance, 1705 MEMBERID memid, 1706 WORD wFlags, 1707 DISPPARAMS* pDispParams, 1708 VARIANT* pVarResult, 1709 EXCEPINFO* pExcepInfo, 1710 UINT* puArgErr) 1711 { 1712 FIXME("not implemented\n"); 1713 return E_FAIL; 1714 } 1715 1716 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub( 1717 ITypeInfo* This) 1718 { 1719 FIXME("not implemented\n"); 1720 return E_FAIL; 1721 } 1722 1723 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(ITypeInfo *This, MEMBERID memid, 1724 BSTR *name, BSTR *doc_string, 1725 DWORD *help_context, BSTR *help_file) 1726 { 1727 DWORD dummy_help_context, flags = 0; 1728 BSTR dummy_name, dummy_doc_string, dummy_help_file; 1729 HRESULT hr; 1730 TRACE("(%p, %08x, %p, %p, %p, %p)\n", This, memid, name, doc_string, help_context, help_file); 1731 1732 if(!name) name = &dummy_name; 1733 else flags = 1; 1734 1735 if(!doc_string) doc_string = &dummy_doc_string; 1736 else flags |= 2; 1737 1738 if(!help_context) help_context = &dummy_help_context; 1739 else flags |= 4; 1740 1741 if(!help_file) help_file = &dummy_help_file; 1742 else flags |= 8; 1743 1744 hr = ITypeInfo_RemoteGetDocumentation_Proxy(This, memid, flags, name, doc_string, help_context, help_file); 1745 1746 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ 1747 1748 return hr; 1749 } 1750 1751 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(ITypeInfo *This, MEMBERID memid, 1752 DWORD flags, BSTR *name, BSTR *doc_string, 1753 DWORD *help_context, BSTR *help_file) 1754 { 1755 TRACE("(%p, %08x, %08x, %p, %p, %p, %p)\n", This, memid, flags, name, doc_string, help_context, help_file); 1756 1757 *name = *doc_string = *help_file = NULL; 1758 *help_context = 0; 1759 1760 if(!(flags & 1)) name = NULL; 1761 if(!(flags & 2)) doc_string = NULL; 1762 if(!(flags & 4)) help_context = NULL; 1763 if(!(flags & 8)) help_file = NULL; 1764 1765 return ITypeInfo_GetDocumentation(This, memid, name, doc_string, help_context, help_file); 1766 } 1767 1768 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(ITypeInfo *This, MEMBERID memid, 1769 INVOKEKIND invkind, BSTR *dll_name, 1770 BSTR* name, WORD *ordinal) 1771 { 1772 DWORD flags = 0; 1773 BSTR dummy_dll_name, dummy_name; 1774 WORD dummy_ordinal; 1775 HRESULT hr; 1776 TRACE("(%p, %08x, %x, %p, %p, %p)\n", This, memid, invkind, dll_name, name, ordinal); 1777 1778 if(!dll_name) dll_name = &dummy_dll_name; 1779 else flags = 1; 1780 1781 if(!name) name = &dummy_name; 1782 else flags |= 2; 1783 1784 if(!ordinal) ordinal = &dummy_ordinal; 1785 else flags |= 4; 1786 1787 hr = ITypeInfo_RemoteGetDllEntry_Proxy(This, memid, invkind, flags, dll_name, name, ordinal); 1788 1789 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ 1790 1791 return hr; 1792 } 1793 1794 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(ITypeInfo *This, MEMBERID memid, 1795 INVOKEKIND invkind, DWORD flags, 1796 BSTR *dll_name, BSTR *name, 1797 WORD *ordinal) 1798 { 1799 TRACE("(%p, %08x, %x, %p, %p, %p)\n", This, memid, invkind, dll_name, name, ordinal); 1800 1801 *dll_name = *name = NULL; 1802 *ordinal = 0; 1803 1804 if(!(flags & 1)) dll_name = NULL; 1805 if(!(flags & 2)) name = NULL; 1806 if(!(flags & 4)) ordinal = NULL; 1807 1808 return ITypeInfo_GetDllEntry(This, memid, invkind, dll_name, name, ordinal); 1809 } 1810 1811 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy( 1812 ITypeInfo* This, 1813 MEMBERID memid, 1814 INVOKEKIND invKind, 1815 PVOID* ppv) 1816 { 1817 FIXME("not implemented\n"); 1818 return E_FAIL; 1819 } 1820 1821 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub( 1822 ITypeInfo* This) 1823 { 1824 FIXME("not implemented\n"); 1825 return E_FAIL; 1826 } 1827 1828 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy( 1829 ITypeInfo* This, 1830 IUnknown* pUnkOuter, 1831 REFIID riid, 1832 PVOID* ppvObj) 1833 { 1834 FIXME("not implemented\n"); 1835 return E_FAIL; 1836 } 1837 1838 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub( 1839 ITypeInfo* This, 1840 REFIID riid, 1841 IUnknown** ppvObj) 1842 { 1843 FIXME("not implemented\n"); 1844 return E_FAIL; 1845 } 1846 1847 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy( 1848 ITypeInfo* This, 1849 ITypeLib** ppTLib, 1850 UINT* pIndex) 1851 { 1852 ITypeLib *pTL; 1853 UINT index; 1854 HRESULT hr; 1855 1856 TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex ); 1857 1858 hr = ITypeInfo_RemoteGetContainingTypeLib_Proxy(This, &pTL, &index); 1859 if(SUCCEEDED(hr)) 1860 { 1861 if(pIndex) 1862 *pIndex = index; 1863 1864 if(ppTLib) 1865 *ppTLib = pTL; 1866 else 1867 ITypeLib_Release(pTL); 1868 } 1869 return hr; 1870 } 1871 1872 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub( 1873 ITypeInfo* This, 1874 ITypeLib** ppTLib, 1875 UINT* pIndex) 1876 { 1877 TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex ); 1878 return ITypeInfo_GetContainingTypeLib(This, ppTLib, pIndex); 1879 } 1880 1881 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy( 1882 ITypeInfo* This, 1883 TYPEATTR* pTypeAttr) 1884 { 1885 TRACE("(%p, %p)\n", This, pTypeAttr); 1886 free_embedded_typedesc(&pTypeAttr->tdescAlias); 1887 CoTaskMemFree(pTypeAttr); 1888 } 1889 1890 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub( 1891 ITypeInfo* This) 1892 { 1893 TRACE("nothing to do\n"); 1894 return S_OK; 1895 } 1896 1897 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy( 1898 ITypeInfo* This, 1899 FUNCDESC* pFuncDesc) 1900 { 1901 SHORT param; 1902 TRACE("(%p, %p)\n", This, pFuncDesc); 1903 1904 for(param = 0; param < pFuncDesc->cParams; param++) 1905 free_embedded_elemdesc(pFuncDesc->lprgelemdescParam + param); 1906 if(param) 1907 CoTaskMemFree(pFuncDesc->lprgelemdescParam); 1908 1909 free_embedded_elemdesc(&pFuncDesc->elemdescFunc); 1910 1911 if(pFuncDesc->cScodes != 0 && pFuncDesc->cScodes != -1) 1912 CoTaskMemFree(pFuncDesc->lprgscode); 1913 1914 CoTaskMemFree(pFuncDesc); 1915 } 1916 1917 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub( 1918 ITypeInfo* This) 1919 { 1920 TRACE("nothing to do\n"); 1921 return S_OK; 1922 } 1923 1924 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy( 1925 ITypeInfo* This, 1926 VARDESC* pVarDesc) 1927 { 1928 TRACE("(%p, %p)\n", This, pVarDesc); 1929 1930 CoTaskMemFree(pVarDesc->lpstrSchema); 1931 1932 if(pVarDesc->varkind == VAR_CONST) 1933 CoTaskMemFree(pVarDesc->u.lpvarValue); 1934 1935 free_embedded_elemdesc(&pVarDesc->elemdescVar); 1936 CoTaskMemFree(pVarDesc); 1937 } 1938 1939 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub( 1940 ITypeInfo* This) 1941 { 1942 TRACE("nothing to do\n"); 1943 return S_OK; 1944 } 1945 1946 1947 /* ITypeInfo2 */ 1948 1949 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(ITypeInfo2 *This, MEMBERID memid, 1950 LCID lcid, BSTR *help_string, 1951 DWORD *help_context, BSTR *help_dll) 1952 { 1953 DWORD dummy_help_context, flags = 0; 1954 BSTR dummy_help_string, dummy_help_dll; 1955 HRESULT hr; 1956 TRACE("(%p, %08x, %08x, %p, %p, %p)\n", This, memid, lcid, help_string, help_context, help_dll); 1957 1958 if(!help_string) help_string = &dummy_help_string; 1959 else flags = 1; 1960 1961 if(!help_context) help_context = &dummy_help_context; 1962 else flags |= 2; 1963 1964 if(!help_dll) help_dll = &dummy_help_dll; 1965 else flags |= 4; 1966 1967 hr = ITypeInfo2_RemoteGetDocumentation2_Proxy(This, memid, lcid, flags, help_string, help_context, help_dll); 1968 1969 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ 1970 1971 return hr; 1972 } 1973 1974 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(ITypeInfo2 *This, MEMBERID memid, 1975 LCID lcid, DWORD flags, 1976 BSTR *help_string, DWORD *help_context, 1977 BSTR *help_dll) 1978 { 1979 TRACE("(%p, %08x, %08x, %08x, %p, %p, %p)\n", This, memid, lcid, flags, help_string, help_context, help_dll); 1980 1981 *help_string = *help_dll = NULL; 1982 *help_context = 0; 1983 1984 if(!(flags & 1)) help_string = NULL; 1985 if(!(flags & 2)) help_context = NULL; 1986 if(!(flags & 4)) help_dll = NULL; 1987 1988 return ITypeInfo2_GetDocumentation2(This, memid, lcid, help_string, help_context, help_dll); 1989 } 1990 1991 /* ITypeLib */ 1992 1993 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy( 1994 ITypeLib* This) 1995 { 1996 UINT count = 0; 1997 TRACE("(%p)\n", This); 1998 1999 ITypeLib_RemoteGetTypeInfoCount_Proxy(This, &count); 2000 2001 return count; 2002 } 2003 2004 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub( 2005 ITypeLib* This, 2006 UINT* pcTInfo) 2007 { 2008 TRACE("(%p, %p)\n", This, pcTInfo); 2009 *pcTInfo = ITypeLib_GetTypeInfoCount(This); 2010 return S_OK; 2011 } 2012 2013 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy( 2014 ITypeLib* This, 2015 TLIBATTR** ppTLibAttr) 2016 { 2017 CLEANLOCALSTORAGE stg; 2018 TRACE("(%p, %p)\n", This, ppTLibAttr); 2019 2020 stg.flags = 0; 2021 stg.pStorage = NULL; 2022 stg.pInterface = NULL; 2023 2024 return ITypeLib_RemoteGetLibAttr_Proxy(This, ppTLibAttr, &stg); 2025 } 2026 2027 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub( 2028 ITypeLib* This, 2029 LPTLIBATTR* ppTLibAttr, 2030 CLEANLOCALSTORAGE* pDummy) 2031 { 2032 HRESULT hr; 2033 TRACE("(%p, %p)\n", This, ppTLibAttr); 2034 2035 hr = ITypeLib_GetLibAttr(This, ppTLibAttr); 2036 if(hr != S_OK) 2037 return hr; 2038 2039 pDummy->flags = CLS_LIBATTR; 2040 ITypeLib_AddRef(This); 2041 pDummy->pInterface = (IUnknown*)This; 2042 pDummy->pStorage = ppTLibAttr; 2043 return hr; 2044 } 2045 2046 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(ITypeLib *This, INT index, BSTR *name, 2047 BSTR *doc_string, DWORD *help_context, 2048 BSTR *help_file) 2049 { 2050 DWORD dummy_help_context, flags = 0; 2051 BSTR dummy_name, dummy_doc_string, dummy_help_file; 2052 HRESULT hr; 2053 TRACE("(%p, %d, %p, %p, %p, %p)\n", This, index, name, doc_string, help_context, help_file); 2054 2055 if(!name) name = &dummy_name; 2056 else flags = 1; 2057 2058 if(!doc_string) doc_string = &dummy_doc_string; 2059 else flags |= 2; 2060 2061 if(!help_context) help_context = &dummy_help_context; 2062 else flags |= 4; 2063 2064 if(!help_file) help_file = &dummy_help_file; 2065 else flags |= 8; 2066 2067 hr = ITypeLib_RemoteGetDocumentation_Proxy(This, index, flags, name, doc_string, help_context, help_file); 2068 2069 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ 2070 2071 return hr; 2072 } 2073 2074 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(ITypeLib *This, INT index, DWORD flags, 2075 BSTR *name, BSTR *doc_string, 2076 DWORD *help_context, BSTR *help_file) 2077 { 2078 TRACE("(%p, %d, %08x, %p, %p, %p, %p)\n", This, index, flags, name, doc_string, help_context, help_file); 2079 2080 *name = *doc_string = *help_file = NULL; 2081 *help_context = 0; 2082 2083 if(!(flags & 1)) name = NULL; 2084 if(!(flags & 2)) doc_string = NULL; 2085 if(!(flags & 4)) help_context = NULL; 2086 if(!(flags & 8)) help_file = NULL; 2087 2088 return ITypeLib_GetDocumentation(This, index, name, doc_string, help_context, help_file); 2089 } 2090 2091 HRESULT CALLBACK ITypeLib_IsName_Proxy( 2092 ITypeLib* This, 2093 LPOLESTR szNameBuf, 2094 ULONG lHashVal, 2095 BOOL* pfName) 2096 { 2097 FIXME("not implemented\n"); 2098 return E_FAIL; 2099 } 2100 2101 HRESULT __RPC_STUB ITypeLib_IsName_Stub( 2102 ITypeLib* This, 2103 LPOLESTR szNameBuf, 2104 ULONG lHashVal, 2105 BOOL* pfName, 2106 BSTR* pBstrLibName) 2107 { 2108 FIXME("not implemented\n"); 2109 return E_FAIL; 2110 } 2111 2112 HRESULT CALLBACK ITypeLib_FindName_Proxy( 2113 ITypeLib* This, 2114 LPOLESTR szNameBuf, 2115 ULONG lHashVal, 2116 ITypeInfo** ppTInfo, 2117 MEMBERID* rgMemId, 2118 USHORT* pcFound) 2119 { 2120 FIXME("not implemented\n"); 2121 return E_FAIL; 2122 } 2123 2124 HRESULT __RPC_STUB ITypeLib_FindName_Stub( 2125 ITypeLib* This, 2126 LPOLESTR szNameBuf, 2127 ULONG lHashVal, 2128 ITypeInfo** ppTInfo, 2129 MEMBERID* rgMemId, 2130 USHORT* pcFound, 2131 BSTR* pBstrLibName) 2132 { 2133 FIXME("not implemented\n"); 2134 return E_FAIL; 2135 } 2136 2137 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy( 2138 ITypeLib* This, 2139 TLIBATTR* pTLibAttr) 2140 { 2141 TRACE("(%p, %p)\n", This, pTLibAttr); 2142 CoTaskMemFree(pTLibAttr); 2143 } 2144 2145 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub( 2146 ITypeLib* This) 2147 { 2148 TRACE("nothing to do\n"); 2149 return S_OK; 2150 } 2151 2152 2153 /* ITypeLib2 */ 2154 2155 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy( 2156 ITypeLib2* This, 2157 ULONG* pcUniqueNames, 2158 ULONG* pcchUniqueNames) 2159 { 2160 FIXME("not implemented\n"); 2161 return E_FAIL; 2162 } 2163 2164 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub( 2165 ITypeLib2* This, 2166 ULONG* pcUniqueNames, 2167 ULONG* pcchUniqueNames) 2168 { 2169 FIXME("not implemented\n"); 2170 return E_FAIL; 2171 } 2172 2173 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(ITypeLib2 *This, INT index, 2174 LCID lcid, BSTR *help_string, 2175 DWORD *help_context, BSTR *help_dll) 2176 { 2177 DWORD dummy_help_context, flags = 0; 2178 BSTR dummy_help_string, dummy_help_dll; 2179 HRESULT hr; 2180 TRACE("(%p, %d, %08x, %p, %p, %p)\n", This, index, lcid, help_string, help_context, help_dll); 2181 2182 if(!help_string) help_string = &dummy_help_string; 2183 else flags = 1; 2184 2185 if(!help_context) help_context = &dummy_help_context; 2186 else flags |= 2; 2187 2188 if(!help_dll) help_dll = &dummy_help_dll; 2189 else flags |= 4; 2190 2191 hr = ITypeLib2_RemoteGetDocumentation2_Proxy(This, index, lcid, flags, help_string, help_context, help_dll); 2192 2193 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ 2194 2195 return hr; 2196 } 2197 2198 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(ITypeLib2 *This, INT index, LCID lcid, 2199 DWORD flags, BSTR *help_string, 2200 DWORD *help_context, BSTR *help_dll) 2201 { 2202 TRACE("(%p, %d, %08x, %08x, %p, %p, %p)\n", This, index, lcid, flags, help_string, help_context, help_dll); 2203 2204 *help_string = *help_dll = NULL; 2205 *help_context = 0; 2206 2207 if(!(flags & 1)) help_string = NULL; 2208 if(!(flags & 2)) help_context = NULL; 2209 if(!(flags & 4)) help_dll = NULL; 2210 2211 return ITypeLib2_GetDocumentation2(This, index, lcid, help_string, help_context, help_dll); 2212 } 2213 2214 HRESULT CALLBACK IPropertyBag_Read_Proxy( 2215 IPropertyBag* This, 2216 LPCOLESTR pszPropName, 2217 VARIANT *pVar, 2218 IErrorLog *pErrorLog) 2219 { 2220 IUnknown *pUnk = NULL; 2221 TRACE("(%p, %s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog); 2222 2223 if(!pVar) 2224 return E_POINTER; 2225 2226 if(V_VT(pVar) & (VT_BYREF | VT_ARRAY | VT_VECTOR)) 2227 { 2228 FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar)); 2229 return E_NOTIMPL; 2230 } 2231 2232 switch(V_VT(pVar)) 2233 { 2234 case VT_DISPATCH: 2235 pUnk = (IUnknown*)V_DISPATCH(pVar); 2236 break; 2237 case VT_UNKNOWN: 2238 pUnk = V_UNKNOWN(pVar); 2239 break; 2240 case VT_SAFEARRAY: 2241 FIXME("Safearray support not yet implemented.\n"); 2242 return E_NOTIMPL; 2243 default: 2244 FIXME("Unknown V_VT %d - support not yet implemented.\n", V_VT(pVar)); 2245 return E_NOTIMPL; 2246 } 2247 2248 return IPropertyBag_RemoteRead_Proxy(This, pszPropName, pVar, pErrorLog, 2249 V_VT(pVar), pUnk); 2250 } 2251 2252 HRESULT __RPC_STUB IPropertyBag_Read_Stub( 2253 IPropertyBag* This, 2254 LPCOLESTR pszPropName, 2255 VARIANT *pVar, 2256 IErrorLog *pErrorLog, 2257 DWORD varType, 2258 IUnknown *pUnkObj) 2259 { 2260 static const WCHAR emptyWstr[] = {0}; 2261 IDispatch *disp; 2262 HRESULT hr; 2263 TRACE("(%p, %s, %p, %p, %x, %p)\n", This, debugstr_w(pszPropName), pVar, 2264 pErrorLog, varType, pUnkObj); 2265 2266 if(varType & (VT_BYREF | VT_ARRAY | VT_VECTOR)) 2267 { 2268 FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar)); 2269 return E_NOTIMPL; 2270 } 2271 2272 V_VT(pVar) = varType; 2273 switch(varType) 2274 { 2275 case VT_DISPATCH: 2276 hr = IUnknown_QueryInterface(pUnkObj, &IID_IDispatch, (LPVOID*)&disp); 2277 if(FAILED(hr)) 2278 return hr; 2279 IUnknown_Release(pUnkObj); 2280 V_DISPATCH(pVar) = disp; 2281 break; 2282 case VT_UNKNOWN: 2283 V_UNKNOWN(pVar) = pUnkObj; 2284 break; 2285 case VT_BSTR: 2286 V_BSTR(pVar) = SysAllocString(emptyWstr); 2287 break; 2288 case VT_SAFEARRAY: 2289 FIXME("Safearray support not yet implemented.\n"); 2290 return E_NOTIMPL; 2291 default: 2292 break; 2293 } 2294 hr = IPropertyBag_Read(This, pszPropName, pVar, pErrorLog); 2295 if(FAILED(hr)) 2296 VariantClear(pVar); 2297 2298 return hr; 2299 } 2300 2301 /* call_as/local stubs for ocidl.idl */ 2302 2303 HRESULT CALLBACK IClassFactory2_CreateInstanceLic_Proxy( 2304 IClassFactory2* This, 2305 IUnknown *pUnkOuter, 2306 IUnknown *pUnkReserved, 2307 REFIID riid, 2308 BSTR bstrKey, 2309 PVOID *ppvObj) 2310 { 2311 TRACE("(%p, %s, %p)\n", pUnkOuter, debugstr_guid(riid), ppvObj); 2312 2313 *ppvObj = NULL; 2314 2315 if (pUnkOuter) 2316 { 2317 ERR("aggregation is not allowed on remote objects\n"); 2318 return CLASS_E_NOAGGREGATION; 2319 } 2320 2321 return IClassFactory2_RemoteCreateInstanceLic_Proxy(This, riid, bstrKey, (IUnknown**)ppvObj); 2322 } 2323 2324 HRESULT __RPC_STUB IClassFactory2_CreateInstanceLic_Stub( 2325 IClassFactory2* This, 2326 REFIID riid, 2327 BSTR bstrKey, 2328 IUnknown **ppvObj) 2329 { 2330 TRACE("(%s, %p)\n", debugstr_guid(riid), ppvObj); 2331 return IClassFactory2_CreateInstanceLic(This, NULL, NULL, riid, bstrKey, (void**)ppvObj); 2332 } 2333 2334 HRESULT CALLBACK IEnumConnections_Next_Proxy( 2335 IEnumConnections* This, 2336 ULONG cConnections, 2337 LPCONNECTDATA rgcd, 2338 ULONG *pcFetched) 2339 { 2340 ULONG fetched; 2341 2342 TRACE("(%u, %p %p)\n", cConnections, rgcd, pcFetched); 2343 2344 if (!pcFetched) 2345 pcFetched = &fetched; 2346 2347 return IEnumConnections_RemoteNext_Proxy(This, cConnections, rgcd, pcFetched); 2348 } 2349 2350 HRESULT __RPC_STUB IEnumConnections_Next_Stub( 2351 IEnumConnections* This, 2352 ULONG cConnections, 2353 LPCONNECTDATA rgcd, 2354 ULONG *pcFetched) 2355 { 2356 HRESULT hr; 2357 2358 TRACE("(%u, %p, %p)\n", cConnections, rgcd, pcFetched); 2359 2360 *pcFetched = 0; 2361 hr = IEnumConnections_Next(This, cConnections, rgcd, pcFetched); 2362 if (hr == S_OK) 2363 *pcFetched = cConnections; 2364 2365 return hr; 2366 } 2367 2368 HRESULT CALLBACK IEnumConnectionPoints_Next_Proxy( 2369 IEnumConnectionPoints* This, 2370 ULONG cConnections, 2371 IConnectionPoint **ppCP, 2372 ULONG *pcFetched) 2373 { 2374 ULONG fetched; 2375 2376 TRACE("(%u, %p %p)\n", cConnections, ppCP, pcFetched); 2377 2378 if (!pcFetched) 2379 pcFetched = &fetched; 2380 2381 return IEnumConnectionPoints_RemoteNext_Proxy(This, cConnections, ppCP, pcFetched); 2382 } 2383 2384 HRESULT __RPC_STUB IEnumConnectionPoints_Next_Stub( 2385 IEnumConnectionPoints* This, 2386 ULONG cConnections, 2387 IConnectionPoint **ppCP, 2388 ULONG *pcFetched) 2389 { 2390 HRESULT hr; 2391 2392 TRACE("(%u, %p, %p)\n", cConnections, ppCP, pcFetched); 2393 2394 *pcFetched = 0; 2395 hr = IEnumConnectionPoints_Next(This, cConnections, ppCP, pcFetched); 2396 if (hr == S_OK) 2397 *pcFetched = cConnections; 2398 2399 return hr; 2400 } 2401 2402 HRESULT CALLBACK IPersistMemory_Load_Proxy( 2403 IPersistMemory* This, 2404 LPVOID pMem, 2405 ULONG cbSize) 2406 { 2407 TRACE("(%p, %u)\n", pMem, cbSize); 2408 2409 if (!pMem) 2410 return E_POINTER; 2411 2412 return IPersistMemory_RemoteLoad_Proxy(This, pMem, cbSize); 2413 } 2414 2415 HRESULT __RPC_STUB IPersistMemory_Load_Stub( 2416 IPersistMemory* This, 2417 BYTE *pMem, 2418 ULONG cbSize) 2419 { 2420 TRACE("(%p, %u)\n", pMem, cbSize); 2421 return IPersistMemory_Load(This, pMem, cbSize); 2422 } 2423 2424 HRESULT CALLBACK IPersistMemory_Save_Proxy( 2425 IPersistMemory* This, 2426 LPVOID pMem, 2427 BOOL fClearDirty, 2428 ULONG cbSize) 2429 { 2430 TRACE("(%p, %d, %u)\n", pMem, fClearDirty, cbSize); 2431 2432 if (!pMem) 2433 return E_POINTER; 2434 2435 return IPersistMemory_RemoteSave_Proxy(This, pMem, fClearDirty, cbSize); 2436 } 2437 2438 HRESULT __RPC_STUB IPersistMemory_Save_Stub( 2439 IPersistMemory* This, 2440 BYTE *pMem, 2441 BOOL fClearDirty, 2442 ULONG cbSize) 2443 { 2444 TRACE("(%p, %d, %u)\n", pMem, fClearDirty, cbSize); 2445 return IPersistMemory_Save(This, pMem, fClearDirty, cbSize); 2446 } 2447 2448 void CALLBACK IAdviseSinkEx_OnViewStatusChange_Proxy( 2449 IAdviseSinkEx* This, 2450 DWORD dwViewStatus) 2451 { 2452 TRACE("(%p, 0x%08x)\n", This, dwViewStatus); 2453 IAdviseSinkEx_RemoteOnViewStatusChange_Proxy(This, dwViewStatus); 2454 } 2455 2456 HRESULT __RPC_STUB IAdviseSinkEx_OnViewStatusChange_Stub( 2457 IAdviseSinkEx* This, 2458 DWORD dwViewStatus) 2459 { 2460 TRACE("(%p, 0x%08x)\n", This, dwViewStatus); 2461 IAdviseSinkEx_OnViewStatusChange(This, dwViewStatus); 2462 return S_OK; 2463 } 2464 2465 HRESULT CALLBACK IEnumOleUndoUnits_Next_Proxy( 2466 IEnumOleUndoUnits* This, 2467 ULONG cElt, 2468 IOleUndoUnit **rgElt, 2469 ULONG *pcEltFetched) 2470 { 2471 ULONG fetched; 2472 2473 TRACE("(%u, %p %p)\n", cElt, rgElt, pcEltFetched); 2474 2475 if (!pcEltFetched) 2476 pcEltFetched = &fetched; 2477 2478 return IEnumOleUndoUnits_RemoteNext_Proxy(This, cElt, rgElt, pcEltFetched); 2479 } 2480 2481 HRESULT __RPC_STUB IEnumOleUndoUnits_Next_Stub( 2482 IEnumOleUndoUnits* This, 2483 ULONG cElt, 2484 IOleUndoUnit **rgElt, 2485 ULONG *pcEltFetched) 2486 { 2487 HRESULT hr; 2488 2489 TRACE("(%u, %p, %p)\n", cElt, rgElt, pcEltFetched); 2490 2491 *pcEltFetched = 0; 2492 hr = IEnumOleUndoUnits_Next(This, cElt, rgElt, pcEltFetched); 2493 if (hr == S_OK) 2494 *pcEltFetched = cElt; 2495 2496 return hr; 2497 } 2498 2499 HRESULT CALLBACK IQuickActivate_QuickActivate_Proxy( 2500 IQuickActivate* This, 2501 QACONTAINER *pQaContainer, 2502 QACONTROL *pQaControl) 2503 { 2504 FIXME("not implemented\n"); 2505 return E_NOTIMPL; 2506 } 2507 2508 HRESULT __RPC_STUB IQuickActivate_QuickActivate_Stub( 2509 IQuickActivate* This, 2510 QACONTAINER *pQaContainer, 2511 QACONTROL *pQaControl) 2512 { 2513 FIXME("not implemented\n"); 2514 return E_NOTIMPL; 2515 } 2516