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