📄 tmarshal.c
字号:
hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
if (hres == S_OK)
{
hres = IPSFactoryBuffer_CreateProxy(factory_buffer, NULL,
&IID_IDispatch, &proxy->dispatch_proxy,
(void **)&proxy->dispatch);
IPSFactoryBuffer_Release(factory_buffer);
}
if ((hres == S_OK) && (nroffuncs < 7))
{
ERR("nroffuncs calculated incorrectly (%d)\n", nroffuncs);
hres = E_UNEXPECTED;
}
if (hres == S_OK)
{
defer_to_dispatch = TRUE;
}
}
ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
}
for (i=0;i<nroffuncs;i++) {
switch (i) {
case 0:
proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
break;
case 1:
proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
break;
case 2:
proxy->lpvtbl[i] = ProxyIUnknown_Release;
break;
case 3:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[3] = ProxyIDispatch_GetTypeInfoCount;
break;
case 4:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[4] = ProxyIDispatch_GetTypeInfo;
break;
case 5:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[5] = ProxyIDispatch_GetIDsOfNames;
break;
case 6:
if(!defer_to_dispatch)
{
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
else proxy->lpvtbl[6] = ProxyIDispatch_Invoke;
break;
default:
hres = init_proxy_entry_point(proxy, i);
if(FAILED(hres)) return hres;
}
}
if (hres == S_OK)
{
*ppv = (LPVOID)proxy;
*ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2);
IUnknown_AddRef((IUnknown *)*ppv);
return S_OK;
}
else
TMProxyImpl_Release((IRpcProxyBuffer *)&proxy->lpvtbl2);
return hres;
}
typedef struct _TMStubImpl {
const IRpcStubBufferVtbl *lpvtbl;
LONG ref;
LPUNKNOWN pUnk;
ITypeInfo *tinfo;
IID iid;
IRpcStubBuffer *dispatch_stub;
BOOL dispatch_derivative;
} TMStubImpl;
static HRESULT WINAPI
TMStubImpl_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv)
{
if (IsEqualIID(riid,&IID_IRpcStubBuffer)||IsEqualIID(riid,&IID_IUnknown)){
*ppv = (LPVOID)iface;
IRpcStubBuffer_AddRef(iface);
return S_OK;
}
FIXME("%s, not supported IID.\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI
TMStubImpl_AddRef(LPRPCSTUBBUFFER iface)
{
TMStubImpl *This = (TMStubImpl *)iface;
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before=%u)\n", This, refCount - 1);
return refCount;
}
static ULONG WINAPI
TMStubImpl_Release(LPRPCSTUBBUFFER iface)
{
TMStubImpl *This = (TMStubImpl *)iface;
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p)->(ref before=%u)\n", This, refCount + 1);
if (!refCount)
{
IRpcStubBuffer_Disconnect(iface);
ITypeInfo_Release(This->tinfo);
if (This->dispatch_stub)
IRpcStubBuffer_Release(This->dispatch_stub);
CoTaskMemFree(This);
}
return refCount;
}
static HRESULT WINAPI
TMStubImpl_Connect(LPRPCSTUBBUFFER iface, LPUNKNOWN pUnkServer)
{
TMStubImpl *This = (TMStubImpl *)iface;
TRACE("(%p)->(%p)\n", This, pUnkServer);
IUnknown_AddRef(pUnkServer);
This->pUnk = pUnkServer;
if (This->dispatch_stub)
IRpcStubBuffer_Connect(This->dispatch_stub, pUnkServer);
return S_OK;
}
static void WINAPI
TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
{
TMStubImpl *This = (TMStubImpl *)iface;
TRACE("(%p)->()\n", This);
if (This->pUnk)
{
IUnknown_Release(This->pUnk);
This->pUnk = NULL;
}
if (This->dispatch_stub)
IRpcStubBuffer_Disconnect(This->dispatch_stub);
}
static HRESULT WINAPI
TMStubImpl_Invoke(
LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf)
{
int i;
const FUNCDESC *fdesc;
TMStubImpl *This = (TMStubImpl *)iface;
HRESULT hres;
DWORD *args = NULL, res, *xargs, nrofargs;
marshal_state buf;
UINT nrofnames = 0;
BSTR names[10];
BSTR iname = NULL;
ITypeInfo *tinfo = NULL;
TRACE("...\n");
if (xmsg->iMethod < 3) {
ERR("IUnknown methods cannot be marshaled by the typelib marshaler\n");
return E_UNEXPECTED;
}
if (This->dispatch_derivative && xmsg->iMethod < sizeof(IDispatchVtbl)/sizeof(void *))
{
IPSFactoryBuffer *factory_buffer;
hres = get_facbuf_for_iid(&IID_IDispatch, &factory_buffer);
if (hres == S_OK)
{
hres = IPSFactoryBuffer_CreateStub(factory_buffer, &IID_IDispatch,
This->pUnk, &This->dispatch_stub);
IPSFactoryBuffer_Release(factory_buffer);
}
if (hres != S_OK)
return hres;
return IRpcStubBuffer_Invoke(This->dispatch_stub, xmsg, rpcchanbuf);
}
memset(&buf,0,sizeof(buf));
buf.size = xmsg->cbBuffer;
buf.base = HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer);
memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer);
buf.curoff = 0;
hres = get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,NULL,NULL);
if (hres) {
ERR("GetFuncDesc on method %d failed with %x\n",xmsg->iMethod,hres);
return hres;
}
if (iname && !lstrcmpW(iname, IDispatchW))
{
ERR("IDispatch cannot be marshaled by the typelib marshaler\n");
hres = E_UNEXPECTED;
SysFreeString (iname);
goto exit;
}
if (iname) SysFreeString (iname);
/* Need them for hack below */
memset(names,0,sizeof(names));
ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
if (nrofnames > sizeof(names)/sizeof(names[0])) {
ERR("Need more names!\n");
}
/*dump_FUNCDESC(fdesc);*/
nrofargs = 0;
for (i=0;i<fdesc->cParams;i++)
nrofargs += _argsize(fdesc->lprgelemdescParam[i].tdesc.vt);
args = HeapAlloc(GetProcessHeap(),0,(nrofargs+1)*sizeof(DWORD));
if (!args)
{
hres = E_OUTOFMEMORY;
goto exit;
}
/* Allocate all stuff used by call. */
xargs = args+1;
for (i=0;i<fdesc->cParams;i++) {
ELEMDESC *elem = fdesc->lprgelemdescParam+i;
hres = deserialize_param(
tinfo,
is_in_elem(elem),
FALSE,
TRUE,
&(elem->tdesc),
xargs,
&buf
);
xargs += _argsize(elem->tdesc.vt);
if (hres) {
ERR("Failed to deserialize param %s, hres %x\n",relaystr(names[i+1]),hres);
break;
}
}
args[0] = (DWORD)This->pUnk;
__TRY
{
res = _invoke(
(*((FARPROC**)args[0]))[fdesc->oVft/4],
fdesc->callconv,
(xargs-args),
args
);
}
__EXCEPT(NULL)
{
DWORD dwExceptionCode = GetExceptionCode();
ERR("invoke call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode);
if (FAILED(dwExceptionCode))
hres = dwExceptionCode;
else
hres = HRESULT_FROM_WIN32(dwExceptionCode);
}
__ENDTRY
if (hres != S_OK)
goto exit;
buf.curoff = 0;
xargs = args+1;
for (i=0;i<fdesc->cParams;i++) {
ELEMDESC *elem = fdesc->lprgelemdescParam+i;
hres = serialize_param(
tinfo,
is_out_elem(elem),
FALSE,
TRUE,
&elem->tdesc,
xargs,
&buf
);
xargs += _argsize(elem->tdesc.vt);
if (hres) {
ERR("Failed to stuballoc param, hres %x\n",hres);
break;
}
}
hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
if (hres != S_OK)
goto exit;
xmsg->cbBuffer = buf.curoff;
hres = IRpcChannelBuffer_GetBuffer(rpcchanbuf, xmsg, &This->iid);
if (hres != S_OK)
ERR("IRpcChannelBuffer_GetBuffer failed with error 0x%08x\n", hres);
if (hres == S_OK)
memcpy(xmsg->Buffer, buf.base, buf.curoff);
exit:
for (i = 0; i < nrofnames; i++)
SysFreeString(names[i]);
ITypeInfo_Release(tinfo);
HeapFree(GetProcessHeap(), 0, args);
HeapFree(GetProcessHeap(), 0, buf.base);
TRACE("returning\n");
return hres;
}
static LPRPCSTUBBUFFER WINAPI
TMStubImpl_IsIIDSupported(LPRPCSTUBBUFFER iface, REFIID riid) {
FIXME("Huh (%s)?\n",debugstr_guid(riid));
return NULL;
}
static ULONG WINAPI
TMStubImpl_CountRefs(LPRPCSTUBBUFFER iface) {
TMStubImpl *This = (TMStubImpl *)iface;
FIXME("()\n");
return This->ref; /*FIXME? */
}
static HRESULT WINAPI
TMStubImpl_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, LPVOID *ppv) {
return E_NOTIMPL;
}
static void WINAPI
TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
return;
}
static const IRpcStubBufferVtbl tmstubvtbl = {
TMStubImpl_QueryInterface,
TMStubImpl_AddRef,
TMStubImpl_Release,
TMStubImpl_Connect,
TMStubImpl_Disconnect,
TMStubImpl_Invoke,
TMStubImpl_IsIIDSupported,
TMStubImpl_CountRefs,
TMStubImpl_DebugServerQueryInterface,
TMStubImpl_DebugServerRelease
};
static HRESULT WINAPI
PSFacBuf_CreateStub(
LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
IRpcStubBuffer** ppStub
) {
HRESULT hres;
ITypeInfo *tinfo;
TMStubImpl *stub;
TYPEATTR *typeattr;
TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
hres = _get_typeinfo_for_iid(riid,&tinfo);
if (hres) {
ERR("No typeinfo for %s?\n",debugstr_guid(riid));
return hres;
}
stub = CoTaskMemAlloc(sizeof(TMStubImpl));
if (!stub)
return E_OUTOFMEMORY;
stub->lpvtbl = &tmstubvtbl;
stub->ref = 1;
stub->tinfo = tinfo;
stub->dispatch_stub = NULL;
stub->dispatch_derivative = FALSE;
memcpy(&(stub->iid),riid,sizeof(*riid));
hres = IRpcStubBuffer_Connect((LPRPCSTUBBUFFER)stub,pUnkServer);
*ppStub = (LPRPCSTUBBUFFER)stub;
TRACE("IRpcStubBuffer: %p\n", stub);
if (hres)
ERR("Connect to pUnkServer failed?\n");
/* if we derive from IDispatch then defer to its stub for some of its methods */
hres = ITypeInfo_GetTypeAttr(tinfo, &typeattr);
if (hres == S_OK)
{
if (typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
stub->dispatch_derivative = TRUE;
ITypeInfo_ReleaseTypeAttr(tinfo, typeattr);
}
return hres;
}
static const IPSFactoryBufferVtbl psfacbufvtbl = {
PSFacBuf_QueryInterface,
PSFacBuf_AddRef,
PSFacBuf_Release,
PSFacBuf_CreateProxy,
PSFacBuf_CreateStub
};
/* This is the whole PSFactoryBuffer object, just the vtableptr */
static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
/***********************************************************************
* TMARSHAL_DllGetClassObject
*/
HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
{
if (IsEqualIID(iid,&IID_IPSFactoryBuffer)) {
*ppv = &lppsfac;
return S_OK;
}
return E_NOINTERFACE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -