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