⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tmarshal.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
            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 + -