Changeset 10629 for trunk/src


Ignore:
Timestamp:
Oct 8, 2004, 11:18:21 AM (21 years ago)
Author:
cinc
Message:

Cinc:
o Rewrote VarNumFromParseNum()
o Added VarDecFromStr() from Wine.
o VarParseNumFromStr() updated with Wine code
o Updated DECIMAL struct (include\win\windef.h) to Wine level.
o updated V_DECIMAL(A) macro (oleaut.h) to Wine level.

Added stubs for:

VarDecAdd()
VarDecMul()
VarDecSub()
VarDecAbs()
VarDecFix()
VarDecInt()
VarDecNeg()
VarDecRound()
VarDecCmp()
VarDecCmpR8()
VarOr()
VarNeg()
VarEqv()
VarIdiv()
VarAbs()
VarMod()
VarImp()
VarFix()
VarRound()
VarInt()
VarFormatNumber()
VarFormatPercent()
VarWeekdayName()
VarMonthName()

Added from Wine:

VarPow()
VarXor()
VarAdd()

svl:
o Added VT_R8 support to VarCmp

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/oleaut32/variant.c

    r9400 r10629  
    201201    {0x00    ,   0,  0          , VT_NULL}
    202202};
     203
     204
     205/************** Form wine: oleaut32/variant.h **************/
     206
     207/* Value of sign for a positive decimal number */
     208#define DECIMAL_POS 0
     209
     210/* Native headers don't change the union ordering for DECIMAL sign/scale (duh).
     211 * This means that the signscale member is only useful for setting both members to 0.
     212 * SIGNSCALE creates endian-correct values so that we can properly set both at once
     213 * to values other than 0.
     214 */
     215#ifdef WORDS_BIGENDIAN
     216#define SIGNSCALE(sign,scale) (((scale) << 8) | sign)
     217#else
     218#define SIGNSCALE(sign,scale) (((sign) << 8) | scale)
     219#endif
     220/* Macros for getting at a DECIMAL's parts */
     221#define DEC_SIGN(d)      ((d)->u.s.sign)
     222#define DEC_SCALE(d)     ((d)->u.s.scale)
     223#define DEC_SIGNSCALE(d) ((d)->u.signscale)
     224#define DEC_HI32(d)      ((d)->Hi32)
     225#define DEC_MID32(d)     ((d)->u1.s1.Mid32)
     226#define DEC_LO32(d)      ((d)->u1.s1.Lo32)
     227#define DEC_LO64(d)      ((d)->u1.Lo64)
     228
     229/* DECIMAL */
     230#define _VarDecFromStr(str,lcid,flags,out) VARIANT_NumberFromBstr(str,lcid,flags,(BYTE*)out,VT_DECIMAL)
     231/* R8 (double) */
     232#define _VarR8FromStr(str,lcid,flags,out) VARIANT_NumberFromBstr(str,lcid,flags,(BYTE*)out,VT_R8)
     233
     234/* Internal flags for low level conversion functions */
     235#define  VAR_BOOLONOFF 0x0400 /* Convert bool to "On"/"Off" */
     236#define  VAR_BOOLYESNO 0x0800 /* Convert bool to "Yes"/"No" */
     237#define  VAR_NEGATIVE  0x1000 /* Number is negative */
     238
     239/* The localised characters that make up a valid number */
     240typedef struct tagVARIANT_NUMBER_CHARS
     241{
     242  WCHAR cNegativeSymbol;
     243  WCHAR cPositiveSymbol;
     244  WCHAR cDecimalPoint;
     245  WCHAR cDigitSeperator;
     246  WCHAR cCurrencyLocal;
     247  WCHAR cCurrencyLocal2;
     248  WCHAR cCurrencyDecimalPoint;
     249  WCHAR cCurrencyDigitSeperator;
     250} VARIANT_NUMBER_CHARS;
     251
     252void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS*,LCID,DWORD);
     253/********** End of Form wine: oleaut32/variant.h ************/
     254
     255/* Write a number from a UI8 and sign */
     256#ifdef __WIN32OS2__
     257static WCHAR *VARIANT_WriteNumber(ULONG ulVal, WCHAR* szOut)
     258{
     259  //FIXME("%s: Hack! No real ULONG64 support here, using ULONG instead. ulVal=%x!!\n", __FUNCTION__, ulVal);
     260#else
     261static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
     262  {
     263#endif
     264
     265  do
     266  {
     267    WCHAR ulNextDigit = ulVal % 10;
     268
     269    *szOut-- = '0' + ulNextDigit;
     270    ulVal = (ulVal - ulNextDigit) / 10;
     271  } while (ulVal);
     272
     273  szOut++;
     274  return szOut;
     275}
     276
     277/* Create a (possibly localised) BSTR from a UI8 and sign */
     278static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
     279{
     280  WCHAR szConverted[256];
     281
     282  if (dwFlags & VAR_NEGATIVE)
     283    *--szOut = '-';
     284
     285  if (dwFlags & LOCALE_USE_NLS)
     286  {
     287    /* Format the number for the locale */
     288    szConverted[0] = '\0';
     289    GetNumberFormatW(lcid,
     290                     dwFlags & LOCALE_NOUSEROVERRIDE,
     291                     szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
     292    szOut = szConverted;
     293  }
     294  return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
     295}
     296
     297
     298/******************************************************************************
     299 * VarBstrFromDec (OLEAUT32.232)
     300 *
     301 * Convert a VT_DECIMAL to a VT_BSTR.
     302 *
     303 * PARAMS
     304 *  pDecIn   [I] Source
     305 *  lcid     [I] LCID for the conversion
     306 *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
     307 *  pbstrOut [O] Destination
     308 *
     309 * RETURNS
     310 *  Success: S_OK.
     311 *  Failure: E_INVALIDARG, if pbstrOut is invalid.
     312 *           E_OUTOFMEMORY, if memory allocation fails.
     313 */
     314HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
     315{
     316  TRACE("%s: entering function. pDecIn->lo32: %x, pDecIn->Mid32: %x, pDecIn->Hi32: %x, sign: %x, dwFlags: %x\n",
     317        __FUNCTION__, DEC_LO32(pDecIn), DEC_MID32(pDecIn), DEC_HI32(pDecIn), DEC_SIGN(pDecIn), dwFlags);
     318  if (!pbstrOut)
     319    return E_INVALIDARG;
     320
     321  if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
     322  {
     323    WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
     324
     325    /* Create the basic number string */
     326    *szOut-- = '\0';
     327
     328
     329#ifdef __WIN32OS2__
     330    szOut = VARIANT_WriteNumber(DEC_LO32(pDecIn), szOut);
     331#else
     332    szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
     333#endif
     334    if (DEC_SIGN(pDecIn))
     335      dwFlags |= VAR_NEGATIVE;
     336
     337    *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
     338    TRACE("%s: returning %s\n", __FUNCTION__, debugstr_w(*pbstrOut));
     339    return *pbstrOut ? S_OK : E_OUTOFMEMORY;
     340  }
     341  FIXME("semi-stub\n");
     342  return E_INVALIDARG;
     343}
     344
     345
     346/* Copy data from one variant to another. */
     347static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
     348{
     349  //  TRACE("%s: entering function.\n", __FUNCTION__);
     350  switch (vt)
     351  {
     352  case VT_I1:
     353  case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
     354  case VT_BOOL:
     355  case VT_I2:
     356  case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
     357  case VT_R4:
     358  case VT_INT:
     359  case VT_I4:
     360  case VT_UINT:
     361  case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
     362  case VT_R8:
     363  case VT_DATE:
     364  case VT_CY:
     365  case VT_I8:
     366#ifdef __WIN32OS2__
     367    /*  case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONGLONG)); break; */
     368    /*  case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break; */
     369  case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
     370#else
     371  case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONGLONG)); break;
     372  case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
     373  case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
     374#endif
     375  default:
     376    FIXME("%s: VT_ type %d unhandled, please report!\n", __FUNCTION__,  vt);
     377  }
     378}
     379
     380/* Form wine: oleaut32/vartype.c */
     381/* Coerce VT_BSTR to a numeric type */
     382HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
     383                               void* pOut, VARTYPE vt)
     384{
     385  VARIANTARG dstVar;
     386  HRESULT hRet;
     387  NUMPARSE np;
     388  BYTE rgb[1024];
     389
     390  TRACE("%s: (StrIn: %s, LCID: 0x%08lx, ulFlags: 0x%08lx )\n", __FUNCTION__, pStrIn, lcid, ulFlags );
     391
     392  /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
     393  np.cDig = sizeof(rgb) / sizeof(BYTE);
     394  np.dwInFlags = NUMPRS_STD;
     395
     396  hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
     397
     398  if (SUCCEEDED(hRet))
     399  {
     400    /* 1 << vt gives us the VTBIT constant for the destination number type */
     401    hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
     402    if (SUCCEEDED(hRet)) {
     403      VARIANT_CopyData(&dstVar, vt, pOut);
     404      TRACE("%s: Returning dstVar-> type : %x", __FUNCTION__, V_VT(&dstVar));
     405    }
     406  }
     407  return hRet;
     408}
     409
    203410
    204411/******************************************************************************
     
    18322039void WINAPI VariantInit(VARIANTARG* pvarg)
    18332040{
    1834   TRACE("(%p)\n",pvarg);
     2041  TRACE("%s: (%p)\n", __FUNCTION__, pvarg);
    18352042
    18362043  memset(pvarg, 0, sizeof (VARIANTARG));
     
    18512058{
    18522059  HRESULT res = S_OK;
    1853   TRACE("(%p)\n",pvarg);
     2060  TRACE("%s: (%p)\n",__FUNCTION__, pvarg);
    18542061
    18552062  res = ValidateVariantType( V_VT(pvarg) );
     
    19112118  HRESULT res = S_OK;
    19122119
    1913   TRACE("(%p, %p), vt=%d\n", pvargDest, pvargSrc, V_VT(pvargSrc));
     2120  TRACE("%s: (Dest: %p, Src: %p), vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, V_VT(pvargSrc));
    19142121
    19152122  res = ValidateVariantType( V_VT(pvargSrc) );
     
    21322339        VARIANTARG varg;
    21332340        VariantInit( &varg );
    2134 
    2135         TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
     2341        TRACE("%s: (Dest: %p, source: %p, LCID: %ld, wFlags: %u, VARTYPE: %u) vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
    21362342    TRACE("Src Var:\n");
    21372343    dump_Variant(pvargSrc);
     
    21702376                         */
    21712377                        VARIANTARG Variant;
     2378
    21722379                        VariantInit( &Variant );
    21732380                        res = VariantCopyInd( &Variant, pvargSrc );
     
    21792386                                VariantClear( &Variant );
    21802387                        }
    2181 
    21822388                }
    21832389                else
     
    21972403                V_VT(pvargDest) = vt;
    21982404
    2199     TRACE("Dest Var:\n");
     2405    TRACE("Dest Var (re: %x)\n", res);
    22002406    dump_Variant(pvargDest);
    22012407
     
    27752981        LPSTR pNewString = NULL;
    27762982
    2777         TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
     2983        TRACE("%s: ( strIn: %p -> %s, lcid: 0x%08lx, dwFlags: 0x%08lx, plOut: %p ), stub\n", __FUNCTION__, strIn, debugstr_w(strIn), lcid, dwFlags, plOut );
    27782984
    27792985        /* Check if we have a valid argument
     
    30993305}
    31003306
     3307#if 0
    31013308/******************************************************************************
    31023309 *              VarR8FromStr            [OLEAUT32.84]
     
    31293336
    31303337        return S_OK;
     3338}
     3339#endif
     3340
     3341/************************************************************************
     3342 * VarR8FromStr (OLEAUT32.84)
     3343 *
     3344 * Convert a VT_BSTR to a VT_R8.
     3345 *
     3346 * PARAMS
     3347 *  strIn   [I] Source
     3348 *  lcid    [I] LCID for the conversion
     3349 *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
     3350 *  pDblOut [O] Destination
     3351 *
     3352 * RETURNS
     3353 *  Success: S_OK.
     3354 *  Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
     3355 *           DISP_E_TYPEMISMATCH, if the type cannot be converted
     3356 */
     3357HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
     3358{
     3359  return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
    31313360}
    31323361
     
    33333562   return S_OK;
    33343563}
     3564
     3565
    33353566
    33363567/******************************************************************************
     
    44854716
    44864717
     4718#define GET_NUMBER_TEXT(fld,name) \
     4719  buff[0] = 0; \
     4720  if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \
     4721    WARN("%s: buffer too small for " #fld "\n", __FUNCTION__); \
     4722  else \
     4723    if (buff[0]) lpChars->name = buff[0]; /* \
     4724  TRACE("lcid 0x%lx, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name)*/
     4725
     4726/* Get the valid number characters for an lcid */
     4727void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
     4728{
     4729  static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',',','$',0,'.',',' };
     4730  LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
     4731  WCHAR buff[4];
     4732
     4733  memcpy(lpChars, &defaultChars, sizeof(defaultChars));
     4734  GET_NUMBER_TEXT(LOCALE_SNEGATIVESIGN, cNegativeSymbol);
     4735  GET_NUMBER_TEXT(LOCALE_SPOSITIVESIGN, cPositiveSymbol);
     4736  GET_NUMBER_TEXT(LOCALE_SDECIMAL, cDecimalPoint);
     4737  GET_NUMBER_TEXT(LOCALE_STHOUSAND, cDigitSeperator);
     4738  GET_NUMBER_TEXT(LOCALE_SMONDECIMALSEP, cCurrencyDecimalPoint);
     4739  GET_NUMBER_TEXT(LOCALE_SMONTHOUSANDSEP, cCurrencyDigitSeperator);
     4740
     4741  /* Local currency symbols are often 2 characters */
     4742  lpChars->cCurrencyLocal2 = '\0';
     4743  switch(GetLocaleInfoW(lcid, lctype|LOCALE_SCURRENCY, buff, sizeof(buff)/sizeof(WCHAR)))
     4744  {
     4745    case 3: lpChars->cCurrencyLocal2 = buff[1]; /* Fall through */
     4746    case 2: lpChars->cCurrencyLocal  = buff[0];
     4747            break;
     4748    default: WARN("buffer too small for LOCALE_SCURRENCY\n");
     4749  }
     4750  TRACE("lcid 0x%lx, cCurrencyLocal =%d,%d '%c','%c'\n", lcid, lpChars->cCurrencyLocal,
     4751        lpChars->cCurrencyLocal2, lpChars->cCurrencyLocal, lpChars->cCurrencyLocal2);
     4752}
     4753
     4754/* Number Parsing States */
     4755#define B_PROCESSING_EXPONENT 0x1
     4756#define B_NEGATIVE_EXPONENT   0x2
     4757#define B_EXPONENT_START      0x4
     4758#define B_INEXACT_ZEROS       0x8
     4759#define B_LEADING_ZERO        0x10
     4760#define B_PROCESSING_HEX      0x20
     4761#define B_PROCESSING_OCT      0x40
     4762/**********************************************************************
     4763 *              VarParseNumFromStr [OLEAUT32.46]
     4764 *
     4765 * Parse a string containing a number into a NUMPARSE structure.
     4766 *
     4767 * PARAMS
     4768 *  lpszStr [I]   String to parse number from
     4769 *  lcid    [I]   Locale Id for the conversion
     4770 *  dwFlags [I]   0, or LOCALE_NOUSEROVERRIDE to use system default number chars
     4771 *  pNumprs [I/O] Destination for parsed number
     4772 *  rgbDig  [O]   Destination for digits read in
     4773 *
     4774 * RETURNS
     4775 *  Success: S_OK. pNumprs and rgbDig contain the parsed representation of
     4776 *           the number.
     4777 *  Failure: E_INVALIDARG, if any parameter is invalid.
     4778 *           DISP_E_TYPEMISMATCH, if the string is not a number or is formatted
     4779 *           incorrectly.
     4780 *           DISP_E_OVERFLOW, if rgbDig is too small to hold the number.
     4781 *
     4782 * NOTES
     4783 *  pNumprs must have the following fields set:
     4784 *   cDig: Set to the size of rgbDig.
     4785 *   dwInFlags: Set to the allowable syntax of the number using NUMPRS_ flags
     4786 *            from "oleauto.h".
     4787 *
     4788 * FIXME
     4789 *  - I am unsure if this function should parse non-arabic (e.g. Thai)
     4790 *   numerals, so this has not been implemented.
     4791 */
     4792HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
     4793                                  NUMPARSE *pNumprs, BYTE *rgbDig)
     4794{
     4795  VARIANT_NUMBER_CHARS chars;
     4796  BYTE rgbTmp[1024];
     4797  DWORD dwState = B_EXPONENT_START|B_INEXACT_ZEROS;
     4798  int iMaxDigits = sizeof(rgbTmp) / sizeof(BYTE);
     4799  int cchUsed = 0;
     4800
     4801  TRACE("%s: (%s, %ld, dwFlags: 0x%08lx,%p,%p, NUMPARSE->dwInFlags: %x)\n", __FUNCTION__, debugstr_w(lpszStr), lcid, dwFlags, pNumprs, rgbDig, pNumprs->dwInFlags);
     4802
     4803  if (!pNumprs || !rgbDig)
     4804    return E_INVALIDARG;
     4805
     4806  if (pNumprs->cDig < iMaxDigits)
     4807    iMaxDigits = pNumprs->cDig;
     4808
     4809  pNumprs->cDig = 0;
     4810  pNumprs->dwOutFlags = 0;
     4811  pNumprs->cchUsed = 0;
     4812  pNumprs->nBaseShift = 0;
     4813  pNumprs->nPwr10 = 0;
     4814
     4815  if (!lpszStr)
     4816    return DISP_E_TYPEMISMATCH;
     4817
     4818  VARIANT_GetLocalisedNumberChars(&chars, lcid, dwFlags);
     4819
     4820  /* First consume all the leading symbols and space from the string */
     4821  while (1)
     4822  {
     4823    if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && isspaceW(*lpszStr))
     4824    {
     4825      pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE;
     4826      do
     4827      {
     4828        cchUsed++;
     4829        lpszStr++;
     4830      } while (isspaceW(*lpszStr));
     4831    }
     4832    else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS &&
     4833             *lpszStr == chars.cPositiveSymbol &&
     4834             !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS))
     4835    {
     4836      pNumprs->dwOutFlags |= NUMPRS_LEADING_PLUS;
     4837      cchUsed++;
     4838      lpszStr++;
     4839    }
     4840    else if (pNumprs->dwInFlags & NUMPRS_LEADING_MINUS &&
     4841             *lpszStr == chars.cNegativeSymbol &&
     4842             !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS))
     4843    {
     4844      pNumprs->dwOutFlags |= (NUMPRS_LEADING_MINUS|NUMPRS_NEG);
     4845      cchUsed++;
     4846      lpszStr++;
     4847    }
     4848    else if (pNumprs->dwInFlags & NUMPRS_CURRENCY &&
     4849             !(pNumprs->dwOutFlags & NUMPRS_CURRENCY) &&
     4850             *lpszStr == chars.cCurrencyLocal &&
     4851             (!chars.cCurrencyLocal2 || lpszStr[1] == chars.cCurrencyLocal2))
     4852    {
     4853      pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
     4854      cchUsed++;
     4855      lpszStr++;
     4856      /* Only accept currency characters */
     4857      chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
     4858      chars.cDigitSeperator = chars.cCurrencyDigitSeperator;
     4859    }
     4860    else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
     4861             !(pNumprs->dwOutFlags & NUMPRS_PARENS))
     4862    {
     4863      pNumprs->dwOutFlags |= NUMPRS_PARENS;
     4864      cchUsed++;
     4865      lpszStr++;
     4866    }
     4867    else
     4868      break;
     4869  } /* End of while */
     4870
     4871  if(pNumprs->dwOutFlags & (1<<VT_LPWSTR))
     4872    {
     4873 TRACE("  I'm here");     
     4874    }
     4875  if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY))
     4876  {
     4877    /* Only accept non-currency characters */
     4878    chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
     4879    chars.cCurrencyDigitSeperator = chars.cDigitSeperator;
     4880  }
     4881
     4882  if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
     4883    pNumprs->dwInFlags & NUMPRS_HEX_OCT)
     4884  {
     4885      dwState |= B_PROCESSING_HEX;
     4886      pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
     4887      cchUsed=cchUsed+2;
     4888      lpszStr=lpszStr+2;
     4889  }
     4890  else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
     4891    pNumprs->dwInFlags & NUMPRS_HEX_OCT)
     4892  {
     4893      dwState |= B_PROCESSING_OCT;
     4894      pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
     4895      cchUsed=cchUsed+2;
     4896      lpszStr=lpszStr+2;
     4897  }
     4898
     4899  /* Strip Leading zeros */
     4900  while (*lpszStr == '0')
     4901  {
     4902    dwState |= B_LEADING_ZERO;
     4903    cchUsed++;
     4904    lpszStr++;
     4905  }
     4906
     4907  while (*lpszStr)
     4908  {
     4909    if (isdigitW(*lpszStr))
     4910    {
     4911      if (dwState & B_PROCESSING_EXPONENT)
     4912      {
     4913        int exponentSize = 0;
     4914        if (dwState & B_EXPONENT_START)
     4915        {
     4916          while (*lpszStr == '0')
     4917          {
     4918            /* Skip leading zero's in the exponent */
     4919            cchUsed++;
     4920            lpszStr++;
     4921          }
     4922          if (!isdigitW(*lpszStr))
     4923            break; /* No exponent digits - invalid */
     4924        }
     4925
     4926        while (isdigitW(*lpszStr))
     4927        {
     4928          exponentSize *= 10;
     4929          exponentSize += *lpszStr - '0';
     4930          cchUsed++;
     4931          lpszStr++;
     4932        }
     4933        if (dwState & B_NEGATIVE_EXPONENT)
     4934          exponentSize = -exponentSize;
     4935        /* Add the exponent into the powers of 10 */
     4936        pNumprs->nPwr10 += exponentSize;
     4937        dwState &= ~(B_PROCESSING_EXPONENT|B_EXPONENT_START);
     4938        lpszStr--; /* back up to allow processing of next char */
     4939      }
     4940      else
     4941      {
     4942        if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
     4943          && !(dwState & B_PROCESSING_OCT))
     4944        {
     4945          pNumprs->dwOutFlags |= NUMPRS_INEXACT;
     4946
     4947          if (*lpszStr != '0')
     4948            dwState &= ~B_INEXACT_ZEROS; /* Inexact number with non-trailing zeros */
     4949
     4950          /* This digit can't be represented, but count it in nPwr10 */
     4951          if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
     4952            pNumprs->nPwr10--;
     4953          else
     4954            pNumprs->nPwr10++;
     4955        }
     4956        else
     4957        {
     4958          if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
     4959            return DISP_E_TYPEMISMATCH;
     4960          }
     4961
     4962          if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
     4963            pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
     4964
     4965          rgbTmp[pNumprs->cDig] = *lpszStr - '0';
     4966        }
     4967        pNumprs->cDig++;
     4968        cchUsed++;
     4969      }
     4970    }
     4971    else if (*lpszStr == chars.cDigitSeperator && pNumprs->dwInFlags & NUMPRS_THOUSANDS)
     4972    {
     4973      pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
     4974      cchUsed++;
     4975    }
     4976    else if (*lpszStr == chars.cDecimalPoint &&
     4977             pNumprs->dwInFlags & NUMPRS_DECIMAL &&
     4978             !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
     4979    {
     4980      pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
     4981      cchUsed++;
     4982
     4983      /* Remove trailing zeros from the whole number part */
     4984      while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
     4985      {
     4986        pNumprs->nPwr10++;
     4987        pNumprs->cDig--;
     4988      }
     4989
     4990      /* If we have no digits so far, skip leading zeros */
     4991      if (!pNumprs->cDig)
     4992      {
     4993        while (lpszStr[1] == '0')
     4994        {
     4995          dwState |= B_LEADING_ZERO;
     4996          cchUsed++;
     4997          lpszStr++;
     4998        }
     4999      }
     5000    }
     5001    else if ((*lpszStr == 'e' || *lpszStr == 'E') &&
     5002             pNumprs->dwInFlags & NUMPRS_EXPONENT &&
     5003             !(pNumprs->dwOutFlags & NUMPRS_EXPONENT))
     5004    {
     5005      dwState |= B_PROCESSING_EXPONENT;
     5006      pNumprs->dwOutFlags |= NUMPRS_EXPONENT;
     5007      cchUsed++;
     5008    }
     5009    else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cPositiveSymbol)
     5010    {
     5011      cchUsed++; /* Ignore positive exponent */
     5012    }
     5013    else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cNegativeSymbol)
     5014    {
     5015      dwState |= B_NEGATIVE_EXPONENT;
     5016      cchUsed++;
     5017    }
     5018    else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
     5019             (*lpszStr >= 'A' && *lpszStr <= 'F')) &&
     5020             dwState & B_PROCESSING_HEX)
     5021    {
     5022      if (pNumprs->cDig >= iMaxDigits)
     5023      {
     5024        return DISP_E_OVERFLOW;
     5025      }
     5026      else
     5027      {
     5028        if (*lpszStr >= 'a')
     5029          rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
     5030        else
     5031          rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
     5032      }
     5033      pNumprs->cDig++;
     5034      cchUsed++;
     5035    }
     5036    else
     5037      break; /* Stop at an unrecognised character */
     5038
     5039    lpszStr++;
     5040  }
     5041
     5042  if (!pNumprs->cDig && dwState & B_LEADING_ZERO)
     5043  {
     5044    /* Ensure a 0 on its own gets stored */
     5045    pNumprs->cDig = 1;
     5046    rgbTmp[0] = 0;
     5047  }
     5048
     5049  if (pNumprs->dwOutFlags & NUMPRS_EXPONENT && dwState & B_PROCESSING_EXPONENT)
     5050  {
     5051    pNumprs->cchUsed = cchUsed;
     5052    return DISP_E_TYPEMISMATCH; /* Failed to completely parse the exponent */
     5053  }
     5054
     5055  if (pNumprs->dwOutFlags & NUMPRS_INEXACT)
     5056  {
     5057    if (dwState & B_INEXACT_ZEROS)
     5058      pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* All zeros doesn't set NUMPRS_INEXACT */
     5059  } else if(pNumprs->dwInFlags & NUMPRS_HEX_OCT)
     5060  {
     5061    /* copy all of the digits into the output digit buffer */
     5062    /* this is exactly what windows does although it also returns */
     5063    /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
     5064    memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
     5065
     5066    if (dwState & B_PROCESSING_HEX) {
     5067      /* hex numbers have always the same format */
     5068      pNumprs->nPwr10=0;
     5069      pNumprs->nBaseShift=4;
     5070    } else {
     5071      if (dwState & B_PROCESSING_OCT) {
     5072        /* oct numbers have always the same format */
     5073        pNumprs->nPwr10=0;
     5074        pNumprs->nBaseShift=3;
     5075      } else {
     5076        while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
     5077        {
     5078          if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
     5079            pNumprs->nPwr10--;
     5080          else
     5081            pNumprs->nPwr10++;
     5082
     5083          pNumprs->cDig--;
     5084        }
     5085      }
     5086    }
     5087  } else
     5088  {
     5089    /* Remove trailing zeros from the last (whole number or decimal) part */
     5090    while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
     5091    {
     5092      if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
     5093        pNumprs->nPwr10--;
     5094      else
     5095        pNumprs->nPwr10++;
     5096
     5097      pNumprs->cDig--;
     5098    }
     5099  }
     5100
     5101  if (pNumprs->cDig <= iMaxDigits)
     5102    pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* Ignore stripped zeros for NUMPRS_INEXACT */
     5103  else
     5104    pNumprs->cDig = iMaxDigits; /* Only return iMaxDigits worth of digits */
     5105
     5106  /* Copy the digits we processed into rgbDig */
     5107  memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
     5108
     5109  /* Consume any trailing symbols and space */
     5110  while (1)
     5111  {
     5112    if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && isspaceW(*lpszStr))
     5113    {
     5114      pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE;
     5115      do
     5116      {
     5117        cchUsed++;
     5118        lpszStr++;
     5119      } while (isspaceW(*lpszStr));
     5120    }
     5121    else if (pNumprs->dwInFlags & NUMPRS_TRAILING_PLUS &&
     5122             !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS) &&
     5123             *lpszStr == chars.cPositiveSymbol)
     5124    {
     5125      pNumprs->dwOutFlags |= NUMPRS_TRAILING_PLUS;
     5126      cchUsed++;
     5127      lpszStr++;
     5128    }
     5129    else if (pNumprs->dwInFlags & NUMPRS_TRAILING_MINUS &&
     5130             !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS) &&
     5131             *lpszStr == chars.cNegativeSymbol)
     5132    {
     5133      pNumprs->dwOutFlags |= (NUMPRS_TRAILING_MINUS|NUMPRS_NEG);
     5134      cchUsed++;
     5135      lpszStr++;
     5136    }
     5137    else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == ')' &&
     5138             pNumprs->dwOutFlags & NUMPRS_PARENS)
     5139    {
     5140      cchUsed++;
     5141      lpszStr++;
     5142      pNumprs->dwOutFlags |= NUMPRS_NEG;
     5143    }
     5144    else
     5145      break;
     5146  }
     5147
     5148  if (pNumprs->dwOutFlags & NUMPRS_PARENS && !(pNumprs->dwOutFlags & NUMPRS_NEG))
     5149  {
     5150    pNumprs->cchUsed = cchUsed;
     5151    return DISP_E_TYPEMISMATCH; /* Opening parenthesis not matched */
     5152  }
     5153
     5154  if (pNumprs->dwInFlags & NUMPRS_USE_ALL && *lpszStr != '\0')
     5155    return DISP_E_TYPEMISMATCH; /* Not all chars were consumed */
     5156
     5157  if (!pNumprs->cDig)
     5158    return DISP_E_TYPEMISMATCH; /* No Number found */
     5159
     5160  pNumprs->cchUsed = cchUsed;
     5161  TRACE("%s: Returning, NUMPARS->cchUsed: %x, NUMPARS->cDig: %x, pNumprs->dwOutFlags: %x, NUMPARS->nBaseShift: %x,, NUMPARS->nPwr10: %x\n",
     5162        __FUNCTION__, cchUsed, pNumprs->cDig, pNumprs->dwOutFlags, pNumprs->nBaseShift, pNumprs->nPwr10);
     5163  return S_OK;
     5164}
     5165
     5166#if 0
    44875167/**********************************************************************
    44885168 *              VarParseNumFromStr [OLEAUT32.46]
     
    45245204    return S_OK;
    45255205}
     5206#endif
    45265207
    45275208
    45285209/**********************************************************************
    45295210 *              VarNumFromParseNum [OLEAUT32.47]
     5211 *
     5212 * Convert a NUMPARSE structure into a numeric Variant type.
     5213 *
     5214 * PARAMS
     5215 *  pNumprs  [I] Source for parsed number. cDig must be set to the size of rgbDig
     5216 *  rgbDig   [I] Source for the numbers digits
     5217 *  dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types
     5218 *  pVarDst  [O] Destination for the converted Variant value.
     5219 *
     5220 * RETURNS
     5221 *  Success: S_OK. pVarDst contains the converted value.
     5222 *  Failure: E_INVALIDARG, if any parameter is invalid.
     5223 *           DISP_E_OVERFLOW, if the number is too big for the types set in dwVtBits.
     5224 *
     5225 * NOTES
     5226 *  - The smallest favoured type present in dwVtBits that can represent the
     5227 *    number in pNumprs without losing precision is used.
     5228 *  - Signed types are preferrred over unsigned types of the same size.
     5229 *  - Preferred types in order are: integer, float, double, currency then decimal.
     5230 *  - Rounding (dropping of decimal points) occurs without error. See VarI8FromR8()
     5231 *    for details of the rounding method.
     5232 *  - pVarDst is not cleared before the result is stored in it.
    45305233 */
    45315234HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig,
    45325235                                  ULONG dwVtBits, VARIANT * pvar)
    45335236{
     5237#ifdef __WIN32OS2__
    45345238    DWORD xint;
    45355239    int i;
    4536     FIXME("(..,dwVtBits=%lx,....), partial stub!\n",dwVtBits);
     5240
     5241    TRACE("%s: NUMPARSE->cDig: %x, NUMPARSE->nBaseShift: %x, NUMPARSE->dwOutFlags: %x dwVtBits=%lx. rgbDig: \n",
     5242          __FUNCTION__, pnumprs->cDig, pnumprs->nBaseShift, pnumprs->dwOutFlags, dwVtBits);
    45375243
    45385244    xint = 0;
    45395245    for (i=0;i<pnumprs->cDig;i++)
    4540         xint = xint*10 + rgbDig[i];
     5246      xint = xint*10 + rgbDig[i];
    45415247
    45425248    if (pnumprs->dwOutFlags & NUMPRS_NEG) {
    45435249        xint = xint * -1;
    45445250    }
     5251    TRACE("%s: xint: %x (%ld)\n", __FUNCTION__, xint, xint);
    45455252
    45465253    VariantInit(pvar);
     
    45745281    }
    45755282
     5283    if (dwVtBits & VTBIT_DECIMAL)
     5284      {
     5285        int i;
     5286        ULONG carry;
     5287        /*    ULONG64 tmp; */
     5288        ULONG tmp;
     5289        DECIMAL* pDec = &V_DECIMAL(pvar);
     5290       
     5291        V_VT(pvar) = VT_DECIMAL;
     5292       
     5293        DECIMAL_SETZERO(pDec);
     5294        DEC_LO32(pDec) = 0;
     5295       
     5296        if (pnumprs->dwOutFlags & NUMPRS_NEG)
     5297          DEC_SIGN(pDec) = DECIMAL_NEG;
     5298        else
     5299          DEC_SIGN(pDec) = DECIMAL_POS;
     5300
     5301        /* Factor the significant digits */
     5302        for (i = 0; i < pnumprs->cDig; i++)
     5303          {
     5304            if(0xffffffff /10 - 9 < DEC_LO32(pDec) ) {
     5305              /* Overflow expected. This code only support 32Bit numbers for now */
     5306              FIXME("%s: Converted number will be  > 32bit! Only partial implementation. Returning DISP_E_OVERFLOW.", __FUNCTION__);
     5307              DEC_LO32(pDec) =  UI4_MAX;
     5308              return DISP_E_OVERFLOW;
     5309            }
     5310
     5311            tmp = DEC_LO32(pDec) * 10 + rgbDig[i];
     5312
     5313            /* No support for numbers > 32 bit for now. */           
     5314            DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
     5315            DEC_MID32(pDec) = (ULONG)0;
     5316            DEC_HI32(pDec) = (ULONG)0;
     5317
     5318            /* The following is not working because of missing ULONG64 !! */
     5319#if 0
     5320            carry = (ULONG)(tmp >> 32);
     5321            DEC_LO64(pDec)=tmp;
     5322            DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
     5323            tmp = (ULONG)DEC_MID32(pDec) * 10 + carry;
     5324            carry = (ULONG)(tmp >> 32);
     5325            DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
     5326            tmp = (ULONG)DEC_HI32(pDec) * 10 + carry;
     5327            DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
     5328#endif
     5329
     5330            if (tmp >> 32 & UI4_MAX)
     5331              {
     5332              VarNumFromParseNum_DecOverflow:
     5333                TRACE("Overflow\n");
     5334                DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
     5335                return DISP_E_OVERFLOW;
     5336              }
     5337          }
     5338       
     5339        TRACE("Done... LO32: %x, MID32: %x, HI32: %x, DEC_LO64: %x, SignScale: %x, sign: %x\n",
     5340              DEC_LO32(pDec), DEC_MID32(pDec), DEC_HI32(pDec), DEC_LO64(pDec), DEC_SIGNSCALE(pDec), DEC_SIGN(pDec) );
     5341       
     5342        return S_OK;
     5343      }
     5344   
     5345    FIXME("%s: (..,dwVtBits=%lx,....), partial stub!\n", __FUNCTION__, dwVtBits);
    45765346        FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint);
    45775347        return E_FAIL;
    4578 }
    4579 
     5348} /* End of __WIN32OS2__ */
     5349
     5350#else
     5351
     5352  /* Scale factors and limits for double arithmetic */
     5353  static const double dblMultipliers[11] = {
     5354    1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0,
     5355    1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0
     5356  };
     5357  static const double dblMinimums[11] = {
     5358    R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0,
     5359    R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0,
     5360    R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0
     5361  };
     5362  static const double dblMaximums[11] = {
     5363    R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0,
     5364    R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0,
     5365    R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0
     5366  };
     5367
     5368  int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0;
     5369
     5370  TRACE("(%p,%p,0x%lx,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst);
     5371
     5372  if (pNumprs->nBaseShift)
     5373  {
     5374    /* nBaseShift indicates a hex or octal number */
     5375    ULONG64 ul64 = 0;
     5376    LONG64 l64;
     5377    int i;
     5378
     5379    /* Convert the hex or octal number string into a UI64 */
     5380    for (i = 0; i < pNumprs->cDig; i++)
     5381    {
     5382      if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
     5383      {
     5384        TRACE("Overflow multiplying digits\n");
     5385        return DISP_E_OVERFLOW;
     5386      }
     5387      ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
     5388    }
     5389
     5390    /* also make a negative representation */
     5391    l64=-ul64;
     5392
     5393    /* Try signed and unsigned types in size order */
     5394    if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN)))
     5395    {
     5396      V_VT(pVarDst) = VT_I1;
     5397      if (ul64 <= I1_MAX)
     5398          V_I1(pVarDst) = ul64;
     5399      else
     5400          V_I1(pVarDst) = l64;
     5401      return S_OK;
     5402    }
     5403    else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
     5404    {
     5405      V_VT(pVarDst) = VT_UI1;
     5406      V_UI1(pVarDst) = ul64;
     5407      return S_OK;
     5408    }
     5409    else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN)))
     5410    {
     5411      V_VT(pVarDst) = VT_I2;
     5412      if (ul64 <= I2_MAX)
     5413          V_I2(pVarDst) = ul64;
     5414      else
     5415          V_I2(pVarDst) = l64;
     5416      return S_OK;
     5417    }
     5418    else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
     5419    {
     5420      V_VT(pVarDst) = VT_UI2;
     5421      V_UI2(pVarDst) = ul64;
     5422      return S_OK;
     5423    }
     5424    else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
     5425    {
     5426      V_VT(pVarDst) = VT_I4;
     5427      if (ul64 <= I4_MAX)
     5428          V_I4(pVarDst) = ul64;
     5429      else
     5430          V_I4(pVarDst) = l64;
     5431      return S_OK;
     5432    }
     5433    else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
     5434    {
     5435      V_VT(pVarDst) = VT_UI4;
     5436      V_UI4(pVarDst) = ul64;
     5437      return S_OK;
     5438    }
     5439    else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN)))
     5440    {
     5441      V_VT(pVarDst) = VT_I8;
     5442      V_I8(pVarDst) = ul64;
     5443      return S_OK;
     5444    }
     5445    else if (dwVtBits & VTBIT_UI8)
     5446    {
     5447      V_VT(pVarDst) = VT_UI8;
     5448      V_UI8(pVarDst) = ul64;
     5449      return S_OK;
     5450    }
     5451    else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
     5452    {
     5453      V_VT(pVarDst) = VT_DECIMAL;
     5454      DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
     5455      DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
     5456      DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
     5457      return S_OK;
     5458    }
     5459    else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
     5460    {
     5461      V_VT(pVarDst) = VT_R4;
     5462      if (ul64 <= I4_MAX)
     5463          V_R4(pVarDst) = ul64;
     5464      else
     5465          V_R4(pVarDst) = l64;
     5466      return S_OK;
     5467    }
     5468    else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
     5469    {
     5470      V_VT(pVarDst) = VT_R8;
     5471      if (ul64 <= I4_MAX)
     5472          V_R8(pVarDst) = ul64;
     5473      else
     5474          V_R8(pVarDst) = l64;
     5475      return S_OK;
     5476    }
     5477    TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
     5478    return DISP_E_OVERFLOW;
     5479  }
     5480
     5481  /* Count the number of relevant fractional and whole digits stored,
     5482   * And compute the divisor/multiplier to scale the number by.
     5483   */
     5484  if (pNumprs->nPwr10 < 0)
     5485  {
     5486    if (-pNumprs->nPwr10 >= pNumprs->cDig)
     5487    {
     5488      /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
     5489      wholeNumberDigits = 0;
     5490      fractionalDigits = pNumprs->cDig;
     5491      divisor10 = -pNumprs->nPwr10;
     5492    }
     5493    else
     5494    {
     5495      /* An exactly represented real number e.g. 1.024 */
     5496      wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10;
     5497      fractionalDigits = pNumprs->cDig - wholeNumberDigits;
     5498      divisor10 = pNumprs->cDig - wholeNumberDigits;
     5499    }
     5500  }
     5501  else if (pNumprs->nPwr10 == 0)
     5502  {
     5503    /* An exactly represented whole number e.g. 1024 */
     5504    wholeNumberDigits = pNumprs->cDig;
     5505    fractionalDigits = 0;
     5506  }
     5507  else /* pNumprs->nPwr10 > 0 */
     5508  {
     5509    /* A whole number followed by nPwr10 0's e.g. 102400 */
     5510    wholeNumberDigits = pNumprs->cDig;
     5511    fractionalDigits = 0;
     5512    multiplier10 = pNumprs->nPwr10;
     5513  }
     5514
     5515  TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", pNumprs->cDig,
     5516        pNumprs->nPwr10, wholeNumberDigits, fractionalDigits);
     5517  TRACE("mult %d; div %d\n", multiplier10, divisor10);
     5518
     5519  if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) &&
     5520      (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL))))
     5521  {
     5522    /* We have one or more integer output choices, and either:
     5523     *  1) An integer input value, or
     5524     *  2) A real number input value but no floating output choices.
     5525     * Alternately, we have a DECIMAL output available and an integer input.
     5526     *
     5527     * So, place the integer value into pVarDst, using the smallest type
     5528     * possible and preferring signed over unsigned types.
     5529     */
     5530    BOOL bOverflow = FALSE, bNegative;
     5531    ULONG64 ul64 = 0;
     5532    int i;
     5533
     5534    /* Convert the integer part of the number into a UI8 */
     5535    for (i = 0; i < wholeNumberDigits; i++)
     5536    {
     5537      if (ul64 > (UI8_MAX / 10 - rgbDig[i]))
     5538      {
     5539        TRACE("Overflow multiplying digits\n");
     5540        bOverflow = TRUE;
     5541        break;
     5542      }
     5543      ul64 = ul64 * 10 + rgbDig[i];
     5544    }
     5545
     5546    /* Account for the scale of the number */
     5547    if (!bOverflow && multiplier10)
     5548    {
     5549      for (i = 0; i < multiplier10; i++)
     5550      {
     5551        if (ul64 > (UI8_MAX / 10))
     5552        {
     5553          TRACE("Overflow scaling number\n");
     5554          bOverflow = TRUE;
     5555          break;
     5556        }
     5557        ul64 = ul64 * 10;
     5558      }
     5559    }
     5560
     5561    /* If we have any fractional digits, round the value.
     5562     * Note we don't have to do this if divisor10 is < 1,
     5563     * because this means the fractional part must be < 0.5
     5564     */
     5565    if (!bOverflow && fractionalDigits && divisor10 > 0)
     5566    {
     5567      const BYTE* fracDig = rgbDig + wholeNumberDigits;
     5568      BOOL bAdjust = FALSE;
     5569
     5570      TRACE("first decimal value is %d\n", *fracDig);
     5571
     5572      if (*fracDig > 5)
     5573        bAdjust = TRUE; /* > 0.5 */
     5574      else if (*fracDig == 5)
     5575      {
     5576        for (i = 1; i < fractionalDigits; i++)
     5577        {
     5578          if (fracDig[i])
     5579          {
     5580            bAdjust = TRUE; /* > 0.5 */
     5581            break;
     5582          }
     5583        }
     5584        /* If exactly 0.5, round only odd values */
     5585        if (i == fractionalDigits && (ul64 & 1))
     5586          bAdjust = TRUE;
     5587      }
     5588
     5589      if (bAdjust)
     5590      {
     5591        if (ul64 == UI8_MAX)
     5592        {
     5593          TRACE("Overflow after rounding\n");
     5594          bOverflow = TRUE;
     5595        }
     5596        ul64++;
     5597      }
     5598    }
     5599
     5600    /* Zero is not a negative number */
     5601    bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64 ? TRUE : FALSE;
     5602
     5603    TRACE("Integer value is %lld, bNeg %d\n", ul64, bNegative);
     5604
     5605    /* For negative integers, try the signed types in size order */
     5606    if (!bOverflow && bNegative)
     5607    {
     5608      if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8))
     5609      {
     5610        if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN)
     5611        {
     5612          V_VT(pVarDst) = VT_I1;
     5613          V_I1(pVarDst) = -ul64;
     5614          return S_OK;
     5615        }
     5616        else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN)
     5617        {
     5618          V_VT(pVarDst) = VT_I2;
     5619          V_I2(pVarDst) = -ul64;
     5620          return S_OK;
     5621        }
     5622        else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN))
     5623        {
     5624          V_VT(pVarDst) = VT_I4;
     5625          V_I4(pVarDst) = -ul64;
     5626          return S_OK;
     5627        }
     5628        else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1)
     5629        {
     5630          V_VT(pVarDst) = VT_I8;
     5631          V_I8(pVarDst) = -ul64;
     5632          return S_OK;
     5633        }
     5634        else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
     5635        {
     5636          /* Decimal is only output choice left - fast path */
     5637          V_VT(pVarDst) = VT_DECIMAL;
     5638          DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
     5639          DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
     5640          DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
     5641          return S_OK;
     5642        }
     5643      }
     5644    }
     5645    else if (!bOverflow)
     5646    {
     5647      /* For positive integers, try signed then unsigned types in size order */
     5648      if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX)
     5649      {
     5650        V_VT(pVarDst) = VT_I1;
     5651        V_I1(pVarDst) = ul64;
     5652        return S_OK;
     5653      }
     5654      else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
     5655      {
     5656        V_VT(pVarDst) = VT_UI1;
     5657        V_UI1(pVarDst) = ul64;
     5658        return S_OK;
     5659      }
     5660      else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
     5661      {
     5662        V_VT(pVarDst) = VT_I2;
     5663        V_I2(pVarDst) = ul64;
     5664        return S_OK;
     5665      }
     5666      else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
     5667      {
     5668        V_VT(pVarDst) = VT_UI2;
     5669        V_UI2(pVarDst) = ul64;
     5670        return S_OK;
     5671      }
     5672      else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
     5673      {
     5674        V_VT(pVarDst) = VT_I4;
     5675        V_I4(pVarDst) = ul64;
     5676        return S_OK;
     5677      }
     5678      else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
     5679      {
     5680        V_VT(pVarDst) = VT_UI4;
     5681        V_UI4(pVarDst) = ul64;
     5682        return S_OK;
     5683      }
     5684      else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
     5685      {
     5686        V_VT(pVarDst) = VT_I8;
     5687        V_I8(pVarDst) = ul64;
     5688        return S_OK;
     5689      }
     5690      else if (dwVtBits & VTBIT_UI8)
     5691      {
     5692        V_VT(pVarDst) = VT_UI8;
     5693        V_UI8(pVarDst) = ul64;
     5694        return S_OK;
     5695      }
     5696      else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
     5697      {
     5698        /* Decimal is only output choice left - fast path */
     5699        V_VT(pVarDst) = VT_DECIMAL;
     5700        DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
     5701        DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
     5702        DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
     5703        return S_OK;
     5704      }
     5705    }
     5706  }
     5707
     5708  if (dwVtBits & REAL_VTBITS)
     5709  {
     5710    /* Try to put the number into a float or real */
     5711    BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG;
     5712    double whole = 0.0;
     5713    int i;
     5714
     5715    /* Convert the number into a double */
     5716    for (i = 0; i < pNumprs->cDig; i++)
     5717      whole = whole * 10.0 + rgbDig[i];
     5718
     5719    TRACE("Whole double value is %16.16g\n", whole);
     5720
     5721    /* Account for the scale */
     5722    while (multiplier10 > 10)
     5723    {
     5724      if (whole > dblMaximums[10])
     5725      {
     5726        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
     5727        bOverflow = TRUE;
     5728        break;
     5729      }
     5730      whole = whole * dblMultipliers[10];
     5731      multiplier10 -= 10;
     5732    }
     5733    if (multiplier10)
     5734    {
     5735      if (whole > dblMaximums[multiplier10])
     5736      {
     5737        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
     5738        bOverflow = TRUE;
     5739      }
     5740      else
     5741        whole = whole * dblMultipliers[multiplier10];
     5742    }
     5743
     5744    TRACE("Scaled double value is %16.16g\n", whole);
     5745
     5746    while (divisor10 > 10)
     5747    {
     5748      if (whole < dblMinimums[10])
     5749      {
     5750        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
     5751        bOverflow = TRUE;
     5752        break;
     5753      }
     5754      whole = whole / dblMultipliers[10];
     5755      divisor10 -= 10;
     5756    }
     5757    if (divisor10)
     5758    {
     5759      if (whole < dblMinimums[divisor10])
     5760      {
     5761        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
     5762        bOverflow = TRUE;
     5763      }
     5764      else
     5765        whole = whole / dblMultipliers[divisor10];
     5766    }
     5767    if (!bOverflow)
     5768      TRACE("Final double value is %16.16g\n", whole);
     5769
     5770    if (dwVtBits & VTBIT_R4 &&
     5771        ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0))
     5772    {
     5773      TRACE("Set R4 to final value\n");
     5774      V_VT(pVarDst) = VT_R4; /* Fits into a float */
     5775      V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
     5776      return S_OK;
     5777    }
     5778
     5779    if (dwVtBits & VTBIT_R8)
     5780    {
     5781      TRACE("Set R8 to final value\n");
     5782      V_VT(pVarDst) = VT_R8; /* Fits into a double */
     5783      V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
     5784      return S_OK;
     5785    }
     5786
     5787    if (dwVtBits & VTBIT_CY)
     5788    {
     5789      if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst))))
     5790      {
     5791        V_VT(pVarDst) = VT_CY; /* Fits into a currency */
     5792        TRACE("Set CY to final value\n");
     5793        return S_OK;
     5794      }
     5795      TRACE("Value Overflows CY\n");
     5796    }
     5797  }
     5798
     5799  if (dwVtBits & VTBIT_DECIMAL)
     5800  {
     5801    int i;
     5802    ULONG carry;
     5803    ULONG64 tmp;
     5804    DECIMAL* pDec = &V_DECIMAL(pVarDst);
     5805
     5806    DECIMAL_SETZERO(pDec);
     5807    DEC_LO32(pDec) = 0;
     5808
     5809    if (pNumprs->dwOutFlags & NUMPRS_NEG)
     5810      DEC_SIGN(pDec) = DECIMAL_NEG;
     5811    else
     5812      DEC_SIGN(pDec) = DECIMAL_POS;
     5813
     5814    /* Factor the significant digits */
     5815    for (i = 0; i < pNumprs->cDig; i++)
     5816    {
     5817      tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
     5818      carry = (ULONG)(tmp >> 32);
     5819      DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
     5820      tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
     5821      carry = (ULONG)(tmp >> 32);
     5822      DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
     5823      tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
     5824      DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
     5825
     5826      if (tmp >> 32 & UI4_MAX)
     5827      {
     5828VarNumFromParseNum_DecOverflow:
     5829        TRACE("Overflow\n");
     5830        DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
     5831        return DISP_E_OVERFLOW;
     5832      }
     5833    }
     5834
     5835    /* Account for the scale of the number */
     5836    while (multiplier10 > 0)
     5837    {
     5838      tmp = (ULONG64)DEC_LO32(pDec) * 10;
     5839      carry = (ULONG)(tmp >> 32);
     5840      DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
     5841      tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
     5842      carry = (ULONG)(tmp >> 32);
     5843      DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
     5844      tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
     5845      DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
     5846
     5847      if (tmp >> 32 & UI4_MAX)
     5848        goto VarNumFromParseNum_DecOverflow;
     5849      multiplier10--;
     5850    }
     5851    DEC_SCALE(pDec) = divisor10;
     5852
     5853    V_VT(pVarDst) = VT_DECIMAL;
     5854    return S_OK;
     5855  }
     5856  return DISP_E_OVERFLOW; /* No more output choices */
     5857}
     5858#endif
    45805859
    45815860/**********************************************************************
     
    45965875    return E_NOTIMPL;
    45975876}
     5877
     5878/**********************************************************************
     5879 *              VarFormatNumber [OLEAUT32.107]
     5880 */
     5881HRESULT WINAPI VarFormatNumber(LPVARIANT pvarIn, int iNumDig, int iIncLead, int iUseParens, int iGroup, ULONG dwFlags, BSTR* pbstrOut)
     5882{
     5883  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     5884  return E_NOTIMPL;
     5885}
     5886
     5887
     5888/**********************************************************************
     5889 *              VarFormatPercent [OLEAUT32.117]
     5890 */
     5891HRESULT WINAPI VarFormatPercent(LPVARIANT pvarIn, int iNumDig, int iIncLead, int iUseParens, int iGroup, ULONG dwFlags, BSTR* pbstrOut)
     5892{
     5893  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     5894  return E_NOTIMPL;
     5895}
     5896
     5897
     5898/**********************************************************************
     5899 *              VarWeekdayName [OLEAUT32.128]
     5900 */
     5901HRESULT WINAPI VarWeekdayName(int iWeekday, int fAbbrey, int iFirstDay, ULONG dwFlags, BSTR* pbstrOut)
     5902{
     5903  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     5904  return E_NOTIMPL;
     5905}
     5906
     5907
     5908/**********************************************************************
     5909 *              VarMonthName [OLEAUT32.129]
     5910 */
     5911HRESULT WINAPI VarMonthName(int iMonth, int fAbbrey, ULONG dwFlags, BSTR* pbstrOut)
     5912{
     5913  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     5914  return E_NOTIMPL;
     5915}
     5916
    45985917
    45995918/**********************************************************************
     
    50206339    case VT_UI4  : rVal = V_UNION(right,ulVal); break;
    50216340    case VT_UINT : rVal = V_UNION(right,ulVal); break;
     6341#ifdef __WIN32OS2__
     6342    case VT_R8   : rVal = V_UNION(right,dblVal); break;
     6343#endif
    50226344    default: rOk = FALSE;
    50236345    }
     
    51076429
    51086430/**********************************************************************
     6431 *              VarOr [OLEAUT32.157]
     6432 *
     6433 * Perform a logical or (OR) operation on two variants.
     6434 *
     6435 * PARAMS
     6436 *  pVarLeft  [I] First variant
     6437 *  pVarRight [I] Variant to OR with pVarLeft
     6438 *  pVarOut   [O] Destination for OR result
     6439 *
     6440 * RETURNS
     6441 *  Success: S_OK. pVarOut contains the result of the operation with its type
     6442 *           taken from the table listed under VarXor().
     6443 *  Failure: An HRESULT error code indicating the error.
     6444 *
     6445 * NOTES
     6446 *  See the Notes section of VarXor() for further information.
     6447 */
     6448HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
     6449{
     6450  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6451  return E_NOTIMPL;
     6452
     6453
     6454#if 0
     6455    VARTYPE vt = VT_I4;
     6456    VARIANT varLeft, varRight, varStr;
     6457    HRESULT hRet;
     6458
     6459#if 0
     6460    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
     6461          debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
     6462          debugstr_VF(pVarRight), pVarOut);
     6463#endif
     6464    if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
     6465        V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
     6466        V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH ||
     6467        V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD)
     6468        return DISP_E_BADVARTYPE;
     6469
     6470    V_VT(&varLeft) = V_VT(&varRight) = V_VT(&varStr) = VT_EMPTY;
     6471
     6472    if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
     6473    {
     6474        /* NULL OR Zero is NULL, NULL OR value is value */
     6475        if (V_VT(pVarLeft) == VT_NULL)
     6476            pVarLeft = pVarRight; /* point to the non-NULL var */
     6477
     6478        V_VT(pVarOut) = VT_NULL;
     6479        V_I4(pVarOut) = 0;
     6480
     6481        switch (V_VT(pVarLeft))
     6482        {
     6483        case VT_DATE: case VT_R8:
     6484            if (V_R8(pVarLeft))
     6485                goto VarOr_AsEmpty;
     6486            return S_OK;
     6487        case VT_BOOL:
     6488            if (V_BOOL(pVarLeft))
     6489                *pVarOut = *pVarLeft;
     6490            return S_OK;
     6491         case VT_I2: case VT_UI2:
     6492            if (V_I2(pVarLeft))
     6493                goto VarOr_AsEmpty;
     6494            return S_OK;
     6495        case VT_I1:
     6496            if (V_I1(pVarLeft))
     6497                goto VarOr_AsEmpty;
     6498            return S_OK;
     6499        case VT_UI1:
     6500            if (V_UI1(pVarLeft))
     6501                *pVarOut = *pVarLeft;
     6502            return S_OK;
     6503        case VT_R4:
     6504            if (V_R4(pVarLeft))
     6505                goto VarOr_AsEmpty;
     6506            return S_OK;
     6507        case VT_I4: case VT_UI4: case VT_INT: case VT_UINT:
     6508            if (V_I4(pVarLeft))
     6509                goto VarOr_AsEmpty;
     6510            return S_OK;
     6511        case VT_CY:
     6512            if (V_CY(pVarLeft).int64)
     6513                goto VarOr_AsEmpty;
     6514            return S_OK;
     6515        case VT_I8: case VT_UI8:
     6516            if (V_I8(pVarLeft))
     6517                goto VarOr_AsEmpty;
     6518            return S_OK;
     6519        case VT_DECIMAL:
     6520            if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft)))
     6521                goto VarOr_AsEmpty;
     6522            return S_OK;
     6523        case VT_BSTR:
     6524        {
     6525            VARIANT_BOOL b;
     6526
     6527            if (!V_BSTR(pVarLeft))
     6528                return DISP_E_BADVARTYPE;
     6529
     6530            hRet = VarBoolFromStr(V_BSTR(pVarLeft), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
     6531            if (SUCCEEDED(hRet) && b)
     6532            {
     6533                V_VT(pVarOut) = VT_BOOL;
     6534                V_BOOL(pVarOut) = b;
     6535            }
     6536            return hRet;
     6537        }
     6538        case VT_NULL: case VT_EMPTY:
     6539            V_VT(pVarOut) = VT_NULL;
     6540            return S_OK;
     6541        default:
     6542            return DISP_E_BADVARTYPE;
     6543        }
     6544    }
     6545
     6546    if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY)
     6547    {
     6548        if (V_VT(pVarLeft) == VT_EMPTY)
     6549            pVarLeft = pVarRight; /* point to the non-EMPTY var */
     6550
     6551VarOr_AsEmpty:
     6552        /* Since one argument is empty (0), OR'ing it with the other simply
     6553         * gives the others value (as 0|x => x). So just convert the other
     6554         * argument to the required result type.
     6555         */
     6556        switch (V_VT(pVarLeft))
     6557        {
     6558        case VT_BSTR:
     6559            if (!V_BSTR(pVarLeft))
     6560                return DISP_E_BADVARTYPE;
     6561
     6562            hRet = VariantCopy(&varStr, pVarLeft);
     6563            if (FAILED(hRet))
     6564                goto VarOr_Exit;
     6565            pVarLeft = &varStr;
     6566            hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
     6567            if (FAILED(hRet))
     6568                goto VarOr_Exit;
     6569            /* Fall Through ... */
     6570        case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2:
     6571            V_VT(pVarOut) = VT_I2;
     6572            break;
     6573        case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8:
     6574        case VT_I1: case VT_UI2: case VT_I4: case VT_UI4:
     6575        case VT_INT: case VT_UINT: case VT_UI8:
     6576            V_VT(pVarOut) = VT_I4;
     6577            break;
     6578        case VT_I8:
     6579            V_VT(pVarOut) = VT_I8;
     6580            break;
     6581        default:
     6582            return DISP_E_BADVARTYPE;
     6583        }
     6584        hRet = VariantCopy(&varLeft, pVarLeft);
     6585        if (FAILED(hRet))
     6586            goto VarOr_Exit;
     6587        pVarLeft = &varLeft;
     6588        hRet = VariantChangeType(pVarOut, pVarLeft, 0, V_VT(pVarOut));
     6589        goto VarOr_Exit;
     6590    }
     6591
     6592    if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL)
     6593    {
     6594        V_VT(pVarOut) = VT_BOOL;
     6595        V_BOOL(pVarOut) = V_BOOL(pVarLeft) | V_BOOL(pVarRight);
     6596        return S_OK;
     6597    }
     6598
     6599    if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1)
     6600    {
     6601        V_VT(pVarOut) = VT_UI1;
     6602        V_UI1(pVarOut) = V_UI1(pVarLeft) | V_UI1(pVarRight);
     6603        return S_OK;
     6604    }
     6605
     6606    if (V_VT(pVarLeft) == VT_BSTR)
     6607    {
     6608        hRet = VariantCopy(&varStr, pVarLeft);
     6609        if (FAILED(hRet))
     6610            goto VarOr_Exit;
     6611        pVarLeft = &varStr;
     6612        hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
     6613        if (FAILED(hRet))
     6614            goto VarOr_Exit;
     6615    }
     6616
     6617    if (V_VT(pVarLeft) == VT_BOOL &&
     6618        (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_BSTR))
     6619    {
     6620        vt = VT_BOOL;
     6621    }
     6622    else if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 ||
     6623        V_VT(pVarLeft) == VT_I2 || V_VT(pVarLeft) == VT_BSTR) &&
     6624        (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 ||
     6625        V_VT(pVarRight) == VT_I2 || V_VT(pVarRight) == VT_BSTR))
     6626    {
     6627        vt = VT_I2;
     6628    }
     6629    else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8)
     6630    {
     6631        if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
     6632            return DISP_E_TYPEMISMATCH;
     6633        vt = VT_I8;
     6634    }
     6635
     6636    hRet = VariantCopy(&varLeft, pVarLeft);
     6637    if (FAILED(hRet))
     6638        goto VarOr_Exit;
     6639
     6640    hRet = VariantCopy(&varRight, pVarRight);
     6641    if (FAILED(hRet))
     6642        goto VarOr_Exit;
     6643
     6644    if (vt == VT_I4 && V_VT(&varLeft) == VT_UI4)
     6645        V_VT(&varLeft) = VT_I4; /* Don't overflow */
     6646    else
     6647    {
     6648        double d;
     6649
     6650        if (V_VT(&varLeft) == VT_BSTR &&
     6651            FAILED(VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d)))
     6652            hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, VT_BOOL);
     6653        if (SUCCEEDED(hRet) && V_VT(&varLeft) != vt)
     6654            hRet = VariantChangeType(&varLeft, &varLeft, 0, vt);
     6655        if (FAILED(hRet))
     6656            goto VarOr_Exit;
     6657    }
     6658
     6659    if (vt == VT_I4 && V_VT(&varRight) == VT_UI4)
     6660        V_VT(&varRight) = VT_I4; /* Don't overflow */
     6661    else
     6662    {
     6663        double d;
     6664
     6665        if (V_VT(&varRight) == VT_BSTR &&
     6666            FAILED(VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d)))
     6667            hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, VT_BOOL);
     6668        if (SUCCEEDED(hRet) && V_VT(&varRight) != vt)
     6669            hRet = VariantChangeType(&varRight, &varRight, 0, vt);
     6670        if (FAILED(hRet))
     6671            goto VarOr_Exit;
     6672    }
     6673
     6674    V_VT(pVarOut) = vt;
     6675    if (vt == VT_I8)
     6676    {
     6677        V_I8(pVarOut) = V_I8(&varLeft) | V_I8(&varRight);
     6678    }
     6679    else if (vt == VT_I4)
     6680    {
     6681        V_I4(pVarOut) = V_I4(&varLeft) | V_I4(&varRight);
     6682    }
     6683    else
     6684    {
     6685        V_I2(pVarOut) = V_I2(&varLeft) | V_I2(&varRight);
     6686    }
     6687
     6688VarOr_Exit:
     6689    VariantClear(&varStr);
     6690    VariantClear(&varLeft);
     6691    VariantClear(&varRight);
     6692    return hRet;
     6693#endif
     6694}
     6695
     6696
     6697/**********************************************************************
     6698 *              VarXor [OLEAUT32.167]
     6699 */
     6700HRESULT WINAPI VarXor(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
     6701{
     6702  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6703
     6704  return E_NOTIMPL;
     6705}
     6706
     6707/**********************************************************************
    51096708 *              VarNot [OLEAUT32.174]
    51106709 *
     
    51336732    TRACE("rc=%d, Result:\n", (int) rc);
    51346733    dump_Variant(result);
     6734    return rc;
     6735}
     6736
     6737/**********************************************************************
     6738 *              VarNeg [OLEAUT32.173]
     6739 *
     6740 * Negate the value of a variant.
     6741 *
     6742 * PARAMS
     6743 *  pVarIn  [I] Source variant
     6744 *  pVarOut [O] Destination for converted value
     6745 *
     6746 * RETURNS
     6747 *  Success: S_OK. pVarOut contains the converted value.
     6748 *  Failure: An HRESULT error code indicating the error.
     6749 *
     6750 * NOTES
     6751 *  - The type of the value stored in pVarOut depends on the type of pVarIn,
     6752 *    according to the following table:
     6753 *| Input Type       Output Type
     6754 *| ----------       -----------
     6755 *|  VT_EMPTY         VT_I2
     6756 *|  VT_UI1           VT_I2
     6757 *|  VT_BOOL          VT_I2
     6758 *|  VT_BSTR          VT_R8
     6759 *|  All Others       Unchanged (unless promoted)
     6760 *  - Where the negated value of a variant does not fit in its base type, the type
     6761 *    is promoted according to the following table:
     6762 *| Input Type       Promoted To
     6763 *| ----------       -----------
     6764 *|   VT_I2            VT_I4
     6765 *|   VT_I4            VT_R8
     6766 *|   VT_I8            VT_R8
     6767 *  - The native version of this function returns DISP_E_BADVARTYPE for valid
     6768 *    variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH
     6769 *    for types which are not valid. Since this is in contravention of the
     6770 *    meaning of those error codes and unlikely to be relied on by applications,
     6771 *    this implementation returns errors consistent with the other high level
     6772 *    variant math functions.
     6773 */
     6774HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut)
     6775{
     6776  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6777  return E_NOTIMPL;
     6778}
     6779
     6780/**********************************************************************
     6781 * VarAbs [OLEAUT32.168]
     6782 *
     6783 * Convert a variant to its absolute value.
     6784 *
     6785 * PARAMS
     6786 *  pVarIn  [I] Source variant
     6787 *  pVarOut [O] Destination for converted value
     6788 *
     6789 * RETURNS
     6790 *  Success: S_OK. pVarOut contains the absolute value of pVarIn.
     6791 *  Failure: An HRESULT error code indicating the error.
     6792 *
     6793 * NOTES
     6794 *  - This function does not process by-reference variants.
     6795 *  - The type of the value stored in pVarOut depends on the type of pVarIn,
     6796 *    according to the following table:
     6797 *| Input Type       Output Type
     6798 *| ----------       -----------
     6799 *| VT_BOOL          VT_I2
     6800 *| VT_BSTR          VT_R8
     6801 *| (All others)     Unchanged
     6802 */
     6803HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut)
     6804{
     6805  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6806  return E_NOTIMPL;
     6807}
     6808
     6809/**********************************************************************
     6810 *              VarFix [OLEAUT32.169]
     6811 */
     6812HRESULT WINAPI VarFix(LPVARIANT pvarIn, LPVARIANT pvarResult)
     6813{
     6814  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6815  return E_NOTIMPL;
     6816}
     6817
     6818/**********************************************************************
     6819 *              VarInt [OLEAUT32.172]
     6820 */
     6821HRESULT WINAPI VarInt(LPVARIANT pvarIn, LPVARIANT pvarResult)
     6822{
     6823  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6824  return E_NOTIMPL;
     6825}
     6826
     6827/**********************************************************************
     6828 *              VarImp [OLEAUT32.154]
     6829 */
     6830HRESULT WINAPI VarImp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
     6831{
     6832  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6833  return E_NOTIMPL;
     6834}
     6835
     6836/**********************************************************************
     6837 *              VarMod [OLEAUT32.155]
     6838 */
     6839HRESULT WINAPI VarMod(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
     6840{
     6841  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6842  return E_NOTIMPL;
     6843}
     6844
     6845/**********************************************************************
     6846 *              VarEqv [OLEAUT32.152]
     6847 *
     6848 * Determine if two variants contain the same value.
     6849 *
     6850 * PARAMS
     6851 *  pVarLeft  [I] First variant to compare
     6852 *  pVarRight [I] Variant to compare to pVarLeft
     6853 *  pVarOut   [O] Destination for comparison result
     6854 *
     6855 * RETURNS
     6856 *  Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE
     6857 *           if equivalent or non-zero otherwise.
     6858 *  Failure: An HRESULT error code indicating the error.
     6859 *
     6860 * NOTES
     6861 *  - This function simply calls VarXor() on pVarLeft and pVarRight and inverts
     6862 *    the result.
     6863 */
     6864HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
     6865{
     6866  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6867  return E_NOTIMPL;
     6868}
     6869
     6870
     6871/**********************************************************************
     6872 *              VarIdiv [OLEAUT32.153]
     6873 */
     6874HRESULT WINAPI VarIdiv(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
     6875{
     6876  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6877
     6878  return E_NOTIMPL;
     6879}
     6880
     6881/**********************************************************************
     6882 *              VarRound [OLEAUT32.175]
     6883 */
     6884HRESULT VarRound(LPVARIANT  pvarIn, INT cDecimals, LPVARIANT  pvarResult)
     6885{
     6886  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     6887
     6888  return E_NOTIMPL;
     6889}
     6890
     6891/**********************************************************************
     6892 *              VarPow [OLEAUT32.158]
     6893 *
     6894 */
     6895HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result)
     6896{
     6897    HRESULT hr;
     6898    VARIANT dl,dr;
     6899
     6900#if 0
     6901    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left),
     6902          right, debugstr_VT(right), debugstr_VF(right), result);
     6903#endif
     6904
     6905    hr = VariantChangeType(&dl,left,0,VT_R8);
     6906    if (!SUCCEEDED(hr)) {
     6907        ERR("Could not change passed left argument to VT_R8, handle it differently.\n");
     6908        return E_FAIL;
     6909    }
     6910    hr = VariantChangeType(&dr,right,0,VT_R8);
     6911    if (!SUCCEEDED(hr)) {
     6912        ERR("Could not change passed right argument to VT_R8, handle it differently.\n");
     6913        return E_FAIL;
     6914    }
     6915    V_VT(result) = VT_R8;
     6916    V_R8(result) = pow(V_R8(&dl),V_R8(&dr));
     6917    return S_OK;
     6918}
     6919
     6920/**********************************************************************
     6921 *              VarAdd [OLEAUT32.141]
     6922 * FIXME: From MSDN: If ... Then
     6923 * Both expressions are of the string type Concatenated.
     6924 * One expression is a string type and the other a character Addition.
     6925 * One expression is numeric and the other is a string Addition.
     6926 * Both expressions are numeric Addition.
     6927 * Either expression is NULL NULL is returned.
     6928 * Both expressions are empty  Integer subtype is returned.
     6929 *
     6930 */
     6931HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
     6932{
     6933    HRESULT rc = E_FAIL;
     6934
     6935#if 0
     6936    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
     6937          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
     6938#endif
     6939
     6940    if ((V_VT(left)&VT_TYPEMASK) == VT_EMPTY)
     6941        return VariantCopy(result,right);
     6942
     6943    if ((V_VT(right)&VT_TYPEMASK) == VT_EMPTY)
     6944        return VariantCopy(result,left);
     6945
     6946    /* check if we add doubles */
     6947    if (((V_VT(left)&VT_TYPEMASK) == VT_R8) || ((V_VT(right)&VT_TYPEMASK) == VT_R8)) {
     6948        BOOL         lOk        = TRUE;
     6949        BOOL         rOk        = TRUE;
     6950        double       lVal = -1;
     6951        double       rVal = -1;
     6952        double       res  = -1;
     6953
     6954        lOk = TRUE;
     6955        switch (V_VT(left)&VT_TYPEMASK) {
     6956        case VT_I1   : lVal = V_UNION(left,cVal);   break;
     6957        case VT_I2   : lVal = V_UNION(left,iVal);   break;
     6958        case VT_I4   : lVal = V_UNION(left,lVal);   break;
     6959        case VT_INT  : lVal = V_UNION(left,lVal);   break;
     6960        case VT_UI1  : lVal = V_UNION(left,bVal);   break;
     6961        case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
     6962        case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
     6963        case VT_UINT : lVal = V_UNION(left,ulVal);  break;
     6964        case VT_R4   : lVal = V_UNION(left,fltVal);  break;
     6965        case VT_R8   : lVal = V_UNION(left,dblVal);  break;
     6966        case VT_NULL : lVal = 0.0;  break;
     6967        default: lOk = FALSE;
     6968        }
     6969
     6970        rOk = TRUE;
     6971        switch (V_VT(right)&VT_TYPEMASK) {
     6972        case VT_I1   : rVal = V_UNION(right,cVal);  break;
     6973        case VT_I2   : rVal = V_UNION(right,iVal);  break;
     6974        case VT_I4   : rVal = V_UNION(right,lVal);  break;
     6975        case VT_INT  : rVal = V_UNION(right,lVal);  break;
     6976        case VT_UI1  : rVal = V_UNION(right,bVal);  break;
     6977        case VT_UI2  : rVal = V_UNION(right,uiVal); break;
     6978        case VT_UI4  : rVal = V_UNION(right,ulVal); break;
     6979        case VT_UINT : rVal = V_UNION(right,ulVal); break;
     6980        case VT_R4   : rVal = V_UNION(right,fltVal);break;
     6981        case VT_R8   : rVal = V_UNION(right,dblVal);break;
     6982        case VT_NULL : rVal = 0.0; break;
     6983        default: rOk = FALSE;
     6984        }
     6985
     6986        if (lOk && rOk) {
     6987            res = (lVal + rVal);
     6988            V_VT(result) = VT_R8;
     6989            V_UNION(result,dblVal)  = res;
     6990            rc = S_OK;
     6991        } else {
     6992            FIXME("Unhandled type pair %d / %d in double addition.\n",
     6993                (V_VT(left)&VT_TYPEMASK),
     6994                (V_VT(right)&VT_TYPEMASK)
     6995            );
     6996        }
     6997        return rc;
     6998    }
     6999
     7000    /* now check if we add floats. VT_R8 can no longer happen here! */
     7001    if (((V_VT(left)&VT_TYPEMASK) == VT_R4) || ((V_VT(right)&VT_TYPEMASK) == VT_R4)) {
     7002        BOOL         lOk        = TRUE;
     7003        BOOL         rOk        = TRUE;
     7004        float        lVal = -1;
     7005        float        rVal = -1;
     7006        float        res  = -1;
     7007
     7008        lOk = TRUE;
     7009        switch (V_VT(left)&VT_TYPEMASK) {
     7010        case VT_I1   : lVal = V_UNION(left,cVal);   break;
     7011        case VT_I2   : lVal = V_UNION(left,iVal);   break;
     7012        case VT_I4   : lVal = V_UNION(left,lVal);   break;
     7013        case VT_INT  : lVal = V_UNION(left,lVal);   break;
     7014        case VT_UI1  : lVal = V_UNION(left,bVal);   break;
     7015        case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
     7016        case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
     7017        case VT_UINT : lVal = V_UNION(left,ulVal);  break;
     7018        case VT_R4   : lVal = V_UNION(left,fltVal);  break;
     7019        case VT_NULL : lVal = 0.0;  break;
     7020        default: lOk = FALSE;
     7021        }
     7022
     7023        rOk = TRUE;
     7024        switch (V_VT(right)&VT_TYPEMASK) {
     7025        case VT_I1   : rVal = V_UNION(right,cVal);  break;
     7026        case VT_I2   : rVal = V_UNION(right,iVal);  break;
     7027        case VT_I4   : rVal = V_UNION(right,lVal);  break;
     7028        case VT_INT  : rVal = V_UNION(right,lVal);  break;
     7029        case VT_UI1  : rVal = V_UNION(right,bVal);  break;
     7030        case VT_UI2  : rVal = V_UNION(right,uiVal); break;
     7031        case VT_UI4  : rVal = V_UNION(right,ulVal); break;
     7032        case VT_UINT : rVal = V_UNION(right,ulVal); break;
     7033        case VT_R4   : rVal = V_UNION(right,fltVal);break;
     7034        case VT_NULL : rVal = 0.0; break;
     7035        default: rOk = FALSE;
     7036        }
     7037
     7038        if (lOk && rOk) {
     7039            res = (lVal + rVal);
     7040            V_VT(result) = VT_R4;
     7041            V_UNION(result,fltVal)  = res;
     7042            rc = S_OK;
     7043        } else {
     7044            FIXME("Unhandled type pair %d / %d in float addition.\n",
     7045                (V_VT(left)&VT_TYPEMASK),
     7046                (V_VT(right)&VT_TYPEMASK)
     7047            );
     7048        }
     7049        return rc;
     7050    }
     7051
     7052    /* Handle strings as concat */
     7053    if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR &&
     7054        (V_VT(right)&VT_TYPEMASK) == VT_BSTR) {
     7055        V_VT(result) = VT_BSTR;
     7056        return VarBstrCat(V_BSTR(left), V_BSTR(right), &V_BSTR(result));
     7057    } else {
     7058
     7059        /* Integers */
     7060        BOOL         lOk        = TRUE;
     7061        BOOL         rOk        = TRUE;
     7062        LONGLONG     lVal = -1;
     7063        LONGLONG     rVal = -1;
     7064        LONGLONG     res  = -1;
     7065        int          resT = 0; /* Testing has shown I2 + I2 == I2, all else
     7066                                  becomes I4                                */
     7067
     7068        lOk = TRUE;
     7069        switch (V_VT(left)&VT_TYPEMASK) {
     7070        case VT_I1   : lVal = V_UNION(left,cVal);  resT=VT_I4; break;
     7071        case VT_I2   : lVal = V_UNION(left,iVal);  resT=VT_I2; break;
     7072        case VT_I4   : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
     7073        case VT_INT  : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
     7074        case VT_UI1  : lVal = V_UNION(left,bVal);  resT=VT_I4; break;
     7075        case VT_UI2  : lVal = V_UNION(left,uiVal); resT=VT_I4; break;
     7076        case VT_UI4  : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
     7077        case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
     7078        case VT_NULL : lVal = 0; resT = VT_I4; break;
     7079        default: lOk = FALSE;
     7080        }
     7081
     7082        rOk = TRUE;
     7083        switch (V_VT(right)&VT_TYPEMASK) {
     7084        case VT_I1   : rVal = V_UNION(right,cVal);  resT=VT_I4; break;
     7085        case VT_I2   : rVal = V_UNION(right,iVal);  resT=max(VT_I2, resT); break;
     7086        case VT_I4   : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
     7087        case VT_INT  : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
     7088        case VT_UI1  : rVal = V_UNION(right,bVal);  resT=VT_I4; break;
     7089        case VT_UI2  : rVal = V_UNION(right,uiVal); resT=VT_I4; break;
     7090        case VT_UI4  : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
     7091        case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
     7092        case VT_NULL : rVal = 0; resT=VT_I4; break;
     7093        default: rOk = FALSE;
     7094        }
     7095
     7096        if (lOk && rOk) {
     7097            res = (lVal + rVal);
     7098            V_VT(result) = resT;
     7099            switch (resT) {
     7100            case VT_I2   : V_UNION(result,iVal)  = res; break;
     7101            case VT_I4   : V_UNION(result,lVal)  = res; break;
     7102            default:
     7103                FIXME("Unexpected result variant type %x\n", resT);
     7104                V_UNION(result,lVal)  = res;
     7105            }
     7106            rc = S_OK;
     7107
     7108        } else {
     7109            FIXME("unimplemented part (0x%x + 0x%x)\n",V_VT(left), V_VT(right));
     7110        }
     7111    }
     7112#if 0
     7113    TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
     7114          debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
     7115#endif
     7116    return rc;
     7117}
     7118
     7119/**********************************************************************
     7120 *              VarSub [OLEAUT32.159]
     7121 *
     7122 */
     7123HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
     7124{
     7125    HRESULT rc = E_FAIL;
     7126    VARTYPE lvt,rvt,resvt;
     7127    VARIANT lv,rv;
     7128    BOOL found;
     7129
     7130#if 0
     7131    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
     7132          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
     7133#endif
     7134
     7135    VariantInit(&lv);VariantInit(&rv);
     7136    lvt = V_VT(left)&VT_TYPEMASK;
     7137    rvt = V_VT(right)&VT_TYPEMASK;
     7138    found = FALSE;resvt = VT_VOID;
     7139    if (((1<<lvt) | (1<<rvt)) & ((1<<VT_DATE)|(1<<VT_R4)|(1<<VT_R8))) {
     7140        found = TRUE;
     7141        resvt = VT_R8;
     7142    }
     7143    if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
     7144        found = TRUE;
     7145        resvt = VT_I4;
     7146    }
     7147    if (!found) {
     7148        FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
     7149        return E_FAIL;
     7150    }
     7151    rc = VariantChangeType(&lv, left, 0, resvt);
     7152    if (FAILED(rc)) {
     7153        FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
     7154        return rc;
     7155    }
     7156    rc = VariantChangeType(&rv, right, 0, resvt);
     7157    if (FAILED(rc)) {
     7158        FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
     7159        return rc;
     7160    }
     7161    switch (resvt) {
     7162    case VT_R8:
     7163        V_VT(result) = resvt;
     7164        V_R8(result) = V_R8(&lv) - V_R8(&rv);
     7165        rc = S_OK;
     7166        break;
     7167    case VT_I4:
     7168        V_VT(result) = resvt;
     7169        V_I4(result) = V_I4(&lv) - V_I4(&rv);
     7170        rc = S_OK;
     7171        break;
     7172    }
     7173#if 0
     7174    TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
     7175          debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
     7176#endif
     7177    return rc;
     7178}
     7179
     7180
     7181/**********************************************************************
     7182 *              VarDiv [OLEAUT32.143]
     7183 *
     7184 */
     7185HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
     7186{
     7187    HRESULT rc = E_FAIL;
     7188    VARTYPE lvt,rvt,resvt;
     7189    VARIANT lv,rv;
     7190    BOOL found;
     7191
     7192#if 0
     7193    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
     7194          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
     7195#endif
     7196
     7197    VariantInit(&lv);VariantInit(&rv);
     7198    lvt = V_VT(left)&VT_TYPEMASK;
     7199    rvt = V_VT(right)&VT_TYPEMASK;
     7200    found = FALSE;resvt = VT_VOID;
     7201    if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
     7202        found = TRUE;
     7203        resvt = VT_R8;
     7204    }
     7205    if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
     7206        found = TRUE;
     7207        resvt = VT_I4;
     7208    }
     7209    if (!found) {
     7210        FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
     7211        return E_FAIL;
     7212    }
     7213    rc = VariantChangeType(&lv, left, 0, resvt);
     7214    if (FAILED(rc)) {
     7215        FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
     7216        return rc;
     7217    }
     7218    rc = VariantChangeType(&rv, right, 0, resvt);
     7219    if (FAILED(rc)) {
     7220        FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
     7221        return rc;
     7222    }
     7223    switch (resvt) {
     7224    case VT_R8:
     7225        V_VT(result) = resvt;
     7226        V_R8(result) = V_R8(&lv) / V_R8(&rv);
     7227        rc = S_OK;
     7228        break;
     7229    case VT_I4:
     7230        V_VT(result) = resvt;
     7231        V_I4(result) = V_I4(&lv) / V_I4(&rv);
     7232        rc = S_OK;
     7233        break;
     7234    }
     7235#if 0
     7236    TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
     7237          debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
     7238#endif
     7239    return rc;
     7240}
     7241
     7242/**********************************************************************
     7243 *              VarMul [OLEAUT32.156]
     7244 *
     7245 */
     7246HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
     7247{
     7248    HRESULT rc = E_FAIL;
     7249    VARTYPE lvt,rvt,resvt;
     7250    VARIANT lv,rv;
     7251    BOOL found;
     7252#if 0
     7253    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
     7254          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
     7255#endif
     7256    VariantInit(&lv);VariantInit(&rv);
     7257    lvt = V_VT(left)&VT_TYPEMASK;
     7258    rvt = V_VT(right)&VT_TYPEMASK;
     7259    found = FALSE;resvt=VT_VOID;
     7260    if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
     7261        found = TRUE;
     7262        resvt = VT_R8;
     7263    }
     7264    if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
     7265        found = TRUE;
     7266        resvt = VT_I4;
     7267    }
     7268    if (!found) {
     7269        FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
     7270        return E_FAIL;
     7271    }
     7272    rc = VariantChangeType(&lv, left, 0, resvt);
     7273    if (FAILED(rc)) {
     7274        FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
     7275        return rc;
     7276    }
     7277    rc = VariantChangeType(&rv, right, 0, resvt);
     7278    if (FAILED(rc)) {
     7279        FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
     7280        return rc;
     7281    }
     7282    switch (resvt) {
     7283    case VT_R8:
     7284        V_VT(result) = resvt;
     7285        V_R8(result) = V_R8(&lv) * V_R8(&rv);
     7286        rc = S_OK;
     7287        break;
     7288    case VT_I4:
     7289        V_VT(result) = resvt;
     7290        V_I4(result) = V_I4(&lv) * V_I4(&rv);
     7291        rc = S_OK;
     7292        break;
     7293    }
     7294#if 0
     7295    TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
     7296          debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
     7297#endif
    51357298    return rc;
    51367299}
     
    55747737    return rc;
    55757738}
     7739
     7740
     7741/**********************************************************************
     7742 *              VarDecAdd [OLEAUT32.177]
     7743 */
     7744HRESULT WINAPI VarDecAdd(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
     7745{
     7746  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7747  return E_NOTIMPL;
     7748}
     7749
     7750/**********************************************************************
     7751 *              VarDecSub [OLEAUT32.181]
     7752 */
     7753HRESULT WINAPI VarDecSub(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
     7754{
     7755  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7756  return E_NOTIMPL;
     7757}
     7758
     7759/**********************************************************************
     7760 *              VarDecMul [OLEAUT32.179]
     7761 */
     7762HRESULT WINAPI VarDecMul(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
     7763{
     7764  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7765  return E_NOTIMPL;
     7766}
     7767
     7768/**********************************************************************
     7769 *              VarDecRound [OLEAUT32.203]
     7770 */
     7771HRESULT WINAPI VarDecRound(LPDECIMAL pdecIn, int iDecimals, LPDECIMAL  pdecResult)
     7772{
     7773  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7774  return E_NOTIMPL;
     7775}
     7776
     7777/**********************************************************************
     7778 *              VarDecDiv [OLEAUT32.178]
     7779 */
     7780HRESULT WINAPI VarDecDiv(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
     7781{
     7782  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7783  return E_NOTIMPL;
     7784}
     7785
     7786/**********************************************************************
     7787 *              VarDecCmp [OLEAUT32.204]
     7788 */
     7789HRESULT WINAPI VarDecCmp(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight)
     7790{
     7791  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7792  return E_NOTIMPL;
     7793}
     7794
     7795/**********************************************************************
     7796 *              VarDecAbs [OLEAUT32.182]
     7797 */
     7798HRESULT WINAPI VarDecAbs(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
     7799{
     7800  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7801  return E_NOTIMPL;
     7802}
     7803
     7804/**********************************************************************
     7805 *              VarDecFix [OLEAUT32.187]
     7806 */
     7807HRESULT WINAPI VarDecFix(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
     7808{
     7809  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7810  return E_NOTIMPL;
     7811}
     7812
     7813/**********************************************************************
     7814 *              VarDecInt [OLEAUT32.188]
     7815 */
     7816HRESULT WINAPI VarDecInt(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
     7817{
     7818  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7819  return E_NOTIMPL;
     7820}
     7821
     7822
     7823/**********************************************************************
     7824 *              VarDecNeg [OLEAUT32.189]
     7825 */
     7826HRESULT WINAPI VarDecNeg(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
     7827{
     7828  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7829  return E_NOTIMPL;
     7830}
     7831
     7832/**********************************************************************
     7833 *              VarDecCmpR8 [OLEAUT32.298]
     7834 */
     7835HRESULT WINAPI VarDecCmpR8(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight)
     7836{
     7837  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
     7838  return E_NOTIMPL;
     7839}
     7840
     7841/************************************************************************
     7842 * VarDecFromStr (OLEAUT32.197)
     7843 *
     7844 * Convert a VT_BSTR to a DECIMAL.
     7845 *
     7846 * PARAMS
     7847 *  strIn   [I] Source
     7848 *  lcid    [I] LCID for the conversion
     7849 *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
     7850 *  pDecOut [O] Destination
     7851 *
     7852 * RETURNS
     7853 *  Success: S_OK.
     7854 *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
     7855 */
     7856HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
     7857{
     7858  TRACE("%s: now calling VARIANT_NumberFromBstr\n", __FUNCTION__);
     7859  return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
     7860}
     7861
Note: See TracChangeset for help on using the changeset viewer.