source: trunk/src/oleaut32/tmarshal.c@ 7936

Last change on this file since 7936 was 7936, checked in by sandervl, 24 years ago

packing & calling convention fix

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