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

📄 variant.c

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