Ignore:
Timestamp:
Jun 18, 2009, 6:27:45 PM (16 years ago)
Author:
ydario
Message:

Minor updates, backout imm changes.

File:
1 edited

Legend:

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

    r10629 r21308  
    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 */
    240 typedef 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 
    252 void 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__
    257 static 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
    261 static 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 */
    278 static 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  */
    314 HRESULT 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. */
    347 static 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 */
    382 HRESULT 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 
    410203
    411204/******************************************************************************
     
    20391832void WINAPI VariantInit(VARIANTARG* pvarg)
    20401833{
    2041   TRACE("%s: (%p)\n", __FUNCTION__, pvarg);
     1834  TRACE("(%p)\n",pvarg);
    20421835
    20431836  memset(pvarg, 0, sizeof (VARIANTARG));
     
    20581851{
    20591852  HRESULT res = S_OK;
    2060   TRACE("%s: (%p)\n",__FUNCTION__, pvarg);
     1853  TRACE("(%p)\n",pvarg);
    20611854
    20621855  res = ValidateVariantType( V_VT(pvarg) );
     
    21181911  HRESULT res = S_OK;
    21191912
    2120   TRACE("%s: (Dest: %p, Src: %p), vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, V_VT(pvargSrc));
     1913  TRACE("(%p, %p), vt=%d\n", pvargDest, pvargSrc, V_VT(pvargSrc));
    21211914
    21221915  res = ValidateVariantType( V_VT(pvargSrc) );
     
    23392132        VARIANTARG varg;
    23402133        VariantInit( &varg );
    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));
     2134
     2135        TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
    23422136    TRACE("Src Var:\n");
    23432137    dump_Variant(pvargSrc);
     
    23762170                         */
    23772171                        VARIANTARG Variant;
    2378 
    23792172                        VariantInit( &Variant );
    23802173                        res = VariantCopyInd( &Variant, pvargSrc );
     
    23862179                                VariantClear( &Variant );
    23872180                        }
     2181
    23882182                }
    23892183                else
     
    24032197                V_VT(pvargDest) = vt;
    24042198
    2405     TRACE("Dest Var (re: %x)\n", res);
     2199    TRACE("Dest Var:\n");
    24062200    dump_Variant(pvargDest);
    24072201
     
    29812775        LPSTR pNewString = NULL;
    29822776
    2983         TRACE("%s: ( strIn: %p -> %s, lcid: 0x%08lx, dwFlags: 0x%08lx, plOut: %p ), stub\n", __FUNCTION__, strIn, debugstr_w(strIn), lcid, dwFlags, plOut );
     2777        TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
    29842778
    29852779        /* Check if we have a valid argument
     
    33053099}
    33063100
    3307 #if 0
    33083101/******************************************************************************
    33093102 *              VarR8FromStr            [OLEAUT32.84]
     
    33363129
    33373130        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  */
    3357 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
    3358 {
    3359   return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
    33603131}
    33613132
     
    35623333   return S_OK;
    35633334}
    3564 
    3565 
    35663335
    35673336/******************************************************************************
     
    47164485
    47174486
    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 */
    4727 void 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  */
    4792 HRESULT 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
    51674487/**********************************************************************
    51684488 *              VarParseNumFromStr [OLEAUT32.46]
     
    52044524    return S_OK;
    52054525}
    5206 #endif
    52074526
    52084527
    52094528/**********************************************************************
    52104529 *              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.
    52334530 */
    52344531HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig,
    52354532                                  ULONG dwVtBits, VARIANT * pvar)
    52364533{
    5237 #ifdef __WIN32OS2__
    52384534    DWORD xint;
    52394535    int i;
    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);
     4536    FIXME("(..,dwVtBits=%lx,....), partial stub!\n",dwVtBits);
    52434537
    52444538    xint = 0;
    52454539    for (i=0;i<pnumprs->cDig;i++)
    5246       xint = xint*10 + rgbDig[i];
     4540        xint = xint*10 + rgbDig[i];
    52474541
    52484542    if (pnumprs->dwOutFlags & NUMPRS_NEG) {
    52494543        xint = xint * -1;
    52504544    }
    5251     TRACE("%s: xint: %x (%ld)\n", __FUNCTION__, xint, xint);
    52524545
    52534546    VariantInit(pvar);
     
    52814574    }
    52824575
    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);
    53464576        FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint);
    53474577        return E_FAIL;
    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       {
    5828 VarNumFromParseNum_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
     4578}
     4579
    58594580
    58604581/**********************************************************************
     
    58754596    return E_NOTIMPL;
    58764597}
    5877 
    5878 /**********************************************************************
    5879  *              VarFormatNumber [OLEAUT32.107]
    5880  */
    5881 HRESULT 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  */
    5891 HRESULT 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  */
    5901 HRESULT 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  */
    5911 HRESULT 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 
    59174598
    59184599/**********************************************************************
     
    63395020    case VT_UI4  : rVal = V_UNION(right,ulVal); break;
    63405021    case VT_UINT : rVal = V_UNION(right,ulVal); break;
    6341 #ifdef __WIN32OS2__
    6342     case VT_R8   : rVal = V_UNION(right,dblVal); break;
    6343 #endif
    63445022    default: rOk = FALSE;
    63455023    }
     
    64295107
    64305108/**********************************************************************
    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  */
    6448 HRESULT 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 
    6551 VarOr_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 
    6688 VarOr_Exit:
    6689     VariantClear(&varStr);
    6690     VariantClear(&varLeft);
    6691     VariantClear(&varRight);
    6692     return hRet;
    6693 #endif
    6694 }
    6695 
    6696 
    6697 /**********************************************************************
    6698  *              VarXor [OLEAUT32.167]
    6699  */
    6700 HRESULT 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 /**********************************************************************
    67085109 *              VarNot [OLEAUT32.174]
    67095110 *
     
    67325133    TRACE("rc=%d, Result:\n", (int) rc);
    67335134    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  */
    6774 HRESULT 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  */
    6803 HRESULT 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  */
    6812 HRESULT 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  */
    6821 HRESULT 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  */
    6830 HRESULT 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  */
    6839 HRESULT 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  */
    6864 HRESULT 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  */
    6874 HRESULT 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  */
    6884 HRESULT 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  */
    6895 HRESULT 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  */
    6931 HRESULT 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  */
    7123 HRESULT 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  */
    7185 HRESULT 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  */
    7246 HRESULT 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
    72985135    return rc;
    72995136}
     
    77375574    return rc;
    77385575}
    7739 
    7740 
    7741 /**********************************************************************
    7742  *              VarDecAdd [OLEAUT32.177]
    7743  */
    7744 HRESULT 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  */
    7753 HRESULT 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  */
    7762 HRESULT 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  */
    7771 HRESULT 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  */
    7780 HRESULT 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  */
    7789 HRESULT 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  */
    7798 HRESULT 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  */
    7807 HRESULT 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  */
    7816 HRESULT 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  */
    7826 HRESULT 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  */
    7835 HRESULT 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  */
    7856 HRESULT 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.