📄 tmarshal.c
字号:
LeaveCriticalSection(&tpinfo->crit);
if (relaydeb) {
TRACE_(olerelay)("->");
if (iname)
TRACE_(olerelay)("%s:",relaystr(iname));
if (fname)
TRACE_(olerelay)("%s(%d)",relaystr(fname),method);
else
TRACE_(olerelay)("%d",method);
TRACE_(olerelay)("(");
}
if (iname) SysFreeString(iname);
if (fname) SysFreeString(fname);
memset(&buf,0,sizeof(buf));
/* normal typelib driven serializing */
/* Need them for hack below */
memset(names,0,sizeof(names));
if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
nrofnames = 0;
if (nrofnames > sizeof(names)/sizeof(names[0]))
ERR("Need more names!\n");
xargs = args;
for (i=0;i<fdesc->cParams;i++) {
ELEMDESC *elem = fdesc->lprgelemdescParam+i;
if (relaydeb) {
if (i) TRACE_(olerelay)(",");
if (i+1<nrofnames && names[i+1])
TRACE_(olerelay)("%s=",relaystr(names[i+1]));
}
/* No need to marshal other data than FIN and any VT_PTR. */
if (!is_in_elem(elem) && (elem->tdesc.vt != VT_PTR)) {
xargs+=_argsize(elem->tdesc.vt);
if (relaydeb) TRACE_(olerelay)("[out]");
continue;
}
hres = serialize_param(
tinfo,
is_in_elem(elem),
relaydeb,
FALSE,
&elem->tdesc,
xargs,
&buf
);
if (hres) {
ERR("Failed to serialize param, hres %x\n",hres);
break;
}
xargs+=_argsize(elem->tdesc.vt);
}
if (relaydeb) TRACE_(olerelay)(")");
memset(&msg,0,sizeof(msg));
msg.cbBuffer = buf.curoff;
msg.iMethod = method;
hres = IRpcChannelBuffer_GetBuffer(chanbuf,&msg,&(tpinfo->iid));
if (hres) {
ERR("RpcChannelBuffer GetBuffer failed, %x\n",hres);
goto exit;
}
memcpy(msg.Buffer,buf.base,buf.curoff);
if (relaydeb) TRACE_(olerelay)("\n");
hres = IRpcChannelBuffer_SendReceive(chanbuf,&msg,&status);
if (hres) {
ERR("RpcChannelBuffer SendReceive failed, %x\n",hres);
goto exit;
}
if (relaydeb) TRACE_(olerelay)(" status = %08x (",status);
if (buf.base)
buf.base = HeapReAlloc(GetProcessHeap(),0,buf.base,msg.cbBuffer);
else
buf.base = HeapAlloc(GetProcessHeap(),0,msg.cbBuffer);
buf.size = msg.cbBuffer;
memcpy(buf.base,msg.Buffer,buf.size);
buf.curoff = 0;
/* generic deserializer using typelib description */
xargs = args;
status = S_OK;
for (i=0;i<fdesc->cParams;i++) {
ELEMDESC *elem = fdesc->lprgelemdescParam+i;
if (relaydeb) {
if (i) TRACE_(olerelay)(",");
if (i+1<nrofnames && names[i+1]) TRACE_(olerelay)("%s=",relaystr(names[i+1]));
}
/* No need to marshal other data than FOUT and any VT_PTR */
if (!is_out_elem(elem) && (elem->tdesc.vt != VT_PTR)) {
xargs += _argsize(elem->tdesc.vt);
if (relaydeb) TRACE_(olerelay)("[in]");
continue;
}
hres = deserialize_param(
tinfo,
is_out_elem(elem),
relaydeb,
FALSE,
&(elem->tdesc),
xargs,
&buf
);
if (hres) {
ERR("Failed to unmarshall param, hres %x\n",hres);
status = hres;
break;
}
xargs += _argsize(elem->tdesc.vt);
}
hres = xbuf_get(&buf, (LPBYTE)&remoteresult, sizeof(DWORD));
if (hres != S_OK)
goto exit;
if (relaydeb) TRACE_(olerelay)(") = %08x\n", remoteresult);
hres = remoteresult;
exit:
for (i = 0; i < nrofnames; i++)
SysFreeString(names[i]);
HeapFree(GetProcessHeap(),0,buf.base);
IRpcChannelBuffer_Release(chanbuf);
ITypeInfo_Release(tinfo);
TRACE("-- 0x%08x\n", hres);
return hres;
}
static HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
TMProxyImpl *proxy = (TMProxyImpl *)iface;
TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
if (proxy->outerunknown)
return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);
FIXME("No interface\n");
return E_NOINTERFACE;
}
static ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
{
TMProxyImpl *proxy = (TMProxyImpl *)iface;
TRACE("\n");
if (proxy->outerunknown)
return IUnknown_AddRef(proxy->outerunknown);
return 2; /* FIXME */
}
static ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)
{
TMProxyImpl *proxy = (TMProxyImpl *)iface;
TRACE("\n");
if (proxy->outerunknown)
return IUnknown_Release(proxy->outerunknown);
return 1; /* FIXME */
}
static HRESULT WINAPI ProxyIDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
{
TMProxyImpl *This = (TMProxyImpl *)iface;
TRACE("(%p)\n", pctinfo);
return IDispatch_GetTypeInfoCount(This->dispatch, pctinfo);
}
static HRESULT WINAPI ProxyIDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
{
TMProxyImpl *This = (TMProxyImpl *)iface;
TRACE("(%d, %x, %p)\n", iTInfo, lcid, ppTInfo);
return IDispatch_GetTypeInfo(This->dispatch, iTInfo, lcid, ppTInfo);
}
static HRESULT WINAPI ProxyIDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
{
TMProxyImpl *This = (TMProxyImpl *)iface;
TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
return IDispatch_GetIDsOfNames(This->dispatch, riid, rgszNames,
cNames, lcid, rgDispId);
}
static HRESULT WINAPI ProxyIDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult,
EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
TMProxyImpl *This = (TMProxyImpl *)iface;
TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember,
debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
pExcepInfo, puArgErr);
return IDispatch_Invoke(This->dispatch, dispIdMember, riid, lcid,
wFlags, pDispParams, pVarResult, pExcepInfo,
puArgErr);
}
typedef struct
{
const IRpcChannelBufferVtbl *lpVtbl;
LONG refs;
/* the IDispatch-derived interface we are handling */
IID tmarshal_iid;
IRpcChannelBuffer *pDelegateChannel;
} TMarshalDispatchChannel;
static HRESULT WINAPI TMarshalDispatchChannel_QueryInterface(LPRPCCHANNELBUFFER iface, REFIID riid, LPVOID *ppv)
{
*ppv = NULL;
if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown))
{
*ppv = (LPVOID)iface;
IUnknown_AddRef(iface);
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI TMarshalDispatchChannel_AddRef(LPRPCCHANNELBUFFER iface)
{
TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
return InterlockedIncrement(&This->refs);
}
static ULONG WINAPI TMarshalDispatchChannel_Release(LPRPCCHANNELBUFFER iface)
{
TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
ULONG ref;
ref = InterlockedDecrement(&This->refs);
if (ref)
return ref;
IRpcChannelBuffer_Release(This->pDelegateChannel);
HeapFree(GetProcessHeap(), 0, This);
return 0;
}
static HRESULT WINAPI TMarshalDispatchChannel_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid)
{
TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
TRACE("(%p, %s)\n", olemsg, debugstr_guid(riid));
/* Note: we are pretending to invoke a method on the interface identified
* by tmarshal_iid so that we can re-use the IDispatch proxy/stub code
* without the RPC runtime getting confused by not exporting an IDispatch interface */
return IRpcChannelBuffer_GetBuffer(This->pDelegateChannel, olemsg, &This->tmarshal_iid);
}
static HRESULT WINAPI TMarshalDispatchChannel_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *olemsg, ULONG *pstatus)
{
TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
TRACE("(%p, %p)\n", olemsg, pstatus);
return IRpcChannelBuffer_SendReceive(This->pDelegateChannel, olemsg, pstatus);
}
static HRESULT WINAPI TMarshalDispatchChannel_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg)
{
TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
TRACE("(%p)\n", olemsg);
return IRpcChannelBuffer_FreeBuffer(This->pDelegateChannel, olemsg);
}
static HRESULT WINAPI TMarshalDispatchChannel_GetDestCtx(LPRPCCHANNELBUFFER iface, DWORD* pdwDestContext, void** ppvDestContext)
{
TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
TRACE("(%p,%p)\n", pdwDestContext, ppvDestContext);
return IRpcChannelBuffer_GetDestCtx(This->pDelegateChannel, pdwDestContext, ppvDestContext);
}
static HRESULT WINAPI TMarshalDispatchChannel_IsConnected(LPRPCCHANNELBUFFER iface)
{
TMarshalDispatchChannel *This = (TMarshalDispatchChannel *)iface;
TRACE("()\n");
return IRpcChannelBuffer_IsConnected(This->pDelegateChannel);
}
static const IRpcChannelBufferVtbl TMarshalDispatchChannelVtbl =
{
TMarshalDispatchChannel_QueryInterface,
TMarshalDispatchChannel_AddRef,
TMarshalDispatchChannel_Release,
TMarshalDispatchChannel_GetBuffer,
TMarshalDispatchChannel_SendReceive,
TMarshalDispatchChannel_FreeBuffer,
TMarshalDispatchChannel_GetDestCtx,
TMarshalDispatchChannel_IsConnected
};
static HRESULT TMarshalDispatchChannel_Create(
IRpcChannelBuffer *pDelegateChannel, REFIID tmarshal_riid,
IRpcChannelBuffer **ppChannel)
{
TMarshalDispatchChannel *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
if (!This)
return E_OUTOFMEMORY;
This->lpVtbl = &TMarshalDispatchChannelVtbl;
This->refs = 1;
IRpcChannelBuffer_AddRef(pDelegateChannel);
This->pDelegateChannel = pDelegateChannel;
This->tmarshal_iid = *tmarshal_riid;
*ppChannel = (IRpcChannelBuffer *)&This->lpVtbl;
return S_OK;
}
static inline HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf)
{
HRESULT hr;
CLSID clsid;
if ((hr = CoGetPSClsid(riid, &clsid)))
return hr;
return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
&IID_IPSFactoryBuffer, (LPVOID*)facbuf);
}
static HRESULT init_proxy_entry_point(TMProxyImpl *proxy, unsigned int num)
{
int j;
/* nrofargs without This */
int nrofargs;
ITypeInfo *tinfo2;
TMAsmProxy *xasm = proxy->asmstubs + num;
HRESULT hres;
const FUNCDESC *fdesc;
hres = get_funcdesc(proxy->tinfo, num, &tinfo2, &fdesc, NULL, NULL, NULL);
if (hres) {
ERR("GetFuncDesc %x should not fail here.\n",hres);
return hres;
}
ITypeInfo_Release(tinfo2);
/* some args take more than 4 byte on the stack */
nrofargs = 0;
for (j=0;j<fdesc->cParams;j++)
nrofargs += _argsize(fdesc->lprgelemdescParam[j].tdesc.vt);
#ifdef __i386__
if (fdesc->callconv != CC_STDCALL) {
ERR("calling convention is not stdcall????\n");
return E_FAIL;
}
/* popl %eax - return ptr
* pushl <nr>
* pushl %eax
* call xCall
* lret <nr> (+4)
*
*
* arg3 arg2 arg1 <method> <returnptr>
*/
xasm->popleax = 0x58;
xasm->pushlval = 0x6a;
xasm->nr = num;
xasm->pushleax = 0x50;
xasm->lcall = 0xe8; /* relative jump */
xasm->xcall = (DWORD)xCall;
xasm->xcall -= (DWORD)&(xasm->lret);
xasm->lret = 0xc2;
xasm->bytestopop = (nrofargs+2)*4; /* pop args, This, iMethod */
proxy->lpvtbl[num] = xasm;
#else
FIXME("not implemented on non i386\n");
return E_FAIL;
#endif
return S_OK;
}
static HRESULT WINAPI
PSFacBuf_CreateProxy(
LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
IRpcProxyBuffer **ppProxy, LPVOID *ppv)
{
HRESULT hres;
ITypeInfo *tinfo;
unsigned int i, nroffuncs;
TMProxyImpl *proxy;
TYPEATTR *typeattr;
BOOL defer_to_dispatch = FALSE;
TRACE("(...%s...)\n",debugstr_guid(riid));
hres = _get_typeinfo_for_iid(riid,&tinfo);
if (hres) {
ERR("No typeinfo for %s?\n",debugstr_guid(riid));
return hres;
}
hres = num_of_funcs(tinfo, &nroffuncs);
if (FAILED(hres)) {
ERR("Cannot get number of functions for typeinfo %s\n",debugstr_guid(riid));
ITypeInfo_Release(tinfo);
return hres;
}
proxy = CoTaskMemAlloc(sizeof(TMProxyImpl));
if (!proxy) return E_OUTOFMEMORY;
assert(sizeof(TMAsmProxy) == 12);
proxy->dispatch = NULL;
proxy->dispatch_proxy = NULL;
proxy->outerunknown = pUnkOuter;
proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!proxy->asmstubs) {
ERR("Could not commit pages for proxy thunks\n");
CoTaskMemFree(proxy);
return E_OUTOFMEMORY;
}
proxy->lpvtbl2 = &tmproxyvtable;
/* one reference for the proxy */
proxy->ref = 1;
proxy->tinfo = tinfo;
memcpy(&proxy->iid,riid,sizeof(*riid));
proxy->chanbuf = 0;
InitializeCriticalSection(&proxy->crit);
proxy->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TMProxyImpl.crit");
proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
/* if we derive from IDispatch then defer to its proxy for its methods */
hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
if (hres == S_OK)
{
if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
{
IPSFactoryBuffer *factory_buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -