📄 usrmarshal.c
字号:
Buffer += sizeof(ULONG);
wiresa = (wireSAFEARRAY)Buffer;
Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
if (cDims != wiresa->cDims)
RpcRaiseException(RPC_S_INVALID_BOUND);
/* FIXME: there should be a limit on how large cDims can be */
vt = HIWORD(wiresa->cLocks);
sftype = *(ULONG *)Buffer;
Buffer += sizeof(ULONG);
cell_count = *(ULONG *)Buffer;
Buffer += sizeof(ULONG);
ptr = *(ULONG_PTR *)Buffer;
Buffer += sizeof(ULONG_PTR);
if (sftype == SF_HAVEIID)
{
memcpy(&guid, Buffer, sizeof(guid));
Buffer += sizeof(guid);
}
wiresab = (SAFEARRAYBOUND *)Buffer;
Buffer += sizeof(wiresab[0]) * wiresa->cDims;
if(vt)
*ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL);
else
{
SafeArrayAllocDescriptor(wiresa->cDims, ppsa);
if(*ppsa)
memcpy((*ppsa)->rgsabound, wiresab, sizeof(SAFEARRAYBOUND) * wiresa->cDims);
}
if (!*ppsa)
RpcRaiseException(E_OUTOFMEMORY);
/* be careful about which flags we set since they could be a security
* risk */
(*ppsa)->fFeatures &= FADF_AUTOSETFLAGS;
(*ppsa)->fFeatures |= (wiresa->fFeatures & ~(FADF_AUTOSETFLAGS));
/* FIXME: there should be a limit on how large wiresa->cbElements can be */
(*ppsa)->cbElements = wiresa->cbElements;
(*ppsa)->cLocks = LOWORD(wiresa->cLocks);
hr = SafeArrayAllocData(*ppsa);
if (FAILED(hr))
RpcRaiseException(hr);
if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count))
RpcRaiseException(RPC_S_INVALID_BOUND);
Buffer += sizeof(ULONG);
if (ptr)
{
switch (sftype)
{
case SF_BSTR:
{
BSTR* lpBstr;
for (lpBstr = (BSTR*)(*ppsa)->pvData; cell_count; cell_count--, lpBstr++)
Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr);
break;
}
case SF_DISPATCH:
case SF_UNKNOWN:
case SF_HAVEIID:
FIXME("marshal interfaces\n");
break;
case SF_VARIANT:
{
VARIANT* lpVariant;
for (lpVariant = (VARIANT*)(*ppsa)->pvData; cell_count; cell_count--, lpVariant++)
Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant);
break;
}
case SF_RECORD:
{
FIXME("set record info\n");
break;
}
case SF_I8:
ALIGN_POINTER(Buffer, 7);
/* fallthrough */
case SF_I1:
case SF_I2:
case SF_I4:
/* Just copy the data over */
memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements);
Buffer += cell_count * (*ppsa)->cbElements;
break;
default:
break;
}
}
TRACE("safe array unmarshaled: %p\n", *ppsa);
return Buffer;
}
void WINAPI LPSAFEARRAY_UserFree(ULONG *pFlags, LPSAFEARRAY *ppsa)
{
TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa);
SafeArrayDestroy(*ppsa);
}
/* IDispatch */
/* exactly how Invoke is marshalled is not very clear to me yet,
* but the way I've done it seems to work for me */
HRESULT CALLBACK IDispatch_Invoke_Proxy(
IDispatch* This,
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS* pDispParams,
VARIANT* pVarResult,
EXCEPINFO* pExcepInfo,
UINT* puArgErr)
{
HRESULT hr;
VARIANT VarResult;
UINT* rgVarRefIdx = NULL;
VARIANTARG* rgVarRef = NULL;
UINT u, cVarRef;
UINT uArgErr;
EXCEPINFO ExcepInfo;
TRACE("(%p)->(%d,%s,%x,%x,%p,%p,%p,%p)\n", This,
dispIdMember, debugstr_guid(riid),
lcid, wFlags, pDispParams, pVarResult,
pExcepInfo, puArgErr);
/* [out] args can't be null, use dummy vars if needed */
if (!pVarResult) pVarResult = &VarResult;
if (!puArgErr) puArgErr = &uArgErr;
if (!pExcepInfo) pExcepInfo = &ExcepInfo;
/* count by-ref args */
for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
VARIANTARG* arg = &pDispParams->rgvarg[u];
if (V_ISBYREF(arg)) {
cVarRef++;
}
}
if (cVarRef) {
rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
/* make list of by-ref args */
for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
VARIANTARG* arg = &pDispParams->rgvarg[u];
if (V_ISBYREF(arg)) {
rgVarRefIdx[cVarRef] = u;
VariantInit(&rgVarRef[cVarRef]);
cVarRef++;
}
}
} else {
/* [out] args still can't be null,
* but we can point these anywhere in this case,
* since they won't be written to when cVarRef is 0 */
rgVarRefIdx = puArgErr;
rgVarRef = pVarResult;
}
TRACE("passed by ref: %d args\n", cVarRef);
hr = IDispatch_RemoteInvoke_Proxy(This,
dispIdMember,
riid,
lcid,
wFlags,
pDispParams,
pVarResult,
pExcepInfo,
puArgErr,
cVarRef,
rgVarRefIdx,
rgVarRef);
if (cVarRef) {
for (u=0; u<cVarRef; u++) {
unsigned i = rgVarRefIdx[u];
VariantCopy(&pDispParams->rgvarg[i],
&rgVarRef[u]);
VariantClear(&rgVarRef[u]);
}
CoTaskMemFree(rgVarRef);
CoTaskMemFree(rgVarRefIdx);
}
if(pExcepInfo == &ExcepInfo)
{
SysFreeString(pExcepInfo->bstrSource);
SysFreeString(pExcepInfo->bstrDescription);
SysFreeString(pExcepInfo->bstrHelpFile);
}
return hr;
}
HRESULT __RPC_STUB IDispatch_Invoke_Stub(
IDispatch* This,
DISPID dispIdMember,
REFIID riid,
LCID lcid,
DWORD dwFlags,
DISPPARAMS* pDispParams,
VARIANT* pVarResult,
EXCEPINFO* pExcepInfo,
UINT* pArgErr,
UINT cVarRef,
UINT* rgVarRefIdx,
VARIANTARG* rgVarRef)
{
HRESULT hr = S_OK;
VARIANTARG *rgvarg, *arg;
UINT u;
/* initialize out parameters, so that they can be marshalled
* in case the real Invoke doesn't initialize them */
VariantInit(pVarResult);
memset(pExcepInfo, 0, sizeof(*pExcepInfo));
*pArgErr = 0;
/* let the real Invoke operate on a copy of the in parameters,
* so we don't risk losing pointers to allocated memory */
rgvarg = pDispParams->rgvarg;
arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
if (!arg) return E_OUTOFMEMORY;
/* init all args so we can call VariantClear on all the args if the copy
* below fails */
for (u = 0; u < pDispParams->cArgs; u++)
VariantInit(&arg[u]);
for (u = 0; u < pDispParams->cArgs; u++) {
hr = VariantCopy(&arg[u], &rgvarg[u]);
if (FAILED(hr))
break;
}
if (SUCCEEDED(hr)) {
pDispParams->rgvarg = arg;
hr = IDispatch_Invoke(This,
dispIdMember,
riid,
lcid,
dwFlags,
pDispParams,
pVarResult,
pExcepInfo,
pArgErr);
/* copy ref args to out list */
for (u=0; u<cVarRef; u++) {
unsigned i = rgVarRefIdx[u];
VariantInit(&rgVarRef[u]);
VariantCopy(&rgVarRef[u], &arg[i]);
/* clear original if equal, to avoid double-free */
if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
VariantClear(&rgvarg[i]);
}
}
/* clear the duplicate argument list */
for (u=0; u<pDispParams->cArgs; u++)
VariantClear(&arg[u]);
pDispParams->rgvarg = rgvarg;
CoTaskMemFree(arg);
return hr;
}
/* IEnumVARIANT */
HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
IEnumVARIANT* This,
ULONG celt,
VARIANT* rgVar,
ULONG* pCeltFetched)
{
ULONG fetched;
if (!pCeltFetched)
pCeltFetched = &fetched;
return IEnumVARIANT_RemoteNext_Proxy(This,
celt,
rgVar,
pCeltFetched);
}
HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
IEnumVARIANT* This,
ULONG celt,
VARIANT* rgVar,
ULONG* pCeltFetched)
{
HRESULT hr;
*pCeltFetched = 0;
hr = IEnumVARIANT_Next(This,
celt,
rgVar,
pCeltFetched);
if (hr == S_OK) *pCeltFetched = celt;
return hr;
}
/* TypeInfo related freers */
static void free_embedded_typedesc(TYPEDESC *tdesc);
static void free_embedded_arraydesc(ARRAYDESC *adesc)
{
switch(adesc->tdescElem.vt)
{
case VT_PTR:
case VT_SAFEARRAY:
free_embedded_typedesc(adesc->tdescElem.u.lptdesc);
CoTaskMemFree(adesc->tdescElem.u.lptdesc);
break;
case VT_CARRAY:
free_embedded_arraydesc(adesc->tdescElem.u.lpadesc);
CoTaskMemFree(adesc->tdescElem.u.lpadesc);
break;
}
}
static void free_embedded_typedesc(TYPEDESC *tdesc)
{
switch(tdesc->vt)
{
case VT_PTR:
case VT_SAFEARRAY:
free_embedded_typedesc(tdesc->u.lptdesc);
CoTaskMemFree(tdesc->u.lptdesc);
break;
case VT_CARRAY:
free_embedded_arraydesc(tdesc->u.lpadesc);
CoTaskMemFree(tdesc->u.lpadesc);
break;
}
}
static void free_embedded_elemdesc(ELEMDESC *edesc)
{
free_embedded_typedesc(&edesc->tdesc);
if(edesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
CoTaskMemFree(edesc->u.paramdesc.pparamdescex);
}
/* ITypeComp */
HRESULT CALLBACK ITypeComp_Bind_Proxy(
ITypeComp* This,
LPOLESTR szName,
ULONG lHashVal,
WORD wFlags,
ITypeInfo** ppTInfo,
DESCKIND* pDescKind,
BINDPTR* pBindPtr)
{
FIXME("not implemented\n");
return E_FAIL;
}
HRESULT __RPC_STUB ITypeComp_Bind_Stub(
ITypeComp* This,
LPOLESTR szName,
ULONG lHashVal,
WORD wFlags,
ITypeInfo** ppTInfo,
DESCKIND* pDescKind,
LPFUNCDESC* ppFuncDesc,
LPVARDESC* ppVarDesc,
ITypeComp** ppTypeComp,
CLEANLOCALSTORAGE* pDummy)
{
FIXME("not implemented\n");
return E_FAIL;
}
HRESULT CALLBACK ITypeComp_BindType_Proxy(
ITypeComp* This,
LPOLESTR szName,
ULONG lHashVal,
ITypeInfo** ppTInfo,
ITypeComp** ppTComp)
{
FIXME("not implemented\n");
return E_FAIL;
}
HRESULT __RPC_STUB ITypeComp_BindType_Stub(
ITypeComp* This,
LPOLESTR szName,
ULONG lHashVal,
ITypeInfo** ppTInfo)
{
FIXME("not implemented\n");
return E_FAIL;
}
/* ITypeInfo */
HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
ITypeInfo* This,
TYPEATTR** ppTypeAttr)
{
CLEANLOCALSTORAGE stg;
TRACE("(%p, %p)\n", This, ppTypeAttr);
stg.flags = 0;
stg.pStorage = NULL;
stg.pInterface = NULL;
return ITypeInfo_RemoteGetTypeAttr_Proxy(This, ppTypeAttr, &stg);
}
HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
ITypeInfo* This,
LPTYPEATTR* ppTypeAttr,
CLEANLOCALSTORAGE* pDummy)
{
HRESULT hr;
TRACE("(%p, %p)\n", This, ppTypeAttr);
hr = ITypeInfo_GetTypeAttr(This, ppTypeAttr);
if(hr != S_OK)
return hr;
pDummy->flags = CLS_TYPEATTR;
ITypeInfo_AddRef(This);
pDummy->pInterface = (IUnknown*)This;
pDummy->pStorage = ppTypeAttr;
return hr;
}
HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
ITypeInfo* This,
UINT index,
FUNCDESC** ppFuncDesc)
{
CLEANLOCALSTORAGE stg;
TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
stg.flags = 0;
stg.pStorage = NULL;
stg.pInterface = NULL;
return ITypeInfo_RemoteGetFuncDesc_Proxy(This, index, ppFuncDesc, &stg);
}
HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
ITypeInfo* This,
UINT index,
LPFUNCDESC* ppFuncDesc,
CLEANLOCALSTORAGE* pDummy)
{
HRESULT hr;
TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc);
hr = ITypeInfo_GetFuncDesc(This, index, ppFuncDesc);
if(hr != S_OK)
return hr;
pDummy->flags = CLS_FUNCDESC;
ITypeInfo_AddRef(This);
pDummy->pInterface = (IUnknown*)This;
pDummy->pStorage = ppFuncDesc;
return hr;
}
HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
ITypeInfo* This,
UINT index,
VARDESC** ppVarDesc)
{
CLEANLOCALSTORAGE stg;
TRACE("(%p, %d, %p)\n", This, index, ppVarDesc);
stg.flags = 0;
stg.pStorage = NULL;
stg.pInterface = NULL;
return ITypeInfo_RemoteGetVarDesc_Proxy(This, index, ppVarDesc, &stg);
}
HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
ITypeInfo* This,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -