Added IViewObject2 stub implementation.
[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     FUNCDESC    *fdesc;
308     HRESULT     hres;
309
310     n=0;
311     while (1) {
312         hres = ITypeInfo_GetFuncDesc(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                         if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(",");
1057                     }
1058                     if (debugout) TRACE_(olerelay)("}");
1059                     break;
1060                 }
1061                 case TKIND_ALIAS:
1062                     return deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf);
1063                 case TKIND_ENUM:
1064                     if (readit) {
1065                         hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
1066                         if (hres) ERR("Failed to read enum (4 byte)\n");
1067                     }
1068                     if (debugout) TRACE_(olerelay)("%lx",*arg);
1069                     return hres;
1070                 default:
1071                     ERR("Unhandled typekind %d\n",tattr->typekind);
1072                     hres = E_FAIL;
1073                     break;
1074                 }
1075             }
1076             if (hres)
1077                 ERR("failed to stuballoc in TKIND_RECORD.\n");
1078             ITypeInfo_Release(tinfo2);
1079             return hres;
1080         }
1081         case VT_CARRAY: {
1082             /* arg is pointing to the start of the array. */
1083             ARRAYDESC *adesc = tdesc->u.lpadesc;
1084             int         arrsize,i;
1085             arrsize = 1;
1086             if (adesc->cDims > 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");
1087             for (i=0;i<adesc->cDims;i++)
1088                 arrsize *= adesc->rgbounds[i].cElements;
1089             for (i=0;i<arrsize;i++)
1090                 deserialize_param(
1091                     tinfo,
1092                     readit,
1093                     debugout,
1094                     alloc,
1095                     &adesc->tdescElem,
1096                     (DWORD*)((LPBYTE)(arg)+i*_xsize(&adesc->tdescElem)),
1097                     buf
1098                 );
1099             return S_OK;
1100         }
1101         default:
1102             ERR("No handler for VT type %d!\n",tdesc->vt);
1103             return S_OK;
1104         }
1105     }
1106 }
1107
1108 /* Searches function, also in inherited interfaces */
1109 static HRESULT
1110 _get_funcdesc(
1111     ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
1112 {
1113     int i = 0, j = 0;
1114     HRESULT hres;
1115
1116     if (fname) *fname = NULL;
1117     if (iname) *iname = NULL;
1118
1119     *tactual = tinfo;
1120     ITypeInfo_AddRef(*tactual);
1121
1122     while (1) {
1123         hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc);
1124         if (hres) {
1125             ITypeInfo   *tinfo2;
1126             HREFTYPE    href;
1127             TYPEATTR    *attr;
1128
1129             hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
1130             if (hres) {
1131                 ERR("GetTypeAttr failed with %lx\n",hres);
1132                 return hres;
1133             }
1134             /* Not found, so look in inherited ifaces. */
1135             for (j=0;j<attr->cImplTypes;j++) {
1136                 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
1137                 if (hres) {
1138                     ERR("Did not find a reftype for interface offset %d?\n",j);
1139                     break;
1140                 }
1141                 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
1142                 if (hres) {
1143                     ERR("Did not find a typeinfo for reftype %ld?\n",href);
1144                     continue;
1145                 }
1146                 hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname);
1147                 ITypeInfo_Release(tinfo2);
1148                 if (!hres) return S_OK;
1149             }
1150             return hres;
1151         }
1152         if (((*fdesc)->oVft/4) == iMethod) {
1153             if (fname)
1154                 ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
1155             if (iname)
1156                 ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
1157             return S_OK;
1158         }
1159         i++;
1160     }
1161 }
1162
1163 static DWORD
1164 xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
1165 {
1166     DWORD               *args = ((DWORD*)&tpinfo)+1, *xargs;
1167     FUNCDESC            *fdesc;
1168     HRESULT             hres;
1169     int                 i, relaydeb = TRACE_ON(olerelay);
1170     marshal_state       buf;
1171     RPCOLEMESSAGE       msg;
1172     ULONG               status;
1173     BSTR                fname,iname;
1174     BSTR                names[10];
1175     UINT                nrofnames;
1176     DWORD               remoteresult = 0;
1177     ITypeInfo           *tinfo;
1178     IRpcChannelBuffer *chanbuf;
1179
1180     EnterCriticalSection(&tpinfo->crit);
1181
1182     hres = _get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname);
1183     if (hres) {
1184         ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
1185         ITypeInfo_Release(tinfo);
1186         LeaveCriticalSection(&tpinfo->crit);
1187         return E_FAIL;
1188     }
1189
1190     if (!tpinfo->chanbuf)
1191     {
1192         WARN("Tried to use disconnected proxy\n");
1193         ITypeInfo_Release(tinfo);
1194         LeaveCriticalSection(&tpinfo->crit);
1195         return RPC_E_DISCONNECTED;
1196     }
1197     chanbuf = tpinfo->chanbuf;
1198     IRpcChannelBuffer_AddRef(chanbuf);
1199
1200     LeaveCriticalSection(&tpinfo->crit);
1201
1202     if (relaydeb) {
1203        TRACE_(olerelay)("->");
1204         if (iname)
1205             TRACE_(olerelay)("%s:",relaystr(iname));
1206         if (fname)
1207             TRACE_(olerelay)("%s(%d)",relaystr(fname),method);
1208         else
1209             TRACE_(olerelay)("%d",method);
1210         TRACE_(olerelay)("(");
1211     }
1212
1213     if (iname) SysFreeString(iname);
1214     if (fname) SysFreeString(fname);
1215
1216     memset(&buf,0,sizeof(buf));
1217
1218     /* normal typelib driven serializing */
1219
1220     /* Need them for hack below */
1221     memset(names,0,sizeof(names));
1222     if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
1223         nrofnames = 0;
1224     if (nrofnames > sizeof(names)/sizeof(names[0]))
1225         ERR("Need more names!\n");
1226
1227     xargs = args;
1228     for (i=0;i<fdesc->cParams;i++) {
1229         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1230         if (relaydeb) {
1231             if (i) TRACE_(olerelay)(",");
1232             if (i+1<nrofnames && names[i+1])
1233                 TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1234         }
1235         /* No need to marshal other data than FIN and any VT_PTR. */
1236         if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags) && (elem->tdesc.vt != VT_PTR)) {
1237             xargs+=_argsize(elem->tdesc.vt);
1238             if (relaydeb) TRACE_(olerelay)("[out]");
1239             continue;
1240         }
1241         hres = serialize_param(
1242             tinfo,
1243             elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
1244             relaydeb,
1245             FALSE,
1246             &elem->tdesc,
1247             xargs,
1248             &buf
1249         );
1250
1251         if (hres) {
1252             ERR("Failed to serialize param, hres %lx\n",hres);
1253             break;
1254         }
1255         xargs+=_argsize(elem->tdesc.vt);
1256     }
1257     if (relaydeb) TRACE_(olerelay)(")");
1258
1259     memset(&msg,0,sizeof(msg));
1260     msg.cbBuffer = buf.curoff;
1261     msg.iMethod  = method;
1262     hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid));
1263     if (hres) {
1264         ERR("RpcChannelBuffer GetBuffer failed, %lx\n",hres);
1265         goto exit;
1266     }
1267     memcpy(msg.Buffer,buf.base,buf.curoff);
1268     if (relaydeb) TRACE_(olerelay)("\n");
1269     hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status);
1270     if (hres) {
1271         ERR("RpcChannelBuffer SendReceive failed, %lx\n",hres);
1272         goto exit;
1273     }
1274
1275     if (relaydeb) TRACE_(olerelay)(" status = %08lx (",status);
1276     if (buf.base)
1277         buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
1278     else
1279         buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
1280     buf.size = msg.cbBuffer;
1281     memcpy(buf.base,msg.Buffer,buf.size);
1282     buf.curoff = 0;
1283
1284     /* generic deserializer using typelib description */
1285     xargs = args;
1286     status = S_OK;
1287     for (i=0;i<fdesc->cParams;i++) {
1288         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1289
1290         if (relaydeb) {
1291             if (i) TRACE_(olerelay)(",");
1292             if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
1293         }
1294         /* No need to marshal other data than FOUT and any VT_PTR */
1295         if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) && (elem->tdesc.vt != VT_PTR)) {
1296             xargs += _argsize(elem->tdesc.vt);
1297             if (relaydeb) TRACE_(olerelay)("[in]");
1298             continue;
1299         }
1300         hres = deserialize_param(
1301             tinfo,
1302             elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1303             relaydeb,
1304             FALSE,
1305             &(elem->tdesc),
1306             xargs,
1307             &buf
1308         );
1309         if (hres) {
1310             ERR("Failed to unmarshall param, hres %lx\n",hres);
1311             status = hres;
1312             break;
1313         }
1314         xargs += _argsize(elem->tdesc.vt);
1315     }
1316
1317     hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));
1318     if (hres != S_OK)
1319         goto exit;
1320     if (relaydeb) TRACE_(olerelay)(") = %08lx\n", remoteresult);
1321
1322     hres = remoteresult;
1323
1324 exit:
1325     HeapFree(GetProcessHeap(),0,buf.base);
1326     IRpcChannelBuffer_Release(chanbuf);
1327     ITypeInfo_Release(tinfo);
1328     TRACE("-- 0x%08lx\n", hres);
1329     return hres;
1330 }
1331
1332 HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1333 {
1334     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1335
1336     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1337
1338     if (proxy->outerunknown)
1339         return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);
1340
1341     FIXME("No interface\n");
1342     return E_NOINTERFACE;
1343 }
1344
1345 ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
1346 {
1347     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1348
1349     TRACE("\n");
1350
1351     if (proxy->outerunknown)
1352         return IUnknown_AddRef(proxy->outerunknown);
1353
1354     return 2; /* FIXME */
1355 }
1356
1357 ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)
1358 {
1359     TMProxyImpl *proxy = (TMProxyImpl *)iface;
1360
1361     TRACE("\n");
1362
1363     if (proxy->outerunknown)
1364         return IUnknown_Release(proxy->outerunknown);
1365
1366     return 1; /* FIXME */
1367 }
1368
1369 static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
1370 {
1371     TMProxyImpl *This = (TMProxyImpl *)iface;
1372     HRESULT hr;
1373
1374     TRACE("(%p)\n", pctinfo);
1375
1376     if (!This->dispatch)
1377     {
1378         hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
1379                                      (LPVOID *)&This->dispatch);
1380     }
1381     if (This->dispatch)
1382         hr = IDispatch_GetTypeInfoCount(This->dispatch, pctinfo);
1383
1384     return hr;
1385 }
1386
1387 static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1388 {
1389     TMProxyImpl *This = (TMProxyImpl *)iface;
1390     HRESULT hr = S_OK;
1391
1392     TRACE("(%d, %lx, %p)\n", iTInfo, lcid, ppTInfo);
1393
1394     if (!This->dispatch)
1395     {
1396         hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
1397                                      (LPVOID *)&This->dispatch);
1398     }
1399     if (This->dispatch)
1400         hr = IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo);
1401
1402     return hr;
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     HRESULT hr;
1409
1410     TRACE("(%s, %p, %d, 0x%lx, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1411
1412     if (!This->dispatch)
1413     {
1414         hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
1415                                      (LPVOID *)&This->dispatch);
1416     }
1417     if (This->dispatch)
1418         hr = IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames,
1419                                      cNames, lcid, rgDispId);
1420
1421     return hr;
1422 }
1423
1424 static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1425                                             WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult,
1426                                             EXCEPINFO * pExcepInfo, UINT * puArgErr)
1427 {
1428     TMProxyImpl *This = (TMProxyImpl *)iface;
1429     HRESULT hr;
1430
1431     TRACE("(%ld, %s, 0x%lx, 0x%x, %p, %p, %p, %p)\n", dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1432
1433     if (!This->dispatch)
1434     {
1435         hr = IUnknown_QueryInterface(This->outerunknown, &IID_IDispatch,
1436                                      (LPVOID *)&This->dispatch);
1437     }
1438     if (This->dispatch)
1439         hr = IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid,
1440                               wFlags, pDispParams, pVarResult, pExcepInfo,
1441                               puArgErr);
1442
1443     return hr;
1444 }
1445
1446 static HRESULT WINAPI
1447 PSFacBuf_CreateProxy(
1448     LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
1449     IRpcProxyBuffer **ppProxy, LPVOID *ppv)
1450 {
1451     HRESULT     hres;
1452     ITypeInfo   *tinfo;
1453     int         i, nroffuncs;
1454     FUNCDESC    *fdesc;
1455     TMProxyImpl *proxy;
1456     TYPEATTR    *typeattr;
1457
1458     TRACE("(...%s...)\n",debugstr_guid(riid));
1459     hres = _get_typeinfo_for_iid(riid,&tinfo);
1460     if (hres) {
1461         ERR("No typeinfo for %s?\n",debugstr_guid(riid));
1462         return hres;
1463     }
1464     nroffuncs = _nroffuncs(tinfo);
1465     proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
1466     if (!proxy) return E_OUTOFMEMORY;
1467
1468     assert(sizeof(TMAsmProxy) == 12);
1469
1470     proxy->dispatch = NULL;
1471     proxy->outerunknown = pUnkOuter;
1472     proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
1473     if (!proxy->asmstubs) {
1474         ERR("Could not commit pages for proxy thunks\n");
1475         CoTaskMemFree(proxy);
1476         return E_OUTOFMEMORY;
1477     }
1478
1479     InitializeCriticalSection(&proxy->crit);
1480
1481     proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
1482     for (i=0;i<nroffuncs;i++) {
1483         TMAsmProxy      *xasm = proxy->asmstubs+i;
1484
1485         switch (i) {
1486         case 0:
1487                 proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
1488                 break;
1489         case 1:
1490                 proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
1491                 break;
1492         case 2:
1493                 proxy->lpvtbl[i] = ProxyIUnknown_Release;
1494                 break;
1495         default: {
1496                 int j;
1497                 /* nrofargs without This */
1498                 int nrofargs;
1499                 ITypeInfo *tinfo2;
1500                 hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL);
1501                 ITypeInfo_Release(tinfo2);
1502                 if (hres) {
1503                     ERR("GetFuncDesc %lx should not fail here.\n",hres);
1504                     return hres;
1505                 }
1506                 /* some args take more than 4 byte on the stack */
1507                 nrofargs = 0;
1508                 for (j=0;j<fdesc->cParams;j++)
1509                     nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
1510
1511 #ifdef __i386__
1512                 if (fdesc->callconv != CC_STDCALL) {
1513                     ERR("calling convention is not stdcall????\n");
1514                     return E_FAIL;
1515                 }
1516 /* popl %eax    -       return ptr
1517  * pushl <nr>
1518  * pushl %eax
1519  * call xCall
1520  * lret <nr> (+4)
1521  *
1522  *
1523  * arg3 arg2 arg1 <method> <returnptr>
1524  */
1525                 xasm->popleax   = 0x58;
1526                 xasm->pushlval  = 0x6a;
1527                 xasm->nr        = i;
1528                 xasm->pushleax  = 0x50;
1529                 xasm->lcall     = 0xe8; /* relative jump */
1530                 xasm->xcall     = (DWORD)xCall;
1531                 xasm->xcall     -= (DWORD)&(xasm->lret);
1532                 xasm->lret      = 0xc2;
1533                 xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
1534                 proxy->lpvtbl[i] = xasm;
1535                 break;
1536 #else
1537                 FIXME("not implemented on non i386\n");
1538                 return E_FAIL;
1539 #endif
1540             }
1541         }
1542     }
1543
1544     /* if we derive from IDispatch then defer to its proxy for its methods */
1545     hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
1546     if (hres == S_OK)
1547     {
1548         if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
1549         {
1550             proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
1551             proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
1552             proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
1553             proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
1554         }
1555         ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
1556     }
1557
1558     proxy->lpvtbl2      = &tmproxyvtable;
1559     /* one reference for the proxy */
1560     proxy->ref          = 1;
1561     proxy->tinfo        = tinfo;
1562     memcpy(&proxy->iid,riid,sizeof(*riid));
1563     proxy->chanbuf      = 0;
1564     *ppv                = (LPVOID)proxy;
1565     *ppProxy            = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
1566     IUnknown_AddRef((IUnknown *)*ppv);
1567     return S_OK;
1568 }
1569
1570 typedef struct _TMStubImpl {
1571     const IRpcStubBufferVtbl   *lpvtbl;
1572     LONG                        ref;
1573
1574     LPUNKNOWN                   pUnk;
1575     ITypeInfo                   *tinfo;
1576     IID                         iid;
1577 } TMStubImpl;
1578
1579 static HRESULT WINAPI
1580 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
1581 {
1582     if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
1583         *ppv = (LPVOID)iface;
1584         IRpcStubBuffer_AddRef(iface);
1585         return S_OK;
1586     }
1587     FIXME("%s, not supported IID.\n",debugstr_guid(riid));
1588     return E_NOINTERFACE;
1589 }
1590
1591 static ULONG WINAPI
1592 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)
1593 {
1594     TMStubImpl *This = (TMStubImpl *)iface;
1595     ULONG refCount = InterlockedIncrement(&This->ref);
1596         
1597     TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1);
1598
1599     return refCount;
1600 }
1601
1602 static ULONG WINAPI
1603 TMStubImpl_Release(LPRPCSTUBBUFFER iface)
1604 {
1605     TMStubImpl *This = (TMStubImpl *)iface;
1606     ULONG refCount = InterlockedDecrement(&This->ref);
1607
1608     TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1);
1609
1610     if (!refCount)
1611     {
1612         IRpcStubBuffer_Disconnect(iface);
1613         ITypeInfo_Release(This->tinfo);
1614         CoTaskMemFree(This);
1615     }
1616     return refCount;
1617 }
1618
1619 static HRESULT WINAPI
1620 TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
1621 {
1622     TMStubImpl *This = (TMStubImpl *)iface;
1623
1624     TRACE("(%p)->(%p)\n", This, pUnkServer);
1625
1626     IUnknown_AddRef(pUnkServer);
1627     This->pUnk = pUnkServer;
1628     return S_OK;
1629 }
1630
1631 static void WINAPI
1632 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
1633 {
1634     TMStubImpl *This = (TMStubImpl *)iface;
1635
1636     TRACE("(%p)->()\n", This);
1637
1638     if (This->pUnk)
1639     {
1640         IUnknown_Release(This->pUnk);
1641         This->pUnk = NULL;
1642     }
1643 }
1644
1645 static HRESULT WINAPI
1646 TMStubImpl_Invoke(
1647     LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
1648 {
1649     int         i;
1650     FUNCDESC    *fdesc;
1651     TMStubImpl *This = (TMStubImpl *)iface;
1652     HRESULT     hres;
1653     DWORD       *args, res, *xargs, nrofargs;
1654     marshal_state       buf;
1655     UINT        nrofnames;
1656     BSTR        names[10];
1657     BSTR        iname = NULL;
1658     ITypeInfo   *tinfo;
1659
1660     memset(&buf,0,sizeof(buf));
1661     buf.size    = xmsg->cbBuffer;
1662     buf.base    = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer);
1663     memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer);
1664     buf.curoff  = 0;
1665
1666     TRACE("...\n");
1667
1668     if (xmsg->iMethod < 3) {
1669         ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
1670         return E_UNEXPECTED;
1671     }
1672
1673     hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL);
1674     if (hres) {
1675         ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
1676         return hres;
1677     }
1678
1679     if (iname && !lstrcmpW(iname, IDispatchW))
1680     {
1681         ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
1682         ITypeInfo_Release(tinfo);
1683         return E_UNEXPECTED;
1684     }
1685
1686     if (iname) SysFreeString (iname);
1687
1688     /* Need them for hack below */
1689     memset(names,0,sizeof(names));
1690     ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
1691     if (nrofnames > sizeof(names)/sizeof(names[0])) {
1692         ERR("Need more names!\n");
1693     }
1694
1695     /*dump_FUNCDESC(fdesc);*/
1696     nrofargs = 0;
1697     for (i=0;i<fdesc->cParams;i++)
1698         nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
1699     args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
1700     if (!args) return E_OUTOFMEMORY;
1701
1702     /* Allocate all stuff used by call. */
1703     xargs = args+1;
1704     for (i=0;i<fdesc->cParams;i++) {
1705         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1706
1707         hres = deserialize_param(
1708            tinfo,
1709            elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN || !elem->u.paramdesc.wParamFlags,
1710            FALSE,
1711            TRUE,
1712            &(elem->tdesc),
1713            xargs,
1714            &buf
1715         );
1716         xargs += _argsize(elem->tdesc.vt);
1717         if (hres) {
1718             ERR("Failed to deserialize param %s, hres %lx\n",relaystr(names[i+1]),hres);
1719             break;
1720         }
1721     }
1722
1723     args[0] = (DWORD)This->pUnk;
1724     res = _invoke(
1725         (*((FARPROC**)args[0]))[fdesc->oVft/4],
1726         fdesc->callconv,
1727         (xargs-args),
1728         args
1729     );
1730     buf.curoff = 0;
1731
1732     xargs = args+1;
1733     for (i=0;i<fdesc->cParams;i++) {
1734         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1735         hres = serialize_param(
1736            tinfo,
1737            elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
1738            FALSE,
1739            TRUE,
1740            &elem->tdesc,
1741            xargs,
1742            &buf
1743         );
1744         xargs += _argsize(elem->tdesc.vt);
1745         if (hres) {
1746             ERR("Failed to stuballoc param, hres %lx\n",hres);
1747             break;
1748         }
1749     }
1750
1751     hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
1752     if (hres != S_OK)
1753         return hres;
1754
1755     ITypeInfo_Release(tinfo);
1756     HeapFree(GetProcessHeap(), 0, args);
1757
1758     xmsg->cbBuffer      = buf.curoff;
1759     if (rpcchanbuf)
1760     {
1761         hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid);
1762         if (hres != S_OK)
1763             ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08lx\n", hres);
1764     }
1765     else
1766     {
1767         /* FIXME: remove this case when we start sending an IRpcChannelBuffer
1768          * object with builtin OLE */
1769         RPC_STATUS status = I_RpcGetBuffer((RPC_MESSAGE *)xmsg);
1770         if (status != RPC_S_OK)
1771         {
1772             ERR("I_RpcGetBuffer failed with error %ld\n", status);
1773             hres = E_FAIL;
1774         }
1775     }
1776
1777     if (hres == S_OK)
1778         memcpy(xmsg->Buffer, buf.base, buf.curoff);
1779
1780     HeapFree(GetProcessHeap(), 0, buf.base);
1781
1782     TRACE("returning\n");
1783     return hres;
1784 }
1785
1786 static LPRPCSTUBBUFFER WINAPI
1787 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
1788     FIXME("Huh (%s)?\n",debugstr_guid(riid));
1789     return NULL;
1790 }
1791
1792 static ULONG WINAPI
1793 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
1794     TMStubImpl *This = (TMStubImpl *)iface;
1795
1796     FIXME("()\n");
1797     return This->ref; /*FIXME? */
1798 }
1799
1800 static HRESULT WINAPI
1801 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
1802     return E_NOTIMPL;
1803 }
1804
1805 static void WINAPI
1806 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
1807     return;
1808 }
1809
1810 static const IRpcStubBufferVtbl tmstubvtbl = {
1811     TMStubImpl_QueryInterface,
1812     TMStubImpl_AddRef,
1813     TMStubImpl_Release,
1814     TMStubImpl_Connect,
1815     TMStubImpl_Disconnect,
1816     TMStubImpl_Invoke,
1817     TMStubImpl_IsIIDSupported,
1818     TMStubImpl_CountRefs,
1819     TMStubImpl_DebugServerQueryInterface,
1820     TMStubImpl_DebugServerRelease
1821 };
1822
1823 static HRESULT WINAPI
1824 PSFacBuf_CreateStub(
1825     LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
1826     IRpcStubBuffer** ppStub
1827 ) {
1828     HRESULT hres;
1829     ITypeInfo   *tinfo;
1830     TMStubImpl  *stub;
1831
1832     TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
1833     hres = _get_typeinfo_for_iid(riid,&tinfo);
1834     if (hres) {
1835         ERR("No typeinfo for %s?\n",debugstr_guid(riid));
1836         return hres;
1837     }
1838     stub = CoTaskMemAlloc(sizeof(TMStubImpl));
1839     if (!stub)
1840         return E_OUTOFMEMORY;
1841     stub->lpvtbl        = &tmstubvtbl;
1842     stub->ref           = 1;
1843     stub->tinfo         = tinfo;
1844     memcpy(&(stub->iid),riid,sizeof(*riid));
1845     hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
1846     *ppStub             = (LPRPCSTUBBUFFER)stub;
1847     TRACE("IRpcStubBuffer: %p\n", stub);
1848     if (hres)
1849         ERR("Connect to pUnkServer failed?\n");
1850     return hres;
1851 }
1852
1853 static const IPSFactoryBufferVtbl psfacbufvtbl = {
1854     PSFacBuf_QueryInterface,
1855     PSFacBuf_AddRef,
1856     PSFacBuf_Release,
1857     PSFacBuf_CreateProxy,
1858     PSFacBuf_CreateStub
1859 };
1860
1861 /* This is the whole PSFactoryBuffer object, just the vtableptr */
1862 static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
1863
1864 /***********************************************************************
1865  *           TMARSHAL_DllGetClassObject
1866  */
1867 HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1868 {
1869     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
1870         *ppv = &lppsfac;
1871         return S_OK;
1872     }
1873     return E_NOINTERFACE;
1874 }