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