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