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

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

Wine 20020215 resync + added extended logging

File size: 32.3 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
266typedef struct _TMAsmProxy {
267 BYTE popleax;
268 BYTE pushlval;
269 BYTE nr;
270 BYTE pushleax;
271 BYTE lcall;
272 DWORD xcall;
273 BYTE lret;
274 WORD bytestopop;
275} WINE_PACKED TMAsmProxy;
276
277typedef struct _TMProxyImpl {
278 DWORD *lpvtbl;
279 ICOM_VTABLE(IRpcProxyBuffer) *lpvtbl2;
280 DWORD ref;
281
282 TMAsmProxy *asmstubs;
283 ITypeInfo* tinfo;
284 IRpcChannelBuffer* chanbuf;
285 IID iid;
286} TMProxyImpl;
287
288static HRESULT WINAPI
289TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *ppv) {
290 TRACE("()\n");
291 if (IsEqualIID(riid,&IID_IUnknown)||IsEqualIID(riid,&IID_IRpcProxyBuffer)) {
292 *ppv = (LPVOID)iface;
293 IRpcProxyBuffer_AddRef(iface);
294 return S_OK;
295 }
296 FIXME("no interface for %s\n",debugstr_guid(riid));
297 return E_NOINTERFACE;
298}
299
300static ULONG WINAPI
301TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface) {
302 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
303
304 TRACE("()\n");
305 This->ref++;
306 return This->ref;
307}
308
309static ULONG WINAPI
310TMProxyImpl_Release(LPRPCPROXYBUFFER iface) {
311 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
312
313 TRACE("()\n");
314 This->ref--;
315 if (This->ref) return This->ref;
316 if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
317 HeapFree(GetProcessHeap(),0,This);
318 return 0;
319}
320
321static HRESULT WINAPI
322TMProxyImpl_Connect(
323 LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer
324) {
325 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
326
327 TRACE("(%p)\n",pRpcChannelBuffer);
328 This->chanbuf = pRpcChannelBuffer;
329 IRpcChannelBuffer_AddRef(This->chanbuf);
330 return S_OK;
331}
332
333static void WINAPI
334TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface) {
335 ICOM_THIS_MULTI(TMProxyImpl,lpvtbl2,iface);
336
337 FIXME("()\n");
338 IRpcChannelBuffer_Release(This->chanbuf);
339 This->chanbuf = NULL;
340}
341
342
343static ICOM_VTABLE(IRpcProxyBuffer) tmproxyvtable = {
344 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
345 TMProxyImpl_QueryInterface,
346 TMProxyImpl_AddRef,
347 TMProxyImpl_Release,
348 TMProxyImpl_Connect,
349 TMProxyImpl_Disconnect
350};
351
352static HRESULT
353marshall_param(
354 ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
355) {
356 int relaydeb = TRACE_ON(olerelay);
357 HRESULT hres;
358
359 if (!tdesc) tdesc = &(elem->tdesc);
360 switch (tdesc->vt) {
361 case VT_NULL:
362 return S_OK;
363 case VT_BSTR: { /* DWORD size, string data */
364 DWORD *bstr = ((DWORD*)(*arg))-1;
365
366 if (relaydeb) MESSAGE("%s",debugstr_w((LPWSTR)(bstr+1)));
367 return xbuf_add(buf,(LPBYTE)bstr,bstr[0]+4);
368 }
369 case VT_BOOL:
370 case VT_I4:
371 if (relaydeb) MESSAGE("%ld",*arg);
372 return xbuf_add(buf,(LPBYTE)arg,4);
373 case VT_VARIANT: {
374 /* We use ourselves to marshal the value further */
375 TYPEDESC tdesc2;
376 VARIANT *vt = (VARIANT*)arg;
377 DWORD vttype = V_VT(vt);
378
379 hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
380 if (hres) return hres;
381 tdesc2.vt = vttype;
382 if (relaydeb) MESSAGE("Vt %ld ",vttype);
383 /* shield your eyes, bad pointer voodoo below */
384 return marshall_param(tinfo,elem,&tdesc2,(DWORD*)&(V_I4(vt)),buf);
385 }
386 case VT_PTR:
387 return marshall_param(tinfo,elem,tdesc->u.lptdesc,(DWORD*)*arg,buf);
388 case VT_VOID:
389 hres = _marshal_interface(buf,&(buf->iid),(LPUNKNOWN)arg);
390 if (hres) {
391 FIXME("Failed unmarshaling VT_VOID with guid %s?\n",debugstr_guid(&(buf->iid)));
392 }
393 return hres;
394 case VT_USERDEFINED: {
395 ITypeInfo *tinfo2;
396 TYPEATTR *tattr;
397
398 /*FIXME("VT_USERDEFINED arg is %p, *arg is %p\n",arg,*arg);*/
399 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
400 if (hres) {
401 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
402 return hres;
403 }
404 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
405 switch (tattr->typekind) {
406 case TKIND_INTERFACE:
407 if (relaydeb) MESSAGE("if(%p), vtbl %p",arg,(LPVOID)*arg);
408 hres = _marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)arg);
409 break;
410 case TKIND_RECORD:
411 if (relaydeb) MESSAGE("record %p",arg);
412 if (buf->thisisiid)
413 memcpy(&(buf->iid),arg,sizeof(buf->iid));
414 hres = xbuf_add(buf,(LPBYTE)arg,tattr->cbSizeInstance);
415 break;
416 default:
417 FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
418 hres = E_FAIL;
419 break;
420 }
421 ITypeInfo_Release(tinfo2);
422 return hres;
423 }
424 default:
425 ERR("Cannot marshal type %d\n",tdesc->vt);
426 /*dump_ELEMDESC(elem);*/
427 return E_FAIL;
428 }
429 return S_OK;
430}
431
432static HRESULT
433unmarshall_param(
434 ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
435) {
436 HRESULT hres = S_OK;
437 int relaydeb = TRACE_ON(olerelay);
438
439 if (!tdesc) tdesc = &(elem->tdesc);
440 switch (tdesc->vt) {
441 case VT_I4: {
442 DWORD x;
443 xbuf_get(buf,(LPBYTE)&x,sizeof(x));
444 *arg = x;
445 if (relaydeb) MESSAGE("%ld ",x);
446 return S_OK;
447 }
448 case VT_PTR:
449 if ((tdesc->u.lptdesc->vt != VT_USERDEFINED) &&
450 (tdesc->u.lptdesc->vt != VT_VOID)
451 )
452 hres = unmarshall_param(tinfo,elem,tdesc->u.lptdesc,(DWORD*)(*arg),buf);
453 else
454 hres = unmarshall_param(tinfo,elem,tdesc->u.lptdesc,arg,buf);
455 if (relaydeb) MESSAGE("%p ",(LPVOID)*arg);
456 return S_OK;
457 case VT_USERDEFINED: {
458 ITypeInfo *tinfo2;
459 TYPEATTR *tattr;
460
461 if (relaydeb) MESSAGE("%p",arg);
462 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
463 if (hres) {
464 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
465 return hres;
466 }
467 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
468 if (hres) {
469 FIXME("Could not get typeattr in VT_USERDEFINED.\n");
470 return hres;
471 }
472 switch (tattr->typekind) {
473 case TKIND_INTERFACE:
474 hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
475 break;
476 case TKIND_RECORD:
477 hres = xbuf_get(buf,(LPBYTE)arg,tattr->cbSizeInstance);
478 break;
479 default:
480 hres = E_FAIL;
481 FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
482 }
483 ITypeInfo_Release(tinfo2);
484 return hres;
485 }
486 case VT_VOID:
487 /* Hacky. If we are LPVOID* we apparently have to guess the IID
488 * for the interface. This sucks pretty badly. */
489 return _unmarshal_interface(buf,&(buf->iid),(LPUNKNOWN*)arg);
490 default: ERR("Cannot unmarshal type %d\n",tdesc->vt);
491 return E_FAIL;
492 }
493 return S_OK;
494}
495
496/* Searches function, also in inherited interfaces */
497static HRESULT
498_get_funcdesc(
499 ITypeInfo *tinfo, int iMethod, FUNCDESC **fdesc,
500 BSTR *iname, BSTR *fname
501) {
502 int i = 0, j = 0;
503 HRESULT hres;
504
505 if (fname) *fname = NULL;
506 if (iname) *iname = NULL;
507
508 while (1) {
509 hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc);
510 if (hres) {
511 ITypeInfo *tinfo2;
512 HREFTYPE href;
513 TYPEATTR *attr;
514
515 hres = ITypeInfo_GetTypeAttr(tinfo, &attr);
516 if (hres) {
517 FIXME("GetTypeAttr failed with %lx\n",hres);
518 return hres;
519 }
520 /* Not found, so look in inherited ifaces. */
521 for (j=0;j<attr->cImplTypes;j++) {
522 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, j, &href);
523 if (hres) {
524 FIXME("Did not find a reftype for interface offset %d?\n",j);
525 break;
526 }
527 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
528 if (hres) {
529 FIXME("Did not find a typeinfo for reftype %ld?\n",href);
530 continue;
531 }
532 hres = _get_funcdesc(tinfo2,iMethod,fdesc,iname,fname);
533 ITypeInfo_Release(tinfo2);
534 if (!hres) return S_OK;
535 }
536 return E_FAIL;
537 }
538 if (((*fdesc)->oVft/4) == iMethod) {
539 if (fname)
540 ITypeInfo_GetDocumentation(tinfo,(*fdesc)->memid,fname,NULL,NULL,NULL);
541 if (iname)
542 ITypeInfo_GetDocumentation(tinfo,-1,iname,NULL,NULL,NULL);
543 return S_OK;
544 }
545 i++;
546 }
547 return E_FAIL;
548}
549
550/* how much space do we use on stack in DWORD steps. */
551static int
552_argsize(DWORD vt_type) {
553 switch (vt_type) {
554 case VT_VARIANT:
555 return (sizeof(VARIANT)+3)/sizeof(DWORD);
556 default:
557 return 1;
558 }
559}
560
561static DWORD
562xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) {
563 DWORD *args = ((DWORD*)&tpinfo)+1, *xargs;
564 FUNCDESC *fdesc;
565 HRESULT hres;
566 int i, relaydeb = TRACE_ON(olerelay);
567 marshal_state buf;
568 RPCOLEMESSAGE msg;
569 ULONG status;
570 BSTR fname,iname;
571 BSTR names[10];
572 int nrofnames;
573
574 hres = _get_funcdesc(tpinfo->tinfo,method,&fdesc,&iname,&fname);
575 if (hres) {
576 ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
577 return 0;
578 }
579
580 /*dump_FUNCDESC(fdesc);*/
581 if (relaydeb) {
582 TRACE_(olerelay)("->");
583 if (iname)
584 MESSAGE("%s:",debugstr_w(iname));
585 if (fname)
586 MESSAGE("%s(%d)",debugstr_w(fname),method);
587 else
588 MESSAGE("%d",method);
589 MESSAGE("(");
590 if (iname) SysFreeString(iname);
591 if (fname) SysFreeString(fname);
592 }
593 /* Need them for hack below */
594 memset(names,0,sizeof(names));
595 ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
596 if (nrofnames > sizeof(names)/sizeof(names[0])) {
597 ERR("Need more names!\n");
598 }
599 memset(&buf,0,sizeof(buf));
600 buf.iid = IID_IUnknown;
601 if (method == 0) {
602 xbuf_add(&buf,(LPBYTE)args[0],sizeof(IID));
603 if (relaydeb) MESSAGE("riid=%s,[out]",debugstr_guid((REFIID)args[0]));
604 } else {
605 xargs = args;
606 for (i=0;i<fdesc->cParams;i++) {
607 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
608 if (relaydeb) {
609 if (i) MESSAGE(",");
610 if (i+1<nrofnames && names[i+1])
611 MESSAGE("%s=",debugstr_w(names[i+1]));
612 }
613 if (((i+1)<nrofnames) && !lstrcmpW(names[i+1],riidW)) {
614 buf.thisisiid = TRUE;
615 } else {
616 buf.thisisiid = FALSE;
617 }
618 /* No need to marshal other data than FIN */
619 if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)) {
620 xargs+=_argsize(elem->tdesc.vt);
621 if (relaydeb) MESSAGE("[out]");
622 continue;
623 }
624 hres = marshall_param(tpinfo->tinfo,elem,NULL,xargs,&buf);
625 xargs+=_argsize(elem->tdesc.vt);
626 if (hres) {
627 FIXME("Failed to marshall param, hres %lx\n",hres);
628 break;
629 }
630 }
631 }
632 if (relaydeb) MESSAGE(")");
633 memset(&msg,0,sizeof(msg));
634 msg.cbBuffer = buf.curoff;
635 msg.iMethod = method;
636 hres = IRpcChannelBuffer_GetBuffer(tpinfo->chanbuf,&msg,&(tpinfo->iid));
637 if (hres) {
638 FIXME("RpcChannelBuffer GetBuffer failed, %lx\n",hres);
639 return hres;
640 }
641 memcpy(msg.Buffer,buf.base,buf.curoff);
642 hres = IRpcChannelBuffer_SendReceive(tpinfo->chanbuf,&msg,&status);
643 if (hres) {
644 FIXME("RpcChannelBuffer SendReceive failed, %lx\n",hres);
645 return hres;
646 }
647 if (relaydeb) MESSAGE(" = %08lx (",status);
648 if (buf.base)
649 buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
650 else
651 buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
652 buf.size = msg.cbBuffer;
653 memcpy(buf.base,msg.Buffer,buf.size);
654 buf.curoff = 0;
655 if (method == 0) {
656 _unmarshal_interface(&buf,(REFIID)args[0],(LPUNKNOWN*)args[1]);
657 if (relaydeb) MESSAGE("[in],%p",*((DWORD**)args[1]));
658 } else {
659 xargs = args;
660 for (i=0;i<fdesc->cParams;i++) {
661 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
662
663 if (relaydeb) {
664 if (i) MESSAGE(",");
665 if (i+1<nrofnames && names[i+1]) MESSAGE("%s=",debugstr_w(names[i+1]));
666 }
667 /* No need to marshal other data than FOUT I think */
668 if (!(elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)) {
669 xargs += _argsize(elem->tdesc.vt);
670 if (relaydeb) MESSAGE("[in]");
671 continue;
672 }
673 hres = unmarshall_param(tpinfo->tinfo,elem,&(elem->tdesc),xargs,&buf);
674 xargs += _argsize(elem->tdesc.vt);
675 if (hres) {
676 FIXME("Failed to unmarshall param, hres %lx\n",hres);
677 break;
678 }
679 }
680 }
681 if (relaydeb) MESSAGE(")\n");
682 HeapFree(GetProcessHeap(),0,buf.base);
683 return status;
684}
685
686static HRESULT WINAPI
687PSFacBuf_CreateProxy(
688 LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
689 IRpcProxyBuffer **ppProxy, LPVOID *ppv
690) {
691 HRESULT hres;
692 ITypeInfo *tinfo;
693 int i, nroffuncs;
694 FUNCDESC *fdesc;
695 TMProxyImpl *proxy;
696
697 TRACE("(...%s...)\n",debugstr_guid(riid));
698 hres = _get_typeinfo_for_iid(riid,&tinfo);
699 if (hres) {
700 FIXME("No typeinfo for %s?\n",debugstr_guid(riid));
701 return hres;
702 }
703 nroffuncs = _nroffuncs(tinfo);
704 proxy = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TMProxyImpl));
705 if (!proxy) return E_OUTOFMEMORY;
706 proxy->asmstubs=HeapAlloc(GetProcessHeap(),0,sizeof(TMAsmProxy)*nroffuncs);
707
708 assert(sizeof(TMAsmProxy) == 12);
709
710 proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
711 for (i=0;i<nroffuncs;i++) {
712 int nrofargs;
713 TMAsmProxy *xasm = proxy->asmstubs+i;
714
715 /* nrofargs without This */
716 switch (i) {
717 case 0: nrofargs = 2;
718 break;
719 case 1: case 2: nrofargs = 0;
720 break;
721 default: {
722 int j;
723 hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);
724 if (hres) {
725 FIXME("GetFuncDesc %lx should not fail here.\n",hres);
726 return hres;
727 }
728 /* some args take more than 4 byte on the stack */
729 nrofargs = 0;
730 for (j=0;j<fdesc->cParams;j++)
731 nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
732
733 if (fdesc->callconv != CC_STDCALL) {
734 ERR("calling convention is not stdcall????\n");
735 return E_FAIL;
736 }
737 break;
738 }
739 }
740/* popl %eax - return ptr
741 * pushl <nr>
742 * pushl %eax
743 * call xCall
744 * lret <nr> (+4)
745 *
746 *
747 * arg3 arg2 arg1 <method> <returnptr>
748 */
749 xasm->popleax = 0x58;
750 xasm->pushlval = 0x6a;
751 xasm->nr = i;
752 xasm->pushleax = 0x50;
753 xasm->lcall = 0xe8; /* relative jump */
754 xasm->xcall = (DWORD)xCall;
755 xasm->xcall -= (DWORD)&(xasm->lret);
756 xasm->lret = 0xc2;
757 xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
758 proxy->lpvtbl[i] = (DWORD)xasm;
759 }
760 proxy->lpvtbl2 = &tmproxyvtable;
761 proxy->ref = 2;
762 proxy->tinfo = tinfo;
763 memcpy(&proxy->iid,riid,sizeof(*riid));
764 *ppv = (LPVOID)proxy;
765 *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
766 return S_OK;
767}
768
769typedef struct _TMStubImpl {
770 ICOM_VTABLE(IRpcStubBuffer) *lpvtbl;
771 DWORD ref;
772
773 LPUNKNOWN pUnk;
774 ITypeInfo *tinfo;
775 IID iid;
776} TMStubImpl;
777
778static HRESULT WINAPI
779TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv) {
780 if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
781 *ppv = (LPVOID)iface;
782 IRpcStubBuffer_AddRef(iface);
783 return S_OK;
784 }
785 FIXME("%s, not supported IID.\n",debugstr_guid(riid));
786 return E_NOINTERFACE;
787}
788
789static ULONG WINAPI
790TMStubImpl_AddRef(LPRPCSTUBBUFFER iface) {
791 ICOM_THIS(TMStubImpl,iface);
792
793 This->ref++;
794 return This->ref;
795}
796
797static ULONG WINAPI
798TMStubImpl_Release(LPRPCSTUBBUFFER iface) {
799 ICOM_THIS(TMStubImpl,iface);
800
801 This->ref--;
802 if (This->ref)
803 return This->ref;
804 HeapFree(GetProcessHeap(),0,This);
805 return 0;
806}
807
808static HRESULT WINAPI
809TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer) {
810 ICOM_THIS(TMStubImpl,iface);
811
812 IUnknown_AddRef(pUnkServer);
813 This->pUnk = pUnkServer;
814 return S_OK;
815}
816
817static void WINAPI
818TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface) {
819 ICOM_THIS(TMStubImpl,iface);
820
821 IUnknown_Release(This->pUnk);
822 This->pUnk = NULL;
823 return;
824}
825
826static HRESULT
827stuballoc_param(
828 ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
829) {
830 HRESULT hres;
831
832 while (1) {
833 switch (tdesc->vt) {
834 case VT_VARIANT: {
835 DWORD vttype;
836 VARIANT *vt = (VARIANT*)arg;
837 TYPEDESC tdesc2;
838
839 hres = xbuf_get(buf,(LPBYTE)&vttype,sizeof(vttype));
840 if (hres) return hres;
841 memset(&tdesc2,0,sizeof(tdesc));
842 tdesc2.vt = vttype;
843 V_VT(vt) = vttype;
844 return stuballoc_param(tinfo,elem,&tdesc2,&(V_I4(vt)),buf);
845 }
846 case VT_BOOL: case VT_I4:
847 xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
848 return S_OK;
849 case VT_BSTR: {
850 WCHAR *str;
851 DWORD len;
852
853 hres = xbuf_get(buf,(LPBYTE)&len,sizeof(DWORD));
854 if (hres)
855 return hres;
856 str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));
857 hres = xbuf_get(buf,(LPBYTE)str,len);
858 if (hres) return hres;
859 *arg = (DWORD)SysAllocStringLen(str,len);
860 HeapFree(GetProcessHeap(),0,str);
861 return S_OK;
862 }
863 case VT_PTR:
864 if ((tdesc->u.lptdesc->vt != VT_USERDEFINED) &&
865 (tdesc->u.lptdesc->vt != VT_VOID)
866 ) {
867 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPVOID));
868 arg = (DWORD*)*arg;
869 }
870 tdesc = tdesc->u.lptdesc;
871 break;
872 case VT_UNKNOWN:
873 /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
874 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
875 return S_OK;
876 case VT_VOID:
877 *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID));
878 hres = S_OK;
879 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN)
880 hres = _unmarshal_interface(buf,&(buf->iid),(LPUNKNOWN*)arg);
881 return hres;
882 case VT_USERDEFINED: {
883 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN) {
884 ITypeInfo *tinfo2;
885 TYPEATTR *tattr;
886
887 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
888 if (hres) {
889 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
890 return hres;
891 }
892 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
893 if (hres) {
894 FIXME("Could not get typeattr in VT_USERDEFINED.\n");
895 return hres;
896 }
897 switch (tattr->typekind) {
898 case TKIND_INTERFACE:
899 hres = _unmarshal_interface(buf,&(tattr->guid),(LPUNKNOWN*)arg);
900 break;
901 case TKIND_RECORD:
902 *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,tattr->cbSizeInstance);
903 hres = xbuf_get(buf,(LPBYTE)*arg,tattr->cbSizeInstance);
904 if (buf->thisisiid)
905 memcpy(&(buf->iid),(LPBYTE)*arg,sizeof(buf->iid));
906 break;
907 default:
908 FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
909 hres = E_FAIL;
910 break;
911 }
912 ITypeInfo_Release(tinfo2);
913 return hres;
914 } else {
915 *arg = (DWORD)HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID));
916 return S_OK;
917 }
918 }
919 default:
920 ERR("No handler for VT type %d, just allocating 4 bytes.\n",tdesc->vt);
921 *arg=(DWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD));
922 return S_OK;
923 }
924 }
925}
926
927static HRESULT
928stubunalloc_param(
929 ITypeInfo *tinfo, ELEMDESC *elem, TYPEDESC *tdesc, DWORD *arg, marshal_state *buf
930) {
931 HRESULT hres = S_OK;
932
933 if (!tdesc) tdesc = &(elem->tdesc);
934
935 switch (tdesc->vt) {
936 case VT_BOOL:
937 case VT_I4:
938 hres = S_OK;
939 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)
940 hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
941 return hres;
942 case VT_VARIANT: {
943 TYPEDESC tdesc2;
944 VARIANT *vt = (VARIANT*)arg;
945 DWORD vttype = V_VT(vt);
946
947 tdesc2.vt = vttype;
948 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
949 hres = xbuf_add(buf,(LPBYTE)&vttype,sizeof(vttype));
950 if (hres) return hres;
951 }
952 /* need to recurse since we need to free the stuff */
953 hres = stubunalloc_param(tinfo,elem,&tdesc2,&(V_I4(vt)),buf);
954 return hres;
955 }
956 case VT_BSTR: {
957 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
958 DWORD *bstr = ((DWORD*)(*arg))-1;
959
960 hres = xbuf_add(buf,(LPBYTE)bstr,bstr[0]+4);
961 if (hres)
962 return hres;
963 }
964 SysFreeString((BSTR)*arg);
965 return S_OK;
966 }
967 case VT_PTR:
968 /*FIXME("VT_PTR *arg is %p\n",(LPVOID)*arg);*/
969 if ((tdesc->u.lptdesc->vt != VT_USERDEFINED) &&
970 (tdesc->u.lptdesc->vt != VT_VOID)
971 ) {
972 hres = stubunalloc_param(tinfo,elem,tdesc->u.lptdesc,arg,buf);
973 } else {
974 hres = stubunalloc_param(tinfo,elem,tdesc->u.lptdesc,(DWORD*)*arg,buf);
975 HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
976 }
977 return hres;
978 case VT_UNKNOWN:
979 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
980 FIXME("Marshaling back VT_UNKNOWN %lx\n",*arg);
981 hres = xbuf_add(buf,(LPBYTE)*arg,sizeof(DWORD));
982 }
983 HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
984 return hres;
985 case VT_VOID:
986 hres = S_OK;
987 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT)
988 hres = _marshal_interface(buf,&(buf->iid),(LPUNKNOWN)*arg);
989 return hres;
990 case VT_USERDEFINED: {
991 ITypeInfo *tinfo2;
992 TYPEATTR *tattr;
993
994 if (elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT) {
995 /*FIXME("VT_USERDEFINED arg is %p, *arg is %p\n",arg,*arg);*/
996 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
997 if (hres) {
998 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc->u.hreftype);
999 return hres;
1000 }
1001 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
1002 switch (tattr->typekind) {
1003 case TKIND_INTERFACE:
1004 hres = _marshal_interface(buf,&(tattr->guid),(LPUNKNOWN)*arg);
1005 break;
1006 case TKIND_RECORD:
1007 hres = xbuf_add(buf,(LPBYTE)arg,tattr->cbSizeInstance);
1008 break;
1009 default:
1010 FIXME("Don't know how to marshal type kind %d\n",tattr->typekind);
1011 hres = E_FAIL;
1012 break;
1013 }
1014 ITypeInfo_Release(tinfo2);
1015 }
1016 return hres;
1017 }
1018 default:
1019 ERR("Unhandled marshal type %d.\n",tdesc->vt);
1020 HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
1021 return S_OK;
1022 }
1023}
1024
1025static HRESULT WINAPI
1026TMStubImpl_Invoke(
1027 LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf
1028) {
1029 int i;
1030 FUNCDESC *fdesc;
1031 ICOM_THIS(TMStubImpl,iface);
1032 HRESULT hres;
1033 DWORD *args, res, *xargs, nrofargs;
1034 marshal_state buf;
1035 int nrofnames;
1036 BSTR names[10];
1037
1038 memset(&buf,0,sizeof(buf));
1039 buf.size = xmsg->cbBuffer;
1040 buf.base = xmsg->Buffer;
1041 buf.curoff = 0;
1042 buf.iid = IID_IUnknown;
1043
1044 TRACE("...\n");
1045 if (xmsg->iMethod == 0) { /* QI */
1046 IID xiid;
1047 /* in: IID, out: <iface> */
1048
1049 xbuf_get(&buf,(LPBYTE)&xiid,sizeof(xiid));
1050 buf.curoff = 0;
1051 hres = _marshal_interface(&buf,&xiid,This->pUnk);
1052 xmsg->Buffer = buf.base; /* Might have been reallocated */
1053 xmsg->cbBuffer = buf.size;
1054 return hres;
1055 }
1056 hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,NULL,NULL);
1057 if (hres) {
1058 FIXME("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
1059 return hres;
1060 }
1061 /* Need them for hack below */
1062 memset(names,0,sizeof(names));
1063 ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
1064 if (nrofnames > sizeof(names)/sizeof(names[0])) {
1065 ERR("Need more names!\n");
1066 }
1067
1068 /*dump_FUNCDESC(fdesc);*/
1069 nrofargs = 0;
1070 for (i=0;i<fdesc->cParams;i++)
1071 nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
1072 args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
1073 if (!args) return E_OUTOFMEMORY;
1074
1075 /* Allocate all stuff used by call. */
1076 xargs = args+1;
1077 for (i=0;i<fdesc->cParams;i++) {
1078 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
1079
1080 if (((i+1)<nrofnames) && !lstrcmpW(names[i+1],riidW))
1081 buf.thisisiid = TRUE;
1082 else
1083 buf.thisisiid = FALSE;
1084 hres = stuballoc_param(This->tinfo,elem,&(elem->tdesc),xargs,&buf);
1085 xargs += _argsize(elem->tdesc.vt);
1086 if (hres) {
1087 FIXME("Failed to stuballoc param %s, hres %lx\n",debugstr_w(names[i+1]),hres);
1088 break;
1089 }
1090 }
1091 hres = IUnknown_QueryInterface(This->pUnk,&(This->iid),(LPVOID*)&(args[0]));
1092 if (hres) {
1093 ERR("Does not support iface %s\n",debugstr_guid(&(This->iid)));
1094 return hres;
1095 }
1096 res = _invoke(
1097 (*((LPVOID**)args[0]))[fdesc->oVft/4],
1098 fdesc->callconv,
1099 (xargs-args),
1100 args
1101 );
1102 IUnknown_Release((LPUNKNOWN)args[0]);
1103 buf.curoff = 0;
1104 xargs = args+1;
1105 for (i=0;i<fdesc->cParams;i++) {
1106 ELEMDESC *elem = fdesc->lprgelemdescParam+i;
1107 hres = stubunalloc_param(This->tinfo,elem,NULL,xargs,&buf);
1108 xargs += _argsize(elem->tdesc.vt);
1109 if (hres) {
1110 FIXME("Failed to stuballoc param, hres %lx\n",hres);
1111 break;
1112 }
1113 }
1114 /* might need to use IRpcChannelBuffer_GetBuffer ? */
1115 xmsg->cbBuffer = buf.curoff;
1116 xmsg->Buffer = buf.base;
1117 HeapFree(GetProcessHeap(),0,args);
1118 return res;
1119}
1120
1121static LPRPCSTUBBUFFER WINAPI
1122TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
1123 FIXME("Huh (%s)?\n",debugstr_guid(riid));
1124 return NULL;
1125}
1126
1127static ULONG WINAPI
1128TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
1129 ICOM_THIS(TMStubImpl,iface);
1130
1131 return This->ref; /*FIXME? */
1132}
1133
1134static HRESULT WINAPI
1135TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
1136 return E_NOTIMPL;
1137}
1138
1139static void WINAPI
1140TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
1141 return;
1142}
1143
1144ICOM_VTABLE(IRpcStubBuffer) tmstubvtbl = {
1145 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1146 TMStubImpl_QueryInterface,
1147 TMStubImpl_AddRef,
1148 TMStubImpl_Release,
1149 TMStubImpl_Connect,
1150 TMStubImpl_Disconnect,
1151 TMStubImpl_Invoke,
1152 TMStubImpl_IsIIDSupported,
1153 TMStubImpl_CountRefs,
1154 TMStubImpl_DebugServerQueryInterface,
1155 TMStubImpl_DebugServerRelease
1156};
1157
1158static HRESULT WINAPI
1159PSFacBuf_CreateStub(
1160 LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
1161 IRpcStubBuffer** ppStub
1162) {
1163 HRESULT hres;
1164 ITypeInfo *tinfo;
1165 TMStubImpl *stub;
1166
1167 TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
1168 hres = _get_typeinfo_for_iid(riid,&tinfo);
1169 if (hres) {
1170 FIXME("No typeinfo for %s?\n",debugstr_guid(riid));
1171 return hres;
1172 }
1173 stub = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TMStubImpl));
1174 if (!stub)
1175 return E_OUTOFMEMORY;
1176 stub->lpvtbl = &tmstubvtbl;
1177 stub->ref = 1;
1178 stub->tinfo = tinfo;
1179 memcpy(&(stub->iid),riid,sizeof(*riid));
1180 hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
1181 *ppStub = (LPRPCSTUBBUFFER)stub;
1182 if (hres)
1183 FIXME("Connect to pUnkServer failed?\n");
1184 return hres;
1185}
1186
1187static ICOM_VTABLE(IPSFactoryBuffer) psfacbufvtbl = {
1188 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1189 PSFacBuf_QueryInterface,
1190 PSFacBuf_AddRef,
1191 PSFacBuf_Release,
1192 PSFacBuf_CreateProxy,
1193 PSFacBuf_CreateStub
1194};
1195
1196/* This is the whole PSFactoryBuffer object, just the vtableptr */
1197static ICOM_VTABLE(IPSFactoryBuffer) *lppsfac = &psfacbufvtbl;
1198
1199/***********************************************************************
1200 * DllGetClassObject [OLE32.63]
1201 */
1202HRESULT WINAPI
1203TypeLibFac_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1204{
1205 if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
1206 *ppv = &lppsfac;
1207 return S_OK;
1208 }
1209 return E_NOINTERFACE;
1210}
Note: See TracBrowser for help on using the repository browser.