📄 usrmarshal.c
字号:
{
if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
memcpy(Pos, pvar, type_size);
else
memcpy(Pos, &pvar->n1.n2.n3, type_size);
Pos += type_size;
}
if(header->vt & VT_ARRAY)
{
if(header->vt & VT_BYREF)
Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar));
else
Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar));
}
else
{
switch (header->vt)
{
case VT_BSTR:
Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
break;
case VT_BSTR | VT_BYREF:
Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
break;
case VT_VARIANT | VT_BYREF:
Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
break;
case VT_UNKNOWN:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar));
break;
case VT_UNKNOWN | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar));
break;
case VT_DISPATCH:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
break;
case VT_DISPATCH | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
break;
case VT_RECORD:
FIXME("handle BRECORD by val\n");
break;
case VT_RECORD | VT_BYREF:
FIXME("handle BRECORD by ref\n");
break;
}
}
header->clSize = ((Pos - Buffer) + 7) >> 3;
TRACE("marshalled size=%d\n", header->clSize);
return Pos;
}
unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar)
{
variant_wire_t *header;
ULONG type_size;
int align;
unsigned char *Pos;
TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar);
ALIGN_POINTER(Buffer, 7);
VariantClear(pvar);
header = (variant_wire_t *)Buffer;
pvar->n1.n2.vt = header->vt;
pvar->n1.n2.wReserved1 = header->wReserved1;
pvar->n1.n2.wReserved2 = header->wReserved2;
pvar->n1.n2.wReserved3 = header->wReserved3;
Pos = (unsigned char*)(header + 1);
type_size = get_type_size(pFlags, pvar);
align = get_type_alignment(pFlags, pvar);
ALIGN_POINTER(Pos, align);
if(header->vt & VT_BYREF)
{
Pos += 4;
pvar->n1.n2.n3.byref = CoTaskMemAlloc(type_size);
memcpy(pvar->n1.n2.n3.byref, Pos, type_size);
if((header->vt & VT_TYPEMASK) != VT_VARIANT)
Pos += type_size;
else
Pos += 4;
}
else
{
if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
memcpy(pvar, Pos, type_size);
else
memcpy(&pvar->n1.n2.n3, Pos, type_size);
Pos += type_size;
}
if(header->vt & VT_ARRAY)
{
if(header->vt & VT_BYREF)
Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar));
else
Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar));
}
else
{
switch (header->vt)
{
case VT_BSTR:
V_BSTR(pvar) = NULL;
Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
break;
case VT_BSTR | VT_BYREF:
*V_BSTRREF(pvar) = NULL;
Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
break;
case VT_VARIANT | VT_BYREF:
Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
break;
case VT_UNKNOWN:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar));
break;
case VT_UNKNOWN | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar));
break;
case VT_DISPATCH:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar));
break;
case VT_DISPATCH | VT_BYREF:
/* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar));
break;
case VT_RECORD:
FIXME("handle BRECORD by val\n");
break;
case VT_RECORD | VT_BYREF:
FIXME("handle BRECORD by ref\n");
break;
}
}
return Pos;
}
void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar)
{
VARTYPE vt = V_VT(pvar);
PVOID ref = NULL;
TRACE("(%x,%p)\n", *pFlags, pvar);
TRACE("vt=%04x\n", V_VT(pvar));
if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
VariantClear(pvar);
if (!ref) return;
if(vt & VT_ARRAY)
LPSAFEARRAY_UserFree(pFlags, V_ARRAYREF(pvar));
else
{
switch (vt)
{
case VT_BSTR | VT_BYREF:
BSTR_UserFree(pFlags, V_BSTRREF(pvar));
break;
case VT_VARIANT | VT_BYREF:
VARIANT_UserFree(pFlags, V_VARIANTREF(pvar));
break;
case VT_RECORD | VT_BYREF:
FIXME("handle BRECORD by ref\n");
break;
case VT_UNKNOWN | VT_BYREF:
case VT_DISPATCH | VT_BYREF:
IUnknown_Release(*V_UNKNOWNREF(pvar));
break;
}
}
CoTaskMemFree(ref);
}
/* LPSAFEARRAY */
/* Get the number of cells in a SafeArray */
static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
{
const SAFEARRAYBOUND* psab = psa->rgsabound;
USHORT cCount = psa->cDims;
ULONG ulNumCells = 1;
while (cCount--)
{
/* This is a valid bordercase. See testcases. -Marcus */
if (!psab->cElements)
return 0;
ulNumCells *= psab->cElements;
psab++;
}
return ulNumCells;
}
static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
{
VARTYPE vt;
HRESULT hr;
hr = SafeArrayGetVartype(psa, &vt);
if (FAILED(hr))
{
if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT;
switch(psa->cbElements)
{
case 1: vt = VT_I1; break;
case 2: vt = VT_I2; break;
case 4: vt = VT_I4; break;
case 8: vt = VT_I8; break;
default:
RpcRaiseException(hr);
}
}
if (psa->fFeatures & FADF_HAVEIID)
return SF_HAVEIID;
switch (vt)
{
case VT_I1:
case VT_UI1: return SF_I1;
case VT_BOOL:
case VT_I2:
case VT_UI2: return SF_I2;
case VT_INT:
case VT_UINT:
case VT_I4:
case VT_UI4:
case VT_R4: return SF_I4;
case VT_DATE:
case VT_CY:
case VT_R8:
case VT_I8:
case VT_UI8: return SF_I8;
case VT_INT_PTR:
case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8);
case VT_BSTR: return SF_BSTR;
case VT_DISPATCH: return SF_DISPATCH;
case VT_VARIANT: return SF_VARIANT;
case VT_UNKNOWN: return SF_UNKNOWN;
/* Note: Return a non-zero size to indicate vt is valid. The actual size
* of a UDT is taken from the result of IRecordInfo_GetSize().
*/
case VT_RECORD: return SF_RECORD;
default: return SF_ERROR;
}
}
ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa)
{
ULONG size = StartingSize;
TRACE("("); dump_user_flags(pFlags); TRACE(", %d, %p\n", StartingSize, *ppsa);
ALIGN_LENGTH(size, 3);
size += sizeof(ULONG_PTR);
if (*ppsa)
{
SAFEARRAY *psa = *ppsa;
ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
SF_TYPE sftype;
HRESULT hr;
size += sizeof(ULONG);
size += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
sftype = SAFEARRAY_GetUnionType(psa);
size += sizeof(ULONG);
size += sizeof(ULONG);
size += sizeof(ULONG_PTR);
if (sftype == SF_HAVEIID)
size += sizeof(IID);
size += sizeof(psa->rgsabound[0]) * psa->cDims;
size += sizeof(ULONG);
switch (sftype)
{
case SF_BSTR:
{
BSTR* lpBstr;
for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
size = BSTR_UserSize(pFlags, size, lpBstr);
break;
}
case SF_DISPATCH:
case SF_UNKNOWN:
case SF_HAVEIID:
FIXME("size interfaces\n");
break;
case SF_VARIANT:
{
VARIANT* lpVariant;
for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
size = VARIANT_UserSize(pFlags, size, lpVariant);
break;
}
case SF_RECORD:
{
IRecordInfo* pRecInfo = NULL;
hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
if (FAILED(hr))
RpcRaiseException(hr);
if (pRecInfo)
{
FIXME("size record info %p\n", pRecInfo);
IRecordInfo_Release(pRecInfo);
}
break;
}
case SF_I8:
ALIGN_LENGTH(size, 7);
/* fallthrough */
case SF_I1:
case SF_I2:
case SF_I4:
size += ulCellCount * psa->cbElements;
break;
default:
break;
}
}
return size;
}
unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
{
HRESULT hr;
TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa);
ALIGN_POINTER(Buffer, 3);
*(ULONG_PTR *)Buffer = *ppsa ? TRUE : FALSE;
Buffer += sizeof(ULONG_PTR);
if (*ppsa)
{
VARTYPE vt;
SAFEARRAY *psa = *ppsa;
ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
wireSAFEARRAY wiresa;
SF_TYPE sftype;
GUID guid;
*(ULONG *)Buffer = psa->cDims;
Buffer += sizeof(ULONG);
wiresa = (wireSAFEARRAY)Buffer;
wiresa->cDims = psa->cDims;
wiresa->fFeatures = psa->fFeatures;
wiresa->cbElements = psa->cbElements;
hr = SafeArrayGetVartype(psa, &vt);
if (FAILED(hr)) vt = 0;
wiresa->cLocks = (USHORT)psa->cLocks | (vt << 16);
Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs);
sftype = SAFEARRAY_GetUnionType(psa);
*(ULONG *)Buffer = sftype;
Buffer += sizeof(ULONG);
*(ULONG *)Buffer = ulCellCount;
Buffer += sizeof(ULONG);
*(ULONG_PTR *)Buffer = (ULONG_PTR)psa->pvData;
Buffer += sizeof(ULONG_PTR);
if (sftype == SF_HAVEIID)
{
SafeArrayGetIID(psa, &guid);
memcpy(Buffer, &guid, sizeof(guid));
Buffer += sizeof(guid);
}
memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims);
Buffer += sizeof(psa->rgsabound[0]) * psa->cDims;
*(ULONG *)Buffer = ulCellCount;
Buffer += sizeof(ULONG);
if (psa->pvData)
{
switch (sftype)
{
case SF_BSTR:
{
BSTR* lpBstr;
for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++)
Buffer = BSTR_UserMarshal(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*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++)
Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant);
break;
}
case SF_RECORD:
{
IRecordInfo* pRecInfo = NULL;
hr = SafeArrayGetRecordInfo(psa, &pRecInfo);
if (FAILED(hr))
RpcRaiseException(hr);
if (pRecInfo)
{
FIXME("write record info %p\n", pRecInfo);
IRecordInfo_Release(pRecInfo);
}
break;
}
case SF_I8:
ALIGN_POINTER(Buffer, 7);
/* fallthrough */
case SF_I1:
case SF_I2:
case SF_I4:
/* Just copy the data over */
memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements);
Buffer += ulCellCount * psa->cbElements;
break;
default:
break;
}
}
}
return Buffer;
}
#define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \
FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \
FADF_VARIANT | FADF_CREATEVECTOR)
unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa)
{
ULONG_PTR ptr;
wireSAFEARRAY wiresa;
ULONG cDims;
HRESULT hr;
SF_TYPE sftype;
ULONG cell_count;
GUID guid;
VARTYPE vt;
SAFEARRAYBOUND *wiresab;
TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa);
ALIGN_POINTER(Buffer, 3);
ptr = *(ULONG_PTR *)Buffer;
Buffer += sizeof(ULONG_PTR);
if (!ptr)
{
*ppsa = NULL;
TRACE("NULL safe array unmarshaled\n");
return Buffer;
}
cDims = *(ULONG *)Buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -