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