Changeset 21308 for trunk/src/oleaut32/variant.c
- Timestamp:
- Jun 18, 2009, 6:27:45 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/oleaut32/variant.c
r10629 r21308 201 201 {0x00 , 0, 0 , VT_NULL} 202 202 }; 203 204 205 /************** Form wine: oleaut32/variant.h **************/206 207 /* Value of sign for a positive decimal number */208 #define DECIMAL_POS 0209 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 once213 * to values other than 0.214 */215 #ifdef WORDS_BIGENDIAN216 #define SIGNSCALE(sign,scale) (((scale) << 8) | sign)217 #else218 #define SIGNSCALE(sign,scale) (((sign) << 8) | scale)219 #endif220 /* 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_CHARS241 {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 #else261 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)262 {263 #endif264 265 do266 {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 * PARAMS304 * pDecIn [I] Source305 * lcid [I] LCID for the conversion306 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")307 * pbstrOut [O] Destination308 *309 * RETURNS310 * 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 #else332 szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);333 #endif334 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 #else371 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 #endif375 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 410 203 411 204 /****************************************************************************** … … 2039 1832 void WINAPI VariantInit(VARIANTARG* pvarg) 2040 1833 { 2041 TRACE(" %s: (%p)\n", __FUNCTION__,pvarg);1834 TRACE("(%p)\n",pvarg); 2042 1835 2043 1836 memset(pvarg, 0, sizeof (VARIANTARG)); … … 2058 1851 { 2059 1852 HRESULT res = S_OK; 2060 TRACE(" %s: (%p)\n",__FUNCTION__,pvarg);1853 TRACE("(%p)\n",pvarg); 2061 1854 2062 1855 res = ValidateVariantType( V_VT(pvarg) ); … … 2118 1911 HRESULT res = S_OK; 2119 1912 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)); 2121 1914 2122 1915 res = ValidateVariantType( V_VT(pvargSrc) ); … … 2339 2132 VARIANTARG varg; 2340 2133 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)); 2342 2136 TRACE("Src Var:\n"); 2343 2137 dump_Variant(pvargSrc); … … 2376 2170 */ 2377 2171 VARIANTARG Variant; 2378 2379 2172 VariantInit( &Variant ); 2380 2173 res = VariantCopyInd( &Variant, pvargSrc ); … … 2386 2179 VariantClear( &Variant ); 2387 2180 } 2181 2388 2182 } 2389 2183 else … … 2403 2197 V_VT(pvargDest) = vt; 2404 2198 2405 TRACE("Dest Var (re: %x)\n", res);2199 TRACE("Dest Var:\n"); 2406 2200 dump_Variant(pvargDest); 2407 2201 … … 2981 2775 LPSTR pNewString = NULL; 2982 2776 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 ); 2984 2778 2985 2779 /* Check if we have a valid argument … … 3305 3099 } 3306 3100 3307 #if 03308 3101 /****************************************************************************** 3309 3102 * VarR8FromStr [OLEAUT32.84] … … 3336 3129 3337 3130 return S_OK; 3338 }3339 #endif3340 3341 /************************************************************************3342 * VarR8FromStr (OLEAUT32.84)3343 *3344 * Convert a VT_BSTR to a VT_R8.3345 *3346 * PARAMS3347 * strIn [I] Source3348 * lcid [I] LCID for the conversion3349 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")3350 * pDblOut [O] Destination3351 *3352 * RETURNS3353 * Success: S_OK.3354 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.3355 * DISP_E_TYPEMISMATCH, if the type cannot be converted3356 */3357 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)3358 {3359 return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);3360 3131 } 3361 3132 … … 3562 3333 return S_OK; 3563 3334 } 3564 3565 3566 3335 3567 3336 /****************************************************************************** … … 4716 4485 4717 4486 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 0x14756 #define B_NEGATIVE_EXPONENT 0x24757 #define B_EXPONENT_START 0x44758 #define B_INEXACT_ZEROS 0x84759 #define B_LEADING_ZERO 0x104760 #define B_PROCESSING_HEX 0x204761 #define B_PROCESSING_OCT 0x404762 /**********************************************************************4763 * VarParseNumFromStr [OLEAUT32.46]4764 *4765 * Parse a string containing a number into a NUMPARSE structure.4766 *4767 * PARAMS4768 * lpszStr [I] String to parse number from4769 * lcid [I] Locale Id for the conversion4770 * dwFlags [I] 0, or LOCALE_NOUSEROVERRIDE to use system default number chars4771 * pNumprs [I/O] Destination for parsed number4772 * rgbDig [O] Destination for digits read in4773 *4774 * RETURNS4775 * Success: S_OK. pNumprs and rgbDig contain the parsed representation of4776 * the number.4777 * Failure: E_INVALIDARG, if any parameter is invalid.4778 * DISP_E_TYPEMISMATCH, if the string is not a number or is formatted4779 * incorrectly.4780 * DISP_E_OVERFLOW, if rgbDig is too small to hold the number.4781 *4782 * NOTES4783 * 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_ flags4786 * from "oleauto.h".4787 *4788 * FIXME4789 * - 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 do4827 {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 else4868 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 else4941 {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 else4954 pNumprs->nPwr10++;4955 }4956 else4957 {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 else5027 {5028 if (*lpszStr >= 'a')5029 rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;5030 else5031 rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;5032 }5033 pNumprs->cDig++;5034 cchUsed++;5035 }5036 else5037 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 else5081 pNumprs->nPwr10++;5082 5083 pNumprs->cDig--;5084 }5085 }5086 }5087 } else5088 {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 else5095 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 else5104 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 do5116 {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 else5145 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 05167 4487 /********************************************************************** 5168 4488 * VarParseNumFromStr [OLEAUT32.46] … … 5204 4524 return S_OK; 5205 4525 } 5206 #endif5207 4526 5208 4527 5209 4528 /********************************************************************** 5210 4529 * VarNumFromParseNum [OLEAUT32.47] 5211 *5212 * Convert a NUMPARSE structure into a numeric Variant type.5213 *5214 * PARAMS5215 * pNumprs [I] Source for parsed number. cDig must be set to the size of rgbDig5216 * rgbDig [I] Source for the numbers digits5217 * dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types5218 * pVarDst [O] Destination for the converted Variant value.5219 *5220 * RETURNS5221 * 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 * NOTES5226 * - The smallest favoured type present in dwVtBits that can represent the5227 * 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.5233 4530 */ 5234 4531 HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig, 5235 4532 ULONG dwVtBits, VARIANT * pvar) 5236 4533 { 5237 #ifdef __WIN32OS2__5238 4534 DWORD xint; 5239 4535 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); 5243 4537 5244 4538 xint = 0; 5245 4539 for (i=0;i<pnumprs->cDig;i++) 5246 4540 xint = xint*10 + rgbDig[i]; 5247 4541 5248 4542 if (pnumprs->dwOutFlags & NUMPRS_NEG) { 5249 4543 xint = xint * -1; 5250 4544 } 5251 TRACE("%s: xint: %x (%ld)\n", __FUNCTION__, xint, xint);5252 4545 5253 4546 VariantInit(pvar); … … 5281 4574 } 5282 4575 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 else5299 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 05320 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 #endif5329 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);5346 4576 FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint); 5347 4577 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 5859 4580 5860 4581 /********************************************************************** … … 5875 4596 return E_NOTIMPL; 5876 4597 } 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 5917 4598 5918 4599 /********************************************************************** … … 6339 5020 case VT_UI4 : rVal = V_UNION(right,ulVal); break; 6340 5021 case VT_UINT : rVal = V_UNION(right,ulVal); break; 6341 #ifdef __WIN32OS2__6342 case VT_R8 : rVal = V_UNION(right,dblVal); break;6343 #endif6344 5022 default: rOk = FALSE; 6345 5023 } … … 6429 5107 6430 5108 /********************************************************************** 6431 * VarOr [OLEAUT32.157]6432 *6433 * Perform a logical or (OR) operation on two variants.6434 *6435 * PARAMS6436 * pVarLeft [I] First variant6437 * pVarRight [I] Variant to OR with pVarLeft6438 * pVarOut [O] Destination for OR result6439 *6440 * RETURNS6441 * Success: S_OK. pVarOut contains the result of the operation with its type6442 * taken from the table listed under VarXor().6443 * Failure: An HRESULT error code indicating the error.6444 *6445 * NOTES6446 * 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 06455 VARTYPE vt = VT_I4;6456 VARIANT varLeft, varRight, varStr;6457 HRESULT hRet;6458 6459 #if 06460 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 #endif6464 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 simply6553 * gives the others value (as 0|x => x). So just convert the other6554 * 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 else6647 {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 else6662 {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 else6684 {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 #endif6694 }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 /**********************************************************************6708 5109 * VarNot [OLEAUT32.174] 6709 5110 * … … 6732 5133 TRACE("rc=%d, Result:\n", (int) rc); 6733 5134 dump_Variant(result); 6734 return rc;6735 }6736 6737 /**********************************************************************6738 * VarNeg [OLEAUT32.173]6739 *6740 * Negate the value of a variant.6741 *6742 * PARAMS6743 * pVarIn [I] Source variant6744 * pVarOut [O] Destination for converted value6745 *6746 * RETURNS6747 * Success: S_OK. pVarOut contains the converted value.6748 * Failure: An HRESULT error code indicating the error.6749 *6750 * NOTES6751 * - The type of the value stored in pVarOut depends on the type of pVarIn,6752 * according to the following table:6753 *| Input Type Output Type6754 *| ---------- -----------6755 *| VT_EMPTY VT_I26756 *| VT_UI1 VT_I26757 *| VT_BOOL VT_I26758 *| VT_BSTR VT_R86759 *| All Others Unchanged (unless promoted)6760 * - Where the negated value of a variant does not fit in its base type, the type6761 * is promoted according to the following table:6762 *| Input Type Promoted To6763 *| ---------- -----------6764 *| VT_I2 VT_I46765 *| VT_I4 VT_R86766 *| VT_I8 VT_R86767 * - The native version of this function returns DISP_E_BADVARTYPE for valid6768 * variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH6769 * for types which are not valid. Since this is in contravention of the6770 * meaning of those error codes and unlikely to be relied on by applications,6771 * this implementation returns errors consistent with the other high level6772 * 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 * PARAMS6786 * pVarIn [I] Source variant6787 * pVarOut [O] Destination for converted value6788 *6789 * RETURNS6790 * Success: S_OK. pVarOut contains the absolute value of pVarIn.6791 * Failure: An HRESULT error code indicating the error.6792 *6793 * NOTES6794 * - 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 Type6798 *| ---------- -----------6799 *| VT_BOOL VT_I26800 *| VT_BSTR VT_R86801 *| (All others) Unchanged6802 */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 * PARAMS6851 * pVarLeft [I] First variant to compare6852 * pVarRight [I] Variant to compare to pVarLeft6853 * pVarOut [O] Destination for comparison result6854 *6855 * RETURNS6856 * Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE6857 * if equivalent or non-zero otherwise.6858 * Failure: An HRESULT error code indicating the error.6859 *6860 * NOTES6861 * - This function simply calls VarXor() on pVarLeft and pVarRight and inverts6862 * 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 06901 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 #endif6904 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 ... Then6923 * 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 06936 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 #endif6939 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 else7066 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 07113 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 #endif7116 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 07131 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 #endif7134 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 07174 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 #endif7177 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 07193 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 #endif7196 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 07236 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 #endif7239 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 07253 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 #endif7256 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 07295 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 #endif7298 5135 return rc; 7299 5136 } … … 7737 5574 return rc; 7738 5575 } 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 * PARAMS7847 * strIn [I] Source7848 * lcid [I] LCID for the conversion7849 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")7850 * pDecOut [O] Destination7851 *7852 * RETURNS7853 * Success: S_OK.7854 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination7855 */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.