oleaut32: Win64 printf format warning fixes.
[wine] / dlls / oleaut32 / tmarshal.c
1 /*
2  *      TYPELIB Marshaler
3  *
4  *      Copyright 2002,2005     Marcus Meissner
5  *
6  * The olerelay debug channel allows you to see calls marshalled by
7  * the typelib marshaller. It is not a generic COM relaying system.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <ctype.h>
32
33 #define COBJMACROS
34 #define NONAMELESSUNION
35 #define NONAMELESSSTRUCT
36
37 #include "winerror.h"
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winnls.h"
41 #include "winreg.h"
42 #include "winuser.h"
43 #include "excpt.h"
44
45 #include "ole2.h"
46 #include "propidl.h" /* for LPSAFEARRAY_User* functions */
47 #include "typelib.h"
48 #include "variant.h"
49 #include "wine/debug.h"
50 #include "wine/exception.h"
51
52 static const WCHAR IDispatchW[] = { 'I','D','i','s','p','a','t','c','h',0};
53
54 WINE_DEFAULT_DEBUG_CHANNEL(ole);
55 WINE_DECLARE_DEBUG_CHANNEL(olerelay);
56
57 #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
58
59 typedef struct _marshal_state {
60     LPBYTE      base;
61     int         size;
62     int         curoff;
63 } marshal_state;
64
65 /* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */
66 static char *relaystr(WCHAR *in) {
67     char *tmp = (char *)debugstr_w(in);
68     tmp += 2;
69     tmp[strlen(tmp)-1] = '\0';
70     return tmp;
71 }
72
73 static HRESULT
74 xbuf_resize(marshal_state *buf, DWORD newsize)
75 {
76     if(buf->size >= newsize)
77         return S_FALSE;
78
79     if(buf->base)
80     {
81         buf->base = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buf->base, newsize);
82         if(!buf->base)
83             return E_OUTOFMEMORY;
84     }
85     else
86     {
87         buf->base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newsize);
88         if(!buf->base)
89             return E_OUTOFMEMORY;
90     }
91     buf->size = newsize;
92     return S_OK;
93 }
94
95 static HRESULT
96 xbuf_add(marshal_state *buf, LPBYTE stuff, DWORD size)
97 {
98     HRESULT hr;
99
100     if(buf->size - buf->curoff < size)
101     {
102         hr = xbuf_resize(buf, buf->size + size + 100);
103         if(FAILED(hr)) return hr;
104     }
105     memcpy(buf->base+buf->curoff,stuff,size);
106     buf->curoff += size;
107     return S_OK;
108 }
109
110 static HRESULT
111 xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) {
112     if (buf->size < buf->curoff+size) return E_FAIL;
113     memcpy(stuff,buf->base+buf->curoff,size);
114     buf->curoff += size;
115     return S_OK;
116 }
117
118 static HRESULT
119 xbuf_skip(marshal_state *buf, DWORD size) {
120     if (buf->size < buf->curoff+size) return E_FAIL;
121     buf->curoff += size;
122     return S_OK;
123 }
124
125 static HRESULT
126 _unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) {
127     IStream             *pStm;
128     ULARGE_INTEGER      newpos;
129     LARGE_INTEGER       seekto;
130     ULONG               res;
131     HRESULT             hres;
132     DWORD               xsize;
133
134     TRACE("...%s...\n",debugstr_guid(riid));
135     
136     *pUnk = NULL;
137     hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize));
138     if (hres) {
139         ERR("xbuf_get failed\n");
140         return hres;
141     }
142     
143     if (xsize == 0) return S_OK;
144     
145     hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
146     if (hres) {
147         ERR("Stream create failed %x\n",hres);
148         return hres;
149     }
150     
151     hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res);
152     if (hres) {
153         ERR("stream write %x\n",hres);
154         return hres;
155     }
156     
157     memset(&seekto,0,sizeof(seekto));
158     hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
159     if (hres) {
160         ERR("Failed Seek %x\n",hres);
161         return hres;
162     }
163     
164     hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk);
165     if (hres) {
166         ERR("Unmarshalling interface %s failed with %x\n",debugstr_guid(riid),hres);
167         return hres;
168     }
169     
170     IStream_Release(pStm);
171     return xbuf_skip(buf,xsize);
172 }
173
174 static HRESULT
175 _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) {
176     LPBYTE              tempbuf = NULL;
177     IStream             *pStm = NULL;
178     STATSTG             ststg;
179     ULARGE_INTEGER      newpos;
180     LARGE_INTEGER       seekto;
181     ULONG               res;
182     DWORD               xsize;
183     HRESULT             hres;
184
185     if (!pUnk) {
186         /* this is valid, if for instance we serialize
187          * a VT_DISPATCH with NULL ptr which apparently
188          * can happen. S_OK to make sure we continue
189          * serializing.
190          */
191         WARN("pUnk is NULL\n");
192         xsize = 0;
193         return xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
194     }
195
196     hres = E_FAIL;
197
198     TRACE("...%s...\n",debugstr_guid(riid));
199     
200     hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
201     if (hres) {
202         ERR("Stream create failed %x\n",hres);
203         goto fail;
204     }
205     
206     hres = CoMarshalInterface(pStm,riid,pUnk,0,NULL,0);
207     if (hres) {
208         ERR("Marshalling interface %s failed with %x\n", debugstr_guid(riid), hres);
209         goto fail;
210     }
211     
212     hres = IStream_Stat(pStm,&ststg,0);
213     if (hres) {
214         ERR("Stream stat failed\n");
215         goto fail;
216     }
217     
218     tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.u.LowPart);
219     memset(&seekto,0,sizeof(seekto));
220     hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
221     if (hres) {
222         ERR("Failed Seek %x\n",hres);
223         goto fail;
224     }
225     
226     hres = IStream_Read(pStm,tempbuf,ststg.cbSize.u.LowPart,&res);
227     if (hres) {
228         ERR("Failed Read %x\n",hres);
229         goto fail;
230     }
231     
232     xsize = ststg.cbSize.u.LowPart;
233     xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
234     hres = xbuf_add(buf,tempbuf,ststg.cbSize.u.LowPart);
235     
236     HeapFree(GetProcessHeap(),0,tempbuf);
237     IStream_Release(pStm);
238     
239     return hres;
240     
241 fail:
242     xsize = 0;
243     xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
244     if (pStm) IUnknown_Release(pStm);
245     HeapFree(GetProcessHeap(), 0, tempbuf);
246     return hres;
247 }
248
249 /********************* OLE Proxy/Stub Factory ********************************/
250 static HRESULT WINAPI
251 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
252     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {
253         *ppv = (LPVOID)iface;
254         /* No ref counting, static class */
255         return S_OK;
256     }
257     FIXME("(%s) unknown IID?\n",debugstr_guid(iid));
258     return E_NOINTERFACE;
259 }
260
261 static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }
262 static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }
263
264 static HRESULT
265 _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
266     HRESULT     hres;
267     HKEY        ikey;
268     char        tlguid[200],typelibkey[300],interfacekey[300],ver[100];
269     char        tlfn[260];
270     OLECHAR     tlfnW[260];
271     DWORD       tlguidlen, verlen, type;
272     LONG        tlfnlen;
273     ITypeLib    *tl;
274
275     sprintf( interfacekey, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
276         riid->Data1, riid->Data2, riid->Data3,
277         riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
278         riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]
279     );
280
281     if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) {
282         ERR("No %s key found.\n",interfacekey);
283         return E_FAIL;
284     }
285     type = (1<<REG_SZ);
286     tlguidlen = sizeof(tlguid);
287     if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) {
288         ERR("Getting typelib guid failed.\n");
289         RegCloseKey(ikey);
290         return E_FAIL;
291     }
292     type = (1<<REG_SZ);
293     verlen = sizeof(ver);
294     if (RegQueryValueExA(ikey,"Version",NULL,&type,(LPBYTE)ver,&verlen)) {
295         ERR("Could not get version value?\n");
296         RegCloseKey(ikey);
297         return E_FAIL;
298     }
299     RegCloseKey(ikey);
300     sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win32",tlguid,ver);
301     tlfnlen = sizeof(tlfn);
302     if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) {
303         ERR("Could not get typelib fn?\n");
304         return E_FAIL;
305     }
306     MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, sizeof(tlfnW) / sizeof(tlfnW[0]));
307     hres = LoadTypeLib(tlfnW,&tl);
308     if (hres) {
309         ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid));
310         return hres;
311     }
312     hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti);
313     if (hres) {
314         ERR("typelib does not contain info for %s?\n",debugstr_guid(riid));
315         ITypeLib_Release(tl);
316         return hres;
317     }
318     /* FIXME: do this?  ITypeLib_Release(tl); */
319     return hres;
320 }
321
322 /* Determine nr of functions. Since we use the toplevel interface and all
323  * inherited ones have lower numbers, we are ok to not to descent into
324  * the inheritance tree I think.
325  */
326 static int _nroffuncs(ITypeInfo *tinfo) {
327     int         n, max = 0;
328     const FUNCDESC *fdesc;
329     HRESULT     hres;
330
331     n=0;
332     while (1) {
333         hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo,n,&fdesc);
334         if (hres)
335             return max+1;
336         if (fdesc->oVft/4 > max)
337             max = fdesc->oVft/4;
338         n++;
339     }
340     /*NOTREACHED*/
341 }
342
343 #ifdef __i386__
344
345 #include "pshpack1.h"
346
347 typedef struct _TMAsmProxy {
348     BYTE        popleax;
349     BYTE        pushlval;
350     BYTE        nr;
351     BYTE        pushleax;
352     BYTE        lcall;
353     DWORD       xcall;
354     BYTE        lret;
355     WORD        bytestopop;
356 } TMAsmProxy;
357
358 #include "poppack.h"
359
360 #else /* __i386__ */
361 # warning You need to implement stubless proxies for your architecture
362 typedef struct _TMAsmProxy {
363 } TMAsmProxy;
364 #endif
365
366 typedef struct _TMProxyImpl {
367     LPVOID                             *lpvtbl;
368     const IRpcProxyBufferVtbl          *lpvtbl2;
369     LONG                                ref;
370
371     TMAsmProxy                          *asmstubs;
372     ITypeInfo*                          tinfo;
373     IRpcChannelBuffer*                  chanbuf;
374     IID                                 iid;
375     CRITICAL_SECTION    crit;
376     IUnknown                            *outerunknown;
377     IDispatch                           *dispatch;
378     IRpcProxyBuffer                     *dispatch_proxy;
379 } TMProxyImpl;
380
381 static HRESULT WINAPI
382 TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv)
383 {
384     TRACE("()\n");
385     if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {
386         *ppv = (LPVOID)iface;
387         IRpcProxyBuffer_AddRef(iface);
388         return S_OK;
389     }
390     FIXME("no interface for %s\n",debugstr_guid(riid));
391     return E_NOINTERFACE;
392 }
393
394 static ULONG WINAPI
395 TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface)
396 {
397     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
398     ULONG refCount = InterlockedIncrement(&This->ref);
399
400     TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
401
402     return refCount;
403 }
404
405 static ULONG WINAPI
406 TMProxyImpl_Release(LPRPCPROXYBUFFER iface)
407 {
408     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
409     ULONG refCount = InterlockedDecrement(&This->ref);
410
411     TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
412
413     if (!refCount)
414     {
415         if (This->dispatch_proxy) IRpcProxyBuffer_Release(This->dispatch_proxy);
416         DeleteCriticalSection(&This->crit);
417         if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
418         VirtualFree(This->asmstubs, 0, MEM_RELEASE);
419         HeapFree(GetProcessHeap(), 0, This->lpvtbl);
420         CoTaskMemFree(This);
421     }
422     return refCount;
423 }
424
425 static HRESULT WINAPI
426 TMProxyImpl_Connect(
427     LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer)
428 {
429     ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
430
431     TRACE("(%p)\n", pRpcChannelBuffer);
432
433     EnterCriticalSection(&This->crit);
434
435     IRpcChannelBuffer_AddRef(pRpcChannelBuffer);
436     This->chanbuf = pRpcChannelBuffer;
437
438     LeaveCriticalSection(&This->crit);
439
440     if (This->dispatch_proxy)
441         IRpcProxyBuffer_Connect(This->dispatch_proxy, pRpcChannelBuffer);
442
443     return S_OK;
444 }
445
446 static void WINAPI
447 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)
448 {
449     ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
450
451     TRACE("()\n");
452
453     EnterCriticalSection(&This->crit);
454
455     IRpcChannelBuffer_Release(This->chanbuf);
456     This->chanbuf = NULL;
457
458     LeaveCriticalSection(&This->crit);
459
460     if (This->dispatch_proxy)
461         IRpcProxyBuffer_Disconnect(This->dispatch_proxy);
462 }
463
464
465 static const IRpcProxyBufferVtbl tmproxyvtable = {
466     TMProxyImpl_QueryInterface,
467     TMProxyImpl_AddRef,
468     TMProxyImpl_Release,
469     TMProxyImpl_Connect,
470     TMProxyImpl_Disconnect
471 };
472
473 /* how much space do we use on stack in DWORD steps. */
474 int
475 _argsize(DWORD vt) {
476     switch (vt) {
477     case VT_UI8:
478         return 8/sizeof(DWORD);
479     case VT_R8:
480         return sizeof(double)/sizeof(DWORD);
481     case VT_CY:
482         return sizeof(CY)/sizeof(DWORD);
483     case VT_DATE:
484         return sizeof(DATE)/sizeof(DWORD);
485     case VT_VARIANT:
486         return (sizeof(VARIANT)+3)/sizeof(DWORD);
487     default:
488         return 1;
489     }
490 }
491
492 static int
493 _xsize(TYPEDESC *td) {
494     switch (td->vt) {
495     case VT_DATE:
496         return sizeof(DATE);
497     case VT_VARIANT:
498         return sizeof(VARIANT)+3;
499     case VT_CARRAY: {
500         int i, arrsize = 1;
501         ARRAYDESC *adesc = td->u.lpadesc;
502
503         for (i=0;i<adesc->cDims;i++)
504             arrsize *= adesc->rgbounds[i].cElements;
505         return arrsize*_xsize(&adesc->tdescElem);
506     }
507     case VT_UI8:
508     case VT_I8:
509         return 8;
510     case VT_UI2:
511     case VT_I2:
512         return 2;
513     case VT_UI1:
514     case VT_I1:
515         return 1;
516     default:
517         return 4;
518     }
519 }
520
521 static HRESULT
522 serialize_param(
523     ITypeInfo           *tinfo,
524     BOOL                writeit,
525     BOOL                debugout,
526     BOOL                dealloc,
527     TYPEDESC            *tdesc,
528     DWORD               *arg,
529     marshal_state       *buf)
530 {
531     HRESULT hres = S_OK;
532
533     TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt));
534
535     switch (tdesc->vt) {
536     case VT_EMPTY: /* nothing. empty variant for instance */
537         return S_OK;
538     case VT_I8:
539     case VT_UI8:
540     case VT_CY:
541         hres = S_OK;
542         if (debugout) TRACE_(olerelay)("%x%x",arg[0],arg[1]);
543         if (writeit)
544             hres = xbuf_add(buf,(LPBYTE)arg,8);
545         return hres;
546     case VT_BOOL:
547     case VT_ERROR:
548     case VT_INT:
549     case VT_UINT:
550     case VT_I4:
551     case VT_R4:
552     case VT_UI4:
553         hres = S_OK;
554         if (debugout) TRACE_(olerelay)("%x",*arg);
555         if (writeit)
556             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
557         return hres;
558     case VT_I2:
559     case VT_UI2:
560         hres = S_OK;
561         if (debugout) TRACE_(olerelay)("%04x",*arg & 0xffff);
562         if (writeit)
563             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
564         return hres;
565     case VT_I1:
566     case VT_UI1:
567         hres = S_OK;
568         if (debugout) TRACE_(olerelay)("%02x",*arg & 0xff);
569         if (writeit)
570             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
571         return hres;
572     case VT_I4|VT_BYREF:
573         hres = S_OK;
574         if (debugout) TRACE_(olerelay)("&0x%x",*arg);
575         if (writeit)
576             hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));
577         /* do not dealloc at this time */
578         return hres;
579     case VT_VARIANT: {
580         TYPEDESC        tdesc2;
581         VARIANT         *vt = (VARIANT*)arg;
582         DWORD           vttype = V_VT(vt);
583
584         if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
585         tdesc2.vt = vttype;
586         if (writeit) {
587             hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
588             if (hres) return hres;
589         }
590         /* need to recurse since we need to free the stuff */
591         hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,(DWORD*)&(V_I4(vt)),buf);
592         if (debugout) TRACE_(olerelay)(")");
593         return hres;
594     }
595     case VT_BSTR|VT_BYREF: {
596         if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");
597         if (writeit) {
598             /* ptr to ptr to magic widestring, basically */
599             BSTR *bstr = (BSTR *) *arg;
600             DWORD len;
601             if (!*bstr) {
602                 /* -1 means "null string" which is equivalent to empty string */
603                 len = -1;     
604                 hres = xbuf_add(buf, (LPBYTE)&len,sizeof(DWORD));
605                 if (hres) return hres;
606             } else {
607                 len = *((DWORD*)*bstr-1)/sizeof(WCHAR);
608                 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
609                 if (hres) return hres;
610                 hres = xbuf_add(buf,(LPBYTE)*bstr,len * sizeof(WCHAR));
611                 if (hres) return hres;
612             }
613         }
614
615         if (dealloc && arg) {
616             BSTR *str = *((BSTR **)arg);
617             SysFreeString(*str);
618         }
619         return S_OK;
620     }
621     
622     case VT_BSTR: {
623         if (debugout) {
624             if (*arg)
625                    TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));
626             else
627                     TRACE_(olerelay)("<bstr NULL>");
628         }
629         if (writeit) {
630             BSTR bstr = (BSTR)*arg;
631             DWORD len;
632             if (!bstr) {
633                 len = -1;
634                 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
635                 if (hres) return hres;
636             } else {
637                 len = *((DWORD*)bstr-1)/sizeof(WCHAR);
638                 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
639                 if (hres) return hres;
640                 hres = xbuf_add(buf,(LPBYTE)bstr,len * sizeof(WCHAR));
641                 if (hres) return hres;
642             }
643         }
644
645         if (dealloc && arg)
646             SysFreeString((BSTR)*arg);
647         return S_OK;
648     }
649     case VT_PTR: {
650         DWORD cookie;
651         BOOL        derefhere = TRUE;
652
653         if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
654             ITypeInfo   *tinfo2;
655             TYPEATTR    *tattr;
656
657             hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
658             if (hres) {
659                 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
660                 return hres;
661             }
662             ITypeInfo_GetTypeAttr(tinfo2,&tattr);
663             switch (tattr->typekind) {
664             case TKIND_ENUM:    /* confirmed */
665             case TKIND_RECORD:  /* FIXME: mostly untested */
666                 derefhere=TRUE;
667                 break;
668             case TKIND_ALIAS:   /* FIXME: untested */
669             case TKIND_DISPATCH:        /* will be done in VT_USERDEFINED case */
670             case TKIND_INTERFACE:       /* will be done in VT_USERDEFINED case */
671                 derefhere=FALSE;
672                 break;
673             default:
674                 FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
675                 derefhere=FALSE;
676                 break;
677             }
678             ITypeInfo_Release(tinfo2);
679         }
680
681         if (debugout) TRACE_(olerelay)("*");
682         /* Write always, so the other side knows when it gets a NULL pointer.
683          */
684         cookie = *arg ? 0x42424242 : 0;
685         hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
686         if (hres)
687             return hres;
688         if (!*arg) {
689             if (debugout) TRACE_(olerelay)("NULL");
690             return S_OK;
691         }
692         hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);
693         if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
694         return hres;
695     }
696     case VT_UNKNOWN:
697         if (debugout) TRACE_(olerelay)("unk(0x%x)",*arg);
698         if (writeit)
699             hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);
700         if (dealloc && *(IUnknown **)arg)
701             IUnknown_Release((LPUNKNOWN)*arg);
702         return hres;
703     case VT_DISPATCH:
704         if (debugout) TRACE_(olerelay)("idisp(0x%x)",*arg);
705         if (writeit)
706             hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg);
707         if (dealloc && *(IUnknown **)arg)
708             IUnknown_Release((LPUNKNOWN)*arg);
709         return hres;
710     case VT_VOID:
711         if (debugout) TRACE_(olerelay)("<void>");
712         return S_OK;
713     case VT_USERDEFINED: {
714         ITypeInfo       *tinfo2;
715         TYPEATTR        *tattr;
716
717         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
718         if (hres) {
719             ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype);
720             return hres;
721         }
722         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
723         switch (tattr->typekind) {
724         case TKIND_DISPATCH:
725         case TKIND_INTERFACE:
726             if (writeit)
727                hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
728             if (dealloc)
729                 IUnknown_Release((LPUNKNOWN)arg);
730             break;
731         case TKIND_RECORD: {
732             int i;
733             if (debugout) TRACE_(olerelay)("{");
734             for (i=0;i<tattr->cVars;i++) {
735                 VARDESC *vdesc;
736                 ELEMDESC *elem2;
737                 TYPEDESC *tdesc2;
738
739                 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
740                 if (hres) {
741                     ERR("Could not get vardesc of %d\n",i);
742                     return hres;
743                 }
744                 /* Need them for hack below */
745                 /*
746                 memset(names,0,sizeof(names));
747                 hres = ITypeInfo_GetNames(tinfo2,vdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
748                 if (nrofnames > sizeof(names)/sizeof(names[0])) {
749                     ERR("Need more names!\n");
750                 }
751                 if (!hres && debugout)
752                     TRACE_(olerelay)("%s=",relaystr(names[0]));
753                 */
754                 elem2 = &vdesc->elemdescVar;
755                 tdesc2 = &elem2->tdesc;
756                 hres = serialize_param(
757                     tinfo2,
758                     writeit,
759                     debugout,
760                     dealloc,
761                     tdesc2,
762                     (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
763                     buf
764                 );
765                 ITypeInfo_ReleaseVarDesc(tinfo2, vdesc);
766                 if (hres!=S_OK)
767                     return hres;
768                 if (debugout && (i<(tattr->cVars-1)))
769                     TRACE_(olerelay)(",");
770             }
771             if (debugout) TRACE_(olerelay)("}");
772             break;
773         }
774         case TKIND_ALIAS:
775             return serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf);
776         case TKIND_ENUM:
777             hres = S_OK;
778             if (debugout) TRACE_(olerelay)("%x",*arg);
779             if (writeit)
780                 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
781             return hres;
782         default:
783             FIXME("Unhandled typekind %d\n",tattr->typekind);
784             hres = E_FAIL;
785             break;
786         }
787         ITypeInfo_Release(tinfo2);
788         return hres;
789     }
790     case VT_CARRAY: {
791         ARRAYDESC *adesc = tdesc->u.lpadesc;
792         int i, arrsize = 1;
793
794         if (debugout) TRACE_(olerelay)("carr");
795         for (i=0;i<adesc->cDims;i++) {
796             if (debugout) TRACE_(olerelay)("[%d]",adesc->rgbounds[i].cElements);
797             arrsize *= adesc->rgbounds[i].cElements;
798         }
799         if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(adesc->tdescElem.vt));
800         if (debugout) TRACE_(olerelay)("[");
801         for (i=0;i<arrsize;i++) {
802             hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);
803             if (hres)
804                 return hres;
805             if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");
806         }
807         if (debugout) TRACE_(olerelay)("]");
808         return S_OK;
809     }
810     case VT_SAFEARRAY: {
811         if (writeit)
812         {
813             unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
814             unsigned long size = LPSAFEARRAY_UserSize(&flags, buf->curoff, (LPSAFEARRAY *)arg);
815             xbuf_resize(buf, size);
816             LPSAFEARRAY_UserMarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
817             buf->curoff = size;
818         }
819         return S_OK;
820     }
821     default:
822         ERR("Unhandled marshal type %d.\n",tdesc->vt);
823         return S_OK;
824     }
825 }
826
827 static HRESULT
828 deserialize_param(
829     ITypeInfo           *tinfo,
830     BOOL                readit,
831     BOOL                debugout,
832     BOOL                alloc,
833     TYPEDESC            *tdesc,
834     DWORD               *arg,
835     marshal_state       *buf)
836 {
837     HRESULT hres = S_OK;
838
839     TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg);
840
841     while (1) {
842         switch (tdesc->vt) {
843         case VT_EMPTY:
844             if (debugout) TRACE_(olerelay)("<empty>");
845             return S_OK;
846         case VT_NULL:
847             if (debugout) TRACE_(olerelay)("<null>");
848             return S_OK;
849         case VT_VARIANT: {
850             VARIANT     *vt = (VARIANT*)arg;
851
852             if (readit) {
853                 DWORD   vttype;
854                 TYPEDESC        tdesc2;
855                 hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
856                 if (hres) {
857                     FIXME("vt type not read?\n");
858                     return hres;
859                 }
860                 memset(&tdesc2,0,sizeof(tdesc2));
861                 tdesc2.vt = vttype;
862                 V_VT(vt)  = vttype;
863                 if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
864                 hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, (DWORD*)&(V_I4(vt)), buf);
865                 TRACE_(olerelay)(")");
866                 return hres;
867             } else {
868                 VariantInit(vt);
869                 return S_OK;
870             }
871         }
872         case VT_I8:
873         case VT_UI8:
874         case VT_CY:
875             if (readit) {
876                 hres = xbuf_get(buf,(LPBYTE)arg,8);
877                 if (hres) ERR("Failed to read integer 8 byte\n");
878             }
879             if (debugout) TRACE_(olerelay)("%x%x",arg[0],arg[1]);
880             return hres;
881         case VT_ERROR:
882         case VT_BOOL:
883         case VT_I4:
884         case VT_INT:
885         case VT_UINT:
886         case VT_R4:
887         case VT_UI4:
888             if (readit) {
889                 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
890                 if (hres) ERR("Failed to read integer 4 byte\n");
891             }
892             if (debugout) TRACE_(olerelay)("%x",*arg);
893             return hres;
894         case VT_I2:
895         case VT_UI2:
896             if (readit) {
897                 DWORD x;
898                 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
899                 if (hres) ERR("Failed to read integer 4 byte\n");
900                 memcpy(arg,&x,2);
901             }
902             if (debugout) TRACE_(olerelay)("%04x",*arg & 0xffff);
903             return hres;
904         case VT_I1:
905         case VT_UI1:
906             if (readit) {
907                 DWORD x;
908                 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
909                 if (hres) ERR("Failed to read integer 4 byte\n");
910                 memcpy(arg,&x,1);
911             }
912             if (debugout) TRACE_(olerelay)("%02x",*arg & 0xff);
913             return hres;
914         case VT_I4|VT_BYREF:
915             hres = S_OK;
916             if (alloc)
917                 *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
918             if (readit) {
919                 hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));
920                 if (hres) ERR("Failed to read integer 4 byte\n");
921             }
922             if (debugout) TRACE_(olerelay)("&0x%x",*(DWORD*)*arg);
923             return hres;
924         case VT_BSTR|VT_BYREF: {
925             BSTR **bstr = (BSTR **)arg;
926             WCHAR       *str;
927             DWORD       len;
928
929             if (readit) {
930                 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
931                 if (hres) {
932                     ERR("failed to read bstr klen\n");
933                     return hres;
934                 }
935                 if (len == -1) {
936                     *bstr = CoTaskMemAlloc(sizeof(BSTR *));
937                     **bstr = NULL;
938                     if (debugout) TRACE_(olerelay)("<bstr NULL>");
939                 } else {
940                     str  = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
941                     hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
942                     if (hres) {
943                         ERR("Failed to read BSTR.\n");
944                         return hres;
945                     }
946                     *bstr = CoTaskMemAlloc(sizeof(BSTR *));
947                     **bstr = SysAllocStringLen(str,len);
948                     if (debugout) TRACE_(olerelay)("%s",relaystr(str));
949                     HeapFree(GetProcessHeap(),0,str);
950                 }
951             } else {
952                 *bstr = NULL;
953             }
954             return S_OK;
955         }
956         case VT_BSTR: {
957             WCHAR       *str;
958             DWORD       len;
959
960             if (readit) {
961                 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
962                 if (hres) {
963                     ERR("failed to read bstr klen\n");
964                     return hres;
965                 }
966                 if (len == -1) {
967                     *arg = 0;
968                     if (debugout) TRACE_(olerelay)("<bstr NULL>");
969                 } else {
970                     str  = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
971                     hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
972                     if (hres) {
973                         ERR("Failed to read BSTR.\n");
974                         return hres;
975                     }
976                     *arg = (DWORD)SysAllocStringLen(str,len);
977                     if (debugout) TRACE_(olerelay)("%s",relaystr(str));
978                     HeapFree(GetProcessHeap(),0,str);
979                 }
980             } else {
981                 *arg = 0;
982             }
983             return S_OK;
984         }
985         case VT_PTR: {
986             DWORD       cookie;
987             BOOL        derefhere = TRUE;
988
989             if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
990                 ITypeInfo       *tinfo2;
991                 TYPEATTR        *tattr;
992
993                 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
994                 if (hres) {
995                     ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
996                     return hres;
997                 }
998                 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
999                 switch (tattr->typekind) {
1000                 case TKIND_ENUM:        /* confirmed */
1001                 case TKIND_RECORD:      /* FIXME: mostly untested */
1002                     derefhere=TRUE;
1003                     break;
1004                 case TKIND_ALIAS:       /* FIXME: untested */
1005                 case TKIND_DISPATCH:    /* will be done in VT_USERDEFINED case */
1006                 case TKIND_INTERFACE:   /* will be done in VT_USERDEFINED case */
1007                     derefhere=FALSE;
1008                     break;
1009                 default:
1010                     FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
1011                     derefhere=FALSE;
1012                     break;
1013                 }
1014                 ITypeInfo_Release(tinfo2);
1015             }
1016             /* read it in all cases, we need to know if we have 
1017              * NULL pointer or not.
1018              */
1019             hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
1020             if (hres) {
1021                 ERR("Failed to load pointer cookie.\n");
1022                 return hres;
1023             }
1024             if (cookie != 0x42424242) {
1025                 /* we read a NULL ptr from the remote side */
1026                 if (debugout) TRACE_(olerelay)("NULL");
1027                 *arg = 0;
1028                 return S_OK;
1029             }
1030             if (debugout) TRACE_(olerelay)("*");
1031             if (alloc) {
1032                 /* Allocate space for the referenced struct */
1033                 if (derefhere)
1034                     *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));
1035             }
1036             if (derefhere)
1037                 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf);
1038             else
1039                 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf);
1040         }
1041         case VT_UNKNOWN:
1042             /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
1043             if (alloc)
1044                 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
1045             hres = S_OK;
1046             if (readit)
1047                 hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg);
1048             if (debugout)
1049                 TRACE_(olerelay)("unk(%p)",arg);
1050             return hres;
1051         case VT_DISPATCH:
1052             hres = S_OK;
1053             if (readit)
1054                 hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg);
1055             if (debugout)
1056                 TRACE_(olerelay)("idisp(%p)",arg);
1057             return hres;
1058         case VT_VOID:
1059             if (debugout) TRACE_(olerelay)("<void>");
1060             return S_OK;
1061         case VT_USERDEFINED: {
1062             ITypeInfo   *tinfo2;
1063             TYPEATTR    *tattr;
1064
1065             hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
1066             if (hres) {
1067                 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype);
1068                 return hres;
1069             }
1070             hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
1071             if (hres) {
1072                 ERR("Could not get typeattr in VT_USERDEFINED.\n");
1073             } else {
1074                 switch (tattr->typekind) {
1075                 case TKIND_DISPATCH:
1076                 case TKIND_INTERFACE:
1077                     if (readit)
1078                         hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
1079                     break;
1080                 case TKIND_RECORD: {
1081                     int i;
1082
1083                     if (alloc)
1084                         *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);
1085
1086                     if (debugout) TRACE_(olerelay)("{");
1087                     for (i=0;i<tattr->cVars;i++) {
1088                         VARDESC *vdesc;
1089
1090                         hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
1091                         if (hres) {
1092                             ERR("Could not get vardesc of %d\n",i);
1093                             return hres;
1094                         }
1095                         hres = deserialize_param(
1096                             tinfo2,
1097                             readit,
1098                             debugout,
1099                             alloc,
1100                             &vdesc->elemdescVar.tdesc,
1101                             (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst),
1102                             buf
1103                         );
1104                         ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc);
1105                         if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");
1106                     }
1107                     if (debugout) TRACE_(olerelay)("}");
1108                     break;
1109                 }
1110                 case TKIND_ALIAS:
1111                     return deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf);
1112                 case TKIND_ENUM:
1113                     if (readit) {
1114                         hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
1115                         if (hres) ERR("Failed to read enum (4 byte)\n");
1116                     }
1117                     if (debugout) TRACE_(olerelay)("%x",*arg);
1118                     return hres;
1119                 default:
1120                     ERR("Unhandled typekind %d\n",tattr->typekind);
1121                     hres = E_FAIL;
1122                     break;
1123                 }
1124             }
1125             if (hres)
1126                 ERR("failed to stuballoc in TKIND_RECORD.\n");
1127             ITypeInfo_Release(tinfo2);
1128             return hres;
1129         }
1130         case VT_CARRAY: {
1131             /* arg is pointing to the start of the array. */
1132             ARRAYDESC *adesc = tdesc->u.lpadesc;
1133             int         arrsize,i;
1134             arrsize = 1;
1135             if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");
1136             for (i=0;i<adesc->cDims;i++)
1137                 arrsize *= adesc->rgbounds[i].cElements;
1138             for (i=0;i<arrsize;i++)
1139                 deserialize_param(
1140                     tinfo,
1141                     readit,
1142                     debugout,
1143                     alloc,
1144                     &adesc->tdescElem,
1145                     (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)),
1146                     buf
1147                 );
1148             return S_OK;
1149         }
1150     case VT_SAFEARRAY: {
1151             if (readit)
1152             {
1153                 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
1154                 unsigned char *buffer;
1155                 buffer = LPSAFEARRAY_UserUnmarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
1156                 buf->curoff = buffer - buf->base;
1157             }
1158             return S_OK;
1159         }
1160         default:
1161             ERR("No handler for VT type %d!\n",tdesc->vt);
1162             return S_OK;
1163         }
1164     }
1165 }
1166
1167 /* Searches function, also in inherited interfaces */
1168 static HRESULT
1169 _get_funcdesc(
1170     ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
1171 {
1172     int i = 0, j = 0;
1173     HRESULT hres;
1174
1175     if (fname) *fname = NULL;
1176     if (iname) *iname = NULL;
1177
1178     *tactual = tinfo;
1179     ITypeInfo_AddRef(*tactual);
1180
1181     while (1) {
1182         hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i, fdesc);
1183
1184         if (hres) {
1185             ITypeInfo   *tinfo2;
1186             HREFTYPE    href;
1187             TYPEATTR    *attr;
1188
1189             hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
1190             if (hres) {
1191                 ERR("GetTypeAttr failed with %x\n",hres);
1192                 return hres;
1193             }
1194             /* Not found, so look in inherited ifaces. */
1195             for (j=0;j<attr->cImplTypes;j++) {
1196                 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
1197                 if (hres) {
1198                     ERR("Did not find a reftype for interface offset %d?\n",j);
1199                     break;
1200                 }
1201                 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
1202                 if (hres) {
1203                     ERR("Did not find a typeinfo for reftype %d?\n",href);
1204                     continue;
1205                 }
1206                 hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname);
1207                 ITypeInfo_Release(tinfo2);
1208                 if (!hres) return S_OK;
1209             }
1210             return hres;
1211         }
1212         if (((*fdesc)->oVft/4) == iMethod) {
1213             if (fname)
1214                 ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
1215             if (iname)
1216                 ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
1217             return S_OK;
1218         }
1219         i++;
1220     }
1221 }
1222
1223 static DWORD
1224 xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
1225 {
1226     DWORD               *args = ((DWORD*)&tpinfo)+1, *xargs;
1227     const FUNCDESC      *fdesc;
1228     HRESULT             hres;
1229     int                 i, relaydeb = TRACE_ON(olerelay);
1230     marshal_state       buf;
1231     RPCOLEMESSAGE       msg;
1232     ULONG               status;
1233     BSTR                fname,iname;
1234     BSTR                names[10];
1235     UINT                nrofnames;
1236     DWORD               remoteresult = 0;
1237     ITypeInfo           *tinfo;
1238     IRpcChannelBuffer *chanbuf;
1239
1240     EnterCriticalSection(&tpinfo->crit);
1241
1242     hres = _get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname);
1243     if (hres) {
1244         ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
1245         ITypeInfo_Release(tinfo);
1246         LeaveCriticalSection(&tpinfo->crit);
1247         return E_FAIL;
1248     }
1249
1250     if (!tpinfo->chanbuf)
1251     {
1252         WARN("Tried to use disconnected proxy\n");
1253         ITypeInfo_Release(tinfo);
1254         LeaveCriticalSection(&tpinfo->crit);
1255         return RPC_E_DISCONNECTED;
1256     }
1257     chanbuf = tpinfo->chanbuf;
1258     IRpcChannelBuffer_AddRef(chanbuf);
1259
1260     LeaveCriticalSection(&tpinfo->crit);
1261
1262     if (relaydeb) {
1263        TRACE_(olerelay)("->");
1264         if (iname)
1265             TRACE_(olerelay)("%s:",relaystr(iname));
1266         if (fname)
1267             TRACE_(olerelay)("%s(%d)",relaystr(fname),method);
1268         else
1269             TRACE_(olerelay)("%d",method);
1270         TRACE_(olerelay)("(");
1271     }
1272
1273     if (iname) SysFreeString(iname);
1274     if (fname) SysFreeString(fname);
1275
1276     memset(&buf,0,sizeof(buf));
1277
1278     /* normal typelib driven serializing */
1279
1280     /* Need them for hack below */
1281     memset(names,0,sizeof(names));
1282     if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
1283         nrofnames = 0;
1284     if (nrofnames > sizeof(names)/sizeof(names[0]))
1285         ERR("Need more names!\n");
1286
1287     xargs = args;
1288     for (i=0;i<fdesc->cParams;i++) {
1289         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1290         if (relaydeb) {
1291             if (i) TRACE_(olerelay)(",");
1292             if (i+1<nrofnames && names[i+1])
1293                 TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1294         }
1295         /* No need to marshal other data than FIN and any VT_PTR. */
1296         if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags) && (elem->tdesc.vt != VT_PTR)) {
1297             xargs+=_argsize(elem->tdesc.vt);
1298             if (relaydeb) TRACE_(olerelay)("[out]");
1299             continue;
1300         }
1301         hres = serialize_param(
1302             tinfo,
1303             elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
1304             relaydeb,
1305             FALSE,
1306             &elem->tdesc,
1307             xargs,
1308             &buf
1309         );
1310
1311         if (hres) {
1312             ERR("Failed to serialize param, hres %x\n",hres);
1313             break;
1314         }
1315         xargs+=_argsize(elem->tdesc.vt);
1316     }
1317     if (relaydeb) TRACE_(olerelay)(")");
1318
1319     memset(&msg,0,sizeof(msg));
1320     msg.cbBuffer = buf.curoff;
1321     msg.iMethod  = method;
1322     hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid));
1323     if (hres) {
1324         ERR("RpcChannelBuffer GetBuffer failed, %x\n",hres);
1325         goto exit;
1326     }
1327     memcpy(msg.Buffer,buf.base,buf.curoff);
1328     if (relaydeb) TRACE_(olerelay)("\n");
1329     hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status);
1330     if (hres) {
1331         ERR("RpcChannelBuffer SendReceive failed, %x\n",hres);
1332         goto exit;
1333     }
1334
1335     if (relaydeb) TRACE_(olerelay)(" status = %08x (",status);
1336     if (buf.base)
1337         buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
1338     else
1339         buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
1340     buf.size = msg.cbBuffer;
1341     memcpy(buf.base,msg.Buffer,buf.size);
1342     buf.curoff = 0;
1343
1344     /* generic deserializer using typelib description */
1345     xargs = args;
1346     status = S_OK;
1347     for (i=0;i<fdesc->cParams;i++) {
1348         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1349
1350         if (relaydeb) {
1351             if (i) TRACE_(olerelay)(",");
1352             if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1353         }
1354         /* No need to marshal other data than FOUT and any VT_PTR */
1355         if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {
1356             xargs += _argsize(elem->tdesc.vt);
1357             if (relaydeb) TRACE_(olerelay)("[in]");
1358             continue;
1359         }
1360         hres = deserialize_param(
1361             tinfo,
1362             elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1363             relaydeb,
1364             FALSE,
1365             &(elem->tdesc),
1366             xargs,
1367             &buf
1368         );
1369         if (hres) {
1370             ERR("Failed to unmarshall param, hres %x\n",hres);
1371             status = hres;
1372             break;
1373         }
1374         xargs += _argsize(elem->tdesc.vt);
1375     }
1376
1377     hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));
1378     if (hres != S_OK)
1379         goto exit;
1380     if (relaydeb) TRACE_(olerelay)(") = %08x\n", remoteresult);
1381
1382     hres = remoteresult;
1383
1384 exit:
1385     HeapFree(GetProcessHeap(),0,buf.base);
1386     IRpcChannelBuffer_Release(chanbuf);
1387     ITypeInfo_Release(tinfo);
1388     TRACE("-- 0x%08x\n", hres);
1389     return hres;
1390 }
1391
1392 static HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1393 {
1394     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1395
1396     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1397
1398     if (proxy->outerunknown)
1399         return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);
1400
1401     FIXME("No interface\n");
1402     return E_NOINTERFACE;
1403 }
1404
1405 static ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
1406 {
1407     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1408
1409     TRACE("\n");
1410
1411     if (proxy->outerunknown)
1412         return IUnknown_AddRef(proxy->outerunknown);
1413
1414     return 2; /* FIXME */
1415 }
1416
1417 static ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)
1418 {
1419     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1420
1421     TRACE("\n");
1422
1423     if (proxy->outerunknown)
1424         return IUnknown_Release(proxy->outerunknown);
1425
1426     return 1; /* FIXME */
1427 }
1428
1429 static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
1430 {
1431     TMProxyImpl *This = (TMProxyImpl *)iface;
1432
1433     TRACE("(%p)\n", pctinfo);
1434
1435     return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo);
1436 }
1437
1438 static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1439 {
1440     TMProxyImpl *This = (TMProxyImpl *)iface;
1441
1442     TRACE("(%d, %x, %p)\n", iTInfo, lcid, ppTInfo);
1443
1444     return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo);
1445 }
1446
1447 static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
1448 {
1449     TMProxyImpl *This = (TMProxyImpl *)iface;
1450
1451     TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1452
1453     return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames,
1454                                    cNames, lcid, rgDispId);
1455 }
1456
1457 static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1458                                             WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult,
1459                                             EXCEPINFO * pExcepInfo, UINT * puArgErr)
1460 {
1461     TMProxyImpl *This = (TMProxyImpl *)iface;
1462
1463     TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember,
1464           debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
1465           pExcepInfo, puArgErr);
1466
1467     return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid,
1468                             wFlags, pDispParams, pVarResult, pExcepInfo,
1469                             puArgErr);
1470 }
1471
1472 static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf)
1473 {
1474     HRESULT       hr;
1475     CLSID         clsid;
1476
1477     if ((hr = CoGetPSClsid(riid, &clsid)))
1478         return hr;
1479     return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
1480                              &IID_IPSFactoryBuffer, (LPVOID*)facbuf);
1481 }
1482
1483 static HRESULT WINAPI
1484 PSFacBuf_CreateProxy(
1485     LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
1486     IRpcProxyBuffer **ppProxy, LPVOID *ppv)
1487 {
1488     HRESULT     hres;
1489     ITypeInfo   *tinfo;
1490     int         i, nroffuncs;
1491     const FUNCDESC *fdesc;
1492     TMProxyImpl *proxy;
1493     TYPEATTR    *typeattr;
1494
1495     TRACE("(...%s...)\n",debugstr_guid(riid));
1496     hres = _get_typeinfo_for_iid(riid,&tinfo);
1497     if (hres) {
1498         ERR("No typeinfo for %s?\n",debugstr_guid(riid));
1499         return hres;
1500     }
1501     nroffuncs = _nroffuncs(tinfo);
1502     proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
1503     if (!proxy) return E_OUTOFMEMORY;
1504
1505     assert(sizeof(TMAsmProxy) == 12);
1506
1507     proxy->dispatch = NULL;
1508     proxy->dispatch_proxy = NULL;
1509     proxy->outerunknown = pUnkOuter;
1510     proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
1511     if (!proxy->asmstubs) {
1512         ERR("Could not commit pages for proxy thunks\n");
1513         CoTaskMemFree(proxy);
1514         return E_OUTOFMEMORY;
1515     }
1516
1517     InitializeCriticalSection(&proxy->crit);
1518
1519     proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
1520     for (i=0;i<nroffuncs;i++) {
1521         TMAsmProxy      *xasm = proxy->asmstubs+i;
1522
1523         switch (i) {
1524         case 0:
1525                 proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
1526                 break;
1527         case 1:
1528                 proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
1529                 break;
1530         case 2:
1531                 proxy->lpvtbl[i] = ProxyIUnknown_Release;
1532                 break;
1533         default: {
1534                 int j;
1535                 /* nrofargs without This */
1536                 int nrofargs;
1537                 ITypeInfo *tinfo2;
1538                 hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL);
1539                 ITypeInfo_Release(tinfo2);
1540                 if (hres) {
1541                     ERR("GetFuncDesc %x should not fail here.\n",hres);
1542                     return hres;
1543                 }
1544                 /* some args take more than 4 byte on the stack */
1545                 nrofargs = 0;
1546                 for (j=0;j<fdesc->cParams;j++)
1547                     nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
1548
1549 #ifdef __i386__
1550                 if (fdesc->callconv != CC_STDCALL) {
1551                     ERR("calling convention is not stdcall????\n");
1552                     return E_FAIL;
1553                 }
1554 /* popl %eax    -       return ptr
1555  * pushl <nr>
1556  * pushl %eax
1557  * call xCall
1558  * lret <nr> (+4)
1559  *
1560  *
1561  * arg3 arg2 arg1 <method> <returnptr>
1562  */
1563                 xasm->popleax   = 0x58;
1564                 xasm->pushlval  = 0x6a;
1565                 xasm->nr        = i;
1566                 xasm->pushleax  = 0x50;
1567                 xasm->lcall     = 0xe8; /* relative jump */
1568                 xasm->xcall     = (DWORD)xCall;
1569                 xasm->xcall     -= (DWORD)&(xasm->lret);
1570                 xasm->lret      = 0xc2;
1571                 xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
1572                 proxy->lpvtbl[i] = xasm;
1573                 break;
1574 #else
1575                 FIXME("not implemented on non i386\n");
1576                 return E_FAIL;
1577 #endif
1578             }
1579         }
1580     }
1581
1582     /* if we derive from IDispatch then defer to its proxy for its methods */
1583     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
1584     if (hres == S_OK)
1585     {
1586         if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
1587         {
1588             IPSFactoryBuffer *factory_buffer;
1589             hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
1590             if (hres == S_OK)
1591             {
1592                 hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL,
1593                     &IID_IDispatch, &proxy->dispatch_proxy,
1594                     (void **)&proxy->dispatch);
1595                 IPSFactoryBuffer_Release(factory_buffer);
1596             }
1597             if (hres == S_OK)
1598             {
1599                 proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
1600                 proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
1601                 proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
1602                 proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
1603             }
1604         }
1605         ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
1606     }
1607
1608     proxy->lpvtbl2      = &tmproxyvtable;
1609     /* one reference for the proxy */
1610     proxy->ref          = 1;
1611     proxy->tinfo        = tinfo;
1612     memcpy(&proxy->iid,riid,sizeof(*riid));
1613     proxy->chanbuf      = 0;
1614     if (hres == S_OK)
1615     {
1616         *ppv            = (LPVOID)proxy;
1617         *ppProxy                = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
1618         IUnknown_AddRef((IUnknown *)*ppv);
1619         return S_OK;
1620     }
1621     else
1622         TMProxyImpl_Release((IRpcProxyBuffer *)&proxy->lpvtbl2);
1623     return hres;
1624 }
1625
1626 typedef struct _TMStubImpl {
1627     const IRpcStubBufferVtbl   *lpvtbl;
1628     LONG                        ref;
1629
1630     LPUNKNOWN                   pUnk;
1631     ITypeInfo                   *tinfo;
1632     IID                         iid;
1633     IRpcStubBuffer              *dispatch_stub;
1634     BOOL                        dispatch_derivative;
1635 } TMStubImpl;
1636
1637 static HRESULT WINAPI
1638 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
1639 {
1640     if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
1641         *ppv = (LPVOID)iface;
1642         IRpcStubBuffer_AddRef(iface);
1643         return S_OK;
1644     }
1645     FIXME("%s, not supported IID.\n",debugstr_guid(riid));
1646     return E_NOINTERFACE;
1647 }
1648
1649 static ULONG WINAPI
1650 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)
1651 {
1652     TMStubImpl *This = (TMStubImpl *)iface;
1653     ULONG refCount = InterlockedIncrement(&This->ref);
1654         
1655     TRACE("(%p)->(ref before=%u)\n", This, refCount - 1);
1656
1657     return refCount;
1658 }
1659
1660 static ULONG WINAPI
1661 TMStubImpl_Release(LPRPCSTUBBUFFER iface)
1662 {
1663     TMStubImpl *This = (TMStubImpl *)iface;
1664     ULONG refCount = InterlockedDecrement(&This->ref);
1665
1666     TRACE("(%p)->(ref before=%u)\n", This, refCount + 1);
1667
1668     if (!refCount)
1669     {
1670         IRpcStubBuffer_Disconnect(iface);
1671         ITypeInfo_Release(This->tinfo);
1672         if (This->dispatch_stub)
1673             IRpcStubBuffer_Release(This->dispatch_stub);
1674         CoTaskMemFree(This);
1675     }
1676     return refCount;
1677 }
1678
1679 static HRESULT WINAPI
1680 TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
1681 {
1682     TMStubImpl *This = (TMStubImpl *)iface;
1683
1684     TRACE("(%p)->(%p)\n", This, pUnkServer);
1685
1686     IUnknown_AddRef(pUnkServer);
1687     This->pUnk = pUnkServer;
1688
1689     if (This->dispatch_stub)
1690         IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer);
1691
1692     return S_OK;
1693 }
1694
1695 static void WINAPI
1696 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
1697 {
1698     TMStubImpl *This = (TMStubImpl *)iface;
1699
1700     TRACE("(%p)->()\n", This);
1701
1702     if (This->pUnk)
1703     {
1704         IUnknown_Release(This->pUnk);
1705         This->pUnk = NULL;
1706     }
1707
1708     if (This->dispatch_stub)
1709         IRpcStubBuffer_Disconnect(This->dispatch_stub);
1710 }
1711
1712 static HRESULT WINAPI
1713 TMStubImpl_Invoke(
1714     LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
1715 {
1716     int         i;
1717     const FUNCDESC *fdesc;
1718     TMStubImpl *This = (TMStubImpl *)iface;
1719     HRESULT     hres;
1720     DWORD       *args, res, *xargs, nrofargs;
1721     marshal_state       buf;
1722     UINT        nrofnames;
1723     BSTR        names[10];
1724     BSTR        iname = NULL;
1725     ITypeInfo   *tinfo;
1726
1727     TRACE("...\n");
1728
1729     if (xmsg->iMethod < 3) {
1730         ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
1731         return E_UNEXPECTED;
1732     }
1733
1734     if (This->dispatch_derivative && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *))
1735     {
1736         IPSFactoryBuffer *factory_buffer;
1737         hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
1738         if (hres == S_OK)
1739         {
1740             hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch,
1741                 This->pUnk, &This->dispatch_stub);
1742             IPSFactoryBuffer_Release(factory_buffer);
1743         }
1744         if (hres != S_OK)
1745             return hres;
1746         return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf);
1747     }
1748
1749     memset(&buf,0,sizeof(buf));
1750     buf.size    = xmsg->cbBuffer;
1751     buf.base    = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer);
1752     memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer);
1753     buf.curoff  = 0;
1754
1755     hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL);
1756     if (hres) {
1757         ERR("GetFuncDesc on method %d failed with %x\n",xmsg->iMethod,hres);
1758         return hres;
1759     }
1760
1761     if (iname && !lstrcmpW(iname, IDispatchW))
1762     {
1763         ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
1764         ITypeInfo_Release(tinfo);
1765         return E_UNEXPECTED;
1766     }
1767
1768     if (iname) SysFreeString (iname);
1769
1770     /* Need them for hack below */
1771     memset(names,0,sizeof(names));
1772     ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
1773     if (nrofnames > sizeof(names)/sizeof(names[0])) {
1774         ERR("Need more names!\n");
1775     }
1776
1777     /*dump_FUNCDESC(fdesc);*/
1778     nrofargs = 0;
1779     for (i=0;i<fdesc->cParams;i++)
1780         nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
1781     args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
1782     if (!args) return E_OUTOFMEMORY;
1783
1784     /* Allocate all stuff used by call. */
1785     xargs = args+1;
1786     for (i=0;i<fdesc->cParams;i++) {
1787         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1788
1789         hres = deserialize_param(
1790            tinfo,
1791            elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
1792            FALSE,
1793            TRUE,
1794            &(elem->tdesc),
1795            xargs,
1796            &buf
1797         );
1798         xargs += _argsize(elem->tdesc.vt);
1799         if (hres) {
1800             ERR("Failed to deserialize param %s, hres %x\n",relaystr(names[i+1]),hres);
1801             break;
1802         }
1803     }
1804
1805     args[0] = (DWORD)This->pUnk;
1806
1807     __TRY
1808     {
1809         res = _invoke(
1810             (*((FARPROC**)args[0]))[fdesc->oVft/4],
1811             fdesc->callconv,
1812             (xargs-args),
1813             args
1814         );
1815     }
1816     __EXCEPT(NULL)
1817     {
1818         DWORD dwExceptionCode = GetExceptionCode();
1819         ERR("invoke call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode);
1820         if (FAILED(dwExceptionCode))
1821             hres = dwExceptionCode;
1822         else
1823             hres = HRESULT_FROM_WIN32(dwExceptionCode);
1824     }
1825     __ENDTRY
1826
1827     if (hres != S_OK)
1828         return hres;
1829
1830     buf.curoff = 0;
1831
1832     xargs = args+1;
1833     for (i=0;i<fdesc->cParams;i++) {
1834         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1835         hres = serialize_param(
1836            tinfo,
1837            elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1838            FALSE,
1839            TRUE,
1840            &elem->tdesc,
1841            xargs,
1842            &buf
1843         );
1844         xargs += _argsize(elem->tdesc.vt);
1845         if (hres) {
1846             ERR("Failed to stuballoc param, hres %x\n",hres);
1847             break;
1848         }
1849     }
1850
1851     hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
1852     if (hres != S_OK)
1853         return hres;
1854
1855     ITypeInfo_Release(tinfo);
1856     HeapFree(GetProcessHeap(), 0, args);
1857
1858     xmsg->cbBuffer      = buf.curoff;
1859     hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid);
1860     if (hres != S_OK)
1861         ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08x\n", hres);
1862
1863     if (hres == S_OK)
1864         memcpy(xmsg->Buffer, buf.base, buf.curoff);
1865
1866     HeapFree(GetProcessHeap(), 0, buf.base);
1867
1868     TRACE("returning\n");
1869     return hres;
1870 }
1871
1872 static LPRPCSTUBBUFFER WINAPI
1873 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
1874     FIXME("Huh (%s)?\n",debugstr_guid(riid));
1875     return NULL;
1876 }
1877
1878 static ULONG WINAPI
1879 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
1880     TMStubImpl *This = (TMStubImpl *)iface;
1881
1882     FIXME("()\n");
1883     return This->ref; /*FIXME? */
1884 }
1885
1886 static HRESULT WINAPI
1887 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
1888     return E_NOTIMPL;
1889 }
1890
1891 static void WINAPI
1892 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
1893     return;
1894 }
1895
1896 static const IRpcStubBufferVtbl tmstubvtbl = {
1897     TMStubImpl_QueryInterface,
1898     TMStubImpl_AddRef,
1899     TMStubImpl_Release,
1900     TMStubImpl_Connect,
1901     TMStubImpl_Disconnect,
1902     TMStubImpl_Invoke,
1903     TMStubImpl_IsIIDSupported,
1904     TMStubImpl_CountRefs,
1905     TMStubImpl_DebugServerQueryInterface,
1906     TMStubImpl_DebugServerRelease
1907 };
1908
1909 static HRESULT WINAPI
1910 PSFacBuf_CreateStub(
1911     LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
1912     IRpcStubBuffer** ppStub
1913 ) {
1914     HRESULT hres;
1915     ITypeInfo   *tinfo;
1916     TMStubImpl  *stub;
1917     TYPEATTR *typeattr;
1918
1919     TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
1920
1921     hres = _get_typeinfo_for_iid(riid,&tinfo);
1922     if (hres) {
1923         ERR("No typeinfo for %s?\n",debugstr_guid(riid));
1924         return hres;
1925     }
1926
1927     stub = CoTaskMemAlloc(sizeof(TMStubImpl));
1928     if (!stub)
1929         return E_OUTOFMEMORY;
1930     stub->lpvtbl        = &tmstubvtbl;
1931     stub->ref           = 1;
1932     stub->tinfo         = tinfo;
1933     stub->dispatch_stub = NULL;
1934     stub->dispatch_derivative = FALSE;
1935     memcpy(&(stub->iid),riid,sizeof(*riid));
1936     hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
1937     *ppStub             = (LPRPCSTUBBUFFER)stub;
1938     TRACE("IRpcStubBuffer: %p\n", stub);
1939     if (hres)
1940         ERR("Connect to pUnkServer failed?\n");
1941
1942     /* if we derive from IDispatch then defer to its stub for some of its methods */
1943     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
1944     if (hres == S_OK)
1945     {
1946         if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
1947             stub->dispatch_derivative = TRUE;
1948         ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
1949     }
1950
1951     return hres;
1952 }
1953
1954 static const IPSFactoryBufferVtbl psfacbufvtbl = {
1955     PSFacBuf_QueryInterface,
1956     PSFacBuf_AddRef,
1957     PSFacBuf_Release,
1958     PSFacBuf_CreateProxy,
1959     PSFacBuf_CreateStub
1960 };
1961
1962 /* This is the whole PSFactoryBuffer object, just the vtableptr */
1963 static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
1964
1965 /***********************************************************************
1966  *           TMARSHAL_DllGetClassObject
1967  */
1968 HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1969 {
1970     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
1971         *ppv = &lppsfac;
1972         return S_OK;
1973     }
1974     return E_NOINTERFACE;
1975 }