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