4 * Copyright 2002 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #include "wine/unicode.h"
36 #include "wine/obj_base.h"
37 #include "wine/obj_channel.h"
38 #include "wine/obj_storage.h"
42 #include "wine/debug.h"
45 static const WCHAR riidW
[5] = {'r','i','i','d',0};
47 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
48 WINE_DECLARE_DEBUG_CHANNEL(olerelay
);
50 typedef struct _marshal_state
{
56 IID iid
; /* HACK: for VT_VOID */
60 xbuf_add(marshal_state
*buf
, LPBYTE stuff
, DWORD size
) {
61 while (buf
->size
- buf
->curoff
< size
) {
64 buf
->base
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,buf
->base
,buf
->size
);
68 buf
->base
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,32);
74 memcpy(buf
->base
+buf
->curoff
,stuff
,size
);
80 xbuf_get(marshal_state
*buf
, LPBYTE stuff
, DWORD size
) {
81 if (buf
->size
< buf
->curoff
+size
) return E_FAIL
;
82 memcpy(stuff
,buf
->base
+buf
->curoff
,size
);
88 xbuf_skip(marshal_state
*buf
, DWORD size
) {
89 if (buf
->size
< buf
->curoff
+size
) return E_FAIL
;
95 _unmarshal_interface(marshal_state
*buf
, REFIID riid
, LPUNKNOWN
*pUnk
) {
97 ULARGE_INTEGER newpos
;
103 TRACE("...%s...\n",debugstr_guid(riid
));
105 hres
= xbuf_get(buf
,(LPBYTE
)&xsize
,sizeof(xsize
));
106 if (hres
) return hres
;
107 if (xsize
== 0) return S_OK
;
108 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
110 FIXME("Stream create failed %lx\n",hres
);
113 hres
= IStream_Write(pStm
,buf
->base
+buf
->curoff
,xsize
,&res
);
114 if (hres
) { FIXME("stream write %lx\n",hres
); return hres
; }
115 memset(&seekto
,0,sizeof(seekto
));
116 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
117 if (hres
) { FIXME("Failed Seek %lx\n",hres
); return hres
;}
118 hres
= CoUnmarshalInterface(pStm
,riid
,(LPVOID
*)pUnk
);
120 FIXME("Marshaling interface %s failed with %lx\n",debugstr_guid(riid
),hres
);
123 IStream_Release(pStm
);
124 return xbuf_skip(buf
,xsize
);
128 _marshal_interface(marshal_state
*buf
, REFIID riid
, LPUNKNOWN pUnk
) {
133 ULARGE_INTEGER newpos
;
134 LARGE_INTEGER seekto
;
143 TRACE("...%s...\n",debugstr_guid(riid
));
144 hres
=IUnknown_QueryInterface(pUnk
,riid
,(LPVOID
*)&newiface
);
146 TRACE("%p does not support iface %s\n",pUnk
,debugstr_guid(riid
));
149 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
151 FIXME("Stream create failed %lx\n",hres
);
154 hres
= CoMarshalInterface(pStm
,riid
,newiface
,0,NULL
,0);
155 IUnknown_Release(newiface
);
157 FIXME("Marshaling interface %s failed with %lx\n",
158 debugstr_guid(riid
),hres
162 hres
= IStream_Stat(pStm
,&ststg
,0);
163 tempbuf
= HeapAlloc(GetProcessHeap(), 0, ststg
.cbSize
.s
.LowPart
);
164 memset(&seekto
,0,sizeof(seekto
));
165 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
166 if (hres
) { FIXME("Failed Seek %lx\n",hres
); goto fail
;}
167 hres
= IStream_Read(pStm
,tempbuf
,ststg
.cbSize
.s
.LowPart
,&res
);
168 if (hres
) { FIXME("Failed Read %lx\n",hres
); goto fail
;}
169 IStream_Release(pStm
);
170 xsize
= ststg
.cbSize
.s
.LowPart
;
171 xbuf_add(buf
,(LPBYTE
)&xsize
,sizeof(xsize
));
172 hres
= xbuf_add(buf
,tempbuf
,ststg
.cbSize
.s
.LowPart
);
173 HeapFree(GetProcessHeap(),0,tempbuf
);
177 xbuf_add(buf
,(LPBYTE
)&xsize
,sizeof(xsize
));
181 /********************* OLE Proxy/Stub Factory ********************************/
182 static HRESULT WINAPI
183 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface
, REFIID iid
, LPVOID
*ppv
) {
184 if (IsEqualIID(iid
,&IID_IPSFactoryBuffer
)||IsEqualIID(iid
,&IID_IUnknown
)) {
185 *ppv
= (LPVOID
)iface
;
186 /* No ref counting, static class */
189 FIXME("(%s) unknown IID?\n",debugstr_guid(iid
));
190 return E_NOINTERFACE
;
193 static ULONG WINAPI
PSFacBuf_AddRef(LPPSFACTORYBUFFER iface
) { return 2; }
194 static ULONG WINAPI
PSFacBuf_Release(LPPSFACTORYBUFFER iface
) { return 1; }
197 _get_typeinfo_for_iid(REFIID riid
, ITypeInfo
**ti
) {
200 char tlguid
[200],typelibkey
[300],interfacekey
[300],ver
[100];
203 DWORD tlguidlen
, verlen
, type
, tlfnlen
;
206 sprintf( interfacekey
, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
207 riid
->Data1
, riid
->Data2
, riid
->Data3
,
208 riid
->Data4
[0], riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3],
209 riid
->Data4
[4], riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]
212 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,interfacekey
,&ikey
)) {
213 FIXME("No %s key found.\n",interfacekey
);
217 tlguidlen
= sizeof(tlguid
);
218 if (RegQueryValueExA(ikey
,NULL
,NULL
,&type
,tlguid
,&tlguidlen
)) {
219 FIXME("Getting typelib guid failed.\n");
224 verlen
= sizeof(ver
);
225 if (RegQueryValueExA(ikey
,"Version",NULL
,&type
,ver
,&verlen
)) {
226 FIXME("Could not get version value?\n");
231 sprintf(typelibkey
,"Typelib\\%s\\%s\\0\\win32",tlguid
,ver
);
232 tlfnlen
= sizeof(tlfn
);
233 if (RegQueryValueA(HKEY_CLASSES_ROOT
,typelibkey
,tlfn
,&tlfnlen
)) {
234 FIXME("Could not get typelib fn?\n");
237 MultiByteToWideChar(CP_ACP
, 0, tlfn
, -1, tlfnW
, -1);
238 hres
= LoadTypeLib(tlfnW
,&tl
);
240 ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid
));
243 hres
= ITypeLib_GetTypeInfoOfGuid(tl
,riid
,ti
);
245 ERR("typelib does not contain info for %s?\n",debugstr_guid(riid
));
246 ITypeLib_Release(tl
);
249 /* FIXME: do this? ITypeLib_Release(tl); */
253 /* Determine nr of functions. Since we use the toplevel interface and all
254 * inherited ones have lower numbers, we are ok to not to descent into
255 * the inheritance tree I think.
257 static int _nroffuncs(ITypeInfo
*tinfo
) {
264 hres
= ITypeInfo_GetFuncDesc(tinfo
,n
,&fdesc
);
265 if (fdesc
->oVft
/4 > max
)
274 typedef struct _TMAsmProxy
{
283 } WINE_PACKED TMAsmProxy
;
285 typedef struct _TMProxyImpl
{
287 ICOM_VTABLE(IRpcProxyBuffer
) *lpvtbl2
;
290 TMAsmProxy
*asmstubs
;
292 IRpcChannelBuffer
* chanbuf
;
296 static HRESULT WINAPI
297 TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface
, REFIID riid
, LPVOID
*ppv
) {
299 if (IsEqualIID(riid
,&IID_IUnknown
)||IsEqualIID(riid
,&IID_IRpcProxyBuffer
)) {
300 *ppv
= (LPVOID
)iface
;
301 IRpcProxyBuffer_AddRef(iface
);
304 FIXME("no interface for %s\n",debugstr_guid(riid
));
305 return E_NOINTERFACE
;
309 TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface
) {
310 ICOM_THIS_MULTI(TMProxyImpl
,lpvtbl2
,iface
);
318 TMProxyImpl_Release(LPRPCPROXYBUFFER iface
) {
319 ICOM_THIS_MULTI(TMProxyImpl
,lpvtbl2
,iface
);
323 if (This
->ref
) return This
->ref
;
324 if (This
->chanbuf
) IRpcChannelBuffer_Release(This
->chanbuf
);
325 HeapFree(GetProcessHeap(),0,This
);
329 static HRESULT WINAPI
331 LPRPCPROXYBUFFER iface
,IRpcChannelBuffer
* pRpcChannelBuffer
333 ICOM_THIS_MULTI(TMProxyImpl
,lpvtbl2
,iface
);
335 TRACE("(%p)\n",pRpcChannelBuffer
);
336 This
->chanbuf
= pRpcChannelBuffer
;
337 IRpcChannelBuffer_AddRef(This
->chanbuf
);
342 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface
) {
343 ICOM_THIS_MULTI(TMProxyImpl
,lpvtbl2
,iface
);
346 IRpcChannelBuffer_Release(This
->chanbuf
);
347 This
->chanbuf
= NULL
;
351 static ICOM_VTABLE(IRpcProxyBuffer
) tmproxyvtable
= {
352 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
353 TMProxyImpl_QueryInterface
,
357 TMProxyImpl_Disconnect
362 ITypeInfo
*tinfo
, ELEMDESC
*elem
, TYPEDESC
*tdesc
, DWORD
*arg
, marshal_state
*buf
364 int relaydeb
= TRACE_ON(olerelay
);
367 if (!tdesc
) tdesc
= &(elem
->tdesc
);
371 case VT_BSTR
: { /* DWORD size, string data */
372 DWORD
*bstr
= ((DWORD
*)(*arg
))-1;
374 if (relaydeb
) MESSAGE("%s",debugstr_w((LPWSTR
)(bstr
+1)));
375 return xbuf_add(buf
,(LPBYTE
)bstr
,bstr
[0]+4);
379 if (relaydeb
) MESSAGE("%ld",*arg
);
380 return xbuf_add(buf
,(LPBYTE
)arg
,4);
382 /* We use ourselves to marshal the value further */
384 VARIANT
*vt
= (VARIANT
*)arg
;
385 DWORD vttype
= V_VT(vt
);
387 hres
= xbuf_add(buf
,(LPBYTE
)&vttype
,sizeof(vttype
));
388 if (hres
) return hres
;
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
);
395 return marshall_param(tinfo
,elem
,tdesc
->u
.lptdesc
,(DWORD
*)*arg
,buf
);
397 hres
= _marshal_interface(buf
,&(buf
->iid
),(LPUNKNOWN
)arg
);
399 FIXME("Failed unmarshaling VT_VOID with guid %s?\n",debugstr_guid(&(buf
->iid
)));
402 case VT_USERDEFINED
: {
406 /*FIXME("VT_USERDEFINED arg is %p, *arg is %p\n",arg,*arg);*/
407 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
409 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc
->u
.hreftype
);
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
);
419 if (relaydeb
) MESSAGE("record %p",arg
);
421 memcpy(&(buf
->iid
),arg
,sizeof(buf
->iid
));
422 hres
= xbuf_add(buf
,(LPBYTE
)arg
,tattr
->cbSizeInstance
);
425 FIXME("Don't know how to marshal type kind %d\n",tattr
->typekind
);
429 ITypeInfo_Release(tinfo2
);
433 ERR("Cannot marshal type %d\n",tdesc
->vt
);
434 /*dump_ELEMDESC(elem);*/
442 ITypeInfo
*tinfo
, ELEMDESC
*elem
, TYPEDESC
*tdesc
, DWORD
*arg
, marshal_state
*buf
445 int relaydeb
= TRACE_ON(olerelay
);
447 if (!tdesc
) tdesc
= &(elem
->tdesc
);
451 xbuf_get(buf
,(LPBYTE
)&x
,sizeof(x
));
453 if (relaydeb
) MESSAGE("%ld ",x
);
457 if ((tdesc
->u
.lptdesc
->vt
!= VT_USERDEFINED
) &&
458 (tdesc
->u
.lptdesc
->vt
!= VT_VOID
)
460 hres
= unmarshall_param(tinfo
,elem
,tdesc
->u
.lptdesc
,(DWORD
*)(*arg
),buf
);
462 hres
= unmarshall_param(tinfo
,elem
,tdesc
->u
.lptdesc
,arg
,buf
);
463 if (relaydeb
) MESSAGE("%p ",(LPVOID
)*arg
);
465 case VT_USERDEFINED
: {
469 if (relaydeb
) MESSAGE("%p",arg
);
470 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
472 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc
->u
.hreftype
);
475 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
477 FIXME("Could not get typeattr in VT_USERDEFINED.\n");
480 switch (tattr
->typekind
) {
481 case TKIND_INTERFACE
:
482 hres
= _unmarshal_interface(buf
,&(tattr
->guid
),(LPUNKNOWN
*)arg
);
485 hres
= xbuf_get(buf
,(LPBYTE
)arg
,tattr
->cbSizeInstance
);
489 FIXME("Don't know how to marshal type kind %d\n",tattr
->typekind
);
491 ITypeInfo_Release(tinfo2
);
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
);
504 /* Searches function, also in inherited interfaces */
507 ITypeInfo
*tinfo
, int iMethod
, FUNCDESC
**fdesc
,
508 BSTR
*iname
, BSTR
*fname
513 if (fname
) *fname
= NULL
;
514 if (iname
) *iname
= NULL
;
517 hres
= ITypeInfo_GetFuncDesc(tinfo
, i
, fdesc
);
523 hres
= ITypeInfo_GetTypeAttr(tinfo
, &attr
);
525 FIXME("GetTypeAttr failed with %lx\n",hres
);
528 /* Not found, so look in inherited ifaces. */
529 for (j
=0;j
<attr
->cImplTypes
;j
++) {
530 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, j
, &href
);
532 FIXME("Did not find a reftype for interface offset %d?\n",j
);
535 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
537 FIXME("Did not find a typeinfo for reftype %ld?\n",href
);
540 hres
= _get_funcdesc(tinfo2
,iMethod
,fdesc
,iname
,fname
);
541 ITypeInfo_Release(tinfo2
);
542 if (!hres
) return S_OK
;
546 if (((*fdesc
)->oVft
/4) == iMethod
) {
548 ITypeInfo_GetDocumentation(tinfo
,(*fdesc
)->memid
,fname
,NULL
,NULL
,NULL
);
550 ITypeInfo_GetDocumentation(tinfo
,-1,iname
,NULL
,NULL
,NULL
);
558 /* how much space do we use on stack in DWORD steps. */
560 _argsize(DWORD vt_type
) {
563 return (sizeof(VARIANT
)+3)/sizeof(DWORD
);
570 xCall(LPVOID retptr
, int method
, TMProxyImpl
*tpinfo
/*, args */) {
571 DWORD
*args
= ((DWORD
*)&tpinfo
)+1, *xargs
;
574 int i
, relaydeb
= TRACE_ON(olerelay
);
582 hres
= _get_funcdesc(tpinfo
->tinfo
,method
,&fdesc
,&iname
,&fname
);
584 ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method
);
588 /*dump_FUNCDESC(fdesc);*/
590 TRACE_(olerelay
)("->");
592 MESSAGE("%s:",debugstr_w(iname
));
594 MESSAGE("%s(%d)",debugstr_w(fname
),method
);
596 MESSAGE("%d",method
);
598 if (iname
) SysFreeString(iname
);
599 if (fname
) SysFreeString(fname
);
601 /* Need them for hack below */
602 memset(names
,0,sizeof(names
));
603 ITypeInfo_GetNames(tpinfo
->tinfo
,fdesc
->memid
,names
,sizeof(names
)/sizeof(names
[0]),&nrofnames
);
604 if (nrofnames
> sizeof(names
)/sizeof(names
[0])) {
605 ERR("Need more names!\n");
607 memset(&buf
,0,sizeof(buf
));
608 buf
.iid
= IID_IUnknown
;
610 xbuf_add(&buf
,(LPBYTE
)args
[0],sizeof(IID
));
611 if (relaydeb
) MESSAGE("riid=%s,[out]",debugstr_guid((REFIID
)args
[0]));
614 for (i
=0;i
<fdesc
->cParams
;i
++) {
615 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
618 if (i
+1<nrofnames
&& names
[i
+1])
619 MESSAGE("%s=",debugstr_w(names
[i
+1]));
621 if (((i
+1)<nrofnames
) && !lstrcmpW(names
[i
+1],riidW
)) {
622 buf
.thisisiid
= TRUE
;
624 buf
.thisisiid
= FALSE
;
626 /* No need to marshal other data than FIN */
627 if (!(elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FIN
)) {
628 xargs
+=_argsize(elem
->tdesc
.vt
);
629 if (relaydeb
) MESSAGE("[out]");
632 hres
= marshall_param(tpinfo
->tinfo
,elem
,NULL
,xargs
,&buf
);
633 xargs
+=_argsize(elem
->tdesc
.vt
);
635 FIXME("Failed to marshall param, hres %lx\n",hres
);
640 if (relaydeb
) MESSAGE(")");
641 memset(&msg
,0,sizeof(msg
));
642 msg
.cbBuffer
= buf
.curoff
;
643 msg
.iMethod
= method
;
644 hres
= IRpcChannelBuffer_GetBuffer(tpinfo
->chanbuf
,&msg
,&(tpinfo
->iid
));
646 FIXME("RpcChannelBuffer GetBuffer failed, %lx\n",hres
);
649 memcpy(msg
.Buffer
,buf
.base
,buf
.curoff
);
650 hres
= IRpcChannelBuffer_SendReceive(tpinfo
->chanbuf
,&msg
,&status
);
652 FIXME("RpcChannelBuffer SendReceive failed, %lx\n",hres
);
655 if (relaydeb
) MESSAGE(" = %08lx (",status
);
657 buf
.base
= HeapReAlloc(GetProcessHeap(),0,buf
.base
,msg
.cbBuffer
);
659 buf
.base
= HeapAlloc(GetProcessHeap(),0,msg
.cbBuffer
);
660 buf
.size
= msg
.cbBuffer
;
661 memcpy(buf
.base
,msg
.Buffer
,buf
.size
);
664 _unmarshal_interface(&buf
,(REFIID
)args
[0],(LPUNKNOWN
*)args
[1]);
665 if (relaydeb
) MESSAGE("[in],%p",*((DWORD
**)args
[1]));
668 for (i
=0;i
<fdesc
->cParams
;i
++) {
669 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
673 if (i
+1<nrofnames
&& names
[i
+1]) MESSAGE("%s=",debugstr_w(names
[i
+1]));
675 /* No need to marshal other data than FOUT I think */
676 if (!(elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
)) {
677 xargs
+= _argsize(elem
->tdesc
.vt
);
678 if (relaydeb
) MESSAGE("[in]");
681 hres
= unmarshall_param(tpinfo
->tinfo
,elem
,&(elem
->tdesc
),xargs
,&buf
);
682 xargs
+= _argsize(elem
->tdesc
.vt
);
684 FIXME("Failed to unmarshall param, hres %lx\n",hres
);
689 if (relaydeb
) MESSAGE(")\n");
690 HeapFree(GetProcessHeap(),0,buf
.base
);
694 static HRESULT WINAPI
695 PSFacBuf_CreateProxy(
696 LPPSFACTORYBUFFER iface
, IUnknown
* pUnkOuter
, REFIID riid
,
697 IRpcProxyBuffer
**ppProxy
, LPVOID
*ppv
705 TRACE("(...%s...)\n",debugstr_guid(riid
));
706 hres
= _get_typeinfo_for_iid(riid
,&tinfo
);
708 FIXME("No typeinfo for %s?\n",debugstr_guid(riid
));
711 nroffuncs
= _nroffuncs(tinfo
);
712 proxy
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(TMProxyImpl
));
713 if (!proxy
) return E_OUTOFMEMORY
;
714 proxy
->asmstubs
=HeapAlloc(GetProcessHeap(),0,sizeof(TMAsmProxy
)*nroffuncs
);
716 assert(sizeof(TMAsmProxy
) == 12);
718 proxy
->lpvtbl
= HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE
)*nroffuncs
);
719 for (i
=0;i
<nroffuncs
;i
++) {
721 TMAsmProxy
*xasm
= proxy
->asmstubs
+i
;
723 /* nrofargs without This */
725 case 0: nrofargs
= 2;
727 case 1: case 2: nrofargs
= 0;
731 hres
= _get_funcdesc(tinfo
,i
,&fdesc
,NULL
,NULL
);
733 FIXME("GetFuncDesc %lx should not fail here.\n",hres
);
736 /* some args take more than 4 byte on the stack */
738 for (j
=0;j
<fdesc
->cParams
;j
++)
739 nrofargs
+= _argsize(fdesc
->lprgelemdescParam
[j
].tdesc
.vt
);
741 if (fdesc
->callconv
!= CC_STDCALL
) {
742 ERR("calling convention is not stdcall????\n");
748 /* popl %eax - return ptr
755 * arg3 arg2 arg1 <method> <returnptr>
757 xasm
->popleax
= 0x58;
758 xasm
->pushlval
= 0x6a;
760 xasm
->pushleax
= 0x50;
761 xasm
->lcall
= 0xe8; /* relative jump */
762 xasm
->xcall
= (DWORD
)xCall
;
763 xasm
->xcall
-= (DWORD
)&(xasm
->lret
);
765 xasm
->bytestopop
= (nrofargs
+2)*4; /* pop args, This, iMethod */
766 proxy
->lpvtbl
[i
] = (DWORD
)xasm
;
768 proxy
->lpvtbl2
= &tmproxyvtable
;
770 proxy
->tinfo
= tinfo
;
771 memcpy(&proxy
->iid
,riid
,sizeof(*riid
));
772 *ppv
= (LPVOID
)proxy
;
773 *ppProxy
= (IRpcProxyBuffer
*)&(proxy
->lpvtbl2
);
777 typedef struct _TMStubImpl
{
778 ICOM_VTABLE(IRpcStubBuffer
) *lpvtbl
;
786 static HRESULT WINAPI
787 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface
, REFIID riid
, LPVOID
*ppv
) {
788 if (IsEqualIID(riid
,&IID_IRpcStubBuffer
)||IsEqualIID(riid
,&IID_IUnknown
)){
789 *ppv
= (LPVOID
)iface
;
790 IRpcStubBuffer_AddRef(iface
);
793 FIXME("%s, not supported IID.\n",debugstr_guid(riid
));
794 return E_NOINTERFACE
;
798 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface
) {
799 ICOM_THIS(TMStubImpl
,iface
);
806 TMStubImpl_Release(LPRPCSTUBBUFFER iface
) {
807 ICOM_THIS(TMStubImpl
,iface
);
812 HeapFree(GetProcessHeap(),0,This
);
816 static HRESULT WINAPI
817 TMStubImpl_Connect(LPRPCSTUBBUFFER iface
, LPUNKNOWN pUnkServer
) {
818 ICOM_THIS(TMStubImpl
,iface
);
820 IUnknown_AddRef(pUnkServer
);
821 This
->pUnk
= pUnkServer
;
826 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface
) {
827 ICOM_THIS(TMStubImpl
,iface
);
829 IUnknown_Release(This
->pUnk
);
836 ITypeInfo
*tinfo
, ELEMDESC
*elem
, TYPEDESC
*tdesc
, DWORD
*arg
, marshal_state
*buf
844 VARIANT
*vt
= (VARIANT
*)arg
;
847 hres
= xbuf_get(buf
,(LPBYTE
)&vttype
,sizeof(vttype
));
848 if (hres
) return hres
;
849 memset(&tdesc2
,0,sizeof(tdesc
));
852 return stuballoc_param(tinfo
,elem
,&tdesc2
,&(V_I4(vt
)),buf
);
854 case VT_BOOL
: case VT_I4
:
855 xbuf_get(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
861 hres
= xbuf_get(buf
,(LPBYTE
)&len
,sizeof(DWORD
));
864 str
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,len
+sizeof(WCHAR
));
865 hres
= xbuf_get(buf
,(LPBYTE
)str
,len
);
866 if (hres
) return hres
;
867 *arg
= (DWORD
)SysAllocStringLen(str
,len
);
868 HeapFree(GetProcessHeap(),0,str
);
872 if ((tdesc
->u
.lptdesc
->vt
!= VT_USERDEFINED
) &&
873 (tdesc
->u
.lptdesc
->vt
!= VT_VOID
)
875 *arg
=(DWORD
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(LPVOID
));
878 tdesc
= tdesc
->u
.lptdesc
;
881 /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
882 *arg
=(DWORD
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
));
885 *arg
= (DWORD
)HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID
));
887 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FIN
)
888 hres
= _unmarshal_interface(buf
,&(buf
->iid
),(LPUNKNOWN
*)arg
);
890 case VT_USERDEFINED
: {
891 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FIN
) {
895 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
897 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc
->u
.hreftype
);
900 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
902 FIXME("Could not get typeattr in VT_USERDEFINED.\n");
905 switch (tattr
->typekind
) {
906 case TKIND_INTERFACE
:
907 hres
= _unmarshal_interface(buf
,&(tattr
->guid
),(LPUNKNOWN
*)arg
);
910 *arg
= (DWORD
)HeapAlloc(GetProcessHeap(),0,tattr
->cbSizeInstance
);
911 hres
= xbuf_get(buf
,(LPBYTE
)*arg
,tattr
->cbSizeInstance
);
913 memcpy(&(buf
->iid
),(LPBYTE
)*arg
,sizeof(buf
->iid
));
916 FIXME("Don't know how to marshal type kind %d\n",tattr
->typekind
);
920 ITypeInfo_Release(tinfo2
);
923 *arg
= (DWORD
)HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID
));
928 ERR("No handler for VT type %d, just allocating 4 bytes.\n",tdesc
->vt
);
929 *arg
=(DWORD
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
));
937 ITypeInfo
*tinfo
, ELEMDESC
*elem
, TYPEDESC
*tdesc
, DWORD
*arg
, marshal_state
*buf
941 if (!tdesc
) tdesc
= &(elem
->tdesc
);
947 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
)
948 hres
= xbuf_add(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
952 VARIANT
*vt
= (VARIANT
*)arg
;
953 DWORD vttype
= V_VT(vt
);
956 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
) {
957 hres
= xbuf_add(buf
,(LPBYTE
)&vttype
,sizeof(vttype
));
958 if (hres
) return hres
;
960 /* need to recurse since we need to free the stuff */
961 hres
= stubunalloc_param(tinfo
,elem
,&tdesc2
,&(V_I4(vt
)),buf
);
965 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
) {
966 DWORD
*bstr
= ((DWORD
*)(*arg
))-1;
968 hres
= xbuf_add(buf
,(LPBYTE
)bstr
,bstr
[0]+4);
972 SysFreeString((BSTR
)*arg
);
976 /*FIXME("VT_PTR *arg is %p\n",(LPVOID)*arg);*/
977 if ((tdesc
->u
.lptdesc
->vt
!= VT_USERDEFINED
) &&
978 (tdesc
->u
.lptdesc
->vt
!= VT_VOID
)
980 hres
= stubunalloc_param(tinfo
,elem
,tdesc
->u
.lptdesc
,arg
,buf
);
982 hres
= stubunalloc_param(tinfo
,elem
,tdesc
->u
.lptdesc
,(DWORD
*)*arg
,buf
);
983 HeapFree(GetProcessHeap(),0,(LPVOID
)*arg
);
987 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
) {
988 FIXME("Marshaling back VT_UNKNOWN %lx\n",*arg
);
989 hres
= xbuf_add(buf
,(LPBYTE
)*arg
,sizeof(DWORD
));
991 HeapFree(GetProcessHeap(),0,(LPVOID
)*arg
);
995 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
)
996 hres
= _marshal_interface(buf
,&(buf
->iid
),(LPUNKNOWN
)*arg
);
998 case VT_USERDEFINED
: {
1002 if (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
) {
1003 /*FIXME("VT_USERDEFINED arg is %p, *arg is %p\n",arg,*arg);*/
1004 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
1006 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED.\n",tdesc
->u
.hreftype
);
1009 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
1010 switch (tattr
->typekind
) {
1011 case TKIND_INTERFACE
:
1012 hres
= _marshal_interface(buf
,&(tattr
->guid
),(LPUNKNOWN
)*arg
);
1015 hres
= xbuf_add(buf
,(LPBYTE
)arg
,tattr
->cbSizeInstance
);
1018 FIXME("Don't know how to marshal type kind %d\n",tattr
->typekind
);
1022 ITypeInfo_Release(tinfo2
);
1027 ERR("Unhandled marshal type %d.\n",tdesc
->vt
);
1028 HeapFree(GetProcessHeap(),0,(LPVOID
)*arg
);
1033 static HRESULT WINAPI
1035 LPRPCSTUBBUFFER iface
, RPCOLEMESSAGE
* xmsg
,IRpcChannelBuffer
*rpcchanbuf
1039 ICOM_THIS(TMStubImpl
,iface
);
1041 DWORD
*args
, res
, *xargs
, nrofargs
;
1046 memset(&buf
,0,sizeof(buf
));
1047 buf
.size
= xmsg
->cbBuffer
;
1048 buf
.base
= xmsg
->Buffer
;
1050 buf
.iid
= IID_IUnknown
;
1053 if (xmsg
->iMethod
== 0) { /* QI */
1055 /* in: IID, out: <iface> */
1057 xbuf_get(&buf
,(LPBYTE
)&xiid
,sizeof(xiid
));
1059 hres
= _marshal_interface(&buf
,&xiid
,This
->pUnk
);
1060 xmsg
->Buffer
= buf
.base
; /* Might have been reallocated */
1061 xmsg
->cbBuffer
= buf
.size
;
1064 hres
= _get_funcdesc(This
->tinfo
,xmsg
->iMethod
,&fdesc
,NULL
,NULL
);
1066 FIXME("GetFuncDesc on method %ld failed with %lx\n",xmsg
->iMethod
,hres
);
1069 /* Need them for hack below */
1070 memset(names
,0,sizeof(names
));
1071 ITypeInfo_GetNames(This
->tinfo
,fdesc
->memid
,names
,sizeof(names
)/sizeof(names
[0]),&nrofnames
);
1072 if (nrofnames
> sizeof(names
)/sizeof(names
[0])) {
1073 ERR("Need more names!\n");
1076 /*dump_FUNCDESC(fdesc);*/
1078 for (i
=0;i
<fdesc
->cParams
;i
++)
1079 nrofargs
+= _argsize(fdesc
->lprgelemdescParam
[i
].tdesc
.vt
);
1080 args
= HeapAlloc(GetProcessHeap(),0,(nrofargs
+1)*sizeof(DWORD
));
1081 if (!args
) return E_OUTOFMEMORY
;
1083 /* Allocate all stuff used by call. */
1085 for (i
=0;i
<fdesc
->cParams
;i
++) {
1086 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
1088 if (((i
+1)<nrofnames
) && !lstrcmpW(names
[i
+1],riidW
))
1089 buf
.thisisiid
= TRUE
;
1091 buf
.thisisiid
= FALSE
;
1092 hres
= stuballoc_param(This
->tinfo
,elem
,&(elem
->tdesc
),xargs
,&buf
);
1093 xargs
+= _argsize(elem
->tdesc
.vt
);
1095 FIXME("Failed to stuballoc param %s, hres %lx\n",debugstr_w(names
[i
+1]),hres
);
1099 hres
= IUnknown_QueryInterface(This
->pUnk
,&(This
->iid
),(LPVOID
*)&(args
[0]));
1101 ERR("Does not support iface %s\n",debugstr_guid(&(This
->iid
)));
1105 (*((LPVOID
**)args
[0]))[fdesc
->oVft
/4],
1110 IUnknown_Release((LPUNKNOWN
)args
[0]);
1113 for (i
=0;i
<fdesc
->cParams
;i
++) {
1114 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
1115 hres
= stubunalloc_param(This
->tinfo
,elem
,NULL
,xargs
,&buf
);
1116 xargs
+= _argsize(elem
->tdesc
.vt
);
1118 FIXME("Failed to stuballoc param, hres %lx\n",hres
);
1122 /* might need to use IRpcChannelBuffer_GetBuffer ? */
1123 xmsg
->cbBuffer
= buf
.curoff
;
1124 xmsg
->Buffer
= buf
.base
;
1125 HeapFree(GetProcessHeap(),0,args
);
1129 static LPRPCSTUBBUFFER WINAPI
1130 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface
, REFIID riid
) {
1131 FIXME("Huh (%s)?\n",debugstr_guid(riid
));
1136 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface
) {
1137 ICOM_THIS(TMStubImpl
,iface
);
1139 return This
->ref
; /*FIXME? */
1142 static HRESULT WINAPI
1143 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface
, LPVOID
*ppv
) {
1148 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface
, LPVOID ppv
) {
1152 ICOM_VTABLE(IRpcStubBuffer
) tmstubvtbl
= {
1153 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1154 TMStubImpl_QueryInterface
,
1158 TMStubImpl_Disconnect
,
1160 TMStubImpl_IsIIDSupported
,
1161 TMStubImpl_CountRefs
,
1162 TMStubImpl_DebugServerQueryInterface
,
1163 TMStubImpl_DebugServerRelease
1166 static HRESULT WINAPI
1167 PSFacBuf_CreateStub(
1168 LPPSFACTORYBUFFER iface
, REFIID riid
,IUnknown
*pUnkServer
,
1169 IRpcStubBuffer
** ppStub
1175 TRACE("(%s,%p,%p)\n",debugstr_guid(riid
),pUnkServer
,ppStub
);
1176 hres
= _get_typeinfo_for_iid(riid
,&tinfo
);
1178 FIXME("No typeinfo for %s?\n",debugstr_guid(riid
));
1181 stub
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(TMStubImpl
));
1183 return E_OUTOFMEMORY
;
1184 stub
->lpvtbl
= &tmstubvtbl
;
1186 stub
->tinfo
= tinfo
;
1187 memcpy(&(stub
->iid
),riid
,sizeof(*riid
));
1188 hres
= IRpcStubBuffer_Connect((LPRPCSTUBBUFFER
)stub
,pUnkServer
);
1189 *ppStub
= (LPRPCSTUBBUFFER
)stub
;
1191 FIXME("Connect to pUnkServer failed?\n");
1195 static ICOM_VTABLE(IPSFactoryBuffer
) psfacbufvtbl
= {
1196 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1197 PSFacBuf_QueryInterface
,
1200 PSFacBuf_CreateProxy
,
1204 /* This is the whole PSFactoryBuffer object, just the vtableptr */
1205 static ICOM_VTABLE(IPSFactoryBuffer
) *lppsfac
= &psfacbufvtbl
;
1207 /***********************************************************************
1208 * DllGetClassObject [OLE32.63]
1211 TypeLibFac_DllGetClassObject(REFCLSID rclsid
, REFIID iid
,LPVOID
*ppv
)
1213 if (IsEqualIID(iid
,&IID_IPSFactoryBuffer
)) {
1217 return E_NOINTERFACE
;