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