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