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