- Timestamp:
- Oct 8, 2004, 11:18:21 AM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/oleaut32/variant.c
r9400 r10629 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 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 203 410 204 411 /****************************************************************************** … … 1832 2039 void WINAPI VariantInit(VARIANTARG* pvarg) 1833 2040 { 1834 TRACE(" (%p)\n",pvarg);2041 TRACE("%s: (%p)\n", __FUNCTION__, pvarg); 1835 2042 1836 2043 memset(pvarg, 0, sizeof (VARIANTARG)); … … 1851 2058 { 1852 2059 HRESULT res = S_OK; 1853 TRACE(" (%p)\n",pvarg);2060 TRACE("%s: (%p)\n",__FUNCTION__, pvarg); 1854 2061 1855 2062 res = ValidateVariantType( V_VT(pvarg) ); … … 1911 2118 HRESULT res = S_OK; 1912 2119 1913 TRACE(" (%p, %p), vt=%d\n", pvargDest, pvargSrc, V_VT(pvargSrc));2120 TRACE("%s: (Dest: %p, Src: %p), vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, V_VT(pvargSrc)); 1914 2121 1915 2122 res = ValidateVariantType( V_VT(pvargSrc) ); … … 2132 2339 VARIANTARG varg; 2133 2340 VariantInit( &varg ); 2134 2135 TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc)); 2341 TRACE("%s: (Dest: %p, source: %p, LCID: %ld, wFlags: %u, VARTYPE: %u) vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc)); 2136 2342 TRACE("Src Var:\n"); 2137 2343 dump_Variant(pvargSrc); … … 2170 2376 */ 2171 2377 VARIANTARG Variant; 2378 2172 2379 VariantInit( &Variant ); 2173 2380 res = VariantCopyInd( &Variant, pvargSrc ); … … 2179 2386 VariantClear( &Variant ); 2180 2387 } 2181 2182 2388 } 2183 2389 else … … 2197 2403 V_VT(pvargDest) = vt; 2198 2404 2199 TRACE("Dest Var :\n");2405 TRACE("Dest Var (re: %x)\n", res); 2200 2406 dump_Variant(pvargDest); 2201 2407 … … 2775 2981 LPSTR pNewString = NULL; 2776 2982 2777 TRACE(" ( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );2983 TRACE("%s: ( strIn: %p -> %s, lcid: 0x%08lx, dwFlags: 0x%08lx, plOut: %p ), stub\n", __FUNCTION__, strIn, debugstr_w(strIn), lcid, dwFlags, plOut ); 2778 2984 2779 2985 /* Check if we have a valid argument … … 3099 3305 } 3100 3306 3307 #if 0 3101 3308 /****************************************************************************** 3102 3309 * VarR8FromStr [OLEAUT32.84] … … 3129 3336 3130 3337 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); 3131 3360 } 3132 3361 … … 3333 3562 return S_OK; 3334 3563 } 3564 3565 3335 3566 3336 3567 /****************************************************************************** … … 4485 4716 4486 4717 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 4487 5167 /********************************************************************** 4488 5168 * VarParseNumFromStr [OLEAUT32.46] … … 4524 5204 return S_OK; 4525 5205 } 5206 #endif 4526 5207 4527 5208 4528 5209 /********************************************************************** 4529 5210 * 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. 4530 5233 */ 4531 5234 HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig, 4532 5235 ULONG dwVtBits, VARIANT * pvar) 4533 5236 { 5237 #ifdef __WIN32OS2__ 4534 5238 DWORD xint; 4535 5239 int i; 4536 FIXME("(..,dwVtBits=%lx,....), partial stub!\n",dwVtBits); 5240 5241 TRACE("%s: NUMPARSE->cDig: %x, NUMPARSE->nBaseShift: %x, NUMPARSE->dwOutFlags: %x dwVtBits=%lx. rgbDig: \n", 5242 __FUNCTION__, pnumprs->cDig, pnumprs->nBaseShift, pnumprs->dwOutFlags, dwVtBits); 4537 5243 4538 5244 xint = 0; 4539 5245 for (i=0;i<pnumprs->cDig;i++) 4540 5246 xint = xint*10 + rgbDig[i]; 4541 5247 4542 5248 if (pnumprs->dwOutFlags & NUMPRS_NEG) { 4543 5249 xint = xint * -1; 4544 5250 } 5251 TRACE("%s: xint: %x (%ld)\n", __FUNCTION__, xint, xint); 4545 5252 4546 5253 VariantInit(pvar); … … 4574 5281 } 4575 5282 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); 4576 5346 FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint); 4577 5347 return E_FAIL; 4578 } 4579 5348 } /* End of __WIN32OS2__ */ 5349 5350 #else 5351 5352 /* Scale factors and limits for double arithmetic */ 5353 static const double dblMultipliers[11] = { 5354 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 5355 1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0 5356 }; 5357 static const double dblMinimums[11] = { 5358 R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0, 5359 R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0, 5360 R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0 5361 }; 5362 static const double dblMaximums[11] = { 5363 R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0, 5364 R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0, 5365 R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0 5366 }; 5367 5368 int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0; 5369 5370 TRACE("(%p,%p,0x%lx,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst); 5371 5372 if (pNumprs->nBaseShift) 5373 { 5374 /* nBaseShift indicates a hex or octal number */ 5375 ULONG64 ul64 = 0; 5376 LONG64 l64; 5377 int i; 5378 5379 /* Convert the hex or octal number string into a UI64 */ 5380 for (i = 0; i < pNumprs->cDig; i++) 5381 { 5382 if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i])) 5383 { 5384 TRACE("Overflow multiplying digits\n"); 5385 return DISP_E_OVERFLOW; 5386 } 5387 ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i]; 5388 } 5389 5390 /* also make a negative representation */ 5391 l64=-ul64; 5392 5393 /* Try signed and unsigned types in size order */ 5394 if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN))) 5395 { 5396 V_VT(pVarDst) = VT_I1; 5397 if (ul64 <= I1_MAX) 5398 V_I1(pVarDst) = ul64; 5399 else 5400 V_I1(pVarDst) = l64; 5401 return S_OK; 5402 } 5403 else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX) 5404 { 5405 V_VT(pVarDst) = VT_UI1; 5406 V_UI1(pVarDst) = ul64; 5407 return S_OK; 5408 } 5409 else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN))) 5410 { 5411 V_VT(pVarDst) = VT_I2; 5412 if (ul64 <= I2_MAX) 5413 V_I2(pVarDst) = ul64; 5414 else 5415 V_I2(pVarDst) = l64; 5416 return S_OK; 5417 } 5418 else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX) 5419 { 5420 V_VT(pVarDst) = VT_UI2; 5421 V_UI2(pVarDst) = ul64; 5422 return S_OK; 5423 } 5424 else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) 5425 { 5426 V_VT(pVarDst) = VT_I4; 5427 if (ul64 <= I4_MAX) 5428 V_I4(pVarDst) = ul64; 5429 else 5430 V_I4(pVarDst) = l64; 5431 return S_OK; 5432 } 5433 else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX) 5434 { 5435 V_VT(pVarDst) = VT_UI4; 5436 V_UI4(pVarDst) = ul64; 5437 return S_OK; 5438 } 5439 else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN))) 5440 { 5441 V_VT(pVarDst) = VT_I8; 5442 V_I8(pVarDst) = ul64; 5443 return S_OK; 5444 } 5445 else if (dwVtBits & VTBIT_UI8) 5446 { 5447 V_VT(pVarDst) = VT_UI8; 5448 V_UI8(pVarDst) = ul64; 5449 return S_OK; 5450 } 5451 else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL) 5452 { 5453 V_VT(pVarDst) = VT_DECIMAL; 5454 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0); 5455 DEC_HI32(&V_DECIMAL(pVarDst)) = 0; 5456 DEC_LO64(&V_DECIMAL(pVarDst)) = ul64; 5457 return S_OK; 5458 } 5459 else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) 5460 { 5461 V_VT(pVarDst) = VT_R4; 5462 if (ul64 <= I4_MAX) 5463 V_R4(pVarDst) = ul64; 5464 else 5465 V_R4(pVarDst) = l64; 5466 return S_OK; 5467 } 5468 else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) 5469 { 5470 V_VT(pVarDst) = VT_R8; 5471 if (ul64 <= I4_MAX) 5472 V_R8(pVarDst) = ul64; 5473 else 5474 V_R8(pVarDst) = l64; 5475 return S_OK; 5476 } 5477 TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64)); 5478 return DISP_E_OVERFLOW; 5479 } 5480 5481 /* Count the number of relevant fractional and whole digits stored, 5482 * And compute the divisor/multiplier to scale the number by. 5483 */ 5484 if (pNumprs->nPwr10 < 0) 5485 { 5486 if (-pNumprs->nPwr10 >= pNumprs->cDig) 5487 { 5488 /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */ 5489 wholeNumberDigits = 0; 5490 fractionalDigits = pNumprs->cDig; 5491 divisor10 = -pNumprs->nPwr10; 5492 } 5493 else 5494 { 5495 /* An exactly represented real number e.g. 1.024 */ 5496 wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10; 5497 fractionalDigits = pNumprs->cDig - wholeNumberDigits; 5498 divisor10 = pNumprs->cDig - wholeNumberDigits; 5499 } 5500 } 5501 else if (pNumprs->nPwr10 == 0) 5502 { 5503 /* An exactly represented whole number e.g. 1024 */ 5504 wholeNumberDigits = pNumprs->cDig; 5505 fractionalDigits = 0; 5506 } 5507 else /* pNumprs->nPwr10 > 0 */ 5508 { 5509 /* A whole number followed by nPwr10 0's e.g. 102400 */ 5510 wholeNumberDigits = pNumprs->cDig; 5511 fractionalDigits = 0; 5512 multiplier10 = pNumprs->nPwr10; 5513 } 5514 5515 TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", pNumprs->cDig, 5516 pNumprs->nPwr10, wholeNumberDigits, fractionalDigits); 5517 TRACE("mult %d; div %d\n", multiplier10, divisor10); 5518 5519 if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) && 5520 (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL)))) 5521 { 5522 /* We have one or more integer output choices, and either: 5523 * 1) An integer input value, or 5524 * 2) A real number input value but no floating output choices. 5525 * Alternately, we have a DECIMAL output available and an integer input. 5526 * 5527 * So, place the integer value into pVarDst, using the smallest type 5528 * possible and preferring signed over unsigned types. 5529 */ 5530 BOOL bOverflow = FALSE, bNegative; 5531 ULONG64 ul64 = 0; 5532 int i; 5533 5534 /* Convert the integer part of the number into a UI8 */ 5535 for (i = 0; i < wholeNumberDigits; i++) 5536 { 5537 if (ul64 > (UI8_MAX / 10 - rgbDig[i])) 5538 { 5539 TRACE("Overflow multiplying digits\n"); 5540 bOverflow = TRUE; 5541 break; 5542 } 5543 ul64 = ul64 * 10 + rgbDig[i]; 5544 } 5545 5546 /* Account for the scale of the number */ 5547 if (!bOverflow && multiplier10) 5548 { 5549 for (i = 0; i < multiplier10; i++) 5550 { 5551 if (ul64 > (UI8_MAX / 10)) 5552 { 5553 TRACE("Overflow scaling number\n"); 5554 bOverflow = TRUE; 5555 break; 5556 } 5557 ul64 = ul64 * 10; 5558 } 5559 } 5560 5561 /* If we have any fractional digits, round the value. 5562 * Note we don't have to do this if divisor10 is < 1, 5563 * because this means the fractional part must be < 0.5 5564 */ 5565 if (!bOverflow && fractionalDigits && divisor10 > 0) 5566 { 5567 const BYTE* fracDig = rgbDig + wholeNumberDigits; 5568 BOOL bAdjust = FALSE; 5569 5570 TRACE("first decimal value is %d\n", *fracDig); 5571 5572 if (*fracDig > 5) 5573 bAdjust = TRUE; /* > 0.5 */ 5574 else if (*fracDig == 5) 5575 { 5576 for (i = 1; i < fractionalDigits; i++) 5577 { 5578 if (fracDig[i]) 5579 { 5580 bAdjust = TRUE; /* > 0.5 */ 5581 break; 5582 } 5583 } 5584 /* If exactly 0.5, round only odd values */ 5585 if (i == fractionalDigits && (ul64 & 1)) 5586 bAdjust = TRUE; 5587 } 5588 5589 if (bAdjust) 5590 { 5591 if (ul64 == UI8_MAX) 5592 { 5593 TRACE("Overflow after rounding\n"); 5594 bOverflow = TRUE; 5595 } 5596 ul64++; 5597 } 5598 } 5599 5600 /* Zero is not a negative number */ 5601 bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64 ? TRUE : FALSE; 5602 5603 TRACE("Integer value is %lld, bNeg %d\n", ul64, bNegative); 5604 5605 /* For negative integers, try the signed types in size order */ 5606 if (!bOverflow && bNegative) 5607 { 5608 if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8)) 5609 { 5610 if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN) 5611 { 5612 V_VT(pVarDst) = VT_I1; 5613 V_I1(pVarDst) = -ul64; 5614 return S_OK; 5615 } 5616 else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN) 5617 { 5618 V_VT(pVarDst) = VT_I2; 5619 V_I2(pVarDst) = -ul64; 5620 return S_OK; 5621 } 5622 else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN)) 5623 { 5624 V_VT(pVarDst) = VT_I4; 5625 V_I4(pVarDst) = -ul64; 5626 return S_OK; 5627 } 5628 else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1) 5629 { 5630 V_VT(pVarDst) = VT_I8; 5631 V_I8(pVarDst) = -ul64; 5632 return S_OK; 5633 } 5634 else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL) 5635 { 5636 /* Decimal is only output choice left - fast path */ 5637 V_VT(pVarDst) = VT_DECIMAL; 5638 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0); 5639 DEC_HI32(&V_DECIMAL(pVarDst)) = 0; 5640 DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64; 5641 return S_OK; 5642 } 5643 } 5644 } 5645 else if (!bOverflow) 5646 { 5647 /* For positive integers, try signed then unsigned types in size order */ 5648 if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX) 5649 { 5650 V_VT(pVarDst) = VT_I1; 5651 V_I1(pVarDst) = ul64; 5652 return S_OK; 5653 } 5654 else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX) 5655 { 5656 V_VT(pVarDst) = VT_UI1; 5657 V_UI1(pVarDst) = ul64; 5658 return S_OK; 5659 } 5660 else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX) 5661 { 5662 V_VT(pVarDst) = VT_I2; 5663 V_I2(pVarDst) = ul64; 5664 return S_OK; 5665 } 5666 else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX) 5667 { 5668 V_VT(pVarDst) = VT_UI2; 5669 V_UI2(pVarDst) = ul64; 5670 return S_OK; 5671 } 5672 else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX) 5673 { 5674 V_VT(pVarDst) = VT_I4; 5675 V_I4(pVarDst) = ul64; 5676 return S_OK; 5677 } 5678 else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX) 5679 { 5680 V_VT(pVarDst) = VT_UI4; 5681 V_UI4(pVarDst) = ul64; 5682 return S_OK; 5683 } 5684 else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX) 5685 { 5686 V_VT(pVarDst) = VT_I8; 5687 V_I8(pVarDst) = ul64; 5688 return S_OK; 5689 } 5690 else if (dwVtBits & VTBIT_UI8) 5691 { 5692 V_VT(pVarDst) = VT_UI8; 5693 V_UI8(pVarDst) = ul64; 5694 return S_OK; 5695 } 5696 else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL) 5697 { 5698 /* Decimal is only output choice left - fast path */ 5699 V_VT(pVarDst) = VT_DECIMAL; 5700 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0); 5701 DEC_HI32(&V_DECIMAL(pVarDst)) = 0; 5702 DEC_LO64(&V_DECIMAL(pVarDst)) = ul64; 5703 return S_OK; 5704 } 5705 } 5706 } 5707 5708 if (dwVtBits & REAL_VTBITS) 5709 { 5710 /* Try to put the number into a float or real */ 5711 BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG; 5712 double whole = 0.0; 5713 int i; 5714 5715 /* Convert the number into a double */ 5716 for (i = 0; i < pNumprs->cDig; i++) 5717 whole = whole * 10.0 + rgbDig[i]; 5718 5719 TRACE("Whole double value is %16.16g\n", whole); 5720 5721 /* Account for the scale */ 5722 while (multiplier10 > 10) 5723 { 5724 if (whole > dblMaximums[10]) 5725 { 5726 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); 5727 bOverflow = TRUE; 5728 break; 5729 } 5730 whole = whole * dblMultipliers[10]; 5731 multiplier10 -= 10; 5732 } 5733 if (multiplier10) 5734 { 5735 if (whole > dblMaximums[multiplier10]) 5736 { 5737 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); 5738 bOverflow = TRUE; 5739 } 5740 else 5741 whole = whole * dblMultipliers[multiplier10]; 5742 } 5743 5744 TRACE("Scaled double value is %16.16g\n", whole); 5745 5746 while (divisor10 > 10) 5747 { 5748 if (whole < dblMinimums[10]) 5749 { 5750 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */ 5751 bOverflow = TRUE; 5752 break; 5753 } 5754 whole = whole / dblMultipliers[10]; 5755 divisor10 -= 10; 5756 } 5757 if (divisor10) 5758 { 5759 if (whole < dblMinimums[divisor10]) 5760 { 5761 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */ 5762 bOverflow = TRUE; 5763 } 5764 else 5765 whole = whole / dblMultipliers[divisor10]; 5766 } 5767 if (!bOverflow) 5768 TRACE("Final double value is %16.16g\n", whole); 5769 5770 if (dwVtBits & VTBIT_R4 && 5771 ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0)) 5772 { 5773 TRACE("Set R4 to final value\n"); 5774 V_VT(pVarDst) = VT_R4; /* Fits into a float */ 5775 V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole; 5776 return S_OK; 5777 } 5778 5779 if (dwVtBits & VTBIT_R8) 5780 { 5781 TRACE("Set R8 to final value\n"); 5782 V_VT(pVarDst) = VT_R8; /* Fits into a double */ 5783 V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole; 5784 return S_OK; 5785 } 5786 5787 if (dwVtBits & VTBIT_CY) 5788 { 5789 if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst)))) 5790 { 5791 V_VT(pVarDst) = VT_CY; /* Fits into a currency */ 5792 TRACE("Set CY to final value\n"); 5793 return S_OK; 5794 } 5795 TRACE("Value Overflows CY\n"); 5796 } 5797 } 5798 5799 if (dwVtBits & VTBIT_DECIMAL) 5800 { 5801 int i; 5802 ULONG carry; 5803 ULONG64 tmp; 5804 DECIMAL* pDec = &V_DECIMAL(pVarDst); 5805 5806 DECIMAL_SETZERO(pDec); 5807 DEC_LO32(pDec) = 0; 5808 5809 if (pNumprs->dwOutFlags & NUMPRS_NEG) 5810 DEC_SIGN(pDec) = DECIMAL_NEG; 5811 else 5812 DEC_SIGN(pDec) = DECIMAL_POS; 5813 5814 /* Factor the significant digits */ 5815 for (i = 0; i < pNumprs->cDig; i++) 5816 { 5817 tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i]; 5818 carry = (ULONG)(tmp >> 32); 5819 DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX); 5820 tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry; 5821 carry = (ULONG)(tmp >> 32); 5822 DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX); 5823 tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry; 5824 DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX); 5825 5826 if (tmp >> 32 & UI4_MAX) 5827 { 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 4580 5859 4581 5860 /********************************************************************** … … 4596 5875 return E_NOTIMPL; 4597 5876 } 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 4598 5917 4599 5918 /********************************************************************** … … 5020 6339 case VT_UI4 : rVal = V_UNION(right,ulVal); break; 5021 6340 case VT_UINT : rVal = V_UNION(right,ulVal); break; 6341 #ifdef __WIN32OS2__ 6342 case VT_R8 : rVal = V_UNION(right,dblVal); break; 6343 #endif 5022 6344 default: rOk = FALSE; 5023 6345 } … … 5107 6429 5108 6430 /********************************************************************** 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 /********************************************************************** 5109 6708 * VarNot [OLEAUT32.174] 5110 6709 * … … 5133 6732 TRACE("rc=%d, Result:\n", (int) rc); 5134 6733 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 5135 7298 return rc; 5136 7299 } … … 5574 7737 return rc; 5575 7738 } 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.