wined3d: Simplify some uses of the WineD3D_Context object.
[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\\{%08x-%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     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         ITypeInfo_Release(This->tinfo);
421         CoTaskMemFree(This);
422     }
423     return refCount;
424 }
425
426 static HRESULT WINAPI
427 TMProxyImpl_Connect(
428     LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer)
429 {
430     ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
431
432     TRACE("(%p)\n", pRpcChannelBuffer);
433
434     EnterCriticalSection(&This->crit);
435
436     IRpcChannelBuffer_AddRef(pRpcChannelBuffer);
437     This->chanbuf = pRpcChannelBuffer;
438
439     LeaveCriticalSection(&This->crit);
440
441     if (This->dispatch_proxy)
442         IRpcProxyBuffer_Connect(This->dispatch_proxy, pRpcChannelBuffer);
443
444     return S_OK;
445 }
446
447 static void WINAPI
448 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)
449 {
450     ICOM_THIS_MULTI(TMProxyImpl, lpvtbl2, iface);
451
452     TRACE("()\n");
453
454     EnterCriticalSection(&This->crit);
455
456     IRpcChannelBuffer_Release(This->chanbuf);
457     This->chanbuf = NULL;
458
459     LeaveCriticalSection(&This->crit);
460
461     if (This->dispatch_proxy)
462         IRpcProxyBuffer_Disconnect(This->dispatch_proxy);
463 }
464
465
466 static const IRpcProxyBufferVtbl tmproxyvtable = {
467     TMProxyImpl_QueryInterface,
468     TMProxyImpl_AddRef,
469     TMProxyImpl_Release,
470     TMProxyImpl_Connect,
471     TMProxyImpl_Disconnect
472 };
473
474 /* how much space do we use on stack in DWORD steps. */
475 int
476 _argsize(DWORD vt) {
477     switch (vt) {
478     case VT_UI8:
479         return 8/sizeof(DWORD);
480     case VT_R8:
481         return sizeof(double)/sizeof(DWORD);
482     case VT_CY:
483         return sizeof(CY)/sizeof(DWORD);
484     case VT_DATE:
485         return sizeof(DATE)/sizeof(DWORD);
486     case VT_VARIANT:
487         return (sizeof(VARIANT)+3)/sizeof(DWORD);
488     default:
489         return 1;
490     }
491 }
492
493 static int
494 _xsize(TYPEDESC *td) {
495     switch (td->vt) {
496     case VT_DATE:
497         return sizeof(DATE);
498     case VT_VARIANT:
499         return sizeof(VARIANT)+3;
500     case VT_CARRAY: {
501         int i, arrsize = 1;
502         ARRAYDESC *adesc = td->u.lpadesc;
503
504         for (i=0;i<adesc->cDims;i++)
505             arrsize *= adesc->rgbounds[i].cElements;
506         return arrsize*_xsize(&adesc->tdescElem);
507     }
508     case VT_UI8:
509     case VT_I8:
510         return 8;
511     case VT_UI2:
512     case VT_I2:
513         return 2;
514     case VT_UI1:
515     case VT_I1:
516         return 1;
517     default:
518         return 4;
519     }
520 }
521
522 static HRESULT
523 serialize_param(
524     ITypeInfo           *tinfo,
525     BOOL                writeit,
526     BOOL                debugout,
527     BOOL                dealloc,
528     TYPEDESC            *tdesc,
529     DWORD               *arg,
530     marshal_state       *buf)
531 {
532     HRESULT hres = S_OK;
533
534     TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc->vt));
535
536     switch (tdesc->vt) {
537     case VT_EMPTY: /* nothing. empty variant for instance */
538         return S_OK;
539     case VT_I8:
540     case VT_UI8:
541     case VT_CY:
542         hres = S_OK;
543         if (debugout) TRACE_(olerelay)("%x%x\n",arg[0],arg[1]);
544         if (writeit)
545             hres = xbuf_add(buf,(LPBYTE)arg,8);
546         return hres;
547     case VT_BOOL:
548     case VT_ERROR:
549     case VT_INT:
550     case VT_UINT:
551     case VT_I4:
552     case VT_R4:
553     case VT_UI4:
554         hres = S_OK;
555         if (debugout) TRACE_(olerelay)("%x\n",*arg);
556         if (writeit)
557             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
558         return hres;
559     case VT_I2:
560     case VT_UI2:
561         hres = S_OK;
562         if (debugout) TRACE_(olerelay)("%04x\n",*arg & 0xffff);
563         if (writeit)
564             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
565         return hres;
566     case VT_I1:
567     case VT_UI1:
568         hres = S_OK;
569         if (debugout) TRACE_(olerelay)("%02x\n",*arg & 0xff);
570         if (writeit)
571             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
572         return hres;
573     case VT_I4|VT_BYREF:
574         hres = S_OK;
575         if (debugout) TRACE_(olerelay)("&0x%x\n",*arg);
576         if (writeit)
577             hres = xbuf_add(buf,(LPBYTE)(DWORD*)*arg,sizeof(DWORD));
578         /* do not dealloc at this time */
579         return hres;
580     case VT_VARIANT: {
581         TYPEDESC        tdesc2;
582         VARIANT         *vt = (VARIANT*)arg;
583         DWORD           vttype = V_VT(vt);
584
585         if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
586         tdesc2.vt = vttype;
587         if (writeit) {
588             hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
589             if (hres) return hres;
590         }
591         /* need to recurse since we need to free the stuff */
592         hres = serialize_param(tinfo,writeit,debugout,dealloc,&tdesc2,(DWORD*)&(V_I4(vt)),buf);
593         if (debugout) TRACE_(olerelay)(")");
594         return hres;
595     }
596     case VT_BSTR|VT_BYREF: {
597         if (debugout) TRACE_(olerelay)("[byref]'%s'", *(BSTR*)*arg ? relaystr(*((BSTR*)*arg)) : "<bstr NULL>");
598         if (writeit) {
599             /* ptr to ptr to magic widestring, basically */
600             BSTR *bstr = (BSTR *) *arg;
601             DWORD len;
602             if (!*bstr) {
603                 /* -1 means "null string" which is equivalent to empty string */
604                 len = -1;     
605                 hres = xbuf_add(buf, (LPBYTE)&len,sizeof(DWORD));
606                 if (hres) return hres;
607             } else {
608                 len = *((DWORD*)*bstr-1)/sizeof(WCHAR);
609                 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
610                 if (hres) return hres;
611                 hres = xbuf_add(buf,(LPBYTE)*bstr,len * sizeof(WCHAR));
612                 if (hres) return hres;
613             }
614         }
615
616         if (dealloc && arg) {
617             BSTR *str = *((BSTR **)arg);
618             SysFreeString(*str);
619         }
620         return S_OK;
621     }
622     
623     case VT_BSTR: {
624         if (debugout) {
625             if (*arg)
626                    TRACE_(olerelay)("%s",relaystr((WCHAR*)*arg));
627             else
628                     TRACE_(olerelay)("<bstr NULL>");
629         }
630         if (writeit) {
631             BSTR bstr = (BSTR)*arg;
632             DWORD len;
633             if (!bstr) {
634                 len = -1;
635                 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
636                 if (hres) return hres;
637             } else {
638                 len = *((DWORD*)bstr-1)/sizeof(WCHAR);
639                 hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
640                 if (hres) return hres;
641                 hres = xbuf_add(buf,(LPBYTE)bstr,len * sizeof(WCHAR));
642                 if (hres) return hres;
643             }
644         }
645
646         if (dealloc && arg)
647             SysFreeString((BSTR)*arg);
648         return S_OK;
649     }
650     case VT_PTR: {
651         DWORD cookie;
652         BOOL        derefhere = TRUE;
653
654         if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
655             ITypeInfo   *tinfo2;
656             TYPEATTR    *tattr;
657
658             hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
659             if (hres) {
660                 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
661                 return hres;
662             }
663             ITypeInfo_GetTypeAttr(tinfo2,&tattr);
664             switch (tattr->typekind) {
665             case TKIND_ENUM:    /* confirmed */
666             case TKIND_RECORD:  /* FIXME: mostly untested */
667                 derefhere=TRUE;
668                 break;
669             case TKIND_ALIAS:   /* FIXME: untested */
670             case TKIND_DISPATCH:        /* will be done in VT_USERDEFINED case */
671             case TKIND_INTERFACE:       /* will be done in VT_USERDEFINED case */
672                 derefhere=FALSE;
673                 break;
674             default:
675                 FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
676                 derefhere=FALSE;
677                 break;
678             }
679             ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
680             ITypeInfo_Release(tinfo2);
681         }
682
683         if (debugout) TRACE_(olerelay)("*");
684         /* Write always, so the other side knows when it gets a NULL pointer.
685          */
686         cookie = *arg ? 0x42424242 : 0;
687         hres = xbuf_add(buf,(LPBYTE)&cookie,sizeof(cookie));
688         if (hres)
689             return hres;
690         if (!*arg) {
691             if (debugout) TRACE_(olerelay)("NULL");
692             return S_OK;
693         }
694         hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);
695         if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
696         return hres;
697     }
698     case VT_UNKNOWN:
699         if (debugout) TRACE_(olerelay)("unk(0x%x)",*arg);
700         if (writeit)
701             hres = _marshal_interface(buf,&IID_IUnknown,(LPUNKNOWN)*arg);
702         if (dealloc && *(IUnknown **)arg)
703             IUnknown_Release((LPUNKNOWN)*arg);
704         return hres;
705     case VT_DISPATCH:
706         if (debugout) TRACE_(olerelay)("idisp(0x%x)",*arg);
707         if (writeit)
708             hres = _marshal_interface(buf,&IID_IDispatch,(LPUNKNOWN)*arg);
709         if (dealloc && *(IUnknown **)arg)
710             IUnknown_Release((LPUNKNOWN)*arg);
711         return hres;
712     case VT_VOID:
713         if (debugout) TRACE_(olerelay)("<void>");
714         return S_OK;
715     case VT_USERDEFINED: {
716         ITypeInfo       *tinfo2;
717         TYPEATTR        *tattr;
718
719         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
720         if (hres) {
721             ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype);
722             return hres;
723         }
724         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
725         switch (tattr->typekind) {
726         case TKIND_DISPATCH:
727         case TKIND_INTERFACE:
728             if (writeit)
729                hres=_marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
730             if (dealloc)
731                 IUnknown_Release((LPUNKNOWN)arg);
732             break;
733         case TKIND_RECORD: {
734             int i;
735             if (debugout) TRACE_(olerelay)("{");
736             for (i=0;i<tattr->cVars;i++) {
737                 VARDESC *vdesc;
738                 ELEMDESC *elem2;
739                 TYPEDESC *tdesc2;
740
741                 hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
742                 if (hres) {
743                     ERR("Could not get vardesc of %d\n",i);
744                     return hres;
745                 }
746                 elem2 = &vdesc->elemdescVar;
747                 tdesc2 = &elem2->tdesc;
748                 hres = serialize_param(
749                     tinfo2,
750                     writeit,
751                     debugout,
752                     dealloc,
753                     tdesc2,
754                     (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
755                     buf
756                 );
757                 ITypeInfo_ReleaseVarDesc(tinfo2, vdesc);
758                 if (hres!=S_OK)
759                     return hres;
760                 if (debugout && (i<(tattr->cVars-1)))
761                     TRACE_(olerelay)(",");
762             }
763             if (debugout) TRACE_(olerelay)("}");
764             break;
765         }
766         case TKIND_ALIAS:
767             hres = serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf);
768             break;
769         case TKIND_ENUM:
770             hres = S_OK;
771             if (debugout) TRACE_(olerelay)("%x",*arg);
772             if (writeit)
773                 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
774             break;
775         default:
776             FIXME("Unhandled typekind %d\n",tattr->typekind);
777             hres = E_FAIL;
778             break;
779         }
780         ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
781         ITypeInfo_Release(tinfo2);
782         return hres;
783     }
784     case VT_CARRAY: {
785         ARRAYDESC *adesc = tdesc->u.lpadesc;
786         int i, arrsize = 1;
787
788         if (debugout) TRACE_(olerelay)("carr");
789         for (i=0;i<adesc->cDims;i++) {
790             if (debugout) TRACE_(olerelay)("[%d]",adesc->rgbounds[i].cElements);
791             arrsize *= adesc->rgbounds[i].cElements;
792         }
793         if (debugout) TRACE_(olerelay)("(vt %s)",debugstr_vt(adesc->tdescElem.vt));
794         if (debugout) TRACE_(olerelay)("[");
795         for (i=0;i<arrsize;i++) {
796             hres = serialize_param(tinfo, writeit, debugout, dealloc, &adesc->tdescElem, (DWORD*)((LPBYTE)arg+i*_xsize(&adesc->tdescElem)), buf);
797             if (hres)
798                 return hres;
799             if (debugout && (i<arrsize-1)) TRACE_(olerelay)(",");
800         }
801         if (debugout) TRACE_(olerelay)("]");
802         return S_OK;
803     }
804     case VT_SAFEARRAY: {
805         if (writeit)
806         {
807             unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
808             unsigned long size = LPSAFEARRAY_UserSize(&flags, buf->curoff, (LPSAFEARRAY *)arg);
809             xbuf_resize(buf, size);
810             LPSAFEARRAY_UserMarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
811             buf->curoff = size;
812         }
813         return S_OK;
814     }
815     default:
816         ERR("Unhandled marshal type %d.\n",tdesc->vt);
817         return S_OK;
818     }
819 }
820
821 static HRESULT
822 deserialize_param(
823     ITypeInfo           *tinfo,
824     BOOL                readit,
825     BOOL                debugout,
826     BOOL                alloc,
827     TYPEDESC            *tdesc,
828     DWORD               *arg,
829     marshal_state       *buf)
830 {
831     HRESULT hres = S_OK;
832
833     TRACE("vt %s at %p\n",debugstr_vt(tdesc->vt),arg);
834
835     while (1) {
836         switch (tdesc->vt) {
837         case VT_EMPTY:
838             if (debugout) TRACE_(olerelay)("<empty>\n");
839             return S_OK;
840         case VT_NULL:
841             if (debugout) TRACE_(olerelay)("<null>\n");
842             return S_OK;
843         case VT_VARIANT: {
844             VARIANT     *vt = (VARIANT*)arg;
845
846             if (readit) {
847                 DWORD   vttype;
848                 TYPEDESC        tdesc2;
849                 hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
850                 if (hres) {
851                     FIXME("vt type not read?\n");
852                     return hres;
853                 }
854                 memset(&tdesc2,0,sizeof(tdesc2));
855                 tdesc2.vt = vttype;
856                 V_VT(vt)  = vttype;
857                 if (debugout) TRACE_(olerelay)("Vt(%s%s)(",debugstr_vt(vttype),debugstr_vf(vttype));
858                 hres = deserialize_param(tinfo, readit, debugout, alloc, &tdesc2, (DWORD*)&(V_I4(vt)), buf);
859                 TRACE_(olerelay)(")");
860                 return hres;
861             } else {
862                 VariantInit(vt);
863                 return S_OK;
864             }
865         }
866         case VT_I8:
867         case VT_UI8:
868         case VT_CY:
869             if (readit) {
870                 hres = xbuf_get(buf,(LPBYTE)arg,8);
871                 if (hres) ERR("Failed to read integer 8 byte\n");
872             }
873             if (debugout) TRACE_(olerelay)("%x%x",arg[0],arg[1]);
874             return hres;
875         case VT_ERROR:
876         case VT_BOOL:
877         case VT_I4:
878         case VT_INT:
879         case VT_UINT:
880         case VT_R4:
881         case VT_UI4:
882             if (readit) {
883                 hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
884                 if (hres) ERR("Failed to read integer 4 byte\n");
885             }
886             if (debugout) TRACE_(olerelay)("%x",*arg);
887             return hres;
888         case VT_I2:
889         case VT_UI2:
890             if (readit) {
891                 DWORD x;
892                 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
893                 if (hres) ERR("Failed to read integer 4 byte\n");
894                 memcpy(arg,&x,2);
895             }
896             if (debugout) TRACE_(olerelay)("%04x",*arg & 0xffff);
897             return hres;
898         case VT_I1:
899         case VT_UI1:
900             if (readit) {
901                 DWORD x;
902                 hres = xbuf_get(buf,(LPBYTE)&x,sizeof(DWORD));
903                 if (hres) ERR("Failed to read integer 4 byte\n");
904                 memcpy(arg,&x,1);
905             }
906             if (debugout) TRACE_(olerelay)("%02x",*arg & 0xff);
907             return hres;
908         case VT_I4|VT_BYREF:
909             hres = S_OK;
910             if (alloc)
911                 *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
912             if (readit) {
913                 hres = xbuf_get(buf,(LPBYTE)*arg,sizeof(DWORD));
914                 if (hres) ERR("Failed to read integer 4 byte\n");
915             }
916             if (debugout) TRACE_(olerelay)("&0x%x",*(DWORD*)*arg);
917             return hres;
918         case VT_BSTR|VT_BYREF: {
919             BSTR **bstr = (BSTR **)arg;
920             WCHAR       *str;
921             DWORD       len;
922
923             if (readit) {
924                 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
925                 if (hres) {
926                     ERR("failed to read bstr klen\n");
927                     return hres;
928                 }
929                 if (len == -1) {
930                     *bstr = CoTaskMemAlloc(sizeof(BSTR *));
931                     **bstr = NULL;
932                     if (debugout) TRACE_(olerelay)("<bstr NULL>");
933                 } else {
934                     str  = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
935                     hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
936                     if (hres) {
937                         ERR("Failed to read BSTR.\n");
938                         return hres;
939                     }
940                     *bstr = CoTaskMemAlloc(sizeof(BSTR *));
941                     **bstr = SysAllocStringLen(str,len);
942                     if (debugout) TRACE_(olerelay)("%s",relaystr(str));
943                     HeapFree(GetProcessHeap(),0,str);
944                 }
945             } else {
946                 *bstr = NULL;
947             }
948             return S_OK;
949         }
950         case VT_BSTR: {
951             WCHAR       *str;
952             DWORD       len;
953
954             if (readit) {
955                 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
956                 if (hres) {
957                     ERR("failed to read bstr klen\n");
958                     return hres;
959                 }
960                 if (len == -1) {
961                     *arg = 0;
962                     if (debugout) TRACE_(olerelay)("<bstr NULL>");
963                 } else {
964                     str  = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
965                     hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
966                     if (hres) {
967                         ERR("Failed to read BSTR.\n");
968                         return hres;
969                     }
970                     *arg = (DWORD)SysAllocStringLen(str,len);
971                     if (debugout) TRACE_(olerelay)("%s",relaystr(str));
972                     HeapFree(GetProcessHeap(),0,str);
973                 }
974             } else {
975                 *arg = 0;
976             }
977             return S_OK;
978         }
979         case VT_PTR: {
980             DWORD       cookie;
981             BOOL        derefhere = TRUE;
982
983             if (tdesc->u.lptdesc->vt == VT_USERDEFINED) {
984                 ITypeInfo       *tinfo2;
985                 TYPEATTR        *tattr;
986
987                 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.lptdesc->u.hreftype,&tinfo2);
988                 if (hres) {
989                     ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.lptdesc->u.hreftype);
990                     return hres;
991                 }
992                 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
993                 switch (tattr->typekind) {
994                 case TKIND_ENUM:        /* confirmed */
995                 case TKIND_RECORD:      /* FIXME: mostly untested */
996                     derefhere=TRUE;
997                     break;
998                 case TKIND_ALIAS:       /* FIXME: untested */
999                 case TKIND_DISPATCH:    /* will be done in VT_USERDEFINED case */
1000                 case TKIND_INTERFACE:   /* will be done in VT_USERDEFINED case */
1001                     derefhere=FALSE;
1002                     break;
1003                 default:
1004                     FIXME("unhandled switch cases tattr->typekind %d\n", tattr->typekind);
1005                     derefhere=FALSE;
1006                     break;
1007                 }
1008                 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
1009                 ITypeInfo_Release(tinfo2);
1010             }
1011             /* read it in all cases, we need to know if we have 
1012              * NULL pointer or not.
1013              */
1014             hres = xbuf_get(buf,(LPBYTE)&cookie,sizeof(cookie));
1015             if (hres) {
1016                 ERR("Failed to load pointer cookie.\n");
1017                 return hres;
1018             }
1019             if (cookie != 0x42424242) {
1020                 /* we read a NULL ptr from the remote side */
1021                 if (debugout) TRACE_(olerelay)("NULL");
1022                 *arg = 0;
1023                 return S_OK;
1024             }
1025             if (debugout) TRACE_(olerelay)("*");
1026             if (alloc) {
1027                 /* Allocate space for the referenced struct */
1028                 if (derefhere)
1029                     *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,_xsize(tdesc->u.lptdesc));
1030             }
1031             if (derefhere)
1032                 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, (LPDWORD)*arg, buf);
1033             else
1034                 return deserialize_param(tinfo, readit, debugout, alloc, tdesc->u.lptdesc, arg, buf);
1035         }
1036         case VT_UNKNOWN:
1037             /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
1038             if (alloc)
1039                 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
1040             hres = S_OK;
1041             if (readit)
1042                 hres = _unmarshal_interface(buf,&IID_IUnknown,(LPUNKNOWN*)arg);
1043             if (debugout)
1044                 TRACE_(olerelay)("unk(%p)",arg);
1045             return hres;
1046         case VT_DISPATCH:
1047             hres = S_OK;
1048             if (readit)
1049                 hres = _unmarshal_interface(buf,&IID_IDispatch,(LPUNKNOWN*)arg);
1050             if (debugout)
1051                 TRACE_(olerelay)("idisp(%p)",arg);
1052             return hres;
1053         case VT_VOID:
1054             if (debugout) TRACE_(olerelay)("<void>");
1055             return S_OK;
1056         case VT_USERDEFINED: {
1057             ITypeInfo   *tinfo2;
1058             TYPEATTR    *tattr;
1059
1060             hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
1061             if (hres) {
1062                 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc->u.hreftype);
1063                 return hres;
1064             }
1065             hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
1066             if (hres) {
1067                 ERR("Could not get typeattr in VT_USERDEFINED.\n");
1068             } else {
1069                 switch (tattr->typekind) {
1070                 case TKIND_DISPATCH:
1071                 case TKIND_INTERFACE:
1072                     if (readit)
1073                         hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
1074                     break;
1075                 case TKIND_RECORD: {
1076                     int i;
1077
1078                     if (alloc)
1079                         *arg = (DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,tattr->cbSizeInstance);
1080
1081                     if (debugout) TRACE_(olerelay)("{");
1082                     for (i=0;i<tattr->cVars;i++) {
1083                         VARDESC *vdesc;
1084
1085                         hres = ITypeInfo2_GetVarDesc(tinfo2, i, &vdesc);
1086                         if (hres) {
1087                             ERR("Could not get vardesc of %d\n",i);
1088                             ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
1089                             ITypeInfo_Release(tinfo2);
1090                             return hres;
1091                         }
1092                         hres = deserialize_param(
1093                             tinfo2,
1094                             readit,
1095                             debugout,
1096                             alloc,
1097                             &vdesc->elemdescVar.tdesc,
1098                             (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst),
1099                             buf
1100                         );
1101                         ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc);
1102                         if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");
1103                     }
1104                     if (debugout) TRACE_(olerelay)("}");
1105                     break;
1106                 }
1107                 case TKIND_ALIAS:
1108                     hres = deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf);
1109                     break;
1110                 case TKIND_ENUM:
1111                     if (readit) {
1112                         hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
1113                         if (hres) ERR("Failed to read enum (4 byte)\n");
1114                     }
1115                     if (debugout) TRACE_(olerelay)("%x",*arg);
1116                     break;
1117                 default:
1118                     ERR("Unhandled typekind %d\n",tattr->typekind);
1119                     hres = E_FAIL;
1120                     break;
1121                 }
1122                 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
1123             }
1124             if (hres)
1125                 ERR("failed to stuballoc in TKIND_RECORD.\n");
1126             ITypeInfo_Release(tinfo2);
1127             return hres;
1128         }
1129         case VT_CARRAY: {
1130             /* arg is pointing to the start of the array. */
1131             ARRAYDESC *adesc = tdesc->u.lpadesc;
1132             int         arrsize,i;
1133             arrsize = 1;
1134             if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");
1135             for (i=0;i<adesc->cDims;i++)
1136                 arrsize *= adesc->rgbounds[i].cElements;
1137             for (i=0;i<arrsize;i++)
1138                 deserialize_param(
1139                     tinfo,
1140                     readit,
1141                     debugout,
1142                     alloc,
1143                     &adesc->tdescElem,
1144                     (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)),
1145                     buf
1146                 );
1147             return S_OK;
1148         }
1149     case VT_SAFEARRAY: {
1150             if (readit)
1151             {
1152                 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
1153                 unsigned char *buffer;
1154                 buffer = LPSAFEARRAY_UserUnmarshal(&flags, buf->base + buf->curoff, (LPSAFEARRAY *)arg);
1155                 buf->curoff = buffer - buf->base;
1156             }
1157             return S_OK;
1158         }
1159         default:
1160             ERR("No handler for VT type %d!\n",tdesc->vt);
1161             return S_OK;
1162         }
1163     }
1164 }
1165
1166 /* Searches function, also in inherited interfaces */
1167 static HRESULT
1168 _get_funcdesc(
1169     ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
1170 {
1171     int i = 0, j = 0;
1172     HRESULT hres;
1173
1174     if (fname) *fname = NULL;
1175     if (iname) *iname = NULL;
1176
1177     while (1) {
1178         hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i, fdesc);
1179
1180         if (hres) {
1181             ITypeInfo   *tinfo2;
1182             HREFTYPE    href;
1183             TYPEATTR    *attr;
1184
1185             hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
1186             if (hres) {
1187                 ERR("GetTypeAttr failed with %x\n",hres);
1188                 return hres;
1189             }
1190             /* Not found, so look in inherited ifaces. */
1191             for (j=0;j<attr->cImplTypes;j++) {
1192                 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
1193                 if (hres) {
1194                     ERR("Did not find a reftype for interface offset %d?\n",j);
1195                     break;
1196                 }
1197                 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
1198                 if (hres) {
1199                     ERR("Did not find a typeinfo for reftype %d?\n",href);
1200                     continue;
1201                 }
1202                 hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname);
1203                 ITypeInfo_Release(tinfo2);
1204                 if (!hres) {
1205                     ITypeInfo_ReleaseTypeAttr(tinfo, attr);
1206                     return S_OK;
1207                 }
1208             }
1209             ITypeInfo_ReleaseTypeAttr(tinfo, attr);
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             *tactual = tinfo;
1218             ITypeInfo_AddRef(*tactual);
1219             return S_OK;
1220         }
1221         i++;
1222     }
1223 }
1224
1225 static DWORD
1226 xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
1227 {
1228     DWORD               *args = ((DWORD*)&tpinfo)+1, *xargs;
1229     const FUNCDESC      *fdesc;
1230     HRESULT             hres;
1231     int                 i, relaydeb = TRACE_ON(olerelay);
1232     marshal_state       buf;
1233     RPCOLEMESSAGE       msg;
1234     ULONG               status;
1235     BSTR                fname,iname;
1236     BSTR                names[10];
1237     UINT                nrofnames;
1238     DWORD               remoteresult = 0;
1239     ITypeInfo           *tinfo;
1240     IRpcChannelBuffer *chanbuf;
1241
1242     EnterCriticalSection(&tpinfo->crit);
1243
1244     hres = _get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname);
1245     if (hres) {
1246         ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
1247         ITypeInfo_Release(tinfo);
1248         LeaveCriticalSection(&tpinfo->crit);
1249         return E_FAIL;
1250     }
1251
1252     if (!tpinfo->chanbuf)
1253     {
1254         WARN("Tried to use disconnected proxy\n");
1255         ITypeInfo_Release(tinfo);
1256         LeaveCriticalSection(&tpinfo->crit);
1257         return RPC_E_DISCONNECTED;
1258     }
1259     chanbuf = tpinfo->chanbuf;
1260     IRpcChannelBuffer_AddRef(chanbuf);
1261
1262     LeaveCriticalSection(&tpinfo->crit);
1263
1264     if (relaydeb) {
1265        TRACE_(olerelay)("->");
1266         if (iname)
1267             TRACE_(olerelay)("%s:",relaystr(iname));
1268         if (fname)
1269             TRACE_(olerelay)("%s(%d)",relaystr(fname),method);
1270         else
1271             TRACE_(olerelay)("%d",method);
1272         TRACE_(olerelay)("(");
1273     }
1274
1275     if (iname) SysFreeString(iname);
1276     if (fname) SysFreeString(fname);
1277
1278     memset(&buf,0,sizeof(buf));
1279
1280     /* normal typelib driven serializing */
1281
1282     /* Need them for hack below */
1283     memset(names,0,sizeof(names));
1284     if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
1285         nrofnames = 0;
1286     if (nrofnames > sizeof(names)/sizeof(names[0]))
1287         ERR("Need more names!\n");
1288
1289     xargs = args;
1290     for (i=0;i<fdesc->cParams;i++) {
1291         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1292         if (relaydeb) {
1293             if (i) TRACE_(olerelay)(",");
1294             if (i+1<nrofnames && names[i+1])
1295                 TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1296         }
1297         /* No need to marshal other data than FIN and any VT_PTR. */
1298         if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags) && (elem->tdesc.vt != VT_PTR)) {
1299             xargs+=_argsize(elem->tdesc.vt);
1300             if (relaydeb) TRACE_(olerelay)("[out]");
1301             continue;
1302         }
1303         hres = serialize_param(
1304             tinfo,
1305             elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
1306             relaydeb,
1307             FALSE,
1308             &elem->tdesc,
1309             xargs,
1310             &buf
1311         );
1312
1313         if (hres) {
1314             ERR("Failed to serialize param, hres %x\n",hres);
1315             break;
1316         }
1317         xargs+=_argsize(elem->tdesc.vt);
1318     }
1319     if (relaydeb) TRACE_(olerelay)(")");
1320
1321     memset(&msg,0,sizeof(msg));
1322     msg.cbBuffer = buf.curoff;
1323     msg.iMethod  = method;
1324     hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid));
1325     if (hres) {
1326         ERR("RpcChannelBuffer GetBuffer failed, %x\n",hres);
1327         goto exit;
1328     }
1329     memcpy(msg.Buffer,buf.base,buf.curoff);
1330     if (relaydeb) TRACE_(olerelay)("\n");
1331     hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status);
1332     if (hres) {
1333         ERR("RpcChannelBuffer SendReceive failed, %x\n",hres);
1334         goto exit;
1335     }
1336
1337     if (relaydeb) TRACE_(olerelay)(" status = %08x (",status);
1338     if (buf.base)
1339         buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
1340     else
1341         buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
1342     buf.size = msg.cbBuffer;
1343     memcpy(buf.base,msg.Buffer,buf.size);
1344     buf.curoff = 0;
1345
1346     /* generic deserializer using typelib description */
1347     xargs = args;
1348     status = S_OK;
1349     for (i=0;i<fdesc->cParams;i++) {
1350         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1351
1352         if (relaydeb) {
1353             if (i) TRACE_(olerelay)(",");
1354             if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1355         }
1356         /* No need to marshal other data than FOUT and any VT_PTR */
1357         if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {
1358             xargs += _argsize(elem->tdesc.vt);
1359             if (relaydeb) TRACE_(olerelay)("[in]");
1360             continue;
1361         }
1362         hres = deserialize_param(
1363             tinfo,
1364             elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1365             relaydeb,
1366             FALSE,
1367             &(elem->tdesc),
1368             xargs,
1369             &buf
1370         );
1371         if (hres) {
1372             ERR("Failed to unmarshall param, hres %x\n",hres);
1373             status = hres;
1374             break;
1375         }
1376         xargs += _argsize(elem->tdesc.vt);
1377     }
1378
1379     hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));
1380     if (hres != S_OK)
1381         goto exit;
1382     if (relaydeb) TRACE_(olerelay)(") = %08x\n", remoteresult);
1383
1384     hres = remoteresult;
1385
1386 exit:
1387     for (i = 0; i < nrofnames; i++)
1388         SysFreeString(names[i]);
1389     HeapFree(GetProcessHeap(),0,buf.base);
1390     IRpcChannelBuffer_Release(chanbuf);
1391     ITypeInfo_Release(tinfo);
1392     TRACE("-- 0x%08x\n", hres);
1393     return hres;
1394 }
1395
1396 static HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1397 {
1398     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1399
1400     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1401
1402     if (proxy->outerunknown)
1403         return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);
1404
1405     FIXME("No interface\n");
1406     return E_NOINTERFACE;
1407 }
1408
1409 static ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
1410 {
1411     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1412
1413     TRACE("\n");
1414
1415     if (proxy->outerunknown)
1416         return IUnknown_AddRef(proxy->outerunknown);
1417
1418     return 2; /* FIXME */
1419 }
1420
1421 static ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)
1422 {
1423     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1424
1425     TRACE("\n");
1426
1427     if (proxy->outerunknown)
1428         return IUnknown_Release(proxy->outerunknown);
1429
1430     return 1; /* FIXME */
1431 }
1432
1433 static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
1434 {
1435     TMProxyImpl *This = (TMProxyImpl *)iface;
1436
1437     TRACE("(%p)\n", pctinfo);
1438
1439     return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo);
1440 }
1441
1442 static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1443 {
1444     TMProxyImpl *This = (TMProxyImpl *)iface;
1445
1446     TRACE("(%d, %x, %p)\n", iTInfo, lcid, ppTInfo);
1447
1448     return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo);
1449 }
1450
1451 static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
1452 {
1453     TMProxyImpl *This = (TMProxyImpl *)iface;
1454
1455     TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1456
1457     return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames,
1458                                    cNames, lcid, rgDispId);
1459 }
1460
1461 static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1462                                             WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult,
1463                                             EXCEPINFO * pExcepInfo, UINT * puArgErr)
1464 {
1465     TMProxyImpl *This = (TMProxyImpl *)iface;
1466
1467     TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember,
1468           debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
1469           pExcepInfo, puArgErr);
1470
1471     return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid,
1472                             wFlags, pDispParams, pVarResult, pExcepInfo,
1473                             puArgErr);
1474 }
1475
1476 static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf)
1477 {
1478     HRESULT       hr;
1479     CLSID         clsid;
1480
1481     if ((hr = CoGetPSClsid(riid, &clsid)))
1482         return hr;
1483     return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
1484                              &IID_IPSFactoryBuffer, (LPVOID*)facbuf);
1485 }
1486
1487 static HRESULT WINAPI
1488 PSFacBuf_CreateProxy(
1489     LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
1490     IRpcProxyBuffer **ppProxy, LPVOID *ppv)
1491 {
1492     HRESULT     hres;
1493     ITypeInfo   *tinfo;
1494     int         i, nroffuncs;
1495     const FUNCDESC *fdesc;
1496     TMProxyImpl *proxy;
1497     TYPEATTR    *typeattr;
1498
1499     TRACE("(...%s...)\n",debugstr_guid(riid));
1500     hres = _get_typeinfo_for_iid(riid,&tinfo);
1501     if (hres) {
1502         ERR("No typeinfo for %s?\n",debugstr_guid(riid));
1503         return hres;
1504     }
1505     nroffuncs = _nroffuncs(tinfo);
1506     proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
1507     if (!proxy) return E_OUTOFMEMORY;
1508
1509     assert(sizeof(TMAsmProxy) == 12);
1510
1511     proxy->dispatch = NULL;
1512     proxy->dispatch_proxy = NULL;
1513     proxy->outerunknown = pUnkOuter;
1514     proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
1515     if (!proxy->asmstubs) {
1516         ERR("Could not commit pages for proxy thunks\n");
1517         CoTaskMemFree(proxy);
1518         return E_OUTOFMEMORY;
1519     }
1520
1521     InitializeCriticalSection(&proxy->crit);
1522
1523     proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
1524     for (i=0;i<nroffuncs;i++) {
1525         TMAsmProxy      *xasm = proxy->asmstubs+i;
1526
1527         switch (i) {
1528         case 0:
1529                 proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
1530                 break;
1531         case 1:
1532                 proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
1533                 break;
1534         case 2:
1535                 proxy->lpvtbl[i] = ProxyIUnknown_Release;
1536                 break;
1537         default: {
1538                 int j;
1539                 /* nrofargs without This */
1540                 int nrofargs;
1541                 ITypeInfo *tinfo2;
1542                 hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL);
1543                 ITypeInfo_Release(tinfo2);
1544                 if (hres) {
1545                     ERR("GetFuncDesc %x should not fail here.\n",hres);
1546                     return hres;
1547                 }
1548                 /* some args take more than 4 byte on the stack */
1549                 nrofargs = 0;
1550                 for (j=0;j<fdesc->cParams;j++)
1551                     nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
1552
1553 #ifdef __i386__
1554                 if (fdesc->callconv != CC_STDCALL) {
1555                     ERR("calling convention is not stdcall????\n");
1556                     return E_FAIL;
1557                 }
1558 /* popl %eax    -       return ptr
1559  * pushl <nr>
1560  * pushl %eax
1561  * call xCall
1562  * lret <nr> (+4)
1563  *
1564  *
1565  * arg3 arg2 arg1 <method> <returnptr>
1566  */
1567                 xasm->popleax   = 0x58;
1568                 xasm->pushlval  = 0x6a;
1569                 xasm->nr        = i;
1570                 xasm->pushleax  = 0x50;
1571                 xasm->lcall     = 0xe8; /* relative jump */
1572                 xasm->xcall     = (DWORD)xCall;
1573                 xasm->xcall     -= (DWORD)&(xasm->lret);
1574                 xasm->lret      = 0xc2;
1575                 xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
1576                 proxy->lpvtbl[i] = xasm;
1577                 break;
1578 #else
1579                 FIXME("not implemented on non i386\n");
1580                 return E_FAIL;
1581 #endif
1582             }
1583         }
1584     }
1585
1586     /* if we derive from IDispatch then defer to its proxy for its methods */
1587     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
1588     if (hres == S_OK)
1589     {
1590         if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
1591         {
1592             IPSFactoryBuffer *factory_buffer;
1593             hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
1594             if (hres == S_OK)
1595             {
1596                 hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL,
1597                     &IID_IDispatch, &proxy->dispatch_proxy,
1598                     (void **)&proxy->dispatch);
1599                 IPSFactoryBuffer_Release(factory_buffer);
1600             }
1601             if (hres == S_OK)
1602             {
1603                 proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
1604                 proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
1605                 proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
1606                 proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
1607             }
1608         }
1609         ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
1610     }
1611
1612     proxy->lpvtbl2      = &tmproxyvtable;
1613     /* one reference for the proxy */
1614     proxy->ref          = 1;
1615     proxy->tinfo        = tinfo;
1616     memcpy(&proxy->iid,riid,sizeof(*riid));
1617     proxy->chanbuf      = 0;
1618     if (hres == S_OK)
1619     {
1620         *ppv            = (LPVOID)proxy;
1621         *ppProxy                = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
1622         IUnknown_AddRef((IUnknown *)*ppv);
1623         return S_OK;
1624     }
1625     else
1626         TMProxyImpl_Release((IRpcProxyBuffer *)&proxy->lpvtbl2);
1627     return hres;
1628 }
1629
1630 typedef struct _TMStubImpl {
1631     const IRpcStubBufferVtbl   *lpvtbl;
1632     LONG                        ref;
1633
1634     LPUNKNOWN                   pUnk;
1635     ITypeInfo                   *tinfo;
1636     IID                         iid;
1637     IRpcStubBuffer              *dispatch_stub;
1638     BOOL                        dispatch_derivative;
1639 } TMStubImpl;
1640
1641 static HRESULT WINAPI
1642 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
1643 {
1644     if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
1645         *ppv = (LPVOID)iface;
1646         IRpcStubBuffer_AddRef(iface);
1647         return S_OK;
1648     }
1649     FIXME("%s, not supported IID.\n",debugstr_guid(riid));
1650     return E_NOINTERFACE;
1651 }
1652
1653 static ULONG WINAPI
1654 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)
1655 {
1656     TMStubImpl *This = (TMStubImpl *)iface;
1657     ULONG refCount = InterlockedIncrement(&This->ref);
1658         
1659     TRACE("(%p)->(ref before=%u)\n", This, refCount - 1);
1660
1661     return refCount;
1662 }
1663
1664 static ULONG WINAPI
1665 TMStubImpl_Release(LPRPCSTUBBUFFER iface)
1666 {
1667     TMStubImpl *This = (TMStubImpl *)iface;
1668     ULONG refCount = InterlockedDecrement(&This->ref);
1669
1670     TRACE("(%p)->(ref before=%u)\n", This, refCount + 1);
1671
1672     if (!refCount)
1673     {
1674         IRpcStubBuffer_Disconnect(iface);
1675         ITypeInfo_Release(This->tinfo);
1676         if (This->dispatch_stub)
1677             IRpcStubBuffer_Release(This->dispatch_stub);
1678         CoTaskMemFree(This);
1679     }
1680     return refCount;
1681 }
1682
1683 static HRESULT WINAPI
1684 TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
1685 {
1686     TMStubImpl *This = (TMStubImpl *)iface;
1687
1688     TRACE("(%p)->(%p)\n", This, pUnkServer);
1689
1690     IUnknown_AddRef(pUnkServer);
1691     This->pUnk = pUnkServer;
1692
1693     if (This->dispatch_stub)
1694         IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer);
1695
1696     return S_OK;
1697 }
1698
1699 static void WINAPI
1700 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
1701 {
1702     TMStubImpl *This = (TMStubImpl *)iface;
1703
1704     TRACE("(%p)->()\n", This);
1705
1706     if (This->pUnk)
1707     {
1708         IUnknown_Release(This->pUnk);
1709         This->pUnk = NULL;
1710     }
1711
1712     if (This->dispatch_stub)
1713         IRpcStubBuffer_Disconnect(This->dispatch_stub);
1714 }
1715
1716 static HRESULT WINAPI
1717 TMStubImpl_Invoke(
1718     LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
1719 {
1720     int         i;
1721     const FUNCDESC *fdesc;
1722     TMStubImpl *This = (TMStubImpl *)iface;
1723     HRESULT     hres;
1724     DWORD       *args = NULL, res, *xargs, nrofargs;
1725     marshal_state       buf;
1726     UINT        nrofnames;
1727     BSTR        names[10];
1728     BSTR        iname = NULL;
1729     ITypeInfo   *tinfo = NULL;
1730
1731     TRACE("...\n");
1732
1733     if (xmsg->iMethod < 3) {
1734         ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
1735         return E_UNEXPECTED;
1736     }
1737
1738     if (This->dispatch_derivative && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *))
1739     {
1740         IPSFactoryBuffer *factory_buffer;
1741         hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
1742         if (hres == S_OK)
1743         {
1744             hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch,
1745                 This->pUnk, &This->dispatch_stub);
1746             IPSFactoryBuffer_Release(factory_buffer);
1747         }
1748         if (hres != S_OK)
1749             return hres;
1750         return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf);
1751     }
1752
1753     memset(&buf,0,sizeof(buf));
1754     buf.size    = xmsg->cbBuffer;
1755     buf.base    = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer);
1756     memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer);
1757     buf.curoff  = 0;
1758
1759     hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL);
1760     if (hres) {
1761         ERR("GetFuncDesc on method %d failed with %x\n",xmsg->iMethod,hres);
1762         return hres;
1763     }
1764
1765     if (iname && !lstrcmpW(iname, IDispatchW))
1766     {
1767         ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
1768         hres = E_UNEXPECTED;
1769         SysFreeString (iname);
1770         goto exit;
1771     }
1772
1773     if (iname) SysFreeString (iname);
1774
1775     /* Need them for hack below */
1776     memset(names,0,sizeof(names));
1777     ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
1778     if (nrofnames > sizeof(names)/sizeof(names[0])) {
1779         ERR("Need more names!\n");
1780     }
1781
1782     /*dump_FUNCDESC(fdesc);*/
1783     nrofargs = 0;
1784     for (i=0;i<fdesc->cParams;i++)
1785         nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
1786     args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
1787     if (!args)
1788     {
1789         hres = E_OUTOFMEMORY;
1790         goto exit;
1791     }
1792
1793     /* Allocate all stuff used by call. */
1794     xargs = args+1;
1795     for (i=0;i<fdesc->cParams;i++) {
1796         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1797
1798         hres = deserialize_param(
1799            tinfo,
1800            elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
1801            FALSE,
1802            TRUE,
1803            &(elem->tdesc),
1804            xargs,
1805            &buf
1806         );
1807         xargs += _argsize(elem->tdesc.vt);
1808         if (hres) {
1809             ERR("Failed to deserialize param %s, hres %x\n",relaystr(names[i+1]),hres);
1810             break;
1811         }
1812     }
1813
1814     args[0] = (DWORD)This->pUnk;
1815
1816     __TRY
1817     {
1818         res = _invoke(
1819             (*((FARPROC**)args[0]))[fdesc->oVft/4],
1820             fdesc->callconv,
1821             (xargs-args),
1822             args
1823         );
1824     }
1825     __EXCEPT(NULL)
1826     {
1827         DWORD dwExceptionCode = GetExceptionCode();
1828         ERR("invoke call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode);
1829         if (FAILED(dwExceptionCode))
1830             hres = dwExceptionCode;
1831         else
1832             hres = HRESULT_FROM_WIN32(dwExceptionCode);
1833     }
1834     __ENDTRY
1835
1836     if (hres != S_OK)
1837         goto exit;
1838
1839     buf.curoff = 0;
1840
1841     xargs = args+1;
1842     for (i=0;i<fdesc->cParams;i++) {
1843         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1844         hres = serialize_param(
1845            tinfo,
1846            elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1847            FALSE,
1848            TRUE,
1849            &elem->tdesc,
1850            xargs,
1851            &buf
1852         );
1853         xargs += _argsize(elem->tdesc.vt);
1854         if (hres) {
1855             ERR("Failed to stuballoc param, hres %x\n",hres);
1856             break;
1857         }
1858     }
1859
1860     hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
1861
1862     if (hres != S_OK)
1863         goto exit;
1864
1865     xmsg->cbBuffer      = buf.curoff;
1866     hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid);
1867     if (hres != S_OK)
1868         ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08x\n", hres);
1869
1870     if (hres == S_OK)
1871         memcpy(xmsg->Buffer, buf.base, buf.curoff);
1872
1873 exit:
1874     for (i = 0; i < nrofnames; i++)
1875         SysFreeString(names[i]);
1876
1877     ITypeInfo_Release(tinfo);
1878     HeapFree(GetProcessHeap(), 0, args);
1879
1880     HeapFree(GetProcessHeap(), 0, buf.base);
1881
1882     TRACE("returning\n");
1883     return hres;
1884 }
1885
1886 static LPRPCSTUBBUFFER WINAPI
1887 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
1888     FIXME("Huh (%s)?\n",debugstr_guid(riid));
1889     return NULL;
1890 }
1891
1892 static ULONG WINAPI
1893 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
1894     TMStubImpl *This = (TMStubImpl *)iface;
1895
1896     FIXME("()\n");
1897     return This->ref; /*FIXME? */
1898 }
1899
1900 static HRESULT WINAPI
1901 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
1902     return E_NOTIMPL;
1903 }
1904
1905 static void WINAPI
1906 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
1907     return;
1908 }
1909
1910 static const IRpcStubBufferVtbl tmstubvtbl = {
1911     TMStubImpl_QueryInterface,
1912     TMStubImpl_AddRef,
1913     TMStubImpl_Release,
1914     TMStubImpl_Connect,
1915     TMStubImpl_Disconnect,
1916     TMStubImpl_Invoke,
1917     TMStubImpl_IsIIDSupported,
1918     TMStubImpl_CountRefs,
1919     TMStubImpl_DebugServerQueryInterface,
1920     TMStubImpl_DebugServerRelease
1921 };
1922
1923 static HRESULT WINAPI
1924 PSFacBuf_CreateStub(
1925     LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
1926     IRpcStubBuffer** ppStub
1927 ) {
1928     HRESULT hres;
1929     ITypeInfo   *tinfo;
1930     TMStubImpl  *stub;
1931     TYPEATTR *typeattr;
1932
1933     TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
1934
1935     hres = _get_typeinfo_for_iid(riid,&tinfo);
1936     if (hres) {
1937         ERR("No typeinfo for %s?\n",debugstr_guid(riid));
1938         return hres;
1939     }
1940
1941     stub = CoTaskMemAlloc(sizeof(TMStubImpl));
1942     if (!stub)
1943         return E_OUTOFMEMORY;
1944     stub->lpvtbl        = &tmstubvtbl;
1945     stub->ref           = 1;
1946     stub->tinfo         = tinfo;
1947     stub->dispatch_stub = NULL;
1948     stub->dispatch_derivative = FALSE;
1949     memcpy(&(stub->iid),riid,sizeof(*riid));
1950     hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
1951     *ppStub             = (LPRPCSTUBBUFFER)stub;
1952     TRACE("IRpcStubBuffer: %p\n", stub);
1953     if (hres)
1954         ERR("Connect to pUnkServer failed?\n");
1955
1956     /* if we derive from IDispatch then defer to its stub for some of its methods */
1957     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
1958     if (hres == S_OK)
1959     {
1960         if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
1961             stub->dispatch_derivative = TRUE;
1962         ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
1963     }
1964
1965     return hres;
1966 }
1967
1968 static const IPSFactoryBufferVtbl psfacbufvtbl = {
1969     PSFacBuf_QueryInterface,
1970     PSFacBuf_AddRef,
1971     PSFacBuf_Release,
1972     PSFacBuf_CreateProxy,
1973     PSFacBuf_CreateStub
1974 };
1975
1976 /* This is the whole PSFactoryBuffer object, just the vtableptr */
1977 static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
1978
1979 /***********************************************************************
1980  *           TMARSHAL_DllGetClassObject
1981  */
1982 HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1983 {
1984     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
1985         *ppv = &lppsfac;
1986         return S_OK;
1987     }
1988     return E_NOINTERFACE;
1989 }