Added implementation of security.dll.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41
42 /* FIXME: not supposed to be here */
43
44 const CLSID CLSID_PSDispatch = {
45   0x20420, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
46 };
47
48 static CStdPSFactoryBuffer PSFactoryBuffer;
49
50 CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
51
52 extern const ExtendedProxyFileInfo oaidl_ProxyFileInfo;
53
54 const ProxyFileInfo* OLEAUT32_ProxyFileList[] = {
55   &oaidl_ProxyFileInfo,
56   NULL
57 };
58
59 HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
60 {
61   return NdrDllGetClassObject(rclsid, riid, ppv, OLEAUT32_ProxyFileList,
62                               &CLSID_PSDispatch, &PSFactoryBuffer);
63 }
64
65 /* CLEANLOCALSTORAGE */
66 /* I'm not sure how this is supposed to work yet */
67
68 unsigned long WINAPI CLEANLOCALSTORAGE_UserSize(unsigned long *pFlags, unsigned long Start, CLEANLOCALSTORAGE *pstg)
69 {
70   return Start + sizeof(DWORD);
71 }
72
73 unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
74 {
75   *(DWORD*)Buffer = 0;
76   return Buffer + sizeof(DWORD);
77 }
78
79 unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
80 {
81   return Buffer + sizeof(DWORD);
82 }
83
84 void WINAPI CLEANLOCALSTORAGE_UserFree(unsigned long *pFlags, CLEANLOCALSTORAGE *pstr)
85 {
86 }
87
88 /* BSTR */
89
90 unsigned long WINAPI BSTR_UserSize(unsigned long *pFlags, unsigned long Start, BSTR *pstr)
91 {
92   TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
93   if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
94   Start += sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (SysStringLen(*pstr) - 1);
95   TRACE("returning %ld\n", Start);
96   return Start;
97 }
98
99 unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
100 {
101   wireBSTR str = (wireBSTR)Buffer;
102
103   TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
104   if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
105   str->fFlags = 0;
106   str->clSize = SysStringLen(*pstr);
107   if (str->clSize)
108     memcpy(&str->asData, *pstr, sizeof(OLECHAR) * str->clSize);
109   return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
110 }
111
112 unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
113 {
114   wireBSTR str = (wireBSTR)Buffer;
115   TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
116   if (str->clSize) {
117     SysReAllocStringLen(pstr, (OLECHAR*)&str->asData, str->clSize);
118   }
119   else if (*pstr) {
120     SysFreeString(*pstr);
121     *pstr = NULL;
122   }
123   if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
124   return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
125 }
126
127 void WINAPI BSTR_UserFree(unsigned long *pFlags, BSTR *pstr)
128 {
129   TRACE("(%lx,%p) => %p\n", *pFlags, pstr, *pstr);
130   if (*pstr) {
131     SysFreeString(*pstr);
132     *pstr = NULL;
133   }
134 }
135
136 /* VARIANT */
137 /* I'm not too sure how to do this yet */
138
139 #define VARIANT_wiresize sizeof(struct _wireVARIANT)
140
141 static unsigned wire_size(VARTYPE vt)
142 {
143   if (vt & VT_ARRAY) return 0;
144
145   switch (vt & ~VT_BYREF) {
146   case VT_EMPTY:
147   case VT_NULL:
148     return 0;
149   case VT_I1:
150   case VT_UI1:
151     return sizeof(CHAR);
152   case VT_I2:
153   case VT_UI2:
154     return sizeof(SHORT);
155   case VT_I4:
156   case VT_UI4:
157     return sizeof(LONG);
158   case VT_INT:
159   case VT_UINT:
160     return sizeof(INT);
161   case VT_R4:
162     return sizeof(FLOAT);
163   case VT_R8:
164     return sizeof(DOUBLE);
165   case VT_BOOL:
166     return sizeof(VARIANT_BOOL);
167   case VT_ERROR:
168     return sizeof(SCODE);
169   case VT_DATE:
170     return sizeof(DATE);
171   case VT_CY:
172     return sizeof(CY);
173   case VT_DECIMAL:
174     return sizeof(DECIMAL);
175   case VT_BSTR:
176   case VT_VARIANT:
177   case VT_UNKNOWN:
178   case VT_DISPATCH:
179   case VT_SAFEARRAY:
180   case VT_RECORD:
181     return 0;
182   default:
183     FIXME("unhandled VT %d\n", vt);
184     return 0;
185   }
186 }
187
188 static unsigned interface_variant_size(unsigned long *pFlags, REFIID riid, VARIANT *pvar)
189 {
190   ULONG size;
191   HRESULT hr;
192   /* find the buffer size of the marshalled dispatch interface */
193   hr = CoGetMarshalSizeMax(&size, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
194   if (FAILED(hr)) {
195     if (!V_DISPATCH(pvar))
196       WARN("NULL dispatch pointer\n");
197     else
198       ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%lx\n", hr);
199     return 0;
200   }
201   size += sizeof(ULONG); /* we have to store the buffersize in the stream */
202   TRACE("wire-size extra of dispatch variant is %ld\n", size);
203   return size;
204 }
205
206 static unsigned wire_extra(unsigned long *pFlags, VARIANT *pvar)
207 {
208   if (V_ISARRAY(pvar)) {
209     FIXME("wire-size safearray\n");
210     return 0;
211   }
212   switch (V_VT(pvar)) {
213   case VT_BSTR:
214     return BSTR_UserSize(pFlags, 0, &V_BSTR(pvar));
215   case VT_BSTR | VT_BYREF:
216     return BSTR_UserSize(pFlags, 0, V_BSTRREF(pvar));
217   case VT_SAFEARRAY:
218   case VT_SAFEARRAY | VT_BYREF:
219     FIXME("wire-size safearray\n");
220     return 0;
221   case VT_VARIANT | VT_BYREF:
222     return VARIANT_UserSize(pFlags, 0, V_VARIANTREF(pvar));
223   case VT_UNKNOWN:
224     return interface_variant_size(pFlags, &IID_IUnknown, pvar);
225   case VT_DISPATCH:
226     return interface_variant_size(pFlags, &IID_IDispatch, pvar);
227   case VT_RECORD:
228     FIXME("wire-size record\n");
229     return 0;
230   default:
231     return 0;
232   }
233 }
234
235 /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer. returns Buffer on failure, new position otherwise */
236 static unsigned char* interface_variant_marshal(unsigned long *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
237 {
238   IStream *working; 
239   HGLOBAL working_mem;
240   void *working_memlocked;
241   unsigned char *oldpos;
242   ULONG size;
243   HRESULT hr;
244   
245   TRACE("pFlags=%ld, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
246
247   oldpos = Buffer;
248   
249   /* CoMarshalInterface needs a stream, whereas at this level we are operating in terms of buffers.
250    * We create a stream on an HGLOBAL, so we can simply do a memcpy to move it to the buffer.
251    * in rpcrt4/ndr_ole.c, a simple IStream implementation is wrapped around the buffer object,
252    * but that would be overkill here, hence this implementation. We save the size because the unmarshal
253    * code has no way to know how long the marshalled buffer is. */
254
255   size = wire_extra(pFlags, pvar);
256   
257   working_mem = GlobalAlloc(0, size);
258   if (!working_mem) return oldpos;
259
260   hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
261   if (hr != S_OK) {
262     GlobalFree(working_mem);
263     return oldpos;
264   }
265   
266   hr = CoMarshalInterface(working, riid, V_UNKNOWN(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
267   if (hr != S_OK) {
268     IStream_Release(working); /* this also releases the hglobal */
269     return oldpos;
270   }
271
272   working_memlocked = GlobalLock(working_mem);
273   memcpy(Buffer, &size, sizeof(ULONG)); /* copy the buffersize */
274   Buffer += sizeof(ULONG);
275   memcpy(Buffer, working_memlocked, size);
276   GlobalUnlock(working_mem);
277
278   IStream_Release(working);
279
280   TRACE("done, size=%ld\n", sizeof(ULONG) + size);
281   return Buffer + sizeof(ULONG) + size;
282 }
283
284 /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer. returns Buffer on failure, new position otherwise */
285 static unsigned char *interface_variant_unmarshal(unsigned long *pFlags, unsigned char *Buffer, REFIID riid, VARIANT *pvar)
286 {
287   IStream *working;
288   HGLOBAL working_mem;
289   void *working_memlocked;
290   unsigned char *oldpos;
291   ULONG size;
292   HRESULT hr;
293   
294   TRACE("pFlags=%ld, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
295
296   oldpos = Buffer;
297   
298   /* get the buffersize */
299   memcpy(&size, Buffer, sizeof(ULONG));
300   TRACE("buffersize=%ld\n", size);
301   Buffer += sizeof(ULONG);
302   
303   working_mem = GlobalAlloc(0, size);
304   if (!working_mem) return oldpos;
305
306   hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
307   if (hr != S_OK) {
308     GlobalFree(working_mem);
309     return oldpos;
310   }
311
312   working_memlocked = GlobalLock(working_mem);
313   
314   /* now we copy the contents of the marshalling buffer to working_memlocked, unlock it, and demarshal the stream */
315   memcpy(working_memlocked, Buffer, size);
316   GlobalUnlock(working_mem);
317
318   hr = CoUnmarshalInterface(working, riid, (void**)&V_UNKNOWN(pvar));
319   if (hr != S_OK) {
320     IStream_Release(working);
321     return oldpos;
322   }
323
324   IStream_Release(working); /* this also frees the underlying hglobal */
325
326   TRACE("done, processed=%ld bytes\n", sizeof(ULONG) + size);
327   return Buffer + sizeof(ULONG) + size;
328 }
329
330
331 unsigned long WINAPI VARIANT_UserSize(unsigned long *pFlags, unsigned long Start, VARIANT *pvar)
332 {
333   TRACE("(%lx,%ld,%p)\n", *pFlags, Start, pvar);
334   TRACE("vt=%04x\n", V_VT(pvar));
335   Start += VARIANT_wiresize + wire_extra(pFlags, pvar);
336   TRACE("returning %ld\n", Start);
337   return Start;
338 }
339
340 unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
341 {
342   wireVARIANT var = (wireVARIANT)Buffer;
343   unsigned size, extra;
344   unsigned char *Pos = Buffer + VARIANT_wiresize;
345
346   TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
347   TRACE("vt=%04x\n", V_VT(pvar));
348
349   memset(var, 0, sizeof(*var));
350   var->clSize = sizeof(*var);
351   var->vt = pvar->n1.n2.vt;
352
353   var->rpcReserved = var->vt;
354   if ((var->vt & VT_ARRAY) ||
355       ((var->vt & VT_TYPEMASK) == VT_SAFEARRAY))
356     var->vt = VT_ARRAY | (var->vt & VT_BYREF);
357
358   if (var->vt == VT_DECIMAL) {
359     /* special case because decVal is on a different level */
360     var->u.decVal = pvar->n1.decVal;
361     return Pos;
362   }
363
364   size = wire_size(V_VT(pvar));
365   extra = wire_extra(pFlags, pvar);
366   var->wReserved1 = pvar->n1.n2.wReserved1;
367   var->wReserved2 = pvar->n1.n2.wReserved2;
368   var->wReserved3 = pvar->n1.n2.wReserved3;
369   if (size) {
370     if (var->vt & VT_BYREF)
371       memcpy(&var->u.cVal, pvar->n1.n2.n3.byref, size);
372     else
373       memcpy(&var->u.cVal, &pvar->n1.n2.n3, size);
374   }
375   if (!extra) return Pos;
376
377   switch (var->vt) {
378   case VT_BSTR:
379     Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
380     break;
381   case VT_BSTR | VT_BYREF:
382     Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
383     break;
384   case VT_VARIANT | VT_BYREF:
385     Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
386     break;
387   case VT_DISPATCH | VT_BYREF:
388     FIXME("handle DISPATCH by ref\n");
389     break;
390   case VT_UNKNOWN:
391     /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
392     Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar);
393     break;
394   case VT_DISPATCH:
395     /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
396     Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar);
397     break;
398   case VT_RECORD:
399     FIXME("handle BRECORD by val\n");
400     break;
401   case VT_RECORD | VT_BYREF:
402     FIXME("handle BRECORD by ref\n");
403     break;
404   default:
405     FIXME("handle unknown complex type\n");
406     break;
407   }
408   var->clSize = Pos - Buffer;
409   TRACE("marshalled size=%ld\n", var->clSize);
410   return Pos;
411 }
412
413 unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
414 {
415   wireVARIANT var = (wireVARIANT)Buffer;
416   unsigned size;
417   unsigned char *Pos = Buffer + VARIANT_wiresize;
418
419   TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
420   VariantInit(pvar);
421   pvar->n1.n2.vt = var->rpcReserved;
422   TRACE("marshalled: clSize=%ld, vt=%04x\n", var->clSize, var->vt);
423   TRACE("vt=%04x\n", V_VT(pvar));
424   TRACE("reserved: %d, %d, %d\n", var->wReserved1, var->wReserved2, var->wReserved3);
425   TRACE("val: %ld\n", var->u.lVal);
426
427   if (var->vt == VT_DECIMAL) {
428     /* special case because decVal is on a different level */
429     pvar->n1.decVal = var->u.decVal;
430     return Pos;
431   }
432
433   size = wire_size(V_VT(pvar));
434   pvar->n1.n2.wReserved1 = var->wReserved1;
435   pvar->n1.n2.wReserved2 = var->wReserved2;
436   pvar->n1.n2.wReserved3 = var->wReserved3;
437   if (size) {
438     if (var->vt & VT_BYREF) {
439       pvar->n1.n2.n3.byref = CoTaskMemAlloc(size);
440       memcpy(pvar->n1.n2.n3.byref, &var->u.cVal, size);
441     }
442     else
443       memcpy(&pvar->n1.n2.n3, &var->u.cVal, size);
444   }
445   if (var->clSize <= VARIANT_wiresize) return Pos;
446
447   switch (var->vt) {
448   case VT_BSTR:
449     Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
450     break;
451   case VT_BSTR | VT_BYREF:
452     pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(BSTR));
453     *(BSTR*)pvar->n1.n2.n3.byref = NULL;
454     Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
455     break;
456   case VT_VARIANT | VT_BYREF:
457     pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(VARIANT));
458     Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
459     break;
460   case VT_RECORD:
461     FIXME("handle BRECORD by val\n");
462     break;
463   case VT_RECORD | VT_BYREF:
464     FIXME("handle BRECORD by ref\n");
465     break;
466   case VT_UNKNOWN:
467     Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar);
468     break;
469   case VT_DISPATCH:
470     Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar);
471     break;
472   case VT_DISPATCH | VT_BYREF:
473     FIXME("handle DISPATCH by ref\n");
474   default:
475     FIXME("handle unknown complex type\n");
476     break;
477   }
478   if (Pos != Buffer + var->clSize) {
479     ERR("size difference during unmarshal\n");
480   }
481   return Buffer + var->clSize;
482 }
483
484 void WINAPI VARIANT_UserFree(unsigned long *pFlags, VARIANT *pvar)
485 {
486   VARTYPE vt = V_VT(pvar);
487   PVOID ref = NULL;
488
489   TRACE("(%lx,%p)\n", *pFlags, pvar);
490   TRACE("vt=%04x\n", V_VT(pvar));
491
492   if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
493
494   VariantClear(pvar);
495   if (!ref) return;
496
497   switch (vt) {
498   case VT_BSTR | VT_BYREF:
499     BSTR_UserFree(pFlags, ref);
500     break;
501   case VT_VARIANT | VT_BYREF:
502     VARIANT_UserFree(pFlags, ref);
503     break;
504   case VT_RECORD | VT_BYREF:
505     FIXME("handle BRECORD by ref\n");
506     break;
507   case VT_UNKNOWN:
508   case VT_DISPATCH:
509     IUnknown_Release(V_UNKNOWN(pvar));
510     break;
511   default:
512     FIXME("handle unknown complex type\n");
513     break;
514   }
515
516   CoTaskMemFree(ref);
517 }
518
519 /* IDispatch */
520 /* exactly how Invoke is marshalled is not very clear to me yet,
521  * but the way I've done it seems to work for me */
522
523 HRESULT CALLBACK IDispatch_Invoke_Proxy(
524     IDispatch* This,
525     DISPID dispIdMember,
526     REFIID riid,
527     LCID lcid,
528     WORD wFlags,
529     DISPPARAMS* pDispParams,
530     VARIANT* pVarResult,
531     EXCEPINFO* pExcepInfo,
532     UINT* puArgErr)
533 {
534   HRESULT hr;
535   VARIANT VarResult;
536   UINT* rgVarRefIdx = NULL;
537   VARIANTARG* rgVarRef = NULL;
538   UINT u, cVarRef;
539   UINT uArgErr;
540   EXCEPINFO ExcepInfo;
541
542   TRACE("(%p)->(%ld,%s,%lx,%x,%p,%p,%p,%p)\n", This,
543         dispIdMember, debugstr_guid(riid),
544         lcid, wFlags, pDispParams, pVarResult,
545         pExcepInfo, puArgErr);
546
547   /* [out] args can't be null, use dummy vars if needed */
548   if (!pVarResult) pVarResult = &VarResult;
549   if (!puArgErr) puArgErr = &uArgErr;
550   if (!pExcepInfo) pExcepInfo = &ExcepInfo;
551
552   /* count by-ref args */
553   for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
554     VARIANTARG* arg = &pDispParams->rgvarg[u];
555     if (V_ISBYREF(arg)) {
556       cVarRef++;
557     }
558   }
559   if (cVarRef) {
560     rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
561     rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
562     /* make list of by-ref args */
563     for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
564       VARIANTARG* arg = &pDispParams->rgvarg[u];
565       if (V_ISBYREF(arg)) {
566         rgVarRefIdx[cVarRef] = u;
567         VariantInit(&rgVarRef[cVarRef]);
568         cVarRef++;
569       }
570     }
571   } else {
572     /* [out] args still can't be null,
573      * but we can point these anywhere in this case,
574      * since they won't be written to when cVarRef is 0 */
575     rgVarRefIdx = puArgErr;
576     rgVarRef = pVarResult;
577   }
578   TRACE("passed by ref: %d args\n", cVarRef);
579   hr = IDispatch_RemoteInvoke_Proxy(This,
580                                     dispIdMember,
581                                     riid,
582                                     lcid,
583                                     wFlags,
584                                     pDispParams,
585                                     pVarResult,
586                                     pExcepInfo,
587                                     puArgErr,
588                                     cVarRef,
589                                     rgVarRefIdx,
590                                     rgVarRef);
591   if (cVarRef) {
592     for (u=0; u<cVarRef; u++) {
593       unsigned i = rgVarRefIdx[u];
594       VariantCopy(&pDispParams->rgvarg[i],
595                   &rgVarRef[u]);
596       VariantClear(&rgVarRef[u]);
597     }
598     CoTaskMemFree(rgVarRef);
599     CoTaskMemFree(rgVarRefIdx);
600   }
601
602   if(pExcepInfo == &ExcepInfo)
603   {
604     SysFreeString(pExcepInfo->bstrSource);
605     SysFreeString(pExcepInfo->bstrDescription);
606     SysFreeString(pExcepInfo->bstrHelpFile);
607   }
608   return hr;
609 }
610
611 HRESULT __RPC_STUB IDispatch_Invoke_Stub(
612     IDispatch* This,
613     DISPID dispIdMember,
614     REFIID riid,
615     LCID lcid,
616     DWORD dwFlags,
617     DISPPARAMS* pDispParams,
618     VARIANT* pVarResult,
619     EXCEPINFO* pExcepInfo,
620     UINT* pArgErr,
621     UINT cVarRef,
622     UINT* rgVarRefIdx,
623     VARIANTARG* rgVarRef)
624 {
625   HRESULT hr = S_OK;
626   VARIANTARG *rgvarg, *arg;
627   UINT u;
628
629   /* initialize out parameters, so that they can be marshalled
630    * in case the real Invoke doesn't initialize them */
631   VariantInit(pVarResult);
632   memset(pExcepInfo, 0, sizeof(*pExcepInfo));
633   *pArgErr = 0;
634
635   /* let the real Invoke operate on a copy of the in parameters,
636    * so we don't risk losing pointers to allocated memory */
637   rgvarg = pDispParams->rgvarg;
638   arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
639   if (!arg) return E_OUTOFMEMORY;
640
641   /* init all args so we can call VariantClear on all the args if the copy
642    * below fails */
643   for (u = 0; u < pDispParams->cArgs; u++)
644     VariantInit(&arg[u]);
645
646   for (u = 0; u < pDispParams->cArgs; u++) {
647     hr = VariantCopy(&arg[u], &rgvarg[u]);
648     if (FAILED(hr))
649         break;
650   }
651
652   if (SUCCEEDED(hr)) {
653     pDispParams->rgvarg = arg;
654
655     hr = IDispatch_Invoke(This,
656                           dispIdMember,
657                           riid,
658                           lcid,
659                           dwFlags,
660                           pDispParams,
661                           pVarResult,
662                           pExcepInfo,
663                           pArgErr);
664
665     /* copy ref args to out list */
666     for (u=0; u<cVarRef; u++) {
667       unsigned i = rgVarRefIdx[u];
668       VariantInit(&rgVarRef[u]);
669       VariantCopy(&rgVarRef[u], &arg[i]);
670       /* clear original if equal, to avoid double-free */
671       if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
672         VariantClear(&rgvarg[i]);
673     }
674   }
675
676   /* clear the duplicate argument list */
677   for (u=0; u<pDispParams->cArgs; u++)
678     VariantClear(&arg[u]);
679
680   pDispParams->rgvarg = rgvarg;
681   CoTaskMemFree(arg);
682
683   return hr;
684 }
685
686 /* IEnumVARIANT */
687
688 HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
689     IEnumVARIANT* This,
690     ULONG celt,
691     VARIANT* rgVar,
692     ULONG* pCeltFetched)
693 {
694   ULONG fetched;
695   if (!pCeltFetched)
696     pCeltFetched = &fetched;
697   return IEnumVARIANT_RemoteNext_Proxy(This,
698                                        celt,
699                                        rgVar,
700                                        pCeltFetched);
701 }
702
703 HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
704     IEnumVARIANT* This,
705     ULONG celt,
706     VARIANT* rgVar,
707     ULONG* pCeltFetched)
708 {
709   HRESULT hr;
710   *pCeltFetched = 0;
711   hr = IEnumVARIANT_Next(This,
712                          celt,
713                          rgVar,
714                          pCeltFetched);
715   if (hr == S_OK) *pCeltFetched = celt;
716   return hr;
717 }
718
719 /* ITypeComp */
720
721 HRESULT CALLBACK ITypeComp_Bind_Proxy(
722     ITypeComp* This,
723     LPOLESTR szName,
724     ULONG lHashVal,
725     WORD wFlags,
726     ITypeInfo** ppTInfo,
727     DESCKIND* pDescKind,
728     BINDPTR* pBindPtr)
729 {
730   FIXME("not implemented\n");
731   return E_FAIL;
732 }
733
734 HRESULT __RPC_STUB ITypeComp_Bind_Stub(
735     ITypeComp* This,
736     LPOLESTR szName,
737     ULONG lHashVal,
738     WORD wFlags,
739     ITypeInfo** ppTInfo,
740     DESCKIND* pDescKind,
741     LPFUNCDESC* ppFuncDesc,
742     LPVARDESC* ppVarDesc,
743     ITypeComp** ppTypeComp,
744     CLEANLOCALSTORAGE* pDummy)
745 {
746   FIXME("not implemented\n");
747   return E_FAIL;
748 }
749
750 HRESULT CALLBACK ITypeComp_BindType_Proxy(
751     ITypeComp* This,
752     LPOLESTR szName,
753     ULONG lHashVal,
754     ITypeInfo** ppTInfo,
755     ITypeComp** ppTComp)
756 {
757   FIXME("not implemented\n");
758   return E_FAIL;
759 }
760
761 HRESULT __RPC_STUB ITypeComp_BindType_Stub(
762     ITypeComp* This,
763     LPOLESTR szName,
764     ULONG lHashVal,
765     ITypeInfo** ppTInfo)
766 {
767   FIXME("not implemented\n");
768   return E_FAIL;
769 }
770
771 /* ITypeInfo */
772
773 HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
774     ITypeInfo* This,
775     TYPEATTR** ppTypeAttr)
776 {
777   FIXME("not implemented\n");
778   return E_FAIL;
779 }
780
781 HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
782     ITypeInfo* This,
783     LPTYPEATTR* ppTypeAttr,
784     CLEANLOCALSTORAGE* pDummy)
785 {
786   FIXME("not implemented\n");
787   return E_FAIL;
788 }
789
790 HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
791     ITypeInfo* This,
792     UINT index,
793     FUNCDESC** ppFuncDesc)
794 {
795   FIXME("not implemented\n");
796   return E_FAIL;
797 }
798
799 HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
800     ITypeInfo* This,
801     UINT index,
802     LPFUNCDESC* ppFuncDesc,
803     CLEANLOCALSTORAGE* pDummy)
804 {
805   FIXME("not implemented\n");
806   return E_FAIL;
807 }
808
809 HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
810     ITypeInfo* This,
811     UINT index,
812     VARDESC** ppVarDesc)
813 {
814   FIXME("not implemented\n");
815   return E_FAIL;
816 }
817
818 HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
819     ITypeInfo* This,
820     UINT index,
821     LPVARDESC* ppVarDesc,
822     CLEANLOCALSTORAGE* pDummy)
823 {
824   FIXME("not implemented\n");
825   return E_FAIL;
826 }
827
828 HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
829     ITypeInfo* This,
830     MEMBERID memid,
831     BSTR* rgBstrNames,
832     UINT cMaxNames,
833     UINT* pcNames)
834 {
835   FIXME("not implemented\n");
836   return E_FAIL;
837 }
838
839 HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
840     ITypeInfo* This,
841     MEMBERID memid,
842     BSTR* rgBstrNames,
843     UINT cMaxNames,
844     UINT* pcNames)
845 {
846   FIXME("not implemented\n");
847   return E_FAIL;
848 }
849
850 HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
851     ITypeInfo* This,
852     LPOLESTR* rgszNames,
853     UINT cNames,
854     MEMBERID* pMemId)
855 {
856   FIXME("not implemented\n");
857   return E_FAIL;
858 }
859
860 HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
861     ITypeInfo* This)
862 {
863   FIXME("not implemented\n");
864   return E_FAIL;
865 }
866
867 HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
868     ITypeInfo* This,
869     PVOID pvInstance,
870     MEMBERID memid,
871     WORD wFlags,
872     DISPPARAMS* pDispParams,
873     VARIANT* pVarResult,
874     EXCEPINFO* pExcepInfo,
875     UINT* puArgErr)
876 {
877   FIXME("not implemented\n");
878   return E_FAIL;
879 }
880
881 HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
882     ITypeInfo* This)
883 {
884   FIXME("not implemented\n");
885   return E_FAIL;
886 }
887
888 HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(
889     ITypeInfo* This,
890     MEMBERID memid,
891     BSTR* pBstrName,
892     BSTR* pBstrDocString,
893     DWORD* pdwHelpContext,
894     BSTR* pBstrHelpFile)
895 {
896   FIXME("not implemented\n");
897   return E_FAIL;
898 }
899
900 HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(
901     ITypeInfo* This,
902     MEMBERID memid,
903     DWORD refPtrFlags,
904     BSTR* pBstrName,
905     BSTR* pBstrDocString,
906     DWORD* pdwHelpContext,
907     BSTR* pBstrHelpFile)
908 {
909   FIXME("not implemented\n");
910   return E_FAIL;
911 }
912
913 HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(
914     ITypeInfo* This,
915     MEMBERID memid,
916     INVOKEKIND invKind,
917     BSTR* pBstrDllName,
918     BSTR* pBstrName,
919     WORD* pwOrdinal)
920 {
921   FIXME("not implemented\n");
922   return E_FAIL;
923 }
924
925 HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(
926     ITypeInfo* This,
927     MEMBERID memid,
928     INVOKEKIND invKind,
929     DWORD refPtrFlags,
930     BSTR* pBstrDllName,
931     BSTR* pBstrName,
932     WORD* pwOrdinal)
933 {
934   FIXME("not implemented\n");
935   return E_FAIL;
936 }
937
938 HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
939     ITypeInfo* This,
940     MEMBERID memid,
941     INVOKEKIND invKind,
942     PVOID* ppv)
943 {
944   FIXME("not implemented\n");
945   return E_FAIL;
946 }
947
948 HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
949     ITypeInfo* This)
950 {
951   FIXME("not implemented\n");
952   return E_FAIL;
953 }
954
955 HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
956     ITypeInfo* This,
957     IUnknown* pUnkOuter,
958     REFIID riid,
959     PVOID* ppvObj)
960 {
961   FIXME("not implemented\n");
962   return E_FAIL;
963 }
964
965 HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
966     ITypeInfo* This,
967     REFIID riid,
968     IUnknown** ppvObj)
969 {
970   FIXME("not implemented\n");
971   return E_FAIL;
972 }
973
974 HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
975     ITypeInfo* This,
976     ITypeLib** ppTLib,
977     UINT* pIndex)
978 {
979     ITypeLib *pTL;
980     UINT index;
981     HRESULT hr;
982
983     TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
984     
985     hr = ITypeInfo_RemoteGetContainingTypeLib_Proxy(This, &pTL, &index);
986     if(SUCCEEDED(hr))
987     {
988         if(pIndex)
989             *pIndex = index;
990
991         if(ppTLib)
992             *ppTLib = pTL;
993         else
994             ITypeLib_Release(pTL);
995     }
996     return hr;
997 }
998
999 HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
1000     ITypeInfo* This,
1001     ITypeLib** ppTLib,
1002     UINT* pIndex)
1003 {
1004     TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex );
1005     return ITypeInfo_GetContainingTypeLib(This, ppTLib, pIndex);
1006 }
1007
1008 void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
1009     ITypeInfo* This,
1010     TYPEATTR* pTypeAttr)
1011 {
1012   FIXME("not implemented\n");
1013 }
1014
1015 HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
1016     ITypeInfo* This)
1017 {
1018   FIXME("not implemented\n");
1019   return E_FAIL;
1020 }
1021
1022 void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
1023     ITypeInfo* This,
1024     FUNCDESC* pFuncDesc)
1025 {
1026   FIXME("not implemented\n");
1027 }
1028
1029 HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
1030     ITypeInfo* This)
1031 {
1032   FIXME("not implemented\n");
1033   return E_FAIL;
1034 }
1035
1036 void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
1037     ITypeInfo* This,
1038     VARDESC* pVarDesc)
1039 {
1040   FIXME("not implemented\n");
1041 }
1042
1043 HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
1044     ITypeInfo* This)
1045 {
1046   FIXME("not implemented\n");
1047   return E_FAIL;
1048 }
1049
1050
1051 /* ITypeInfo2 */
1052
1053 HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(
1054     ITypeInfo2* This,
1055     MEMBERID memid,
1056     LCID lcid,
1057     BSTR* pbstrHelpString,
1058     DWORD* pdwHelpStringContext,
1059     BSTR* pbstrHelpStringDll)
1060 {
1061   FIXME("not implemented\n");
1062   return E_FAIL;
1063 }
1064
1065 HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(
1066     ITypeInfo2* This,
1067     MEMBERID memid,
1068     LCID lcid,
1069     DWORD refPtrFlags,
1070     BSTR* pbstrHelpString,
1071     DWORD* pdwHelpStringContext,
1072     BSTR* pbstrHelpStringDll)
1073 {
1074   FIXME("not implemented\n");
1075   return E_FAIL;
1076 }
1077
1078 /* ITypeLib */
1079
1080 UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
1081     ITypeLib* This)
1082 {
1083     UINT count = 0;
1084     TRACE("(%p)\n", This);
1085
1086     ITypeLib_RemoteGetTypeInfoCount_Proxy(This, &count);
1087     
1088     return count;
1089 }
1090
1091 HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
1092     ITypeLib* This,
1093     UINT* pcTInfo)
1094 {
1095     TRACE("(%p, %p)\n", This, pcTInfo);
1096     *pcTInfo = ITypeLib_GetTypeInfoCount(This);
1097     return S_OK;
1098 }
1099
1100 HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
1101     ITypeLib* This,
1102     TLIBATTR** ppTLibAttr)
1103 {
1104     CLEANLOCALSTORAGE stg;
1105     TRACE("(%p, %p)\n", This, ppTLibAttr);
1106     return ITypeLib_RemoteGetLibAttr_Proxy(This, ppTLibAttr, &stg);    
1107 }
1108
1109 HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
1110     ITypeLib* This,
1111     LPTLIBATTR* ppTLibAttr,
1112     CLEANLOCALSTORAGE* pDummy)
1113 {
1114     TRACE("(%p, %p)\n", This, ppTLibAttr);
1115     return ITypeLib_GetLibAttr(This, ppTLibAttr);
1116 }
1117
1118 HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(
1119     ITypeLib* This,
1120     INT index,
1121     BSTR* pBstrName,
1122     BSTR* pBstrDocString,
1123     DWORD* pdwHelpContext,
1124     BSTR* pBstrHelpFile)
1125 {
1126   FIXME("not implemented\n");
1127   return E_FAIL;
1128 }
1129
1130 HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(
1131     ITypeLib* This,
1132     INT index,
1133     DWORD refPtrFlags,
1134     BSTR* pBstrName,
1135     BSTR* pBstrDocString,
1136     DWORD* pdwHelpContext,
1137     BSTR* pBstrHelpFile)
1138 {
1139   FIXME("not implemented\n");
1140   return E_FAIL;
1141 }
1142
1143 HRESULT CALLBACK ITypeLib_IsName_Proxy(
1144     ITypeLib* This,
1145     LPOLESTR szNameBuf,
1146     ULONG lHashVal,
1147     BOOL* pfName)
1148 {
1149   FIXME("not implemented\n");
1150   return E_FAIL;
1151 }
1152
1153 HRESULT __RPC_STUB ITypeLib_IsName_Stub(
1154     ITypeLib* This,
1155     LPOLESTR szNameBuf,
1156     ULONG lHashVal,
1157     BOOL* pfName,
1158     BSTR* pBstrLibName)
1159 {
1160   FIXME("not implemented\n");
1161   return E_FAIL;
1162 }
1163
1164 HRESULT CALLBACK ITypeLib_FindName_Proxy(
1165     ITypeLib* This,
1166     LPOLESTR szNameBuf,
1167     ULONG lHashVal,
1168     ITypeInfo** ppTInfo,
1169     MEMBERID* rgMemId,
1170     USHORT* pcFound)
1171 {
1172   FIXME("not implemented\n");
1173   return E_FAIL;
1174 }
1175
1176 HRESULT __RPC_STUB ITypeLib_FindName_Stub(
1177     ITypeLib* This,
1178     LPOLESTR szNameBuf,
1179     ULONG lHashVal,
1180     ITypeInfo** ppTInfo,
1181     MEMBERID* rgMemId,
1182     USHORT* pcFound,
1183     BSTR* pBstrLibName)
1184 {
1185   FIXME("not implemented\n");
1186   return E_FAIL;
1187 }
1188
1189 void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
1190     ITypeLib* This,
1191     TLIBATTR* pTLibAttr)
1192 {
1193     TRACE("(%p, %p)\n", This, pTLibAttr);
1194     CoTaskMemFree(pTLibAttr);
1195 }
1196
1197 HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
1198     ITypeLib* This)
1199 {
1200     TRACE("nothing to do\n");
1201     return S_OK;
1202 }
1203
1204
1205 /* ITypeLib2 */
1206
1207 HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
1208     ITypeLib2* This,
1209     ULONG* pcUniqueNames,
1210     ULONG* pcchUniqueNames)
1211 {
1212   FIXME("not implemented\n");
1213   return E_FAIL;
1214 }
1215
1216 HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
1217     ITypeLib2* This,
1218     ULONG* pcUniqueNames,
1219     ULONG* pcchUniqueNames)
1220 {
1221   FIXME("not implemented\n");
1222   return E_FAIL;
1223 }
1224
1225 HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(
1226     ITypeLib2* This,
1227     INT index,
1228     LCID lcid,
1229     BSTR* pbstrHelpString,
1230     DWORD* pdwHelpStringContext,
1231     BSTR* pbstrHelpStringDll)
1232 {
1233   FIXME("not implemented\n");
1234   return E_FAIL;
1235 }
1236
1237 HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(
1238     ITypeLib2* This,
1239     INT index,
1240     LCID lcid,
1241     DWORD refPtrFlags,
1242     BSTR* pbstrHelpString,
1243     DWORD* pdwHelpStringContext,
1244     BSTR* pbstrHelpStringDll)
1245 {
1246   FIXME("not implemented\n");
1247   return E_FAIL;
1248 }