📄 variant.c
字号:
case VT_DATE:
switch (vtFrom)
{
case VT_EMPTY: V_DATE(pd) = 0.0; return S_OK;
case VT_I1: return VarDateFromI1(V_I1(ps), &V_DATE(pd));
case VT_I2: return VarDateFromI2(V_I2(ps), &V_DATE(pd));
case VT_I4: return VarDateFromI4(V_I4(ps), &V_DATE(pd));
case VT_UI1: return VarDateFromUI1(V_UI1(ps), &V_DATE(pd));
case VT_UI2: return VarDateFromUI2(V_UI2(ps), &V_DATE(pd));
case VT_UI4: return VarDateFromUI4(V_UI4(ps), &V_DATE(pd));
case VT_I8: return VarDateFromI8(V_I8(ps), &V_DATE(pd));
case VT_UI8: return VarDateFromUI8(V_UI8(ps), &V_DATE(pd));
case VT_R4: return VarDateFromR4(V_R4(ps), &V_DATE(pd));
case VT_R8: return VarDateFromR8(V_R8(ps), &V_DATE(pd));
case VT_BOOL: return VarDateFromBool(V_BOOL(ps), &V_DATE(pd));
case VT_CY: return VarDateFromCy(V_CY(ps), &V_DATE(pd));
case VT_DECIMAL: return VarDateFromDec(&V_DECIMAL(ps), &V_DATE(pd));
case VT_DISPATCH: return VarDateFromDisp(V_DISPATCH(ps), lcid, &V_DATE(pd));
case VT_BSTR: return VarDateFromStr(V_BSTR(ps), lcid, dwFlags, &V_DATE(pd));
}
break;
case VT_BOOL:
switch (vtFrom)
{
case VT_EMPTY: V_BOOL(pd) = 0; return S_OK;
case VT_I1: return VarBoolFromI1(V_I1(ps), &V_BOOL(pd));
case VT_I2: return VarBoolFromI2(V_I2(ps), &V_BOOL(pd));
case VT_I4: return VarBoolFromI4(V_I4(ps), &V_BOOL(pd));
case VT_UI1: return VarBoolFromUI1(V_UI1(ps), &V_BOOL(pd));
case VT_UI2: return VarBoolFromUI2(V_UI2(ps), &V_BOOL(pd));
case VT_UI4: return VarBoolFromUI4(V_UI4(ps), &V_BOOL(pd));
case VT_I8: return VarBoolFromI8(V_I8(ps), &V_BOOL(pd));
case VT_UI8: return VarBoolFromUI8(V_UI8(ps), &V_BOOL(pd));
case VT_R4: return VarBoolFromR4(V_R4(ps), &V_BOOL(pd));
case VT_R8: return VarBoolFromR8(V_R8(ps), &V_BOOL(pd));
case VT_DATE: return VarBoolFromDate(V_DATE(ps), &V_BOOL(pd));
case VT_CY: return VarBoolFromCy(V_CY(ps), &V_BOOL(pd));
case VT_DECIMAL: return VarBoolFromDec(&V_DECIMAL(ps), &V_BOOL(pd));
case VT_DISPATCH: return VarBoolFromDisp(V_DISPATCH(ps), lcid, &V_BOOL(pd));
case VT_BSTR: return VarBoolFromStr(V_BSTR(ps), lcid, dwFlags, &V_BOOL(pd));
}
break;
case VT_BSTR:
switch (vtFrom)
{
case VT_EMPTY:
V_BSTR(pd) = SysAllocStringLen(NULL, 0);
return V_BSTR(pd) ? S_OK : E_OUTOFMEMORY;
case VT_BOOL:
if (wFlags & (VARIANT_ALPHABOOL|VARIANT_LOCALBOOL))
return VarBstrFromBool(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
return VarBstrFromI2(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_I1: return VarBstrFromI1(V_I1(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_I2: return VarBstrFromI2(V_I2(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_I4: return VarBstrFromI4(V_I4(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_UI1: return VarBstrFromUI1(V_UI1(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_UI2: return VarBstrFromUI2(V_UI2(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_UI4: return VarBstrFromUI4(V_UI4(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_I8: return VarBstrFromI8(V_I8(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_UI8: return VarBstrFromUI8(V_UI8(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_R4: return VarBstrFromR4(V_R4(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_R8: return VarBstrFromR8(V_R8(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_DATE: return VarBstrFromDate(V_DATE(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_CY: return VarBstrFromCy(V_CY(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_DECIMAL: return VarBstrFromDec(&V_DECIMAL(ps), lcid, dwFlags, &V_BSTR(pd));
case VT_DISPATCH: return VarBstrFromDisp(V_DISPATCH(ps), lcid, dwFlags, &V_BSTR(pd));
}
break;
case VT_CY:
switch (vtFrom)
{
case VT_EMPTY: V_CY(pd).int64 = 0; return S_OK;
case VT_I1: return VarCyFromI1(V_I1(ps), &V_CY(pd));
case VT_I2: return VarCyFromI2(V_I2(ps), &V_CY(pd));
case VT_I4: return VarCyFromI4(V_I4(ps), &V_CY(pd));
case VT_UI1: return VarCyFromUI1(V_UI1(ps), &V_CY(pd));
case VT_UI2: return VarCyFromUI2(V_UI2(ps), &V_CY(pd));
case VT_UI4: return VarCyFromUI4(V_UI4(ps), &V_CY(pd));
case VT_I8: return VarCyFromI8(V_I8(ps), &V_CY(pd));
case VT_UI8: return VarCyFromUI8(V_UI8(ps), &V_CY(pd));
case VT_R4: return VarCyFromR4(V_R4(ps), &V_CY(pd));
case VT_R8: return VarCyFromR8(V_R8(ps), &V_CY(pd));
case VT_DATE: return VarCyFromDate(V_DATE(ps), &V_CY(pd));
case VT_BOOL: return VarCyFromBool(V_BOOL(ps), &V_CY(pd));
case VT_DECIMAL: return VarCyFromDec(&V_DECIMAL(ps), &V_CY(pd));
case VT_DISPATCH: return VarCyFromDisp(V_DISPATCH(ps), lcid, &V_CY(pd));
case VT_BSTR: return VarCyFromStr(V_BSTR(ps), lcid, dwFlags, &V_CY(pd));
}
break;
case VT_DECIMAL:
switch (vtFrom)
{
case VT_EMPTY:
case VT_BOOL:
DEC_SIGNSCALE(&V_DECIMAL(pd)) = SIGNSCALE(DECIMAL_POS,0);
DEC_HI32(&V_DECIMAL(pd)) = 0;
DEC_MID32(&V_DECIMAL(pd)) = 0;
/* VarDecFromBool() coerces to -1/0, ChangeTypeEx() coerces to 1/0.
* VT_NULL and VT_EMPTY always give a 0 value.
*/
DEC_LO32(&V_DECIMAL(pd)) = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0;
return S_OK;
case VT_I1: return VarDecFromI1(V_I1(ps), &V_DECIMAL(pd));
case VT_I2: return VarDecFromI2(V_I2(ps), &V_DECIMAL(pd));
case VT_I4: return VarDecFromI4(V_I4(ps), &V_DECIMAL(pd));
case VT_UI1: return VarDecFromUI1(V_UI1(ps), &V_DECIMAL(pd));
case VT_UI2: return VarDecFromUI2(V_UI2(ps), &V_DECIMAL(pd));
case VT_UI4: return VarDecFromUI4(V_UI4(ps), &V_DECIMAL(pd));
case VT_I8: return VarDecFromI8(V_I8(ps), &V_DECIMAL(pd));
case VT_UI8: return VarDecFromUI8(V_UI8(ps), &V_DECIMAL(pd));
case VT_R4: return VarDecFromR4(V_R4(ps), &V_DECIMAL(pd));
case VT_R8: return VarDecFromR8(V_R8(ps), &V_DECIMAL(pd));
case VT_DATE: return VarDecFromDate(V_DATE(ps), &V_DECIMAL(pd));
case VT_CY: return VarDecFromCy(V_CY(ps), &V_DECIMAL(pd));
case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(pd));
case VT_BSTR: return VarDecFromStr(V_BSTR(ps), lcid, dwFlags, &V_DECIMAL(pd));
}
break;
case VT_UNKNOWN:
switch (vtFrom)
{
case VT_DISPATCH:
if (V_DISPATCH(ps) == NULL)
V_UNKNOWN(pd) = NULL;
else
res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd));
break;
}
break;
case VT_DISPATCH:
switch (vtFrom)
{
case VT_UNKNOWN:
if (V_UNKNOWN(ps) == NULL)
V_DISPATCH(pd) = NULL;
else
res = IUnknown_QueryInterface(V_UNKNOWN(ps), &IID_IDispatch, (LPVOID*)&V_DISPATCH(pd));
break;
}
break;
case VT_RECORD:
break;
}
return res;
}
/* Coerce to/from an array */
static inline HRESULT VARIANT_CoerceArray(VARIANTARG* pd, VARIANTARG* ps, VARTYPE vt)
{
if (vt == VT_BSTR && V_VT(ps) == (VT_ARRAY|VT_UI1))
return BstrFromVector(V_ARRAY(ps), &V_BSTR(pd));
if (V_VT(ps) == VT_BSTR && vt == (VT_ARRAY|VT_UI1))
return VectorFromBstr(V_BSTR(ps), &V_ARRAY(ps));
if (V_VT(ps) == vt)
return SafeArrayCopy(V_ARRAY(ps), &V_ARRAY(pd));
return DISP_E_TYPEMISMATCH;
}
/******************************************************************************
* Check if a variants type is valid.
*/
static inline HRESULT VARIANT_ValidateType(VARTYPE vt)
{
VARTYPE vtExtra = vt & VT_EXTRA_TYPE;
vt &= VT_TYPEMASK;
if (!(vtExtra & (VT_VECTOR|VT_RESERVED)))
{
if (vt < VT_VOID || vt == VT_RECORD || vt == VT_CLSID)
{
if ((vtExtra & (VT_BYREF|VT_ARRAY)) && vt <= VT_NULL)
return DISP_E_BADVARTYPE;
if (vt != (VARTYPE)15)
return S_OK;
}
}
return DISP_E_BADVARTYPE;
}
/******************************************************************************
* VariantInit [OLEAUT32.8]
*
* Initialise a variant.
*
* PARAMS
* pVarg [O] Variant to initialise
*
* RETURNS
* Nothing.
*
* NOTES
* This function simply sets the type of the variant to VT_EMPTY. It does not
* free any existing value, use VariantClear() for that.
*/
void WINAPI VariantInit(VARIANTARG* pVarg)
{
TRACE("(%p)\n", pVarg);
V_VT(pVarg) = VT_EMPTY; /* Native doesn't set any other fields */
}
/******************************************************************************
* VariantClear [OLEAUT32.9]
*
* Clear a variant.
*
* PARAMS
* pVarg [I/O] Variant to clear
*
* RETURNS
* Success: S_OK. Any previous value in pVarg is freed and its type is set to VT_EMPTY.
* Failure: DISP_E_BADVARTYPE, if the variant is a not a valid variant type.
*/
HRESULT WINAPI VariantClear(VARIANTARG* pVarg)
{
HRESULT hres = S_OK;
TRACE("(%p->(%s%s))\n", pVarg, debugstr_VT(pVarg), debugstr_VF(pVarg));
hres = VARIANT_ValidateType(V_VT(pVarg));
if (SUCCEEDED(hres))
{
if (!V_ISBYREF(pVarg))
{
if (V_ISARRAY(pVarg) || V_VT(pVarg) == VT_SAFEARRAY)
{
if (V_ARRAY(pVarg))
hres = SafeArrayDestroy(V_ARRAY(pVarg));
}
else if (V_VT(pVarg) == VT_BSTR)
{
if (V_BSTR(pVarg))
SysFreeString(V_BSTR(pVarg));
}
else if (V_VT(pVarg) == VT_RECORD)
{
struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal);
if (pBr->pRecInfo)
{
IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord);
IRecordInfo_Release(pBr->pRecInfo);
}
}
else if (V_VT(pVarg) == VT_DISPATCH ||
V_VT(pVarg) == VT_UNKNOWN)
{
if (V_UNKNOWN(pVarg))
IUnknown_Release(V_UNKNOWN(pVarg));
}
}
V_VT(pVarg) = VT_EMPTY;
}
return hres;
}
/******************************************************************************
* Copy an IRecordInfo object contained in a variant.
*/
static HRESULT VARIANT_CopyIRecordInfo(struct __tagBRECORD* pBr)
{
HRESULT hres = S_OK;
if (pBr->pRecInfo)
{
ULONG ulSize;
hres = IRecordInfo_GetSize(pBr->pRecInfo, &ulSize);
if (SUCCEEDED(hres))
{
PVOID pvRecord = HeapAlloc(GetProcessHeap(), 0, ulSize);
if (!pvRecord)
hres = E_OUTOFMEMORY;
else
{
memcpy(pvRecord, pBr->pvRecord, ulSize);
pBr->pvRecord = pvRecord;
hres = IRecordInfo_RecordCopy(pBr->pRecInfo, pvRecord, pvRecord);
if (SUCCEEDED(hres))
IRecordInfo_AddRef(pBr->pRecInfo);
}
}
}
else if (pBr->pvRecord)
hres = E_INVALIDARG;
return hres;
}
/******************************************************************************
* VariantCopy [OLEAUT32.10]
*
* Copy a variant.
*
* PARAMS
* pvargDest [O] Destination for copy
* pvargSrc [I] Source variant to copy
*
* RETURNS
* Success: S_OK. pvargDest contains a copy of pvargSrc.
* Failure: DISP_E_BADVARTYPE, if either variant has an invalid type.
* E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an
* HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(),
* or IRecordInfo_RecordCopy(), depending on the type of pvargSrc.
*
* NOTES
* - If pvargSrc == pvargDest, this function does nothing, and succeeds if
* pvargSrc is valid. Otherwise, pvargDest is always cleared using
* VariantClear() before pvargSrc is copied to it. If clearing pvargDest
* fails, so does this function.
* - VT_CLSID is a valid type type for pvargSrc, but not for pvargDest.
* - For by-value non-intrinsic types, a deep copy is made, i.e. The whole value
* is copied rather than just any pointers to it.
* - For by-value object types the object pointer is copied and the objects
* reference count increased using IUnknown_AddRef().
* - For all by-reference types, only the referencing pointer is copied.
*/
HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
{
HRESULT hres = S_OK;
TRACE("(%p->(%s%s),%p->(%s%s))\n", pvargDest, debugstr_VT(pvargDest),
debugstr_VF(pvargDest), pvargSrc, debugstr_VT(pvargSrc),
debugstr_VF(pvargSrc));
if (V_TYPE(pvargSrc) == VT_CLSID || /* VT_CLSID is a special case */
FAILED(VARIANT_ValidateType(V_VT(pvargSrc))))
return DISP_E_BADVARTYPE;
if (pvargSrc != pvargDest &&
SUCCEEDED(hres = VariantClear(pvargDest)))
{
*pvargDest = *pvargSrc; /* Shallow copy the value */
if (!V_ISBYREF(pvargSrc))
{
if (V_ISARRAY(pvargSrc))
{
if (V_ARRAY(pvargSrc))
hres = SafeArrayCopy(V_ARRAY(pvargSrc), &V_ARRAY(pvargDest));
}
else if (V_VT(pvargSrc) == VT_BSTR)
{
V_BSTR(pvargDest) = SysAllocStringByteLen((char*)V_BSTR(pvargSrc), SysStringByteLen(V_BSTR(pvargSrc)));
if (!V_BSTR(pvargDest))
{
TRACE("!V_BSTR(pvargDest), SysAllocStringByteLen() failed to allocate %d bytes\n", SysStringByteLen(V_BSTR(pvargSrc)));
hres = E_OUTOFMEMORY;
}
}
else if (V_VT(pvargSrc) == VT_RECORD)
{
hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
}
else if (V_VT(pvargSrc) == VT_DISPATCH ||
V_VT(pvargSrc) == VT_UNKNOWN)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -