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