kernelbase: Use nameless unions/structs for loader data.
[wine.git] / dlls / oleaut32 / usrmarshal.c
blob4a874a23413f7da1c1ea6461dabb440b158f799f
1 /*
2 * Misc marshalling routines
4 * Copyright 2002 Ove Kaaven
5 * Copyright 2003 Mike Hearn
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.
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.
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
22 #include <stdarg.h>
23 #include <string.h>
25 #define COBJMACROS
26 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winerror.h"
34 #include "ole2.h"
35 #include "oleauto.h"
36 #include "typelib.h"
37 #include "ocidl.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
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)
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);
52 static void dump_user_flags(const ULONG *pFlags)
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))
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));
68 /* CLEANLOCALSTORAGE */
70 #define CLS_FUNCDESC 'f'
71 #define CLS_LIBATTR 'l'
72 #define CLS_TYPEATTR 't'
73 #define CLS_VARDESC 'v'
75 ULONG WINAPI CLEANLOCALSTORAGE_UserSize(ULONG *pFlags, ULONG Start, CLEANLOCALSTORAGE *pstg)
77 ALIGN_LENGTH(Start, 3);
78 return Start + sizeof(DWORD);
81 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
83 ALIGN_POINTER(Buffer, 3);
84 *(DWORD*)Buffer = pstg->flags;
86 if (!pstg->pInterface)
87 return Buffer + sizeof(DWORD);
89 switch(pstg->flags)
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;
104 default:
105 ERR("Unknown type %lx\n", pstg->flags);
108 *(VOID**)pstg->pStorage = NULL;
109 IUnknown_Release(pstg->pInterface);
110 pstg->pInterface = NULL;
112 return Buffer + sizeof(DWORD);
115 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
117 ALIGN_POINTER(Buffer, 3);
118 pstr->flags = *(DWORD*)Buffer;
119 return Buffer + sizeof(DWORD);
122 void WINAPI CLEANLOCALSTORAGE_UserFree(ULONG *pFlags, CLEANLOCALSTORAGE *pstr)
124 /* Nothing to do */
127 /* BSTR */
129 typedef struct
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;
136 ULONG WINAPI BSTR_UserSize(ULONG *pFlags, ULONG Start, BSTR *pstr)
138 TRACE("%#lx, %lu, %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 %ld\n", Start);
143 return Start;
146 unsigned char * WINAPI BSTR_UserMarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
148 bstr_wire_t *header;
149 DWORD len = SysStringByteLen(*pstr);
151 TRACE("%#lx, %p, %p => %p\n", *pFlags, Buffer, pstr, *pstr);
152 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
154 ALIGN_POINTER(Buffer, 3);
155 header = (bstr_wire_t*)Buffer;
156 header->len = header->len2 = (len + 1) / 2;
157 if (*pstr)
159 header->byte_len = len;
160 memcpy(header + 1, *pstr, header->len * 2);
162 else
163 header->byte_len = 0xffffffff; /* special case for a null bstr */
165 return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
168 unsigned char * WINAPI BSTR_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
170 bstr_wire_t *header;
171 TRACE("%#lx, %p, %p => %p\n", *pFlags, Buffer, pstr, *pstr);
173 ALIGN_POINTER(Buffer, 3);
174 header = (bstr_wire_t*)Buffer;
175 if(header->len != header->len2)
176 FIXME("len %#lx != len2 %#lx\n", header->len, header->len2);
178 if (header->byte_len == 0xffffffff)
180 SysFreeString(*pstr);
181 *pstr = NULL;
183 else SysReAllocStringLen( pstr, (OLECHAR *)(header + 1), header->len );
185 if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
186 return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
189 void WINAPI BSTR_UserFree(ULONG *pFlags, BSTR *pstr)
191 TRACE("%#lx, %p => %p\n", *pFlags, pstr, *pstr);
192 SysFreeString(*pstr);
193 *pstr = NULL;
196 /* VARIANT */
198 typedef struct
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;
209 unsigned int get_type_size(ULONG *pFlags, VARTYPE vt)
211 if (vt & VT_ARRAY) return 4;
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;
261 static unsigned int get_type_alignment(ULONG *pFlags, VARTYPE vt)
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;
270 /* WdtpInterfacePointer_UserSize takes care of 2 additional DWORDs to store marshalling buffer size */
271 static unsigned interface_user_size(ULONG *pFlags, ULONG Start, REFIID riid, IUnknown *punk)
273 ULONG size = 0;
275 if (punk)
277 size = WdtpInterfacePointer_UserSize(pFlags, LOWORD(*pFlags), 0, punk, riid);
278 if (!size)
280 ERR("interface variant buffer size calculation failed\n");
281 return 0;
284 size += sizeof(ULONG);
285 TRACE("wire-size extra of interface variant is %ld.\n", size);
286 return Start + size;
289 static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
291 if (V_ISARRAY(pvar))
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));
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 interface_user_size(pFlags, Start, &IID_IUnknown, V_UNKNOWN(pvar));
308 case VT_UNKNOWN | VT_BYREF:
309 return interface_user_size(pFlags, Start, &IID_IUnknown, *V_UNKNOWNREF(pvar));
310 case VT_DISPATCH:
311 return interface_user_size(pFlags, Start, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
312 case VT_DISPATCH | VT_BYREF:
313 return interface_user_size(pFlags, Start, &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;
326 /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer */
327 static unsigned char* interface_user_marshal(ULONG *pFlags, unsigned char *Buffer,
328 REFIID riid, IUnknown *punk)
330 TRACE("%#lx, %p, %p.\n", *pFlags, Buffer, punk);
332 /* first DWORD is used to store pointer itself, truncated on win64 */
333 if(!punk)
335 memset(Buffer, 0, sizeof(ULONG));
336 return Buffer + sizeof(ULONG);
338 else
340 *(DWORD*)Buffer = (DWORD_PTR)punk;
341 Buffer += sizeof(DWORD);
344 return WdtpInterfacePointer_UserMarshal(pFlags, LOWORD(*pFlags), Buffer, punk, riid);
347 /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer */
348 static unsigned char *interface_user_unmarshal(ULONG *pFlags, unsigned char *Buffer,
349 REFIID riid, IUnknown **ppunk)
351 DWORD ptr;
353 TRACE("%#lx, %p, %p.\n", *pFlags, Buffer, ppunk);
355 /* skip pointer part itself */
356 ptr = *(DWORD*)Buffer;
357 Buffer += sizeof(DWORD);
359 if(!ptr)
360 return Buffer;
362 return WdtpInterfacePointer_UserUnmarshal(pFlags, Buffer, ppunk, riid);
365 ULONG WINAPI VARIANT_UserSize(ULONG *pFlags, ULONG Start, VARIANT *pvar)
367 int align;
368 TRACE("%#lx, %lu, %p.\n", *pFlags, Start, pvar);
369 TRACE("vt=%04x\n", V_VT(pvar));
371 ALIGN_LENGTH(Start, 7);
372 Start += sizeof(variant_wire_t);
373 if(V_VT(pvar) & VT_BYREF)
374 Start += 4;
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);
384 TRACE("returning %ld\n", Start);
385 return Start;
388 unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
390 variant_wire_t *header;
391 ULONG type_size;
392 int align;
393 unsigned char *Pos;
395 TRACE("%#lx, %p, %p.\n", *pFlags, Buffer, pvar);
396 TRACE("vt=%04x\n", V_VT(pvar));
398 ALIGN_POINTER(Buffer, 7);
400 header = (variant_wire_t *)Buffer;
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;
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);
417 if(header->vt & VT_BYREF)
419 *(DWORD *)Pos = max(type_size, 4);
420 Pos += 4;
421 if((header->vt & VT_TYPEMASK) != VT_VARIANT)
423 memcpy(Pos, pvar->n1.n2.n3.byref, type_size);
424 Pos += type_size;
426 else
428 *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24;
429 Pos += 4;
432 else
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;
441 if(header->vt & VT_ARRAY)
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));
448 else
450 switch (header->vt)
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_user_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar));
463 break;
464 case VT_UNKNOWN | VT_BYREF:
465 Pos = interface_user_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar));
466 break;
467 case VT_DISPATCH:
468 Pos = interface_user_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
469 break;
470 case VT_DISPATCH | VT_BYREF:
471 Pos = interface_user_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;
481 header->clSize = ((Pos - Buffer) + 7) >> 3;
482 TRACE("marshalled size %ld\n", header->clSize);
483 return Pos;
486 unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
488 variant_wire_t *header;
489 ULONG type_size;
490 int align;
491 unsigned char *Pos;
493 TRACE("%#lx, %p, %p.\n", *pFlags, Buffer, pvar);
495 ALIGN_POINTER(Buffer, 7);
497 header = (variant_wire_t *)Buffer;
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);
504 if(header->vt & VT_BYREF)
506 ULONG mem_size;
507 Pos += 4;
509 /* byref array needs to allocate a SAFEARRAY pointer */
510 if (header->vt & VT_ARRAY)
511 mem_size = sizeof(void *);
512 else switch (header->vt & ~VT_BYREF)
514 /* these types have a different memory size compared to wire size */
515 case VT_UNKNOWN:
516 case VT_DISPATCH:
517 case VT_BSTR:
518 mem_size = sizeof(void *);
519 break;
520 default:
521 mem_size = type_size;
522 break;
525 if (V_VT(pvar) != header->vt)
527 VariantClear(pvar);
528 V_BYREF(pvar) = CoTaskMemAlloc(mem_size);
529 memset(V_BYREF(pvar), 0, mem_size);
531 else if (!V_BYREF(pvar))
533 V_BYREF(pvar) = CoTaskMemAlloc(mem_size);
534 memset(V_BYREF(pvar), 0, mem_size);
537 if(!(header->vt & VT_ARRAY)
538 && (header->vt & VT_TYPEMASK) != VT_BSTR
539 && (header->vt & VT_TYPEMASK) != VT_VARIANT
540 && (header->vt & VT_TYPEMASK) != VT_UNKNOWN
541 && (header->vt & VT_TYPEMASK) != VT_DISPATCH
542 && (header->vt & VT_TYPEMASK) != VT_RECORD)
543 memcpy(V_BYREF(pvar), Pos, type_size);
545 if((header->vt & VT_TYPEMASK) != VT_VARIANT)
546 Pos += type_size;
547 else
548 Pos += 4;
550 else
552 VariantClear(pvar);
553 if(header->vt & VT_ARRAY)
554 V_ARRAY(pvar) = NULL;
555 else if((header->vt & VT_TYPEMASK) == VT_BSTR)
556 V_BSTR(pvar) = NULL;
557 else if((header->vt & VT_TYPEMASK) == VT_UNKNOWN)
558 V_UNKNOWN(pvar) = NULL;
559 else if((header->vt & VT_TYPEMASK) == VT_DISPATCH)
560 V_DISPATCH(pvar) = NULL;
561 else if((header->vt & VT_TYPEMASK) == VT_RECORD)
562 V_RECORD(pvar) = NULL;
563 else if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
564 memcpy(pvar, Pos, type_size);
565 else
566 memcpy(&pvar->n1.n2.n3, Pos, type_size);
567 Pos += type_size;
570 pvar->n1.n2.vt = header->vt;
571 pvar->n1.n2.wReserved1 = header->wReserved1;
572 pvar->n1.n2.wReserved2 = header->wReserved2;
573 pvar->n1.n2.wReserved3 = header->wReserved3;
575 if(header->vt & VT_ARRAY)
577 if(header->vt & VT_BYREF)
578 Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar));
579 else
580 Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar));
582 else
584 switch (header->vt)
586 case VT_BSTR:
587 Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
588 break;
589 case VT_BSTR | VT_BYREF:
590 Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
591 break;
592 case VT_VARIANT | VT_BYREF:
593 Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
594 break;
595 case VT_UNKNOWN:
596 Pos = interface_user_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar));
597 break;
598 case VT_UNKNOWN | VT_BYREF:
599 Pos = interface_user_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar));
600 break;
601 case VT_DISPATCH:
602 Pos = interface_user_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar));
603 break;
604 case VT_DISPATCH | VT_BYREF:
605 Pos = interface_user_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar));
606 break;
607 case VT_RECORD:
608 FIXME("handle BRECORD by val\n");
609 break;
610 case VT_RECORD | VT_BYREF:
611 FIXME("handle BRECORD by ref\n");
612 break;
615 return Pos;
618 void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar)
620 VARTYPE vt = V_VT(pvar);
621 PVOID ref = NULL;
623 TRACE("%#lx, %p.\n", *pFlags, pvar);
624 TRACE("vt=%04x\n", V_VT(pvar));
626 if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
628 VariantClear(pvar);
629 if (!ref) return;
631 if(vt & VT_ARRAY)
633 if (vt & VT_BYREF)
634 LPSAFEARRAY_UserFree(pFlags, V_ARRAYREF(pvar));
635 else
636 LPSAFEARRAY_UserFree(pFlags, &V_ARRAY(pvar));
638 else
640 switch (vt)
642 case VT_BSTR | VT_BYREF:
643 BSTR_UserFree(pFlags, V_BSTRREF(pvar));
644 break;
645 case VT_VARIANT | VT_BYREF:
646 VARIANT_UserFree(pFlags, V_VARIANTREF(pvar));
647 break;
648 case VT_RECORD | VT_BYREF:
649 FIXME("handle BRECORD by ref\n");
650 break;
651 case VT_UNKNOWN | VT_BYREF:
652 case VT_DISPATCH | VT_BYREF:
653 if (*V_UNKNOWNREF(pvar))
654 IUnknown_Release(*V_UNKNOWNREF(pvar));
655 break;
659 CoTaskMemFree(ref);
662 /* LPSAFEARRAY */
664 /* Get the number of cells in a SafeArray */
665 static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
667 const SAFEARRAYBOUND* psab = psa->rgsabound;
668 USHORT cCount = psa->cDims;
669 ULONG ulNumCells = 1;
671 while (cCount--)
673 /* This is a valid bordercase. See testcases. -Marcus */
674 if (!psab->cElements)
675 return 0;
676 ulNumCells *= psab->cElements;
677 psab++;
679 return ulNumCells;
682 static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
684 VARTYPE vt;
685 HRESULT hr;
687 hr = SafeArrayGetVartype(psa, &vt);
688 if (FAILED(hr))
690 if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
692 switch(psa->cbElements)
694 case 1: vt = VT_I1; break;
695 case 2: vt = VT_I2; break;
696 case 4: vt = VT_I4; break;
697 case 8: vt = VT_I8; break;
698 default:
699 RpcRaiseException(hr);
703 if (psa->fFeatures & FADF_HAVEIID)
704 return SF_HAVEIID;
706 switch (vt)
708 case VT_I1:
709 case VT_UI1: return SF_I1;
710 case VT_BOOL:
711 case VT_I2:
712 case VT_UI2: return SF_I2;
713 case VT_INT:
714 case VT_UINT:
715 case VT_I4:
716 case VT_UI4:
717 case VT_R4: return SF_I4;
718 case VT_DATE:
719 case VT_CY:
720 case VT_R8:
721 case VT_I8:
722 case VT_UI8: return SF_I8;
723 case VT_INT_PTR:
724 case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
725 case VT_BSTR: return SF_BSTR;
726 case VT_DISPATCH: return SF_DISPATCH;
727 case VT_VARIANT: return SF_VARIANT;
728 case VT_UNKNOWN: return SF_UNKNOWN;
729 /* Note: Return a non-zero size to indicate vt is valid. The actual size
730 * of a UDT is taken from the result of IRecordInfo_GetSize().
732 case VT_RECORD: return SF_RECORD;
733 default: return SF_ERROR;
737 static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
739 switch (sftype)
741 case SF_BSTR:
742 case SF_HAVEIID:
743 case SF_UNKNOWN:
744 case SF_DISPATCH:
745 return sizeof(DWORD);
747 case SF_VARIANT:
748 return sizeof(variant_wire_t) - sizeof(DWORD);
750 default:
751 return lpsa->cbElements;
755 static DWORD elem_mem_size(wireSAFEARRAY wiresa, SF_TYPE sftype)
757 switch (sftype)
759 case SF_HAVEIID:
760 case SF_UNKNOWN:
761 case SF_DISPATCH:
762 return sizeof(void *);
764 case SF_BSTR:
765 return sizeof(BSTR);
767 case SF_VARIANT:
768 return sizeof(VARIANT);
770 default:
771 return wiresa->cbElements;
775 ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa)
777 ULONG size = StartingSize;
779 TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, *ppsa);
781 ALIGN_LENGTH(size, 3);
782 size += sizeof(ULONG);
783 if (*ppsa)
785 SAFEARRAY *psa = *ppsa;
786 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
787 SF_TYPE sftype;
788 HRESULT hr;
790 size += sizeof(ULONG);
791 size += 2 * sizeof(USHORT) + 2 * sizeof(ULONG);
793 sftype = SAFEARRAY_GetUnionType(psa);
794 size += sizeof(ULONG);
796 size += sizeof(ULONG);
797 size += sizeof(ULONG);
798 if (sftype == SF_HAVEIID)
799 size += sizeof(IID);
801 size += sizeof(psa->rgsabound[0]) * psa->cDims;
803 size += sizeof(ULONG);
805 switch (sftype)
807 case SF_BSTR:
809 BSTR* lpBstr;
811 for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
812 size = BSTR_UserSize(pFlags, size, lpBstr);
814 break;
816 case SF_DISPATCH:
817 case SF_UNKNOWN:
818 case SF_HAVEIID:
820 IUnknown **lpUnk;
821 GUID guid;
823 if (sftype == SF_HAVEIID)
824 SafeArrayGetIID(psa, &guid);
825 else if (sftype == SF_UNKNOWN)
826 guid = IID_IUnknown;
827 else
828 guid = IID_IDispatch;
830 for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++)
831 size = interface_user_size(pFlags, size, &guid, *lpUnk);
833 break;
835 case SF_VARIANT:
837 VARIANT* lpVariant;
839 for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
840 size = VARIANT_UserSize(pFlags, size, lpVariant);
842 break;
844 case SF_RECORD:
846 IRecordInfo* pRecInfo = NULL;
848 hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
849 if (FAILED(hr))
850 RpcRaiseException(hr);
852 if (pRecInfo)
854 FIXME("size record info %p\n", pRecInfo);
856 IRecordInfo_Release(pRecInfo);
858 break;
860 case SF_I8:
861 ALIGN_LENGTH(size, 7);
862 /* fallthrough */
863 case SF_I1:
864 case SF_I2:
865 case SF_I4:
866 size += ulCellCount * psa->cbElements;
867 break;
868 default:
869 break;
874 return size;
877 unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
879 HRESULT hr;
881 TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa);
883 ALIGN_POINTER(Buffer, 3);
884 *(ULONG *)Buffer = *ppsa ? 0x1 : 0x0;
885 Buffer += sizeof(ULONG);
886 if (*ppsa)
888 VARTYPE vt;
889 SAFEARRAY *psa = *ppsa;
890 ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
891 SAFEARRAYBOUND *bound;
892 SF_TYPE sftype;
893 GUID guid;
894 INT i;
896 sftype = SAFEARRAY_GetUnionType(psa);
898 *(ULONG *)Buffer = psa->cDims;
899 Buffer += sizeof(ULONG);
900 *(USHORT *)Buffer = psa->cDims;
901 Buffer += sizeof(USHORT);
902 *(USHORT *)Buffer = psa->fFeatures;
903 Buffer += sizeof(USHORT);
904 *(ULONG *)Buffer = elem_wire_size(psa, sftype);
905 Buffer += sizeof(ULONG);
907 hr = SafeArrayGetVartype(psa, &vt);
908 if ((psa->fFeatures & FADF_HAVEIID) || FAILED(hr)) vt = 0;
910 *(ULONG *)Buffer = (USHORT)psa->cLocks | (vt << 16);
911 Buffer += sizeof(ULONG);
913 *(ULONG *)Buffer = sftype;
914 Buffer += sizeof(ULONG);
916 *(ULONG *)Buffer = ulCellCount;
917 Buffer += sizeof(ULONG);
918 *(ULONG *)Buffer = psa->pvData ? 0x2 : 0x0;
919 Buffer += sizeof(ULONG);
920 if (sftype == SF_HAVEIID)
922 SafeArrayGetIID(psa, &guid);
923 memcpy(Buffer, &guid, sizeof(guid));
924 Buffer += sizeof(guid);
927 /* bounds are marshaled in opposite order comparing to storage layout */
928 bound = (SAFEARRAYBOUND*)Buffer;
929 for (i = 0; i < psa->cDims; i++)
931 memcpy(bound++, &psa->rgsabound[psa->cDims-i-1], sizeof(psa->rgsabound[0]));
933 Buffer += sizeof(psa->rgsabound[0]) * psa->cDims;
935 *(ULONG *)Buffer = ulCellCount;
936 Buffer += sizeof(ULONG);
938 if (psa->pvData)
940 switch (sftype)
942 case SF_BSTR:
944 BSTR* lpBstr;
946 for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
947 Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr);
949 break;
951 case SF_DISPATCH:
952 case SF_UNKNOWN:
953 case SF_HAVEIID:
955 IUnknown **lpUnk;
956 const GUID *iid;
958 if (sftype == SF_HAVEIID)
959 iid = &guid;
960 else if (sftype == SF_UNKNOWN)
961 iid = &IID_IUnknown;
962 else
963 iid = &IID_IDispatch;
965 for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++)
966 Buffer = interface_user_marshal(pFlags, Buffer, iid, *lpUnk);
968 break;
970 case SF_VARIANT:
972 VARIANT* lpVariant;
974 for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
975 Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant);
977 break;
979 case SF_RECORD:
981 IRecordInfo* pRecInfo = NULL;
983 hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
984 if (FAILED(hr))
985 RpcRaiseException(hr);
987 if (pRecInfo)
989 FIXME("write record info %p\n", pRecInfo);
991 IRecordInfo_Release(pRecInfo);
993 break;
996 case SF_I8:
997 ALIGN_POINTER(Buffer, 7);
998 /* fallthrough */
999 case SF_I1:
1000 case SF_I2:
1001 case SF_I4:
1002 /* Just copy the data over */
1003 memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements);
1004 Buffer += ulCellCount * psa->cbElements;
1005 break;
1006 default:
1007 break;
1012 return Buffer;
1015 #define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \
1016 FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \
1017 FADF_VARIANT | FADF_CREATEVECTOR)
1019 unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
1021 ULONG ptr;
1022 wireSAFEARRAY wiresa;
1023 ULONG cDims;
1024 HRESULT hr;
1025 SF_TYPE sftype;
1026 ULONG cell_count;
1027 GUID guid;
1028 VARTYPE vt;
1029 SAFEARRAYBOUND *wiresab;
1031 TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa);
1033 ALIGN_POINTER(Buffer, 3);
1034 ptr = *(ULONG *)Buffer;
1035 Buffer += sizeof(ULONG);
1037 if (!ptr)
1039 SafeArrayDestroy(*ppsa);
1040 *ppsa = NULL;
1042 TRACE("NULL safe array unmarshaled\n");
1044 return Buffer;
1047 cDims = *(ULONG *)Buffer;
1048 Buffer += sizeof(ULONG);
1050 wiresa = (wireSAFEARRAY)Buffer;
1051 Buffer += 2 * sizeof(USHORT) + 2 * sizeof(ULONG);
1053 if (cDims != wiresa->cDims)
1054 RpcRaiseException(RPC_S_INVALID_BOUND);
1056 /* FIXME: there should be a limit on how large cDims can be */
1058 vt = HIWORD(wiresa->cLocks);
1060 sftype = *(ULONG *)Buffer;
1061 Buffer += sizeof(ULONG);
1063 cell_count = *(ULONG *)Buffer;
1064 Buffer += sizeof(ULONG);
1065 ptr = *(ULONG *)Buffer;
1066 Buffer += sizeof(ULONG);
1067 if (sftype == SF_HAVEIID)
1069 memcpy(&guid, Buffer, sizeof(guid));
1070 Buffer += sizeof(guid);
1073 wiresab = (SAFEARRAYBOUND *)Buffer;
1074 Buffer += sizeof(wiresab[0]) * wiresa->cDims;
1076 if(*ppsa && (*ppsa)->cDims==wiresa->cDims)
1078 if(((*ppsa)->fFeatures & ~FADF_AUTOSETFLAGS) != (wiresa->fFeatures & ~FADF_AUTOSETFLAGS))
1079 RpcRaiseException(DISP_E_BADCALLEE);
1081 if(SAFEARRAY_GetCellCount(*ppsa)*(*ppsa)->cbElements != cell_count*elem_mem_size(wiresa, sftype))
1083 if((*ppsa)->fFeatures & (FADF_AUTO|FADF_STATIC|FADF_EMBEDDED|FADF_FIXEDSIZE))
1084 RpcRaiseException(DISP_E_BADCALLEE);
1086 hr = SafeArrayDestroyData(*ppsa);
1087 if(FAILED(hr))
1088 RpcRaiseException(hr);
1090 memcpy((*ppsa)->rgsabound, wiresab, sizeof(*wiresab)*wiresa->cDims);
1092 if((*ppsa)->fFeatures & FADF_HAVEVARTYPE)
1093 ((DWORD*)(*ppsa))[-1] = vt;
1095 else if(vt)
1097 SafeArrayDestroy(*ppsa);
1098 *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL);
1099 if (!*ppsa) RpcRaiseException(E_OUTOFMEMORY);
1101 else
1103 SafeArrayDestroy(*ppsa);
1104 if (FAILED(SafeArrayAllocDescriptor(wiresa->cDims, ppsa)))
1105 RpcRaiseException(E_OUTOFMEMORY);
1106 memcpy((*ppsa)->rgsabound, wiresab, sizeof(SAFEARRAYBOUND) * wiresa->cDims);
1109 /* be careful about which flags we set since they could be a security
1110 * risk */
1111 (*ppsa)->fFeatures &= FADF_AUTOSETFLAGS;
1112 (*ppsa)->fFeatures |= (wiresa->fFeatures & ~(FADF_AUTOSETFLAGS));
1113 /* FIXME: there should be a limit on how large wiresa->cbElements can be */
1114 (*ppsa)->cbElements = elem_mem_size(wiresa, sftype);
1116 /* SafeArrayCreateEx allocates the data for us, but
1117 * SafeArrayAllocDescriptor doesn't */
1118 if(!(*ppsa)->pvData)
1120 hr = SafeArrayAllocData(*ppsa);
1121 if (FAILED(hr))
1122 RpcRaiseException(hr);
1125 if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count))
1126 RpcRaiseException(RPC_S_INVALID_BOUND);
1127 Buffer += sizeof(ULONG);
1129 if (ptr)
1131 switch (sftype)
1133 case SF_BSTR:
1135 BSTR* lpBstr;
1137 for (lpBstr = (*ppsa)->pvData; cell_count; cell_count--, lpBstr++)
1138 Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr);
1140 break;
1142 case SF_DISPATCH:
1143 case SF_UNKNOWN:
1144 case SF_HAVEIID:
1146 IUnknown **lpUnk;
1147 const GUID *iid;
1149 if (sftype == SF_HAVEIID)
1150 iid = &guid;
1151 else if (sftype == SF_UNKNOWN)
1152 iid = &IID_IUnknown;
1153 else
1154 iid = &IID_IDispatch;
1156 for (lpUnk = (*ppsa)->pvData; cell_count; cell_count--, lpUnk++)
1157 Buffer = interface_user_unmarshal(pFlags, Buffer, iid, lpUnk);
1159 break;
1161 case SF_VARIANT:
1163 VARIANT* lpVariant;
1165 for (lpVariant = (*ppsa)->pvData; cell_count; cell_count--, lpVariant++)
1166 Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant);
1168 break;
1170 case SF_RECORD:
1172 FIXME("set record info\n");
1174 break;
1177 case SF_I8:
1178 ALIGN_POINTER(Buffer, 7);
1179 /* fallthrough */
1180 case SF_I1:
1181 case SF_I2:
1182 case SF_I4:
1183 /* Just copy the data over */
1184 memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements);
1185 Buffer += cell_count * (*ppsa)->cbElements;
1186 break;
1187 default:
1188 break;
1192 TRACE("safe array unmarshaled: %p\n", *ppsa);
1194 return Buffer;
1197 void WINAPI LPSAFEARRAY_UserFree(ULONG *pFlags, LPSAFEARRAY *ppsa)
1199 TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa);
1201 SafeArrayDestroy(*ppsa);
1202 *ppsa = NULL;
1206 ULONG WINAPI HFONT_UserSize(ULONG *pFlags, ULONG Start, HFONT *phfont)
1208 FIXME(":stub\n");
1209 return 0;
1212 unsigned char * WINAPI HFONT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont)
1214 FIXME(":stub\n");
1215 return NULL;
1218 unsigned char * WINAPI HFONT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont)
1220 FIXME(":stub\n");
1221 return NULL;
1224 void WINAPI HFONT_UserFree(ULONG *pFlags, HFONT *phfont)
1226 FIXME(":stub\n");
1227 return;
1231 /* IDispatch */
1232 /* exactly how Invoke is marshalled is not very clear to me yet,
1233 * but the way I've done it seems to work for me */
1235 HRESULT CALLBACK IDispatch_Invoke_Proxy(
1236 IDispatch* This,
1237 DISPID dispIdMember,
1238 REFIID riid,
1239 LCID lcid,
1240 WORD wFlags,
1241 DISPPARAMS* pDispParams,
1242 VARIANT* pVarResult,
1243 EXCEPINFO* pExcepInfo,
1244 UINT* puArgErr)
1246 HRESULT hr;
1247 VARIANT VarResult;
1248 UINT* rgVarRefIdx = NULL;
1249 VARIANTARG* rgVarRef = NULL;
1250 UINT u, cVarRef;
1251 UINT uArgErr;
1252 EXCEPINFO ExcepInfo;
1254 TRACE("%p, %ld, %s, %#lx, %x, %p, %p, %p, %p.\n", This,
1255 dispIdMember, debugstr_guid(riid),
1256 lcid, wFlags, pDispParams, pVarResult,
1257 pExcepInfo, puArgErr);
1259 /* [out] args can't be null, use dummy vars if needed */
1260 if (!pVarResult) pVarResult = &VarResult;
1261 if (!puArgErr) puArgErr = &uArgErr;
1262 if (!pExcepInfo) pExcepInfo = &ExcepInfo;
1264 /* count by-ref args */
1265 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
1266 VARIANTARG* arg = &pDispParams->rgvarg[u];
1267 if (V_ISBYREF(arg)) {
1268 cVarRef++;
1271 if (cVarRef) {
1272 rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
1273 rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
1274 /* make list of by-ref args */
1275 for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
1276 VARIANTARG* arg = &pDispParams->rgvarg[u];
1277 if (V_ISBYREF(arg)) {
1278 rgVarRefIdx[cVarRef] = u;
1279 VariantInit(&rgVarRef[cVarRef]);
1280 VariantCopy(&rgVarRef[cVarRef], arg);
1281 VariantClear(arg);
1282 cVarRef++;
1285 } else {
1286 /* [out] args still can't be null,
1287 * but we can point these anywhere in this case,
1288 * since they won't be written to when cVarRef is 0 */
1289 rgVarRefIdx = puArgErr;
1290 rgVarRef = pVarResult;
1292 TRACE("passed by ref: %d args\n", cVarRef);
1293 hr = IDispatch_RemoteInvoke_Proxy(This,
1294 dispIdMember,
1295 riid,
1296 lcid,
1297 wFlags,
1298 pDispParams,
1299 pVarResult,
1300 pExcepInfo,
1301 puArgErr,
1302 cVarRef,
1303 rgVarRefIdx,
1304 rgVarRef);
1305 if (cVarRef) {
1306 for (u=0; u<cVarRef; u++) {
1307 unsigned i = rgVarRefIdx[u];
1308 VariantCopy(&pDispParams->rgvarg[i],
1309 &rgVarRef[u]);
1310 VariantClear(&rgVarRef[u]);
1312 CoTaskMemFree(rgVarRef);
1313 CoTaskMemFree(rgVarRefIdx);
1316 if(pExcepInfo == &ExcepInfo)
1318 SysFreeString(pExcepInfo->bstrSource);
1319 SysFreeString(pExcepInfo->bstrDescription);
1320 SysFreeString(pExcepInfo->bstrHelpFile);
1322 return hr;
1325 HRESULT __RPC_STUB IDispatch_Invoke_Stub(
1326 IDispatch* This,
1327 DISPID dispIdMember,
1328 REFIID riid,
1329 LCID lcid,
1330 DWORD dwFlags,
1331 DISPPARAMS* pDispParams,
1332 VARIANT* pVarResult,
1333 EXCEPINFO* pExcepInfo,
1334 UINT* pArgErr,
1335 UINT cVarRef,
1336 UINT* rgVarRefIdx,
1337 VARIANTARG* rgVarRef)
1339 HRESULT hr = S_OK;
1340 VARIANTARG *rgvarg, *arg;
1341 UINT u;
1343 /* initialize out parameters, so that they can be marshalled
1344 * in case the real Invoke doesn't initialize them */
1345 VariantInit(pVarResult);
1346 memset(pExcepInfo, 0, sizeof(*pExcepInfo));
1347 *pArgErr = 0;
1349 /* let the real Invoke operate on a copy of the in parameters,
1350 * so we don't risk losing pointers to allocated memory */
1351 rgvarg = pDispParams->rgvarg;
1352 arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
1353 if (!arg) return E_OUTOFMEMORY;
1355 /* init all args so we can call VariantClear on all the args if the copy
1356 * below fails */
1357 for (u = 0; u < pDispParams->cArgs; u++)
1358 VariantInit(&arg[u]);
1360 for (u = 0; u < pDispParams->cArgs; u++) {
1361 hr = VariantCopy(&arg[u], &rgvarg[u]);
1362 if (FAILED(hr))
1363 break;
1366 if (SUCCEEDED(hr)) {
1367 /* copy ref args to arg array */
1368 for (u=0; u<cVarRef; u++) {
1369 unsigned i = rgVarRefIdx[u];
1370 VariantCopy(&arg[i], &rgVarRef[u]);
1373 pDispParams->rgvarg = arg;
1375 hr = IDispatch_Invoke(This,
1376 dispIdMember,
1377 riid,
1378 lcid,
1379 dwFlags,
1380 pDispParams,
1381 pVarResult,
1382 pExcepInfo,
1383 pArgErr);
1385 /* copy ref args from arg array */
1386 for (u=0; u<cVarRef; u++) {
1387 unsigned i = rgVarRefIdx[u];
1388 VariantCopy(&rgVarRef[u], &arg[i]);
1392 /* clear the duplicate argument list */
1393 for (u=0; u<pDispParams->cArgs; u++)
1394 VariantClear(&arg[u]);
1396 pDispParams->rgvarg = rgvarg;
1397 CoTaskMemFree(arg);
1399 return hr;
1402 /* IEnumVARIANT */
1404 HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
1405 IEnumVARIANT* This,
1406 ULONG celt,
1407 VARIANT* rgVar,
1408 ULONG* pCeltFetched)
1410 ULONG fetched;
1411 if (!pCeltFetched)
1412 pCeltFetched = &fetched;
1413 return IEnumVARIANT_RemoteNext_Proxy(This,
1414 celt,
1415 rgVar,
1416 pCeltFetched);
1419 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
1420 IEnumVARIANT* This,
1421 ULONG celt,
1422 VARIANT* rgVar,
1423 ULONG* pCeltFetched)
1425 HRESULT hr;
1426 *pCeltFetched = 0;
1427 hr = IEnumVARIANT_Next(This,
1428 celt,
1429 rgVar,
1430 pCeltFetched);
1431 if (hr == S_OK) *pCeltFetched = celt;
1432 return hr;
1435 /* TypeInfo related freers */
1437 static void free_embedded_typedesc(TYPEDESC *tdesc);
1438 static void free_embedded_arraydesc(ARRAYDESC *adesc)
1440 switch(adesc->tdescElem.vt)
1442 case VT_PTR:
1443 case VT_SAFEARRAY:
1444 free_embedded_typedesc(adesc->tdescElem.u.lptdesc);
1445 CoTaskMemFree(adesc->tdescElem.u.lptdesc);
1446 break;
1447 case VT_CARRAY:
1448 free_embedded_arraydesc(adesc->tdescElem.u.lpadesc);
1449 CoTaskMemFree(adesc->tdescElem.u.lpadesc);
1450 break;
1454 static void free_embedded_typedesc(TYPEDESC *tdesc)
1456 switch(tdesc->vt)
1458 case VT_PTR:
1459 case VT_SAFEARRAY:
1460 free_embedded_typedesc(tdesc->u.lptdesc);
1461 CoTaskMemFree(tdesc->u.lptdesc);
1462 break;
1463 case VT_CARRAY:
1464 free_embedded_arraydesc(tdesc->u.lpadesc);
1465 CoTaskMemFree(tdesc->u.lpadesc);
1466 break;
1470 static void free_embedded_elemdesc(ELEMDESC *edesc)
1472 free_embedded_typedesc(&edesc->tdesc);
1473 if(edesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
1474 CoTaskMemFree(edesc->u.paramdesc.pparamdescex);
1477 /* ITypeComp */
1479 HRESULT CALLBACK ITypeComp_Bind_Proxy(
1480 ITypeComp* This,
1481 LPOLESTR name,
1482 ULONG lHashVal,
1483 WORD flags,
1484 ITypeInfo **ti,
1485 DESCKIND *desckind,
1486 BINDPTR *bindptr)
1488 CLEANLOCALSTORAGE stg = { 0 };
1489 ITypeComp *typecomp;
1490 FUNCDESC *funcdesc;
1491 VARDESC *vardesc;
1492 HRESULT hr;
1494 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", This, debugstr_w(name), lHashVal, flags, ti,
1495 desckind, bindptr);
1497 *desckind = DESCKIND_NONE;
1498 memset(bindptr, 0, sizeof(*bindptr));
1500 hr = ITypeComp_RemoteBind_Proxy(This, name, lHashVal, flags, ti, desckind,
1501 &funcdesc, &vardesc, &typecomp, &stg);
1503 if (hr == S_OK)
1505 switch (*desckind)
1507 case DESCKIND_FUNCDESC:
1508 bindptr->lpfuncdesc = funcdesc;
1509 break;
1510 case DESCKIND_VARDESC:
1511 case DESCKIND_IMPLICITAPPOBJ:
1512 bindptr->lpvardesc = vardesc;
1513 break;
1514 case DESCKIND_TYPECOMP:
1515 bindptr->lptcomp = typecomp;
1516 break;
1517 default:
1522 return hr;
1525 HRESULT __RPC_STUB ITypeComp_Bind_Stub(
1526 ITypeComp* This,
1527 LPOLESTR name,
1528 ULONG lHashVal,
1529 WORD flags,
1530 ITypeInfo **ti,
1531 DESCKIND *desckind,
1532 FUNCDESC **funcdesc,
1533 VARDESC **vardesc,
1534 ITypeComp **typecomp,
1535 CLEANLOCALSTORAGE *stg)
1537 BINDPTR bindptr;
1538 HRESULT hr;
1540 TRACE("%p, %s, %#lx, %#x, %p, %p, %p, %p, %p, %p.\n", This, debugstr_w(name),
1541 lHashVal, flags, ti, desckind, funcdesc, vardesc, typecomp, stg);
1543 memset(stg, 0, sizeof(*stg));
1544 memset(&bindptr, 0, sizeof(bindptr));
1546 *funcdesc = NULL;
1547 *vardesc = NULL;
1548 *typecomp = NULL;
1549 *ti = NULL;
1551 hr = ITypeComp_Bind(This, name, lHashVal, flags, ti, desckind, &bindptr);
1552 if(hr != S_OK)
1553 return hr;
1555 switch (*desckind)
1557 case DESCKIND_FUNCDESC:
1558 *funcdesc = bindptr.lpfuncdesc;
1559 stg->pInterface = (IUnknown*)*ti;
1560 stg->pStorage = funcdesc;
1561 stg->flags = CLS_FUNCDESC;
1562 break;
1563 case DESCKIND_VARDESC:
1564 case DESCKIND_IMPLICITAPPOBJ:
1565 *vardesc = bindptr.lpvardesc;
1566 stg->pInterface = (IUnknown*)*ti;
1567 stg->pStorage = vardesc;
1568 stg->flags = CLS_VARDESC;
1569 break;
1570 case DESCKIND_TYPECOMP:
1571 *typecomp = bindptr.lptcomp;
1572 break;
1573 default:
1577 if (stg->pInterface)
1578 IUnknown_AddRef(stg->pInterface);
1580 return hr;
1583 HRESULT CALLBACK ITypeComp_BindType_Proxy(
1584 ITypeComp* This,
1585 LPOLESTR name,
1586 ULONG lHashVal,
1587 ITypeInfo **ti,
1588 ITypeComp **typecomp)
1590 HRESULT hr;
1592 TRACE("%p, %s, %#lx, %p, %p.\n", This, debugstr_w(name), lHashVal, ti, typecomp);
1594 hr = ITypeComp_RemoteBindType_Proxy(This, name, lHashVal, ti);
1595 if (hr == S_OK)
1596 ITypeInfo_GetTypeComp(*ti, typecomp);
1597 else if (typecomp)
1598 *typecomp = NULL;
1600 return hr;
1603 HRESULT __RPC_STUB ITypeComp_BindType_Stub(
1604 ITypeComp* This,
1605 LPOLESTR name,
1606 ULONG lHashVal,
1607 ITypeInfo **ti)
1609 ITypeComp *typecomp = NULL;
1610 HRESULT hr;
1612 TRACE("%p, %s, %#lx, %p.\n", This, debugstr_w(name), lHashVal, ti);
1614 hr = ITypeComp_BindType(This, name, lHashVal, ti, &typecomp);
1616 if (typecomp)
1617 ITypeComp_Release(typecomp);
1619 return hr;
1622 /* ITypeInfo */
1624 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
1625 ITypeInfo* This,
1626 TYPEATTR** ppTypeAttr)
1629 CLEANLOCALSTORAGE stg;
1630 TRACE("(%p, %p)\n", This, ppTypeAttr);
1632 stg.flags = 0;
1633 stg.pStorage = NULL;
1634 stg.pInterface = NULL;
1636 return ITypeInfo_RemoteGetTypeAttr_Proxy(This, ppTypeAttr, &stg);
1639 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
1640 ITypeInfo* This,
1641 LPTYPEATTR* ppTypeAttr,
1642 CLEANLOCALSTORAGE* pDummy)
1644 HRESULT hr;
1645 TRACE("(%p, %p)\n", This, ppTypeAttr);
1647 hr = ITypeInfo_GetTypeAttr(This, ppTypeAttr);
1648 if(hr != S_OK)
1649 return hr;
1651 pDummy->flags = CLS_TYPEATTR;
1652 ITypeInfo_AddRef(This);
1653 pDummy->pInterface = (IUnknown*)This;
1654 pDummy->pStorage = ppTypeAttr;
1655 return hr;
1658 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
1659 ITypeInfo* This,
1660 UINT index,
1661 FUNCDESC** ppFuncDesc)
1663 CLEANLOCALSTORAGE stg;
1664 TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
1666 stg.flags = 0;
1667 stg.pStorage = NULL;
1668 stg.pInterface = NULL;
1670 return ITypeInfo_RemoteGetFuncDesc_Proxy(This, index, ppFuncDesc, &stg);
1673 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
1674 ITypeInfo* This,
1675 UINT index,
1676 LPFUNCDESC* ppFuncDesc,
1677 CLEANLOCALSTORAGE* pDummy)
1679 HRESULT hr;
1680 TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
1682 hr = ITypeInfo_GetFuncDesc(This, index, ppFuncDesc);
1683 if(hr != S_OK)
1684 return hr;
1686 pDummy->flags = CLS_FUNCDESC;
1687 ITypeInfo_AddRef(This);
1688 pDummy->pInterface = (IUnknown*)This;
1689 pDummy->pStorage = ppFuncDesc;
1690 return hr;
1693 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
1694 ITypeInfo* This,
1695 UINT index,
1696 VARDESC** ppVarDesc)
1698 CLEANLOCALSTORAGE stg;
1699 TRACE("(%p, %d, %p)\n", This, index, ppVarDesc);
1701 stg.flags = 0;
1702 stg.pStorage = NULL;
1703 stg.pInterface = NULL;
1705 return ITypeInfo_RemoteGetVarDesc_Proxy(This, index, ppVarDesc, &stg);
1708 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
1709 ITypeInfo* This,
1710 UINT index,
1711 LPVARDESC* ppVarDesc,
1712 CLEANLOCALSTORAGE* pDummy)
1714 HRESULT hr;
1715 TRACE("(%p, %d, %p)\n", This, index, ppVarDesc);
1717 hr = ITypeInfo_GetVarDesc(This, index, ppVarDesc);
1718 if(hr != S_OK)
1719 return hr;
1721 pDummy->flags = CLS_VARDESC;
1722 ITypeInfo_AddRef(This);
1723 pDummy->pInterface = (IUnknown*)This;
1724 pDummy->pStorage = ppVarDesc;
1725 return hr;
1728 HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
1729 ITypeInfo* This,
1730 MEMBERID memid,
1731 BSTR* rgBstrNames,
1732 UINT cMaxNames,
1733 UINT* pcNames)
1735 TRACE("%p, %#lx, %p, %d, %p.\n", This, memid, rgBstrNames, cMaxNames, pcNames);
1737 return ITypeInfo_RemoteGetNames_Proxy(This, memid, rgBstrNames, cMaxNames, pcNames);
1740 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
1741 ITypeInfo* This,
1742 MEMBERID memid,
1743 BSTR* rgBstrNames,
1744 UINT cMaxNames,
1745 UINT* pcNames)
1747 TRACE("%p, %#lx, %p, %d, %p.\n", This, memid, rgBstrNames, cMaxNames, pcNames);
1749 return ITypeInfo_GetNames(This, memid, rgBstrNames, cMaxNames, pcNames);
1752 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
1753 ITypeInfo* This,
1754 LPOLESTR* rgszNames,
1755 UINT cNames,
1756 MEMBERID* pMemId)
1758 FIXME("not implemented\n");
1759 return E_FAIL;
1762 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
1763 ITypeInfo* This)
1765 FIXME("not implemented\n");
1766 return E_FAIL;
1769 HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
1770 ITypeInfo* This,
1771 PVOID pvInstance,
1772 MEMBERID memid,
1773 WORD wFlags,
1774 DISPPARAMS* pDispParams,
1775 VARIANT* pVarResult,
1776 EXCEPINFO* pExcepInfo,
1777 UINT* puArgErr)
1779 FIXME("not implemented\n");
1780 return E_FAIL;
1783 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
1784 ITypeInfo* This)
1786 FIXME("not implemented\n");
1787 return E_FAIL;
1790 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(ITypeInfo *This, MEMBERID memid,
1791 BSTR *name, BSTR *doc_string,
1792 DWORD *help_context, BSTR *help_file)
1794 DWORD dummy_help_context, flags = 0;
1795 BSTR dummy_name, dummy_doc_string, dummy_help_file;
1796 HRESULT hr;
1798 TRACE("%p, %#lx, %p, %p, %p, %p.\n", This, memid, name, doc_string, help_context, help_file);
1800 if(!name) name = &dummy_name;
1801 else flags = 1;
1803 if(!doc_string) doc_string = &dummy_doc_string;
1804 else flags |= 2;
1806 if(!help_context) help_context = &dummy_help_context;
1807 else flags |= 4;
1809 if(!help_file) help_file = &dummy_help_file;
1810 else flags |= 8;
1812 hr = ITypeInfo_RemoteGetDocumentation_Proxy(This, memid, flags, name, doc_string, help_context, help_file);
1814 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */
1816 return hr;
1819 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(ITypeInfo *This, MEMBERID memid,
1820 DWORD flags, BSTR *name, BSTR *doc_string,
1821 DWORD *help_context, BSTR *help_file)
1823 TRACE("%p, %#lx, %#lx, %p, %p, %p, %p.\n", This, memid, flags, name, doc_string, help_context, help_file);
1825 *name = *doc_string = *help_file = NULL;
1826 *help_context = 0;
1828 if(!(flags & 1)) name = NULL;
1829 if(!(flags & 2)) doc_string = NULL;
1830 if(!(flags & 4)) help_context = NULL;
1831 if(!(flags & 8)) help_file = NULL;
1833 return ITypeInfo_GetDocumentation(This, memid, name, doc_string, help_context, help_file);
1836 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(ITypeInfo *This, MEMBERID memid,
1837 INVOKEKIND invkind, BSTR *dll_name,
1838 BSTR* name, WORD *ordinal)
1840 DWORD flags = 0;
1841 BSTR dummy_dll_name, dummy_name;
1842 WORD dummy_ordinal;
1843 HRESULT hr;
1845 TRACE("%p, %#lx, %#x, %p, %p, %p.\n", This, memid, invkind, dll_name, name, ordinal);
1847 if(!dll_name) dll_name = &dummy_dll_name;
1848 else flags = 1;
1850 if(!name) name = &dummy_name;
1851 else flags |= 2;
1853 if(!ordinal) ordinal = &dummy_ordinal;
1854 else flags |= 4;
1856 hr = ITypeInfo_RemoteGetDllEntry_Proxy(This, memid, invkind, flags, dll_name, name, ordinal);
1858 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */
1860 return hr;
1863 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(ITypeInfo *This, MEMBERID memid,
1864 INVOKEKIND invkind, DWORD flags,
1865 BSTR *dll_name, BSTR *name,
1866 WORD *ordinal)
1868 TRACE("%p, %#lx, %x, %p, %p, %p.\n", This, memid, invkind, dll_name, name, ordinal);
1870 *dll_name = *name = NULL;
1871 *ordinal = 0;
1873 if(!(flags & 1)) dll_name = NULL;
1874 if(!(flags & 2)) name = NULL;
1875 if(!(flags & 4)) ordinal = NULL;
1877 return ITypeInfo_GetDllEntry(This, memid, invkind, dll_name, name, ordinal);
1880 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
1881 ITypeInfo* This,
1882 MEMBERID memid,
1883 INVOKEKIND invKind,
1884 PVOID* ppv)
1886 FIXME("not implemented\n");
1887 return E_FAIL;
1890 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
1891 ITypeInfo* This)
1893 FIXME("not implemented\n");
1894 return E_FAIL;
1897 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
1898 ITypeInfo* This,
1899 IUnknown* pUnkOuter,
1900 REFIID riid,
1901 PVOID* ppvObj)
1903 FIXME("not implemented\n");
1904 return E_FAIL;
1907 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
1908 ITypeInfo* This,
1909 REFIID riid,
1910 IUnknown** ppvObj)
1912 FIXME("not implemented\n");
1913 return E_FAIL;
1916 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
1917 ITypeInfo* This,
1918 ITypeLib** ppTLib,
1919 UINT* pIndex)
1921 ITypeLib *pTL;
1922 UINT index;
1923 HRESULT hr;
1925 TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
1927 hr = ITypeInfo_RemoteGetContainingTypeLib_Proxy(This, &pTL, &index);
1928 if(SUCCEEDED(hr))
1930 if(pIndex)
1931 *pIndex = index;
1933 if(ppTLib)
1934 *ppTLib = pTL;
1935 else
1936 ITypeLib_Release(pTL);
1938 return hr;
1941 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
1942 ITypeInfo* This,
1943 ITypeLib** ppTLib,
1944 UINT* pIndex)
1946 TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
1947 return ITypeInfo_GetContainingTypeLib(This, ppTLib, pIndex);
1950 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
1951 ITypeInfo* This,
1952 TYPEATTR* pTypeAttr)
1954 TRACE("(%p, %p)\n", This, pTypeAttr);
1955 free_embedded_typedesc(&pTypeAttr->tdescAlias);
1956 CoTaskMemFree(pTypeAttr);
1959 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
1960 ITypeInfo* This)
1962 TRACE("nothing to do\n");
1963 return S_OK;
1966 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
1967 ITypeInfo* This,
1968 FUNCDESC* pFuncDesc)
1970 SHORT param;
1971 TRACE("(%p, %p)\n", This, pFuncDesc);
1973 for(param = 0; param < pFuncDesc->cParams; param++)
1974 free_embedded_elemdesc(pFuncDesc->lprgelemdescParam + param);
1975 if(param)
1976 CoTaskMemFree(pFuncDesc->lprgelemdescParam);
1978 free_embedded_elemdesc(&pFuncDesc->elemdescFunc);
1980 if(pFuncDesc->cScodes != 0 && pFuncDesc->cScodes != -1)
1981 CoTaskMemFree(pFuncDesc->lprgscode);
1983 CoTaskMemFree(pFuncDesc);
1986 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
1987 ITypeInfo* This)
1989 TRACE("nothing to do\n");
1990 return S_OK;
1993 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
1994 ITypeInfo* This,
1995 VARDESC* pVarDesc)
1997 TRACE("(%p, %p)\n", This, pVarDesc);
1999 CoTaskMemFree(pVarDesc->lpstrSchema);
2001 if(pVarDesc->varkind == VAR_CONST)
2002 CoTaskMemFree(pVarDesc->u.lpvarValue);
2004 free_embedded_elemdesc(&pVarDesc->elemdescVar);
2005 CoTaskMemFree(pVarDesc);
2008 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
2009 ITypeInfo* This)
2011 TRACE("nothing to do\n");
2012 return S_OK;
2016 /* ITypeInfo2 */
2018 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(ITypeInfo2 *This, MEMBERID memid,
2019 LCID lcid, BSTR *help_string,
2020 DWORD *help_context, BSTR *help_dll)
2022 DWORD dummy_help_context, flags = 0;
2023 BSTR dummy_help_string, dummy_help_dll;
2024 HRESULT hr;
2026 TRACE("%p, %#lx, %#lx, %p, %p, %p.\n", This, memid, lcid, help_string, help_context, help_dll);
2028 if(!help_string) help_string = &dummy_help_string;
2029 else flags = 1;
2031 if(!help_context) help_context = &dummy_help_context;
2032 else flags |= 2;
2034 if(!help_dll) help_dll = &dummy_help_dll;
2035 else flags |= 4;
2037 hr = ITypeInfo2_RemoteGetDocumentation2_Proxy(This, memid, lcid, flags, help_string, help_context, help_dll);
2039 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */
2041 return hr;
2044 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(ITypeInfo2 *This, MEMBERID memid,
2045 LCID lcid, DWORD flags,
2046 BSTR *help_string, DWORD *help_context,
2047 BSTR *help_dll)
2049 TRACE("%p, %#lx, %#lx, %#lx, %p, %p, %p.\n", This, memid, lcid, flags, help_string, help_context, help_dll);
2051 *help_string = *help_dll = NULL;
2052 *help_context = 0;
2054 if(!(flags & 1)) help_string = NULL;
2055 if(!(flags & 2)) help_context = NULL;
2056 if(!(flags & 4)) help_dll = NULL;
2058 return ITypeInfo2_GetDocumentation2(This, memid, lcid, help_string, help_context, help_dll);
2061 /* ITypeLib */
2063 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
2064 ITypeLib* This)
2066 UINT count = 0;
2067 TRACE("(%p)\n", This);
2069 ITypeLib_RemoteGetTypeInfoCount_Proxy(This, &count);
2071 return count;
2074 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
2075 ITypeLib* This,
2076 UINT* pcTInfo)
2078 TRACE("(%p, %p)\n", This, pcTInfo);
2079 *pcTInfo = ITypeLib_GetTypeInfoCount(This);
2080 return S_OK;
2083 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
2084 ITypeLib* This,
2085 TLIBATTR** ppTLibAttr)
2087 CLEANLOCALSTORAGE stg;
2088 TRACE("(%p, %p)\n", This, ppTLibAttr);
2090 stg.flags = 0;
2091 stg.pStorage = NULL;
2092 stg.pInterface = NULL;
2094 return ITypeLib_RemoteGetLibAttr_Proxy(This, ppTLibAttr, &stg);
2097 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
2098 ITypeLib* This,
2099 LPTLIBATTR* ppTLibAttr,
2100 CLEANLOCALSTORAGE* pDummy)
2102 HRESULT hr;
2103 TRACE("(%p, %p)\n", This, ppTLibAttr);
2105 hr = ITypeLib_GetLibAttr(This, ppTLibAttr);
2106 if(hr != S_OK)
2107 return hr;
2109 pDummy->flags = CLS_LIBATTR;
2110 ITypeLib_AddRef(This);
2111 pDummy->pInterface = (IUnknown*)This;
2112 pDummy->pStorage = ppTLibAttr;
2113 return hr;
2116 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(ITypeLib *This, INT index, BSTR *name,
2117 BSTR *doc_string, DWORD *help_context,
2118 BSTR *help_file)
2120 DWORD dummy_help_context, flags = 0;
2121 BSTR dummy_name, dummy_doc_string, dummy_help_file;
2122 HRESULT hr;
2123 TRACE("(%p, %d, %p, %p, %p, %p)\n", This, index, name, doc_string, help_context, help_file);
2125 if(!name) name = &dummy_name;
2126 else flags = 1;
2128 if(!doc_string) doc_string = &dummy_doc_string;
2129 else flags |= 2;
2131 if(!help_context) help_context = &dummy_help_context;
2132 else flags |= 4;
2134 if(!help_file) help_file = &dummy_help_file;
2135 else flags |= 8;
2137 hr = ITypeLib_RemoteGetDocumentation_Proxy(This, index, flags, name, doc_string, help_context, help_file);
2139 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */
2141 return hr;
2144 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(ITypeLib *This, INT index, DWORD flags,
2145 BSTR *name, BSTR *doc_string,
2146 DWORD *help_context, BSTR *help_file)
2148 TRACE("%p, %d, %#lx, %p, %p, %p, %p.\n", This, index, flags, name, doc_string, help_context, help_file);
2150 *name = *doc_string = *help_file = NULL;
2151 *help_context = 0;
2153 if(!(flags & 1)) name = NULL;
2154 if(!(flags & 2)) doc_string = NULL;
2155 if(!(flags & 4)) help_context = NULL;
2156 if(!(flags & 8)) help_file = NULL;
2158 return ITypeLib_GetDocumentation(This, index, name, doc_string, help_context, help_file);
2161 HRESULT CALLBACK ITypeLib_IsName_Proxy(
2162 ITypeLib* This,
2163 LPOLESTR szNameBuf,
2164 ULONG lHashVal,
2165 BOOL* pfName)
2167 FIXME("not implemented\n");
2168 return E_FAIL;
2171 HRESULT __RPC_STUB ITypeLib_IsName_Stub(
2172 ITypeLib* This,
2173 LPOLESTR szNameBuf,
2174 ULONG lHashVal,
2175 BOOL* pfName,
2176 BSTR* pBstrLibName)
2178 FIXME("not implemented\n");
2179 return E_FAIL;
2182 HRESULT CALLBACK ITypeLib_FindName_Proxy(
2183 ITypeLib* This,
2184 LPOLESTR szNameBuf,
2185 ULONG lHashVal,
2186 ITypeInfo** ppTInfo,
2187 MEMBERID* rgMemId,
2188 USHORT* pcFound)
2190 FIXME("not implemented\n");
2191 return E_FAIL;
2194 HRESULT __RPC_STUB ITypeLib_FindName_Stub(
2195 ITypeLib* This,
2196 LPOLESTR szNameBuf,
2197 ULONG lHashVal,
2198 ITypeInfo** ppTInfo,
2199 MEMBERID* rgMemId,
2200 USHORT* pcFound,
2201 BSTR* pBstrLibName)
2203 FIXME("not implemented\n");
2204 return E_FAIL;
2207 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
2208 ITypeLib* This,
2209 TLIBATTR* pTLibAttr)
2211 TRACE("(%p, %p)\n", This, pTLibAttr);
2212 CoTaskMemFree(pTLibAttr);
2215 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
2216 ITypeLib* This)
2218 TRACE("nothing to do\n");
2219 return S_OK;
2223 /* ITypeLib2 */
2225 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
2226 ITypeLib2* This,
2227 ULONG* pcUniqueNames,
2228 ULONG* pcchUniqueNames)
2230 FIXME("not implemented\n");
2231 return E_FAIL;
2234 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
2235 ITypeLib2* This,
2236 ULONG* pcUniqueNames,
2237 ULONG* pcchUniqueNames)
2239 FIXME("not implemented\n");
2240 return E_FAIL;
2243 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(ITypeLib2 *This, INT index,
2244 LCID lcid, BSTR *help_string,
2245 DWORD *help_context, BSTR *help_dll)
2247 DWORD dummy_help_context, flags = 0;
2248 BSTR dummy_help_string, dummy_help_dll;
2249 HRESULT hr;
2251 TRACE("%p, %d, %#lx, %p, %p, %p.\n", This, index, lcid, help_string, help_context, help_dll);
2253 if(!help_string) help_string = &dummy_help_string;
2254 else flags = 1;
2256 if(!help_context) help_context = &dummy_help_context;
2257 else flags |= 2;
2259 if(!help_dll) help_dll = &dummy_help_dll;
2260 else flags |= 4;
2262 hr = ITypeLib2_RemoteGetDocumentation2_Proxy(This, index, lcid, flags, help_string, help_context, help_dll);
2264 /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */
2266 return hr;
2269 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(ITypeLib2 *This, INT index, LCID lcid,
2270 DWORD flags, BSTR *help_string,
2271 DWORD *help_context, BSTR *help_dll)
2273 TRACE("%p, %d, %#lx, %#lx, %p, %p, %p.\n", This, index, lcid, flags, help_string, help_context, help_dll);
2275 *help_string = *help_dll = NULL;
2276 *help_context = 0;
2278 if(!(flags & 1)) help_string = NULL;
2279 if(!(flags & 2)) help_context = NULL;
2280 if(!(flags & 4)) help_dll = NULL;
2282 return ITypeLib2_GetDocumentation2(This, index, lcid, help_string, help_context, help_dll);
2285 HRESULT CALLBACK IPropertyBag_Read_Proxy(
2286 IPropertyBag* This,
2287 LPCOLESTR pszPropName,
2288 VARIANT *pVar,
2289 IErrorLog *pErrorLog)
2291 IUnknown *pUnk = NULL;
2292 TRACE("(%p, %s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
2294 if(!pVar)
2295 return E_POINTER;
2297 if(V_VT(pVar) & (VT_BYREF | VT_ARRAY | VT_VECTOR))
2299 FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar));
2300 return E_NOTIMPL;
2303 switch(V_VT(pVar))
2305 case VT_DISPATCH:
2306 pUnk = (IUnknown*)V_DISPATCH(pVar);
2307 break;
2308 case VT_UNKNOWN:
2309 pUnk = V_UNKNOWN(pVar);
2310 break;
2311 case VT_SAFEARRAY:
2312 FIXME("Safearray support not yet implemented.\n");
2313 return E_NOTIMPL;
2314 default:
2315 FIXME("Unknown V_VT %d - support not yet implemented.\n", V_VT(pVar));
2316 return E_NOTIMPL;
2319 return IPropertyBag_RemoteRead_Proxy(This, pszPropName, pVar, pErrorLog,
2320 V_VT(pVar), pUnk);
2323 HRESULT __RPC_STUB IPropertyBag_Read_Stub(
2324 IPropertyBag* This,
2325 LPCOLESTR pszPropName,
2326 VARIANT *pVar,
2327 IErrorLog *pErrorLog,
2328 DWORD varType,
2329 IUnknown *pUnkObj)
2331 IDispatch *disp;
2332 HRESULT hr;
2334 TRACE("%p, %s, %p, %p, %lx, %p.\n", This, debugstr_w(pszPropName), pVar,
2335 pErrorLog, varType, pUnkObj);
2337 if(varType & (VT_BYREF | VT_ARRAY | VT_VECTOR))
2339 FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar));
2340 return E_NOTIMPL;
2343 V_VT(pVar) = varType;
2344 switch(varType)
2346 case VT_DISPATCH:
2347 hr = IUnknown_QueryInterface(pUnkObj, &IID_IDispatch, (LPVOID*)&disp);
2348 if(FAILED(hr))
2349 return hr;
2350 IUnknown_Release(pUnkObj);
2351 V_DISPATCH(pVar) = disp;
2352 break;
2353 case VT_UNKNOWN:
2354 V_UNKNOWN(pVar) = pUnkObj;
2355 break;
2356 case VT_BSTR:
2357 V_BSTR(pVar) = SysAllocString(L"");
2358 break;
2359 case VT_SAFEARRAY:
2360 FIXME("Safearray support not yet implemented.\n");
2361 return E_NOTIMPL;
2362 default:
2363 break;
2365 hr = IPropertyBag_Read(This, pszPropName, pVar, pErrorLog);
2366 if(FAILED(hr))
2367 VariantClear(pVar);
2369 return hr;
2372 /* call_as/local stubs for ocidl.idl */
2374 HRESULT CALLBACK IClassFactory2_CreateInstanceLic_Proxy(
2375 IClassFactory2* This,
2376 IUnknown *pUnkOuter,
2377 IUnknown *pUnkReserved,
2378 REFIID riid,
2379 BSTR bstrKey,
2380 PVOID *ppvObj)
2382 TRACE("(%p, %s, %p)\n", pUnkOuter, debugstr_guid(riid), ppvObj);
2384 *ppvObj = NULL;
2386 if (pUnkOuter)
2388 ERR("aggregation is not allowed on remote objects\n");
2389 return CLASS_E_NOAGGREGATION;
2392 return IClassFactory2_RemoteCreateInstanceLic_Proxy(This, riid, bstrKey, (IUnknown**)ppvObj);
2395 HRESULT __RPC_STUB IClassFactory2_CreateInstanceLic_Stub(
2396 IClassFactory2* This,
2397 REFIID riid,
2398 BSTR bstrKey,
2399 IUnknown **ppvObj)
2401 TRACE("(%s, %p)\n", debugstr_guid(riid), ppvObj);
2402 return IClassFactory2_CreateInstanceLic(This, NULL, NULL, riid, bstrKey, (void**)ppvObj);
2405 HRESULT CALLBACK IEnumConnections_Next_Proxy(
2406 IEnumConnections* This,
2407 ULONG cConnections,
2408 LPCONNECTDATA rgcd,
2409 ULONG *pcFetched)
2411 ULONG fetched;
2413 TRACE("%lu, %p, %p.\n", cConnections, rgcd, pcFetched);
2415 if (!pcFetched)
2416 pcFetched = &fetched;
2418 return IEnumConnections_RemoteNext_Proxy(This, cConnections, rgcd, pcFetched);
2421 HRESULT __RPC_STUB IEnumConnections_Next_Stub(
2422 IEnumConnections* This,
2423 ULONG cConnections,
2424 LPCONNECTDATA rgcd,
2425 ULONG *pcFetched)
2427 HRESULT hr;
2429 TRACE("%lu, %p, %p.\n", cConnections, rgcd, pcFetched);
2431 *pcFetched = 0;
2432 hr = IEnumConnections_Next(This, cConnections, rgcd, pcFetched);
2433 if (hr == S_OK)
2434 *pcFetched = cConnections;
2436 return hr;
2439 HRESULT CALLBACK IEnumConnectionPoints_Next_Proxy(
2440 IEnumConnectionPoints* This,
2441 ULONG cConnections,
2442 IConnectionPoint **ppCP,
2443 ULONG *pcFetched)
2445 ULONG fetched;
2447 TRACE("%lu, %p %p.\n", cConnections, ppCP, pcFetched);
2449 if (!pcFetched)
2450 pcFetched = &fetched;
2452 return IEnumConnectionPoints_RemoteNext_Proxy(This, cConnections, ppCP, pcFetched);
2455 HRESULT __RPC_STUB IEnumConnectionPoints_Next_Stub(
2456 IEnumConnectionPoints* This,
2457 ULONG cConnections,
2458 IConnectionPoint **ppCP,
2459 ULONG *pcFetched)
2461 HRESULT hr;
2463 TRACE("%lu, %p, %p.\n", cConnections, ppCP, pcFetched);
2465 *pcFetched = 0;
2466 hr = IEnumConnectionPoints_Next(This, cConnections, ppCP, pcFetched);
2467 if (hr == S_OK)
2468 *pcFetched = cConnections;
2470 return hr;
2473 HRESULT CALLBACK IPersistMemory_Load_Proxy(
2474 IPersistMemory* This,
2475 LPVOID pMem,
2476 ULONG cbSize)
2478 TRACE("%p, %lu.\n", pMem, cbSize);
2480 if (!pMem)
2481 return E_POINTER;
2483 return IPersistMemory_RemoteLoad_Proxy(This, pMem, cbSize);
2486 HRESULT __RPC_STUB IPersistMemory_Load_Stub(
2487 IPersistMemory* This,
2488 BYTE *pMem,
2489 ULONG cbSize)
2491 TRACE("%p, %lu.\n", pMem, cbSize);
2492 return IPersistMemory_Load(This, pMem, cbSize);
2495 HRESULT CALLBACK IPersistMemory_Save_Proxy(
2496 IPersistMemory* This,
2497 LPVOID pMem,
2498 BOOL fClearDirty,
2499 ULONG cbSize)
2501 TRACE("%p, %d, %lu.\n", pMem, fClearDirty, cbSize);
2503 if (!pMem)
2504 return E_POINTER;
2506 return IPersistMemory_RemoteSave_Proxy(This, pMem, fClearDirty, cbSize);
2509 HRESULT __RPC_STUB IPersistMemory_Save_Stub(
2510 IPersistMemory* This,
2511 BYTE *pMem,
2512 BOOL fClearDirty,
2513 ULONG cbSize)
2515 TRACE("%p, %d, %lu.\n", pMem, fClearDirty, cbSize);
2516 return IPersistMemory_Save(This, pMem, fClearDirty, cbSize);
2519 void CALLBACK IAdviseSinkEx_OnViewStatusChange_Proxy(
2520 IAdviseSinkEx* This,
2521 DWORD dwViewStatus)
2523 TRACE("%p, %#lx.\n", This, dwViewStatus);
2524 IAdviseSinkEx_RemoteOnViewStatusChange_Proxy(This, dwViewStatus);
2527 HRESULT __RPC_STUB IAdviseSinkEx_OnViewStatusChange_Stub(
2528 IAdviseSinkEx* This,
2529 DWORD dwViewStatus)
2531 TRACE("%p, %#lx.\n", This, dwViewStatus);
2532 IAdviseSinkEx_OnViewStatusChange(This, dwViewStatus);
2533 return S_OK;
2536 HRESULT CALLBACK IEnumOleUndoUnits_Next_Proxy(
2537 IEnumOleUndoUnits* This,
2538 ULONG cElt,
2539 IOleUndoUnit **rgElt,
2540 ULONG *pcEltFetched)
2542 ULONG fetched;
2544 TRACE("%lu, %p %p.\n", cElt, rgElt, pcEltFetched);
2546 if (!pcEltFetched)
2547 pcEltFetched = &fetched;
2549 return IEnumOleUndoUnits_RemoteNext_Proxy(This, cElt, rgElt, pcEltFetched);
2552 HRESULT __RPC_STUB IEnumOleUndoUnits_Next_Stub(
2553 IEnumOleUndoUnits* This,
2554 ULONG cElt,
2555 IOleUndoUnit **rgElt,
2556 ULONG *pcEltFetched)
2558 HRESULT hr;
2560 TRACE("%lu, %p, %p.\n", cElt, rgElt, pcEltFetched);
2562 *pcEltFetched = 0;
2563 hr = IEnumOleUndoUnits_Next(This, cElt, rgElt, pcEltFetched);
2564 if (hr == S_OK)
2565 *pcEltFetched = cElt;
2567 return hr;
2570 HRESULT CALLBACK IQuickActivate_QuickActivate_Proxy(
2571 IQuickActivate* This,
2572 QACONTAINER *pQaContainer,
2573 QACONTROL *pQaControl)
2575 FIXME("not implemented\n");
2576 return E_NOTIMPL;
2579 HRESULT __RPC_STUB IQuickActivate_QuickActivate_Stub(
2580 IQuickActivate* This,
2581 QACONTAINER *pQaContainer,
2582 QACONTROL *pQaControl)
2584 FIXME("not implemented\n");
2585 return E_NOTIMPL;