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

📄 variant.c

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