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