wined3d: Move point scale render states to the state table.
[wine] / dlls / oleaut32 / usrmarshal.c
1 /*
2  * Misc marshalling routines
3  *
4  * Copyright 2002 Ove Kaaven
5  * Copyright 2003 Mike Hearn
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <string.h>
24
25 #define COBJMACROS
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winerror.h"
34
35 #include "ole2.h"
36 #include "oleauto.h"
37 #include "rpcproxy.h"
38 #include "typelib.h"
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(ole);
42
43 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
44 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
45 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
46 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
47
48 static CStdPSFactoryBuffer PSFactoryBuffer;
49
50 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
51
52 extern const ExtendedProxyFileInfo oaidl_ProxyFileInfo;
53
54 static const ProxyFileInfo *OLEAUT32_ProxyFileList[] = {
55   &oaidl_ProxyFileInfo,
56   NULL
57 };
58
59 HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
60 {
61   return NdrDllGetClassObject(rclsid, riid, ppv, OLEAUT32_ProxyFileList,
62                               &CLSID_PSDispatch, &PSFactoryBuffer);
63 }
64
65 static void dump_user_flags(ULONG *pFlags)
66 {
67     if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
68         TRACE("MAKELONG(NDR_LOCAL_REPRESENTATION, ");
69     else
70         TRACE("MAKELONG(0x%04x, ", HIWORD(*pFlags));
71     switch (LOWORD(*pFlags))
72     {
73         case MSHCTX_LOCAL: TRACE("MSHCTX_LOCAL)"); break;
74         case MSHCTX_NOSHAREDMEM: TRACE("MSHCTX_NOSHAREDMEM)"); break;
75         case MSHCTX_DIFFERENTMACHINE: TRACE("MSHCTX_DIFFERENTMACHINE)"); break;
76         case MSHCTX_INPROC: TRACE("MSHCTX_INPROC)"); break;
77         default: TRACE("%d)", LOWORD(*pFlags));
78     }
79 }
80
81 /* CLEANLOCALSTORAGE */
82
83 #define CLS_FUNCDESC  'f'
84 #define CLS_LIBATTR   'l'
85 #define CLS_TYPEATTR  't'
86 #define CLS_VARDESC   'v'
87
88 ULONG WINAPI CLEANLOCALSTORAGE_UserSize(ULONG *pFlags, ULONG Start, CLEANLOCALSTORAGE *pstg)
89 {
90     ALIGN_LENGTH(Start, 3);
91     return Start + sizeof(DWORD);
92 }
93
94 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
95 {
96     ALIGN_POINTER(Buffer, 3);
97     *(DWORD*)Buffer = pstg->flags;
98     switch(pstg->flags)
99     {
100     case CLS_LIBATTR:
101         ITypeLib_ReleaseTLibAttr((ITypeLib*)pstg->pInterface, *(TLIBATTR**)pstg->pStorage);
102         break;
103     case CLS_TYPEATTR:
104         ITypeInfo_ReleaseTypeAttr((ITypeInfo*)pstg->pInterface, *(TYPEATTR**)pstg->pStorage); 
105         break;
106     case CLS_FUNCDESC:
107         ITypeInfo_ReleaseFuncDesc((ITypeInfo*)pstg->pInterface, *(FUNCDESC**)pstg->pStorage); 
108         break;
109     case CLS_VARDESC:
110         ITypeInfo_ReleaseVarDesc((ITypeInfo*)pstg->pInterface, *(VARDESC**)pstg->pStorage);
111         break;
112
113     default:
114         ERR("Unknown type %x\n", pstg->flags);
115     }
116
117     *(VOID**)pstg->pStorage = NULL;
118     IUnknown_Release(pstg->pInterface);
119     pstg->pInterface = NULL;
120
121     return Buffer + sizeof(DWORD);
122 }
123
124 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
125 {
126     ALIGN_POINTER(Buffer, 3);
127     pstr->flags = *(DWORD*)Buffer;
128     return Buffer + sizeof(DWORD);
129 }
130
131 void WINAPI CLEANLOCALSTORAGE_UserFree(ULONG *pFlags, CLEANLOCALSTORAGE *pstr)
132 {
133     /* Nothing to do */
134 }
135
136 /* BSTR */
137
138 typedef struct
139 {
140     DWORD len;          /* No. of chars not including trailing '\0' */
141     DWORD byte_len;     /* len * 2 or 0xffffffff if len == 0 */
142     DWORD len2;         /* == len */
143 } bstr_wire_t;
144
145 ULONG WINAPI BSTR_UserSize(ULONG *pFlags, ULONG Start, BSTR *pstr)
146 {
147     TRACE("(%x,%d,%p) => %p\n", *pFlags, Start, pstr, *pstr);
148     if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
149     ALIGN_LENGTH(Start, 3);
150     Start += sizeof(bstr_wire_t) + ((SysStringByteLen(*pstr) + 1) & ~1);
151     TRACE("returning %d\n", Start);
152     return Start;
153 }
154
155 unsigned char * WINAPI BSTR_UserMarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
156 {
157     bstr_wire_t *header;
158     DWORD len = SysStringByteLen(*pstr);
159
160     TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
161     if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
162
163     ALIGN_POINTER(Buffer, 3);
164     header = (bstr_wire_t*)Buffer;
165     header->len = header->len2 = (len + 1) / 2;
166     if (*pstr)
167     {
168         header->byte_len = len;
169         memcpy(header + 1, *pstr, header->len * 2);
170     }
171     else
172         header->byte_len = 0xffffffff; /* special case for a null bstr */
173
174     return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
175 }
176
177 unsigned char * WINAPI BSTR_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr)
178 {
179     bstr_wire_t *header;
180     TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
181
182     ALIGN_POINTER(Buffer, 3);
183     header = (bstr_wire_t*)Buffer;
184     if(header->len != header->len2)
185         FIXME("len %08x != len2 %08x\n", header->len, header->len2);
186     
187     if(*pstr)
188     {
189         SysFreeString(*pstr);
190         *pstr = NULL;
191     }
192
193     if(header->byte_len != 0xffffffff)
194         *pstr = SysAllocStringByteLen((char*)(header + 1), header->byte_len);
195
196     if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
197     return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len;
198 }
199
200 void WINAPI BSTR_UserFree(ULONG *pFlags, BSTR *pstr)
201 {
202     TRACE("(%x,%p) => %p\n", *pFlags, pstr, *pstr);
203     if (*pstr)
204     {
205         SysFreeString(*pstr);
206         *pstr = NULL;
207     }
208 }
209
210 /* VARIANT */
211
212 typedef struct
213 {
214     DWORD clSize;
215     DWORD rpcReserverd;
216     USHORT vt;
217     USHORT wReserved1;
218     USHORT wReserved2;
219     USHORT wReserved3;
220     DWORD switch_is;
221 } variant_wire_t;
222
223 static unsigned int get_type_size(ULONG *pFlags, VARIANT *pvar)
224 {
225     if (V_VT(pvar) & VT_ARRAY) return 4;
226
227     switch (V_VT(pvar) & ~VT_BYREF) {
228     case VT_EMPTY:
229     case VT_NULL:
230         return 0;
231     case VT_I1:
232     case VT_UI1:
233         return sizeof(CHAR);
234     case VT_I2:
235     case VT_UI2:
236         return sizeof(SHORT);
237     case VT_I4:
238     case VT_UI4:
239         return sizeof(LONG);
240     case VT_INT:
241     case VT_UINT:
242         return sizeof(INT);
243     case VT_R4:
244         return sizeof(FLOAT);
245     case VT_R8:
246         return sizeof(DOUBLE);
247     case VT_BOOL:
248         return sizeof(VARIANT_BOOL);
249     case VT_ERROR:
250         return sizeof(SCODE);
251     case VT_DATE:
252         return sizeof(DATE);
253     case VT_CY:
254         return sizeof(CY);
255     case VT_DECIMAL:
256         return sizeof(DECIMAL);
257     case VT_BSTR:
258         return sizeof(BSTR);
259     case VT_VARIANT:
260         return sizeof(VARIANT);
261     case VT_UNKNOWN:
262     case VT_DISPATCH:
263     case VT_RECORD:
264         return 0;
265     default:
266         FIXME("unhandled VT %d\n", V_VT(pvar));
267         return 0;
268     }
269 }
270
271 static unsigned int get_type_alignment(ULONG *pFlags, VARIANT *pvar)
272 {
273     unsigned int size = get_type_size(pFlags, pvar);
274     if(V_VT(pvar) & VT_BYREF) return 3;
275     if(size == 0) return 0;
276     if(size <= 4) return size - 1;
277     return 7;
278 }
279
280 static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, VARIANT *pvar)
281 {
282   ULONG size;
283   HRESULT hr;
284   /* find the buffer size of the marshalled dispatch interface */
285   hr = CoGetMarshalSizeMax(&size, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
286   if (FAILED(hr)) {
287     if (!V_DISPATCH(pvar))
288       WARN("NULL dispatch pointer\n");
289     else
290       ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%x\n", hr);
291     return 0;
292   }
293   size += sizeof(ULONG); /* we have to store the buffersize in the stream */
294   TRACE("wire-size extra of dispatch variant is %d\n", size);
295   return size;
296 }
297
298 static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
299 {
300   if (V_ISARRAY(pvar))
301   {
302     if (V_ISBYREF(pvar))
303       return LPSAFEARRAY_UserSize(pFlags, Start, V_ARRAYREF(pvar));
304     else 
305       return LPSAFEARRAY_UserSize(pFlags, Start, &V_ARRAY(pvar));
306   }
307
308   switch (V_VT(pvar)) {
309   case VT_BSTR:
310     return BSTR_UserSize(pFlags, Start, &V_BSTR(pvar));
311   case VT_BSTR | VT_BYREF:
312     return BSTR_UserSize(pFlags, Start, V_BSTRREF(pvar));
313   case VT_VARIANT | VT_BYREF:
314     return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar));
315   case VT_UNKNOWN:
316     return Start + interface_variant_size(pFlags, &IID_IUnknown, pvar);
317   case VT_DISPATCH:
318     return Start + interface_variant_size(pFlags, &IID_IDispatch, pvar);
319   case VT_RECORD:
320     FIXME("wire-size record\n");
321     return Start;
322   case VT_SAFEARRAY:
323   case VT_SAFEARRAY | VT_BYREF:
324     FIXME("wire-size safearray: shouldn't be marshaling this\n");
325     return Start;
326   default:
327     return Start;
328   }
329 }
330
331 /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer. returns Buffer on failure, new position otherwise */
332 static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
333 {
334   IStream *working; 
335   HGLOBAL working_mem;
336   void *working_memlocked;
337   unsigned char *oldpos;
338   ULONG size;
339   HRESULT hr;
340   
341   TRACE("pFlags=%d, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
342
343   oldpos = Buffer;
344   
345   /* CoMarshalInterface needs a stream, whereas at this level we are operating in terms of buffers.
346    * We create a stream on an HGLOBAL, so we can simply do a memcpy to move it to the buffer.
347    * in rpcrt4/ndr_ole.c, a simple IStream implementation is wrapped around the buffer object,
348    * but that would be overkill here, hence this implementation. We save the size because the unmarshal
349    * code has no way to know how long the marshalled buffer is. */
350
351   size = wire_extra_user_size(pFlags, 0, pvar);
352   
353   working_mem = GlobalAlloc(0, size);
354   if (!working_mem) return oldpos;
355
356   hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
357   if (hr != S_OK) {
358     GlobalFree(working_mem);
359     return oldpos;
360   }
361   
362   hr = CoMarshalInterface(working, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
363   if (hr != S_OK) {
364     IStream_Release(working); /* this also releases the hglobal */
365     return oldpos;
366   }
367
368   working_memlocked = GlobalLock(working_mem);
369   memcpy(Buffer, &size, sizeof(ULONG)); /* copy the buffersize */
370   memcpy(Buffer + sizeof(ULONG), working_memlocked, size - sizeof(ULONG));
371   GlobalUnlock(working_mem);
372
373   IStream_Release(working);
374
375   /* size includes the ULONG for the size written above */
376   TRACE("done, size=%d\n", size);
377   return Buffer + size;
378 }
379
380 /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer. returns Buffer on failure, new position otherwise */
381 static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
382 {
383   IStream *working;
384   HGLOBAL working_mem;
385   void *working_memlocked;
386   unsigned char *oldpos;
387   ULONG size;
388   HRESULT hr;
389   
390   TRACE("pFlags=%d, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
391
392   oldpos = Buffer;
393   
394   /* get the buffersize */
395   memcpy(&size, Buffer, sizeof(ULONG));
396   TRACE("buffersize=%d\n", size);
397
398   working_mem = GlobalAlloc(0, size);
399   if (!working_mem) return oldpos;
400
401   hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
402   if (hr != S_OK) {
403     GlobalFree(working_mem);
404     return oldpos;
405   }
406
407   working_memlocked = GlobalLock(working_mem);
408   
409   /* now we copy the contents of the marshalling buffer to working_memlocked, unlock it, and demarshal the stream */
410   memcpy(working_memlocked, Buffer + sizeof(ULONG), size);
411   GlobalUnlock(working_mem);
412
413   hr = CoUnmarshalInterface(working, riid, (void**)&V_UNKNOWN(pvar));
414   if (hr != S_OK) {
415     IStream_Release(working);
416     return oldpos;
417   }
418
419   IStream_Release(working); /* this also frees the underlying hglobal */
420
421   /* size includes the ULONG for the size written above */
422   TRACE("done, processed=%d bytes\n", size);
423   return Buffer + size;
424 }
425
426
427 ULONG WINAPI VARIANT_UserSize(ULONG *pFlags, ULONG Start, VARIANT *pvar)
428 {
429     int align;
430     TRACE("(%x,%d,%p)\n", *pFlags, Start, pvar);
431     TRACE("vt=%04x\n", V_VT(pvar));
432
433     ALIGN_LENGTH(Start, 7);
434     Start += sizeof(variant_wire_t);
435     if(V_VT(pvar) & VT_BYREF)
436         Start += 4;
437
438     align = get_type_alignment(pFlags, pvar);
439     ALIGN_LENGTH(Start, align);
440     if(V_VT(pvar) == (VT_VARIANT | VT_BYREF))
441         Start += 4;
442     else
443         Start += get_type_size(pFlags, pvar);
444     Start = wire_extra_user_size(pFlags, Start, pvar);
445
446     TRACE("returning %d\n", Start);
447     return Start;
448 }
449
450 unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
451 {
452     variant_wire_t *header;
453     ULONG type_size;
454     int align;
455     unsigned char *Pos;
456
457     TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar);
458     TRACE("vt=%04x\n", V_VT(pvar));
459
460     ALIGN_POINTER(Buffer, 7);
461
462     header = (variant_wire_t *)Buffer; 
463
464     header->clSize = 0; /* fixed up at the end */
465     header->rpcReserverd = 0;
466     header->vt = pvar->n1.n2.vt;
467     header->wReserved1 = pvar->n1.n2.wReserved1;
468     header->wReserved2 = pvar->n1.n2.wReserved2;
469     header->wReserved3 = pvar->n1.n2.wReserved3;
470     header->switch_is = pvar->n1.n2.vt;
471     if(header->switch_is & VT_ARRAY)
472         header->switch_is &= ~VT_TYPEMASK;
473
474     Pos = (unsigned char*)(header + 1);
475     type_size = get_type_size(pFlags, pvar);
476     align = get_type_alignment(pFlags, pvar);
477     ALIGN_POINTER(Pos, align);
478
479     if(header->vt & VT_BYREF)
480     {
481         *(DWORD *)Pos = max(type_size, 4);
482         Pos += 4;
483         if((header->vt & VT_TYPEMASK) != VT_VARIANT)
484         {
485             memcpy(Pos, pvar->n1.n2.n3.byref, type_size);
486             Pos += type_size;
487         }
488         else
489         {
490             *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24;
491             Pos += 4;
492         }
493     } 
494     else
495     {
496         if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
497             memcpy(Pos, pvar, type_size);
498         else
499             memcpy(Pos, &pvar->n1.n2.n3, type_size);
500         Pos += type_size;
501     }
502
503     if(header->vt & VT_ARRAY)
504     {
505         if(header->vt & VT_BYREF)
506             Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar));
507         else
508             Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar));
509     }
510     else
511     {
512         switch (header->vt)
513         {
514         case VT_BSTR:
515             Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
516             break;
517         case VT_BSTR | VT_BYREF:
518             Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
519             break;
520         case VT_VARIANT | VT_BYREF:
521             Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
522             break;
523         case VT_DISPATCH | VT_BYREF:
524             FIXME("handle DISPATCH by ref\n");
525             break;
526         case VT_UNKNOWN:
527             /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
528             Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar);
529             break;
530         case VT_DISPATCH:
531             /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
532             Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar);
533             break;
534         case VT_RECORD:
535             FIXME("handle BRECORD by val\n");
536             break;
537         case VT_RECORD | VT_BYREF:
538             FIXME("handle BRECORD by ref\n");
539             break;
540         }
541     }
542     header->clSize = ((Pos - Buffer) + 7) >> 3;
543     TRACE("marshalled size=%d\n", header->clSize);
544     return Pos;
545 }
546
547 unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
548 {
549     variant_wire_t *header;
550     ULONG type_size;
551     int align;
552     unsigned char *Pos;
553
554     TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar);
555
556     ALIGN_POINTER(Buffer, 7);
557     VariantInit(pvar);
558
559     header = (variant_wire_t *)Buffer; 
560     
561     pvar->n1.n2.vt = header->vt;
562     pvar->n1.n2.wReserved1 = header->wReserved1;
563     pvar->n1.n2.wReserved2 = header->wReserved2;
564     pvar->n1.n2.wReserved3 = header->wReserved3;
565
566     Pos = (unsigned char*)(header + 1);
567     type_size = get_type_size(pFlags, pvar);
568     align = get_type_alignment(pFlags, pvar);
569     ALIGN_POINTER(Pos, align);
570
571     if(header->vt & VT_BYREF)
572     {
573         Pos += 4;
574         pvar->n1.n2.n3.byref = CoTaskMemAlloc(type_size);
575         memcpy(pvar->n1.n2.n3.byref, Pos, type_size); 
576         if((header->vt & VT_TYPEMASK) != VT_VARIANT)
577            Pos += type_size;
578         else
579             Pos += 4;
580     }
581     else
582     {
583         if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
584             memcpy(pvar, Pos, type_size);
585         else
586             memcpy(&pvar->n1.n2.n3, Pos, type_size);
587         Pos += type_size;
588     }
589
590     if(header->vt & VT_ARRAY)
591     {
592         if(header->vt & VT_BYREF)
593             Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar));
594         else
595             Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar));
596     }
597     else
598     {
599         switch (header->vt)
600         {
601         case VT_BSTR:
602             V_BSTR(pvar) = NULL;
603             Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
604             break;
605         case VT_BSTR | VT_BYREF:
606             *V_BSTRREF(pvar) = NULL;
607             Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
608             break;
609         case VT_VARIANT | VT_BYREF:
610             Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
611             break;
612         case VT_DISPATCH | VT_BYREF:
613             FIXME("handle DISPATCH by ref\n");
614             break;
615         case VT_UNKNOWN:
616             /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
617             Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar);
618             break;
619         case VT_DISPATCH:
620             /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
621             Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar);
622             break;
623         case VT_RECORD:
624             FIXME("handle BRECORD by val\n");
625             break;
626         case VT_RECORD | VT_BYREF:
627             FIXME("handle BRECORD by ref\n");
628             break;
629         }
630     }
631     return Pos;
632 }
633
634 void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar)
635 {
636   VARTYPE vt = V_VT(pvar);
637   PVOID ref = NULL;
638
639   TRACE("(%x,%p)\n", *pFlags, pvar);
640   TRACE("vt=%04x\n", V_VT(pvar));
641
642   if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
643
644   VariantClear(pvar);
645   if (!ref) return;
646
647   if(vt & VT_ARRAY)
648     LPSAFEARRAY_UserFree(pFlags, V_ARRAYREF(pvar));
649   else
650   {
651     switch (vt)
652     {
653     case VT_BSTR | VT_BYREF:
654       BSTR_UserFree(pFlags, V_BSTRREF(pvar));
655       break;
656     case VT_VARIANT | VT_BYREF:
657       VARIANT_UserFree(pFlags, V_VARIANTREF(pvar));
658       break;
659     case VT_RECORD | VT_BYREF:
660       FIXME("handle BRECORD by ref\n");
661       break;
662     case VT_UNKNOWN | VT_BYREF:
663     case VT_DISPATCH | VT_BYREF:
664       IUnknown_Release(*V_UNKNOWNREF(pvar));
665       break;
666     }
667   }
668
669   CoTaskMemFree(ref);
670 }
671
672 /* LPSAFEARRAY */
673
674 /* Get the number of cells in a SafeArray */
675 static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
676 {
677     const SAFEARRAYBOUND* psab = psa->rgsabound;
678     USHORT cCount = psa->cDims;
679     ULONG ulNumCells = 1;
680
681     while (cCount--)
682     {
683         /* This is a valid bordercase. See testcases. -Marcus */
684         if (!psab->cElements)
685             return 0;
686         ulNumCells *= psab->cElements;
687         psab++;
688     }
689     return ulNumCells;
690 }
691
692 static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
693 {
694     VARTYPE vt;
695     HRESULT hr;
696
697     hr = SafeArrayGetVartype(psa, &vt);
698     if (FAILED(hr))
699         RpcRaiseException(hr);
700
701     if (psa->fFeatures & FADF_HAVEIID)
702         return SF_HAVEIID;
703
704     switch (vt)
705     {
706     case VT_I1:
707     case VT_UI1:      return SF_I1;
708     case VT_BOOL:
709     case VT_I2:
710     case VT_UI2:      return SF_I2;
711     case VT_INT:
712     case VT_UINT:
713     case VT_I4:
714     case VT_UI4:
715     case VT_R4:       return SF_I4;
716     case VT_DATE:
717     case VT_CY:
718     case VT_R8:
719     case VT_I8:
720     case VT_UI8:      return SF_I8;
721     case VT_INT_PTR:
722     case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
723     case VT_BSTR:     return SF_BSTR;
724     case VT_DISPATCH: return SF_DISPATCH;
725     case VT_VARIANT:  return SF_VARIANT;
726     case VT_UNKNOWN:  return SF_UNKNOWN;
727     /* Note: Return a non-zero size to indicate vt is valid. The actual size
728      * of a UDT is taken from the result of IRecordInfo_GetSize().
729      */
730     case VT_RECORD:   return SF_RECORD;
731     default:          return SF_ERROR;
732     }
733 }
734
735 ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa)
736 {
737     ULONG size = StartingSize;
738
739     TRACE("("); dump_user_flags(pFlags); TRACE(", %d, %p\n", StartingSize, *ppsa);
740
741     ALIGN_LENGTH(size, 3);
742     size += sizeof(ULONG_PTR);
743     if (*ppsa)
744     {
745         SAFEARRAY *psa = *ppsa;
746         ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
747         SF_TYPE sftype;
748         HRESULT hr;
749
750         size += sizeof(ULONG);
751         size += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
752
753         sftype = SAFEARRAY_GetUnionType(psa);
754         size += sizeof(ULONG);
755
756         size += sizeof(ULONG);
757         size += sizeof(ULONG_PTR);
758         if (sftype == SF_HAVEIID)
759             size += sizeof(IID);
760
761         size += sizeof(psa->rgsabound[0]) * psa->cDims;
762
763         size += sizeof(ULONG);
764
765         switch (sftype)
766         {
767             case SF_BSTR:
768             {
769                 BSTR* lpBstr;
770
771                 for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
772                     size = BSTR_UserSize(pFlags, size, lpBstr);
773
774                 break;
775             }
776             case SF_DISPATCH:
777             case SF_UNKNOWN:
778             case SF_HAVEIID:
779                 FIXME("size interfaces\n");
780                 break;
781             case SF_VARIANT:
782             {
783                 VARIANT* lpVariant;
784
785                 for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
786                     size = VARIANT_UserSize(pFlags, size, lpVariant);
787
788                 break;
789             }
790             case SF_RECORD:
791             {
792                 IRecordInfo* pRecInfo = NULL;
793
794                 hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
795                 if (FAILED(hr))
796                     RpcRaiseException(hr);
797
798                 if (pRecInfo)
799                 {
800                     FIXME("size record info %p\n", pRecInfo);
801
802                     IRecordInfo_Release(pRecInfo);
803                 }
804                 break;
805             }
806             case SF_I8:
807                 ALIGN_LENGTH(size, 7);
808                 /* fallthrough */
809             case SF_I1:
810             case SF_I2:
811             case SF_I4:
812                 size += ulCellCount * psa->cbElements;
813                 break;
814             default:
815                 break;
816         }
817
818     }
819
820     return size;
821 }
822
823 unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
824 {
825     HRESULT hr;
826
827     TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa);
828
829     ALIGN_POINTER(Buffer, 3);
830     *(ULONG_PTR *)Buffer = *ppsa ? TRUE : FALSE;
831     Buffer += sizeof(ULONG_PTR);
832     if (*ppsa)
833     {
834         VARTYPE vt;
835         SAFEARRAY *psa = *ppsa;
836         ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
837         wireSAFEARRAY wiresa;
838         SF_TYPE sftype;
839         GUID guid;
840
841         *(ULONG *)Buffer = psa->cDims;
842         Buffer += sizeof(ULONG);
843         wiresa = (wireSAFEARRAY)Buffer;
844         wiresa->cDims = psa->cDims;
845         wiresa->fFeatures = psa->fFeatures;
846         wiresa->cbElements = psa->cbElements;
847
848         hr = SafeArrayGetVartype(psa, &vt);
849         if (FAILED(hr))
850             RpcRaiseException(hr);
851         wiresa->cLocks = (USHORT)psa->cLocks | (vt << 16);
852
853         Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
854
855         sftype = SAFEARRAY_GetUnionType(psa);
856         *(ULONG *)Buffer = sftype;
857         Buffer += sizeof(ULONG);
858
859         *(ULONG *)Buffer = ulCellCount;
860         Buffer += sizeof(ULONG);
861         *(ULONG_PTR *)Buffer = (ULONG_PTR)psa->pvData;
862         Buffer += sizeof(ULONG_PTR);
863         if (sftype == SF_HAVEIID)
864         {
865             SafeArrayGetIID(psa, &guid);
866             memcpy(Buffer, &guid, sizeof(guid));
867             Buffer += sizeof(guid);
868         }
869
870         memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims);
871         Buffer += sizeof(psa->rgsabound[0]) * psa->cDims;
872
873         *(ULONG *)Buffer = ulCellCount;
874         Buffer += sizeof(ULONG);
875
876         if (psa->pvData)
877         {
878             switch (sftype)
879             {
880                 case SF_BSTR:
881                 {
882                     BSTR* lpBstr;
883
884                     for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
885                         Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr);
886
887                     break;
888                 }
889                 case SF_DISPATCH:
890                 case SF_UNKNOWN:
891                 case SF_HAVEIID:
892                     FIXME("marshal interfaces\n");
893                     break;
894                 case SF_VARIANT:
895                 {
896                     VARIANT* lpVariant;
897
898                     for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
899                         Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant);
900
901                     break;
902                 }
903                 case SF_RECORD:
904                 {
905                     IRecordInfo* pRecInfo = NULL;
906
907                     hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
908                     if (FAILED(hr))
909                         RpcRaiseException(hr);
910
911                     if (pRecInfo)
912                     {
913                         FIXME("write record info %p\n", pRecInfo);
914
915                         IRecordInfo_Release(pRecInfo);
916                     }
917                     break;
918                 }
919
920                 case SF_I8:
921                     ALIGN_POINTER(Buffer, 7);
922                     /* fallthrough */
923                 case SF_I1:
924                 case SF_I2:
925                 case SF_I4:
926                     /* Just copy the data over */
927                     memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements);
928                     Buffer += ulCellCount * psa->cbElements;
929                     break;
930                 default:
931                     break;
932             }
933         }
934
935     }
936     return Buffer;
937 }
938
939 #define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \
940                            FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \
941                            FADF_VARIANT | FADF_CREATEVECTOR)
942
943 unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
944 {
945     ULONG_PTR ptr;
946     wireSAFEARRAY wiresa;
947     ULONG cDims;
948     HRESULT hr;
949     SF_TYPE sftype;
950     ULONG cell_count;
951     GUID guid;
952     VARTYPE vt;
953     SAFEARRAYBOUND *wiresab;
954
955     TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa);
956
957     ALIGN_POINTER(Buffer, 3);
958     ptr = *(ULONG_PTR *)Buffer;
959     Buffer += sizeof(ULONG_PTR);
960
961     if (!ptr)
962     {
963         *ppsa = NULL;
964
965         TRACE("NULL safe array unmarshaled\n");
966
967         return Buffer;
968     }
969
970     cDims = *(ULONG *)Buffer;
971     Buffer += sizeof(ULONG);
972
973     wiresa = (wireSAFEARRAY)Buffer;
974     Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
975
976     if (cDims != wiresa->cDims)
977         RpcRaiseException(RPC_S_INVALID_BOUND);
978
979     /* FIXME: there should be a limit on how large cDims can be */
980
981     vt = HIWORD(wiresa->cLocks);
982
983     sftype = *(ULONG *)Buffer;
984     Buffer += sizeof(ULONG);
985
986     cell_count = *(ULONG *)Buffer;
987     Buffer += sizeof(ULONG);
988     ptr = *(ULONG_PTR *)Buffer;
989     Buffer += sizeof(ULONG_PTR);
990     if (sftype == SF_HAVEIID)
991     {
992         memcpy(&guid, Buffer, sizeof(guid));
993         Buffer += sizeof(guid);
994     }
995
996     wiresab = (SAFEARRAYBOUND *)Buffer;
997     Buffer += sizeof(wiresab[0]) * wiresa->cDims;
998
999     *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL);
1000     if (!*ppsa)
1001         RpcRaiseException(E_OUTOFMEMORY);
1002
1003     /* be careful about which flags we set since they could be a security
1004      * risk */
1005     (*ppsa)->fFeatures &= FADF_AUTOSETFLAGS;
1006     (*ppsa)->fFeatures |= (wiresa->fFeatures & ~(FADF_AUTOSETFLAGS));
1007     /* FIXME: there should be a limit on how large wiresa->cbElements can be */
1008     (*ppsa)->cbElements = wiresa->cbElements;
1009     (*ppsa)->cLocks = LOWORD(wiresa->cLocks);
1010
1011     hr = SafeArrayAllocData(*ppsa);
1012     if (FAILED(hr))
1013         RpcRaiseException(hr);
1014
1015     if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count))
1016         RpcRaiseException(RPC_S_INVALID_BOUND);
1017     Buffer += sizeof(ULONG);
1018
1019     if (ptr)
1020     {
1021         switch (sftype)
1022         {
1023             case SF_BSTR:
1024             {
1025                 BSTR* lpBstr;
1026
1027                 for (lpBstr = (BSTR*)(*ppsa)->pvData; cell_count; cell_count--, lpBstr++)
1028                     Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr);
1029
1030                 break;
1031             }
1032             case SF_DISPATCH:
1033             case SF_UNKNOWN:
1034             case SF_HAVEIID:
1035                 FIXME("marshal interfaces\n");
1036                 break;
1037             case SF_VARIANT:
1038             {
1039                 VARIANT* lpVariant;
1040
1041                 for (lpVariant = (VARIANT*)(*ppsa)->pvData; cell_count; cell_count--, lpVariant++)
1042                     Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant);
1043
1044                 break;
1045             }
1046             case SF_RECORD:
1047             {
1048                 FIXME("set record info\n");
1049
1050                 break;
1051             }
1052
1053             case SF_I8:
1054                 ALIGN_POINTER(Buffer, 7);
1055                 /* fallthrough */
1056             case SF_I1:
1057             case SF_I2:
1058             case SF_I4:
1059                 /* Just copy the data over */
1060                 memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements);
1061                 Buffer += cell_count * (*ppsa)->cbElements;
1062                 break;
1063             default:
1064                 break;
1065         }
1066     }
1067
1068     TRACE("safe array unmarshaled: %p\n", *ppsa);
1069
1070     return Buffer;
1071 }
1072
1073 void WINAPI LPSAFEARRAY_UserFree(ULONG *pFlags, LPSAFEARRAY *ppsa)
1074 {
1075     TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa);
1076
1077     SafeArrayDestroy(*ppsa);
1078 }
1079
1080 /* IDispatch */
1081 /* exactly how Invoke is marshalled is not very clear to me yet,
1082  * but the way I've done it seems to work for me */
1083
1084 HRESULT CALLBACK IDispatch_Invoke_Proxy(
1085     IDispatch* This,
1086     DISPID dispIdMember,
1087     REFIID riid,
1088     LCID lcid,
1089     WORD wFlags,
1090     DISPPARAMS* pDispParams,
1091     VARIANT* pVarResult,
1092     EXCEPINFO* pExcepInfo,
1093     UINT* puArgErr)
1094 {
1095   HRESULT hr;
1096   VARIANT VarResult;
1097   UINT* rgVarRefIdx = NULL;
1098   VARIANTARG* rgVarRef = NULL;
1099   UINT u, cVarRef;
1100   UINT uArgErr;
1101   EXCEPINFO ExcepInfo;
1102
1103   TRACE("(%p)->(%d,%s,%x,%x,%p,%p,%p,%p)\n", This,
1104         dispIdMember, debugstr_guid(riid),
1105         lcid, wFlags, pDispParams, pVarResult,
1106         pExcepInfo, puArgErr);
1107
1108   /* [out] args can't be null, use dummy vars if needed */
1109   if (!pVarResult) pVarResult = &VarResult;
1110   if (!puArgErr) puArgErr = &uArgErr;
1111   if (!pExcepInfo) pExcepInfo = &ExcepInfo;
1112
1113   /* count by-ref args */
1114   for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
1115     VARIANTARG* arg = &pDispParams->rgvarg[u];
1116     if (V_ISBYREF(arg)) {
1117       cVarRef++;
1118     }
1119   }
1120   if (cVarRef) {
1121     rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
1122     rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
1123     /* make list of by-ref args */
1124     for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
1125       VARIANTARG* arg = &pDispParams->rgvarg[u];
1126       if (V_ISBYREF(arg)) {
1127         rgVarRefIdx[cVarRef] = u;
1128         VariantInit(&rgVarRef[cVarRef]);
1129         cVarRef++;
1130       }
1131     }
1132   } else {
1133     /* [out] args still can't be null,
1134      * but we can point these anywhere in this case,
1135      * since they won't be written to when cVarRef is 0 */
1136     rgVarRefIdx = puArgErr;
1137     rgVarRef = pVarResult;
1138   }
1139   TRACE("passed by ref: %d args\n", cVarRef);
1140   hr = IDispatch_RemoteInvoke_Proxy(This,
1141                                     dispIdMember,
1142                                     riid,
1143                                     lcid,
1144                                     wFlags,
1145                                     pDispParams,
1146                                     pVarResult,
1147                                     pExcepInfo,
1148                                     puArgErr,
1149                                     cVarRef,
1150                                     rgVarRefIdx,
1151                                     rgVarRef);
1152   if (cVarRef) {
1153     for (u=0; u<cVarRef; u++) {
1154       unsigned i = rgVarRefIdx[u];
1155       VariantCopy(&pDispParams->rgvarg[i],
1156                   &rgVarRef[u]);
1157       VariantClear(&rgVarRef[u]);
1158     }
1159     CoTaskMemFree(rgVarRef);
1160     CoTaskMemFree(rgVarRefIdx);
1161   }
1162
1163   if(pExcepInfo == &ExcepInfo)
1164   {
1165     SysFreeString(pExcepInfo->bstrSource);
1166     SysFreeString(pExcepInfo->bstrDescription);
1167     SysFreeString(pExcepInfo->bstrHelpFile);
1168   }
1169   return hr;
1170 }
1171
1172 HRESULT __RPC_STUB IDispatch_Invoke_Stub(
1173     IDispatch* This,
1174     DISPID dispIdMember,
1175     REFIID riid,
1176     LCID lcid,
1177     DWORD dwFlags,
1178     DISPPARAMS* pDispParams,
1179     VARIANT* pVarResult,
1180     EXCEPINFO* pExcepInfo,
1181     UINT* pArgErr,
1182     UINT cVarRef,
1183     UINT* rgVarRefIdx,
1184     VARIANTARG* rgVarRef)
1185 {
1186   HRESULT hr = S_OK;
1187   VARIANTARG *rgvarg, *arg;
1188   UINT u;
1189
1190   /* initialize out parameters, so that they can be marshalled
1191    * in case the real Invoke doesn't initialize them */
1192   VariantInit(pVarResult);
1193   memset(pExcepInfo, 0, sizeof(*pExcepInfo));
1194   *pArgErr = 0;
1195
1196   /* let the real Invoke operate on a copy of the in parameters,
1197    * so we don't risk losing pointers to allocated memory */
1198   rgvarg = pDispParams->rgvarg;
1199   arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
1200   if (!arg) return E_OUTOFMEMORY;
1201
1202   /* init all args so we can call VariantClear on all the args if the copy
1203    * below fails */
1204   for (u = 0; u < pDispParams->cArgs; u++)
1205     VariantInit(&arg[u]);
1206
1207   for (u = 0; u < pDispParams->cArgs; u++) {
1208     hr = VariantCopy(&arg[u], &rgvarg[u]);
1209     if (FAILED(hr))
1210         break;
1211   }
1212
1213   if (SUCCEEDED(hr)) {
1214     pDispParams->rgvarg = arg;
1215
1216     hr = IDispatch_Invoke(This,
1217                           dispIdMember,
1218                           riid,
1219                           lcid,
1220                           dwFlags,
1221                           pDispParams,
1222                           pVarResult,
1223                           pExcepInfo,
1224                           pArgErr);
1225
1226     /* copy ref args to out list */
1227     for (u=0; u<cVarRef; u++) {
1228       unsigned i = rgVarRefIdx[u];
1229       VariantInit(&rgVarRef[u]);
1230       VariantCopy(&rgVarRef[u], &arg[i]);
1231       /* clear original if equal, to avoid double-free */
1232       if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
1233         VariantClear(&rgvarg[i]);
1234     }
1235   }
1236
1237   /* clear the duplicate argument list */
1238   for (u=0; u<pDispParams->cArgs; u++)
1239     VariantClear(&arg[u]);
1240
1241   pDispParams->rgvarg = rgvarg;
1242   CoTaskMemFree(arg);
1243
1244   return hr;
1245 }
1246
1247 /* IEnumVARIANT */
1248
1249 HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
1250     IEnumVARIANT* This,
1251     ULONG celt,
1252     VARIANT* rgVar,
1253     ULONG* pCeltFetched)
1254 {
1255   ULONG fetched;
1256   if (!pCeltFetched)
1257     pCeltFetched = &fetched;
1258   return IEnumVARIANT_RemoteNext_Proxy(This,
1259                                        celt,
1260                                        rgVar,
1261                                        pCeltFetched);
1262 }
1263
1264 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
1265     IEnumVARIANT* This,
1266     ULONG celt,
1267     VARIANT* rgVar,
1268     ULONG* pCeltFetched)
1269 {
1270   HRESULT hr;
1271   *pCeltFetched = 0;
1272   hr = IEnumVARIANT_Next(This,
1273                          celt,
1274                          rgVar,
1275                          pCeltFetched);
1276   if (hr == S_OK) *pCeltFetched = celt;
1277   return hr;
1278 }
1279
1280 /* TypeInfo related freers */
1281
1282 static void free_embedded_typedesc(TYPEDESC *tdesc);
1283 static void free_embedded_arraydesc(ARRAYDESC *adesc)
1284 {
1285     switch(adesc->tdescElem.vt)
1286     {
1287     case VT_PTR:
1288     case VT_SAFEARRAY:
1289         free_embedded_typedesc(adesc->tdescElem.u.lptdesc);
1290         CoTaskMemFree(adesc->tdescElem.u.lptdesc);
1291         break;
1292     case VT_CARRAY:
1293         free_embedded_arraydesc(adesc->tdescElem.u.lpadesc);
1294         CoTaskMemFree(adesc->tdescElem.u.lpadesc);
1295         break;
1296     }
1297 }
1298
1299 static void free_embedded_typedesc(TYPEDESC *tdesc)
1300 {
1301     switch(tdesc->vt)
1302     {
1303     case VT_PTR:
1304     case VT_SAFEARRAY:
1305         free_embedded_typedesc(tdesc->u.lptdesc);
1306         CoTaskMemFree(tdesc->u.lptdesc);
1307         break;
1308     case VT_CARRAY:
1309         free_embedded_arraydesc(tdesc->u.lpadesc);
1310         CoTaskMemFree(tdesc->u.lpadesc);
1311         break;
1312     }
1313 }
1314
1315 static void free_embedded_elemdesc(ELEMDESC *edesc)
1316 {
1317     free_embedded_typedesc(&edesc->tdesc);
1318     if(edesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
1319         CoTaskMemFree(edesc->u.paramdesc.pparamdescex);
1320 }
1321
1322 /* ITypeComp */
1323
1324 HRESULT CALLBACK ITypeComp_Bind_Proxy(
1325     ITypeComp* This,
1326     LPOLESTR szName,
1327     ULONG lHashVal,
1328     WORD wFlags,
1329     ITypeInfo** ppTInfo,
1330     DESCKIND* pDescKind,
1331     BINDPTR* pBindPtr)
1332 {
1333   FIXME("not implemented\n");
1334   return E_FAIL;
1335 }
1336
1337 HRESULT __RPC_STUB ITypeComp_Bind_Stub(
1338     ITypeComp* This,
1339     LPOLESTR szName,
1340     ULONG lHashVal,
1341     WORD wFlags,
1342     ITypeInfo** ppTInfo,
1343     DESCKIND* pDescKind,
1344     LPFUNCDESC* ppFuncDesc,
1345     LPVARDESC* ppVarDesc,
1346     ITypeComp** ppTypeComp,
1347     CLEANLOCALSTORAGE* pDummy)
1348 {
1349   FIXME("not implemented\n");
1350   return E_FAIL;
1351 }
1352
1353 HRESULT CALLBACK ITypeComp_BindType_Proxy(
1354     ITypeComp* This,
1355     LPOLESTR szName,
1356     ULONG lHashVal,
1357     ITypeInfo** ppTInfo,
1358     ITypeComp** ppTComp)
1359 {
1360   FIXME("not implemented\n");
1361   return E_FAIL;
1362 }
1363
1364 HRESULT __RPC_STUB ITypeComp_BindType_Stub(
1365     ITypeComp* This,
1366     LPOLESTR szName,
1367     ULONG lHashVal,
1368     ITypeInfo** ppTInfo)
1369 {
1370   FIXME("not implemented\n");
1371   return E_FAIL;
1372 }
1373
1374 /* ITypeInfo */
1375
1376 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
1377     ITypeInfo* This,
1378     TYPEATTR** ppTypeAttr)
1379
1380 {
1381     CLEANLOCALSTORAGE stg;
1382     TRACE("(%p, %p)\n", This, ppTypeAttr);
1383
1384     stg.flags = 0;
1385     stg.pStorage = NULL;
1386     stg.pInterface = NULL;
1387
1388     return ITypeInfo_RemoteGetTypeAttr_Proxy(This, ppTypeAttr, &stg);
1389 }
1390
1391 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
1392     ITypeInfo* This,
1393     LPTYPEATTR* ppTypeAttr,
1394     CLEANLOCALSTORAGE* pDummy)
1395 {
1396     HRESULT hr;
1397     TRACE("(%p, %p)\n", This, ppTypeAttr);
1398
1399     hr = ITypeInfo_GetTypeAttr(This, ppTypeAttr);
1400     if(hr != S_OK)
1401         return hr;
1402
1403     pDummy->flags = CLS_TYPEATTR;
1404     ITypeInfo_AddRef(This);
1405     pDummy->pInterface = (IUnknown*)This;
1406     pDummy->pStorage = ppTypeAttr;
1407     return hr;
1408 }
1409
1410 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
1411     ITypeInfo* This,
1412     UINT index,
1413     FUNCDESC** ppFuncDesc)
1414 {
1415     CLEANLOCALSTORAGE stg;
1416     TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
1417
1418     stg.flags = 0;
1419     stg.pStorage = NULL;
1420     stg.pInterface = NULL;
1421
1422     return ITypeInfo_RemoteGetFuncDesc_Proxy(This, index, ppFuncDesc, &stg);
1423 }
1424
1425 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
1426     ITypeInfo* This,
1427     UINT index,
1428     LPFUNCDESC* ppFuncDesc,
1429     CLEANLOCALSTORAGE* pDummy)
1430 {
1431     HRESULT hr;
1432     TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
1433
1434     hr = ITypeInfo_GetFuncDesc(This, index, ppFuncDesc);
1435     if(hr != S_OK)
1436         return hr;
1437
1438     pDummy->flags = CLS_FUNCDESC;
1439     ITypeInfo_AddRef(This);
1440     pDummy->pInterface = (IUnknown*)This;
1441     pDummy->pStorage = ppFuncDesc;
1442     return hr;
1443 }
1444
1445 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
1446     ITypeInfo* This,
1447     UINT index,
1448     VARDESC** ppVarDesc)
1449 {
1450     CLEANLOCALSTORAGE stg;
1451     TRACE("(%p, %d, %p)\n", This, index, ppVarDesc);
1452
1453     stg.flags = 0;
1454     stg.pStorage = NULL;
1455     stg.pInterface = NULL;
1456
1457     return ITypeInfo_RemoteGetVarDesc_Proxy(This, index, ppVarDesc, &stg);
1458 }
1459
1460 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
1461     ITypeInfo* This,
1462     UINT index,
1463     LPVARDESC* ppVarDesc,
1464     CLEANLOCALSTORAGE* pDummy)
1465 {
1466     HRESULT hr;
1467     TRACE("(%p, %d, %p)\n", This, index, ppVarDesc);
1468
1469     hr = ITypeInfo_GetVarDesc(This, index, ppVarDesc);
1470     if(hr != S_OK)
1471         return hr;
1472
1473     pDummy->flags = CLS_VARDESC;
1474     ITypeInfo_AddRef(This);
1475     pDummy->pInterface = (IUnknown*)This;
1476     pDummy->pStorage = ppVarDesc;
1477     return hr;
1478 }
1479
1480 HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
1481     ITypeInfo* This,
1482     MEMBERID memid,
1483     BSTR* rgBstrNames,
1484     UINT cMaxNames,
1485     UINT* pcNames)
1486 {
1487   FIXME("not implemented\n");
1488   return E_FAIL;
1489 }
1490
1491 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
1492     ITypeInfo* This,
1493     MEMBERID memid,
1494     BSTR* rgBstrNames,
1495     UINT cMaxNames,
1496     UINT* pcNames)
1497 {
1498   FIXME("not implemented\n");
1499   return E_FAIL;
1500 }
1501
1502 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
1503     ITypeInfo* This,
1504     LPOLESTR* rgszNames,
1505     UINT cNames,
1506     MEMBERID* pMemId)
1507 {
1508   FIXME("not implemented\n");
1509   return E_FAIL;
1510 }
1511
1512 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
1513     ITypeInfo* This)
1514 {
1515   FIXME("not implemented\n");
1516   return E_FAIL;
1517 }
1518
1519 HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
1520     ITypeInfo* This,
1521     PVOID pvInstance,
1522     MEMBERID memid,
1523     WORD wFlags,
1524     DISPPARAMS* pDispParams,
1525     VARIANT* pVarResult,
1526     EXCEPINFO* pExcepInfo,
1527     UINT* puArgErr)
1528 {
1529   FIXME("not implemented\n");
1530   return E_FAIL;
1531 }
1532
1533 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
1534     ITypeInfo* This)
1535 {
1536   FIXME("not implemented\n");
1537   return E_FAIL;
1538 }
1539
1540 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(
1541     ITypeInfo* This,
1542     MEMBERID memid,
1543     BSTR* pBstrName,
1544     BSTR* pBstrDocString,
1545     DWORD* pdwHelpContext,
1546     BSTR* pBstrHelpFile)
1547 {
1548     DWORD help_context;
1549     BSTR name, doc_string, help_file;
1550     HRESULT hr;
1551     TRACE("(%p, %08x, %p, %p, %p, %p)\n", This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
1552
1553     /* FIXME: presumably refPtrFlags is supposed to be a bitmask of which ptrs we actually want? */
1554     hr = ITypeInfo_RemoteGetDocumentation_Proxy(This, memid, 0, &name, &doc_string, &help_context, &help_file);
1555     if(SUCCEEDED(hr))
1556     {
1557         if(pBstrName) *pBstrName = name;
1558         else SysFreeString(name);
1559
1560         if(pBstrDocString) *pBstrDocString = doc_string;
1561         else SysFreeString(doc_string);
1562
1563         if(pBstrHelpFile) *pBstrHelpFile = help_file;
1564         else SysFreeString(help_file);
1565
1566         if(pdwHelpContext) *pdwHelpContext = help_context;
1567     }
1568     return hr;
1569 }
1570
1571 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(
1572     ITypeInfo* This,
1573     MEMBERID memid,
1574     DWORD refPtrFlags,
1575     BSTR* pBstrName,
1576     BSTR* pBstrDocString,
1577     DWORD* pdwHelpContext,
1578     BSTR* pBstrHelpFile)
1579 {
1580     TRACE("(%p, %08x, %08x, %p, %p, %p, %p)\n", This, memid, refPtrFlags, pBstrName, pBstrDocString,
1581           pdwHelpContext, pBstrHelpFile);
1582     return ITypeInfo_GetDocumentation(This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
1583 }
1584
1585 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(
1586     ITypeInfo* This,
1587     MEMBERID memid,
1588     INVOKEKIND invKind,
1589     BSTR* pBstrDllName,
1590     BSTR* pBstrName,
1591     WORD* pwOrdinal)
1592 {
1593   FIXME("not implemented\n");
1594   return E_FAIL;
1595 }
1596
1597 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(
1598     ITypeInfo* This,
1599     MEMBERID memid,
1600     INVOKEKIND invKind,
1601     DWORD refPtrFlags,
1602     BSTR* pBstrDllName,
1603     BSTR* pBstrName,
1604     WORD* pwOrdinal)
1605 {
1606   FIXME("not implemented\n");
1607   return E_FAIL;
1608 }
1609
1610 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
1611     ITypeInfo* This,
1612     MEMBERID memid,
1613     INVOKEKIND invKind,
1614     PVOID* ppv)
1615 {
1616   FIXME("not implemented\n");
1617   return E_FAIL;
1618 }
1619
1620 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
1621     ITypeInfo* This)
1622 {
1623   FIXME("not implemented\n");
1624   return E_FAIL;
1625 }
1626
1627 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
1628     ITypeInfo* This,
1629     IUnknown* pUnkOuter,
1630     REFIID riid,
1631     PVOID* ppvObj)
1632 {
1633   FIXME("not implemented\n");
1634   return E_FAIL;
1635 }
1636
1637 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
1638     ITypeInfo* This,
1639     REFIID riid,
1640     IUnknown** ppvObj)
1641 {
1642   FIXME("not implemented\n");
1643   return E_FAIL;
1644 }
1645
1646 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
1647     ITypeInfo* This,
1648     ITypeLib** ppTLib,
1649     UINT* pIndex)
1650 {
1651     ITypeLib *pTL;
1652     UINT index;
1653     HRESULT hr;
1654
1655     TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
1656     
1657     hr = ITypeInfo_RemoteGetContainingTypeLib_Proxy(This, &pTL, &index);
1658     if(SUCCEEDED(hr))
1659     {
1660         if(pIndex)
1661             *pIndex = index;
1662
1663         if(ppTLib)
1664             *ppTLib = pTL;
1665         else
1666             ITypeLib_Release(pTL);
1667     }
1668     return hr;
1669 }
1670
1671 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
1672     ITypeInfo* This,
1673     ITypeLib** ppTLib,
1674     UINT* pIndex)
1675 {
1676     TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
1677     return ITypeInfo_GetContainingTypeLib(This, ppTLib, pIndex);
1678 }
1679
1680 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
1681     ITypeInfo* This,
1682     TYPEATTR* pTypeAttr)
1683 {
1684     TRACE("(%p, %p)\n", This, pTypeAttr);
1685     free_embedded_typedesc(&pTypeAttr->tdescAlias);
1686     CoTaskMemFree(pTypeAttr);
1687 }
1688
1689 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
1690     ITypeInfo* This)
1691 {
1692     TRACE("nothing to do\n");
1693     return S_OK;
1694 }
1695
1696 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
1697     ITypeInfo* This,
1698     FUNCDESC* pFuncDesc)
1699 {
1700     SHORT param;
1701     TRACE("(%p, %p)\n", This, pFuncDesc);
1702
1703     for(param = 0; param < pFuncDesc->cParams; param++)
1704         free_embedded_elemdesc(pFuncDesc->lprgelemdescParam + param);
1705     if(param)
1706         CoTaskMemFree(pFuncDesc->lprgelemdescParam);
1707
1708     free_embedded_elemdesc(&pFuncDesc->elemdescFunc);
1709
1710     if(pFuncDesc->cScodes != 0 && pFuncDesc->cScodes != -1)
1711         CoTaskMemFree(pFuncDesc->lprgscode);
1712
1713     CoTaskMemFree(pFuncDesc);
1714 }
1715
1716 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
1717     ITypeInfo* This)
1718 {
1719     TRACE("nothing to do\n");
1720     return S_OK;
1721 }
1722
1723 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
1724     ITypeInfo* This,
1725     VARDESC* pVarDesc)
1726 {
1727     TRACE("(%p, %p)\n", This, pVarDesc);
1728
1729     CoTaskMemFree(pVarDesc->lpstrSchema);
1730
1731     if(pVarDesc->varkind == VAR_CONST)
1732         CoTaskMemFree(pVarDesc->u.lpvarValue);
1733
1734     free_embedded_elemdesc(&pVarDesc->elemdescVar);
1735     CoTaskMemFree(pVarDesc);
1736 }
1737
1738 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
1739     ITypeInfo* This)
1740 {
1741     TRACE("nothing to do\n");
1742     return S_OK;
1743 }
1744
1745
1746 /* ITypeInfo2 */
1747
1748 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(
1749     ITypeInfo2* This,
1750     MEMBERID memid,
1751     LCID lcid,
1752     BSTR* pbstrHelpString,
1753     DWORD* pdwHelpStringContext,
1754     BSTR* pbstrHelpStringDll)
1755 {
1756   FIXME("not implemented\n");
1757   return E_FAIL;
1758 }
1759
1760 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(
1761     ITypeInfo2* This,
1762     MEMBERID memid,
1763     LCID lcid,
1764     DWORD refPtrFlags,
1765     BSTR* pbstrHelpString,
1766     DWORD* pdwHelpStringContext,
1767     BSTR* pbstrHelpStringDll)
1768 {
1769   FIXME("not implemented\n");
1770   return E_FAIL;
1771 }
1772
1773 /* ITypeLib */
1774
1775 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
1776     ITypeLib* This)
1777 {
1778     UINT count = 0;
1779     TRACE("(%p)\n", This);
1780
1781     ITypeLib_RemoteGetTypeInfoCount_Proxy(This, &count);
1782     
1783     return count;
1784 }
1785
1786 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
1787     ITypeLib* This,
1788     UINT* pcTInfo)
1789 {
1790     TRACE("(%p, %p)\n", This, pcTInfo);
1791     *pcTInfo = ITypeLib_GetTypeInfoCount(This);
1792     return S_OK;
1793 }
1794
1795 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
1796     ITypeLib* This,
1797     TLIBATTR** ppTLibAttr)
1798 {
1799     CLEANLOCALSTORAGE stg;
1800     TRACE("(%p, %p)\n", This, ppTLibAttr);
1801
1802     stg.flags = 0;
1803     stg.pStorage = NULL;
1804     stg.pInterface = NULL;
1805
1806     return ITypeLib_RemoteGetLibAttr_Proxy(This, ppTLibAttr, &stg);    
1807 }
1808
1809 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
1810     ITypeLib* This,
1811     LPTLIBATTR* ppTLibAttr,
1812     CLEANLOCALSTORAGE* pDummy)
1813 {
1814     HRESULT hr;
1815     TRACE("(%p, %p)\n", This, ppTLibAttr);
1816     
1817     hr = ITypeLib_GetLibAttr(This, ppTLibAttr);
1818     if(hr != S_OK)
1819         return hr;
1820
1821     pDummy->flags = CLS_LIBATTR;
1822     ITypeLib_AddRef(This);
1823     pDummy->pInterface = (IUnknown*)This;
1824     pDummy->pStorage = ppTLibAttr;
1825     return hr;
1826 }
1827
1828 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(
1829     ITypeLib* This,
1830     INT index,
1831     BSTR* pBstrName,
1832     BSTR* pBstrDocString,
1833     DWORD* pdwHelpContext,
1834     BSTR* pBstrHelpFile)
1835 {
1836   FIXME("not implemented\n");
1837   return E_FAIL;
1838 }
1839
1840 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(
1841     ITypeLib* This,
1842     INT index,
1843     DWORD refPtrFlags,
1844     BSTR* pBstrName,
1845     BSTR* pBstrDocString,
1846     DWORD* pdwHelpContext,
1847     BSTR* pBstrHelpFile)
1848 {
1849   FIXME("not implemented\n");
1850   return E_FAIL;
1851 }
1852
1853 HRESULT CALLBACK ITypeLib_IsName_Proxy(
1854     ITypeLib* This,
1855     LPOLESTR szNameBuf,
1856     ULONG lHashVal,
1857     BOOL* pfName)
1858 {
1859   FIXME("not implemented\n");
1860   return E_FAIL;
1861 }
1862
1863 HRESULT __RPC_STUB ITypeLib_IsName_Stub(
1864     ITypeLib* This,
1865     LPOLESTR szNameBuf,
1866     ULONG lHashVal,
1867     BOOL* pfName,
1868     BSTR* pBstrLibName)
1869 {
1870   FIXME("not implemented\n");
1871   return E_FAIL;
1872 }
1873
1874 HRESULT CALLBACK ITypeLib_FindName_Proxy(
1875     ITypeLib* This,
1876     LPOLESTR szNameBuf,
1877     ULONG lHashVal,
1878     ITypeInfo** ppTInfo,
1879     MEMBERID* rgMemId,
1880     USHORT* pcFound)
1881 {
1882   FIXME("not implemented\n");
1883   return E_FAIL;
1884 }
1885
1886 HRESULT __RPC_STUB ITypeLib_FindName_Stub(
1887     ITypeLib* This,
1888     LPOLESTR szNameBuf,
1889     ULONG lHashVal,
1890     ITypeInfo** ppTInfo,
1891     MEMBERID* rgMemId,
1892     USHORT* pcFound,
1893     BSTR* pBstrLibName)
1894 {
1895   FIXME("not implemented\n");
1896   return E_FAIL;
1897 }
1898
1899 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
1900     ITypeLib* This,
1901     TLIBATTR* pTLibAttr)
1902 {
1903     TRACE("(%p, %p)\n", This, pTLibAttr);
1904     CoTaskMemFree(pTLibAttr);
1905 }
1906
1907 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
1908     ITypeLib* This)
1909 {
1910     TRACE("nothing to do\n");
1911     return S_OK;
1912 }
1913
1914
1915 /* ITypeLib2 */
1916
1917 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
1918     ITypeLib2* This,
1919     ULONG* pcUniqueNames,
1920     ULONG* pcchUniqueNames)
1921 {
1922   FIXME("not implemented\n");
1923   return E_FAIL;
1924 }
1925
1926 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
1927     ITypeLib2* This,
1928     ULONG* pcUniqueNames,
1929     ULONG* pcchUniqueNames)
1930 {
1931   FIXME("not implemented\n");
1932   return E_FAIL;
1933 }
1934
1935 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(
1936     ITypeLib2* This,
1937     INT index,
1938     LCID lcid,
1939     BSTR* pbstrHelpString,
1940     DWORD* pdwHelpStringContext,
1941     BSTR* pbstrHelpStringDll)
1942 {
1943   FIXME("not implemented\n");
1944   return E_FAIL;
1945 }
1946
1947 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(
1948     ITypeLib2* This,
1949     INT index,
1950     LCID lcid,
1951     DWORD refPtrFlags,
1952     BSTR* pbstrHelpString,
1953     DWORD* pdwHelpStringContext,
1954     BSTR* pbstrHelpStringDll)
1955 {
1956   FIXME("not implemented\n");
1957   return E_FAIL;
1958 }