📄 variant.c
字号:
/*
* VARIANT
*
* Copyright 1998 Jean-Claude Cote
* Copyright 2003 Jon Griffiths
* Copyright 2005 Daniel Remenak
* Copyright 2006 Google (Benjamin Arai)
*
* The alorithm for conversion from Julian days to day/month/year is based on
* that devised by Henry Fliegel, as implemented in PostgreSQL, which is
* Copyright 1994-7 Regents of the University of California
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "wine/unicode.h"
#include "winerror.h"
#include "variant.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(variant);
const char * const wine_vtypes[VT_CLSID+1] =
{
"VT_EMPTY","VT_NULL","VT_I2","VT_I4","VT_R4","VT_R8","VT_CY","VT_DATE",
"VT_BSTR","VT_DISPATCH","VT_ERROR","VT_BOOL","VT_VARIANT","VT_UNKNOWN",
"VT_DECIMAL","15","VT_I1","VT_UI1","VT_UI2","VT_UI4","VT_I8","VT_UI8",
"VT_INT","VT_UINT","VT_VOID","VT_HRESULT","VT_PTR","VT_SAFEARRAY",
"VT_CARRAY","VT_USERDEFINED","VT_LPSTR","VT_LPWSTR","32","33","34","35",
"VT_RECORD","VT_INT_PTR","VT_UINT_PTR","39","40","41","42","43","44","45",
"46","47","48","49","50","51","52","53","54","55","56","57","58","59","60",
"61","62","63","VT_FILETIME","VT_BLOB","VT_STREAM","VT_STORAGE",
"VT_STREAMED_OBJECT","VT_STORED_OBJECT","VT_BLOB_OBJECT","VT_CF","VT_CLSID"
};
const char * const wine_vflags[16] =
{
"",
"|VT_VECTOR",
"|VT_ARRAY",
"|VT_VECTOR|VT_ARRAY",
"|VT_BYREF",
"|VT_VECTOR|VT_ARRAY",
"|VT_ARRAY|VT_BYREF",
"|VT_VECTOR|VT_ARRAY|VT_BYREF",
"|VT_HARDTYPE",
"|VT_VECTOR|VT_HARDTYPE",
"|VT_ARRAY|VT_HARDTYPE",
"|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
"|VT_BYREF|VT_HARDTYPE",
"|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
"|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
"|VT_VECTOR|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
};
/* Convert a variant from one type to another */
static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
VARIANTARG* ps, VARTYPE vt)
{
HRESULT res = DISP_E_TYPEMISMATCH;
VARTYPE vtFrom = V_TYPE(ps);
DWORD dwFlags = 0;
TRACE("(%p->(%s%s),0x%08x,0x%04x,%p->(%s%s),%s%s)\n", pd, debugstr_VT(pd),
debugstr_VF(pd), lcid, wFlags, ps, debugstr_VT(ps), debugstr_VF(ps),
debugstr_vt(vt), debugstr_vf(vt));
if (vt == VT_BSTR || vtFrom == VT_BSTR)
{
/* All flags passed to low level function are only used for
* changing to or from strings. Map these here.
*/
if (wFlags & VARIANT_LOCALBOOL)
dwFlags |= VAR_LOCALBOOL;
if (wFlags & VARIANT_CALENDAR_HIJRI)
dwFlags |= VAR_CALENDAR_HIJRI;
if (wFlags & VARIANT_CALENDAR_THAI)
dwFlags |= VAR_CALENDAR_THAI;
if (wFlags & VARIANT_CALENDAR_GREGORIAN)
dwFlags |= VAR_CALENDAR_GREGORIAN;
if (wFlags & VARIANT_NOUSEROVERRIDE)
dwFlags |= LOCALE_NOUSEROVERRIDE;
if (wFlags & VARIANT_USE_NLS)
dwFlags |= LOCALE_USE_NLS;
}
/* Map int/uint to i4/ui4 */
if (vt == VT_INT)
vt = VT_I4;
else if (vt == VT_UINT)
vt = VT_UI4;
if (vtFrom == VT_INT)
vtFrom = VT_I4;
else if (vtFrom == VT_UINT)
vtFrom = VT_UI4;
if (vt == vtFrom)
return VariantCopy(pd, ps);
if (wFlags & VARIANT_NOVALUEPROP && vtFrom == VT_DISPATCH && vt != VT_UNKNOWN)
{
/* VARIANT_NOVALUEPROP prevents IDispatch objects from being coerced by
* accessing the default object property.
*/
return DISP_E_TYPEMISMATCH;
}
switch (vt)
{
case VT_EMPTY:
if (vtFrom == VT_NULL)
return DISP_E_TYPEMISMATCH;
/* ... Fall through */
case VT_NULL:
if (vtFrom <= VT_UINT && vtFrom != (VARTYPE)15 && vtFrom != VT_ERROR)
{
res = VariantClear( pd );
if (vt == VT_NULL && SUCCEEDED(res))
V_VT(pd) = VT_NULL;
}
return res;
case VT_I1:
switch (vtFrom)
{
case VT_EMPTY: V_I1(pd) = 0; return S_OK;
case VT_I2: return VarI1FromI2(V_I2(ps), &V_I1(pd));
case VT_I4: return VarI1FromI4(V_I4(ps), &V_I1(pd));
case VT_UI1: V_I1(pd) = V_UI1(ps); return S_OK;
case VT_UI2: return VarI1FromUI2(V_UI2(ps), &V_I1(pd));
case VT_UI4: return VarI1FromUI4(V_UI4(ps), &V_I1(pd));
case VT_I8: return VarI1FromI8(V_I8(ps), &V_I1(pd));
case VT_UI8: return VarI1FromUI8(V_UI8(ps), &V_I1(pd));
case VT_R4: return VarI1FromR4(V_R4(ps), &V_I1(pd));
case VT_R8: return VarI1FromR8(V_R8(ps), &V_I1(pd));
case VT_DATE: return VarI1FromDate(V_DATE(ps), &V_I1(pd));
case VT_BOOL: return VarI1FromBool(V_BOOL(ps), &V_I1(pd));
case VT_CY: return VarI1FromCy(V_CY(ps), &V_I1(pd));
case VT_DECIMAL: return VarI1FromDec(&V_DECIMAL(ps), &V_I1(pd) );
case VT_DISPATCH: return VarI1FromDisp(V_DISPATCH(ps), lcid, &V_I1(pd) );
case VT_BSTR: return VarI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_I1(pd) );
}
break;
case VT_I2:
switch (vtFrom)
{
case VT_EMPTY: V_I2(pd) = 0; return S_OK;
case VT_I1: return VarI2FromI1(V_I1(ps), &V_I2(pd));
case VT_I4: return VarI2FromI4(V_I4(ps), &V_I2(pd));
case VT_UI1: return VarI2FromUI1(V_UI1(ps), &V_I2(pd));
case VT_UI2: V_I2(pd) = V_UI2(ps); return S_OK;
case VT_UI4: return VarI2FromUI4(V_UI4(ps), &V_I2(pd));
case VT_I8: return VarI2FromI8(V_I8(ps), &V_I2(pd));
case VT_UI8: return VarI2FromUI8(V_UI8(ps), &V_I2(pd));
case VT_R4: return VarI2FromR4(V_R4(ps), &V_I2(pd));
case VT_R8: return VarI2FromR8(V_R8(ps), &V_I2(pd));
case VT_DATE: return VarI2FromDate(V_DATE(ps), &V_I2(pd));
case VT_BOOL: return VarI2FromBool(V_BOOL(ps), &V_I2(pd));
case VT_CY: return VarI2FromCy(V_CY(ps), &V_I2(pd));
case VT_DECIMAL: return VarI2FromDec(&V_DECIMAL(ps), &V_I2(pd));
case VT_DISPATCH: return VarI2FromDisp(V_DISPATCH(ps), lcid, &V_I2(pd));
case VT_BSTR: return VarI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_I2(pd));
}
break;
case VT_I4:
switch (vtFrom)
{
case VT_EMPTY: V_I4(pd) = 0; return S_OK;
case VT_I1: return VarI4FromI1(V_I1(ps), &V_I4(pd));
case VT_I2: return VarI4FromI2(V_I2(ps), &V_I4(pd));
case VT_UI1: return VarI4FromUI1(V_UI1(ps), &V_I4(pd));
case VT_UI2: return VarI4FromUI2(V_UI2(ps), &V_I4(pd));
case VT_UI4: V_I4(pd) = V_UI4(ps); return S_OK;
case VT_I8: return VarI4FromI8(V_I8(ps), &V_I4(pd));
case VT_UI8: return VarI4FromUI8(V_UI8(ps), &V_I4(pd));
case VT_R4: return VarI4FromR4(V_R4(ps), &V_I4(pd));
case VT_R8: return VarI4FromR8(V_R8(ps), &V_I4(pd));
case VT_DATE: return VarI4FromDate(V_DATE(ps), &V_I4(pd));
case VT_BOOL: return VarI4FromBool(V_BOOL(ps), &V_I4(pd));
case VT_CY: return VarI4FromCy(V_CY(ps), &V_I4(pd));
case VT_DECIMAL: return VarI4FromDec(&V_DECIMAL(ps), &V_I4(pd));
case VT_DISPATCH: return VarI4FromDisp(V_DISPATCH(ps), lcid, &V_I4(pd));
case VT_BSTR: return VarI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_I4(pd));
}
break;
case VT_UI1:
switch (vtFrom)
{
case VT_EMPTY: V_UI1(pd) = 0; return S_OK;
case VT_I1: V_UI1(pd) = V_I1(ps); return S_OK;
case VT_I2: return VarUI1FromI2(V_I2(ps), &V_UI1(pd));
case VT_I4: return VarUI1FromI4(V_I4(ps), &V_UI1(pd));
case VT_UI2: return VarUI1FromUI2(V_UI2(ps), &V_UI1(pd));
case VT_UI4: return VarUI1FromUI4(V_UI4(ps), &V_UI1(pd));
case VT_I8: return VarUI1FromI8(V_I8(ps), &V_UI1(pd));
case VT_UI8: return VarUI1FromUI8(V_UI8(ps), &V_UI1(pd));
case VT_R4: return VarUI1FromR4(V_R4(ps), &V_UI1(pd));
case VT_R8: return VarUI1FromR8(V_R8(ps), &V_UI1(pd));
case VT_DATE: return VarUI1FromDate(V_DATE(ps), &V_UI1(pd));
case VT_BOOL: return VarUI1FromBool(V_BOOL(ps), &V_UI1(pd));
case VT_CY: return VarUI1FromCy(V_CY(ps), &V_UI1(pd));
case VT_DECIMAL: return VarUI1FromDec(&V_DECIMAL(ps), &V_UI1(pd));
case VT_DISPATCH: return VarUI1FromDisp(V_DISPATCH(ps), lcid, &V_UI1(pd));
case VT_BSTR: return VarUI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI1(pd));
}
break;
case VT_UI2:
switch (vtFrom)
{
case VT_EMPTY: V_UI2(pd) = 0; return S_OK;
case VT_I1: return VarUI2FromI1(V_I1(ps), &V_UI2(pd));
case VT_I2: V_UI2(pd) = V_I2(ps); return S_OK;
case VT_I4: return VarUI2FromI4(V_I4(ps), &V_UI2(pd));
case VT_UI1: return VarUI2FromUI1(V_UI1(ps), &V_UI2(pd));
case VT_UI4: return VarUI2FromUI4(V_UI4(ps), &V_UI2(pd));
case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
case VT_R4: return VarUI2FromR4(V_R4(ps), &V_UI2(pd));
case VT_R8: return VarUI2FromR8(V_R8(ps), &V_UI2(pd));
case VT_DATE: return VarUI2FromDate(V_DATE(ps), &V_UI2(pd));
case VT_BOOL: return VarUI2FromBool(V_BOOL(ps), &V_UI2(pd));
case VT_CY: return VarUI2FromCy(V_CY(ps), &V_UI2(pd));
case VT_DECIMAL: return VarUI2FromDec(&V_DECIMAL(ps), &V_UI2(pd));
case VT_DISPATCH: return VarUI2FromDisp(V_DISPATCH(ps), lcid, &V_UI2(pd));
case VT_BSTR: return VarUI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI2(pd));
}
break;
case VT_UI4:
switch (vtFrom)
{
case VT_EMPTY: V_UI4(pd) = 0; return S_OK;
case VT_I1: return VarUI4FromI1(V_I1(ps), &V_UI4(pd));
case VT_I2: return VarUI4FromI2(V_I2(ps), &V_UI4(pd));
case VT_I4: V_UI4(pd) = V_I4(ps); return S_OK;
case VT_UI1: return VarUI4FromUI1(V_UI1(ps), &V_UI4(pd));
case VT_UI2: return VarUI4FromUI2(V_UI2(ps), &V_UI4(pd));
case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
case VT_R4: return VarUI4FromR4(V_R4(ps), &V_UI4(pd));
case VT_R8: return VarUI4FromR8(V_R8(ps), &V_UI4(pd));
case VT_DATE: return VarUI4FromDate(V_DATE(ps), &V_UI4(pd));
case VT_BOOL: return VarUI4FromBool(V_BOOL(ps), &V_UI4(pd));
case VT_CY: return VarUI4FromCy(V_CY(ps), &V_UI4(pd));
case VT_DECIMAL: return VarUI4FromDec(&V_DECIMAL(ps), &V_UI4(pd));
case VT_DISPATCH: return VarUI4FromDisp(V_DISPATCH(ps), lcid, &V_UI4(pd));
case VT_BSTR: return VarUI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI4(pd));
}
break;
case VT_UI8:
switch (vtFrom)
{
case VT_EMPTY: V_UI8(pd) = 0; return S_OK;
case VT_I4: if (V_I4(ps) < 0) return DISP_E_OVERFLOW; V_UI8(pd) = V_I4(ps); return S_OK;
case VT_I1: return VarUI8FromI1(V_I1(ps), &V_UI8(pd));
case VT_I2: return VarUI8FromI2(V_I2(ps), &V_UI8(pd));
case VT_UI1: return VarUI8FromUI1(V_UI1(ps), &V_UI8(pd));
case VT_UI2: return VarUI8FromUI2(V_UI2(ps), &V_UI8(pd));
case VT_UI4: return VarUI8FromUI4(V_UI4(ps), &V_UI8(pd));
case VT_I8: V_UI8(pd) = V_I8(ps); return S_OK;
case VT_R4: return VarUI8FromR4(V_R4(ps), &V_UI8(pd));
case VT_R8: return VarUI8FromR8(V_R8(ps), &V_UI8(pd));
case VT_DATE: return VarUI8FromDate(V_DATE(ps), &V_UI8(pd));
case VT_BOOL: return VarUI8FromBool(V_BOOL(ps), &V_UI8(pd));
case VT_CY: return VarUI8FromCy(V_CY(ps), &V_UI8(pd));
case VT_DECIMAL: return VarUI8FromDec(&V_DECIMAL(ps), &V_UI8(pd));
case VT_DISPATCH: return VarUI8FromDisp(V_DISPATCH(ps), lcid, &V_UI8(pd));
case VT_BSTR: return VarUI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI8(pd));
}
break;
case VT_I8:
switch (vtFrom)
{
case VT_EMPTY: V_I8(pd) = 0; return S_OK;
case VT_I4: V_I8(pd) = V_I4(ps); return S_OK;
case VT_I1: return VarI8FromI1(V_I1(ps), &V_I8(pd));
case VT_I2: return VarI8FromI2(V_I2(ps), &V_I8(pd));
case VT_UI1: return VarI8FromUI1(V_UI1(ps), &V_I8(pd));
case VT_UI2: return VarI8FromUI2(V_UI2(ps), &V_I8(pd));
case VT_UI4: return VarI8FromUI4(V_UI4(ps), &V_I8(pd));
case VT_UI8: V_I8(pd) = V_UI8(ps); return S_OK;
case VT_R4: return VarI8FromR4(V_R4(ps), &V_I8(pd));
case VT_R8: return VarI8FromR8(V_R8(ps), &V_I8(pd));
case VT_DATE: return VarI8FromDate(V_DATE(ps), &V_I8(pd));
case VT_BOOL: return VarI8FromBool(V_BOOL(ps), &V_I8(pd));
case VT_CY: return VarI8FromCy(V_CY(ps), &V_I8(pd));
case VT_DECIMAL: return VarI8FromDec(&V_DECIMAL(ps), &V_I8(pd));
case VT_DISPATCH: return VarI8FromDisp(V_DISPATCH(ps), lcid, &V_I8(pd));
case VT_BSTR: return VarI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_I8(pd));
}
break;
case VT_R4:
switch (vtFrom)
{
case VT_EMPTY: V_R4(pd) = 0.0f; return S_OK;
case VT_I1: return VarR4FromI1(V_I1(ps), &V_R4(pd));
case VT_I2: return VarR4FromI2(V_I2(ps), &V_R4(pd));
case VT_I4: return VarR4FromI4(V_I4(ps), &V_R4(pd));
case VT_UI1: return VarR4FromUI1(V_UI1(ps), &V_R4(pd));
case VT_UI2: return VarR4FromUI2(V_UI2(ps), &V_R4(pd));
case VT_UI4: return VarR4FromUI4(V_UI4(ps), &V_R4(pd));
case VT_I8: return VarR4FromI8(V_I8(ps), &V_R4(pd));
case VT_UI8: return VarR4FromUI8(V_UI8(ps), &V_R4(pd));
case VT_R8: return VarR4FromR8(V_R8(ps), &V_R4(pd));
case VT_DATE: return VarR4FromDate(V_DATE(ps), &V_R4(pd));
case VT_BOOL: return VarR4FromBool(V_BOOL(ps), &V_R4(pd));
case VT_CY: return VarR4FromCy(V_CY(ps), &V_R4(pd));
case VT_DECIMAL: return VarR4FromDec(&V_DECIMAL(ps), &V_R4(pd));
case VT_DISPATCH: return VarR4FromDisp(V_DISPATCH(ps), lcid, &V_R4(pd));
case VT_BSTR: return VarR4FromStr(V_BSTR(ps), lcid, dwFlags, &V_R4(pd));
}
break;
case VT_R8:
switch (vtFrom)
{
case VT_EMPTY: V_R8(pd) = 0.0; return S_OK;
case VT_I1: return VarR8FromI1(V_I1(ps), &V_R8(pd));
case VT_I2: return VarR8FromI2(V_I2(ps), &V_R8(pd));
case VT_I4: return VarR8FromI4(V_I4(ps), &V_R8(pd));
case VT_UI1: return VarR8FromUI1(V_UI1(ps), &V_R8(pd));
case VT_UI2: return VarR8FromUI2(V_UI2(ps), &V_R8(pd));
case VT_UI4: return VarR8FromUI4(V_UI4(ps), &V_R8(pd));
case VT_I8: return VarR8FromI8(V_I8(ps), &V_R8(pd));
case VT_UI8: return VarR8FromUI8(V_UI8(ps), &V_R8(pd));
case VT_R4: return VarR8FromR4(V_R4(ps), &V_R8(pd));
case VT_DATE: return VarR8FromDate(V_DATE(ps), &V_R8(pd));
case VT_BOOL: return VarR8FromBool(V_BOOL(ps), &V_R8(pd));
case VT_CY: return VarR8FromCy(V_CY(ps), &V_R8(pd));
case VT_DECIMAL: return VarR8FromDec(&V_DECIMAL(ps), &V_R8(pd));
case VT_DISPATCH: return VarR8FromDisp(V_DISPATCH(ps), lcid, &V_R8(pd));
case VT_BSTR: return VarR8FromStr(V_BSTR(ps), lcid, dwFlags, &V_R8(pd));
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -