4 * Copyright 2002,2005 Marcus Meissner
6 * The olerelay debug channel allows you to see calls marshalled by
7 * the typelib marshaller. It is not a generic COM relaying system.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/port.h"
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
46 #include "propidl.h" /* for LPSAFEARRAY_User* functions */
49 #include "wine/debug.h"
50 #include "wine/exception.h"
52 static const WCHAR IDispatchW
[] = { 'I','D','i','s','p','a','t','c','h',0};
54 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
55 WINE_DECLARE_DEBUG_CHANNEL(olerelay
);
57 static HRESULT
TMarshalDispatchChannel_Create(
58 IRpcChannelBuffer
*pDelegateChannel
, REFIID tmarshal_riid
,
59 IRpcChannelBuffer
**ppChannel
);
61 typedef struct _marshal_state
{
67 /* used in the olerelay code to avoid having the L"" stuff added by debugstr_w */
68 static char *relaystr(WCHAR
*in
) {
69 char *tmp
= (char *)debugstr_w(in
);
71 tmp
[strlen(tmp
)-1] = '\0';
76 xbuf_resize(marshal_state
*buf
, DWORD newsize
)
78 if(buf
->size
>= newsize
)
83 buf
->base
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buf
->base
, newsize
);
89 buf
->base
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, newsize
);
98 xbuf_add(marshal_state
*buf
, const BYTE
*stuff
, DWORD size
)
102 if(buf
->size
- buf
->curoff
< size
)
104 hr
= xbuf_resize(buf
, buf
->size
+ size
+ 100);
105 if(FAILED(hr
)) return hr
;
107 memcpy(buf
->base
+buf
->curoff
,stuff
,size
);
113 xbuf_get(marshal_state
*buf
, LPBYTE stuff
, DWORD size
) {
114 if (buf
->size
< buf
->curoff
+size
) return E_FAIL
;
115 memcpy(stuff
,buf
->base
+buf
->curoff
,size
);
121 xbuf_skip(marshal_state
*buf
, DWORD size
) {
122 if (buf
->size
< buf
->curoff
+size
) return E_FAIL
;
128 _unmarshal_interface(marshal_state
*buf
, REFIID riid
, LPUNKNOWN
*pUnk
) {
130 ULARGE_INTEGER newpos
;
131 LARGE_INTEGER seekto
;
136 TRACE("...%s...\n",debugstr_guid(riid
));
139 hres
= xbuf_get(buf
,(LPBYTE
)&xsize
,sizeof(xsize
));
141 ERR("xbuf_get failed\n");
145 if (xsize
== 0) return S_OK
;
147 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
149 ERR("Stream create failed %x\n",hres
);
153 hres
= IStream_Write(pStm
,buf
->base
+buf
->curoff
,xsize
,&res
);
155 ERR("stream write %x\n",hres
);
156 IStream_Release(pStm
);
160 memset(&seekto
,0,sizeof(seekto
));
161 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
163 ERR("Failed Seek %x\n",hres
);
164 IStream_Release(pStm
);
168 hres
= CoUnmarshalInterface(pStm
,riid
,(LPVOID
*)pUnk
);
170 ERR("Unmarshalling interface %s failed with %x\n",debugstr_guid(riid
),hres
);
171 IStream_Release(pStm
);
175 IStream_Release(pStm
);
176 return xbuf_skip(buf
,xsize
);
180 _marshal_interface(marshal_state
*buf
, REFIID riid
, LPUNKNOWN pUnk
) {
181 LPBYTE tempbuf
= NULL
;
182 IStream
*pStm
= NULL
;
184 ULARGE_INTEGER newpos
;
185 LARGE_INTEGER seekto
;
191 /* this is valid, if for instance we serialize
192 * a VT_DISPATCH with NULL ptr which apparently
193 * can happen. S_OK to make sure we continue
196 WARN("pUnk is NULL\n");
198 return xbuf_add(buf
,(LPBYTE
)&xsize
,sizeof(xsize
));
203 TRACE("...%s...\n",debugstr_guid(riid
));
205 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
207 ERR("Stream create failed %x\n",hres
);
211 hres
= CoMarshalInterface(pStm
,riid
,pUnk
,0,NULL
,0);
213 ERR("Marshalling interface %s failed with %x\n", debugstr_guid(riid
), hres
);
217 hres
= IStream_Stat(pStm
,&ststg
,STATFLAG_NONAME
);
219 ERR("Stream stat failed\n");
223 tempbuf
= HeapAlloc(GetProcessHeap(), 0, ststg
.cbSize
.u
.LowPart
);
224 memset(&seekto
,0,sizeof(seekto
));
225 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
227 ERR("Failed Seek %x\n",hres
);
231 hres
= IStream_Read(pStm
,tempbuf
,ststg
.cbSize
.u
.LowPart
,&res
);
233 ERR("Failed Read %x\n",hres
);
237 xsize
= ststg
.cbSize
.u
.LowPart
;
238 xbuf_add(buf
,(LPBYTE
)&xsize
,sizeof(xsize
));
239 hres
= xbuf_add(buf
,tempbuf
,ststg
.cbSize
.u
.LowPart
);
241 HeapFree(GetProcessHeap(),0,tempbuf
);
242 IStream_Release(pStm
);
248 xbuf_add(buf
,(LPBYTE
)&xsize
,sizeof(xsize
));
249 if (pStm
) IUnknown_Release(pStm
);
250 HeapFree(GetProcessHeap(), 0, tempbuf
);
254 /********************* OLE Proxy/Stub Factory ********************************/
255 static HRESULT WINAPI
256 PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface
, REFIID iid
, LPVOID
*ppv
) {
257 if (IsEqualIID(iid
,&IID_IPSFactoryBuffer
)||IsEqualIID(iid
,&IID_IUnknown
)) {
259 /* No ref counting, static class */
262 FIXME("(%s) unknown IID?\n",debugstr_guid(iid
));
263 return E_NOINTERFACE
;
266 static ULONG WINAPI
PSFacBuf_AddRef(LPPSFACTORYBUFFER iface
) { return 2; }
267 static ULONG WINAPI
PSFacBuf_Release(LPPSFACTORYBUFFER iface
) { return 1; }
270 _get_typeinfo_for_iid(REFIID riid
, ITypeInfo
**ti
) {
273 char tlguid
[200],typelibkey
[300],interfacekey
[300],ver
[100];
276 DWORD tlguidlen
, verlen
, type
;
280 sprintf( interfacekey
, "Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
281 riid
->Data1
, riid
->Data2
, riid
->Data3
,
282 riid
->Data4
[0], riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3],
283 riid
->Data4
[4], riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]
286 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,interfacekey
,&ikey
)) {
287 ERR("No %s key found.\n",interfacekey
);
290 tlguidlen
= sizeof(tlguid
);
291 if (RegQueryValueExA(ikey
,NULL
,NULL
,&type
,(LPBYTE
)tlguid
,&tlguidlen
)) {
292 ERR("Getting typelib guid failed.\n");
296 verlen
= sizeof(ver
);
297 if (RegQueryValueExA(ikey
,"Version",NULL
,&type
,(LPBYTE
)ver
,&verlen
)) {
298 ERR("Could not get version value?\n");
303 sprintf(typelibkey
,"Typelib\\%s\\%s\\0\\win%u",tlguid
,ver
,(sizeof(void*) == 8) ? 64 : 32);
304 tlfnlen
= sizeof(tlfn
);
305 if (RegQueryValueA(HKEY_CLASSES_ROOT
,typelibkey
,tlfn
,&tlfnlen
)) {
306 ERR("Could not get typelib fn?\n");
309 MultiByteToWideChar(CP_ACP
, 0, tlfn
, -1, tlfnW
, sizeof(tlfnW
) / sizeof(tlfnW
[0]));
310 hres
= LoadTypeLib(tlfnW
,&tl
);
312 ERR("Failed to load typelib for %s, but it should be there.\n",debugstr_guid(riid
));
315 hres
= ITypeLib_GetTypeInfoOfGuid(tl
,riid
,ti
);
317 ERR("typelib does not contain info for %s?\n",debugstr_guid(riid
));
318 ITypeLib_Release(tl
);
321 ITypeLib_Release(tl
);
326 * Determine the number of functions including all inherited functions.
327 * Note for non-dual dispinterfaces we simply return the size of IDispatch.
329 static HRESULT
num_of_funcs(ITypeInfo
*tinfo
, unsigned int *num
)
336 hres
= ITypeInfo_GetTypeAttr(tinfo
, &attr
);
338 ERR("GetTypeAttr failed with %x\n",hres
);
342 if(attr
->typekind
== TKIND_DISPATCH
&& (attr
->wTypeFlags
& TYPEFLAG_FDUAL
))
345 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, -1, &href
);
348 ERR("Unable to get interface href from dual dispinterface\n");
351 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
354 ERR("Unable to get interface from dual dispinterface\n");
357 hres
= num_of_funcs(tinfo2
, num
);
358 ITypeInfo_Release(tinfo2
);
362 *num
= attr
->cbSizeVft
/ 4;
366 ITypeInfo_ReleaseTypeAttr(tinfo
, attr
);
372 #include "pshpack1.h"
374 typedef struct _TMAsmProxy
{
389 # warning You need to implement stubless proxies for your architecture
390 typedef struct _TMAsmProxy
{
394 typedef struct _TMProxyImpl
{
396 IRpcProxyBuffer IRpcProxyBuffer_iface
;
399 TMAsmProxy
*asmstubs
;
401 IRpcChannelBuffer
* chanbuf
;
403 CRITICAL_SECTION crit
;
404 IUnknown
*outerunknown
;
406 IRpcProxyBuffer
*dispatch_proxy
;
409 static inline TMProxyImpl
*impl_from_IRpcProxyBuffer( IRpcProxyBuffer
*iface
)
411 return CONTAINING_RECORD(iface
, TMProxyImpl
, IRpcProxyBuffer_iface
);
414 static HRESULT WINAPI
415 TMProxyImpl_QueryInterface(LPRPCPROXYBUFFER iface
, REFIID riid
, LPVOID
*ppv
)
418 if (IsEqualIID(riid
,&IID_IUnknown
)||IsEqualIID(riid
,&IID_IRpcProxyBuffer
)) {
420 IRpcProxyBuffer_AddRef(iface
);
423 FIXME("no interface for %s\n",debugstr_guid(riid
));
424 return E_NOINTERFACE
;
428 TMProxyImpl_AddRef(LPRPCPROXYBUFFER iface
)
430 TMProxyImpl
*This
= impl_from_IRpcProxyBuffer( iface
);
431 ULONG refCount
= InterlockedIncrement(&This
->ref
);
433 TRACE("(%p)->(ref before=%u)\n",This
, refCount
- 1);
439 TMProxyImpl_Release(LPRPCPROXYBUFFER iface
)
441 TMProxyImpl
*This
= impl_from_IRpcProxyBuffer( iface
);
442 ULONG refCount
= InterlockedDecrement(&This
->ref
);
444 TRACE("(%p)->(ref before=%u)\n",This
, refCount
+ 1);
448 if (This
->dispatch_proxy
) IRpcProxyBuffer_Release(This
->dispatch_proxy
);
449 This
->crit
.DebugInfo
->Spare
[0] = 0;
450 DeleteCriticalSection(&This
->crit
);
451 if (This
->chanbuf
) IRpcChannelBuffer_Release(This
->chanbuf
);
452 VirtualFree(This
->asmstubs
, 0, MEM_RELEASE
);
453 HeapFree(GetProcessHeap(), 0, This
->lpvtbl
);
454 ITypeInfo_Release(This
->tinfo
);
460 static HRESULT WINAPI
462 LPRPCPROXYBUFFER iface
,IRpcChannelBuffer
* pRpcChannelBuffer
)
464 TMProxyImpl
*This
= impl_from_IRpcProxyBuffer( iface
);
466 TRACE("(%p)\n", pRpcChannelBuffer
);
468 EnterCriticalSection(&This
->crit
);
470 IRpcChannelBuffer_AddRef(pRpcChannelBuffer
);
471 This
->chanbuf
= pRpcChannelBuffer
;
473 LeaveCriticalSection(&This
->crit
);
475 if (This
->dispatch_proxy
)
477 IRpcChannelBuffer
*pDelegateChannel
;
478 HRESULT hr
= TMarshalDispatchChannel_Create(pRpcChannelBuffer
, &This
->iid
, &pDelegateChannel
);
481 hr
= IRpcProxyBuffer_Connect(This
->dispatch_proxy
, pDelegateChannel
);
482 IRpcChannelBuffer_Release(pDelegateChannel
);
490 TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface
)
492 TMProxyImpl
*This
= impl_from_IRpcProxyBuffer( iface
);
496 EnterCriticalSection(&This
->crit
);
498 IRpcChannelBuffer_Release(This
->chanbuf
);
499 This
->chanbuf
= NULL
;
501 LeaveCriticalSection(&This
->crit
);
503 if (This
->dispatch_proxy
)
504 IRpcProxyBuffer_Disconnect(This
->dispatch_proxy
);
508 static const IRpcProxyBufferVtbl tmproxyvtable
= {
509 TMProxyImpl_QueryInterface
,
513 TMProxyImpl_Disconnect
516 /* how much space do we use on stack in DWORD steps. */
518 _argsize(TYPEDESC
*tdesc
, ITypeInfo
*tinfo
) {
522 return 8/sizeof(DWORD
);
524 return sizeof(double)/sizeof(DWORD
);
526 return sizeof(CY
)/sizeof(DWORD
);
528 return sizeof(DATE
)/sizeof(DWORD
);
530 return (sizeof(DECIMAL
)+3)/sizeof(DWORD
);
532 return (sizeof(VARIANT
)+3)/sizeof(DWORD
);
540 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
542 return 0; /* should fail critically in serialize_param */
543 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
544 ret
= (tattr
->cbSizeInstance
+3)/sizeof(DWORD
);
545 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
546 ITypeInfo_Release(tinfo2
);
554 /* how much space do we use on the heap (in bytes) */
556 _xsize(const TYPEDESC
*td
, ITypeInfo
*tinfo
) {
563 return sizeof(VARIANT
)+3; /* FIXME: why the +3? */
566 const ARRAYDESC
*adesc
= td
->u
.lpadesc
;
568 for (i
=0;i
<adesc
->cDims
;i
++)
569 arrsize
*= adesc
->rgbounds
[i
].cElements
;
570 return arrsize
*_xsize(&adesc
->tdescElem
, tinfo
);
590 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,td
->u
.hreftype
,&tinfo2
);
593 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
594 ret
= tattr
->cbSizeInstance
;
595 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
596 ITypeInfo_Release(tinfo2
);
617 TRACE("(tdesc.vt %s)\n",debugstr_vt(tdesc
->vt
));
620 if ((vartype
& 0xf000) == VT_ARRAY
)
621 vartype
= VT_SAFEARRAY
;
630 if (debugout
) TRACE_(olerelay
)("%x%x\n",arg
[0],arg
[1]);
632 hres
= xbuf_add(buf
,(LPBYTE
)arg
,8);
641 if (debugout
) TRACE_(olerelay
)("%x\n",*arg
);
643 hres
= xbuf_add(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
649 if (debugout
) TRACE_(olerelay
)("%04x\n",*arg
& 0xffff);
651 hres
= xbuf_add(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
656 if (debugout
) TRACE_(olerelay
)("%02x\n",*arg
& 0xff);
658 hres
= xbuf_add(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
661 if (debugout
) TRACE_(olerelay
)("Vt(%s%s)(",debugstr_vt(V_VT((VARIANT
*)arg
)),debugstr_vf(V_VT((VARIANT
*)arg
)));
664 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
665 ULONG size
= VARIANT_UserSize(&flags
, buf
->curoff
, (VARIANT
*)arg
);
666 xbuf_resize(buf
, size
);
667 VARIANT_UserMarshal(&flags
, buf
->base
+ buf
->curoff
, (VARIANT
*)arg
);
672 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
673 VARIANT_UserFree(&flags
, (VARIANT
*)arg
);
680 TRACE_(olerelay
)("%s",relaystr((WCHAR
*)*arg
));
682 TRACE_(olerelay
)("<bstr NULL>");
686 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
687 ULONG size
= BSTR_UserSize(&flags
, buf
->curoff
, (BSTR
*)arg
);
688 xbuf_resize(buf
, size
);
689 BSTR_UserMarshal(&flags
, buf
->base
+ buf
->curoff
, (BSTR
*)arg
);
694 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
695 BSTR_UserFree(&flags
, (BSTR
*)arg
);
701 BOOL derefhere
= TRUE
;
703 if (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
) {
707 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.lptdesc
->u
.hreftype
,&tinfo2
);
709 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc
->u
.lptdesc
->u
.hreftype
);
712 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
713 switch (tattr
->typekind
) {
715 if (tattr
->tdescAlias
.vt
== VT_USERDEFINED
)
717 DWORD href
= tattr
->tdescAlias
.u
.hreftype
;
718 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
719 ITypeInfo_Release(tinfo2
);
720 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,href
,&tinfo2
);
722 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc
->u
.lptdesc
->u
.hreftype
);
725 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
726 derefhere
= (tattr
->typekind
!= TKIND_DISPATCH
&& tattr
->typekind
!= TKIND_INTERFACE
);
729 case TKIND_ENUM
: /* confirmed */
730 case TKIND_RECORD
: /* FIXME: mostly untested */
732 case TKIND_DISPATCH
: /* will be done in VT_USERDEFINED case */
733 case TKIND_INTERFACE
: /* will be done in VT_USERDEFINED case */
737 FIXME("unhandled switch cases tattr->typekind %d\n", tattr
->typekind
);
741 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
742 ITypeInfo_Release(tinfo2
);
745 if (debugout
) TRACE_(olerelay
)("*");
746 /* Write always, so the other side knows when it gets a NULL pointer.
748 cookie
= *arg
? 0x42424242 : 0;
749 hres
= xbuf_add(buf
,(LPBYTE
)&cookie
,sizeof(cookie
));
753 if (debugout
) TRACE_(olerelay
)("NULL");
756 hres
= serialize_param(tinfo
,writeit
,debugout
,dealloc
,tdesc
->u
.lptdesc
,(DWORD
*)*arg
,buf
);
757 if (derefhere
&& dealloc
) HeapFree(GetProcessHeap(),0,(LPVOID
)*arg
);
761 if (debugout
) TRACE_(olerelay
)("unk(0x%x)",*arg
);
763 hres
= _marshal_interface(buf
,&IID_IUnknown
,(LPUNKNOWN
)*arg
);
764 if (dealloc
&& *(IUnknown
**)arg
)
765 IUnknown_Release((LPUNKNOWN
)*arg
);
768 if (debugout
) TRACE_(olerelay
)("idisp(0x%x)",*arg
);
770 hres
= _marshal_interface(buf
,&IID_IDispatch
,(LPUNKNOWN
)*arg
);
771 if (dealloc
&& *(IUnknown
**)arg
)
772 IUnknown_Release((LPUNKNOWN
)*arg
);
775 if (debugout
) TRACE_(olerelay
)("<void>");
777 case VT_USERDEFINED
: {
781 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
783 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc
->u
.hreftype
);
786 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
787 switch (tattr
->typekind
) {
789 case TKIND_INTERFACE
:
791 hres
=_marshal_interface(buf
,&(tattr
->guid
),(LPUNKNOWN
)arg
);
793 IUnknown_Release((LPUNKNOWN
)arg
);
797 if (debugout
) TRACE_(olerelay
)("{");
798 for (i
=0;i
<tattr
->cVars
;i
++) {
803 hres
= ITypeInfo2_GetVarDesc(tinfo2
, i
, &vdesc
);
805 ERR("Could not get vardesc of %d\n",i
);
808 elem2
= &vdesc
->elemdescVar
;
809 tdesc2
= &elem2
->tdesc
;
810 hres
= serialize_param(
816 (DWORD
*)(((LPBYTE
)arg
)+vdesc
->u
.oInst
),
819 ITypeInfo_ReleaseVarDesc(tinfo2
, vdesc
);
822 if (debugout
&& (i
<(tattr
->cVars
-1)))
823 TRACE_(olerelay
)(",");
825 if (debugout
) TRACE_(olerelay
)("}");
829 hres
= serialize_param(tinfo2
,writeit
,debugout
,dealloc
,&tattr
->tdescAlias
,arg
,buf
);
833 if (debugout
) TRACE_(olerelay
)("%x",*arg
);
835 hres
= xbuf_add(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
838 FIXME("Unhandled typekind %d\n",tattr
->typekind
);
842 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
843 ITypeInfo_Release(tinfo2
);
847 ARRAYDESC
*adesc
= tdesc
->u
.lpadesc
;
850 if (debugout
) TRACE_(olerelay
)("carr");
851 for (i
=0;i
<adesc
->cDims
;i
++) {
852 if (debugout
) TRACE_(olerelay
)("[%d]",adesc
->rgbounds
[i
].cElements
);
853 arrsize
*= adesc
->rgbounds
[i
].cElements
;
855 if (debugout
) TRACE_(olerelay
)("(vt %s)",debugstr_vt(adesc
->tdescElem
.vt
));
856 if (debugout
) TRACE_(olerelay
)("[");
857 for (i
=0;i
<arrsize
;i
++) {
858 hres
= serialize_param(tinfo
, writeit
, debugout
, dealloc
, &adesc
->tdescElem
, (DWORD
*)((LPBYTE
)(*arg
)+i
*_xsize(&adesc
->tdescElem
, tinfo
)), buf
);
861 if (debugout
&& (i
<arrsize
-1)) TRACE_(olerelay
)(",");
863 if (debugout
) TRACE_(olerelay
)("]");
865 HeapFree(GetProcessHeap(), 0, *(void **)arg
);
871 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
872 ULONG size
= LPSAFEARRAY_UserSize(&flags
, buf
->curoff
, (LPSAFEARRAY
*)arg
);
873 xbuf_resize(buf
, size
);
874 LPSAFEARRAY_UserMarshal(&flags
, buf
->base
+ buf
->curoff
, (LPSAFEARRAY
*)arg
);
879 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
880 LPSAFEARRAY_UserFree(&flags
, (LPSAFEARRAY
*)arg
);
885 ERR("Unhandled marshal type %d.\n",tdesc
->vt
);
903 TRACE("vt %s at %p\n",debugstr_vt(tdesc
->vt
),arg
);
906 if ((vartype
& 0xf000) == VT_ARRAY
)
907 vartype
= VT_SAFEARRAY
;
914 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
915 unsigned char *buffer
;
916 buffer
= VARIANT_UserUnmarshal(&flags
, buf
->base
+ buf
->curoff
, (VARIANT
*)arg
);
917 buf
->curoff
= buffer
- buf
->base
;
927 hres
= xbuf_get(buf
,(LPBYTE
)arg
,8);
928 if (hres
) ERR("Failed to read integer 8 byte\n");
930 if (debugout
) TRACE_(olerelay
)("%x%x",arg
[0],arg
[1]);
939 hres
= xbuf_get(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
940 if (hres
) ERR("Failed to read integer 4 byte\n");
942 if (debugout
) TRACE_(olerelay
)("%x",*arg
);
949 hres
= xbuf_get(buf
,(LPBYTE
)&x
,sizeof(DWORD
));
950 if (hres
) ERR("Failed to read integer 4 byte\n");
953 if (debugout
) TRACE_(olerelay
)("%04x",*arg
& 0xffff);
959 hres
= xbuf_get(buf
,(LPBYTE
)&x
,sizeof(DWORD
));
960 if (hres
) ERR("Failed to read integer 4 byte\n");
963 if (debugout
) TRACE_(olerelay
)("%02x",*arg
& 0xff);
968 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
969 unsigned char *buffer
;
970 buffer
= BSTR_UserUnmarshal(&flags
, buf
->base
+ buf
->curoff
, (BSTR
*)arg
);
971 buf
->curoff
= buffer
- buf
->base
;
972 if (debugout
) TRACE_(olerelay
)("%s",debugstr_w(*(BSTR
*)arg
));
978 BOOL derefhere
= TRUE
;
980 if (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
) {
984 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.lptdesc
->u
.hreftype
,&tinfo2
);
986 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc
->u
.lptdesc
->u
.hreftype
);
989 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
990 switch (tattr
->typekind
) {
992 if (tattr
->tdescAlias
.vt
== VT_USERDEFINED
)
994 DWORD href
= tattr
->tdescAlias
.u
.hreftype
;
995 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
996 ITypeInfo_Release(tinfo2
);
997 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,href
,&tinfo2
);
999 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc
->u
.lptdesc
->u
.hreftype
);
1002 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
1003 derefhere
= (tattr
->typekind
!= TKIND_DISPATCH
&& tattr
->typekind
!= TKIND_INTERFACE
);
1006 case TKIND_ENUM
: /* confirmed */
1007 case TKIND_RECORD
: /* FIXME: mostly untested */
1009 case TKIND_DISPATCH
: /* will be done in VT_USERDEFINED case */
1010 case TKIND_INTERFACE
: /* will be done in VT_USERDEFINED case */
1014 FIXME("unhandled switch cases tattr->typekind %d\n", tattr
->typekind
);
1018 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
1019 ITypeInfo_Release(tinfo2
);
1021 /* read it in all cases, we need to know if we have
1022 * NULL pointer or not.
1024 hres
= xbuf_get(buf
,(LPBYTE
)&cookie
,sizeof(cookie
));
1026 ERR("Failed to load pointer cookie.\n");
1029 if (cookie
!= 0x42424242) {
1030 /* we read a NULL ptr from the remote side */
1031 if (debugout
) TRACE_(olerelay
)("NULL");
1035 if (debugout
) TRACE_(olerelay
)("*");
1037 /* Allocate space for the referenced struct */
1039 *arg
=(DWORD
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,_xsize(tdesc
->u
.lptdesc
, tinfo
));
1042 return deserialize_param(tinfo
, readit
, debugout
, alloc
, tdesc
->u
.lptdesc
, (LPDWORD
)*arg
, buf
);
1044 return deserialize_param(tinfo
, readit
, debugout
, alloc
, tdesc
->u
.lptdesc
, arg
, buf
);
1047 /* FIXME: UNKNOWN is unknown ..., but allocate 4 byte for it */
1049 *arg
=(DWORD
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
));
1052 hres
= _unmarshal_interface(buf
,&IID_IUnknown
,(LPUNKNOWN
*)arg
);
1054 TRACE_(olerelay
)("unk(%p)",arg
);
1059 hres
= _unmarshal_interface(buf
,&IID_IDispatch
,(LPUNKNOWN
*)arg
);
1061 TRACE_(olerelay
)("idisp(%p)",arg
);
1064 if (debugout
) TRACE_(olerelay
)("<void>");
1066 case VT_USERDEFINED
: {
1070 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
1072 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED.\n",tdesc
->u
.hreftype
);
1075 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
1077 ERR("Could not get typeattr in VT_USERDEFINED.\n");
1079 switch (tattr
->typekind
) {
1080 case TKIND_DISPATCH
:
1081 case TKIND_INTERFACE
:
1083 hres
= _unmarshal_interface(buf
,&(tattr
->guid
),(LPUNKNOWN
*)arg
);
1085 case TKIND_RECORD
: {
1088 if (debugout
) TRACE_(olerelay
)("{");
1089 for (i
=0;i
<tattr
->cVars
;i
++) {
1092 hres
= ITypeInfo2_GetVarDesc(tinfo2
, i
, &vdesc
);
1094 ERR("Could not get vardesc of %d\n",i
);
1095 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
1096 ITypeInfo_Release(tinfo2
);
1099 hres
= deserialize_param(
1104 &vdesc
->elemdescVar
.tdesc
,
1105 (DWORD
*)(((LPBYTE
)arg
)+vdesc
->u
.oInst
),
1108 ITypeInfo2_ReleaseVarDesc(tinfo2
, vdesc
);
1109 if (debugout
&& (i
<tattr
->cVars
-1)) TRACE_(olerelay
)(",");
1111 if (debugout
) TRACE_(olerelay
)("}");
1115 hres
= deserialize_param(tinfo2
,readit
,debugout
,alloc
,&tattr
->tdescAlias
,arg
,buf
);
1119 hres
= xbuf_get(buf
,(LPBYTE
)arg
,sizeof(DWORD
));
1120 if (hres
) ERR("Failed to read enum (4 byte)\n");
1122 if (debugout
) TRACE_(olerelay
)("%x",*arg
);
1125 ERR("Unhandled typekind %d\n",tattr
->typekind
);
1129 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
1132 ERR("failed to stuballoc in TKIND_RECORD.\n");
1133 ITypeInfo_Release(tinfo2
);
1137 /* arg is pointing to the start of the array. */
1138 ARRAYDESC
*adesc
= tdesc
->u
.lpadesc
;
1141 if (adesc
->cDims
> 1) FIXME("cDims > 1 in VT_CARRAY. Does it work?\n");
1142 for (i
=0;i
<adesc
->cDims
;i
++)
1143 arrsize
*= adesc
->rgbounds
[i
].cElements
;
1144 *arg
=(DWORD
)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,_xsize(tdesc
->u
.lptdesc
, tinfo
) * arrsize
);
1145 for (i
=0;i
<arrsize
;i
++)
1152 (DWORD
*)((LPBYTE
)(*arg
)+i
*_xsize(&adesc
->tdescElem
, tinfo
)),
1157 case VT_SAFEARRAY
: {
1160 ULONG flags
= MAKELONG(MSHCTX_DIFFERENTMACHINE
, NDR_LOCAL_DATA_REPRESENTATION
);
1161 unsigned char *buffer
;
1162 buffer
= LPSAFEARRAY_UserUnmarshal(&flags
, buf
->base
+ buf
->curoff
, (LPSAFEARRAY
*)arg
);
1163 buf
->curoff
= buffer
- buf
->base
;
1168 ERR("No handler for VT type %d!\n",tdesc
->vt
);
1174 /* Retrieves a function's funcdesc, searching back into inherited interfaces. */
1175 static HRESULT
get_funcdesc(ITypeInfo
*tinfo
, int iMethod
, ITypeInfo
**tactual
, const FUNCDESC
**fdesc
,
1176 BSTR
*iname
, BSTR
*fname
, UINT
*num
)
1180 UINT inherited_funcs
= 0;
1183 if (fname
) *fname
= NULL
;
1184 if (iname
) *iname
= NULL
;
1188 hr
= ITypeInfo_GetTypeAttr(tinfo
, &attr
);
1191 ERR("GetTypeAttr failed with %x\n",hr
);
1195 if(attr
->typekind
== TKIND_DISPATCH
)
1197 if(attr
->wTypeFlags
& TYPEFLAG_FDUAL
)
1202 hr
= ITypeInfo_GetRefTypeOfImplType(tinfo
, -1, &href
);
1205 ERR("Cannot get interface href from dual dispinterface\n");
1206 ITypeInfo_ReleaseTypeAttr(tinfo
, attr
);
1209 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
1212 ERR("Cannot get interface from dual dispinterface\n");
1213 ITypeInfo_ReleaseTypeAttr(tinfo
, attr
);
1216 hr
= get_funcdesc(tinfo2
, iMethod
, tactual
, fdesc
, iname
, fname
, num
);
1217 ITypeInfo_Release(tinfo2
);
1218 ITypeInfo_ReleaseTypeAttr(tinfo
, attr
);
1221 ERR("Shouldn't be called with a non-dual dispinterface\n");
1225 impl_types
= attr
->cImplTypes
;
1226 ITypeInfo_ReleaseTypeAttr(tinfo
, attr
);
1228 for (i
= 0; i
< impl_types
; i
++)
1231 ITypeInfo
*pSubTypeInfo
;
1234 hr
= ITypeInfo_GetRefTypeOfImplType(tinfo
, i
, &href
);
1235 if (FAILED(hr
)) return hr
;
1236 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &pSubTypeInfo
);
1237 if (FAILED(hr
)) return hr
;
1239 hr
= get_funcdesc(pSubTypeInfo
, iMethod
, tactual
, fdesc
, iname
, fname
, &sub_funcs
);
1240 inherited_funcs
+= sub_funcs
;
1241 ITypeInfo_Release(pSubTypeInfo
);
1242 if(SUCCEEDED(hr
)) return hr
;
1244 if(iMethod
< inherited_funcs
)
1246 ERR("shouldn't be here\n");
1247 return E_INVALIDARG
;
1250 for(i
= inherited_funcs
; i
<= iMethod
; i
++)
1252 hr
= ITypeInfoImpl_GetInternalFuncDesc(tinfo
, i
- inherited_funcs
, fdesc
);
1260 /* found it. We don't care about num so zero it */
1263 ITypeInfo_AddRef(*tactual
);
1264 if (fname
) ITypeInfo_GetDocumentation(tinfo
,(*fdesc
)->memid
,fname
,NULL
,NULL
,NULL
);
1265 if (iname
) ITypeInfo_GetDocumentation(tinfo
,-1,iname
,NULL
,NULL
,NULL
);
1269 static inline BOOL
is_in_elem(const ELEMDESC
*elem
)
1271 return (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FIN
|| !elem
->u
.paramdesc
.wParamFlags
);
1274 static inline BOOL
is_out_elem(const ELEMDESC
*elem
)
1276 return (elem
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FOUT
|| !elem
->u
.paramdesc
.wParamFlags
);
1280 xCall(LPVOID retptr
, int method
, TMProxyImpl
*tpinfo
/*, args */)
1282 DWORD
*args
= ((DWORD
*)&tpinfo
)+1, *xargs
;
1283 const FUNCDESC
*fdesc
;
1285 int i
, relaydeb
= TRACE_ON(olerelay
);
1292 DWORD remoteresult
= 0;
1294 IRpcChannelBuffer
*chanbuf
;
1296 EnterCriticalSection(&tpinfo
->crit
);
1298 hres
= get_funcdesc(tpinfo
->tinfo
,method
,&tinfo
,&fdesc
,&iname
,&fname
,NULL
);
1300 ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method
);
1301 LeaveCriticalSection(&tpinfo
->crit
);
1305 if (!tpinfo
->chanbuf
)
1307 WARN("Tried to use disconnected proxy\n");
1308 ITypeInfo_Release(tinfo
);
1309 LeaveCriticalSection(&tpinfo
->crit
);
1310 return RPC_E_DISCONNECTED
;
1312 chanbuf
= tpinfo
->chanbuf
;
1313 IRpcChannelBuffer_AddRef(chanbuf
);
1315 LeaveCriticalSection(&tpinfo
->crit
);
1318 TRACE_(olerelay
)("->");
1320 TRACE_(olerelay
)("%s:",relaystr(iname
));
1322 TRACE_(olerelay
)("%s(%d)",relaystr(fname
),method
);
1324 TRACE_(olerelay
)("%d",method
);
1325 TRACE_(olerelay
)("(");
1328 SysFreeString(iname
);
1329 SysFreeString(fname
);
1331 memset(&buf
,0,sizeof(buf
));
1333 /* normal typelib driven serializing */
1335 /* Need them for hack below */
1336 memset(names
,0,sizeof(names
));
1337 if (ITypeInfo_GetNames(tinfo
,fdesc
->memid
,names
,sizeof(names
)/sizeof(names
[0]),&nrofnames
))
1339 if (nrofnames
> sizeof(names
)/sizeof(names
[0]))
1340 ERR("Need more names!\n");
1343 for (i
=0;i
<fdesc
->cParams
;i
++) {
1344 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
1346 if (i
) TRACE_(olerelay
)(",");
1347 if (i
+1<nrofnames
&& names
[i
+1])
1348 TRACE_(olerelay
)("%s=",relaystr(names
[i
+1]));
1350 /* No need to marshal other data than FIN and any VT_PTR. */
1351 if (!is_in_elem(elem
) && (elem
->tdesc
.vt
!= VT_PTR
)) {
1352 xargs
+=_argsize(&elem
->tdesc
, tinfo
);
1353 if (relaydeb
) TRACE_(olerelay
)("[out]");
1356 hres
= serialize_param(
1367 ERR("Failed to serialize param, hres %x\n",hres
);
1370 xargs
+=_argsize(&elem
->tdesc
, tinfo
);
1372 if (relaydeb
) TRACE_(olerelay
)(")");
1374 memset(&msg
,0,sizeof(msg
));
1375 msg
.cbBuffer
= buf
.curoff
;
1376 msg
.iMethod
= method
;
1377 hres
= IRpcChannelBuffer_GetBuffer(chanbuf
,&msg
,&(tpinfo
->iid
));
1379 ERR("RpcChannelBuffer GetBuffer failed, %x\n",hres
);
1382 memcpy(msg
.Buffer
,buf
.base
,buf
.curoff
);
1383 if (relaydeb
) TRACE_(olerelay
)("\n");
1384 hres
= IRpcChannelBuffer_SendReceive(chanbuf
,&msg
,&status
);
1386 ERR("RpcChannelBuffer SendReceive failed, %x\n",hres
);
1390 if (relaydeb
) TRACE_(olerelay
)(" status = %08x (",status
);
1392 buf
.base
= HeapReAlloc(GetProcessHeap(),0,buf
.base
,msg
.cbBuffer
);
1394 buf
.base
= HeapAlloc(GetProcessHeap(),0,msg
.cbBuffer
);
1395 buf
.size
= msg
.cbBuffer
;
1396 memcpy(buf
.base
,msg
.Buffer
,buf
.size
);
1399 /* generic deserializer using typelib description */
1402 for (i
=0;i
<fdesc
->cParams
;i
++) {
1403 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
1406 if (i
) TRACE_(olerelay
)(",");
1407 if (i
+1<nrofnames
&& names
[i
+1]) TRACE_(olerelay
)("%s=",relaystr(names
[i
+1]));
1409 /* No need to marshal other data than FOUT and any VT_PTR */
1410 if (!is_out_elem(elem
) && (elem
->tdesc
.vt
!= VT_PTR
)) {
1411 xargs
+= _argsize(&elem
->tdesc
, tinfo
);
1412 if (relaydeb
) TRACE_(olerelay
)("[in]");
1415 hres
= deserialize_param(
1425 ERR("Failed to unmarshall param, hres %x\n",hres
);
1429 xargs
+= _argsize(&elem
->tdesc
, tinfo
);
1432 hres
= xbuf_get(&buf
, (LPBYTE
)&remoteresult
, sizeof(DWORD
));
1435 if (relaydeb
) TRACE_(olerelay
)(") = %08x\n", remoteresult
);
1437 hres
= remoteresult
;
1440 IRpcChannelBuffer_FreeBuffer(chanbuf
,&msg
);
1441 for (i
= 0; i
< nrofnames
; i
++)
1442 SysFreeString(names
[i
]);
1443 HeapFree(GetProcessHeap(),0,buf
.base
);
1444 IRpcChannelBuffer_Release(chanbuf
);
1445 ITypeInfo_Release(tinfo
);
1446 TRACE("-- 0x%08x\n", hres
);
1450 static HRESULT WINAPI
ProxyIUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
1452 TMProxyImpl
*proxy
= (TMProxyImpl
*)iface
;
1454 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
1456 if (proxy
->outerunknown
)
1457 return IUnknown_QueryInterface(proxy
->outerunknown
, riid
, ppv
);
1459 FIXME("No interface\n");
1460 return E_NOINTERFACE
;
1463 static ULONG WINAPI
ProxyIUnknown_AddRef(IUnknown
*iface
)
1465 TMProxyImpl
*proxy
= (TMProxyImpl
*)iface
;
1469 if (proxy
->outerunknown
)
1470 return IUnknown_AddRef(proxy
->outerunknown
);
1472 return 2; /* FIXME */
1475 static ULONG WINAPI
ProxyIUnknown_Release(IUnknown
*iface
)
1477 TMProxyImpl
*proxy
= (TMProxyImpl
*)iface
;
1481 if (proxy
->outerunknown
)
1482 return IUnknown_Release(proxy
->outerunknown
);
1484 return 1; /* FIXME */
1487 static HRESULT WINAPI
ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface
, UINT
* pctinfo
)
1489 TMProxyImpl
*This
= (TMProxyImpl
*)iface
;
1491 TRACE("(%p)\n", pctinfo
);
1493 return IDispatch_GetTypeInfoCount(This
->dispatch
, pctinfo
);
1496 static HRESULT WINAPI
ProxyIDispatch_GetTypeInfo(LPDISPATCH iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
1498 TMProxyImpl
*This
= (TMProxyImpl
*)iface
;
1500 TRACE("(%d, %x, %p)\n", iTInfo
, lcid
, ppTInfo
);
1502 return IDispatch_GetTypeInfo(This
->dispatch
, iTInfo
, lcid
, ppTInfo
);
1505 static HRESULT WINAPI
ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface
, REFIID riid
, LPOLESTR
* rgszNames
, UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
1507 TMProxyImpl
*This
= (TMProxyImpl
*)iface
;
1509 TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1511 return IDispatch_GetIDsOfNames(This
->dispatch
, riid
, rgszNames
,
1512 cNames
, lcid
, rgDispId
);
1515 static HRESULT WINAPI
ProxyIDispatch_Invoke(LPDISPATCH iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
1516 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
1517 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
1519 TMProxyImpl
*This
= (TMProxyImpl
*)iface
;
1521 TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember
,
1522 debugstr_guid(riid
), lcid
, wFlags
, pDispParams
, pVarResult
,
1523 pExcepInfo
, puArgErr
);
1525 return IDispatch_Invoke(This
->dispatch
, dispIdMember
, riid
, lcid
,
1526 wFlags
, pDispParams
, pVarResult
, pExcepInfo
,
1532 IRpcChannelBuffer IRpcChannelBuffer_iface
;
1534 /* the IDispatch-derived interface we are handling */
1536 IRpcChannelBuffer
*pDelegateChannel
;
1537 } TMarshalDispatchChannel
;
1539 static inline TMarshalDispatchChannel
*impl_from_IRpcChannelBuffer(IRpcChannelBuffer
*iface
)
1541 return CONTAINING_RECORD(iface
, TMarshalDispatchChannel
, IRpcChannelBuffer_iface
);
1544 static HRESULT WINAPI
TMarshalDispatchChannel_QueryInterface(LPRPCCHANNELBUFFER iface
, REFIID riid
, LPVOID
*ppv
)
1547 if (IsEqualIID(riid
,&IID_IRpcChannelBuffer
) || IsEqualIID(riid
,&IID_IUnknown
))
1550 IUnknown_AddRef(iface
);
1553 return E_NOINTERFACE
;
1556 static ULONG WINAPI
TMarshalDispatchChannel_AddRef(LPRPCCHANNELBUFFER iface
)
1558 TMarshalDispatchChannel
*This
= impl_from_IRpcChannelBuffer(iface
);
1559 return InterlockedIncrement(&This
->refs
);
1562 static ULONG WINAPI
TMarshalDispatchChannel_Release(LPRPCCHANNELBUFFER iface
)
1564 TMarshalDispatchChannel
*This
= impl_from_IRpcChannelBuffer(iface
);
1567 ref
= InterlockedDecrement(&This
->refs
);
1571 IRpcChannelBuffer_Release(This
->pDelegateChannel
);
1572 HeapFree(GetProcessHeap(), 0, This
);
1576 static HRESULT WINAPI
TMarshalDispatchChannel_GetBuffer(LPRPCCHANNELBUFFER iface
, RPCOLEMESSAGE
* olemsg
, REFIID riid
)
1578 TMarshalDispatchChannel
*This
= impl_from_IRpcChannelBuffer(iface
);
1579 TRACE("(%p, %s)\n", olemsg
, debugstr_guid(riid
));
1580 /* Note: we are pretending to invoke a method on the interface identified
1581 * by tmarshal_iid so that we can re-use the IDispatch proxy/stub code
1582 * without the RPC runtime getting confused by not exporting an IDispatch interface */
1583 return IRpcChannelBuffer_GetBuffer(This
->pDelegateChannel
, olemsg
, &This
->tmarshal_iid
);
1586 static HRESULT WINAPI
TMarshalDispatchChannel_SendReceive(LPRPCCHANNELBUFFER iface
, RPCOLEMESSAGE
*olemsg
, ULONG
*pstatus
)
1588 TMarshalDispatchChannel
*This
= impl_from_IRpcChannelBuffer(iface
);
1589 TRACE("(%p, %p)\n", olemsg
, pstatus
);
1590 return IRpcChannelBuffer_SendReceive(This
->pDelegateChannel
, olemsg
, pstatus
);
1593 static HRESULT WINAPI
TMarshalDispatchChannel_FreeBuffer(LPRPCCHANNELBUFFER iface
, RPCOLEMESSAGE
* olemsg
)
1595 TMarshalDispatchChannel
*This
= impl_from_IRpcChannelBuffer(iface
);
1596 TRACE("(%p)\n", olemsg
);
1597 return IRpcChannelBuffer_FreeBuffer(This
->pDelegateChannel
, olemsg
);
1600 static HRESULT WINAPI
TMarshalDispatchChannel_GetDestCtx(LPRPCCHANNELBUFFER iface
, DWORD
* pdwDestContext
, void** ppvDestContext
)
1602 TMarshalDispatchChannel
*This
= impl_from_IRpcChannelBuffer(iface
);
1603 TRACE("(%p,%p)\n", pdwDestContext
, ppvDestContext
);
1604 return IRpcChannelBuffer_GetDestCtx(This
->pDelegateChannel
, pdwDestContext
, ppvDestContext
);
1607 static HRESULT WINAPI
TMarshalDispatchChannel_IsConnected(LPRPCCHANNELBUFFER iface
)
1609 TMarshalDispatchChannel
*This
= impl_from_IRpcChannelBuffer(iface
);
1611 return IRpcChannelBuffer_IsConnected(This
->pDelegateChannel
);
1614 static const IRpcChannelBufferVtbl TMarshalDispatchChannelVtbl
=
1616 TMarshalDispatchChannel_QueryInterface
,
1617 TMarshalDispatchChannel_AddRef
,
1618 TMarshalDispatchChannel_Release
,
1619 TMarshalDispatchChannel_GetBuffer
,
1620 TMarshalDispatchChannel_SendReceive
,
1621 TMarshalDispatchChannel_FreeBuffer
,
1622 TMarshalDispatchChannel_GetDestCtx
,
1623 TMarshalDispatchChannel_IsConnected
1626 static HRESULT
TMarshalDispatchChannel_Create(
1627 IRpcChannelBuffer
*pDelegateChannel
, REFIID tmarshal_riid
,
1628 IRpcChannelBuffer
**ppChannel
)
1630 TMarshalDispatchChannel
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1632 return E_OUTOFMEMORY
;
1634 This
->IRpcChannelBuffer_iface
.lpVtbl
= &TMarshalDispatchChannelVtbl
;
1636 IRpcChannelBuffer_AddRef(pDelegateChannel
);
1637 This
->pDelegateChannel
= pDelegateChannel
;
1638 This
->tmarshal_iid
= *tmarshal_riid
;
1640 *ppChannel
= &This
->IRpcChannelBuffer_iface
;
1645 static inline HRESULT
get_facbuf_for_iid(REFIID riid
, IPSFactoryBuffer
**facbuf
)
1650 if ((hr
= CoGetPSClsid(riid
, &clsid
)))
1652 return CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
,
1653 &IID_IPSFactoryBuffer
, (LPVOID
*)facbuf
);
1656 static HRESULT
init_proxy_entry_point(TMProxyImpl
*proxy
, unsigned int num
)
1659 /* nrofargs without This */
1662 TMAsmProxy
*xasm
= proxy
->asmstubs
+ num
;
1664 const FUNCDESC
*fdesc
;
1666 hres
= get_funcdesc(proxy
->tinfo
, num
, &tinfo2
, &fdesc
, NULL
, NULL
, NULL
);
1668 ERR("GetFuncDesc %x should not fail here.\n",hres
);
1671 ITypeInfo_Release(tinfo2
);
1672 /* some args take more than 4 byte on the stack */
1674 for (j
=0;j
<fdesc
->cParams
;j
++)
1675 nrofargs
+= _argsize(&fdesc
->lprgelemdescParam
[j
].tdesc
, proxy
->tinfo
);
1678 if (fdesc
->callconv
!= CC_STDCALL
) {
1679 ERR("calling convention is not stdcall????\n");
1682 /* popl %eax - return ptr
1689 * arg3 arg2 arg1 <method> <returnptr>
1691 xasm
->popleax
= 0x58;
1692 xasm
->pushlval
= 0x68;
1694 xasm
->pushleax
= 0x50;
1695 xasm
->lcall
= 0xe8; /* relative jump */
1696 xasm
->xcall
= (DWORD
)xCall
;
1697 xasm
->xcall
-= (DWORD
)&(xasm
->lret
);
1699 xasm
->bytestopop
= (nrofargs
+2)*4; /* pop args, This, iMethod */
1701 proxy
->lpvtbl
[num
] = xasm
;
1703 FIXME("not implemented on non i386\n");
1709 static HRESULT WINAPI
1710 PSFacBuf_CreateProxy(
1711 LPPSFACTORYBUFFER iface
, IUnknown
* pUnkOuter
, REFIID riid
,
1712 IRpcProxyBuffer
**ppProxy
, LPVOID
*ppv
)
1716 unsigned int i
, nroffuncs
;
1719 BOOL defer_to_dispatch
= FALSE
;
1721 TRACE("(...%s...)\n",debugstr_guid(riid
));
1722 hres
= _get_typeinfo_for_iid(riid
,&tinfo
);
1724 ERR("No typeinfo for %s?\n",debugstr_guid(riid
));
1728 hres
= num_of_funcs(tinfo
, &nroffuncs
);
1730 ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid
));
1731 ITypeInfo_Release(tinfo
);
1735 proxy
= CoTaskMemAlloc(sizeof(TMProxyImpl
));
1736 if (!proxy
) return E_OUTOFMEMORY
;
1738 assert(sizeof(TMAsmProxy
) == 16);
1740 proxy
->dispatch
= NULL
;
1741 proxy
->dispatch_proxy
= NULL
;
1742 proxy
->outerunknown
= pUnkOuter
;
1743 proxy
->asmstubs
= VirtualAlloc(NULL
, sizeof(TMAsmProxy
) * nroffuncs
, MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
1744 if (!proxy
->asmstubs
) {
1745 ERR("Could not commit pages for proxy thunks\n");
1746 CoTaskMemFree(proxy
);
1747 return E_OUTOFMEMORY
;
1749 proxy
->IRpcProxyBuffer_iface
.lpVtbl
= &tmproxyvtable
;
1750 /* one reference for the proxy */
1752 proxy
->tinfo
= tinfo
;
1756 InitializeCriticalSection(&proxy
->crit
);
1757 proxy
->crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": TMProxyImpl.crit");
1759 proxy
->lpvtbl
= HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE
)*nroffuncs
);
1761 /* if we derive from IDispatch then defer to its proxy for its methods */
1762 hres
= ITypeInfo_GetTypeAttr(tinfo
, &typeattr
);
1765 if (typeattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
1767 IPSFactoryBuffer
*factory_buffer
;
1768 hres
= get_facbuf_for_iid(&IID_IDispatch
, &factory_buffer
);
1771 hres
= IPSFactoryBuffer_CreateProxy(factory_buffer
, NULL
,
1772 &IID_IDispatch
, &proxy
->dispatch_proxy
,
1773 (void **)&proxy
->dispatch
);
1774 IPSFactoryBuffer_Release(factory_buffer
);
1776 if ((hres
== S_OK
) && (nroffuncs
< 7))
1778 ERR("nroffuncs calculated incorrectly (%d)\n", nroffuncs
);
1779 hres
= E_UNEXPECTED
;
1783 defer_to_dispatch
= TRUE
;
1786 ITypeInfo_ReleaseTypeAttr(tinfo
, typeattr
);
1789 for (i
=0;i
<nroffuncs
;i
++) {
1792 proxy
->lpvtbl
[i
] = ProxyIUnknown_QueryInterface
;
1795 proxy
->lpvtbl
[i
] = ProxyIUnknown_AddRef
;
1798 proxy
->lpvtbl
[i
] = ProxyIUnknown_Release
;
1801 if(!defer_to_dispatch
)
1803 hres
= init_proxy_entry_point(proxy
, i
);
1804 if(FAILED(hres
)) return hres
;
1806 else proxy
->lpvtbl
[3] = ProxyIDispatch_GetTypeInfoCount
;
1809 if(!defer_to_dispatch
)
1811 hres
= init_proxy_entry_point(proxy
, i
);
1812 if(FAILED(hres
)) return hres
;
1814 else proxy
->lpvtbl
[4] = ProxyIDispatch_GetTypeInfo
;
1817 if(!defer_to_dispatch
)
1819 hres
= init_proxy_entry_point(proxy
, i
);
1820 if(FAILED(hres
)) return hres
;
1822 else proxy
->lpvtbl
[5] = ProxyIDispatch_GetIDsOfNames
;
1825 if(!defer_to_dispatch
)
1827 hres
= init_proxy_entry_point(proxy
, i
);
1828 if(FAILED(hres
)) return hres
;
1830 else proxy
->lpvtbl
[6] = ProxyIDispatch_Invoke
;
1833 hres
= init_proxy_entry_point(proxy
, i
);
1834 if(FAILED(hres
)) return hres
;
1841 *ppProxy
= &proxy
->IRpcProxyBuffer_iface
;
1842 IUnknown_AddRef((IUnknown
*)*ppv
);
1846 TMProxyImpl_Release(&proxy
->IRpcProxyBuffer_iface
);
1850 typedef struct _TMStubImpl
{
1851 IRpcStubBuffer IRpcStubBuffer_iface
;
1857 IRpcStubBuffer
*dispatch_stub
;
1858 BOOL dispatch_derivative
;
1861 static inline TMStubImpl
*impl_from_IRpcStubBuffer(IRpcStubBuffer
*iface
)
1863 return CONTAINING_RECORD(iface
, TMStubImpl
, IRpcStubBuffer_iface
);
1866 static HRESULT WINAPI
1867 TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface
, REFIID riid
, LPVOID
*ppv
)
1869 if (IsEqualIID(riid
,&IID_IRpcStubBuffer
)||IsEqualIID(riid
,&IID_IUnknown
)){
1871 IRpcStubBuffer_AddRef(iface
);
1874 FIXME("%s, not supported IID.\n",debugstr_guid(riid
));
1875 return E_NOINTERFACE
;
1879 TMStubImpl_AddRef(LPRPCSTUBBUFFER iface
)
1881 TMStubImpl
*This
= impl_from_IRpcStubBuffer(iface
);
1882 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1884 TRACE("(%p)->(ref before=%u)\n", This
, refCount
- 1);
1890 TMStubImpl_Release(LPRPCSTUBBUFFER iface
)
1892 TMStubImpl
*This
= impl_from_IRpcStubBuffer(iface
);
1893 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1895 TRACE("(%p)->(ref before=%u)\n", This
, refCount
+ 1);
1899 IRpcStubBuffer_Disconnect(iface
);
1900 ITypeInfo_Release(This
->tinfo
);
1901 if (This
->dispatch_stub
)
1902 IRpcStubBuffer_Release(This
->dispatch_stub
);
1903 CoTaskMemFree(This
);
1908 static HRESULT WINAPI
1909 TMStubImpl_Connect(LPRPCSTUBBUFFER iface
, LPUNKNOWN pUnkServer
)
1911 TMStubImpl
*This
= impl_from_IRpcStubBuffer(iface
);
1913 TRACE("(%p)->(%p)\n", This
, pUnkServer
);
1915 IUnknown_AddRef(pUnkServer
);
1916 This
->pUnk
= pUnkServer
;
1918 if (This
->dispatch_stub
)
1919 IRpcStubBuffer_Connect(This
->dispatch_stub
, pUnkServer
);
1925 TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface
)
1927 TMStubImpl
*This
= impl_from_IRpcStubBuffer(iface
);
1929 TRACE("(%p)->()\n", This
);
1933 IUnknown_Release(This
->pUnk
);
1937 if (This
->dispatch_stub
)
1938 IRpcStubBuffer_Disconnect(This
->dispatch_stub
);
1941 static HRESULT WINAPI
1943 LPRPCSTUBBUFFER iface
, RPCOLEMESSAGE
* xmsg
,IRpcChannelBuffer
*rpcchanbuf
)
1947 const FUNCDESC
*fdesc
;
1948 TMStubImpl
*This
= impl_from_IRpcStubBuffer(iface
);
1950 DWORD
*args
= NULL
, res
, *xargs
, nrofargs
;
1955 ITypeInfo
*tinfo
= NULL
;
1959 if (xmsg
->iMethod
< 3) {
1960 ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
1961 return E_UNEXPECTED
;
1964 if (This
->dispatch_derivative
&& xmsg
->iMethod
< sizeof(IDispatchVtbl
)/sizeof(void *))
1966 IPSFactoryBuffer
*factory_buffer
;
1967 hres
= get_facbuf_for_iid(&IID_IDispatch
, &factory_buffer
);
1970 hres
= IPSFactoryBuffer_CreateStub(factory_buffer
, &IID_IDispatch
,
1971 This
->pUnk
, &This
->dispatch_stub
);
1972 IPSFactoryBuffer_Release(factory_buffer
);
1976 return IRpcStubBuffer_Invoke(This
->dispatch_stub
, xmsg
, rpcchanbuf
);
1979 memset(&buf
,0,sizeof(buf
));
1980 buf
.size
= xmsg
->cbBuffer
;
1981 buf
.base
= HeapAlloc(GetProcessHeap(), 0, xmsg
->cbBuffer
);
1982 memcpy(buf
.base
, xmsg
->Buffer
, xmsg
->cbBuffer
);
1985 hres
= get_funcdesc(This
->tinfo
,xmsg
->iMethod
,&tinfo
,&fdesc
,&iname
,NULL
,NULL
);
1987 ERR("GetFuncDesc on method %d failed with %x\n",xmsg
->iMethod
,hres
);
1991 if (iname
&& !lstrcmpW(iname
, IDispatchW
))
1993 ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
1994 hres
= E_UNEXPECTED
;
1995 SysFreeString (iname
);
1999 SysFreeString (iname
);
2001 /* Need them for hack below */
2002 memset(names
,0,sizeof(names
));
2003 ITypeInfo_GetNames(tinfo
,fdesc
->memid
,names
,sizeof(names
)/sizeof(names
[0]),&nrofnames
);
2004 if (nrofnames
> sizeof(names
)/sizeof(names
[0])) {
2005 ERR("Need more names!\n");
2008 /*dump_FUNCDESC(fdesc);*/
2010 for (i
=0;i
<fdesc
->cParams
;i
++)
2011 nrofargs
+= _argsize(&fdesc
->lprgelemdescParam
[i
].tdesc
, tinfo
);
2012 args
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,(nrofargs
+1)*sizeof(DWORD
));
2015 hres
= E_OUTOFMEMORY
;
2019 /* Allocate all stuff used by call. */
2021 for (i
=0;i
<fdesc
->cParams
;i
++) {
2022 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
2024 hres
= deserialize_param(
2033 xargs
+= _argsize(&elem
->tdesc
, tinfo
);
2035 ERR("Failed to deserialize param %s, hres %x\n",relaystr(names
[i
+1]),hres
);
2040 args
[0] = (DWORD
)This
->pUnk
;
2045 (*((FARPROC
**)args
[0]))[fdesc
->oVft
/4],
2053 DWORD dwExceptionCode
= GetExceptionCode();
2054 ERR("invoke call failed with exception 0x%08x (%d)\n", dwExceptionCode
, dwExceptionCode
);
2055 if (FAILED(dwExceptionCode
))
2056 hres
= dwExceptionCode
;
2058 hres
= HRESULT_FROM_WIN32(dwExceptionCode
);
2068 for (i
=0;i
<fdesc
->cParams
;i
++) {
2069 ELEMDESC
*elem
= fdesc
->lprgelemdescParam
+i
;
2070 hres
= serialize_param(
2079 xargs
+= _argsize(&elem
->tdesc
, tinfo
);
2081 ERR("Failed to stuballoc param, hres %x\n",hres
);
2086 hres
= xbuf_add (&buf
, (LPBYTE
)&res
, sizeof(DWORD
));
2091 xmsg
->cbBuffer
= buf
.curoff
;
2092 hres
= IRpcChannelBuffer_GetBuffer(rpcchanbuf
, xmsg
, &This
->iid
);
2094 ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08x\n", hres
);
2097 memcpy(xmsg
->Buffer
, buf
.base
, buf
.curoff
);
2100 for (i
= 0; i
< nrofnames
; i
++)
2101 SysFreeString(names
[i
]);
2103 ITypeInfo_Release(tinfo
);
2104 HeapFree(GetProcessHeap(), 0, args
);
2106 HeapFree(GetProcessHeap(), 0, buf
.base
);
2108 TRACE("returning\n");
2111 FIXME( "not implemented on non-i386\n" );
2116 static LPRPCSTUBBUFFER WINAPI
2117 TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface
, REFIID riid
) {
2118 FIXME("Huh (%s)?\n",debugstr_guid(riid
));
2123 TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface
) {
2124 TMStubImpl
*This
= impl_from_IRpcStubBuffer(iface
);
2127 return This
->ref
; /*FIXME? */
2130 static HRESULT WINAPI
2131 TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface
, LPVOID
*ppv
) {
2136 TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface
, LPVOID ppv
) {
2140 static const IRpcStubBufferVtbl tmstubvtbl
= {
2141 TMStubImpl_QueryInterface
,
2145 TMStubImpl_Disconnect
,
2147 TMStubImpl_IsIIDSupported
,
2148 TMStubImpl_CountRefs
,
2149 TMStubImpl_DebugServerQueryInterface
,
2150 TMStubImpl_DebugServerRelease
2153 static HRESULT WINAPI
2154 PSFacBuf_CreateStub(
2155 LPPSFACTORYBUFFER iface
, REFIID riid
,IUnknown
*pUnkServer
,
2156 IRpcStubBuffer
** ppStub
2163 TRACE("(%s,%p,%p)\n",debugstr_guid(riid
),pUnkServer
,ppStub
);
2165 hres
= _get_typeinfo_for_iid(riid
,&tinfo
);
2167 ERR("No typeinfo for %s?\n",debugstr_guid(riid
));
2171 stub
= CoTaskMemAlloc(sizeof(TMStubImpl
));
2173 return E_OUTOFMEMORY
;
2174 stub
->IRpcStubBuffer_iface
.lpVtbl
= &tmstubvtbl
;
2176 stub
->tinfo
= tinfo
;
2177 stub
->dispatch_stub
= NULL
;
2178 stub
->dispatch_derivative
= FALSE
;
2180 hres
= IRpcStubBuffer_Connect(&stub
->IRpcStubBuffer_iface
,pUnkServer
);
2181 *ppStub
= &stub
->IRpcStubBuffer_iface
;
2182 TRACE("IRpcStubBuffer: %p\n", stub
);
2184 ERR("Connect to pUnkServer failed?\n");
2186 /* if we derive from IDispatch then defer to its stub for some of its methods */
2187 hres
= ITypeInfo_GetTypeAttr(tinfo
, &typeattr
);
2190 if (typeattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
2191 stub
->dispatch_derivative
= TRUE
;
2192 ITypeInfo_ReleaseTypeAttr(tinfo
, typeattr
);
2198 static const IPSFactoryBufferVtbl psfacbufvtbl
= {
2199 PSFacBuf_QueryInterface
,
2202 PSFacBuf_CreateProxy
,
2206 /* This is the whole PSFactoryBuffer object, just the vtableptr */
2207 static const IPSFactoryBufferVtbl
*lppsfac
= &psfacbufvtbl
;
2209 /***********************************************************************
2210 * TMARSHAL_DllGetClassObject
2212 HRESULT
TMARSHAL_DllGetClassObject(REFCLSID rclsid
, REFIID iid
,LPVOID
*ppv
)
2214 if (IsEqualIID(iid
,&IID_IPSFactoryBuffer
)) {
2218 return E_NOINTERFACE
;