Various cosmetic changes.
[wine] / dlls / oleaut32 / tmarshal.c
1 /*
2  *      TYPELIB Marshaler
3  *
4  *      Copyright 2002  Marcus Meissner
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <ctype.h>
14
15 #include "winerror.h"
16 #include "winnls.h"
17 #include "winreg.h"
18 #include "winuser.h"
19
20 #include "ole2.h"
21 #include "wine/unicode.h"
22 #include "wine/obj_base.h"
23 #include "wine/obj_channel.h"
24 #include "wine/obj_storage.h"
25 #include "heap.h"
26 #include "ole2disp.h"
27 #include "typelib.h"
28 #include "debugtools.h"
29 #include "ntddk.h"
30
31 static const WCHAR riidW[5] = {'r','i','i','d',0};
32
33 DEFAULT_DEBUG_CHANNEL(ole);
34 DECLARE_DEBUG_CHANNEL(olerelay);
35
36 typedef struct _marshal_state {
37     LPBYTE      base;
38     int         size;
39     int         curoff;
40
41     BOOL        thisisiid;
42     IID         iid;    /* HACK: for VT_VOID */
43 } marshal_state;
44
45 static HRESULT
46 xbuf_add(marshal_state *buf, LPBYTE stuff, DWORD size) {
47     while (buf->size - buf->curoff < size) {
48         if (buf->base) {
49             buf->size += 100;
50             buf->base = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,buf->base,buf->size);
51             if (!buf->base)
52                 return E_OUTOFMEMORY;
53         } else {
54             buf->base = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,32);
55             buf->size = 32;
56             if (!buf->base)
57                 return E_OUTOFMEMORY;
58         }
59     }
60     memcpy(buf->base+buf->curoff,stuff,size);
61     buf->curoff += size;
62     return S_OK;
63 }
64
65 static HRESULT
66 xbuf_get(marshal_state *buf, LPBYTE stuff, DWORD size) {
67     if (buf->size < buf->curoff+size) return E_FAIL;
68     memcpy(stuff,buf->base+buf->curoff,size);
69     buf->curoff += size;
70     return S_OK;
71 }
72
73 static HRESULT
74 xbuf_skip(marshal_state *buf, DWORD size) {
75     if (buf->size < buf->curoff+size) return E_FAIL;
76     buf->curoff += size;
77     return S_OK;
78 }
79
80 static HRESULT
81 _unmarshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN *pUnk) {
82     IStream             *pStm;
83     ULARGE_INTEGER      newpos;
84     LARGE_INTEGER       seekto;
85     ULONG               res;
86     HRESULT             hres;
87     DWORD               xsize;
88
89     TRACE("...%s...\n",debugstr_guid(riid));
90     *pUnk = NULL;
91     hres = xbuf_get(buf,(LPBYTE)&xsize,sizeof(xsize));
92     if (hres) return hres;
93     if (xsize == 0) return S_OK;
94     hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
95     if (hres) {
96         FIXME("Stream create failed %lx\n",hres);
97         return hres;
98     }
99     hres = IStream_Write(pStm,buf->base+buf->curoff,xsize,&res);
100     if (hres) { FIXME("stream write %lx\n",hres); return hres; }
101     memset(&seekto,0,sizeof(seekto));
102     hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
103     if (hres) { FIXME("Failed Seek %lx\n",hres); return hres;}
104     hres = CoUnmarshalInterface(pStm,riid,(LPVOID*)pUnk);
105     if (hres) {
106         FIXME("Marshaling interface %s failed with %lx\n",debugstr_guid(riid),hres);
107         return hres;
108     }
109     IStream_Release(pStm);
110     return xbuf_skip(buf,xsize);
111 }
112
113 static HRESULT
114 _marshal_interface(marshal_state *buf, REFIID riid, LPUNKNOWN pUnk) {
115     LPUNKNOWN           newiface;
116     LPBYTE              tempbuf;
117     IStream             *pStm;
118     STATSTG             ststg;
119     ULARGE_INTEGER      newpos;
120     LARGE_INTEGER       seekto;
121     ULONG               res;
122     DWORD               xsize;
123     HRESULT             hres;
124
125     hres = S_OK;
126     if (!pUnk)
127         goto fail;
128
129     TRACE("...%s...\n",debugstr_guid(riid));
130     hres=IUnknown_QueryInterface(pUnk,riid,(LPVOID*)&newiface);
131     if (hres) {
132         TRACE("%p does not support iface %s\n",pUnk,debugstr_guid(riid));
133         goto fail;
134     }
135     hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
136     if (hres) {
137         FIXME("Stream create failed %lx\n",hres);
138         goto fail;
139     }
140     hres = CoMarshalInterface(pStm,riid,newiface,0,NULL,0);
141     IUnknown_Release(newiface);
142     if (hres) {
143         FIXME("Marshaling interface %s failed with %lx\n",
144                 debugstr_guid(riid),hres
145         );
146         goto fail;
147     }
148     hres = IStream_Stat(pStm,&ststg,0);
149     tempbuf = HeapAlloc(GetProcessHeap(), 0, ststg.cbSize.s.LowPart);
150     memset(&seekto,0,sizeof(seekto));
151     hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
152     if (hres) { FIXME("Failed Seek %lx\n",hres); goto fail;}
153     hres = IStream_Read(pStm,tempbuf,ststg.cbSize.s.LowPart,&res);
154     if (hres) { FIXME("Failed Read %lx\n",hres); goto fail;}
155     IStream_Release(pStm);
156     xsize = ststg.cbSize.s.LowPart;
157     xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
158     hres = xbuf_add(buf,tempbuf,ststg.cbSize.s.LowPart);
159     HeapFree(GetProcessHeap(),0,tempbuf);
160     return hres;
161 fail:
162     xsize = 0;
163     xbuf_add(buf,(LPBYTE)&xsize,sizeof(xsize));
164     return hres;
165 }
166
167 /********************* OLE Proxy/Stub Factory ********************************/
168 static HRESULT WINAPI
169 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
170     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {
171         *ppv = (LPVOID)iface; 
172         /* No ref counting, static class */
173         return S_OK;
174     }
175     FIXME("(%s) unknown IID?\n",debugstr_guid(iid));
176     return E_NOINTERFACE;
177 }
178
179 static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }
180 static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }
181
182 static HRESULT
183 _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
184     HRESULT     hres;
185     HKEY        ikey;
186     char        tlguid[200],typelibkey[300],interfacekey[300],ver[100];
187     char        tlfn[260];
188     OLECHAR     tlfnW[260];
189     DWORD       tlguidlen, verlen, type, tlfnlen;
190     ITypeLib    *tl;
191
192     sprintf( interfacekey, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
193         riid->Data1, riid->Data2, riid->Data3,
194         riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
195         riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]
196     );
197
198     if (RegOpenKeyA(HKEY_CLASSES_ROOT,interfacekey,&ikey)) {
199         FIXME("No %s key found.\n",interfacekey);
200         return E_FAIL;
201     }
202     type = (1<<REG_SZ);
203     tlguidlen = sizeof(tlguid);
204     if (RegQueryValueExA(ikey,NULL,NULL,&type,tlguid,&tlguidlen)) {
205         FIXME("Getting typelib guid failed.\n");
206         RegCloseKey(ikey);
207         return E_FAIL;
208     }
209     type = (1<<REG_SZ);
210     verlen = sizeof(ver);
211     if (RegQueryValueExA(ikey,"Version",NULL,&type,ver,&verlen)) {
212         FIXME("Could not get version value?\n");
213         RegCloseKey(ikey);
214         return E_FAIL;
215     }
216     RegCloseKey(ikey);
217     sprintf(typelibkey,"Typelib\\%s\\%s\\0\\win32",tlguid,ver);
218     tlfnlen = sizeof(tlfn);
219     if (RegQueryValueA(HKEY_CLASSES_ROOT,typelibkey,tlfn,&tlfnlen)) {
220         FIXME("Could not get typelib fn?\n");
221         return E_FAIL;
222     }
223     MultiByteToWideChar(CP_ACP, 0, tlfn, -1, tlfnW, -1);
224     hres = LoadTypeLib(tlfnW,&tl);
225     if (hres) {
226         ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid));
227         return hres;
228     }
229     hres = ITypeLib_GetTypeInfoOfGuid(tl,riid,ti);
230     if (hres) {
231         ERR("typelib does not contain info for %s?\n",debugstr_guid(riid));
232         ITypeLib_Release(tl);
233         return hres;
234     }
235     /* FIXME: do this?  ITypeLib_Release(tl); */
236     return hres;
237 }
238
239 /* Determine nr of functions. Since we use the toplevel interface and all
240  * inherited ones have lower numbers, we are ok to not to descent into 
241  * the inheritance tree I think.
242  */
243 static int _nroffuncs(ITypeInfo *tinfo) {
244     int         n, max = 0;
245     FUNCDESC    *fdesc;
246     HRESULT     hres;
247
248     n=0;
249     while (1) {
250         hres = ITypeInfo_GetFuncDesc(tinfo,n,&fdesc);
251         if (fdesc->oVft/4 > max)
252             max = fdesc->oVft/4;
253         if (hres)
254             return max+1;
255         n++;
256     }
257     /*NOTREACHED*/
258 }
259
260 typedef struct _TMAsmProxy {
261     BYTE        popleax;
262     BYTE        pushlval;
263     BYTE        nr;
264     BYTE        pushleax;
265     BYTE        lcall;
266     DWORD       xcall;
267     BYTE        lret;
268     WORD        bytestopop;
269 } WINE_PACKED TMAsmProxy;
270
271 typedef struct _TMProxyImpl {
272     DWORD                               *lpvtbl;
273     ICOM_VTABLE(IRpcProxyBuffer)        *lpvtbl2;
274     DWORD                               ref;
275
276     TMAsmProxy                          *asmstubs;
277     ITypeInfo*                          tinfo;
278     IRpcChannelBuffer*                  chanbuf;
279     IID                                 iid;
280 } TMProxyImpl;
281
282 static HRESULT WINAPI
283 TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv) {
284     TRACE("()\n");
285     if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {
286         *ppv = (LPVOID)iface;
287         IRpcProxyBuffer_AddRef(iface);
288         return S_OK;
289     }
290     FIXME("no interface for %s\n",debugstr_guid(riid));
291     return E_NOINTERFACE;
292 }
293
294 static ULONG WINAPI
295 TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface) {
296     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
297
298     TRACE("()\n");
299     This->ref++;
300     return This->ref;
301 }
302
303 static ULONG WINAPI
304 TMProxyImpl_Release(LPRPCPROXYBUFFER iface) {
305     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
306
307     TRACE("()\n");
308     This->ref--;
309     if (This->ref) return This->ref;
310     if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
311     HeapFree(GetProcessHeap(),0,This);
312     return 0;
313 }
314
315 static HRESULT WINAPI
316 TMProxyImpl_Connect(
317     LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer
318 ) {
319     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
320
321     TRACE("(%p)\n",pRpcChannelBuffer);
322     This->chanbuf = pRpcChannelBuffer;
323     IRpcChannelBuffer_AddRef(This->chanbuf);
324     return S_OK;
325 }
326
327 static void WINAPI
328 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface) {
329     ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
330
331     FIXME("()\n");
332     IRpcChannelBuffer_Release(This->chanbuf);
333     This->chanbuf = NULL;
334 }
335
336
337 static ICOM_VTABLE(IRpcProxyBuffer) tmproxyvtable = {
338     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
339     TMProxyImpl_QueryInterface,
340     TMProxyImpl_AddRef,
341     TMProxyImpl_Release,
342     TMProxyImpl_Connect,
343     TMProxyImpl_Disconnect
344 };
345
346 static HRESULT
347 marshall_param(
348     ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
349 ) {
350     int relaydeb = TRACE_ON(olerelay);
351     HRESULT     hres;
352
353     if (!tdesc) tdesc = &(elem->tdesc);
354     switch (tdesc->vt) {
355     case VT_NULL:
356         return S_OK;
357     case VT_BSTR: {     /* DWORD size, string data */
358             DWORD *bstr = ((DWORD*)(*arg))-1;
359
360             if (relaydeb) MESSAGE("%s",debugstr_w((LPWSTR)(bstr+1)));
361             return xbuf_add(buf,(LPBYTE)bstr,bstr[0]+4);
362         }
363     case VT_BOOL:
364     case VT_I4:
365         if (relaydeb) MESSAGE("%ld",*arg);
366         return xbuf_add(buf,(LPBYTE)arg,4);
367     case VT_VARIANT: {
368         /* We use ourselves to marshal the value further */
369         TYPEDESC tdesc2;
370         VARIANT *vt = (VARIANT*)arg;
371         DWORD vttype = V_VT(vt);
372
373         hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
374         if (hres) return hres;
375         tdesc2.vt = vttype;
376         if (relaydeb) MESSAGE("Vt %ld ",vttype);
377         /* shield your eyes, bad pointer voodoo below */
378         return marshall_param(tinfo,elem,&tdesc2,(DWORD*)&(V_I4(vt)),buf);
379     }
380     case VT_PTR:
381         return marshall_param(tinfo,elem,tdesc->u.lptdesc,(DWORD*)*arg,buf);
382     case VT_VOID:
383         hres = _marshal_interface(buf,&(buf->iid),(LPUNKNOWN)arg);
384         if (hres) {
385             FIXME("Failed unmarshaling VT_VOID with guid %s?\n",debugstr_guid(&(buf->iid)));
386         }
387         return hres;
388     case VT_USERDEFINED: {
389         ITypeInfo       *tinfo2;
390         TYPEATTR        *tattr;
391
392         /*FIXME("VT_USERDEFINED arg is %p, *arg is %p\n",arg,*arg);*/
393         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
394         if (hres) {
395             FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
396             return hres;
397         }
398         ITypeInfo_GetTypeAttr(tinfo2,&tattr);
399         switch (tattr->typekind) {
400         case TKIND_INTERFACE:
401             if (relaydeb) MESSAGE("if(%p), vtbl %p",arg,(LPVOID)*arg);
402             hres = _marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
403             break;
404         case TKIND_RECORD:
405             if (relaydeb) MESSAGE("record %p",arg);
406             if (buf->thisisiid)
407                 memcpy(&(buf->iid),arg,sizeof(buf->iid));
408             hres = xbuf_add(buf,(LPBYTE)arg,tattr->cbSizeInstance);
409             break;
410         default:
411             FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
412             hres = E_FAIL;
413             break;
414         }
415         ITypeInfo_Release(tinfo2);
416         return hres;
417     }
418     default:
419         ERR("Cannot marshal type %d\n",tdesc->vt);
420         /*dump_ELEMDESC(elem);*/
421         return E_FAIL;
422     }
423     return S_OK;
424 }
425
426 static HRESULT
427 unmarshall_param(
428     ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
429 ) {
430     HRESULT hres = S_OK;
431     int relaydeb = TRACE_ON(olerelay);
432
433     if (!tdesc) tdesc = &(elem->tdesc);
434     switch (tdesc->vt) {
435     case VT_I4: {
436         DWORD x;
437         xbuf_get(buf,(LPBYTE)&x,sizeof(x));
438         *arg = x;
439         if (relaydeb) MESSAGE("%ld ",x);
440         return S_OK;
441     }
442     case VT_PTR:
443         if ((tdesc->u.lptdesc->vt != VT_USERDEFINED) &&
444             (tdesc->u.lptdesc->vt != VT_VOID)
445         )
446             hres = unmarshall_param(tinfo,elem,tdesc->u.lptdesc,(DWORD*)(*arg),buf);
447         else
448             hres = unmarshall_param(tinfo,elem,tdesc->u.lptdesc,arg,buf);
449         if (relaydeb) MESSAGE("%p ",(LPVOID)*arg);
450         return S_OK;
451     case VT_USERDEFINED: {
452         ITypeInfo       *tinfo2;
453         TYPEATTR        *tattr;
454
455         if (relaydeb) MESSAGE("%p",arg);
456         hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
457         if (hres) {
458             FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
459             return hres;
460         }
461         hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
462         if (hres) {
463             FIXME("Could not get typeattr in VT_USERDEFINED.\n");
464             return hres;
465         }
466         switch (tattr->typekind) {
467         case TKIND_INTERFACE:
468             hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
469             break;
470         case TKIND_RECORD:
471             hres = xbuf_get(buf,(LPBYTE)arg,tattr->cbSizeInstance);
472             break;
473         default:
474             hres = E_FAIL;
475             FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
476         }
477         ITypeInfo_Release(tinfo2);
478         return hres;
479     }
480     case VT_VOID: 
481         /* Hacky. If we are LPVOID* we apparently have to guess the IID
482          * for the interface. This sucks pretty badly. */
483         return _unmarshal_interface(buf,&(buf->iid),(LPUNKNOWN*)arg);
484     default:    ERR("Cannot unmarshal type %d\n",tdesc->vt);
485                 return E_FAIL;
486     }
487     return S_OK;
488 }
489
490 /* Searches function, also in inherited interfaces */
491 static HRESULT
492 _get_funcdesc(
493         ITypeInfo *tinfo, int iMethod, FUNCDESC **fdesc,
494         BSTR *iname, BSTR *fname
495 ) {
496     int i = 0, j = 0;
497     HRESULT hres;
498
499     if (fname) *fname = NULL;
500     if (iname) *iname = NULL;
501
502     while (1) {
503         hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc);
504         if (hres) {
505             ITypeInfo   *tinfo2;
506             HREFTYPE    href;
507             TYPEATTR    *attr;
508
509             hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
510             if (hres) {
511                 FIXME("GetTypeAttr failed with %lx\n",hres);
512                 return hres;
513             }
514             /* Not found, so look in inherited ifaces. */
515             for (j=0;j<attr->cImplTypes;j++) {
516                 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
517                 if (hres) {
518                     FIXME("Did not find a reftype for interface offset %d?\n",j);
519                     break;
520                 }
521                 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
522                 if (hres) {
523                     FIXME("Did not find a typeinfo for reftype %ld?\n",href);
524                     continue;
525                 }
526                 hres = _get_funcdesc(tinfo2,iMethod,fdesc,iname,fname);
527                 ITypeInfo_Release(tinfo2);
528                 if (!hres) return S_OK;
529             }
530             return E_FAIL;
531         }
532         if (((*fdesc)->oVft/4) == iMethod) {
533             if (fname)
534                 ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
535             if (iname)
536                 ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
537             return S_OK;
538         }
539         i++;
540     }
541     return E_FAIL;
542 }
543
544 /* how much space do we use on stack in DWORD steps. */
545 static int 
546 _argsize(DWORD vt_type) {
547     switch (vt_type) {
548     case VT_VARIANT:
549         return (sizeof(VARIANT)+3)/sizeof(DWORD);
550     default:
551         return 1;
552     }
553 }
554
555 static DWORD
556 xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) {
557     DWORD               *args = ((DWORD*)&tpinfo)+1, *xargs;
558     FUNCDESC            *fdesc;
559     HRESULT             hres;
560     int                 i, relaydeb = TRACE_ON(olerelay);
561     marshal_state       buf;
562     RPCOLEMESSAGE       msg;
563     ULONG               status;
564     BSTR                fname,iname;
565     BSTR                names[10];
566     int                 nrofnames;
567
568     hres = _get_funcdesc(tpinfo->tinfo,method,&fdesc,&iname,&fname);
569     if (hres) {
570         ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
571         return 0;
572     }
573
574     /*dump_FUNCDESC(fdesc);*/
575     if (relaydeb) {
576         TRACE_(olerelay)("->");
577         if (iname)
578             MESSAGE("%s:",debugstr_w(iname));
579         if (fname)
580             MESSAGE("%s(%d)",debugstr_w(fname),method);
581         else
582             MESSAGE("%d",method);
583         MESSAGE("(");
584         if (iname) SysFreeString(iname);
585         if (fname) SysFreeString(fname);
586     }
587     /* Need them for hack below */
588     memset(names,0,sizeof(names));
589     ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
590     if (nrofnames > sizeof(names)/sizeof(names[0])) {
591         ERR("Need more names!\n");
592     }
593     memset(&buf,0,sizeof(buf));
594     buf.iid = IID_IUnknown;
595     if (method == 0) {
596         xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));
597         if (relaydeb) MESSAGE("riid=%s,[out]",debugstr_guid((REFIID)args[0]));
598     } else {
599         xargs = args;
600         for (i=0;i<fdesc->cParams;i++) {
601             ELEMDESC    *elem = fdesc->lprgelemdescParam+i;
602             if (relaydeb) {
603                 if (i) MESSAGE(",");
604                 if (i+1<nrofnames && names[i+1])
605                     MESSAGE("%s=",debugstr_w(names[i+1]));
606             }
607             if (((i+1)<nrofnames) && !lstrcmpW(names[i+1],riidW)) {
608                 buf.thisisiid = TRUE;
609             } else {
610                 buf.thisisiid = FALSE;
611             }
612             /* No need to marshal other data than FIN */
613             if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)) {
614                 xargs+=_argsize(elem->tdesc.vt);
615                 if (relaydeb) MESSAGE("[out]");
616                 continue;
617             }
618             hres = marshall_param(tpinfo->tinfo,elem,NULL,xargs,&buf);
619             xargs+=_argsize(elem->tdesc.vt);
620             if (hres) {
621                 FIXME("Failed to marshall param, hres %lx\n",hres);
622                 break;
623             }
624         }
625     }
626     if (relaydeb) MESSAGE(")");
627     memset(&msg,0,sizeof(msg));
628     msg.cbBuffer = buf.curoff;
629     msg.iMethod  = method;
630     hres = IRpcChannelBuffer_GetBuffer(tpinfo->chanbuf,&msg,&(tpinfo->iid));
631     if (hres) {
632         FIXME("RpcChannelBuffer GetBuffer failed, %lx\n",hres);
633         return hres;
634     }
635     memcpy(msg.Buffer,buf.base,buf.curoff);
636     hres = IRpcChannelBuffer_SendReceive(tpinfo->chanbuf,&msg,&status);
637     if (hres) {
638         FIXME("RpcChannelBuffer SendReceive failed, %lx\n",hres);
639         return hres;
640     }
641     if (relaydeb) MESSAGE(" = %08lx (",status);
642     if (buf.base)
643         buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
644     else
645         buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
646     buf.size = msg.cbBuffer;
647     memcpy(buf.base,msg.Buffer,buf.size);
648     buf.curoff = 0;
649     if (method == 0) {
650         _unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]);
651         if (relaydeb) MESSAGE("[in],%p",*((DWORD**)args[1]));
652     } else {
653         xargs = args;
654         for (i=0;i<fdesc->cParams;i++) {
655             ELEMDESC    *elem = fdesc->lprgelemdescParam+i;
656
657             if (relaydeb) {
658                 if (i) MESSAGE(",");
659                 if (i+1<nrofnames && names[i+1]) MESSAGE("%s=",debugstr_w(names[i+1]));
660             }
661             /* No need to marshal other data than FOUT I think */
662             if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)) {
663                 xargs += _argsize(elem->tdesc.vt);
664                 if (relaydeb) MESSAGE("[in]");
665                 continue;
666             }
667             hres = unmarshall_param(tpinfo->tinfo,elem,&(elem->tdesc),xargs,&buf);
668             xargs += _argsize(elem->tdesc.vt);
669             if (hres) {
670                 FIXME("Failed to unmarshall param, hres %lx\n",hres);
671                 break;
672             }
673         }
674     }
675     if (relaydeb) MESSAGE(")\n");
676     HeapFree(GetProcessHeap(),0,buf.base);
677     return status;
678 }
679
680 static HRESULT WINAPI
681 PSFacBuf_CreateProxy(
682     LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
683     IRpcProxyBuffer **ppProxy, LPVOID *ppv
684 ) {
685     HRESULT     hres;
686     ITypeInfo   *tinfo;
687     int         i, nroffuncs;
688     FUNCDESC    *fdesc;
689     TMProxyImpl *proxy;
690     
691     TRACE("(...%s...)\n",debugstr_guid(riid));
692     hres = _get_typeinfo_for_iid(riid,&tinfo);
693     if (hres) {
694         FIXME("No typeinfo for %s?\n",debugstr_guid(riid));
695         return hres;
696     }
697     nroffuncs = _nroffuncs(tinfo);
698     proxy = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TMProxyImpl));
699     if (!proxy) return E_OUTOFMEMORY;
700     proxy->asmstubs=HeapAlloc(GetProcessHeap(),0,sizeof(TMAsmProxy)*nroffuncs);
701
702     assert(sizeof(TMAsmProxy) == 12);
703
704     proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
705     for (i=0;i<nroffuncs;i++) {
706         int             nrofargs;
707         TMAsmProxy      *xasm = proxy->asmstubs+i;
708
709         /* nrofargs without This */
710         switch (i) {
711         case 0: nrofargs = 2;
712                 break;
713         case 1: case 2: nrofargs = 0;
714                 break;
715         default: {
716                 int j;
717                 hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);
718                 if (hres) {
719                     FIXME("GetFuncDesc %lx should not fail here.\n",hres);
720                     return hres;
721                 }
722                 /* some args take more than 4 byte on the stack */
723                 nrofargs = 0;
724                 for (j=0;j<fdesc->cParams;j++)
725                     nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
726
727                 if (fdesc->callconv != CC_STDCALL) {
728                     ERR("calling convention is not stdcall????\n");
729                     return E_FAIL;
730                 }
731                 break;
732             }
733         }
734 /* popl %eax    -       return ptr
735  * pushl <nr>
736  * pushl %eax
737  * call xCall
738  * lret <nr> (+4)
739  *
740  *
741  * arg3 arg2 arg1 <method> <returnptr>
742  */
743         xasm->popleax   = 0x58;
744         xasm->pushlval  = 0x6a;
745         xasm->nr        = i;
746         xasm->pushleax  = 0x50;
747         xasm->lcall     = 0xe8; /* relative jump */
748         xasm->xcall     = (DWORD)xCall;
749         xasm->xcall     -= (DWORD)&(xasm->lret);
750         xasm->lret      = 0xc2;
751         xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
752         proxy->lpvtbl[i] = (DWORD)xasm;
753     }
754     proxy->lpvtbl2      = &tmproxyvtable;
755     proxy->ref          = 2;
756     proxy->tinfo        = tinfo;
757     memcpy(&proxy->iid,riid,sizeof(*riid));
758     *ppv                = (LPVOID)proxy;
759     *ppProxy            = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
760     return S_OK;
761 }
762
763 typedef struct _TMStubImpl {
764     ICOM_VTABLE(IRpcStubBuffer) *lpvtbl;
765     DWORD                       ref;
766
767     LPUNKNOWN                   pUnk;
768     ITypeInfo                   *tinfo;
769     IID                         iid;
770 } TMStubImpl;
771
772 static HRESULT WINAPI
773 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv) {
774     if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
775         *ppv = (LPVOID)iface;
776         IRpcStubBuffer_AddRef(iface);
777         return S_OK;
778     }
779     FIXME("%s, not supported IID.\n",debugstr_guid(riid));
780     return E_NOINTERFACE;
781 }
782
783 static ULONG WINAPI
784 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface) {
785     ICOM_THIS(TMStubImpl,iface);
786
787     This->ref++;
788     return This->ref;
789 }
790
791 static ULONG WINAPI
792 TMStubImpl_Release(LPRPCSTUBBUFFER iface) {
793     ICOM_THIS(TMStubImpl,iface);
794
795     This->ref--;
796     if (This->ref)
797         return This->ref;
798     HeapFree(GetProcessHeap(),0,This);
799     return 0;
800 }
801
802 static HRESULT WINAPI
803 TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer) {
804     ICOM_THIS(TMStubImpl,iface);
805
806     IUnknown_AddRef(pUnkServer);
807     This->pUnk = pUnkServer;
808     return S_OK;
809 }
810
811 static void WINAPI
812 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface) {
813     ICOM_THIS(TMStubImpl,iface);
814
815     IUnknown_Release(This->pUnk);
816     This->pUnk = NULL;
817     return;
818 }
819
820 static HRESULT
821 stuballoc_param(
822     ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
823 ) {
824     HRESULT hres;
825
826     while (1) {
827         switch (tdesc->vt) {
828         case VT_VARIANT: {
829             DWORD       vttype;
830             VARIANT     *vt = (VARIANT*)arg;
831             TYPEDESC    tdesc2;
832
833             hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
834             if (hres) return hres;
835             memset(&tdesc2,0,sizeof(tdesc));
836             tdesc2.vt = vttype;
837             V_VT(vt)  = vttype;
838             return stuballoc_param(tinfo,elem,&tdesc2,&(V_I4(vt)),buf);
839         }
840         case VT_BOOL: case VT_I4:
841             xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
842             return S_OK;
843         case VT_BSTR: {
844                 WCHAR   *str;
845                 DWORD   len;
846
847                 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
848                 if (hres)
849                     return hres;
850                 str  = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));
851                 hres = xbuf_get(buf,(LPBYTE)str,len);
852                 if (hres) return hres;
853                 *arg = (DWORD)SysAllocStringLen(str,len);
854                 HeapFree(GetProcessHeap(),0,str);
855                 return S_OK;
856             }
857         case VT_PTR:
858             if ((tdesc->u.lptdesc->vt != VT_USERDEFINED) &&
859                 (tdesc->u.lptdesc->vt != VT_VOID)
860             ) {
861                 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPVOID));
862                 arg = (DWORD*)*arg;
863             }
864             tdesc = tdesc->u.lptdesc;
865             break;
866         case VT_UNKNOWN:
867             /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
868             *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
869             return S_OK;
870         case VT_VOID:
871             *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID));
872             hres = S_OK;
873             if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)
874                 hres = _unmarshal_interface(buf,&(buf->iid),(LPUNKNOWN*)arg);
875             return hres;
876         case VT_USERDEFINED: {
877             if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) {
878                 ITypeInfo       *tinfo2;
879                 TYPEATTR        *tattr;
880
881                 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
882                 if (hres) {
883                     FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
884                     return hres;
885                 }
886                 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
887                 if (hres) {
888                     FIXME("Could not get typeattr in VT_USERDEFINED.\n");
889                     return hres;
890                 }
891                 switch (tattr->typekind) {
892                 case TKIND_INTERFACE:
893                     hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
894                     break;
895                 case TKIND_RECORD:
896                     *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,tattr->cbSizeInstance);
897                     hres = xbuf_get(buf,(LPBYTE)*arg,tattr->cbSizeInstance);
898                     if (buf->thisisiid)
899                         memcpy(&(buf->iid),(LPBYTE)*arg,sizeof(buf->iid));
900                     break;
901                 default:
902                     FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
903                     hres = E_FAIL;
904                     break;
905                 }
906                 ITypeInfo_Release(tinfo2);
907                 return hres;
908             } else {
909                 *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID));
910                 return S_OK;
911             }
912         }
913         default:
914             ERR("No handler for VT type %d, just allocating 4 bytes.\n",tdesc->vt);
915             *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
916             return S_OK;
917         }
918     }
919 }
920
921 static HRESULT
922 stubunalloc_param(
923     ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
924 ) {
925     HRESULT hres = S_OK;
926
927     if (!tdesc) tdesc = &(elem->tdesc);
928
929     switch (tdesc->vt) {
930     case VT_BOOL:
931     case VT_I4: 
932         hres = S_OK;
933         if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)
934             hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
935         return hres;
936     case VT_VARIANT: {
937         TYPEDESC        tdesc2;
938         VARIANT         *vt = (VARIANT*)arg;
939         DWORD           vttype = V_VT(vt);
940
941         tdesc2.vt = vttype;
942         if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
943             hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
944             if (hres) return hres;
945         }
946         /* need to recurse since we need to free the stuff */
947         hres = stubunalloc_param(tinfo,elem,&tdesc2,&(V_I4(vt)),buf);
948         return hres;
949     }
950     case VT_BSTR: {
951         if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
952             DWORD *bstr = ((DWORD*)(*arg))-1;
953
954             hres = xbuf_add(buf,(LPBYTE)bstr,bstr[0]+4);
955             if (hres)
956                 return hres;
957         }
958         SysFreeString((BSTR)*arg);
959         return S_OK;
960     }
961     case VT_PTR:
962         /*FIXME("VT_PTR *arg is %p\n",(LPVOID)*arg);*/
963         if ((tdesc->u.lptdesc->vt != VT_USERDEFINED) &&
964             (tdesc->u.lptdesc->vt != VT_VOID)
965         ) {
966             hres = stubunalloc_param(tinfo,elem,tdesc->u.lptdesc,arg,buf);
967         } else {
968             hres = stubunalloc_param(tinfo,elem,tdesc->u.lptdesc,(DWORD*)*arg,buf);
969             HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
970         }
971         return hres;
972     case VT_UNKNOWN:
973         if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
974             FIXME("Marshaling back VT_UNKNOWN %lx\n",*arg);
975             hres = xbuf_add(buf,(LPBYTE)*arg,sizeof(DWORD));
976         }
977         HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
978         return hres;
979     case VT_VOID:
980         hres = S_OK;
981         if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)
982             hres = _marshal_interface(buf,&(buf->iid),(LPUNKNOWN)*arg);
983         return hres;
984     case VT_USERDEFINED: {
985         ITypeInfo       *tinfo2;
986         TYPEATTR        *tattr;
987
988         if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
989             /*FIXME("VT_USERDEFINED arg is %p, *arg is %p\n",arg,*arg);*/
990             hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
991             if (hres) {
992                 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
993                 return hres;
994             }
995             ITypeInfo_GetTypeAttr(tinfo2,&tattr);
996             switch (tattr->typekind) {
997             case TKIND_INTERFACE:
998                 hres = _marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)*arg);
999                 break;
1000             case TKIND_RECORD:
1001                 hres = xbuf_add(buf,(LPBYTE)arg,tattr->cbSizeInstance);
1002                 break;
1003             default:
1004                 FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
1005                 hres = E_FAIL;
1006                 break;
1007             }
1008             ITypeInfo_Release(tinfo2);
1009         }
1010         return hres;
1011     }
1012     default:
1013         ERR("Unhandled marshal type %d.\n",tdesc->vt);
1014         HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
1015         return S_OK;
1016     }
1017 }
1018
1019 static HRESULT WINAPI
1020 TMStubImpl_Invoke(
1021     LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf
1022 ) {
1023     int         i;
1024     FUNCDESC    *fdesc;
1025     ICOM_THIS(TMStubImpl,iface);
1026     HRESULT     hres;
1027     DWORD       *args, res, *xargs, nrofargs;
1028     marshal_state       buf;
1029     int         nrofnames;
1030     BSTR        names[10];
1031
1032     memset(&buf,0,sizeof(buf));
1033     buf.size    = xmsg->cbBuffer;
1034     buf.base    = xmsg->Buffer;
1035     buf.curoff  = 0;
1036     buf.iid     = IID_IUnknown;
1037
1038     TRACE("...\n");
1039     if (xmsg->iMethod == 0) { /* QI */
1040         IID             xiid;
1041         /* in: IID, out: <iface> */
1042
1043         xbuf_get(&buf,(LPBYTE)&xiid,sizeof(xiid));
1044         buf.curoff = 0;
1045         hres = _marshal_interface(&buf,&xiid,This->pUnk);
1046         xmsg->Buffer    = buf.base; /* Might have been reallocated */
1047         xmsg->cbBuffer  = buf.size;
1048         return hres;
1049     }
1050     hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,NULL,NULL);
1051     if (hres) {
1052         FIXME("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
1053         return hres;
1054     }
1055     /* Need them for hack below */
1056     memset(names,0,sizeof(names));
1057     ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
1058     if (nrofnames > sizeof(names)/sizeof(names[0])) {
1059         ERR("Need more names!\n");
1060     }
1061
1062     /*dump_FUNCDESC(fdesc);*/
1063     nrofargs = 0;
1064     for (i=0;i<fdesc->cParams;i++)
1065         nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
1066     args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
1067     if (!args) return E_OUTOFMEMORY;
1068
1069     /* Allocate all stuff used by call. */
1070     xargs = args+1;
1071     for (i=0;i<fdesc->cParams;i++) {
1072         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1073
1074         if (((i+1)<nrofnames) && !lstrcmpW(names[i+1],riidW))
1075             buf.thisisiid = TRUE;
1076         else
1077             buf.thisisiid = FALSE;
1078         hres   = stuballoc_param(This->tinfo,elem,&(elem->tdesc),xargs,&buf);
1079         xargs += _argsize(elem->tdesc.vt);
1080         if (hres) {
1081             FIXME("Failed to stuballoc param %s, hres %lx\n",debugstr_w(names[i+1]),hres);
1082             break;
1083         }
1084     }
1085     hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0]));
1086     if (hres) {
1087         ERR("Does not support iface %s\n",debugstr_guid(&(This->iid)));
1088         return hres;
1089     }
1090     res = _invoke(
1091             (*((LPVOID**)args[0]))[fdesc->oVft/4],
1092             fdesc->callconv,
1093             (xargs-args),
1094             args
1095     );
1096     IUnknown_Release((LPUNKNOWN)args[0]);
1097     buf.curoff = 0;
1098     xargs = args+1;
1099     for (i=0;i<fdesc->cParams;i++) {
1100         ELEMDESC        *elem = fdesc->lprgelemdescParam+i;
1101         hres = stubunalloc_param(This->tinfo,elem,NULL,xargs,&buf);
1102         xargs += _argsize(elem->tdesc.vt);
1103         if (hres) {
1104             FIXME("Failed to stuballoc param, hres %lx\n",hres);
1105             break;
1106         }
1107     }
1108     /* might need to use IRpcChannelBuffer_GetBuffer ? */
1109     xmsg->cbBuffer      = buf.curoff;
1110     xmsg->Buffer        = buf.base;
1111     HeapFree(GetProcessHeap(),0,args);
1112     return res;
1113 }
1114
1115 static LPRPCSTUBBUFFER WINAPI
1116 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
1117     FIXME("Huh (%s)?\n",debugstr_guid(riid));
1118     return NULL;
1119 }
1120
1121 static ULONG WINAPI
1122 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
1123     ICOM_THIS(TMStubImpl,iface);
1124
1125     return This->ref; /*FIXME? */
1126 }
1127
1128 static HRESULT WINAPI
1129 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
1130     return E_NOTIMPL;
1131 }
1132
1133 static void WINAPI
1134 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
1135     return;
1136 }
1137
1138 ICOM_VTABLE(IRpcStubBuffer) tmstubvtbl = {
1139     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1140     TMStubImpl_QueryInterface,
1141     TMStubImpl_AddRef,
1142     TMStubImpl_Release,
1143     TMStubImpl_Connect,
1144     TMStubImpl_Disconnect,
1145     TMStubImpl_Invoke,
1146     TMStubImpl_IsIIDSupported,
1147     TMStubImpl_CountRefs,
1148     TMStubImpl_DebugServerQueryInterface,
1149     TMStubImpl_DebugServerRelease
1150 };
1151
1152 static HRESULT WINAPI
1153 PSFacBuf_CreateStub(
1154     LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
1155     IRpcStubBuffer** ppStub
1156 ) {
1157     HRESULT hres;
1158     ITypeInfo   *tinfo;
1159     TMStubImpl  *stub;
1160
1161     TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
1162     hres = _get_typeinfo_for_iid(riid,&tinfo);
1163     if (hres) {
1164         FIXME("No typeinfo for %s?\n",debugstr_guid(riid));
1165         return hres;
1166     }
1167     stub = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TMStubImpl));
1168     if (!stub)
1169         return E_OUTOFMEMORY;
1170     stub->lpvtbl        = &tmstubvtbl;
1171     stub->ref           = 1;
1172     stub->tinfo         = tinfo;
1173     memcpy(&(stub->iid),riid,sizeof(*riid));
1174     hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
1175     *ppStub             = (LPRPCSTUBBUFFER)stub;
1176     if (hres)
1177         FIXME("Connect to pUnkServer failed?\n");
1178     return hres;
1179 }
1180
1181 static ICOM_VTABLE(IPSFactoryBuffer) psfacbufvtbl = {
1182     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1183     PSFacBuf_QueryInterface,
1184     PSFacBuf_AddRef,
1185     PSFacBuf_Release,
1186     PSFacBuf_CreateProxy,
1187     PSFacBuf_CreateStub
1188 };
1189
1190 /* This is the whole PSFactoryBuffer object, just the vtableptr */
1191 static ICOM_VTABLE(IPSFactoryBuffer) *lppsfac = &psfacbufvtbl;
1192
1193 /***********************************************************************
1194  *           DllGetClassObject [OLE32.63]
1195  */
1196 HRESULT WINAPI
1197 TypeLibFac_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1198 {
1199     if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
1200         *ppv = &lppsfac;
1201         return S_OK;
1202     }
1203     return E_NOINTERFACE;
1204 }