ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

vartype.c
Go to the documentation of this file.
00001 /*
00002  * Low level variant functions
00003  *
00004  * Copyright 2003 Jon Griffiths
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #define COBJMACROS
00022 #define NONAMELESSUNION
00023 #define NONAMELESSSTRUCT
00024 
00025 #include "wine/debug.h"
00026 #include "wine/unicode.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "winnt.h"
00030 #include "variant.h"
00031 #include "resource.h"
00032 
00033 WINE_DEFAULT_DEBUG_CHANNEL(variant);
00034 
00035 extern HMODULE hProxyDll DECLSPEC_HIDDEN;
00036 
00037 #define CY_MULTIPLIER   10000             /* 4 dp of precision */
00038 #define CY_MULTIPLIER_F 10000.0
00039 #define CY_HALF         (CY_MULTIPLIER/2) /* 0.5 */
00040 #define CY_HALF_F       (CY_MULTIPLIER_F/2.0)
00041 
00042 static const WCHAR szFloatFormatW[] = { '%','.','7','G','\0' };
00043 static const WCHAR szDoubleFormatW[] = { '%','.','1','5','G','\0' };
00044 
00045 /* Copy data from one variant to another. */
00046 static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
00047 {
00048   switch (vt)
00049   {
00050   case VT_I1:
00051   case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
00052   case VT_BOOL:
00053   case VT_I2:
00054   case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
00055   case VT_R4:
00056   case VT_INT:
00057   case VT_I4:
00058   case VT_UINT:
00059   case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
00060   case VT_R8:
00061   case VT_DATE:
00062   case VT_CY:
00063   case VT_I8:
00064   case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
00065   case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
00066   case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
00067   case VT_BSTR: memcpy(pOut, &V_BSTR(srcVar), sizeof(BSTR)); break;
00068   default:
00069     FIXME("VT_ type %d unhandled, please report!\n", vt);
00070   }
00071 }
00072 
00073 /* Macro to inline conversion from a float or double to any integer type,
00074  * rounding according to the 'dutch' convention.
00075  */
00076 #define VARIANT_DutchRound(typ, value, res) do { \
00077   double whole = value < 0 ? ceil(value) : floor(value); \
00078   double fract = value - whole; \
00079   if (fract > 0.5) res = (typ)whole + (typ)1; \
00080   else if (fract == 0.5) { typ is_odd = (typ)whole & 1; res = whole + is_odd; } \
00081   else if (fract >= 0.0) res = (typ)whole; \
00082   else if (fract == -0.5) { typ is_odd = (typ)whole & 1; res = whole - is_odd; } \
00083   else if (fract > -0.5) res = (typ)whole; \
00084   else res = (typ)whole - (typ)1; \
00085 } while(0)
00086 
00087 
00088 /* Coerce VT_BSTR to a numeric type */
00089 static HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
00090                                       void* pOut, VARTYPE vt)
00091 {
00092   VARIANTARG dstVar;
00093   HRESULT hRet;
00094   NUMPARSE np;
00095   BYTE rgb[1024];
00096 
00097   /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
00098   np.cDig = sizeof(rgb) / sizeof(BYTE);
00099   np.dwInFlags = NUMPRS_STD;
00100 
00101   hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
00102 
00103   if (SUCCEEDED(hRet))
00104   {
00105     /* 1 << vt gives us the VTBIT constant for the destination number type */
00106     hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
00107     if (SUCCEEDED(hRet))
00108       VARIANT_CopyData(&dstVar, vt, pOut);
00109   }
00110   return hRet;
00111 }
00112 
00113 /* Coerce VT_DISPATCH to another type */
00114 static HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut,
00115                                 VARTYPE vt, DWORD dwFlags)
00116 {
00117   static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
00118   VARIANTARG srcVar, dstVar;
00119   HRESULT hRet;
00120 
00121   if (!pdispIn)
00122     return DISP_E_BADVARTYPE;
00123 
00124   /* Get the default 'value' property from the IDispatch */
00125   hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
00126                           &emptyParams, &srcVar, NULL, NULL);
00127 
00128   if (SUCCEEDED(hRet))
00129   {
00130     /* Convert the property to the requested type */
00131     V_VT(&dstVar) = VT_EMPTY;
00132     hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, dwFlags, vt);
00133     VariantClear(&srcVar);
00134 
00135     if (SUCCEEDED(hRet))
00136     {
00137       VARIANT_CopyData(&dstVar, vt, pOut);
00138       VariantClear(&srcVar);
00139     }
00140   }
00141   else
00142     hRet = DISP_E_TYPEMISMATCH;
00143   return hRet;
00144 }
00145 
00146 /* Inline return type */
00147 #define RETTYP static inline HRESULT
00148 
00149 
00150 /* Simple compiler cast from one type to another */
00151 #define SIMPLE(dest, src, func) RETTYP _##func(src in, dest* out) { \
00152   *out = in; return S_OK; }
00153 
00154 /* Compiler cast where input cannot be negative */
00155 #define NEGTST(dest, src, func) RETTYP _##func(src in, dest* out) { \
00156   if (in < 0) return DISP_E_OVERFLOW; *out = in; return S_OK; }
00157 
00158 /* Compiler cast where input cannot be > some number */
00159 #define POSTST(dest, src, func, tst) RETTYP _##func(src in, dest* out) { \
00160   if (in > (dest)tst) return DISP_E_OVERFLOW; *out = in; return S_OK; }
00161 
00162 /* Compiler cast where input cannot be < some number or >= some other number */
00163 #define BOTHTST(dest, src, func, lo, hi) RETTYP _##func(src in, dest* out) { \
00164   if (in < (dest)lo || in > hi) return DISP_E_OVERFLOW; *out = in; return S_OK; }
00165 
00166 /* I1 */
00167 POSTST(signed char, BYTE, VarI1FromUI1, I1_MAX)
00168 BOTHTST(signed char, SHORT, VarI1FromI2, I1_MIN, I1_MAX)
00169 BOTHTST(signed char, LONG, VarI1FromI4, I1_MIN, I1_MAX)
00170 SIMPLE(signed char, VARIANT_BOOL, VarI1FromBool)
00171 POSTST(signed char, USHORT, VarI1FromUI2, I1_MAX)
00172 POSTST(signed char, ULONG, VarI1FromUI4, I1_MAX)
00173 BOTHTST(signed char, LONG64, VarI1FromI8, I1_MIN, I1_MAX)
00174 POSTST(signed char, ULONG64, VarI1FromUI8, I1_MAX)
00175 
00176 /* UI1 */
00177 BOTHTST(BYTE, SHORT, VarUI1FromI2, UI1_MIN, UI1_MAX)
00178 SIMPLE(BYTE, VARIANT_BOOL, VarUI1FromBool)
00179 NEGTST(BYTE, signed char, VarUI1FromI1)
00180 POSTST(BYTE, USHORT, VarUI1FromUI2, UI1_MAX)
00181 BOTHTST(BYTE, LONG, VarUI1FromI4, UI1_MIN, UI1_MAX)
00182 POSTST(BYTE, ULONG, VarUI1FromUI4, UI1_MAX)
00183 BOTHTST(BYTE, LONG64, VarUI1FromI8, UI1_MIN, UI1_MAX)
00184 POSTST(BYTE, ULONG64, VarUI1FromUI8, UI1_MAX)
00185 
00186 /* I2 */
00187 SIMPLE(SHORT, BYTE, VarI2FromUI1)
00188 BOTHTST(SHORT, LONG, VarI2FromI4, I2_MIN, I2_MAX)
00189 SIMPLE(SHORT, VARIANT_BOOL, VarI2FromBool)
00190 SIMPLE(SHORT, signed char, VarI2FromI1)
00191 POSTST(SHORT, USHORT, VarI2FromUI2, I2_MAX)
00192 POSTST(SHORT, ULONG, VarI2FromUI4, I2_MAX)
00193 BOTHTST(SHORT, LONG64, VarI2FromI8, I2_MIN, I2_MAX)
00194 POSTST(SHORT, ULONG64, VarI2FromUI8, I2_MAX)
00195 
00196 /* UI2 */
00197 SIMPLE(USHORT, BYTE, VarUI2FromUI1)
00198 NEGTST(USHORT, SHORT, VarUI2FromI2)
00199 BOTHTST(USHORT, LONG, VarUI2FromI4, UI2_MIN, UI2_MAX)
00200 SIMPLE(USHORT, VARIANT_BOOL, VarUI2FromBool)
00201 NEGTST(USHORT, signed char, VarUI2FromI1)
00202 POSTST(USHORT, ULONG, VarUI2FromUI4, UI2_MAX)
00203 BOTHTST(USHORT, LONG64, VarUI2FromI8, UI2_MIN, UI2_MAX)
00204 POSTST(USHORT, ULONG64, VarUI2FromUI8, UI2_MAX)
00205 
00206 /* I4 */
00207 SIMPLE(LONG, BYTE, VarI4FromUI1)
00208 SIMPLE(LONG, SHORT, VarI4FromI2)
00209 SIMPLE(LONG, VARIANT_BOOL, VarI4FromBool)
00210 SIMPLE(LONG, signed char, VarI4FromI1)
00211 SIMPLE(LONG, USHORT, VarI4FromUI2)
00212 POSTST(LONG, ULONG, VarI4FromUI4, I4_MAX)
00213 BOTHTST(LONG, LONG64, VarI4FromI8, I4_MIN, I4_MAX)
00214 POSTST(LONG, ULONG64, VarI4FromUI8, I4_MAX)
00215 
00216 /* UI4 */
00217 SIMPLE(ULONG, BYTE, VarUI4FromUI1)
00218 NEGTST(ULONG, SHORT, VarUI4FromI2)
00219 NEGTST(ULONG, LONG, VarUI4FromI4)
00220 SIMPLE(ULONG, VARIANT_BOOL, VarUI4FromBool)
00221 NEGTST(ULONG, signed char, VarUI4FromI1)
00222 SIMPLE(ULONG, USHORT, VarUI4FromUI2)
00223 BOTHTST(ULONG, LONG64, VarUI4FromI8, UI4_MIN, UI4_MAX)
00224 POSTST(ULONG, ULONG64, VarUI4FromUI8, UI4_MAX)
00225 
00226 /* I8 */
00227 SIMPLE(LONG64, BYTE, VarI8FromUI1)
00228 SIMPLE(LONG64, SHORT, VarI8FromI2)
00229 SIMPLE(LONG64, signed char, VarI8FromI1)
00230 SIMPLE(LONG64, USHORT, VarI8FromUI2)
00231 SIMPLE(LONG64, ULONG, VarI8FromUI4)
00232 POSTST(LONG64, ULONG64, VarI8FromUI8, I8_MAX)
00233 
00234 /* UI8 */
00235 SIMPLE(ULONG64, BYTE, VarUI8FromUI1)
00236 NEGTST(ULONG64, SHORT, VarUI8FromI2)
00237 NEGTST(ULONG64, signed char, VarUI8FromI1)
00238 SIMPLE(ULONG64, USHORT, VarUI8FromUI2)
00239 SIMPLE(ULONG64, ULONG, VarUI8FromUI4)
00240 NEGTST(ULONG64, LONG64, VarUI8FromI8)
00241 
00242 /* R4 (float) */
00243 SIMPLE(float, BYTE, VarR4FromUI1)
00244 SIMPLE(float, SHORT, VarR4FromI2)
00245 SIMPLE(float, signed char, VarR4FromI1)
00246 SIMPLE(float, USHORT, VarR4FromUI2)
00247 SIMPLE(float, LONG, VarR4FromI4)
00248 SIMPLE(float, ULONG, VarR4FromUI4)
00249 SIMPLE(float, LONG64, VarR4FromI8)
00250 SIMPLE(float, ULONG64, VarR4FromUI8)
00251 
00252 /* R8 (double) */
00253 SIMPLE(double, BYTE, VarR8FromUI1)
00254 SIMPLE(double, SHORT, VarR8FromI2)
00255 SIMPLE(double, float, VarR8FromR4)
00256 RETTYP _VarR8FromCy(CY i, double* o) { *o = (double)i.int64 / CY_MULTIPLIER_F; return S_OK; }
00257 SIMPLE(double, DATE, VarR8FromDate)
00258 SIMPLE(double, signed char, VarR8FromI1)
00259 SIMPLE(double, USHORT, VarR8FromUI2)
00260 SIMPLE(double, LONG, VarR8FromI4)
00261 SIMPLE(double, ULONG, VarR8FromUI4)
00262 SIMPLE(double, LONG64, VarR8FromI8)
00263 SIMPLE(double, ULONG64, VarR8FromUI8)
00264 
00265 
00266 /* I1
00267  */
00268 
00269 /************************************************************************
00270  * VarI1FromUI1 (OLEAUT32.244)
00271  *
00272  * Convert a VT_UI1 to a VT_I1.
00273  *
00274  * PARAMS
00275  *  bIn     [I] Source
00276  *  pcOut   [O] Destination
00277  *
00278  * RETURNS
00279  *  Success: S_OK.
00280  *  Failure: E_INVALIDARG, if the source value is invalid
00281  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00282  */
00283 HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
00284 {
00285   return _VarI1FromUI1(bIn, pcOut);
00286 }
00287 
00288 /************************************************************************
00289  * VarI1FromI2 (OLEAUT32.245)
00290  *
00291  * Convert a VT_I2 to a VT_I1.
00292  *
00293  * PARAMS
00294  *  sIn     [I] Source
00295  *  pcOut   [O] Destination
00296  *
00297  * RETURNS
00298  *  Success: S_OK.
00299  *  Failure: E_INVALIDARG, if the source value is invalid
00300  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00301  */
00302 HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
00303 {
00304   return _VarI1FromI2(sIn, pcOut);
00305 }
00306 
00307 /************************************************************************
00308  * VarI1FromI4 (OLEAUT32.246)
00309  *
00310  * Convert a VT_I4 to a VT_I1.
00311  *
00312  * PARAMS
00313  *  iIn     [I] Source
00314  *  pcOut   [O] Destination
00315  *
00316  * RETURNS
00317  *  Success: S_OK.
00318  *  Failure: E_INVALIDARG, if the source value is invalid
00319  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00320  */
00321 HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
00322 {
00323   return _VarI1FromI4(iIn, pcOut);
00324 }
00325 
00326 /************************************************************************
00327  * VarI1FromR4 (OLEAUT32.247)
00328  *
00329  * Convert a VT_R4 to a VT_I1.
00330  *
00331  * PARAMS
00332  *  fltIn   [I] Source
00333  *  pcOut   [O] Destination
00334  *
00335  * RETURNS
00336  *  Success: S_OK.
00337  *  Failure: E_INVALIDARG, if the source value is invalid
00338  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00339  */
00340 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
00341 {
00342   return VarI1FromR8(fltIn, pcOut);
00343 }
00344 
00345 /************************************************************************
00346  * VarI1FromR8 (OLEAUT32.248)
00347  *
00348  * Convert a VT_R8 to a VT_I1.
00349  *
00350  * PARAMS
00351  *  dblIn   [I] Source
00352  *  pcOut   [O] Destination
00353  *
00354  * RETURNS
00355  *  Success: S_OK.
00356  *  Failure: E_INVALIDARG, if the source value is invalid
00357  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00358  *
00359  * NOTES
00360  *  See VarI8FromR8() for details concerning rounding.
00361  */
00362 HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
00363 {
00364   if (dblIn < (double)I1_MIN || dblIn > (double)I1_MAX)
00365     return DISP_E_OVERFLOW;
00366   VARIANT_DutchRound(CHAR, dblIn, *pcOut);
00367   return S_OK;
00368 }
00369 
00370 /************************************************************************
00371  * VarI1FromDate (OLEAUT32.249)
00372  *
00373  * Convert a VT_DATE to a VT_I1.
00374  *
00375  * PARAMS
00376  *  dateIn  [I] Source
00377  *  pcOut   [O] Destination
00378  *
00379  * RETURNS
00380  *  Success: S_OK.
00381  *  Failure: E_INVALIDARG, if the source value is invalid
00382  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00383  */
00384 HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
00385 {
00386   return VarI1FromR8(dateIn, pcOut);
00387 }
00388 
00389 /************************************************************************
00390  * VarI1FromCy (OLEAUT32.250)
00391  *
00392  * Convert a VT_CY to a VT_I1.
00393  *
00394  * PARAMS
00395  *  cyIn    [I] Source
00396  *  pcOut   [O] Destination
00397  *
00398  * RETURNS
00399  *  Success: S_OK.
00400  *  Failure: E_INVALIDARG, if the source value is invalid
00401  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00402  */
00403 HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
00404 {
00405   LONG i = I1_MAX + 1;
00406 
00407   VarI4FromCy(cyIn, &i);
00408   return _VarI1FromI4(i, pcOut);
00409 }
00410 
00411 /************************************************************************
00412  * VarI1FromStr (OLEAUT32.251)
00413  *
00414  * Convert a VT_BSTR to a VT_I1.
00415  *
00416  * PARAMS
00417  *  strIn   [I] Source
00418  *  lcid    [I] LCID for the conversion
00419  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
00420  *  pcOut   [O] Destination
00421  *
00422  * RETURNS
00423  *  Success: S_OK.
00424  *  Failure: E_INVALIDARG, if the source value is invalid
00425  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00426  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
00427  */
00428 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
00429 {
00430   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pcOut, VT_I1);
00431 }
00432 
00433 /************************************************************************
00434  * VarI1FromDisp (OLEAUT32.252)
00435  *
00436  * Convert a VT_DISPATCH to a VT_I1.
00437  *
00438  * PARAMS
00439  *  pdispIn  [I] Source
00440  *  lcid     [I] LCID for conversion
00441  *  pcOut    [O] Destination
00442  *
00443  * RETURNS
00444  *  Success: S_OK.
00445  *  Failure: E_INVALIDARG, if the source value is invalid
00446  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00447  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
00448  */
00449 HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
00450 {
00451   return VARIANT_FromDisp(pdispIn, lcid, pcOut, VT_I1, 0);
00452 }
00453 
00454 /************************************************************************
00455  * VarI1FromBool (OLEAUT32.253)
00456  *
00457  * Convert a VT_BOOL to a VT_I1.
00458  *
00459  * PARAMS
00460  *  boolIn  [I] Source
00461  *  pcOut   [O] Destination
00462  *
00463  * RETURNS
00464  *  S_OK.
00465  */
00466 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
00467 {
00468   return _VarI1FromBool(boolIn, pcOut);
00469 }
00470 
00471 /************************************************************************
00472  * VarI1FromUI2 (OLEAUT32.254)
00473  *
00474  * Convert a VT_UI2 to a VT_I1.
00475  *
00476  * PARAMS
00477  *  usIn    [I] Source
00478  *  pcOut   [O] Destination
00479  *
00480  * RETURNS
00481  *  Success: S_OK.
00482  *  Failure: E_INVALIDARG, if the source value is invalid
00483  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00484  */
00485 HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
00486 {
00487   return _VarI1FromUI2(usIn, pcOut);
00488 }
00489 
00490 /************************************************************************
00491  * VarI1FromUI4 (OLEAUT32.255)
00492  *
00493  * Convert a VT_UI4 to a VT_I1.
00494  *
00495  * PARAMS
00496  *  ulIn    [I] Source
00497  *  pcOut   [O] Destination
00498  *
00499  * RETURNS
00500  *  Success: S_OK.
00501  *  Failure: E_INVALIDARG, if the source value is invalid
00502  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00503  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
00504  */
00505 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
00506 {
00507   return _VarI1FromUI4(ulIn, pcOut);
00508 }
00509 
00510 /************************************************************************
00511  * VarI1FromDec (OLEAUT32.256)
00512  *
00513  * Convert a VT_DECIMAL to a VT_I1.
00514  *
00515  * PARAMS
00516  *  pDecIn  [I] Source
00517  *  pcOut   [O] Destination
00518  *
00519  * RETURNS
00520  *  Success: S_OK.
00521  *  Failure: E_INVALIDARG, if the source value is invalid
00522  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00523  */
00524 HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
00525 {
00526   LONG64 i64;
00527   HRESULT hRet;
00528 
00529   hRet = VarI8FromDec(pdecIn, &i64);
00530 
00531   if (SUCCEEDED(hRet))
00532     hRet = _VarI1FromI8(i64, pcOut);
00533   return hRet;
00534 }
00535 
00536 /************************************************************************
00537  * VarI1FromI8 (OLEAUT32.376)
00538  *
00539  * Convert a VT_I8 to a VT_I1.
00540  *
00541  * PARAMS
00542  *  llIn  [I] Source
00543  *  pcOut [O] Destination
00544  *
00545  * RETURNS
00546  *  Success: S_OK.
00547  *  Failure: E_INVALIDARG, if the source value is invalid
00548  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00549  */
00550 HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
00551 {
00552   return _VarI1FromI8(llIn, pcOut);
00553 }
00554 
00555 /************************************************************************
00556  * VarI1FromUI8 (OLEAUT32.377)
00557  *
00558  * Convert a VT_UI8 to a VT_I1.
00559  *
00560  * PARAMS
00561  *  ullIn   [I] Source
00562  *  pcOut   [O] Destination
00563  *
00564  * RETURNS
00565  *  Success: S_OK.
00566  *  Failure: E_INVALIDARG, if the source value is invalid
00567  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00568  */
00569 HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
00570 {
00571   return _VarI1FromUI8(ullIn, pcOut);
00572 }
00573 
00574 /* UI1
00575  */
00576 
00577 /************************************************************************
00578  * VarUI1FromI2 (OLEAUT32.130)
00579  *
00580  * Convert a VT_I2 to a VT_UI1.
00581  *
00582  * PARAMS
00583  *  sIn   [I] Source
00584  *  pbOut [O] Destination
00585  *
00586  * RETURNS
00587  *  Success: S_OK.
00588  *  Failure: E_INVALIDARG, if the source value is invalid
00589  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00590  */
00591 HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
00592 {
00593   return _VarUI1FromI2(sIn, pbOut);
00594 }
00595 
00596 /************************************************************************
00597  * VarUI1FromI4 (OLEAUT32.131)
00598  *
00599  * Convert a VT_I4 to a VT_UI1.
00600  *
00601  * PARAMS
00602  *  iIn   [I] Source
00603  *  pbOut [O] Destination
00604  *
00605  * RETURNS
00606  *  Success: S_OK.
00607  *  Failure: E_INVALIDARG, if the source value is invalid
00608  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00609  */
00610 HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
00611 {
00612   return _VarUI1FromI4(iIn, pbOut);
00613 }
00614 
00615 /************************************************************************
00616  * VarUI1FromR4 (OLEAUT32.132)
00617  *
00618  * Convert a VT_R4 to a VT_UI1.
00619  *
00620  * PARAMS
00621  *  fltIn [I] Source
00622  *  pbOut [O] Destination
00623  *
00624  * RETURNS
00625  *  Success: S_OK.
00626  *  Failure: E_INVALIDARG, if the source value is invalid
00627  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00628  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
00629  */
00630 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
00631 {
00632   return VarUI1FromR8(fltIn, pbOut);
00633 }
00634 
00635 /************************************************************************
00636  * VarUI1FromR8 (OLEAUT32.133)
00637  *
00638  * Convert a VT_R8 to a VT_UI1.
00639  *
00640  * PARAMS
00641  *  dblIn [I] Source
00642  *  pbOut [O] Destination
00643  *
00644  * RETURNS
00645  *  Success: S_OK.
00646  *  Failure: E_INVALIDARG, if the source value is invalid
00647  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00648  *
00649  * NOTES
00650  *  See VarI8FromR8() for details concerning rounding.
00651  */
00652 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
00653 {
00654   if (dblIn < -0.5 || dblIn > (double)UI1_MAX)
00655     return DISP_E_OVERFLOW;
00656   VARIANT_DutchRound(BYTE, dblIn, *pbOut);
00657   return S_OK;
00658 }
00659 
00660 /************************************************************************
00661  * VarUI1FromCy (OLEAUT32.134)
00662  *
00663  * Convert a VT_CY to a VT_UI1.
00664  *
00665  * PARAMS
00666  *  cyIn     [I] Source
00667  *  pbOut [O] Destination
00668  *
00669  * RETURNS
00670  *  Success: S_OK.
00671  *  Failure: E_INVALIDARG, if the source value is invalid
00672  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00673  *
00674  * NOTES
00675  *  Negative values >= -5000 will be converted to 0.
00676  */
00677 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
00678 {
00679   ULONG i = UI1_MAX + 1;
00680 
00681   VarUI4FromCy(cyIn, &i);
00682   return _VarUI1FromUI4(i, pbOut);
00683 }
00684 
00685 /************************************************************************
00686  * VarUI1FromDate (OLEAUT32.135)
00687  *
00688  * Convert a VT_DATE to a VT_UI1.
00689  *
00690  * PARAMS
00691  *  dateIn [I] Source
00692  *  pbOut  [O] Destination
00693  *
00694  * RETURNS
00695  *  Success: S_OK.
00696  *  Failure: E_INVALIDARG, if the source value is invalid
00697  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00698  */
00699 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
00700 {
00701   return VarUI1FromR8(dateIn, pbOut);
00702 }
00703 
00704 /************************************************************************
00705  * VarUI1FromStr (OLEAUT32.136)
00706  *
00707  * Convert a VT_BSTR to a VT_UI1.
00708  *
00709  * PARAMS
00710  *  strIn   [I] Source
00711  *  lcid    [I] LCID for the conversion
00712  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
00713  *  pbOut   [O] Destination
00714  *
00715  * RETURNS
00716  *  Success: S_OK.
00717  *  Failure: E_INVALIDARG, if the source value is invalid
00718  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00719  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
00720  */
00721 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
00722 {
00723   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pbOut, VT_UI1);
00724 }
00725 
00726 /************************************************************************
00727  * VarUI1FromDisp (OLEAUT32.137)
00728  *
00729  * Convert a VT_DISPATCH to a VT_UI1.
00730  *
00731  * PARAMS
00732  *  pdispIn [I] Source
00733  *  lcid    [I] LCID for conversion
00734  *  pbOut   [O] Destination
00735  *
00736  * RETURNS
00737  *  Success: S_OK.
00738  *  Failure: E_INVALIDARG, if the source value is invalid
00739  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00740  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
00741  */
00742 HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
00743 {
00744   return VARIANT_FromDisp(pdispIn, lcid, pbOut, VT_UI1, 0);
00745 }
00746 
00747 /************************************************************************
00748  * VarUI1FromBool (OLEAUT32.138)
00749  *
00750  * Convert a VT_BOOL to a VT_UI1.
00751  *
00752  * PARAMS
00753  *  boolIn [I] Source
00754  *  pbOut  [O] Destination
00755  *
00756  * RETURNS
00757  *  S_OK.
00758  */
00759 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
00760 {
00761   return _VarUI1FromBool(boolIn, pbOut);
00762 }
00763 
00764 /************************************************************************
00765  * VarUI1FromI1 (OLEAUT32.237)
00766  *
00767  * Convert a VT_I1 to a VT_UI1.
00768  *
00769  * PARAMS
00770  *  cIn   [I] Source
00771  *  pbOut [O] Destination
00772  *
00773  * RETURNS
00774  *  Success: S_OK.
00775  *  Failure: E_INVALIDARG, if the source value is invalid
00776  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00777  */
00778 HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
00779 {
00780   return _VarUI1FromI1(cIn, pbOut);
00781 }
00782 
00783 /************************************************************************
00784  * VarUI1FromUI2 (OLEAUT32.238)
00785  *
00786  * Convert a VT_UI2 to a VT_UI1.
00787  *
00788  * PARAMS
00789  *  usIn  [I] Source
00790  *  pbOut [O] Destination
00791  *
00792  * RETURNS
00793  *  Success: S_OK.
00794  *  Failure: E_INVALIDARG, if the source value is invalid
00795  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00796  */
00797 HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
00798 {
00799   return _VarUI1FromUI2(usIn, pbOut);
00800 }
00801 
00802 /************************************************************************
00803  * VarUI1FromUI4 (OLEAUT32.239)
00804  *
00805  * Convert a VT_UI4 to a VT_UI1.
00806  *
00807  * PARAMS
00808  *  ulIn  [I] Source
00809  *  pbOut [O] Destination
00810  *
00811  * RETURNS
00812  *  Success: S_OK.
00813  *  Failure: E_INVALIDARG, if the source value is invalid
00814  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00815  */
00816 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
00817 {
00818   return _VarUI1FromUI4(ulIn, pbOut);
00819 }
00820 
00821 /************************************************************************
00822  * VarUI1FromDec (OLEAUT32.240)
00823  *
00824  * Convert a VT_DECIMAL to a VT_UI1.
00825  *
00826  * PARAMS
00827  *  pDecIn [I] Source
00828  *  pbOut  [O] Destination
00829  *
00830  * RETURNS
00831  *  Success: S_OK.
00832  *  Failure: E_INVALIDARG, if the source value is invalid
00833  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00834  */
00835 HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
00836 {
00837   LONG64 i64;
00838   HRESULT hRet;
00839 
00840   hRet = VarI8FromDec(pdecIn, &i64);
00841 
00842   if (SUCCEEDED(hRet))
00843     hRet = _VarUI1FromI8(i64, pbOut);
00844   return hRet;
00845 }
00846 
00847 /************************************************************************
00848  * VarUI1FromI8 (OLEAUT32.372)
00849  *
00850  * Convert a VT_I8 to a VT_UI1.
00851  *
00852  * PARAMS
00853  *  llIn  [I] Source
00854  *  pbOut [O] Destination
00855  *
00856  * RETURNS
00857  *  Success: S_OK.
00858  *  Failure: E_INVALIDARG, if the source value is invalid
00859  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00860  */
00861 HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
00862 {
00863   return _VarUI1FromI8(llIn, pbOut);
00864 }
00865 
00866 /************************************************************************
00867  * VarUI1FromUI8 (OLEAUT32.373)
00868  *
00869  * Convert a VT_UI8 to a VT_UI1.
00870  *
00871  * PARAMS
00872  *  ullIn   [I] Source
00873  *  pbOut   [O] Destination
00874  *
00875  * RETURNS
00876  *  Success: S_OK.
00877  *  Failure: E_INVALIDARG, if the source value is invalid
00878  *           DISP_E_OVERFLOW, if the value will not fit in the destination
00879  */
00880 HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
00881 {
00882   return _VarUI1FromUI8(ullIn, pbOut);
00883 }
00884 
00885 
00886 /* I2
00887  */
00888 
00889 /************************************************************************
00890  * VarI2FromUI1 (OLEAUT32.48)
00891  *
00892  * Convert a VT_UI2 to a VT_I2.
00893  *
00894  * PARAMS
00895  *  bIn     [I] Source
00896  *  psOut   [O] Destination
00897  *
00898  * RETURNS
00899  *  S_OK.
00900  */
00901 HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
00902 {
00903   return _VarI2FromUI1(bIn, psOut);
00904 }
00905 
00906 /************************************************************************
00907  * VarI2FromI4 (OLEAUT32.49)
00908  *
00909  * Convert a VT_I4 to a VT_I2.
00910  *
00911  * PARAMS
00912  *  iIn     [I] Source
00913  *  psOut   [O] Destination
00914  *
00915  * RETURNS
00916  *  Success: S_OK.
00917  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
00918  */
00919 HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
00920 {
00921   return _VarI2FromI4(iIn, psOut);
00922 }
00923 
00924 /************************************************************************
00925  * VarI2FromR4 (OLEAUT32.50)
00926  *
00927  * Convert a VT_R4 to a VT_I2.
00928  *
00929  * PARAMS
00930  *  fltIn   [I] Source
00931  *  psOut   [O] Destination
00932  *
00933  * RETURNS
00934  *  Success: S_OK.
00935  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
00936  */
00937 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
00938 {
00939   return VarI2FromR8(fltIn, psOut);
00940 }
00941 
00942 /************************************************************************
00943  * VarI2FromR8 (OLEAUT32.51)
00944  *
00945  * Convert a VT_R8 to a VT_I2.
00946  *
00947  * PARAMS
00948  *  dblIn   [I] Source
00949  *  psOut   [O] Destination
00950  *
00951  * RETURNS
00952  *  Success: S_OK.
00953  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
00954  *
00955  * NOTES
00956  *  See VarI8FromR8() for details concerning rounding.
00957  */
00958 HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
00959 {
00960   if (dblIn < (double)I2_MIN || dblIn > (double)I2_MAX)
00961     return DISP_E_OVERFLOW;
00962   VARIANT_DutchRound(SHORT, dblIn, *psOut);
00963   return S_OK;
00964 }
00965 
00966 /************************************************************************
00967  * VarI2FromCy (OLEAUT32.52)
00968  *
00969  * Convert a VT_CY to a VT_I2.
00970  *
00971  * PARAMS
00972  *  cyIn    [I] Source
00973  *  psOut   [O] Destination
00974  *
00975  * RETURNS
00976  *  Success: S_OK.
00977  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
00978  */
00979 HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
00980 {
00981   LONG i = I2_MAX + 1;
00982 
00983   VarI4FromCy(cyIn, &i);
00984   return _VarI2FromI4(i, psOut);
00985 }
00986 
00987 /************************************************************************
00988  * VarI2FromDate (OLEAUT32.53)
00989  *
00990  * Convert a VT_DATE to a VT_I2.
00991  *
00992  * PARAMS
00993  *  dateIn  [I] Source
00994  *  psOut   [O] Destination
00995  *
00996  * RETURNS
00997  *  Success: S_OK.
00998  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
00999  */
01000 HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
01001 {
01002   return VarI2FromR8(dateIn, psOut);
01003 }
01004 
01005 /************************************************************************
01006  * VarI2FromStr (OLEAUT32.54)
01007  *
01008  * Convert a VT_BSTR to a VT_I2.
01009  *
01010  * PARAMS
01011  *  strIn   [I] Source
01012  *  lcid    [I] LCID for the conversion
01013  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
01014  *  psOut   [O] Destination
01015  *
01016  * RETURNS
01017  *  Success: S_OK.
01018  *  Failure: E_INVALIDARG, if any parameter is invalid
01019  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01020  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
01021  */
01022 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
01023 {
01024   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, psOut, VT_I2);
01025 }
01026 
01027 /************************************************************************
01028  * VarI2FromDisp (OLEAUT32.55)
01029  *
01030  * Convert a VT_DISPATCH to a VT_I2.
01031  *
01032  * PARAMS
01033  *  pdispIn  [I] Source
01034  *  lcid     [I] LCID for conversion
01035  *  psOut    [O] Destination
01036  *
01037  * RETURNS
01038  *  Success: S_OK.
01039  *  Failure: E_INVALIDARG, if pdispIn is invalid,
01040  *           DISP_E_OVERFLOW, if the value will not fit in the destination,
01041  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
01042  */
01043 HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
01044 {
01045   return VARIANT_FromDisp(pdispIn, lcid, psOut, VT_I2, 0);
01046 }
01047 
01048 /************************************************************************
01049  * VarI2FromBool (OLEAUT32.56)
01050  *
01051  * Convert a VT_BOOL to a VT_I2.
01052  *
01053  * PARAMS
01054  *  boolIn  [I] Source
01055  *  psOut   [O] Destination
01056  *
01057  * RETURNS
01058  *  S_OK.
01059  */
01060 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
01061 {
01062   return _VarI2FromBool(boolIn, psOut);
01063 }
01064 
01065 /************************************************************************
01066  * VarI2FromI1 (OLEAUT32.205)
01067  *
01068  * Convert a VT_I1 to a VT_I2.
01069  *
01070  * PARAMS
01071  *  cIn     [I] Source
01072  *  psOut   [O] Destination
01073  *
01074  * RETURNS
01075  *  S_OK.
01076  */
01077 HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
01078 {
01079   return _VarI2FromI1(cIn, psOut);
01080 }
01081 
01082 /************************************************************************
01083  * VarI2FromUI2 (OLEAUT32.206)
01084  *
01085  * Convert a VT_UI2 to a VT_I2.
01086  *
01087  * PARAMS
01088  *  usIn    [I] Source
01089  *  psOut   [O] Destination
01090  *
01091  * RETURNS
01092  *  Success: S_OK.
01093  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01094  */
01095 HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
01096 {
01097   return _VarI2FromUI2(usIn, psOut);
01098 }
01099 
01100 /************************************************************************
01101  * VarI2FromUI4 (OLEAUT32.207)
01102  *
01103  * Convert a VT_UI4 to a VT_I2.
01104  *
01105  * PARAMS
01106  *  ulIn    [I] Source
01107  *  psOut   [O] Destination
01108  *
01109  * RETURNS
01110  *  Success: S_OK.
01111  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01112  */
01113 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
01114 {
01115   return _VarI2FromUI4(ulIn, psOut);
01116 }
01117 
01118 /************************************************************************
01119  * VarI2FromDec (OLEAUT32.208)
01120  *
01121  * Convert a VT_DECIMAL to a VT_I2.
01122  *
01123  * PARAMS
01124  *  pDecIn  [I] Source
01125  *  psOut   [O] Destination
01126  *
01127  * RETURNS
01128  *  Success: S_OK.
01129  *  Failure: E_INVALIDARG, if the source value is invalid
01130  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01131  */
01132 HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
01133 {
01134   LONG64 i64;
01135   HRESULT hRet;
01136 
01137   hRet = VarI8FromDec(pdecIn, &i64);
01138 
01139   if (SUCCEEDED(hRet))
01140     hRet = _VarI2FromI8(i64, psOut);
01141   return hRet;
01142 }
01143 
01144 /************************************************************************
01145  * VarI2FromI8 (OLEAUT32.346)
01146  *
01147  * Convert a VT_I8 to a VT_I2.
01148  *
01149  * PARAMS
01150  *  llIn  [I] Source
01151  *  psOut [O] Destination
01152  *
01153  * RETURNS
01154  *  Success: S_OK.
01155  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01156  */
01157 HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
01158 {
01159   return _VarI2FromI8(llIn, psOut);
01160 }
01161 
01162 /************************************************************************
01163  * VarI2FromUI8 (OLEAUT32.347)
01164  *
01165  * Convert a VT_UI8 to a VT_I2.
01166  *
01167  * PARAMS
01168  *  ullIn [I] Source
01169  *  psOut [O] Destination
01170  *
01171  * RETURNS
01172  *  Success: S_OK.
01173  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01174  */
01175 HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
01176 {
01177   return _VarI2FromUI8(ullIn, psOut);
01178 }
01179 
01180 /* UI2
01181  */
01182 
01183 /************************************************************************
01184  * VarUI2FromUI1 (OLEAUT32.257)
01185  *
01186  * Convert a VT_UI1 to a VT_UI2.
01187  *
01188  * PARAMS
01189  *  bIn    [I] Source
01190  *  pusOut [O] Destination
01191  *
01192  * RETURNS
01193  *  S_OK.
01194  */
01195 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
01196 {
01197   return _VarUI2FromUI1(bIn, pusOut);
01198 }
01199 
01200 /************************************************************************
01201  * VarUI2FromI2 (OLEAUT32.258)
01202  *
01203  * Convert a VT_I2 to a VT_UI2.
01204  *
01205  * PARAMS
01206  *  sIn    [I] Source
01207  *  pusOut [O] Destination
01208  *
01209  * RETURNS
01210  *  Success: S_OK.
01211  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01212  */
01213 HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
01214 {
01215   return _VarUI2FromI2(sIn, pusOut);
01216 }
01217 
01218 /************************************************************************
01219  * VarUI2FromI4 (OLEAUT32.259)
01220  *
01221  * Convert a VT_I4 to a VT_UI2.
01222  *
01223  * PARAMS
01224  *  iIn    [I] Source
01225  *  pusOut [O] Destination
01226  *
01227  * RETURNS
01228  *  Success: S_OK.
01229  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01230  */
01231 HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
01232 {
01233   return _VarUI2FromI4(iIn, pusOut);
01234 }
01235 
01236 /************************************************************************
01237  * VarUI2FromR4 (OLEAUT32.260)
01238  *
01239  * Convert a VT_R4 to a VT_UI2.
01240  *
01241  * PARAMS
01242  *  fltIn  [I] Source
01243  *  pusOut [O] Destination
01244  *
01245  * RETURNS
01246  *  Success: S_OK.
01247  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01248  */
01249 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
01250 {
01251   return VarUI2FromR8(fltIn, pusOut);
01252 }
01253 
01254 /************************************************************************
01255  * VarUI2FromR8 (OLEAUT32.261)
01256  *
01257  * Convert a VT_R8 to a VT_UI2.
01258  *
01259  * PARAMS
01260  *  dblIn  [I] Source
01261  *  pusOut [O] Destination
01262  *
01263  * RETURNS
01264  *  Success: S_OK.
01265  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01266  *
01267  * NOTES
01268  *  See VarI8FromR8() for details concerning rounding.
01269  */
01270 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
01271 {
01272   if (dblIn < -0.5 || dblIn > (double)UI2_MAX)
01273     return DISP_E_OVERFLOW;
01274   VARIANT_DutchRound(USHORT, dblIn, *pusOut);
01275   return S_OK;
01276 }
01277 
01278 /************************************************************************
01279  * VarUI2FromDate (OLEAUT32.262)
01280  *
01281  * Convert a VT_DATE to a VT_UI2.
01282  *
01283  * PARAMS
01284  *  dateIn [I] Source
01285  *  pusOut [O] Destination
01286  *
01287  * RETURNS
01288  *  Success: S_OK.
01289  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01290  */
01291 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
01292 {
01293   return VarUI2FromR8(dateIn, pusOut);
01294 }
01295 
01296 /************************************************************************
01297  * VarUI2FromCy (OLEAUT32.263)
01298  *
01299  * Convert a VT_CY to a VT_UI2.
01300  *
01301  * PARAMS
01302  *  cyIn   [I] Source
01303  *  pusOut [O] Destination
01304  *
01305  * RETURNS
01306  *  Success: S_OK.
01307  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01308  *
01309  * NOTES
01310  *  Negative values >= -5000 will be converted to 0.
01311  */
01312 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
01313 {
01314   ULONG i = UI2_MAX + 1;
01315 
01316   VarUI4FromCy(cyIn, &i);
01317   return _VarUI2FromUI4(i, pusOut);
01318 }
01319 
01320 /************************************************************************
01321  * VarUI2FromStr (OLEAUT32.264)
01322  *
01323  * Convert a VT_BSTR to a VT_UI2.
01324  *
01325  * PARAMS
01326  *  strIn   [I] Source
01327  *  lcid    [I] LCID for the conversion
01328  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
01329  *  pusOut  [O] Destination
01330  *
01331  * RETURNS
01332  *  Success: S_OK.
01333  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01334  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
01335  */
01336 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
01337 {
01338   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pusOut, VT_UI2);
01339 }
01340 
01341 /************************************************************************
01342  * VarUI2FromDisp (OLEAUT32.265)
01343  *
01344  * Convert a VT_DISPATCH to a VT_UI2.
01345  *
01346  * PARAMS
01347  *  pdispIn  [I] Source
01348  *  lcid     [I] LCID for conversion
01349  *  pusOut   [O] Destination
01350  *
01351  * RETURNS
01352  *  Success: S_OK.
01353  *  Failure: E_INVALIDARG, if the source value is invalid
01354  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01355  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
01356  */
01357 HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
01358 {
01359   return VARIANT_FromDisp(pdispIn, lcid, pusOut, VT_UI2, 0);
01360 }
01361 
01362 /************************************************************************
01363  * VarUI2FromBool (OLEAUT32.266)
01364  *
01365  * Convert a VT_BOOL to a VT_UI2.
01366  *
01367  * PARAMS
01368  *  boolIn  [I] Source
01369  *  pusOut  [O] Destination
01370  *
01371  * RETURNS
01372  *  S_OK.
01373  */
01374 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
01375 {
01376   return _VarUI2FromBool(boolIn, pusOut);
01377 }
01378 
01379 /************************************************************************
01380  * VarUI2FromI1 (OLEAUT32.267)
01381  *
01382  * Convert a VT_I1 to a VT_UI2.
01383  *
01384  * PARAMS
01385  *  cIn    [I] Source
01386  *  pusOut [O] Destination
01387  *
01388  * RETURNS
01389  *  Success: S_OK.
01390  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01391  */
01392 HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
01393 {
01394   return _VarUI2FromI1(cIn, pusOut);
01395 }
01396 
01397 /************************************************************************
01398  * VarUI2FromUI4 (OLEAUT32.268)
01399  *
01400  * Convert a VT_UI4 to a VT_UI2.
01401  *
01402  * PARAMS
01403  *  ulIn   [I] Source
01404  *  pusOut [O] Destination
01405  *
01406  * RETURNS
01407  *  Success: S_OK.
01408  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01409  */
01410 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
01411 {
01412   return _VarUI2FromUI4(ulIn, pusOut);
01413 }
01414 
01415 /************************************************************************
01416  * VarUI2FromDec (OLEAUT32.269)
01417  *
01418  * Convert a VT_DECIMAL to a VT_UI2.
01419  *
01420  * PARAMS
01421  *  pDecIn  [I] Source
01422  *  pusOut  [O] Destination
01423  *
01424  * RETURNS
01425  *  Success: S_OK.
01426  *  Failure: E_INVALIDARG, if the source value is invalid
01427  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01428  */
01429 HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
01430 {
01431   LONG64 i64;
01432   HRESULT hRet;
01433 
01434   hRet = VarI8FromDec(pdecIn, &i64);
01435 
01436   if (SUCCEEDED(hRet))
01437     hRet = _VarUI2FromI8(i64, pusOut);
01438   return hRet;
01439 }
01440 
01441 /************************************************************************
01442  * VarUI2FromI8 (OLEAUT32.378)
01443  *
01444  * Convert a VT_I8 to a VT_UI2.
01445  *
01446  * PARAMS
01447  *  llIn   [I] Source
01448  *  pusOut [O] Destination
01449  *
01450  * RETURNS
01451  *  Success: S_OK.
01452  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01453  */
01454 HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
01455 {
01456   return _VarUI2FromI8(llIn, pusOut);
01457 }
01458 
01459 /************************************************************************
01460  * VarUI2FromUI8 (OLEAUT32.379)
01461  *
01462  * Convert a VT_UI8 to a VT_UI2.
01463  *
01464  * PARAMS
01465  *  ullIn    [I] Source
01466  *  pusOut   [O] Destination
01467  *
01468  * RETURNS
01469  *  Success: S_OK.
01470  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01471  */
01472 HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
01473 {
01474   return _VarUI2FromUI8(ullIn, pusOut);
01475 }
01476 
01477 /* I4
01478  */
01479 
01480 /************************************************************************
01481  * VarI4FromUI1 (OLEAUT32.58)
01482  *
01483  * Convert a VT_UI1 to a VT_I4.
01484  *
01485  * PARAMS
01486  *  bIn     [I] Source
01487  *  piOut   [O] Destination
01488  *
01489  * RETURNS
01490  *  S_OK.
01491  */
01492 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
01493 {
01494   return _VarI4FromUI1(bIn, piOut);
01495 }
01496 
01497 /************************************************************************
01498  * VarI4FromI2 (OLEAUT32.59)
01499  *
01500  * Convert a VT_I2 to a VT_I4.
01501  *
01502  * PARAMS
01503  *  sIn     [I] Source
01504  *  piOut   [O] Destination
01505  *
01506  * RETURNS
01507  *  Success: S_OK.
01508  *  Failure: E_INVALIDARG, if the source value is invalid
01509  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01510  */
01511 HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
01512 {
01513   return _VarI4FromI2(sIn, piOut);
01514 }
01515 
01516 /************************************************************************
01517  * VarI4FromR4 (OLEAUT32.60)
01518  *
01519  * Convert a VT_R4 to a VT_I4.
01520  *
01521  * PARAMS
01522  *  fltIn   [I] Source
01523  *  piOut   [O] Destination
01524  *
01525  * RETURNS
01526  *  Success: S_OK.
01527  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01528  */
01529 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
01530 {
01531   return VarI4FromR8(fltIn, piOut);
01532 }
01533 
01534 /************************************************************************
01535  * VarI4FromR8 (OLEAUT32.61)
01536  *
01537  * Convert a VT_R8 to a VT_I4.
01538  *
01539  * PARAMS
01540  *  dblIn   [I] Source
01541  *  piOut   [O] Destination
01542  *
01543  * RETURNS
01544  *  Success: S_OK.
01545  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01546  *
01547  * NOTES
01548  *  See VarI8FromR8() for details concerning rounding.
01549  */
01550 HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
01551 {
01552   if (dblIn < (double)I4_MIN || dblIn > (double)I4_MAX)
01553     return DISP_E_OVERFLOW;
01554   VARIANT_DutchRound(LONG, dblIn, *piOut);
01555   return S_OK;
01556 }
01557 
01558 /************************************************************************
01559  * VarI4FromCy (OLEAUT32.62)
01560  *
01561  * Convert a VT_CY to a VT_I4.
01562  *
01563  * PARAMS
01564  *  cyIn    [I] Source
01565  *  piOut   [O] Destination
01566  *
01567  * RETURNS
01568  *  Success: S_OK.
01569  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01570  */
01571 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
01572 {
01573   double d = cyIn.int64 / CY_MULTIPLIER_F;
01574   return VarI4FromR8(d, piOut);
01575 }
01576 
01577 /************************************************************************
01578  * VarI4FromDate (OLEAUT32.63)
01579  *
01580  * Convert a VT_DATE to a VT_I4.
01581  *
01582  * PARAMS
01583  *  dateIn  [I] Source
01584  *  piOut   [O] Destination
01585  *
01586  * RETURNS
01587  *  Success: S_OK.
01588  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01589  */
01590 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
01591 {
01592   return VarI4FromR8(dateIn, piOut);
01593 }
01594 
01595 /************************************************************************
01596  * VarI4FromStr (OLEAUT32.64)
01597  *
01598  * Convert a VT_BSTR to a VT_I4.
01599  *
01600  * PARAMS
01601  *  strIn   [I] Source
01602  *  lcid    [I] LCID for the conversion
01603  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
01604  *  piOut   [O] Destination
01605  *
01606  * RETURNS
01607  *  Success: S_OK.
01608  *  Failure: E_INVALIDARG, if any parameter is invalid
01609  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01610  *           DISP_E_TYPEMISMATCH, if strIn cannot be converted
01611  */
01612 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
01613 {
01614   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, piOut, VT_I4);
01615 }
01616 
01617 /************************************************************************
01618  * VarI4FromDisp (OLEAUT32.65)
01619  *
01620  * Convert a VT_DISPATCH to a VT_I4.
01621  *
01622  * PARAMS
01623  *  pdispIn  [I] Source
01624  *  lcid     [I] LCID for conversion
01625  *  piOut    [O] Destination
01626  *
01627  * RETURNS
01628  *  Success: S_OK.
01629  *  Failure: E_INVALIDARG, if the source value is invalid
01630  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01631  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
01632  */
01633 HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
01634 {
01635   return VARIANT_FromDisp(pdispIn, lcid, piOut, VT_I4, 0);
01636 }
01637 
01638 /************************************************************************
01639  * VarI4FromBool (OLEAUT32.66)
01640  *
01641  * Convert a VT_BOOL to a VT_I4.
01642  *
01643  * PARAMS
01644  *  boolIn  [I] Source
01645  *  piOut   [O] Destination
01646  *
01647  * RETURNS
01648  *  S_OK.
01649  */
01650 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
01651 {
01652   return _VarI4FromBool(boolIn, piOut);
01653 }
01654 
01655 /************************************************************************
01656  * VarI4FromI1 (OLEAUT32.209)
01657  *
01658  * Convert a VT_I4 to a VT_I4.
01659  *
01660  * PARAMS
01661  *  cIn     [I] Source
01662  *  piOut   [O] Destination
01663  *
01664  * RETURNS
01665  *  S_OK.
01666  */
01667 HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
01668 {
01669   return _VarI4FromI1(cIn, piOut);
01670 }
01671 
01672 /************************************************************************
01673  * VarI4FromUI2 (OLEAUT32.210)
01674  *
01675  * Convert a VT_UI2 to a VT_I4.
01676  *
01677  * PARAMS
01678  *  usIn    [I] Source
01679  *  piOut   [O] Destination
01680  *
01681  * RETURNS
01682  *  S_OK.
01683  */
01684 HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
01685 {
01686   return _VarI4FromUI2(usIn, piOut);
01687 }
01688 
01689 /************************************************************************
01690  * VarI4FromUI4 (OLEAUT32.211)
01691  *
01692  * Convert a VT_UI4 to a VT_I4.
01693  *
01694  * PARAMS
01695  *  ulIn    [I] Source
01696  *  piOut   [O] Destination
01697  *
01698  * RETURNS
01699  *  Success: S_OK.
01700  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01701  */
01702 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
01703 {
01704   return _VarI4FromUI4(ulIn, piOut);
01705 }
01706 
01707 /************************************************************************
01708  * VarI4FromDec (OLEAUT32.212)
01709  *
01710  * Convert a VT_DECIMAL to a VT_I4.
01711  *
01712  * PARAMS
01713  *  pDecIn  [I] Source
01714  *  piOut   [O] Destination
01715  *
01716  * RETURNS
01717  *  Success: S_OK.
01718  *  Failure: E_INVALIDARG, if pdecIn is invalid
01719  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01720  */
01721 HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
01722 {
01723   LONG64 i64;
01724   HRESULT hRet;
01725 
01726   hRet = VarI8FromDec(pdecIn, &i64);
01727 
01728   if (SUCCEEDED(hRet))
01729     hRet = _VarI4FromI8(i64, piOut);
01730   return hRet;
01731 }
01732 
01733 /************************************************************************
01734  * VarI4FromI8 (OLEAUT32.348)
01735  *
01736  * Convert a VT_I8 to a VT_I4.
01737  *
01738  * PARAMS
01739  *  llIn  [I] Source
01740  *  piOut [O] Destination
01741  *
01742  * RETURNS
01743  *  Success: S_OK.
01744  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01745  */
01746 HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
01747 {
01748   return _VarI4FromI8(llIn, piOut);
01749 }
01750 
01751 /************************************************************************
01752  * VarI4FromUI8 (OLEAUT32.349)
01753  *
01754  * Convert a VT_UI8 to a VT_I4.
01755  *
01756  * PARAMS
01757  *  ullIn [I] Source
01758  *  piOut [O] Destination
01759  *
01760  * RETURNS
01761  *  Success: S_OK.
01762  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01763  */
01764 HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
01765 {
01766   return _VarI4FromUI8(ullIn, piOut);
01767 }
01768 
01769 /* UI4
01770  */
01771 
01772 /************************************************************************
01773  * VarUI4FromUI1 (OLEAUT32.270)
01774  *
01775  * Convert a VT_UI1 to a VT_UI4.
01776  *
01777  * PARAMS
01778  *  bIn    [I] Source
01779  *  pulOut [O] Destination
01780  *
01781  * RETURNS
01782  *  S_OK.
01783  */
01784 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
01785 {
01786   return _VarUI4FromUI1(bIn, pulOut);
01787 }
01788 
01789 /************************************************************************
01790  * VarUI4FromI2 (OLEAUT32.271)
01791  *
01792  * Convert a VT_I2 to a VT_UI4.
01793  *
01794  * PARAMS
01795  *  sIn    [I] Source
01796  *  pulOut [O] Destination
01797  *
01798  * RETURNS
01799  *  Success: S_OK.
01800  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01801  */
01802 HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
01803 {
01804   return _VarUI4FromI2(sIn, pulOut);
01805 }
01806 
01807 /************************************************************************
01808  * VarUI4FromI4 (OLEAUT32.272)
01809  *
01810  * Convert a VT_I4 to a VT_UI4.
01811  *
01812  * PARAMS
01813  *  iIn    [I] Source
01814  *  pulOut [O] Destination
01815  *
01816  * RETURNS
01817  *  Success: S_OK.
01818  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01819  */
01820 HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
01821 {
01822   return _VarUI4FromI4(iIn, pulOut);
01823 }
01824 
01825 /************************************************************************
01826  * VarUI4FromR4 (OLEAUT32.273)
01827  *
01828  * Convert a VT_R4 to a VT_UI4.
01829  *
01830  * PARAMS
01831  *  fltIn  [I] Source
01832  *  pulOut [O] Destination
01833  *
01834  * RETURNS
01835  *  Success: S_OK.
01836  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01837  */
01838 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
01839 {
01840   return VarUI4FromR8(fltIn, pulOut);
01841 }
01842 
01843 /************************************************************************
01844  * VarUI4FromR8 (OLEAUT32.274)
01845  *
01846  * Convert a VT_R8 to a VT_UI4.
01847  *
01848  * PARAMS
01849  *  dblIn  [I] Source
01850  *  pulOut [O] Destination
01851  *
01852  * RETURNS
01853  *  Success: S_OK.
01854  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01855  *
01856  * NOTES
01857  *  See VarI8FromR8() for details concerning rounding.
01858  */
01859 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
01860 {
01861   if (dblIn < -0.5 || dblIn > (double)UI4_MAX)
01862     return DISP_E_OVERFLOW;
01863   VARIANT_DutchRound(ULONG, dblIn, *pulOut);
01864   return S_OK;
01865 }
01866 
01867 /************************************************************************
01868  * VarUI4FromDate (OLEAUT32.275)
01869  *
01870  * Convert a VT_DATE to a VT_UI4.
01871  *
01872  * PARAMS
01873  *  dateIn [I] Source
01874  *  pulOut [O] Destination
01875  *
01876  * RETURNS
01877  *  Success: S_OK.
01878  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01879  */
01880 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
01881 {
01882   return VarUI4FromR8(dateIn, pulOut);
01883 }
01884 
01885 /************************************************************************
01886  * VarUI4FromCy (OLEAUT32.276)
01887  *
01888  * Convert a VT_CY to a VT_UI4.
01889  *
01890  * PARAMS
01891  *  cyIn   [I] Source
01892  *  pulOut [O] Destination
01893  *
01894  * RETURNS
01895  *  Success: S_OK.
01896  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01897  */
01898 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
01899 {
01900   double d = cyIn.int64 / CY_MULTIPLIER_F;
01901   return VarUI4FromR8(d, pulOut);
01902 }
01903 
01904 /************************************************************************
01905  * VarUI4FromStr (OLEAUT32.277)
01906  *
01907  * Convert a VT_BSTR to a VT_UI4.
01908  *
01909  * PARAMS
01910  *  strIn   [I] Source
01911  *  lcid    [I] LCID for the conversion
01912  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
01913  *  pulOut  [O] Destination
01914  *
01915  * RETURNS
01916  *  Success: S_OK.
01917  *  Failure: E_INVALIDARG, if any parameter is invalid
01918  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01919  *           DISP_E_TYPEMISMATCH, if strIn cannot be converted
01920  */
01921 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
01922 {
01923   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pulOut, VT_UI4);
01924 }
01925 
01926 /************************************************************************
01927  * VarUI4FromDisp (OLEAUT32.278)
01928  *
01929  * Convert a VT_DISPATCH to a VT_UI4.
01930  *
01931  * PARAMS
01932  *  pdispIn  [I] Source
01933  *  lcid     [I] LCID for conversion
01934  *  pulOut   [O] Destination
01935  *
01936  * RETURNS
01937  *  Success: S_OK.
01938  *  Failure: E_INVALIDARG, if the source value is invalid
01939  *           DISP_E_OVERFLOW, if the value will not fit in the destination
01940  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
01941  */
01942 HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
01943 {
01944   return VARIANT_FromDisp(pdispIn, lcid, pulOut, VT_UI4, 0);
01945 }
01946 
01947 /************************************************************************
01948  * VarUI4FromBool (OLEAUT32.279)
01949  *
01950  * Convert a VT_BOOL to a VT_UI4.
01951  *
01952  * PARAMS
01953  *  boolIn  [I] Source
01954  *  pulOut  [O] Destination
01955  *
01956  * RETURNS
01957  *  S_OK.
01958  */
01959 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
01960 {
01961   return _VarUI4FromBool(boolIn, pulOut);
01962 }
01963 
01964 /************************************************************************
01965  * VarUI4FromI1 (OLEAUT32.280)
01966  *
01967  * Convert a VT_I1 to a VT_UI4.
01968  *
01969  * PARAMS
01970  *  cIn    [I] Source
01971  *  pulOut [O] Destination
01972  *
01973  * RETURNS
01974  *  Success: S_OK.
01975  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
01976  */
01977 HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
01978 {
01979   return _VarUI4FromI1(cIn, pulOut);
01980 }
01981 
01982 /************************************************************************
01983  * VarUI4FromUI2 (OLEAUT32.281)
01984  *
01985  * Convert a VT_UI2 to a VT_UI4.
01986  *
01987  * PARAMS
01988  *  usIn   [I] Source
01989  *  pulOut [O] Destination
01990  *
01991  * RETURNS
01992  *  S_OK.
01993  */
01994 HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
01995 {
01996   return _VarUI4FromUI2(usIn, pulOut);
01997 }
01998 
01999 /************************************************************************
02000  * VarUI4FromDec (OLEAUT32.282)
02001  *
02002  * Convert a VT_DECIMAL to a VT_UI4.
02003  *
02004  * PARAMS
02005  *  pDecIn  [I] Source
02006  *  pulOut  [O] Destination
02007  *
02008  * RETURNS
02009  *  Success: S_OK.
02010  *  Failure: E_INVALIDARG, if pdecIn is invalid
02011  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02012  */
02013 HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
02014 {
02015   LONG64 i64;
02016   HRESULT hRet;
02017 
02018   hRet = VarI8FromDec(pdecIn, &i64);
02019 
02020   if (SUCCEEDED(hRet))
02021     hRet = _VarUI4FromI8(i64, pulOut);
02022   return hRet;
02023 }
02024 
02025 /************************************************************************
02026  * VarUI4FromI8 (OLEAUT32.425)
02027  *
02028  * Convert a VT_I8 to a VT_UI4.
02029  *
02030  * PARAMS
02031  *  llIn   [I] Source
02032  *  pulOut [O] Destination
02033  *
02034  * RETURNS
02035  *  Success: S_OK.
02036  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
02037  */
02038 HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
02039 {
02040   return _VarUI4FromI8(llIn, pulOut);
02041 }
02042 
02043 /************************************************************************
02044  * VarUI4FromUI8 (OLEAUT32.426)
02045  *
02046  * Convert a VT_UI8 to a VT_UI4.
02047  *
02048  * PARAMS
02049  *  ullIn    [I] Source
02050  *  pulOut   [O] Destination
02051  *
02052  * RETURNS
02053  *  Success: S_OK.
02054  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
02055  */
02056 HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
02057 {
02058   return _VarUI4FromUI8(ullIn, pulOut);
02059 }
02060 
02061 /* I8
02062  */
02063 
02064 /************************************************************************
02065  * VarI8FromUI1 (OLEAUT32.333)
02066  *
02067  * Convert a VT_UI1 to a VT_I8.
02068  *
02069  * PARAMS
02070  *  bIn     [I] Source
02071  *  pi64Out [O] Destination
02072  *
02073  * RETURNS
02074  *  S_OK.
02075  */
02076 HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
02077 {
02078   return _VarI8FromUI1(bIn, pi64Out);
02079 }
02080 
02081 
02082 /************************************************************************
02083  * VarI8FromI2 (OLEAUT32.334)
02084  *
02085  * Convert a VT_I2 to a VT_I8.
02086  *
02087  * PARAMS
02088  *  sIn     [I] Source
02089  *  pi64Out [O] Destination
02090  *
02091  * RETURNS
02092  *  S_OK.
02093  */
02094 HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
02095 {
02096   return _VarI8FromI2(sIn, pi64Out);
02097 }
02098 
02099 /************************************************************************
02100  * VarI8FromR4 (OLEAUT32.335)
02101  *
02102  * Convert a VT_R4 to a VT_I8.
02103  *
02104  * PARAMS
02105  *  fltIn   [I] Source
02106  *  pi64Out [O] Destination
02107  *
02108  * RETURNS
02109  *  Success: S_OK.
02110  *  Failure: E_INVALIDARG, if the source value is invalid
02111  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02112  */
02113 HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
02114 {
02115   return VarI8FromR8(fltIn, pi64Out);
02116 }
02117 
02118 /************************************************************************
02119  * VarI8FromR8 (OLEAUT32.336)
02120  *
02121  * Convert a VT_R8 to a VT_I8.
02122  *
02123  * PARAMS
02124  *  dblIn   [I] Source
02125  *  pi64Out [O] Destination
02126  *
02127  * RETURNS
02128  *  Success: S_OK.
02129  *  Failure: E_INVALIDARG, if the source value is invalid
02130  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02131  *
02132  * NOTES
02133  *  Only values that fit into 63 bits are accepted. Due to rounding issues,
02134  *  very high or low values will not be accurately converted.
02135  *
02136  *  Numbers are rounded using Dutch rounding, as follows:
02137  *
02138  *|  Fractional Part   Sign  Direction  Example
02139  *|  ---------------   ----  ---------  -------
02140  *|  < 0.5              +    Down        0.4 ->  0.0
02141  *|  < 0.5              -    Up         -0.4 ->  0.0
02142  *|  > 0.5              +    Up          0.6 ->  1.0
02143  *|  < 0.5              -    Up         -0.6 -> -1.0
02144  *|  = 0.5              +    Up/Down    Down if even, Up if odd
02145  *|  = 0.5              -    Up/Down    Up if even, Down if odd
02146  *
02147  *  This system is often used in supermarkets.
02148  */
02149 HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
02150 {
02151   if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
02152     return DISP_E_OVERFLOW;
02153   VARIANT_DutchRound(LONG64, dblIn, *pi64Out);
02154   return S_OK;
02155 }
02156 
02157 /************************************************************************
02158  * VarI8FromCy (OLEAUT32.337)
02159  *
02160  * Convert a VT_CY to a VT_I8.
02161  *
02162  * PARAMS
02163  *  cyIn    [I] Source
02164  *  pi64Out [O] Destination
02165  *
02166  * RETURNS
02167  *  S_OK.
02168  *
02169  * NOTES
02170  *  All negative numbers are rounded down by 1, including those that are
02171  *  evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
02172  *  Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
02173  *  for details.
02174  */
02175 HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
02176 {
02177   *pi64Out = cyIn.int64 / CY_MULTIPLIER;
02178 
02179   if (cyIn.int64 < 0)
02180     (*pi64Out)--; /* Mimic Win32 bug */
02181   else
02182   {
02183     cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
02184 
02185     if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
02186       (*pi64Out)++;
02187   }
02188   return S_OK;
02189 }
02190 
02191 /************************************************************************
02192  * VarI8FromDate (OLEAUT32.338)
02193  *
02194  * Convert a VT_DATE to a VT_I8.
02195  *
02196  * PARAMS
02197  *  dateIn  [I] Source
02198  *  pi64Out [O] Destination
02199  *
02200  * RETURNS
02201  *  Success: S_OK.
02202  *  Failure: E_INVALIDARG, if the source value is invalid
02203  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02204  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02205  */
02206 HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
02207 {
02208   return VarI8FromR8(dateIn, pi64Out);
02209 }
02210 
02211 /************************************************************************
02212  * VarI8FromStr (OLEAUT32.339)
02213  *
02214  * Convert a VT_BSTR to a VT_I8.
02215  *
02216  * PARAMS
02217  *  strIn   [I] Source
02218  *  lcid    [I] LCID for the conversion
02219  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
02220  *  pi64Out [O] Destination
02221  *
02222  * RETURNS
02223  *  Success: S_OK.
02224  *  Failure: E_INVALIDARG, if the source value is invalid
02225  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02226  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02227  */
02228 HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
02229 {
02230   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pi64Out, VT_I8);
02231 }
02232 
02233 /************************************************************************
02234  * VarI8FromDisp (OLEAUT32.340)
02235  *
02236  * Convert a VT_DISPATCH to a VT_I8.
02237  *
02238  * PARAMS
02239  *  pdispIn  [I] Source
02240  *  lcid     [I] LCID for conversion
02241  *  pi64Out  [O] Destination
02242  *
02243  * RETURNS
02244  *  Success: S_OK.
02245  *  Failure: E_INVALIDARG, if the source value is invalid
02246  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02247  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02248  */
02249 HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
02250 {
02251   return VARIANT_FromDisp(pdispIn, lcid, pi64Out, VT_I8, 0);
02252 }
02253 
02254 /************************************************************************
02255  * VarI8FromBool (OLEAUT32.341)
02256  *
02257  * Convert a VT_BOOL to a VT_I8.
02258  *
02259  * PARAMS
02260  *  boolIn  [I] Source
02261  *  pi64Out [O] Destination
02262  *
02263  * RETURNS
02264  *  S_OK.
02265  */
02266 HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
02267 {
02268   return VarI8FromI2(boolIn, pi64Out);
02269 }
02270 
02271 /************************************************************************
02272  * VarI8FromI1 (OLEAUT32.342)
02273  *
02274  * Convert a VT_I1 to a VT_I8.
02275  *
02276  * PARAMS
02277  *  cIn     [I] Source
02278  *  pi64Out [O] Destination
02279  *
02280  * RETURNS
02281  *  S_OK.
02282  */
02283 HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
02284 {
02285   return _VarI8FromI1(cIn, pi64Out);
02286 }
02287 
02288 /************************************************************************
02289  * VarI8FromUI2 (OLEAUT32.343)
02290  *
02291  * Convert a VT_UI2 to a VT_I8.
02292  *
02293  * PARAMS
02294  *  usIn    [I] Source
02295  *  pi64Out [O] Destination
02296  *
02297  * RETURNS
02298  *  S_OK.
02299  */
02300 HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
02301 {
02302   return _VarI8FromUI2(usIn, pi64Out);
02303 }
02304 
02305 /************************************************************************
02306  * VarI8FromUI4 (OLEAUT32.344)
02307  *
02308  * Convert a VT_UI4 to a VT_I8.
02309  *
02310  * PARAMS
02311  *  ulIn    [I] Source
02312  *  pi64Out [O] Destination
02313  *
02314  * RETURNS
02315  *  S_OK.
02316  */
02317 HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
02318 {
02319   return _VarI8FromUI4(ulIn, pi64Out);
02320 }
02321 
02322 /************************************************************************
02323  * VarI8FromDec (OLEAUT32.345)
02324  *
02325  * Convert a VT_DECIMAL to a VT_I8.
02326  *
02327  * PARAMS
02328  *  pDecIn  [I] Source
02329  *  pi64Out [O] Destination
02330  *
02331  * RETURNS
02332  *  Success: S_OK.
02333  *  Failure: E_INVALIDARG, if the source value is invalid
02334  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02335  */
02336 HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
02337 {
02338   if (!DEC_SCALE(pdecIn))
02339   {
02340     /* This decimal is just a 96 bit integer */
02341     if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
02342       return E_INVALIDARG;
02343 
02344     if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
02345       return DISP_E_OVERFLOW;
02346 
02347     if (DEC_SIGN(pdecIn))
02348       *pi64Out = -DEC_LO64(pdecIn);
02349     else
02350       *pi64Out = DEC_LO64(pdecIn);
02351     return S_OK;
02352   }
02353   else
02354   {
02355     /* Decimal contains a floating point number */
02356     HRESULT hRet;
02357     double dbl;
02358 
02359     hRet = VarR8FromDec(pdecIn, &dbl);
02360     if (SUCCEEDED(hRet))
02361       hRet = VarI8FromR8(dbl, pi64Out);
02362     return hRet;
02363   }
02364 }
02365 
02366 /************************************************************************
02367  * VarI8FromUI8 (OLEAUT32.427)
02368  *
02369  * Convert a VT_UI8 to a VT_I8.
02370  *
02371  * PARAMS
02372  *  ullIn   [I] Source
02373  *  pi64Out [O] Destination
02374  *
02375  * RETURNS
02376  *  Success: S_OK.
02377  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
02378  */
02379 HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
02380 {
02381   return _VarI8FromUI8(ullIn, pi64Out);
02382 }
02383 
02384 /* UI8
02385  */
02386 
02387 /************************************************************************
02388  * VarUI8FromI8 (OLEAUT32.428)
02389  *
02390  * Convert a VT_I8 to a VT_UI8.
02391  *
02392  * PARAMS
02393  *  ulIn     [I] Source
02394  *  pui64Out [O] Destination
02395  *
02396  * RETURNS
02397  *  Success: S_OK.
02398  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
02399  */
02400 HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
02401 {
02402   return _VarUI8FromI8(llIn, pui64Out);
02403 }
02404 
02405 /************************************************************************
02406  * VarUI8FromUI1 (OLEAUT32.429)
02407  *
02408  * Convert a VT_UI1 to a VT_UI8.
02409  *
02410  * PARAMS
02411  *  bIn      [I] Source
02412  *  pui64Out [O] Destination
02413  *
02414  * RETURNS
02415  *  S_OK.
02416  */
02417 HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
02418 {
02419   return _VarUI8FromUI1(bIn, pui64Out);
02420 }
02421 
02422 /************************************************************************
02423  * VarUI8FromI2 (OLEAUT32.430)
02424  *
02425  * Convert a VT_I2 to a VT_UI8.
02426  *
02427  * PARAMS
02428  *  sIn      [I] Source
02429  *  pui64Out [O] Destination
02430  *
02431  * RETURNS
02432  *  S_OK.
02433  */
02434 HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
02435 {
02436   return _VarUI8FromI2(sIn, pui64Out);
02437 }
02438 
02439 /************************************************************************
02440  * VarUI8FromR4 (OLEAUT32.431)
02441  *
02442  * Convert a VT_R4 to a VT_UI8.
02443  *
02444  * PARAMS
02445  *  fltIn    [I] Source
02446  *  pui64Out [O] Destination
02447  *
02448  * RETURNS
02449  *  Success: S_OK.
02450  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
02451  */
02452 HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
02453 {
02454   return VarUI8FromR8(fltIn, pui64Out);
02455 }
02456 
02457 /************************************************************************
02458  * VarUI8FromR8 (OLEAUT32.432)
02459  *
02460  * Convert a VT_R8 to a VT_UI8.
02461  *
02462  * PARAMS
02463  *  dblIn    [I] Source
02464  *  pui64Out [O] Destination
02465  *
02466  * RETURNS
02467  *  Success: S_OK.
02468  *  Failure: E_INVALIDARG, if the source value is invalid
02469  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02470  *
02471  * NOTES
02472  *  See VarI8FromR8() for details concerning rounding.
02473  */
02474 HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
02475 {
02476   if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
02477     return DISP_E_OVERFLOW;
02478   VARIANT_DutchRound(ULONG64, dblIn, *pui64Out);
02479   return S_OK;
02480 }
02481 
02482 /************************************************************************
02483  * VarUI8FromCy (OLEAUT32.433)
02484  *
02485  * Convert a VT_CY to a VT_UI8.
02486  *
02487  * PARAMS
02488  *  cyIn     [I] Source
02489  *  pui64Out [O] Destination
02490  *
02491  * RETURNS
02492  *  Success: S_OK.
02493  *  Failure: E_INVALIDARG, if the source value is invalid
02494  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02495  *
02496  * NOTES
02497  *  Negative values >= -5000 will be converted to 0.
02498  */
02499 HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
02500 {
02501   if (cyIn.int64 < 0)
02502   {
02503     if (cyIn.int64 < -CY_HALF)
02504       return DISP_E_OVERFLOW;
02505     *pui64Out = 0;
02506   }
02507   else
02508   {
02509     *pui64Out = cyIn.int64 / CY_MULTIPLIER;
02510 
02511     cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
02512 
02513     if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
02514       (*pui64Out)++;
02515   }
02516   return S_OK;
02517 }
02518 
02519 /************************************************************************
02520  * VarUI8FromDate (OLEAUT32.434)
02521  *
02522  * Convert a VT_DATE to a VT_UI8.
02523  *
02524  * PARAMS
02525  *  dateIn   [I] Source
02526  *  pui64Out [O] Destination
02527  *
02528  * RETURNS
02529  *  Success: S_OK.
02530  *  Failure: E_INVALIDARG, if the source value is invalid
02531  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02532  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02533  */
02534 HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
02535 {
02536   return VarUI8FromR8(dateIn, pui64Out);
02537 }
02538 
02539 /************************************************************************
02540  * VarUI8FromStr (OLEAUT32.435)
02541  *
02542  * Convert a VT_BSTR to a VT_UI8.
02543  *
02544  * PARAMS
02545  *  strIn    [I] Source
02546  *  lcid     [I] LCID for the conversion
02547  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
02548  *  pui64Out [O] Destination
02549  *
02550  * RETURNS
02551  *  Success: S_OK.
02552  *  Failure: E_INVALIDARG, if the source value is invalid
02553  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02554  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02555  */
02556 HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
02557 {
02558   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pui64Out, VT_UI8);
02559 }
02560 
02561 /************************************************************************
02562  * VarUI8FromDisp (OLEAUT32.436)
02563  *
02564  * Convert a VT_DISPATCH to a VT_UI8.
02565  *
02566  * PARAMS
02567  *  pdispIn   [I] Source
02568  *  lcid      [I] LCID for conversion
02569  *  pui64Out  [O] Destination
02570  *
02571  * RETURNS
02572  *  Success: S_OK.
02573  *  Failure: E_INVALIDARG, if the source value is invalid
02574  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02575  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02576  */
02577 HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
02578 {
02579   return VARIANT_FromDisp(pdispIn, lcid, pui64Out, VT_UI8, 0);
02580 }
02581 
02582 /************************************************************************
02583  * VarUI8FromBool (OLEAUT32.437)
02584  *
02585  * Convert a VT_BOOL to a VT_UI8.
02586  *
02587  * PARAMS
02588  *  boolIn   [I] Source
02589  *  pui64Out [O] Destination
02590  *
02591  * RETURNS
02592  *  Success: S_OK.
02593  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
02594  */
02595 HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
02596 {
02597   return VarI8FromI2(boolIn, (LONG64 *)pui64Out);
02598 }
02599 /************************************************************************
02600  * VarUI8FromI1 (OLEAUT32.438)
02601  *
02602  * Convert a VT_I1 to a VT_UI8.
02603  *
02604  * PARAMS
02605  *  cIn      [I] Source
02606  *  pui64Out [O] Destination
02607  *
02608  * RETURNS
02609  *  Success: S_OK.
02610  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
02611  */
02612 HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
02613 {
02614   return _VarUI8FromI1(cIn, pui64Out);
02615 }
02616 
02617 /************************************************************************
02618  * VarUI8FromUI2 (OLEAUT32.439)
02619  *
02620  * Convert a VT_UI2 to a VT_UI8.
02621  *
02622  * PARAMS
02623  *  usIn     [I] Source
02624  *  pui64Out [O] Destination
02625  *
02626  * RETURNS
02627  *  S_OK.
02628  */
02629 HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
02630 {
02631   return _VarUI8FromUI2(usIn, pui64Out);
02632 }
02633 
02634 /************************************************************************
02635  * VarUI8FromUI4 (OLEAUT32.440)
02636  *
02637  * Convert a VT_UI4 to a VT_UI8.
02638  *
02639  * PARAMS
02640  *  ulIn     [I] Source
02641  *  pui64Out [O] Destination
02642  *
02643  * RETURNS
02644  *  S_OK.
02645  */
02646 HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
02647 {
02648   return _VarUI8FromUI4(ulIn, pui64Out);
02649 }
02650 
02651 /************************************************************************
02652  * VarUI8FromDec (OLEAUT32.441)
02653  *
02654  * Convert a VT_DECIMAL to a VT_UI8.
02655  *
02656  * PARAMS
02657  *  pDecIn   [I] Source
02658  *  pui64Out [O] Destination
02659  *
02660  * RETURNS
02661  *  Success: S_OK.
02662  *  Failure: E_INVALIDARG, if the source value is invalid
02663  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02664  *
02665  * NOTES
02666  *  Under native Win32, if the source value has a scale of 0, its sign is
02667  *  ignored, i.e. this function takes the absolute value rather than fail
02668  *  with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
02669  *  (use VarAbs() on pDecIn first if you really want this behaviour).
02670  */
02671 HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
02672 {
02673   if (!DEC_SCALE(pdecIn))
02674   {
02675     /* This decimal is just a 96 bit integer */
02676     if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
02677       return E_INVALIDARG;
02678 
02679     if (DEC_HI32(pdecIn))
02680       return DISP_E_OVERFLOW;
02681 
02682     if (DEC_SIGN(pdecIn))
02683     {
02684       WARN("Sign would be ignored under Win32!\n");
02685       return DISP_E_OVERFLOW;
02686     }
02687 
02688     *pui64Out = DEC_LO64(pdecIn);
02689     return S_OK;
02690   }
02691   else
02692   {
02693     /* Decimal contains a floating point number */
02694     HRESULT hRet;
02695     double dbl;
02696 
02697     hRet = VarR8FromDec(pdecIn, &dbl);
02698     if (SUCCEEDED(hRet))
02699       hRet = VarUI8FromR8(dbl, pui64Out);
02700     return hRet;
02701   }
02702 }
02703 
02704 /* R4
02705  */
02706 
02707 /************************************************************************
02708  * VarR4FromUI1 (OLEAUT32.68)
02709  *
02710  * Convert a VT_UI1 to a VT_R4.
02711  *
02712  * PARAMS
02713  *  bIn     [I] Source
02714  *  pFltOut [O] Destination
02715  *
02716  * RETURNS
02717  *  S_OK.
02718  */
02719 HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
02720 {
02721   return _VarR4FromUI1(bIn, pFltOut);
02722 }
02723 
02724 /************************************************************************
02725  * VarR4FromI2 (OLEAUT32.69)
02726  *
02727  * Convert a VT_I2 to a VT_R4.
02728  *
02729  * PARAMS
02730  *  sIn     [I] Source
02731  *  pFltOut [O] Destination
02732  *
02733  * RETURNS
02734  *  S_OK.
02735  */
02736 HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
02737 {
02738   return _VarR4FromI2(sIn, pFltOut);
02739 }
02740 
02741 /************************************************************************
02742  * VarR4FromI4 (OLEAUT32.70)
02743  *
02744  * Convert a VT_I4 to a VT_R4.
02745  *
02746  * PARAMS
02747  *  sIn     [I] Source
02748  *  pFltOut [O] Destination
02749  *
02750  * RETURNS
02751  *  S_OK.
02752  */
02753 HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
02754 {
02755   return _VarR4FromI4(lIn, pFltOut);
02756 }
02757 
02758 /************************************************************************
02759  * VarR4FromR8 (OLEAUT32.71)
02760  *
02761  * Convert a VT_R8 to a VT_R4.
02762  *
02763  * PARAMS
02764  *  dblIn   [I] Source
02765  *  pFltOut [O] Destination
02766  *
02767  * RETURNS
02768  *  Success: S_OK.
02769  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
02770  */
02771 HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
02772 {
02773   double d = dblIn < 0.0 ? -dblIn : dblIn;
02774   if (d > R4_MAX) return DISP_E_OVERFLOW;
02775   *pFltOut = dblIn;
02776   return S_OK;
02777 }
02778 
02779 /************************************************************************
02780  * VarR4FromCy (OLEAUT32.72)
02781  *
02782  * Convert a VT_CY to a VT_R4.
02783  *
02784  * PARAMS
02785  *  cyIn    [I] Source
02786  *  pFltOut [O] Destination
02787  *
02788  * RETURNS
02789  *  S_OK.
02790  */
02791 HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
02792 {
02793   *pFltOut = (double)cyIn.int64 / CY_MULTIPLIER_F;
02794   return S_OK;
02795 }
02796 
02797 /************************************************************************
02798  * VarR4FromDate (OLEAUT32.73)
02799  *
02800  * Convert a VT_DATE to a VT_R4.
02801  *
02802  * PARAMS
02803  *  dateIn  [I] Source
02804  *  pFltOut [O] Destination
02805  *
02806  * RETURNS
02807  *  Success: S_OK.
02808  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
02809  */
02810 HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
02811 {
02812   return VarR4FromR8(dateIn, pFltOut);
02813 }
02814 
02815 /************************************************************************
02816  * VarR4FromStr (OLEAUT32.74)
02817  *
02818  * Convert a VT_BSTR to a VT_R4.
02819  *
02820  * PARAMS
02821  *  strIn   [I] Source
02822  *  lcid    [I] LCID for the conversion
02823  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
02824  *  pFltOut [O] Destination
02825  *
02826  * RETURNS
02827  *  Success: S_OK.
02828  *  Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
02829  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02830  */
02831 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
02832 {
02833   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pFltOut, VT_R4);
02834 }
02835 
02836 /************************************************************************
02837  * VarR4FromDisp (OLEAUT32.75)
02838  *
02839  * Convert a VT_DISPATCH to a VT_R4.
02840  *
02841  * PARAMS
02842  *  pdispIn  [I] Source
02843  *  lcid     [I] LCID for conversion
02844  *  pFltOut  [O] Destination
02845  *
02846  * RETURNS
02847  *  Success: S_OK.
02848  *  Failure: E_INVALIDARG, if the source value is invalid
02849  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02850  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02851  */
02852 HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
02853 {
02854   return VARIANT_FromDisp(pdispIn, lcid, pFltOut, VT_R4, 0);
02855 }
02856 
02857 /************************************************************************
02858  * VarR4FromBool (OLEAUT32.76)
02859  *
02860  * Convert a VT_BOOL to a VT_R4.
02861  *
02862  * PARAMS
02863  *  boolIn  [I] Source
02864  *  pFltOut [O] Destination
02865  *
02866  * RETURNS
02867  *  S_OK.
02868  */
02869 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
02870 {
02871   return VarR4FromI2(boolIn, pFltOut);
02872 }
02873 
02874 /************************************************************************
02875  * VarR4FromI1 (OLEAUT32.213)
02876  *
02877  * Convert a VT_I1 to a VT_R4.
02878  *
02879  * PARAMS
02880  *  cIn     [I] Source
02881  *  pFltOut [O] Destination
02882  *
02883  * RETURNS
02884  *  Success: S_OK.
02885  *  Failure: E_INVALIDARG, if the source value is invalid
02886  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02887  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02888  */
02889 HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
02890 {
02891   return _VarR4FromI1(cIn, pFltOut);
02892 }
02893 
02894 /************************************************************************
02895  * VarR4FromUI2 (OLEAUT32.214)
02896  *
02897  * Convert a VT_UI2 to a VT_R4.
02898  *
02899  * PARAMS
02900  *  usIn    [I] Source
02901  *  pFltOut [O] Destination
02902  *
02903  * RETURNS
02904  *  Success: S_OK.
02905  *  Failure: E_INVALIDARG, if the source value is invalid
02906  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02907  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02908  */
02909 HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
02910 {
02911   return _VarR4FromUI2(usIn, pFltOut);
02912 }
02913 
02914 /************************************************************************
02915  * VarR4FromUI4 (OLEAUT32.215)
02916  *
02917  * Convert a VT_UI4 to a VT_R4.
02918  *
02919  * PARAMS
02920  *  ulIn    [I] Source
02921  *  pFltOut [O] Destination
02922  *
02923  * RETURNS
02924  *  Success: S_OK.
02925  *  Failure: E_INVALIDARG, if the source value is invalid
02926  *           DISP_E_OVERFLOW, if the value will not fit in the destination
02927  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
02928  */
02929 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
02930 {
02931   return _VarR4FromUI4(ulIn, pFltOut);
02932 }
02933 
02934 /************************************************************************
02935  * VarR4FromDec (OLEAUT32.216)
02936  *
02937  * Convert a VT_DECIMAL to a VT_R4.
02938  *
02939  * PARAMS
02940  *  pDecIn  [I] Source
02941  *  pFltOut [O] Destination
02942  *
02943  * RETURNS
02944  *  Success: S_OK.
02945  *  Failure: E_INVALIDARG, if the source value is invalid.
02946  */
02947 HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
02948 {
02949   BYTE scale = DEC_SCALE(pDecIn);
02950   int divisor = 1;
02951   double highPart;
02952 
02953   if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
02954     return E_INVALIDARG;
02955 
02956   while (scale--)
02957     divisor *= 10;
02958 
02959   if (DEC_SIGN(pDecIn))
02960     divisor = -divisor;
02961 
02962   if (DEC_HI32(pDecIn))
02963   {
02964     highPart = (double)DEC_HI32(pDecIn) / (double)divisor;
02965     highPart *= 4294967296.0F;
02966     highPart *= 4294967296.0F;
02967   }
02968   else
02969     highPart = 0.0;
02970 
02971   *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
02972   return S_OK;
02973 }
02974 
02975 /************************************************************************
02976  * VarR4FromI8 (OLEAUT32.360)
02977  *
02978  * Convert a VT_I8 to a VT_R4.
02979  *
02980  * PARAMS
02981  *  ullIn   [I] Source
02982  *  pFltOut [O] Destination
02983  *
02984  * RETURNS
02985  *  S_OK.
02986  */
02987 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
02988 {
02989   return _VarR4FromI8(llIn, pFltOut);
02990 }
02991 
02992 /************************************************************************
02993  * VarR4FromUI8 (OLEAUT32.361)
02994  *
02995  * Convert a VT_UI8 to a VT_R4.
02996  *
02997  * PARAMS
02998  *  ullIn   [I] Source
02999  *  pFltOut [O] Destination
03000  *
03001  * RETURNS
03002  *  S_OK.
03003  */
03004 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
03005 {
03006   return _VarR4FromUI8(ullIn, pFltOut);
03007 }
03008 
03009 /************************************************************************
03010  * VarR4CmpR8 (OLEAUT32.316)
03011  *
03012  * Compare a VT_R4 to a VT_R8.
03013  *
03014  * PARAMS
03015  *  fltLeft  [I] Source
03016  *  dblRight [I] Value to compare
03017  *
03018  * RETURNS
03019  *  VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
03020  *  equal to or greater than dblRight respectively.
03021  */
03022 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
03023 {
03024   if (fltLeft < dblRight)
03025     return VARCMP_LT;
03026   else if (fltLeft > dblRight)
03027     return VARCMP_GT;
03028   return VARCMP_EQ;
03029 }
03030 
03031 /* R8
03032  */
03033 
03034 /************************************************************************
03035  * VarR8FromUI1 (OLEAUT32.78)
03036  *
03037  * Convert a VT_UI1 to a VT_R8.
03038  *
03039  * PARAMS
03040  *  bIn     [I] Source
03041  *  pDblOut [O] Destination
03042  *
03043  * RETURNS
03044  *  S_OK.
03045  */
03046 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
03047 {
03048   return _VarR8FromUI1(bIn, pDblOut);
03049 }
03050 
03051 /************************************************************************
03052  * VarR8FromI2 (OLEAUT32.79)
03053  *
03054  * Convert a VT_I2 to a VT_R8.
03055  *
03056  * PARAMS
03057  *  sIn     [I] Source
03058  *  pDblOut [O] Destination
03059  *
03060  * RETURNS
03061  *  S_OK.
03062  */
03063 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
03064 {
03065   return _VarR8FromI2(sIn, pDblOut);
03066 }
03067 
03068 /************************************************************************
03069  * VarR8FromI4 (OLEAUT32.80)
03070  *
03071  * Convert a VT_I4 to a VT_R8.
03072  *
03073  * PARAMS
03074  *  sIn     [I] Source
03075  *  pDblOut [O] Destination
03076  *
03077  * RETURNS
03078  *  S_OK.
03079  */
03080 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
03081 {
03082   return _VarR8FromI4(lIn, pDblOut);
03083 }
03084 
03085 /************************************************************************
03086  * VarR8FromR4 (OLEAUT32.81)
03087  *
03088  * Convert a VT_R4 to a VT_R8.
03089  *
03090  * PARAMS
03091  *  fltIn   [I] Source
03092  *  pDblOut [O] Destination
03093  *
03094  * RETURNS
03095  *  S_OK.
03096  */
03097 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
03098 {
03099   return _VarR8FromR4(fltIn, pDblOut);
03100 }
03101 
03102 /************************************************************************
03103  * VarR8FromCy (OLEAUT32.82)
03104  *
03105  * Convert a VT_CY to a VT_R8.
03106  *
03107  * PARAMS
03108  *  cyIn    [I] Source
03109  *  pDblOut [O] Destination
03110  *
03111  * RETURNS
03112  *  S_OK.
03113  */
03114 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
03115 {
03116   return _VarR8FromCy(cyIn, pDblOut);
03117 }
03118 
03119 /************************************************************************
03120  * VarR8FromDate (OLEAUT32.83)
03121  *
03122  * Convert a VT_DATE to a VT_R8.
03123  *
03124  * PARAMS
03125  *  dateIn  [I] Source
03126  *  pDblOut [O] Destination
03127  *
03128  * RETURNS
03129  *  S_OK.
03130  */
03131 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
03132 {
03133   return _VarR8FromDate(dateIn, pDblOut);
03134 }
03135 
03136 /************************************************************************
03137  * VarR8FromStr (OLEAUT32.84)
03138  *
03139  * Convert a VT_BSTR to a VT_R8.
03140  *
03141  * PARAMS
03142  *  strIn   [I] Source
03143  *  lcid    [I] LCID for the conversion
03144  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
03145  *  pDblOut [O] Destination
03146  *
03147  * RETURNS
03148  *  Success: S_OK.
03149  *  Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
03150  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03151  */
03152 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
03153 {
03154   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDblOut, VT_R8);
03155 }
03156 
03157 /************************************************************************
03158  * VarR8FromDisp (OLEAUT32.85)
03159  *
03160  * Convert a VT_DISPATCH to a VT_R8.
03161  *
03162  * PARAMS
03163  *  pdispIn  [I] Source
03164  *  lcid     [I] LCID for conversion
03165  *  pDblOut  [O] Destination
03166  *
03167  * RETURNS
03168  *  Success: S_OK.
03169  *  Failure: E_INVALIDARG, if the source value is invalid
03170  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03171  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03172  */
03173 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
03174 {
03175   return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8, 0);
03176 }
03177 
03178 /************************************************************************
03179  * VarR8FromBool (OLEAUT32.86)
03180  *
03181  * Convert a VT_BOOL to a VT_R8.
03182  *
03183  * PARAMS
03184  *  boolIn  [I] Source
03185  *  pDblOut [O] Destination
03186  *
03187  * RETURNS
03188  *  S_OK.
03189  */
03190 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
03191 {
03192   return VarR8FromI2(boolIn, pDblOut);
03193 }
03194 
03195 /************************************************************************
03196  * VarR8FromI1 (OLEAUT32.217)
03197  *
03198  * Convert a VT_I1 to a VT_R8.
03199  *
03200  * PARAMS
03201  *  cIn     [I] Source
03202  *  pDblOut [O] Destination
03203  *
03204  * RETURNS
03205  *  Success: S_OK.
03206  *  Failure: E_INVALIDARG, if the source value is invalid
03207  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03208  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03209  */
03210 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
03211 {
03212   return _VarR8FromI1(cIn, pDblOut);
03213 }
03214 
03215 /************************************************************************
03216  * VarR8FromUI2 (OLEAUT32.218)
03217  *
03218  * Convert a VT_UI2 to a VT_R8.
03219  *
03220  * PARAMS
03221  *  usIn    [I] Source
03222  *  pDblOut [O] Destination
03223  *
03224  * RETURNS
03225  *  Success: S_OK.
03226  *  Failure: E_INVALIDARG, if the source value is invalid
03227  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03228  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03229  */
03230 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
03231 {
03232   return _VarR8FromUI2(usIn, pDblOut);
03233 }
03234 
03235 /************************************************************************
03236  * VarR8FromUI4 (OLEAUT32.219)
03237  *
03238  * Convert a VT_UI4 to a VT_R8.
03239  *
03240  * PARAMS
03241  *  ulIn    [I] Source
03242  *  pDblOut [O] Destination
03243  *
03244  * RETURNS
03245  *  Success: S_OK.
03246  *  Failure: E_INVALIDARG, if the source value is invalid
03247  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03248  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03249  */
03250 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
03251 {
03252   return _VarR8FromUI4(ulIn, pDblOut);
03253 }
03254 
03255 /************************************************************************
03256  * VarR8FromDec (OLEAUT32.220)
03257  *
03258  * Convert a VT_DECIMAL to a VT_R8.
03259  *
03260  * PARAMS
03261  *  pDecIn  [I] Source
03262  *  pDblOut [O] Destination
03263  *
03264  * RETURNS
03265  *  Success: S_OK.
03266  *  Failure: E_INVALIDARG, if the source value is invalid.
03267  */
03268 HRESULT WINAPI VarR8FromDec(const DECIMAL* pDecIn, double *pDblOut)
03269 {
03270   BYTE scale = DEC_SCALE(pDecIn);
03271   double divisor = 1.0, highPart;
03272 
03273   if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
03274     return E_INVALIDARG;
03275 
03276   while (scale--)
03277     divisor *= 10;
03278 
03279   if (DEC_SIGN(pDecIn))
03280     divisor = -divisor;
03281 
03282   if (DEC_HI32(pDecIn))
03283   {
03284     highPart = (double)DEC_HI32(pDecIn) / divisor;
03285     highPart *= 4294967296.0F;
03286     highPart *= 4294967296.0F;
03287   }
03288   else
03289     highPart = 0.0;
03290 
03291   *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
03292   return S_OK;
03293 }
03294 
03295 /************************************************************************
03296  * VarR8FromI8 (OLEAUT32.362)
03297  *
03298  * Convert a VT_I8 to a VT_R8.
03299  *
03300  * PARAMS
03301  *  ullIn   [I] Source
03302  *  pDblOut [O] Destination
03303  *
03304  * RETURNS
03305  *  S_OK.
03306  */
03307 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
03308 {
03309   return _VarR8FromI8(llIn, pDblOut);
03310 }
03311 
03312 /************************************************************************
03313  * VarR8FromUI8 (OLEAUT32.363)
03314  *
03315  * Convert a VT_UI8 to a VT_R8.
03316  *
03317  * PARAMS
03318  *  ullIn   [I] Source
03319  *  pDblOut [O] Destination
03320  *
03321  * RETURNS
03322  *  S_OK.
03323  */
03324 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
03325 {
03326   return _VarR8FromUI8(ullIn, pDblOut);
03327 }
03328 
03329 /************************************************************************
03330  * VarR8Pow (OLEAUT32.315)
03331  *
03332  * Raise a VT_R8 to a power.
03333  *
03334  * PARAMS
03335  *  dblLeft [I] Source
03336  *  dblPow  [I] Power to raise dblLeft by
03337  *  pDblOut [O] Destination
03338  *
03339  * RETURNS
03340  *  S_OK. pDblOut contains dblLeft to the power of dblRight.
03341  */
03342 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
03343 {
03344   *pDblOut = pow(dblLeft, dblPow);
03345   return S_OK;
03346 }
03347 
03348 /************************************************************************
03349  * VarR8Round (OLEAUT32.317)
03350  *
03351  * Round a VT_R8 to a given number of decimal points.
03352  *
03353  * PARAMS
03354  *  dblIn   [I] Source
03355  *  nDig    [I] Number of decimal points to round to
03356  *  pDblOut [O] Destination for rounded number
03357  *
03358  * RETURNS
03359  *  Success: S_OK. pDblOut is rounded to nDig digits.
03360  *  Failure: E_INVALIDARG, if cDecimals is less than 0.
03361  *
03362  * NOTES
03363  *  The native version of this function rounds using the internal
03364  *  binary representation of the number. Wine uses the dutch rounding
03365  *  convention, so therefore small differences can occur in the value returned.
03366  *  MSDN says that you should use your own rounding function if you want
03367  *  rounding to be predictable in your application.
03368  */
03369 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
03370 {
03371   double scale, whole, fract;
03372 
03373   if (nDig < 0)
03374     return E_INVALIDARG;
03375 
03376   scale = pow(10.0, nDig);
03377 
03378   dblIn *= scale;
03379   whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
03380   fract = dblIn - whole;
03381 
03382   if (fract > 0.5)
03383     dblIn = whole + 1.0;
03384   else if (fract == 0.5)
03385     dblIn = whole + fmod(whole, 2.0);
03386   else if (fract >= 0.0)
03387     dblIn = whole;
03388   else if (fract == -0.5)
03389     dblIn = whole - fmod(whole, 2.0);
03390   else if (fract > -0.5)
03391     dblIn = whole;
03392   else
03393     dblIn = whole - 1.0;
03394 
03395   *pDblOut = dblIn / scale;
03396   return S_OK;
03397 }
03398 
03399 /* CY
03400  */
03401 
03402 /* Powers of 10 from 0..4 D.P. */
03403 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
03404   CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
03405 
03406 /************************************************************************
03407  * VarCyFromUI1 (OLEAUT32.98)
03408  *
03409  * Convert a VT_UI1 to a VT_CY.
03410  *
03411  * PARAMS
03412  *  bIn    [I] Source
03413  *  pCyOut [O] Destination
03414  *
03415  * RETURNS
03416  *  Success: S_OK.
03417  *  Failure: E_INVALIDARG, if the source value is invalid
03418  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03419  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03420  */
03421 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
03422 {
03423     pCyOut->int64 = (ULONG64)bIn * CY_MULTIPLIER;
03424     return S_OK;
03425 }
03426 
03427 /************************************************************************
03428  * VarCyFromI2 (OLEAUT32.99)
03429  *
03430  * Convert a VT_I2 to a VT_CY.
03431  *
03432  * PARAMS
03433  *  sIn    [I] Source
03434  *  pCyOut [O] Destination
03435  *
03436  * RETURNS
03437  *  Success: S_OK.
03438  *  Failure: E_INVALIDARG, if the source value is invalid
03439  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03440  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03441  */
03442 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
03443 {
03444     pCyOut->int64 = (LONG64)sIn * CY_MULTIPLIER;
03445     return S_OK;
03446 }
03447 
03448 /************************************************************************
03449  * VarCyFromI4 (OLEAUT32.100)
03450  *
03451  * Convert a VT_I4 to a VT_CY.
03452  *
03453  * PARAMS
03454  *  sIn    [I] Source
03455  *  pCyOut [O] Destination
03456  *
03457  * RETURNS
03458  *  Success: S_OK.
03459  *  Failure: E_INVALIDARG, if the source value is invalid
03460  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03461  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03462  */
03463 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
03464 {
03465     pCyOut->int64 = (LONG64)lIn * CY_MULTIPLIER;
03466     return S_OK;
03467 }
03468 
03469 /************************************************************************
03470  * VarCyFromR4 (OLEAUT32.101)
03471  *
03472  * Convert a VT_R4 to a VT_CY.
03473  *
03474  * PARAMS
03475  *  fltIn  [I] Source
03476  *  pCyOut [O] Destination
03477  *
03478  * RETURNS
03479  *  Success: S_OK.
03480  *  Failure: E_INVALIDARG, if the source value is invalid
03481  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03482  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03483  */
03484 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
03485 {
03486   return VarCyFromR8(fltIn, pCyOut);
03487 }
03488 
03489 /************************************************************************
03490  * VarCyFromR8 (OLEAUT32.102)
03491  *
03492  * Convert a VT_R8 to a VT_CY.
03493  *
03494  * PARAMS
03495  *  dblIn  [I] Source
03496  *  pCyOut [O] Destination
03497  *
03498  * RETURNS
03499  *  Success: S_OK.
03500  *  Failure: E_INVALIDARG, if the source value is invalid
03501  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03502  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03503  */
03504 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
03505 {
03506 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
03507   /* This code gives identical results to Win32 on Intel.
03508    * Here we use fp exceptions to catch overflows when storing the value.
03509    */
03510   static const unsigned short r8_fpcontrol = 0x137f;
03511   static const double r8_multiplier = CY_MULTIPLIER_F;
03512   unsigned short old_fpcontrol, result_fpstatus;
03513 
03514   /* Clear exceptions, save the old fp state and load the new state */
03515   __asm__ __volatile__( "fnclex" );
03516   __asm__ __volatile__( "fstcw %0"   :   "=m" (old_fpcontrol) : );
03517   __asm__ __volatile__( "fldcw %0"   : : "m"  (r8_fpcontrol) );
03518   /* Perform the conversion. */
03519   __asm__ __volatile__( "fldl  %0"   : : "m"  (dblIn) );
03520   __asm__ __volatile__( "fmull %0"   : : "m"  (r8_multiplier) );
03521   __asm__ __volatile__( "fistpll %0" : : "m"  (*pCyOut) );
03522   /* Save the resulting fp state, load the old state and clear exceptions */
03523   __asm__ __volatile__( "fstsw %0"   :   "=m" (result_fpstatus) : );
03524   __asm__ __volatile__( "fnclex" );
03525   __asm__ __volatile__( "fldcw %0"   : : "m"  (old_fpcontrol) );
03526 
03527   if (result_fpstatus & 0x9) /* Overflow | Invalid */
03528     return DISP_E_OVERFLOW;
03529 #else
03530   /* This version produces slightly different results for boundary cases */
03531   if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
03532     return DISP_E_OVERFLOW;
03533   dblIn *= CY_MULTIPLIER_F;
03534   VARIANT_DutchRound(LONG64, dblIn, pCyOut->int64);
03535 #endif
03536   return S_OK;
03537 }
03538 
03539 /************************************************************************
03540  * VarCyFromDate (OLEAUT32.103)
03541  *
03542  * Convert a VT_DATE to a VT_CY.
03543  *
03544  * PARAMS
03545  *  dateIn [I] Source
03546  *  pCyOut [O] Destination
03547  *
03548  * RETURNS
03549  *  Success: S_OK.
03550  *  Failure: E_INVALIDARG, if the source value is invalid
03551  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03552  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03553  */
03554 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
03555 {
03556   return VarCyFromR8(dateIn, pCyOut);
03557 }
03558 
03559 /************************************************************************
03560  * VarCyFromStr (OLEAUT32.104)
03561  *
03562  * Convert a VT_BSTR to a VT_CY.
03563  *
03564  * PARAMS
03565  *  strIn   [I] Source
03566  *  lcid    [I] LCID for the conversion
03567  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
03568  *  pCyOut  [O] Destination
03569  *
03570  * RETURNS
03571  *  Success: S_OK.
03572  *  Failure: E_INVALIDARG, if the source value is invalid
03573  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03574  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03575  */
03576 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
03577 {
03578   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pCyOut, VT_CY);
03579 }
03580 
03581 /************************************************************************
03582  * VarCyFromDisp (OLEAUT32.105)
03583  *
03584  * Convert a VT_DISPATCH to a VT_CY.
03585  *
03586  * PARAMS
03587  *  pdispIn [I] Source
03588  *  lcid    [I] LCID for conversion
03589  *  pCyOut  [O] Destination
03590  *
03591  * RETURNS
03592  *  Success: S_OK.
03593  *  Failure: E_INVALIDARG, if the source value is invalid
03594  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03595  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03596  */
03597 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
03598 {
03599   return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY, 0);
03600 }
03601 
03602 /************************************************************************
03603  * VarCyFromBool (OLEAUT32.106)
03604  *
03605  * Convert a VT_BOOL to a VT_CY.
03606  *
03607  * PARAMS
03608  *  boolIn [I] Source
03609  *  pCyOut [O] Destination
03610  *
03611  * RETURNS
03612  *  Success: S_OK.
03613  *  Failure: E_INVALIDARG, if the source value is invalid
03614  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03615  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03616  *
03617  * NOTES
03618  *  While the sign of the boolean is stored in the currency, the value is
03619  *  converted to either 0 or 1.
03620  */
03621 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
03622 {
03623     pCyOut->int64 = (LONG64)boolIn * CY_MULTIPLIER;
03624     return S_OK;
03625 }
03626 
03627 /************************************************************************
03628  * VarCyFromI1 (OLEAUT32.225)
03629  *
03630  * Convert a VT_I1 to a VT_CY.
03631  *
03632  * PARAMS
03633  *  cIn    [I] Source
03634  *  pCyOut [O] Destination
03635  *
03636  * RETURNS
03637  *  Success: S_OK.
03638  *  Failure: E_INVALIDARG, if the source value is invalid
03639  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03640  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03641  */
03642 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
03643 {
03644     pCyOut->int64 = (LONG64)cIn * CY_MULTIPLIER;
03645     return S_OK;
03646 }
03647 
03648 /************************************************************************
03649  * VarCyFromUI2 (OLEAUT32.226)
03650  *
03651  * Convert a VT_UI2 to a VT_CY.
03652  *
03653  * PARAMS
03654  *  usIn   [I] Source
03655  *  pCyOut [O] Destination
03656  *
03657  * RETURNS
03658  *  Success: S_OK.
03659  *  Failure: E_INVALIDARG, if the source value is invalid
03660  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03661  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03662  */
03663 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
03664 {
03665     pCyOut->int64 = (ULONG64)usIn * CY_MULTIPLIER;
03666     return S_OK;
03667 }
03668 
03669 /************************************************************************
03670  * VarCyFromUI4 (OLEAUT32.227)
03671  *
03672  * Convert a VT_UI4 to a VT_CY.
03673  *
03674  * PARAMS
03675  *  ulIn   [I] Source
03676  *  pCyOut [O] Destination
03677  *
03678  * RETURNS
03679  *  Success: S_OK.
03680  *  Failure: E_INVALIDARG, if the source value is invalid
03681  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03682  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03683  */
03684 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
03685 {
03686     pCyOut->int64 = (ULONG64)ulIn * CY_MULTIPLIER;
03687     return S_OK;
03688 }
03689 
03690 /************************************************************************
03691  * VarCyFromDec (OLEAUT32.228)
03692  *
03693  * Convert a VT_DECIMAL to a VT_CY.
03694  *
03695  * PARAMS
03696  *  pdecIn  [I] Source
03697  *  pCyOut  [O] Destination
03698  *
03699  * RETURNS
03700  *  Success: S_OK.
03701  *  Failure: E_INVALIDARG, if the source value is invalid
03702  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03703  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03704  */
03705 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
03706 {
03707   DECIMAL rounded;
03708   HRESULT hRet;
03709 
03710   hRet = VarDecRound(pdecIn, 4, &rounded);
03711 
03712   if (SUCCEEDED(hRet))
03713   {
03714     double d;
03715 
03716     if (DEC_HI32(&rounded))
03717       return DISP_E_OVERFLOW;
03718 
03719     /* Note: Without the casts this promotes to int64 which loses precision */
03720     d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
03721     if (DEC_SIGN(&rounded))
03722       d = -d;
03723     return VarCyFromR8(d, pCyOut);
03724   }
03725   return hRet;
03726 }
03727 
03728 /************************************************************************
03729  * VarCyFromI8 (OLEAUT32.366)
03730  *
03731  * Convert a VT_I8 to a VT_CY.
03732  *
03733  * PARAMS
03734  *  ullIn  [I] Source
03735  *  pCyOut [O] Destination
03736  *
03737  * RETURNS
03738  *  Success: S_OK.
03739  *  Failure: E_INVALIDARG, if the source value is invalid
03740  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03741  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03742  */
03743 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
03744 {
03745   if (llIn <= (I8_MIN/CY_MULTIPLIER) || llIn >= (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
03746   pCyOut->int64 = llIn * CY_MULTIPLIER;
03747   return S_OK;
03748 }
03749 
03750 /************************************************************************
03751  * VarCyFromUI8 (OLEAUT32.375)
03752  *
03753  * Convert a VT_UI8 to a VT_CY.
03754  *
03755  * PARAMS
03756  *  ullIn  [I] Source
03757  *  pCyOut [O] Destination
03758  *
03759  * RETURNS
03760  *  Success: S_OK.
03761  *  Failure: E_INVALIDARG, if the source value is invalid
03762  *           DISP_E_OVERFLOW, if the value will not fit in the destination
03763  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
03764  */
03765 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
03766 {
03767     if (ullIn >= (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
03768     pCyOut->int64 = ullIn * CY_MULTIPLIER;
03769     return S_OK;
03770 }
03771 
03772 /************************************************************************
03773  * VarCyAdd (OLEAUT32.299)
03774  *
03775  * Add one CY to another.
03776  *
03777  * PARAMS
03778  *  cyLeft  [I] Source
03779  *  cyRight [I] Value to add
03780  *  pCyOut  [O] Destination
03781  *
03782  * RETURNS
03783  *  Success: S_OK.
03784  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03785  */
03786 HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
03787 {
03788   double l,r;
03789   _VarR8FromCy(cyLeft, &l);
03790   _VarR8FromCy(cyRight, &r);
03791   l = l + r;
03792   return VarCyFromR8(l, pCyOut);
03793 }
03794 
03795 /************************************************************************
03796  * VarCyMul (OLEAUT32.303)
03797  *
03798  * Multiply one CY by another.
03799  *
03800  * PARAMS
03801  *  cyLeft  [I] Source
03802  *  cyRight [I] Value to multiply by
03803  *  pCyOut  [O] Destination
03804  *
03805  * RETURNS
03806  *  Success: S_OK.
03807  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03808  */
03809 HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
03810 {
03811   double l,r;
03812   _VarR8FromCy(cyLeft, &l);
03813   _VarR8FromCy(cyRight, &r);
03814   l = l * r;
03815   return VarCyFromR8(l, pCyOut);
03816 }
03817 
03818 /************************************************************************
03819  * VarCyMulI4 (OLEAUT32.304)
03820  *
03821  * Multiply one CY by a VT_I4.
03822  *
03823  * PARAMS
03824  *  cyLeft  [I] Source
03825  *  lRight  [I] Value to multiply by
03826  *  pCyOut  [O] Destination
03827  *
03828  * RETURNS
03829  *  Success: S_OK.
03830  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03831  */
03832 HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
03833 {
03834   double d;
03835 
03836   _VarR8FromCy(cyLeft, &d);
03837   d = d * lRight;
03838   return VarCyFromR8(d, pCyOut);
03839 }
03840 
03841 /************************************************************************
03842  * VarCySub (OLEAUT32.305)
03843  *
03844  * Subtract one CY from another.
03845  *
03846  * PARAMS
03847  *  cyLeft  [I] Source
03848  *  cyRight [I] Value to subtract
03849  *  pCyOut  [O] Destination
03850  *
03851  * RETURNS
03852  *  Success: S_OK.
03853  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03854  */
03855 HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
03856 {
03857   double l,r;
03858   _VarR8FromCy(cyLeft, &l);
03859   _VarR8FromCy(cyRight, &r);
03860   l = l - r;
03861   return VarCyFromR8(l, pCyOut);
03862 }
03863 
03864 /************************************************************************
03865  * VarCyAbs (OLEAUT32.306)
03866  *
03867  * Convert a VT_CY into its absolute value.
03868  *
03869  * PARAMS
03870  *  cyIn   [I] Source
03871  *  pCyOut [O] Destination
03872  *
03873  * RETURNS
03874  *  Success: S_OK. pCyOut contains the absolute value.
03875  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03876  */
03877 HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
03878 {
03879   if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
03880     return DISP_E_OVERFLOW;
03881 
03882   pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
03883   return S_OK;
03884 }
03885 
03886 /************************************************************************
03887  * VarCyFix (OLEAUT32.307)
03888  *
03889  * Return the integer part of a VT_CY.
03890  *
03891  * PARAMS
03892  *  cyIn   [I] Source
03893  *  pCyOut [O] Destination
03894  *
03895  * RETURNS
03896  *  Success: S_OK.
03897  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03898  *
03899  * NOTES
03900  *  - The difference between this function and VarCyInt() is that VarCyInt() rounds
03901  *    negative numbers away from 0, while this function rounds them towards zero.
03902  */
03903 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
03904 {
03905   pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
03906   pCyOut->int64 *= CY_MULTIPLIER;
03907   return S_OK;
03908 }
03909 
03910 /************************************************************************
03911  * VarCyInt (OLEAUT32.308)
03912  *
03913  * Return the integer part of a VT_CY.
03914  *
03915  * PARAMS
03916  *  cyIn   [I] Source
03917  *  pCyOut [O] Destination
03918  *
03919  * RETURNS
03920  *  Success: S_OK.
03921  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03922  *
03923  * NOTES
03924  *  - The difference between this function and VarCyFix() is that VarCyFix() rounds
03925  *    negative numbers towards 0, while this function rounds them away from zero.
03926  */
03927 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
03928 {
03929   pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
03930   pCyOut->int64 *= CY_MULTIPLIER;
03931 
03932   if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
03933   {
03934     pCyOut->int64 -= CY_MULTIPLIER;
03935   }
03936   return S_OK;
03937 }
03938 
03939 /************************************************************************
03940  * VarCyNeg (OLEAUT32.309)
03941  *
03942  * Change the sign of a VT_CY.
03943  *
03944  * PARAMS
03945  *  cyIn   [I] Source
03946  *  pCyOut [O] Destination
03947  *
03948  * RETURNS
03949  *  Success: S_OK.
03950  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
03951  */
03952 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
03953 {
03954   if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
03955     return DISP_E_OVERFLOW;
03956 
03957   pCyOut->int64 = -cyIn.int64;
03958   return S_OK;
03959 }
03960 
03961 /************************************************************************
03962  * VarCyRound (OLEAUT32.310)
03963  *
03964  * Change the precision of a VT_CY.
03965  *
03966  * PARAMS
03967  *  cyIn      [I] Source
03968  *  cDecimals [I] New number of decimals to keep
03969  *  pCyOut    [O] Destination
03970  *
03971  * RETURNS
03972  *  Success: S_OK.
03973  *  Failure: E_INVALIDARG, if cDecimals is less than 0.
03974  */
03975 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
03976 {
03977   if (cDecimals < 0)
03978     return E_INVALIDARG;
03979 
03980   if (cDecimals > 3)
03981   {
03982     /* Rounding to more precision than we have */
03983     *pCyOut = cyIn;
03984     return S_OK;
03985   }
03986   else
03987   {
03988     double d, div = CY_Divisors[cDecimals];
03989 
03990     _VarR8FromCy(cyIn, &d);
03991     d = d * div;
03992     VARIANT_DutchRound(LONGLONG, d, pCyOut->int64);
03993     d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
03994     VARIANT_DutchRound(LONGLONG, d, pCyOut->int64);
03995     return S_OK;
03996   }
03997 }
03998 
03999 /************************************************************************
04000  * VarCyCmp (OLEAUT32.311)
04001  *
04002  * Compare two VT_CY values.
04003  *
04004  * PARAMS
04005  *  cyLeft  [I] Source
04006  *  cyRight [I] Value to compare
04007  *
04008  * RETURNS
04009  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
04010  *           compare is less, equal or greater than source respectively.
04011  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
04012  */
04013 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
04014 {
04015   HRESULT hRet;
04016   CY result;
04017 
04018   /* Subtract right from left, and compare the result to 0 */
04019   hRet = VarCySub(cyLeft, cyRight, &result);
04020 
04021   if (SUCCEEDED(hRet))
04022   {
04023     if (result.int64 < 0)
04024       hRet = (HRESULT)VARCMP_LT;
04025     else if (result.int64 > 0)
04026       hRet = (HRESULT)VARCMP_GT;
04027     else
04028       hRet = (HRESULT)VARCMP_EQ;
04029   }
04030   return hRet;
04031 }
04032 
04033 /************************************************************************
04034  * VarCyCmpR8 (OLEAUT32.312)
04035  *
04036  * Compare a VT_CY to a double
04037  *
04038  * PARAMS
04039  *  cyLeft   [I] Currency Source
04040  *  dblRight [I] double to compare to cyLeft
04041  *
04042  * RETURNS
04043  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
04044  *           less than, equal to or greater than cyLeft respectively.
04045  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
04046  */
04047 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
04048 {
04049   HRESULT hRet;
04050   CY cyRight;
04051 
04052   hRet = VarCyFromR8(dblRight, &cyRight);
04053 
04054   if (SUCCEEDED(hRet))
04055     hRet = VarCyCmp(cyLeft, cyRight);
04056 
04057   return hRet;
04058 }
04059 
04060 /************************************************************************
04061  * VarCyMulI8 (OLEAUT32.329)
04062  *
04063  * Multiply a VT_CY by a VT_I8.
04064  *
04065  * PARAMS
04066  *  cyLeft  [I] Source
04067  *  llRight [I] Value to multiply by
04068  *  pCyOut  [O] Destination
04069  *
04070  * RETURNS
04071  *  Success: S_OK.
04072  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
04073  */
04074 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
04075 {
04076   double d;
04077 
04078   _VarR8FromCy(cyLeft, &d);
04079   d = d  * (double)llRight;
04080   return VarCyFromR8(d, pCyOut);
04081 }
04082 
04083 /* DECIMAL
04084  */
04085 
04086 /************************************************************************
04087  * VarDecFromUI1 (OLEAUT32.190)
04088  *
04089  * Convert a VT_UI1 to a DECIMAL.
04090  *
04091  * PARAMS
04092  *  bIn     [I] Source
04093  *  pDecOut [O] Destination
04094  *
04095  * RETURNS
04096  *  S_OK.
04097  */
04098 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
04099 {
04100   return VarDecFromUI4(bIn, pDecOut);
04101 }
04102 
04103 /************************************************************************
04104  * VarDecFromI2 (OLEAUT32.191)
04105  *
04106  * Convert a VT_I2 to a DECIMAL.
04107  *
04108  * PARAMS
04109  *  sIn     [I] Source
04110  *  pDecOut [O] Destination
04111  *
04112  * RETURNS
04113  *  S_OK.
04114  */
04115 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
04116 {
04117   return VarDecFromI4(sIn, pDecOut);
04118 }
04119 
04120 /************************************************************************
04121  * VarDecFromI4 (OLEAUT32.192)
04122  *
04123  * Convert a VT_I4 to a DECIMAL.
04124  *
04125  * PARAMS
04126  *  sIn     [I] Source
04127  *  pDecOut [O] Destination
04128  *
04129  * RETURNS
04130  *  S_OK.
04131  */
04132 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
04133 {
04134   DEC_HI32(pDecOut) = 0;
04135   DEC_MID32(pDecOut) = 0;
04136 
04137   if (lIn < 0)
04138   {
04139     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
04140     DEC_LO32(pDecOut) = -lIn;
04141   }
04142   else
04143   {
04144     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
04145     DEC_LO32(pDecOut) = lIn;
04146   }
04147   return S_OK;
04148 }
04149 
04150 #define LOCALE_EN_US        (MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT))
04151 
04152 /* internal representation of the value stored in a DECIMAL. The bytes are
04153    stored from LSB at index 0 to MSB at index 11
04154  */
04155 typedef struct DECIMAL_internal
04156 {
04157     DWORD bitsnum[3];  /* 96 significant bits, unsigned */
04158     unsigned char scale;      /* number scaled * 10 ^ -(scale) */
04159     unsigned int  sign : 1;   /* 0 - positive, 1 - negative */
04160 } VARIANT_DI;
04161 
04162 static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI * dest);
04163 static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest);
04164 static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to);
04165 static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to);
04166 
04167 /************************************************************************
04168  * VarDecFromR4 (OLEAUT32.193)
04169  *
04170  * Convert a VT_R4 to a DECIMAL.
04171  *
04172  * PARAMS
04173  *  fltIn   [I] Source
04174  *  pDecOut [O] Destination
04175  *
04176  * RETURNS
04177  *  S_OK.
04178  */
04179 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
04180 {
04181   VARIANT_DI di;
04182   HRESULT hres;
04183 
04184   hres = VARIANT_DI_FromR4(fltIn, &di);
04185   if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
04186   return hres;
04187 }
04188 
04189 /************************************************************************
04190  * VarDecFromR8 (OLEAUT32.194)
04191  *
04192  * Convert a VT_R8 to a DECIMAL.
04193  *
04194  * PARAMS
04195  *  dblIn   [I] Source
04196  *  pDecOut [O] Destination
04197  *
04198  * RETURNS
04199  *  S_OK.
04200  */
04201 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
04202 {
04203   VARIANT_DI di;
04204   HRESULT hres;
04205 
04206   hres = VARIANT_DI_FromR8(dblIn, &di);
04207   if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
04208   return hres;
04209 }
04210 
04211 /************************************************************************
04212  * VarDecFromDate (OLEAUT32.195)
04213  *
04214  * Convert a VT_DATE to a DECIMAL.
04215  *
04216  * PARAMS
04217  *  dateIn  [I] Source
04218  *  pDecOut [O] Destination
04219  *
04220  * RETURNS
04221  *  S_OK.
04222  */
04223 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
04224 {
04225   return VarDecFromR8(dateIn, pDecOut);
04226 }
04227 
04228 /************************************************************************
04229  * VarDecFromCy (OLEAUT32.196)
04230  *
04231  * Convert a VT_CY to a DECIMAL.
04232  *
04233  * PARAMS
04234  *  cyIn    [I] Source
04235  *  pDecOut [O] Destination
04236  *
04237  * RETURNS
04238  *  S_OK.
04239  */
04240 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
04241 {
04242   DEC_HI32(pDecOut) = 0;
04243 
04244   /* Note: This assumes 2s complement integer representation */
04245   if (cyIn.s.Hi & 0x80000000)
04246   {
04247     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
04248     DEC_LO64(pDecOut) = -cyIn.int64;
04249   }
04250   else
04251   {
04252     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
04253     DEC_MID32(pDecOut) = cyIn.s.Hi;
04254     DEC_LO32(pDecOut) = cyIn.s.Lo;
04255   }
04256   return S_OK;
04257 }
04258 
04259 /************************************************************************
04260  * VarDecFromStr (OLEAUT32.197)
04261  *
04262  * Convert a VT_BSTR to a DECIMAL.
04263  *
04264  * PARAMS
04265  *  strIn   [I] Source
04266  *  lcid    [I] LCID for the conversion
04267  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
04268  *  pDecOut [O] Destination
04269  *
04270  * RETURNS
04271  *  Success: S_OK.
04272  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
04273  */
04274 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
04275 {
04276   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDecOut, VT_DECIMAL);
04277 }
04278 
04279 /************************************************************************
04280  * VarDecFromDisp (OLEAUT32.198)
04281  *
04282  * Convert a VT_DISPATCH to a DECIMAL.
04283  *
04284  * PARAMS
04285  *  pdispIn  [I] Source
04286  *  lcid     [I] LCID for conversion
04287  *  pDecOut  [O] Destination
04288  *
04289  * RETURNS
04290  *  Success: S_OK.
04291  *  Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
04292  */
04293 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
04294 {
04295   return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL, 0);
04296 }
04297 
04298 /************************************************************************
04299  * VarDecFromBool (OLEAUT32.199)
04300  *
04301  * Convert a VT_BOOL to a DECIMAL.
04302  *
04303  * PARAMS
04304  *  bIn     [I] Source
04305  *  pDecOut [O] Destination
04306  *
04307  * RETURNS
04308  *  S_OK.
04309  *
04310  * NOTES
04311  *  The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
04312  */
04313 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
04314 {
04315   DEC_HI32(pDecOut) = 0;
04316   DEC_MID32(pDecOut) = 0;
04317   if (bIn)
04318   {
04319     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
04320     DEC_LO32(pDecOut) = 1;
04321   }
04322   else
04323   {
04324     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
04325     DEC_LO32(pDecOut) = 0;
04326   }
04327   return S_OK;
04328 }
04329 
04330 /************************************************************************
04331  * VarDecFromI1 (OLEAUT32.241)
04332  *
04333  * Convert a VT_I1 to a DECIMAL.
04334  *
04335  * PARAMS
04336  *  cIn     [I] Source
04337  *  pDecOut [O] Destination
04338  *
04339  * RETURNS
04340  *  S_OK.
04341  */
04342 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
04343 {
04344   return VarDecFromI4(cIn, pDecOut);
04345 }
04346 
04347 /************************************************************************
04348  * VarDecFromUI2 (OLEAUT32.242)
04349  *
04350  * Convert a VT_UI2 to a DECIMAL.
04351  *
04352  * PARAMS
04353  *  usIn    [I] Source
04354  *  pDecOut [O] Destination
04355  *
04356  * RETURNS
04357  *  S_OK.
04358  */
04359 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
04360 {
04361   return VarDecFromUI4(usIn, pDecOut);
04362 }
04363 
04364 /************************************************************************
04365  * VarDecFromUI4 (OLEAUT32.243)
04366  *
04367  * Convert a VT_UI4 to a DECIMAL.
04368  *
04369  * PARAMS
04370  *  ulIn    [I] Source
04371  *  pDecOut [O] Destination
04372  *
04373  * RETURNS
04374  *  S_OK.
04375  */
04376 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
04377 {
04378   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
04379   DEC_HI32(pDecOut) = 0;
04380   DEC_MID32(pDecOut) = 0;
04381   DEC_LO32(pDecOut) = ulIn;
04382   return S_OK;
04383 }
04384 
04385 /************************************************************************
04386  * VarDecFromI8 (OLEAUT32.374)
04387  *
04388  * Convert a VT_I8 to a DECIMAL.
04389  *
04390  * PARAMS
04391  *  llIn    [I] Source
04392  *  pDecOut [O] Destination
04393  *
04394  * RETURNS
04395  *  S_OK.
04396  */
04397 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
04398 {
04399   PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
04400 
04401   DEC_HI32(pDecOut) = 0;
04402 
04403   /* Note: This assumes 2s complement integer representation */
04404   if (pLi->u.HighPart & 0x80000000)
04405   {
04406     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
04407     DEC_LO64(pDecOut) = -pLi->QuadPart;
04408   }
04409   else
04410   {
04411     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
04412     DEC_MID32(pDecOut) = pLi->u.HighPart;
04413     DEC_LO32(pDecOut) = pLi->u.LowPart;
04414   }
04415   return S_OK;
04416 }
04417 
04418 /************************************************************************
04419  * VarDecFromUI8 (OLEAUT32.375)
04420  *
04421  * Convert a VT_UI8 to a DECIMAL.
04422  *
04423  * PARAMS
04424  *  ullIn   [I] Source
04425  *  pDecOut [O] Destination
04426  *
04427  * RETURNS
04428  *  S_OK.
04429  */
04430 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
04431 {
04432   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
04433   DEC_HI32(pDecOut) = 0;
04434   DEC_LO64(pDecOut) = ullIn;
04435   return S_OK;
04436 }
04437 
04438 /* Make two DECIMALS the same scale; used by math functions below */
04439 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
04440                                 const DECIMAL** ppDecRight,
04441                                 DECIMAL* pDecOut)
04442 {
04443   static DECIMAL scaleFactor;
04444   DECIMAL decTemp;
04445   int scaleAmount, i;
04446   HRESULT hRet = S_OK;
04447 
04448   if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
04449     return E_INVALIDARG;
04450 
04451   DEC_LO32(&scaleFactor) = 10;
04452 
04453   i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
04454 
04455   if (!scaleAmount)
04456     return S_OK; /* Same scale */
04457 
04458   if (scaleAmount > 0)
04459   {
04460     decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
04461     *ppDecRight = pDecOut;
04462   }
04463   else
04464   {
04465     decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
04466     *ppDecLeft = pDecOut;
04467     i = scaleAmount = -scaleAmount;
04468   }
04469 
04470   if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
04471     return DISP_E_OVERFLOW; /* Can't scale up */
04472 
04473   /* Multiply up the value to be scaled by the correct amount */
04474   while (SUCCEEDED(hRet) && i--)
04475   {
04476     /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
04477     hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
04478     decTemp = *pDecOut;
04479   }
04480   DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
04481   return hRet;
04482 }
04483 
04484 /* Add two unsigned 32 bit values with overflow */
04485 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
04486 {
04487   ULARGE_INTEGER ul64;
04488 
04489   ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
04490   *pulHigh = ul64.u.HighPart;
04491   return ul64.u.LowPart;
04492 }
04493 
04494 /* Subtract two unsigned 32 bit values with underflow */
04495 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
04496 {
04497   int invert = 0;
04498   ULARGE_INTEGER ul64;
04499 
04500   ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
04501   if (ulLeft < ulRight)
04502     invert = 1;
04503 
04504   if (ul64.QuadPart > (ULONG64)*pulHigh)
04505     ul64.QuadPart -= (ULONG64)*pulHigh;
04506   else
04507   {
04508     ul64.QuadPart -= (ULONG64)*pulHigh;
04509     invert = 1;
04510   }
04511   if (invert)
04512     ul64.u.HighPart = -ul64.u.HighPart ;
04513 
04514   *pulHigh = ul64.u.HighPart;
04515   return ul64.u.LowPart;
04516 }
04517 
04518 /* Multiply two unsigned 32 bit values with overflow */
04519 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
04520 {
04521   ULARGE_INTEGER ul64;
04522 
04523   ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
04524   *pulHigh = ul64.u.HighPart;
04525   return ul64.u.LowPart;
04526 }
04527 
04528 /* Compare two decimals that have the same scale */
04529 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
04530 {
04531   if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
04532       (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
04533     return -1;
04534   else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
04535     return 0;
04536   return 1;
04537 }
04538 
04539 /************************************************************************
04540  * VarDecAdd (OLEAUT32.177)
04541  *
04542  * Add one DECIMAL to another.
04543  *
04544  * PARAMS
04545  *  pDecLeft  [I] Source
04546  *  pDecRight [I] Value to add
04547  *  pDecOut   [O] Destination
04548  *
04549  * RETURNS
04550  *  Success: S_OK.
04551  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
04552  */
04553 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
04554 {
04555   HRESULT hRet;
04556   DECIMAL scaled;
04557 
04558   hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
04559 
04560   if (SUCCEEDED(hRet))
04561   {
04562     /* Our decimals now have the same scale, we can add them as 96 bit integers */
04563     ULONG overflow = 0;
04564     BYTE sign = DECIMAL_POS;
04565 
04566     /* Correct for the sign of the result */
04567     if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
04568     {
04569       /* -x + -y : Negative */
04570       sign = DECIMAL_NEG;
04571       goto VarDecAdd_AsPositive;
04572     }
04573     else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
04574     {
04575       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
04576 
04577       /* -x + y : Negative if x > y */
04578       if (cmp > 0)
04579       {
04580         sign = DECIMAL_NEG;
04581 VarDecAdd_AsNegative:
04582         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
04583         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
04584         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
04585       }
04586       else
04587       {
04588 VarDecAdd_AsInvertedNegative:
04589         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecRight),  DEC_LO32(pDecLeft),  &overflow);
04590         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
04591         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecRight),  DEC_HI32(pDecLeft),  &overflow);
04592       }
04593     }
04594     else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
04595     {
04596       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
04597 
04598       /* x + -y : Negative if x <= y */
04599       if (cmp <= 0)
04600       {
04601         sign = DECIMAL_NEG;
04602         goto VarDecAdd_AsInvertedNegative;
04603       }
04604       goto VarDecAdd_AsNegative;
04605     }
04606     else
04607     {
04608       /* x + y : Positive */
04609 VarDecAdd_AsPositive:
04610       DEC_LO32(pDecOut)  = VARIANT_Add(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
04611       DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
04612       DEC_HI32(pDecOut)  = VARIANT_Add(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
04613     }
04614 
04615     if (overflow)
04616       return DISP_E_OVERFLOW; /* overflowed */
04617 
04618     DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
04619     DEC_SIGN(pDecOut) = sign;
04620   }
04621   return hRet;
04622 }
04623 
04624 /* translate from external DECIMAL format into an internal representation */
04625 static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to)
04626 {
04627     to->scale = DEC_SCALE(from);
04628     to->sign = DEC_SIGN(from) ? 1 : 0;
04629 
04630     to->bitsnum[0] = DEC_LO32(from);
04631     to->bitsnum[1] = DEC_MID32(from);
04632     to->bitsnum[2] = DEC_HI32(from);
04633 }
04634 
04635 static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to)
04636 {
04637     if (from->sign) {
04638         DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_NEG, from->scale);
04639     } else {
04640         DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_POS, from->scale);
04641     }
04642 
04643     DEC_LO32(to) = from->bitsnum[0];
04644     DEC_MID32(to) = from->bitsnum[1];
04645     DEC_HI32(to) = from->bitsnum[2];
04646 }
04647 
04648 /* clear an internal representation of a DECIMAL */
04649 static void VARIANT_DI_clear(VARIANT_DI * i)
04650 {
04651     memset(i, 0, sizeof(VARIANT_DI));
04652 }
04653 
04654 /* divide the (unsigned) number stored in p (LSB) by a byte value (<= 0xff). Any nonzero
04655    size is supported. The value in p is replaced by the quotient of the division, and
04656    the remainder is returned as a result. This routine is most often used with a divisor
04657    of 10 in order to scale up numbers, and in the DECIMAL->string conversion.
04658  */
04659 static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor)
04660 {
04661     if (divisor == 0) {
04662         /* division by 0 */
04663         return 0xFF;
04664     } else if (divisor == 1) {
04665         /* dividend remains unchanged */
04666         return 0;
04667     } else {
04668         unsigned char remainder = 0;
04669         ULONGLONG iTempDividend;
04670         signed int i;
04671         
04672         for (i = n - 1; i >= 0 && !p[i]; i--);  /* skip leading zeros */
04673         for (; i >= 0; i--) {
04674             iTempDividend = ((ULONGLONG)remainder << 32) + p[i];
04675             remainder = iTempDividend % divisor;
04676             p[i] = iTempDividend / divisor;
04677         }
04678         
04679         return remainder;
04680     }
04681 }
04682 
04683 /* check to test if encoded number is a zero. Returns 1 if zero, 0 for nonzero */
04684 static int VARIANT_int_iszero(const DWORD * p, unsigned int n)
04685 {
04686     for (; n > 0; n--) if (*p++ != 0) return 0;
04687     return 1;
04688 }
04689 
04690 /* multiply two DECIMALS, without changing either one, and place result in third
04691    parameter. Result is normalized when scale is > 0. Attempts to remove significant
04692    digits when scale > 0 in order to fit an overflowing result. Final overflow
04693    flag is returned.
04694  */
04695 static int VARIANT_DI_mul(const VARIANT_DI * a, const VARIANT_DI * b, VARIANT_DI * result)
04696 {
04697     int r_overflow = 0;
04698     DWORD running[6];
04699     signed int mulstart;
04700 
04701     VARIANT_DI_clear(result);
04702     result->sign = (a->sign ^ b->sign) ? 1 : 0;
04703 
04704     /* Multiply 128-bit operands into a (max) 256-bit result. The scale
04705        of the result is formed by adding the scales of the operands.
04706      */
04707     result->scale = a->scale + b->scale;
04708     memset(running, 0, sizeof(running));
04709 
04710     /* count number of leading zero-bytes in operand A */
04711     for (mulstart = sizeof(a->bitsnum)/sizeof(DWORD) - 1; mulstart >= 0 && !a->bitsnum[mulstart]; mulstart--);
04712     if (mulstart < 0) {
04713         /* result is 0, because operand A is 0 */
04714         result->scale = 0;
04715         result->sign = 0;
04716     } else {
04717         unsigned char remainder = 0;
04718         int iA;        
04719 
04720         /* perform actual multiplication */
04721         for (iA = 0; iA <= mulstart; iA++) {
04722             ULONG iOverflowMul;
04723             int iB;
04724             
04725             for (iOverflowMul = 0, iB = 0; iB < sizeof(b->bitsnum)/sizeof(DWORD); iB++) {
04726                 ULONG iRV;
04727                 int iR;
04728                 
04729                 iRV = VARIANT_Mul(b->bitsnum[iB], a->bitsnum[iA], &iOverflowMul);
04730                 iR = iA + iB;
04731                 do {
04732                     running[iR] = VARIANT_Add(running[iR], 0, &iRV);
04733                     iR++;
04734                 } while (iRV);
04735             }
04736         }
04737 
04738 /* Too bad - native oleaut does not do this, so we should not either */
04739 #if 0
04740         /* While the result is divisible by 10, and the scale > 0, divide by 10.
04741            This operation should not lose significant digits, and gives an
04742            opportunity to reduce the possibility of overflows in future
04743            operations issued by the application.
04744          */
04745         while (result->scale > 0) {
04746             memcpy(quotient, running, sizeof(quotient));
04747             remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
04748             if (remainder > 0) break;
04749             memcpy(running, quotient, sizeof(quotient));
04750             result->scale--;
04751         }
04752 #endif
04753         /* While the 256-bit result overflows, and the scale > 0, divide by 10.
04754            This operation *will* lose significant digits of the result because
04755            all the factors of 10 were consumed by the previous operation.
04756         */
04757         while (result->scale > 0 && !VARIANT_int_iszero(
04758             running + sizeof(result->bitsnum) / sizeof(DWORD),
04759             (sizeof(running) - sizeof(result->bitsnum)) / sizeof(DWORD))) {
04760             
04761             remainder = VARIANT_int_divbychar(running, sizeof(running) / sizeof(DWORD), 10);
04762             if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
04763             result->scale--;
04764         }
04765         
04766         /* round up the result - native oleaut32 does this */
04767         if (remainder >= 5) {
04768             unsigned int i;
04769             for (remainder = 1, i = 0; i < sizeof(running)/sizeof(DWORD) && remainder; i++) {
04770                 ULONGLONG digit = running[i] + 1;
04771                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
04772                 running[i] = digit & 0xFFFFFFFF;
04773             }
04774         }
04775 
04776         /* Signal overflow if scale == 0 and 256-bit result still overflows,
04777            and copy result bits into result structure
04778         */
04779         r_overflow = !VARIANT_int_iszero(
04780             running + sizeof(result->bitsnum)/sizeof(DWORD), 
04781             (sizeof(running) - sizeof(result->bitsnum))/sizeof(DWORD));
04782         memcpy(result->bitsnum, running, sizeof(result->bitsnum));
04783     }
04784     return r_overflow;
04785 }
04786 
04787 /* cast DECIMAL into string. Any scale should be handled properly. en_US locale is
04788    hardcoded (period for decimal separator, dash as negative sign). Returns 0 for
04789    success, nonzero if insufficient space in output buffer.
04790  */
04791 static int VARIANT_DI_tostringW(const VARIANT_DI * a, WCHAR * s, unsigned int n)
04792 {
04793     int overflow = 0;
04794     DWORD quotient[3];
04795     unsigned char remainder;
04796     unsigned int i;
04797 
04798     /* place negative sign */
04799     if (!VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD)) && a->sign) {
04800         if (n > 0) {
04801             *s++ = '-';
04802             n--;
04803         }
04804         else overflow = 1;
04805     }
04806 
04807     /* prepare initial 0 */
04808     if (!overflow) {
04809         if (n >= 2) {
04810             s[0] = '0';
04811             s[1] = '\0';
04812         } else overflow = 1;
04813     }
04814 
04815     i = 0;
04816     memcpy(quotient, a->bitsnum, sizeof(a->bitsnum));
04817     while (!overflow && !VARIANT_int_iszero(quotient, sizeof(quotient) / sizeof(DWORD))) {
04818         remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
04819         if (i + 2 > n) {
04820             overflow = 1;
04821         } else {
04822             s[i++] = '0' + remainder;
04823             s[i] = '\0';
04824         }
04825     }
04826 
04827     if (!overflow && !VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD))) {
04828 
04829         /* reverse order of digits */
04830         WCHAR * x = s; WCHAR * y = s + i - 1;
04831         while (x < y) {
04832             *x ^= *y;
04833             *y ^= *x;
04834             *x++ ^= *y--;
04835         }
04836 
04837         /* check for decimal point. "i" now has string length */
04838         if (i <= a->scale) {
04839             unsigned int numzeroes = a->scale + 1 - i;
04840             if (i + 1 + numzeroes >= n) {
04841                 overflow = 1;
04842             } else {
04843                 memmove(s + numzeroes, s, (i + 1) * sizeof(WCHAR));
04844                 i += numzeroes;
04845                 while (numzeroes > 0) {
04846                     s[--numzeroes] = '0';
04847                 }
04848             }
04849         }
04850 
04851         /* place decimal point */
04852         if (a->scale > 0) {
04853             unsigned int periodpos = i - a->scale;
04854             if (i + 2 >= n) {
04855                 overflow = 1;
04856             } else {
04857                 memmove(s + periodpos + 1, s + periodpos, (i + 1 - periodpos) * sizeof(WCHAR));
04858                 s[periodpos] = '.'; i++;
04859                 
04860                 /* remove extra zeros at the end, if any */
04861                 while (s[i - 1] == '0') s[--i] = '\0';
04862                 if (s[i - 1] == '.') s[--i] = '\0';
04863             }
04864         }
04865     }
04866 
04867     return overflow;
04868 }
04869 
04870 /* shift the bits of a DWORD array to the left. p[0] is assumed LSB */
04871 static void VARIANT_int_shiftleft(DWORD * p, unsigned int n, unsigned int shift)
04872 {
04873     DWORD shifted;
04874     unsigned int i;
04875     
04876     /* shift whole DWORDs to the left */
04877     while (shift >= 32)
04878     {
04879         memmove(p + 1, p, (n - 1) * sizeof(DWORD));
04880         *p = 0; shift -= 32;
04881     }
04882     
04883     /* shift remainder (1..31 bits) */
04884     shifted = 0;
04885     if (shift > 0) for (i = 0; i < n; i++)
04886     {
04887         DWORD b;
04888         b = p[i] >> (32 - shift);
04889         p[i] = (p[i] << shift) | shifted;
04890         shifted = b;
04891     }
04892 }
04893 
04894 /* add the (unsigned) numbers stored in two DWORD arrays with LSB at index 0.
04895    Value at v is incremented by the value at p. Any size is supported, provided
04896    that v is not shorter than p. Any unapplied carry is returned as a result.
04897  */
04898 static unsigned char VARIANT_int_add(DWORD * v, unsigned int nv, const DWORD * p,
04899     unsigned int np)
04900 {
04901     unsigned char carry = 0;
04902 
04903     if (nv >= np) {
04904         ULONGLONG sum;
04905         unsigned int i;
04906 
04907         for (i = 0; i < np; i++) {
04908             sum = (ULONGLONG)v[i]
04909                 + (ULONGLONG)p[i]
04910                 + (ULONGLONG)carry;
04911             v[i] = sum & 0xffffffff;
04912             carry = sum >> 32;
04913         }
04914         for (; i < nv && carry; i++) {
04915             sum = (ULONGLONG)v[i]
04916                 + (ULONGLONG)carry;
04917             v[i] = sum & 0xffffffff;
04918             carry = sum >> 32;
04919         }
04920     }
04921     return carry;
04922 }
04923 
04924 /* perform integral division with operand p as dividend. Parameter n indicates 
04925    number of available DWORDs in divisor p, but available space in p must be 
04926    actually at least 2 * n DWORDs, because the remainder of the integral 
04927    division is built in the next n DWORDs past the start of the quotient. This 
04928    routine replaces the dividend in p with the quotient, and appends n 
04929    additional DWORDs for the remainder.
04930 
04931    Thanks to Lee & Mark Atkinson for their book _Using_C_ (my very first book on
04932    C/C++ :-) where the "longhand binary division" algorithm was exposed for the
04933    source code to the VLI (Very Large Integer) division operator. This algorithm
04934    was then heavily modified by me (Alex Villacis Lasso) in order to handle
04935    variably-scaled integers such as the MS DECIMAL representation.
04936  */
04937 static void VARIANT_int_div(DWORD * p, unsigned int n, const DWORD * divisor,
04938     unsigned int dn)
04939 {
04940     unsigned int i;
04941     DWORD tempsub[8];
04942     DWORD * negdivisor = tempsub + n;
04943 
04944     /* build 2s-complement of divisor */
04945     for (i = 0; i < n; i++) negdivisor[i] = (i < dn) ? ~divisor[i] : 0xFFFFFFFF;
04946     p[n] = 1;
04947     VARIANT_int_add(negdivisor, n, p + n, 1);
04948     memset(p + n, 0, n * sizeof(DWORD));
04949 
04950     /* skip all leading zero DWORDs in quotient */
04951     for (i = 0; i < n && !p[n - 1]; i++) VARIANT_int_shiftleft(p, n, 32);
04952     /* i is now number of DWORDs left to process */
04953     for (i <<= 5; i < (n << 5); i++) {
04954         VARIANT_int_shiftleft(p, n << 1, 1);    /* shl quotient+remainder */
04955 
04956         /* trial subtraction */
04957         memcpy(tempsub, p + n, n * sizeof(DWORD));
04958         VARIANT_int_add(tempsub, n, negdivisor, n);
04959 
04960         /* check whether result of subtraction was negative */
04961         if ((tempsub[n - 1] & 0x80000000) == 0) {
04962             memcpy(p + n, tempsub, n * sizeof(DWORD));
04963             p[0] |= 1;
04964         }
04965     }
04966 }
04967 
04968 /* perform integral multiplication by a byte operand. Used for scaling by 10 */
04969 static unsigned char VARIANT_int_mulbychar(DWORD * p, unsigned int n, unsigned char m)
04970 {
04971     unsigned int i;
04972     ULONG iOverflowMul;
04973     
04974     for (iOverflowMul = 0, i = 0; i < n; i++)
04975         p[i] = VARIANT_Mul(p[i], m, &iOverflowMul);
04976     return (unsigned char)iOverflowMul;
04977 }
04978 
04979 /* increment value in A by the value indicated in B, with scale adjusting. 
04980    Modifies parameters by adjusting scales. Returns 0 if addition was 
04981    successful, nonzero if a parameter underflowed before it could be 
04982    successfully used in the addition.
04983  */
04984 static int VARIANT_int_addlossy(
04985     DWORD * a, int * ascale, unsigned int an,
04986     DWORD * b, int * bscale, unsigned int bn)
04987 {
04988     int underflow = 0;
04989 
04990     if (VARIANT_int_iszero(a, an)) {
04991         /* if A is zero, copy B into A, after removing digits */
04992         while (bn > an && !VARIANT_int_iszero(b + an, bn - an)) {
04993             VARIANT_int_divbychar(b, bn, 10);
04994             (*bscale)--;
04995         }
04996         memcpy(a, b, an * sizeof(DWORD));
04997         *ascale = *bscale;
04998     } else if (!VARIANT_int_iszero(b, bn)) {
04999         unsigned int tn = an + 1;
05000         DWORD t[5];
05001 
05002         if (bn + 1 > tn) tn = bn + 1;
05003         if (*ascale != *bscale) {
05004             /* first (optimistic) try - try to scale down the one with the bigger
05005                scale, while this number is divisible by 10 */
05006             DWORD * digitchosen;
05007             unsigned int nchosen;
05008             int * scalechosen;
05009             int targetscale;
05010 
05011             if (*ascale < *bscale) {
05012                 targetscale = *ascale;
05013                 scalechosen = bscale;
05014                 digitchosen = b;
05015                 nchosen = bn;
05016             } else {
05017                 targetscale = *bscale;
05018                 scalechosen = ascale;
05019                 digitchosen = a;
05020                 nchosen = an;
05021             }
05022             memset(t, 0, tn * sizeof(DWORD));
05023             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
05024 
05025             /* divide by 10 until target scale is reached */
05026             while (*scalechosen > targetscale) {
05027                 unsigned char remainder = VARIANT_int_divbychar(t, tn, 10);
05028                 if (!remainder) {
05029                     (*scalechosen)--;
05030                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
05031                 } else break;
05032             }
05033         }
05034 
05035         if (*ascale != *bscale) {
05036             DWORD * digitchosen;
05037             unsigned int nchosen;
05038             int * scalechosen;
05039             int targetscale;
05040 
05041             /* try to scale up the one with the smaller scale */
05042             if (*ascale > *bscale) {
05043                 targetscale = *ascale;
05044                 scalechosen = bscale;
05045                 digitchosen = b;
05046                 nchosen = bn;
05047             } else {
05048                 targetscale = *bscale;
05049                 scalechosen = ascale;
05050                 digitchosen = a;
05051                 nchosen = an;
05052             }
05053             memset(t, 0, tn * sizeof(DWORD));
05054             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
05055 
05056             /* multiply by 10 until target scale is reached, or
05057                significant bytes overflow the number
05058              */
05059             while (*scalechosen < targetscale && t[nchosen] == 0) {
05060                 VARIANT_int_mulbychar(t, tn, 10);
05061                 if (t[nchosen] == 0) {
05062                     /* still does not overflow */
05063                     (*scalechosen)++;
05064                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
05065                 }
05066             }
05067         }
05068 
05069         if (*ascale != *bscale) {
05070             /* still different? try to scale down the one with the bigger scale
05071                (this *will* lose significant digits) */
05072             DWORD * digitchosen;
05073             unsigned int nchosen;
05074             int * scalechosen;
05075             int targetscale;
05076 
05077             if (*ascale < *bscale) {
05078                 targetscale = *ascale;
05079                 scalechosen = bscale;
05080                 digitchosen = b;
05081                 nchosen = bn;
05082             } else {
05083                 targetscale = *bscale;
05084                 scalechosen = ascale;
05085                 digitchosen = a;
05086                 nchosen = an;
05087             }
05088             memset(t, 0, tn * sizeof(DWORD));
05089             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
05090 
05091             /* divide by 10 until target scale is reached */
05092             while (*scalechosen > targetscale) {
05093                 VARIANT_int_divbychar(t, tn, 10);
05094                 (*scalechosen)--;
05095                 memcpy(digitchosen, t, nchosen * sizeof(DWORD));
05096             }
05097         }
05098 
05099         /* check whether any of the operands still has significant digits
05100            (underflow case 1)
05101          */
05102         if (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn)) {
05103             underflow = 1;
05104         } else {
05105             /* at this step, both numbers have the same scale and can be added
05106                as integers. However, the result might not fit in A, so further
05107                scaling down might be necessary.
05108              */
05109             while (!underflow) {
05110                 memset(t, 0, tn * sizeof(DWORD));
05111                 memcpy(t, a, an * sizeof(DWORD));
05112 
05113                 VARIANT_int_add(t, tn, b, bn);
05114                 if (VARIANT_int_iszero(t + an, tn - an)) {
05115                     /* addition was successful */
05116                     memcpy(a, t, an * sizeof(DWORD));
05117                     break;
05118                 } else {
05119                     /* addition overflowed - remove significant digits
05120                        from both operands and try again */
05121                     VARIANT_int_divbychar(a, an, 10); (*ascale)--;
05122                     VARIANT_int_divbychar(b, bn, 10); (*bscale)--;
05123                     /* check whether any operand keeps significant digits after
05124                        scaledown (underflow case 2)
05125                      */
05126                     underflow = (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn));
05127                 }
05128             }
05129         }
05130     }
05131     return underflow;
05132 }
05133 
05134 /* perform complete DECIMAL division in the internal representation. Returns
05135    0 if the division was completed (even if quotient is set to 0), or nonzero
05136    in case of quotient overflow.
05137  */
05138 static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * divisor,
05139                               VARIANT_DI * quotient)
05140 {
05141     HRESULT r_overflow = S_OK;
05142 
05143     if (VARIANT_int_iszero(divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD))) {
05144         /* division by 0 */
05145         r_overflow = DISP_E_DIVBYZERO;
05146     } else if (VARIANT_int_iszero(dividend->bitsnum, sizeof(dividend->bitsnum)/sizeof(DWORD))) {
05147         VARIANT_DI_clear(quotient);
05148     } else {
05149         int quotientscale, remainderscale, tempquotientscale;
05150         DWORD remainderplusquotient[8];
05151         int underflow;
05152 
05153         quotientscale = remainderscale = (int)dividend->scale - (int)divisor->scale;
05154         tempquotientscale = quotientscale;
05155         VARIANT_DI_clear(quotient);
05156         quotient->sign = (dividend->sign ^ divisor->sign) ? 1 : 0;
05157 
05158         /*  The following strategy is used for division
05159             1) if there was a nonzero remainder from previous iteration, use it as
05160                dividend for this iteration, else (for first iteration) use intended
05161                dividend
05162             2) perform integer division in temporary buffer, develop quotient in
05163                low-order part, remainder in high-order part
05164             3) add quotient from step 2 to final result, with possible loss of
05165                significant digits
05166             4) multiply integer part of remainder by 10, while incrementing the
05167                scale of the remainder. This operation preserves the intended value
05168                of the remainder.
05169             5) loop to step 1 until one of the following is true:
05170                 a) remainder is zero (exact division achieved)
05171                 b) addition in step 3 fails to modify bits in quotient (remainder underflow)
05172          */
05173         memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
05174         memcpy(remainderplusquotient, dividend->bitsnum, sizeof(dividend->bitsnum));
05175         do {
05176             VARIANT_int_div(
05177                 remainderplusquotient, 4,
05178                 divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD));
05179             underflow = VARIANT_int_addlossy(
05180                 quotient->bitsnum, &quotientscale, sizeof(quotient->bitsnum) / sizeof(DWORD),
05181                 remainderplusquotient, &tempquotientscale, 4);
05182             VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
05183             memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
05184             tempquotientscale = ++remainderscale;
05185         } while (!underflow && !VARIANT_int_iszero(remainderplusquotient + 4, 4));
05186 
05187         /* quotient scale might now be negative (extremely big number). If, so, try
05188            to multiply quotient by 10 (without overflowing), while adjusting the scale,
05189            until scale is 0. If this cannot be done, it is a real overflow.
05190          */
05191         while (r_overflow == S_OK && quotientscale < 0) {
05192             memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
05193             memcpy(remainderplusquotient, quotient->bitsnum, sizeof(quotient->bitsnum));
05194             VARIANT_int_mulbychar(remainderplusquotient, sizeof(remainderplusquotient)/sizeof(DWORD), 10);
05195             if (VARIANT_int_iszero(remainderplusquotient + sizeof(quotient->bitsnum)/sizeof(DWORD),
05196                 (sizeof(remainderplusquotient) - sizeof(quotient->bitsnum))/sizeof(DWORD))) {
05197                 quotientscale++;
05198                 memcpy(quotient->bitsnum, remainderplusquotient, sizeof(quotient->bitsnum));
05199             } else r_overflow = DISP_E_OVERFLOW;
05200         }
05201         if (r_overflow == S_OK) {
05202             if (quotientscale <= 255) quotient->scale = quotientscale;
05203             else VARIANT_DI_clear(quotient);
05204         }
05205     }
05206     return r_overflow;
05207 }
05208 
05209 /* This procedure receives a VARIANT_DI with a defined mantissa and sign, but
05210    with an undefined scale, which will be assigned to (if possible). It also
05211    receives an exponent of 2. This procedure will then manipulate the mantissa
05212    and calculate a corresponding scale, so that the exponent2 value is assimilated
05213    into the VARIANT_DI and is therefore no longer necessary. Returns S_OK if
05214    successful, or DISP_E_OVERFLOW if the represented value is too big to fit into
05215    a DECIMAL. */
05216 static HRESULT VARIANT_DI_normalize(VARIANT_DI * val, int exponent2, int isDouble)
05217 {
05218     HRESULT hres = S_OK;
05219     int exponent5, exponent10;
05220 
05221     /* A factor of 2^exponent2 is equivalent to (10^exponent2)/(5^exponent2), and
05222        thus equal to (5^-exponent2)*(10^exponent2). After all manipulations,
05223        exponent10 might be used to set the VARIANT_DI scale directly. However,
05224        the value of 5^-exponent5 must be assimilated into the VARIANT_DI. */
05225     exponent5 = -exponent2;
05226     exponent10 = exponent2;
05227 
05228     /* Handle exponent5 > 0 */
05229     while (exponent5 > 0) {
05230         char bPrevCarryBit;
05231         char bCurrCarryBit;
05232 
05233         /* In order to multiply the value represented by the VARIANT_DI by 5, it
05234            is best to multiply by 10/2. Therefore, exponent10 is incremented, and
05235            somehow the mantissa should be divided by 2.  */
05236         if ((val->bitsnum[0] & 1) == 0) {
05237             /* The mantissa is divisible by 2. Therefore the division can be done
05238                without losing significant digits. */
05239             exponent10++; exponent5--;
05240 
05241             /* Shift right */
05242             bPrevCarryBit = val->bitsnum[2] & 1;
05243             val->bitsnum[2] >>= 1;
05244             bCurrCarryBit = val->bitsnum[1] & 1;
05245             val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
05246             val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
05247         } else {
05248             /* The mantissa is NOT divisible by 2. Therefore the mantissa should
05249                be multiplied by 5, unless the multiplication overflows. */
05250             DWORD temp_bitsnum[3];
05251 
05252             exponent5--;
05253 
05254             memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
05255             if (0 == VARIANT_int_mulbychar(temp_bitsnum, 3, 5)) {
05256                 /* Multiplication succeeded without overflow, so copy result back
05257                    into VARIANT_DI */
05258                 memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
05259 
05260                 /* Mask out 3 extraneous bits introduced by the multiply */
05261             } else {
05262                 /* Multiplication by 5 overflows. The mantissa should be divided
05263                    by 2, and therefore will lose significant digits. */
05264                 exponent10++;
05265 
05266                 /* Shift right */
05267                 bPrevCarryBit = val->bitsnum[2] & 1;
05268                 val->bitsnum[2] >>= 1;
05269                 bCurrCarryBit = val->bitsnum[1] & 1;
05270                 val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
05271                 val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
05272             }
05273         }
05274     }
05275 
05276     /* Handle exponent5 < 0 */
05277     while (exponent5 < 0) {
05278         /* In order to divide the value represented by the VARIANT_DI by 5, it
05279            is best to multiply by 2/10. Therefore, exponent10 is decremented,
05280            and the mantissa should be multiplied by 2 */
05281         if ((val->bitsnum[2] & 0x80000000) == 0) {
05282             /* The mantissa can withstand a shift-left without overflowing */
05283             exponent10--; exponent5++;
05284             VARIANT_int_shiftleft(val->bitsnum, 3, 1);
05285         } else {
05286             /* The mantissa would overflow if shifted. Therefore it should be
05287                directly divided by 5. This will lose significant digits, unless
05288                by chance the mantissa happens to be divisible by 5 */
05289             exponent5++;
05290             VARIANT_int_divbychar(val->bitsnum, 3, 5);
05291         }
05292     }
05293 
05294     /* At this point, the mantissa has assimilated the exponent5, but the
05295        exponent10 might not be suitable for assignment. The exponent10 must be
05296        in the range [-DEC_MAX_SCALE..0], so the mantissa must be scaled up or
05297        down appropriately. */
05298     while (hres == S_OK && exponent10 > 0) {
05299         /* In order to bring exponent10 down to 0, the mantissa should be
05300            multiplied by 10 to compensate. If the exponent10 is too big, this
05301            will cause the mantissa to overflow. */
05302         if (0 == VARIANT_int_mulbychar(val->bitsnum, 3, 10)) {
05303             exponent10--;
05304         } else {
05305             hres = DISP_E_OVERFLOW;
05306         }
05307     }
05308     while (exponent10 < -DEC_MAX_SCALE) {
05309         int rem10;
05310         /* In order to bring exponent up to -DEC_MAX_SCALE, the mantissa should
05311            be divided by 10 to compensate. If the exponent10 is too small, this
05312            will cause the mantissa to underflow and become 0 */
05313         rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
05314         exponent10++;
05315         if (VARIANT_int_iszero(val->bitsnum, 3)) {
05316             /* Underflow, unable to keep dividing */
05317             exponent10 = 0;
05318         } else if (rem10 >= 5) {
05319             DWORD x = 1;
05320             VARIANT_int_add(val->bitsnum, 3, &x, 1);
05321         }
05322     }
05323     /* This step is required in order to remove excess bits of precision from the
05324        end of the bit representation, down to the precision guaranteed by the
05325        floating point number. */
05326     if (isDouble) {
05327         while (exponent10 < 0 && (val->bitsnum[2] != 0 || (val->bitsnum[2] == 0 && (val->bitsnum[1] & 0xFFE00000) != 0))) {
05328             int rem10;
05329 
05330             rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
05331             exponent10++;
05332             if (rem10 >= 5) {
05333                 DWORD x = 1;
05334                 VARIANT_int_add(val->bitsnum, 3, &x, 1);
05335             }
05336         }
05337     } else {
05338         while (exponent10 < 0 && (val->bitsnum[2] != 0 || val->bitsnum[1] != 0 ||
05339             (val->bitsnum[2] == 0 && val->bitsnum[1] == 0 && (val->bitsnum[0] & 0xFF000000) != 0))) {
05340             int rem10;
05341 
05342             rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
05343             exponent10++;
05344             if (rem10 >= 5) {
05345                 DWORD x = 1;
05346                 VARIANT_int_add(val->bitsnum, 3, &x, 1);
05347             }
05348         }
05349     }
05350     /* Remove multiples of 10 from the representation */
05351     while (exponent10 < 0) {
05352         DWORD temp_bitsnum[3];
05353 
05354         memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
05355         if (0 == VARIANT_int_divbychar(temp_bitsnum, 3, 10)) {
05356             exponent10++;
05357             memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
05358         } else break;
05359     }
05360 
05361     /* Scale assignment */
05362     if (hres == S_OK) val->scale = -exponent10;
05363 
05364     return hres;
05365 }
05366 
05367 typedef union
05368 {
05369     struct
05370     {
05371         unsigned int m : 23;
05372         unsigned int exp_bias : 8;
05373         unsigned int sign : 1;
05374     } i;
05375     float f;
05376 } R4_FIELDS;
05377 
05378 /* Convert a 32-bit floating point number into a DECIMAL, without using an
05379    intermediate string step. */
05380 static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI * dest)
05381 {
05382     HRESULT hres = S_OK;
05383     R4_FIELDS fx;
05384 
05385     fx.f = source;
05386 
05387     /* Detect special cases */
05388     if (fx.i.m == 0 && fx.i.exp_bias == 0) {
05389         /* Floating-point zero */
05390         VARIANT_DI_clear(dest);
05391     } else if (fx.i.m == 0  && fx.i.exp_bias == 0xFF) {
05392         /* Floating-point infinity */
05393         hres = DISP_E_OVERFLOW;
05394     } else if (fx.i.exp_bias == 0xFF) {
05395         /* Floating-point NaN */
05396         hres = DISP_E_BADVARTYPE;
05397     } else {
05398         int exponent2;
05399         VARIANT_DI_clear(dest);
05400 
05401         exponent2 = fx.i.exp_bias - 127;   /* Get unbiased exponent */
05402         dest->sign = fx.i.sign;             /* Sign is simply copied */
05403 
05404         /* Copy significant bits to VARIANT_DI mantissa */
05405         dest->bitsnum[0] = fx.i.m;
05406         dest->bitsnum[0] &= 0x007FFFFF;
05407         if (fx.i.exp_bias == 0) {
05408             /* Denormalized number - correct exponent */
05409             exponent2++;
05410         } else {
05411             /* Add hidden bit to mantissa */
05412             dest->bitsnum[0] |= 0x00800000;
05413         }
05414 
05415         /* The act of copying a FP mantissa as integer bits is equivalent to
05416            shifting left the mantissa 23 bits. The exponent2 is reduced to
05417            compensate. */
05418         exponent2 -= 23;
05419 
05420         hres = VARIANT_DI_normalize(dest, exponent2, 0);
05421     }
05422 
05423     return hres;
05424 }
05425 
05426 typedef union
05427 {
05428     struct
05429     {
05430         unsigned int m_lo : 32;     /* 52 bits of precision */
05431         unsigned int m_hi : 20;
05432         unsigned int exp_bias : 11; /* bias == 1023 */
05433         unsigned int sign : 1;
05434     } i;
05435     double d;
05436 } R8_FIELDS;
05437 
05438 /* Convert a 64-bit floating point number into a DECIMAL, without using an
05439    intermediate string step. */
05440 static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest)
05441 {
05442     HRESULT hres = S_OK;
05443     R8_FIELDS fx;
05444 
05445     fx.d = source;
05446 
05447     /* Detect special cases */
05448     if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0) {
05449         /* Floating-point zero */
05450         VARIANT_DI_clear(dest);
05451     } else if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0x7FF) {
05452         /* Floating-point infinity */
05453         hres = DISP_E_OVERFLOW;
05454     } else if (fx.i.exp_bias == 0x7FF) {
05455         /* Floating-point NaN */
05456         hres = DISP_E_BADVARTYPE;
05457     } else {
05458         int exponent2;
05459         VARIANT_DI_clear(dest);
05460 
05461         exponent2 = fx.i.exp_bias - 1023;   /* Get unbiased exponent */
05462         dest->sign = fx.i.sign;             /* Sign is simply copied */
05463 
05464         /* Copy significant bits to VARIANT_DI mantissa */
05465         dest->bitsnum[0] = fx.i.m_lo;
05466         dest->bitsnum[1] = fx.i.m_hi;
05467         dest->bitsnum[1] &= 0x000FFFFF;
05468         if (fx.i.exp_bias == 0) {
05469             /* Denormalized number - correct exponent */
05470             exponent2++;
05471         } else {
05472             /* Add hidden bit to mantissa */
05473             dest->bitsnum[1] |= 0x00100000;
05474         }
05475 
05476         /* The act of copying a FP mantissa as integer bits is equivalent to
05477            shifting left the mantissa 52 bits. The exponent2 is reduced to
05478            compensate. */
05479         exponent2 -= 52;
05480 
05481         hres = VARIANT_DI_normalize(dest, exponent2, 1);
05482     }
05483 
05484     return hres;
05485 }
05486 
05487 /************************************************************************
05488  * VarDecDiv (OLEAUT32.178)
05489  *
05490  * Divide one DECIMAL by another.
05491  *
05492  * PARAMS
05493  *  pDecLeft  [I] Source
05494  *  pDecRight [I] Value to divide by
05495  *  pDecOut   [O] Destination
05496  *
05497  * RETURNS
05498  *  Success: S_OK.
05499  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
05500  */
05501 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
05502 {
05503   HRESULT hRet = S_OK;
05504   VARIANT_DI di_left, di_right, di_result;
05505   HRESULT divresult;
05506 
05507   if (!pDecLeft || !pDecRight || !pDecOut) return E_INVALIDARG;
05508 
05509   VARIANT_DIFromDec(pDecLeft, &di_left);
05510   VARIANT_DIFromDec(pDecRight, &di_right);
05511   divresult = VARIANT_DI_div(&di_left, &di_right, &di_result);
05512   if (divresult != S_OK)
05513   {
05514       /* division actually overflowed */
05515       hRet = divresult;
05516   }
05517   else
05518   {
05519       hRet = S_OK;
05520 
05521       if (di_result.scale > DEC_MAX_SCALE)
05522       {
05523         unsigned char remainder = 0;
05524       
05525         /* division underflowed. In order to comply with the MSDN
05526            specifications for DECIMAL ranges, some significant digits
05527            must be removed
05528          */
05529         WARN("result scale is %u, scaling (with loss of significant digits)...\n",
05530             di_result.scale);
05531         while (di_result.scale > DEC_MAX_SCALE && 
05532                !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD)))
05533         {
05534             remainder = VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD), 10);
05535             di_result.scale--;
05536         }
05537         if (di_result.scale > DEC_MAX_SCALE)
05538         {
05539             WARN("result underflowed, setting to 0\n");
05540             di_result.scale = 0;
05541             di_result.sign = 0;
05542         }
05543         else if (remainder >= 5)    /* round up result - native oleaut32 does this */
05544         {
05545             unsigned int i;
05546             for (remainder = 1, i = 0; i < sizeof(di_result.bitsnum) / sizeof(DWORD) && remainder; i++) {
05547                 ULONGLONG digit = di_result.bitsnum[i] + 1;
05548                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
05549                 di_result.bitsnum[i] = digit & 0xFFFFFFFF;
05550             }
05551         }
05552       }
05553       VARIANT_DecFromDI(&di_result, pDecOut);
05554   }
05555   return hRet;
05556 }
05557 
05558 /************************************************************************
05559  * VarDecMul (OLEAUT32.179)
05560  *
05561  * Multiply one DECIMAL by another.
05562  *
05563  * PARAMS
05564  *  pDecLeft  [I] Source
05565  *  pDecRight [I] Value to multiply by
05566  *  pDecOut   [O] Destination
05567  *
05568  * RETURNS
05569  *  Success: S_OK.
05570  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
05571  */
05572 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
05573 {
05574   HRESULT hRet = S_OK;
05575   VARIANT_DI di_left, di_right, di_result;
05576   int mulresult;
05577 
05578   VARIANT_DIFromDec(pDecLeft, &di_left);
05579   VARIANT_DIFromDec(pDecRight, &di_right);
05580   mulresult = VARIANT_DI_mul(&di_left, &di_right, &di_result);
05581   if (mulresult)
05582   {
05583     /* multiplication actually overflowed */
05584     hRet = DISP_E_OVERFLOW;
05585   }
05586   else
05587   {
05588     if (di_result.scale > DEC_MAX_SCALE)
05589     {
05590       /* multiplication underflowed. In order to comply with the MSDN
05591          specifications for DECIMAL ranges, some significant digits
05592          must be removed
05593        */
05594       WARN("result scale is %u, scaling (with loss of significant digits)...\n",
05595           di_result.scale);
05596       while (di_result.scale > DEC_MAX_SCALE && 
05597             !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD)))
05598       {
05599         VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD), 10);
05600         di_result.scale--;
05601       }
05602       if (di_result.scale > DEC_MAX_SCALE)
05603       {
05604         WARN("result underflowed, setting to 0\n");
05605         di_result.scale = 0;
05606         di_result.sign = 0;
05607       }
05608     }
05609     VARIANT_DecFromDI(&di_result, pDecOut);
05610   }
05611   return hRet;
05612 }
05613 
05614 /************************************************************************
05615  * VarDecSub (OLEAUT32.181)
05616  *
05617  * Subtract one DECIMAL from another.
05618  *
05619  * PARAMS
05620  *  pDecLeft  [I] Source
05621  *  pDecRight [I] DECIMAL to subtract from pDecLeft
05622  *  pDecOut   [O] Destination
05623  *
05624  * RETURNS
05625  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
05626  */
05627 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
05628 {
05629   DECIMAL decRight;
05630 
05631   /* Implement as addition of the negative */
05632   VarDecNeg(pDecRight, &decRight);
05633   return VarDecAdd(pDecLeft, &decRight, pDecOut);
05634 }
05635 
05636 /************************************************************************
05637  * VarDecAbs (OLEAUT32.182)
05638  *
05639  * Convert a DECIMAL into its absolute value.
05640  *
05641  * PARAMS
05642  *  pDecIn  [I] Source
05643  *  pDecOut [O] Destination
05644  *
05645  * RETURNS
05646  *  S_OK. This function does not fail.
05647  */
05648 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
05649 {
05650   *pDecOut = *pDecIn;
05651   DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
05652   return S_OK;
05653 }
05654 
05655 /************************************************************************
05656  * VarDecFix (OLEAUT32.187)
05657  *
05658  * Return the integer portion of a DECIMAL.
05659  *
05660  * PARAMS
05661  *  pDecIn  [I] Source
05662  *  pDecOut [O] Destination
05663  *
05664  * RETURNS
05665  *  Success: S_OK.
05666  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
05667  *
05668  * NOTES
05669  *  - The difference between this function and VarDecInt() is that VarDecInt() rounds
05670  *    negative numbers away from 0, while this function rounds them towards zero.
05671  */
05672 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
05673 {
05674   double dbl;
05675   HRESULT hr;
05676 
05677   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
05678     return E_INVALIDARG;
05679 
05680   if (!DEC_SCALE(pDecIn))
05681   {
05682     *pDecOut = *pDecIn; /* Already an integer */
05683     return S_OK;
05684   }
05685 
05686   hr = VarR8FromDec(pDecIn, &dbl);
05687   if (SUCCEEDED(hr)) {
05688     LONGLONG rounded = dbl;
05689 
05690     hr = VarDecFromI8(rounded, pDecOut);
05691   }
05692   return hr;
05693 }
05694 
05695 /************************************************************************
05696  * VarDecInt (OLEAUT32.188)
05697  *
05698  * Return the integer portion of a DECIMAL.
05699  *
05700  * PARAMS
05701  *  pDecIn  [I] Source
05702  *  pDecOut [O] Destination
05703  *
05704  * RETURNS
05705  *  Success: S_OK.
05706  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
05707  *
05708  * NOTES
05709  *  - The difference between this function and VarDecFix() is that VarDecFix() rounds
05710  *    negative numbers towards 0, while this function rounds them away from zero.
05711  */
05712 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
05713 {
05714   double dbl;
05715   HRESULT hr;
05716 
05717   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
05718     return E_INVALIDARG;
05719 
05720   if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
05721     return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
05722 
05723   hr = VarR8FromDec(pDecIn, &dbl);
05724   if (SUCCEEDED(hr)) {
05725     LONGLONG rounded = dbl >= 0.0 ? dbl + 0.5 : dbl - 0.5;
05726 
05727     hr = VarDecFromI8(rounded, pDecOut);
05728   }
05729   return hr;
05730 }
05731 
05732 /************************************************************************
05733  * VarDecNeg (OLEAUT32.189)
05734  *
05735  * Change the sign of a DECIMAL.
05736  *
05737  * PARAMS
05738  *  pDecIn  [I] Source
05739  *  pDecOut [O] Destination
05740  *
05741  * RETURNS
05742  *  S_OK. This function does not fail.
05743  */
05744 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
05745 {
05746   *pDecOut = *pDecIn;
05747   DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
05748   return S_OK;
05749 }
05750 
05751 /************************************************************************
05752  * VarDecRound (OLEAUT32.203)
05753  *
05754  * Change the precision of a DECIMAL.
05755  *
05756  * PARAMS
05757  *  pDecIn    [I] Source
05758  *  cDecimals [I] New number of decimals to keep
05759  *  pDecOut   [O] Destination
05760  *
05761  * RETURNS
05762  *  Success: S_OK. pDecOut contains the rounded value.
05763  *  Failure: E_INVALIDARG if any argument is invalid.
05764  */
05765 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
05766 {
05767   if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
05768     return E_INVALIDARG;
05769 
05770   if (cDecimals >= DEC_SCALE(pDecIn))
05771   {
05772     *pDecOut = *pDecIn; /* More precision than we have */
05773     return S_OK;
05774   }
05775 
05776   FIXME("semi-stub!\n");
05777 
05778   return DISP_E_OVERFLOW;
05779 }
05780 
05781 /************************************************************************
05782  * VarDecCmp (OLEAUT32.204)
05783  *
05784  * Compare two DECIMAL values.
05785  *
05786  * PARAMS
05787  *  pDecLeft  [I] Source
05788  *  pDecRight [I] Value to compare
05789  *
05790  * RETURNS
05791  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
05792  *           is less than, equal to or greater than pDecRight respectively.
05793  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
05794  */
05795 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
05796 {
05797   HRESULT hRet;
05798   DECIMAL result;
05799 
05800   if (!pDecLeft || !pDecRight)
05801     return VARCMP_NULL;
05802 
05803   if ((!(DEC_SIGN(pDecLeft) & DECIMAL_NEG)) && (DEC_SIGN(pDecRight) & DECIMAL_NEG) &&
05804       (DEC_HI32(pDecLeft) | DEC_MID32(pDecLeft) | DEC_LO32(pDecLeft)))
05805     return VARCMP_GT;
05806   else if ((DEC_SIGN(pDecLeft) & DECIMAL_NEG) && (!(DEC_SIGN(pDecRight) & DECIMAL_NEG)) &&
05807       (DEC_HI32(pDecLeft) | DEC_MID32(pDecLeft) | DEC_LO32(pDecLeft)))
05808     return VARCMP_LT;
05809 
05810   /* Subtract right from left, and compare the result to 0 */
05811   hRet = VarDecSub(pDecLeft, pDecRight, &result);
05812 
05813   if (SUCCEEDED(hRet))
05814   {
05815     int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
05816 
05817     if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
05818       hRet = (HRESULT)VARCMP_LT;
05819     else if (non_zero)
05820       hRet = (HRESULT)VARCMP_GT;
05821     else
05822       hRet = (HRESULT)VARCMP_EQ;
05823   }
05824   return hRet;
05825 }
05826 
05827 /************************************************************************
05828  * VarDecCmpR8 (OLEAUT32.298)
05829  *
05830  * Compare a DECIMAL to a double
05831  *
05832  * PARAMS
05833  *  pDecLeft [I] DECIMAL Source
05834  *  dblRight [I] double to compare to pDecLeft
05835  *
05836  * RETURNS
05837  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
05838  *           is less than, equal to or greater than pDecLeft respectively.
05839  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
05840  */
05841 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
05842 {
05843   HRESULT hRet;
05844   DECIMAL decRight;
05845 
05846   hRet = VarDecFromR8(dblRight, &decRight);
05847 
05848   if (SUCCEEDED(hRet))
05849     hRet = VarDecCmp(pDecLeft, &decRight);
05850 
05851   return hRet;
05852 }
05853 
05854 /* BOOL
05855  */
05856 
05857 /************************************************************************
05858  * VarBoolFromUI1 (OLEAUT32.118)
05859  *
05860  * Convert a VT_UI1 to a VT_BOOL.
05861  *
05862  * PARAMS
05863  *  bIn      [I] Source
05864  *  pBoolOut [O] Destination
05865  *
05866  * RETURNS
05867  *  S_OK.
05868  */
05869 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
05870 {
05871   *pBoolOut = bIn ? VARIANT_TRUE : VARIANT_FALSE;
05872   return S_OK;
05873 }
05874 
05875 /************************************************************************
05876  * VarBoolFromI2 (OLEAUT32.119)
05877  *
05878  * Convert a VT_I2 to a VT_BOOL.
05879  *
05880  * PARAMS
05881  *  sIn      [I] Source
05882  *  pBoolOut [O] Destination
05883  *
05884  * RETURNS
05885  *  S_OK.
05886  */
05887 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
05888 {
05889   *pBoolOut = sIn ? VARIANT_TRUE : VARIANT_FALSE;
05890   return S_OK;
05891 }
05892 
05893 /************************************************************************
05894  * VarBoolFromI4 (OLEAUT32.120)
05895  *
05896  * Convert a VT_I4 to a VT_BOOL.
05897  *
05898  * PARAMS
05899  *  sIn      [I] Source
05900  *  pBoolOut [O] Destination
05901  *
05902  * RETURNS
05903  *  S_OK.
05904  */
05905 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
05906 {
05907   *pBoolOut = lIn ? VARIANT_TRUE : VARIANT_FALSE;
05908   return S_OK;
05909 }
05910 
05911 /************************************************************************
05912  * VarBoolFromR4 (OLEAUT32.121)
05913  *
05914  * Convert a VT_R4 to a VT_BOOL.
05915  *
05916  * PARAMS
05917  *  fltIn    [I] Source
05918  *  pBoolOut [O] Destination
05919  *
05920  * RETURNS
05921  *  S_OK.
05922  */
05923 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
05924 {
05925   *pBoolOut = fltIn ? VARIANT_TRUE : VARIANT_FALSE;
05926   return S_OK;
05927 }
05928 
05929 /************************************************************************
05930  * VarBoolFromR8 (OLEAUT32.122)
05931  *
05932  * Convert a VT_R8 to a VT_BOOL.
05933  *
05934  * PARAMS
05935  *  dblIn    [I] Source
05936  *  pBoolOut [O] Destination
05937  *
05938  * RETURNS
05939  *  S_OK.
05940  */
05941 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
05942 {
05943   *pBoolOut = dblIn ? VARIANT_TRUE : VARIANT_FALSE;
05944   return S_OK;
05945 }
05946 
05947 /************************************************************************
05948  * VarBoolFromDate (OLEAUT32.123)
05949  *
05950  * Convert a VT_DATE to a VT_BOOL.
05951  *
05952  * PARAMS
05953  *  dateIn   [I] Source
05954  *  pBoolOut [O] Destination
05955  *
05956  * RETURNS
05957  *  S_OK.
05958  */
05959 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
05960 {
05961   *pBoolOut = dateIn ? VARIANT_TRUE : VARIANT_FALSE;
05962   return S_OK;
05963 }
05964 
05965 /************************************************************************
05966  * VarBoolFromCy (OLEAUT32.124)
05967  *
05968  * Convert a VT_CY to a VT_BOOL.
05969  *
05970  * PARAMS
05971  *  cyIn     [I] Source
05972  *  pBoolOut [O] Destination
05973  *
05974  * RETURNS
05975  *  S_OK.
05976  */
05977 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
05978 {
05979   *pBoolOut = cyIn.int64 ? VARIANT_TRUE : VARIANT_FALSE;
05980   return S_OK;
05981 }
05982 
05983 /************************************************************************
05984  * VARIANT_GetLocalisedText [internal]
05985  *
05986  * Get a localized string from the resources
05987  *
05988  */
05989 BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
05990 {
05991   HRSRC hrsrc;
05992 
05993   hrsrc = FindResourceExW( hProxyDll, (LPWSTR)RT_STRING,
05994                            MAKEINTRESOURCEW((dwId >> 4) + 1), langId );
05995   if (hrsrc)
05996   {
05997     HGLOBAL hmem = LoadResource( hProxyDll, hrsrc );
05998 
05999     if (hmem)
06000     {
06001       const WCHAR *p;
06002       unsigned int i;
06003 
06004       p = LockResource( hmem );
06005       for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
06006 
06007       memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
06008       lpszDest[*p] = '\0';
06009       TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
06010       return TRUE;
06011     }
06012   }
06013   return FALSE;
06014 }
06015 
06016 /************************************************************************
06017  * VarBoolFromStr (OLEAUT32.125)
06018  *
06019  * Convert a VT_BSTR to a VT_BOOL.
06020  *
06021  * PARAMS
06022  *  strIn    [I] Source
06023  *  lcid     [I] LCID for the conversion
06024  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06025  *  pBoolOut [O] Destination
06026  *
06027  * RETURNS
06028  *  Success: S_OK.
06029  *  Failure: E_INVALIDARG, if pBoolOut is invalid.
06030  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
06031  *
06032  * NOTES
06033  *  - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
06034  *  it may contain (in any case mapping) the text "true" or "false".
06035  *  - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
06036  *  localised text of "True" or "False" in the language specified by lcid.
06037  *  - If none of these matches occur, the string is treated as a numeric string
06038  *  and the boolean pBoolOut will be set according to whether the number is zero
06039  *  or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
06040  *  - If the text is not numeric and does not match any of the above, then
06041  *  DISP_E_TYPEMISMATCH is returned.
06042  */
06043 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
06044 {
06045   /* Any VB/VBA programmers out there should recognise these strings... */
06046   static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
06047   static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
06048   WCHAR szBuff[64];
06049   LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
06050   HRESULT hRes = S_OK;
06051 
06052   if (!strIn || !pBoolOut)
06053     return DISP_E_TYPEMISMATCH;
06054 
06055   /* Check if we should be comparing against localised text */
06056   if (dwFlags & VAR_LOCALBOOL)
06057   {
06058     /* Convert our LCID into a usable value */
06059     lcid = ConvertDefaultLocale(lcid);
06060 
06061     langId = LANGIDFROMLCID(lcid);
06062 
06063     if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
06064       langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
06065 
06066     /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
06067      * I don't think this is needed unless any of the localised text strings
06068      * contain characters that can be so mapped. In the event that this is
06069      * true for a given language (possibly some Asian languages), then strIn
06070      * should be mapped here _only_ if langId is an Id for which this can occur.
06071      */
06072   }
06073 
06074   /* Note that if we are not comparing against localised strings, langId
06075    * will have its default value of LANG_ENGLISH. This allows us to mimic
06076    * the native behaviour of always checking against English strings even
06077    * after we've checked for localised ones.
06078    */
06079 VarBoolFromStr_CheckLocalised:
06080   if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
06081   {
06082     /* Compare against localised strings, ignoring case */
06083     if (!strcmpiW(strIn, szBuff))
06084     {
06085       *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
06086       return hRes;
06087     }
06088     VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
06089     if (!strcmpiW(strIn, szBuff))
06090     {
06091       *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
06092       return hRes;
06093     }
06094   }
06095 
06096   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
06097   {
06098     /* We have checked the localised text, now check English */
06099     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
06100     goto VarBoolFromStr_CheckLocalised;
06101   }
06102 
06103   /* All checks against localised text have failed, try #TRUE#/#FALSE# */
06104   if (!strcmpW(strIn, szFalse))
06105     *pBoolOut = VARIANT_FALSE;
06106   else if (!strcmpW(strIn, szTrue))
06107     *pBoolOut = VARIANT_TRUE;
06108   else
06109   {
06110     double d;
06111 
06112     /* If this string is a number, convert it as one */
06113     hRes = VarR8FromStr(strIn, lcid, dwFlags, &d);
06114     if (SUCCEEDED(hRes)) *pBoolOut = d ? VARIANT_TRUE : VARIANT_FALSE;
06115   }
06116   return hRes;
06117 }
06118 
06119 /************************************************************************
06120  * VarBoolFromDisp (OLEAUT32.126)
06121  *
06122  * Convert a VT_DISPATCH to a VT_BOOL.
06123  *
06124  * PARAMS
06125  *  pdispIn   [I] Source
06126  *  lcid      [I] LCID for conversion
06127  *  pBoolOut  [O] Destination
06128  *
06129  * RETURNS
06130  *  Success: S_OK.
06131  *  Failure: E_INVALIDARG, if the source value is invalid
06132  *           DISP_E_OVERFLOW, if the value will not fit in the destination
06133  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
06134  */
06135 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
06136 {
06137   return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL, 0);
06138 }
06139 
06140 /************************************************************************
06141  * VarBoolFromI1 (OLEAUT32.233)
06142  *
06143  * Convert a VT_I1 to a VT_BOOL.
06144  *
06145  * PARAMS
06146  *  cIn      [I] Source
06147  *  pBoolOut [O] Destination
06148  *
06149  * RETURNS
06150  *  S_OK.
06151  */
06152 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
06153 {
06154   *pBoolOut = cIn ? VARIANT_TRUE : VARIANT_FALSE;
06155   return S_OK;
06156 }
06157 
06158 /************************************************************************
06159  * VarBoolFromUI2 (OLEAUT32.234)
06160  *
06161  * Convert a VT_UI2 to a VT_BOOL.
06162  *
06163  * PARAMS
06164  *  usIn     [I] Source
06165  *  pBoolOut [O] Destination
06166  *
06167  * RETURNS
06168  *  S_OK.
06169  */
06170 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
06171 {
06172   *pBoolOut = usIn ? VARIANT_TRUE : VARIANT_FALSE;
06173   return S_OK;
06174 }
06175 
06176 /************************************************************************
06177  * VarBoolFromUI4 (OLEAUT32.235)
06178  *
06179  * Convert a VT_UI4 to a VT_BOOL.
06180  *
06181  * PARAMS
06182  *  ulIn     [I] Source
06183  *  pBoolOut [O] Destination
06184  *
06185  * RETURNS
06186  *  S_OK.
06187  */
06188 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
06189 {
06190   *pBoolOut = ulIn ? VARIANT_TRUE : VARIANT_FALSE;
06191   return S_OK;
06192 }
06193 
06194 /************************************************************************
06195  * VarBoolFromDec (OLEAUT32.236)
06196  *
06197  * Convert a VT_DECIMAL to a VT_BOOL.
06198  *
06199  * PARAMS
06200  *  pDecIn   [I] Source
06201  *  pBoolOut [O] Destination
06202  *
06203  * RETURNS
06204  *  Success: S_OK.
06205  *  Failure: E_INVALIDARG, if pDecIn is invalid.
06206  */
06207 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
06208 {
06209   if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
06210     return E_INVALIDARG;
06211 
06212   if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
06213     *pBoolOut = VARIANT_TRUE;
06214   else
06215     *pBoolOut = VARIANT_FALSE;
06216   return S_OK;
06217 }
06218 
06219 /************************************************************************
06220  * VarBoolFromI8 (OLEAUT32.370)
06221  *
06222  * Convert a VT_I8 to a VT_BOOL.
06223  *
06224  * PARAMS
06225  *  ullIn    [I] Source
06226  *  pBoolOut [O] Destination
06227  *
06228  * RETURNS
06229  *  S_OK.
06230  */
06231 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
06232 {
06233   *pBoolOut = llIn ? VARIANT_TRUE : VARIANT_FALSE;
06234   return S_OK;
06235 }
06236 
06237 /************************************************************************
06238  * VarBoolFromUI8 (OLEAUT32.371)
06239  *
06240  * Convert a VT_UI8 to a VT_BOOL.
06241  *
06242  * PARAMS
06243  *  ullIn    [I] Source
06244  *  pBoolOut [O] Destination
06245  *
06246  * RETURNS
06247  *  S_OK.
06248  */
06249 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
06250 {
06251   *pBoolOut = ullIn ? VARIANT_TRUE : VARIANT_FALSE;
06252   return S_OK;
06253 }
06254 
06255 /* BSTR
06256  */
06257 
06258 /* Write a number from a UI8 and sign */
06259 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
06260 {
06261   do
06262   {
06263     WCHAR ulNextDigit = ulVal % 10;
06264 
06265     *szOut-- = '0' + ulNextDigit;
06266     ulVal = (ulVal - ulNextDigit) / 10;
06267   } while (ulVal);
06268 
06269   szOut++;
06270   return szOut;
06271 }
06272 
06273 /* Create a (possibly localised) BSTR from a UI8 and sign */
06274 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
06275 {
06276   WCHAR szConverted[256];
06277 
06278   if (dwFlags & VAR_NEGATIVE)
06279     *--szOut = '-';
06280 
06281   if (dwFlags & LOCALE_USE_NLS)
06282   {
06283     /* Format the number for the locale */
06284     szConverted[0] = '\0';
06285     GetNumberFormatW(lcid,
06286                      dwFlags & LOCALE_NOUSEROVERRIDE,
06287                      szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
06288     szOut = szConverted;
06289   }
06290   return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
06291 }
06292 
06293 /* Create a (possibly localised) BSTR from a UI8 and sign */
06294 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
06295 {
06296   WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
06297 
06298   if (!pbstrOut)
06299     return E_INVALIDARG;
06300 
06301   /* Create the basic number string */
06302   *szOut-- = '\0';
06303   szOut = VARIANT_WriteNumber(ulVal, szOut);
06304 
06305   *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
06306   TRACE("returning %s\n", debugstr_w(*pbstrOut));
06307   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
06308 }
06309 
06310 /******************************************************************************
06311  * VarBstrFromUI1 (OLEAUT32.108)
06312  *
06313  * Convert a VT_UI1 to a VT_BSTR.
06314  *
06315  * PARAMS
06316  *  bIn      [I] Source
06317  *  lcid     [I] LCID for the conversion
06318  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06319  *  pbstrOut [O] Destination
06320  *
06321  * RETURNS
06322  *  Success: S_OK.
06323  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06324  *           E_OUTOFMEMORY, if memory allocation fails.
06325  */
06326 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06327 {
06328   return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
06329 }
06330 
06331 /******************************************************************************
06332  * VarBstrFromI2 (OLEAUT32.109)
06333  *
06334  * Convert a VT_I2 to a VT_BSTR.
06335  *
06336  * PARAMS
06337  *  sIn      [I] Source
06338  *  lcid     [I] LCID for the conversion
06339  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06340  *  pbstrOut [O] Destination
06341  *
06342  * RETURNS
06343  *  Success: S_OK.
06344  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06345  *           E_OUTOFMEMORY, if memory allocation fails.
06346  */
06347 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06348 {
06349   ULONG64 ul64 = sIn;
06350 
06351   if (sIn < 0)
06352   {
06353     ul64 = -sIn;
06354     dwFlags |= VAR_NEGATIVE;
06355   }
06356   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
06357 }
06358 
06359 /******************************************************************************
06360  * VarBstrFromI4 (OLEAUT32.110)
06361  *
06362  * Convert a VT_I4 to a VT_BSTR.
06363  *
06364  * PARAMS
06365  *  lIn      [I] Source
06366  *  lcid     [I] LCID for the conversion
06367  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06368  *  pbstrOut [O] Destination
06369  *
06370  * RETURNS
06371  *  Success: S_OK.
06372  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06373  *           E_OUTOFMEMORY, if memory allocation fails.
06374  */
06375 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06376 {
06377   ULONG64 ul64 = lIn;
06378 
06379   if (lIn < 0)
06380   {
06381     ul64 = (ULONG)-lIn;
06382     dwFlags |= VAR_NEGATIVE;
06383   }
06384   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
06385 }
06386 
06387 static BSTR VARIANT_BstrReplaceDecimal(const WCHAR * buff, LCID lcid, ULONG dwFlags)
06388 {
06389   BSTR bstrOut;
06390   WCHAR lpDecimalSep[16];
06391 
06392   /* Native oleaut32 uses the locale-specific decimal separator even in the
06393      absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin 
06394      American locales will see "one thousand and one tenth" as "1000,1" 
06395      instead of "1000.1" (notice the comma). The following code checks for
06396      the need to replace the decimal separator, and if so, will prepare an
06397      appropriate NUMBERFMTW structure to do the job via GetNumberFormatW().
06398    */
06399   GetLocaleInfoW(lcid, LOCALE_SDECIMAL | (dwFlags & LOCALE_NOUSEROVERRIDE),
06400                  lpDecimalSep, sizeof(lpDecimalSep) / sizeof(WCHAR));
06401   if (lpDecimalSep[0] == '.' && lpDecimalSep[1] == '\0')
06402   {
06403     /* locale is compatible with English - return original string */
06404     bstrOut = SysAllocString(buff);
06405   }
06406   else
06407   {
06408     WCHAR *p;
06409     WCHAR numbuff[256];
06410     WCHAR empty[1] = {'\0'};
06411     NUMBERFMTW minFormat;
06412 
06413     minFormat.NumDigits = 0;
06414     minFormat.LeadingZero = 0;
06415     minFormat.Grouping = 0;
06416     minFormat.lpDecimalSep = lpDecimalSep;
06417     minFormat.lpThousandSep = empty;
06418     minFormat.NegativeOrder = 1; /* NLS_NEG_LEFT */
06419 
06420     /* count number of decimal digits in string */
06421     p = strchrW( buff, '.' );
06422     if (p) minFormat.NumDigits = strlenW(p + 1);
06423 
06424     numbuff[0] = '\0';
06425     if (!GetNumberFormatW(lcid, 0, buff, &minFormat, numbuff, sizeof(numbuff) / sizeof(WCHAR)))
06426     {
06427       WARN("GetNumberFormatW() failed, returning raw number string instead\n");
06428       bstrOut = SysAllocString(buff);
06429     }
06430     else
06431     {
06432       TRACE("created minimal NLS string %s\n", debugstr_w(numbuff));
06433       bstrOut = SysAllocString(numbuff);
06434     }
06435   }
06436   return bstrOut;
06437 }
06438 
06439 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
06440                                     BSTR* pbstrOut, LPCWSTR lpszFormat)
06441 {
06442   WCHAR buff[256];
06443 
06444   if (!pbstrOut)
06445     return E_INVALIDARG;
06446 
06447   sprintfW( buff, lpszFormat, dblIn );
06448 
06449   /* Negative zeroes are disallowed (some applications depend on this).
06450      If buff starts with a minus, and then nothing follows but zeroes
06451      and/or a period, it is a negative zero and is replaced with a
06452      canonical zero. This duplicates native oleaut32 behavior.
06453    */
06454   if (buff[0] == '-')
06455   {
06456     const WCHAR szAccept[] = {'0', '.', '\0'};
06457     if (strlenW(buff + 1) == strspnW(buff + 1, szAccept))
06458     { buff[0] = '0'; buff[1] = '\0'; }
06459   }
06460 
06461   TRACE("created string %s\n", debugstr_w(buff));
06462   if (dwFlags & LOCALE_USE_NLS)
06463   {
06464     WCHAR numbuff[256];
06465 
06466     /* Format the number for the locale */
06467     numbuff[0] = '\0';
06468     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
06469                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
06470     TRACE("created NLS string %s\n", debugstr_w(numbuff));
06471     *pbstrOut = SysAllocString(numbuff);
06472   }
06473   else
06474   {
06475     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
06476   }
06477   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
06478 }
06479 
06480 /******************************************************************************
06481  * VarBstrFromR4 (OLEAUT32.111)
06482  *
06483  * Convert a VT_R4 to a VT_BSTR.
06484  *
06485  * PARAMS
06486  *  fltIn    [I] Source
06487  *  lcid     [I] LCID for the conversion
06488  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06489  *  pbstrOut [O] Destination
06490  *
06491  * RETURNS
06492  *  Success: S_OK.
06493  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06494  *           E_OUTOFMEMORY, if memory allocation fails.
06495  */
06496 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06497 {
06498   return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
06499 }
06500 
06501 /******************************************************************************
06502  * VarBstrFromR8 (OLEAUT32.112)
06503  *
06504  * Convert a VT_R8 to a VT_BSTR.
06505  *
06506  * PARAMS
06507  *  dblIn    [I] Source
06508  *  lcid     [I] LCID for the conversion
06509  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06510  *  pbstrOut [O] Destination
06511  *
06512  * RETURNS
06513  *  Success: S_OK.
06514  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06515  *           E_OUTOFMEMORY, if memory allocation fails.
06516  */
06517 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06518 {
06519   return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
06520 }
06521 
06522 /******************************************************************************
06523  *    VarBstrFromCy   [OLEAUT32.113]
06524  *
06525  * Convert a VT_CY to a VT_BSTR.
06526  *
06527  * PARAMS
06528  *  cyIn     [I] Source
06529  *  lcid     [I] LCID for the conversion
06530  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06531  *  pbstrOut [O] Destination
06532  *
06533  * RETURNS
06534  *  Success: S_OK.
06535  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06536  *           E_OUTOFMEMORY, if memory allocation fails.
06537  */
06538 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
06539 {
06540   WCHAR buff[256];
06541   VARIANT_DI decVal;
06542 
06543   if (!pbstrOut)
06544     return E_INVALIDARG;
06545 
06546   decVal.scale = 4;
06547   decVal.sign = 0;
06548   decVal.bitsnum[0] = cyIn.s.Lo;
06549   decVal.bitsnum[1] = cyIn.s.Hi;
06550   if (cyIn.s.Hi & 0x80000000UL) {
06551     DWORD one = 1;
06552 
06553     /* Negative number! */
06554     decVal.sign = 1;
06555     decVal.bitsnum[0] = ~decVal.bitsnum[0];
06556     decVal.bitsnum[1] = ~decVal.bitsnum[1];
06557     VARIANT_int_add(decVal.bitsnum, 3, &one, 1);
06558   }
06559   decVal.bitsnum[2] = 0;
06560   VARIANT_DI_tostringW(&decVal, buff, sizeof(buff)/sizeof(buff[0]));
06561 
06562   if (dwFlags & LOCALE_USE_NLS)
06563   {
06564     WCHAR cybuff[256];
06565 
06566     /* Format the currency for the locale */
06567     cybuff[0] = '\0';
06568     GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
06569                        buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
06570     *pbstrOut = SysAllocString(cybuff);
06571   }
06572   else
06573     *pbstrOut = VARIANT_BstrReplaceDecimal(buff,lcid,dwFlags);
06574 
06575   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
06576 }
06577 
06578 /******************************************************************************
06579  *    VarBstrFromDate    [OLEAUT32.114]
06580  *
06581  * Convert a VT_DATE to a VT_BSTR.
06582  *
06583  * PARAMS
06584  *  dateIn   [I] Source
06585  *  lcid     [I] LCID for the conversion
06586  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06587  *  pbstrOut [O] Destination
06588  *
06589  * RETURNS
06590  *  Success: S_OK.
06591  *  Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
06592  *           E_OUTOFMEMORY, if memory allocation fails.
06593  */
06594 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06595 {
06596   SYSTEMTIME st;
06597   DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
06598   WCHAR date[128], *time;
06599 
06600   TRACE("(%g,0x%08x,0x%08x,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
06601 
06602   if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
06603     return E_INVALIDARG;
06604 
06605   *pbstrOut = NULL;
06606 
06607   if (dwFlags & VAR_CALENDAR_THAI)
06608       st.wYear += 553; /* Use the Thai buddhist calendar year */
06609   else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
06610       FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
06611 
06612   if (dwFlags & LOCALE_USE_NLS)
06613     dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
06614   else
06615   {
06616     double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
06617     double partial = dateIn - whole;
06618 
06619     if (whole == 0.0)
06620       dwFlags |= VAR_TIMEVALUEONLY;
06621     else if (partial < 1e-12)
06622       dwFlags |= VAR_DATEVALUEONLY;
06623   }
06624 
06625   if (dwFlags & VAR_TIMEVALUEONLY)
06626     date[0] = '\0';
06627   else
06628     if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
06629                         sizeof(date)/sizeof(WCHAR)))
06630       return E_INVALIDARG;
06631 
06632   if (!(dwFlags & VAR_DATEVALUEONLY))
06633   {
06634     time = date + strlenW(date);
06635     if (time != date)
06636       *time++ = ' ';
06637     if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
06638                         sizeof(date)/sizeof(WCHAR)-(time-date)))
06639       return E_INVALIDARG;
06640   }
06641 
06642   *pbstrOut = SysAllocString(date);
06643   if (*pbstrOut)
06644     TRACE("returning %s\n", debugstr_w(*pbstrOut));
06645   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
06646 }
06647 
06648 /******************************************************************************
06649  * VarBstrFromBool (OLEAUT32.116)
06650  *
06651  * Convert a VT_BOOL to a VT_BSTR.
06652  *
06653  * PARAMS
06654  *  boolIn   [I] Source
06655  *  lcid     [I] LCID for the conversion
06656  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06657  *  pbstrOut [O] Destination
06658  *
06659  * RETURNS
06660  *  Success: S_OK.
06661  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06662  *           E_OUTOFMEMORY, if memory allocation fails.
06663  *
06664  * NOTES
06665  *  If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
06666  *  localised text of "True" or "False". To convert a bool into a
06667  *  numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
06668  */
06669 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06670 {
06671   WCHAR szBuff[64];
06672   DWORD dwResId = IDS_TRUE;
06673   LANGID langId;
06674 
06675   TRACE("%d,0x%08x,0x%08x,%p\n", boolIn, lcid, dwFlags, pbstrOut);
06676 
06677   if (!pbstrOut)
06678     return E_INVALIDARG;
06679 
06680   /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
06681    * for variant formatting */
06682   switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
06683   {
06684   case VAR_BOOLONOFF:
06685       dwResId = IDS_ON;
06686       break;
06687   case VAR_BOOLYESNO:
06688       dwResId = IDS_YES;
06689       break;
06690   case VAR_LOCALBOOL:
06691       break;
06692   default:
06693     lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
06694   }
06695 
06696   lcid = ConvertDefaultLocale(lcid);
06697   langId = LANGIDFROMLCID(lcid);
06698   if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
06699     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
06700 
06701   if (boolIn == VARIANT_FALSE)
06702     dwResId++; /* Use negative form */
06703 
06704 VarBstrFromBool_GetLocalised:
06705   if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
06706   {
06707     *pbstrOut = SysAllocString(szBuff);
06708     return *pbstrOut ? S_OK : E_OUTOFMEMORY;
06709   }
06710 
06711   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
06712   {
06713     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
06714     goto VarBstrFromBool_GetLocalised;
06715   }
06716 
06717   /* Should never get here */
06718   WARN("Failed to load bool text!\n");
06719   return E_OUTOFMEMORY;
06720 }
06721 
06722 /******************************************************************************
06723  * VarBstrFromI1 (OLEAUT32.229)
06724  *
06725  * Convert a VT_I1 to a VT_BSTR.
06726  *
06727  * PARAMS
06728  *  cIn      [I] Source
06729  *  lcid     [I] LCID for the conversion
06730  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06731  *  pbstrOut [O] Destination
06732  *
06733  * RETURNS
06734  *  Success: S_OK.
06735  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06736  *           E_OUTOFMEMORY, if memory allocation fails.
06737  */
06738 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06739 {
06740   ULONG64 ul64 = cIn;
06741 
06742   if (cIn < 0)
06743   {
06744     ul64 = -cIn;
06745     dwFlags |= VAR_NEGATIVE;
06746   }
06747   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
06748 }
06749 
06750 /******************************************************************************
06751  * VarBstrFromUI2 (OLEAUT32.230)
06752  *
06753  * Convert a VT_UI2 to a VT_BSTR.
06754  *
06755  * PARAMS
06756  *  usIn     [I] Source
06757  *  lcid     [I] LCID for the conversion
06758  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06759  *  pbstrOut [O] Destination
06760  *
06761  * RETURNS
06762  *  Success: S_OK.
06763  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06764  *           E_OUTOFMEMORY, if memory allocation fails.
06765  */
06766 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06767 {
06768   return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
06769 }
06770 
06771 /******************************************************************************
06772  * VarBstrFromUI4 (OLEAUT32.231)
06773  *
06774  * Convert a VT_UI4 to a VT_BSTR.
06775  *
06776  * PARAMS
06777  *  ulIn     [I] Source
06778  *  lcid     [I] LCID for the conversion
06779  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06780  *  pbstrOut [O] Destination
06781  *
06782  * RETURNS
06783  *  Success: S_OK.
06784  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06785  *           E_OUTOFMEMORY, if memory allocation fails.
06786  */
06787 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06788 {
06789   return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
06790 }
06791 
06792 /******************************************************************************
06793  * VarBstrFromDec (OLEAUT32.232)
06794  *
06795  * Convert a VT_DECIMAL to a VT_BSTR.
06796  *
06797  * PARAMS
06798  *  pDecIn   [I] Source
06799  *  lcid     [I] LCID for the conversion
06800  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06801  *  pbstrOut [O] Destination
06802  *
06803  * RETURNS
06804  *  Success: S_OK.
06805  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06806  *           E_OUTOFMEMORY, if memory allocation fails.
06807  */
06808 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06809 {
06810   WCHAR buff[256];
06811   VARIANT_DI temp;
06812 
06813   if (!pbstrOut)
06814     return E_INVALIDARG;
06815 
06816   VARIANT_DIFromDec(pDecIn, &temp);
06817   VARIANT_DI_tostringW(&temp, buff, 256);
06818 
06819   if (dwFlags & LOCALE_USE_NLS)
06820   {
06821     WCHAR numbuff[256];
06822 
06823     /* Format the number for the locale */
06824     numbuff[0] = '\0';
06825     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
06826                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
06827     TRACE("created NLS string %s\n", debugstr_w(numbuff));
06828     *pbstrOut = SysAllocString(numbuff);
06829   }
06830   else
06831   {
06832     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
06833   }
06834   
06835   TRACE("returning %s\n", debugstr_w(*pbstrOut));
06836   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
06837 }
06838 
06839 /************************************************************************
06840  * VarBstrFromI8 (OLEAUT32.370)
06841  *
06842  * Convert a VT_I8 to a VT_BSTR.
06843  *
06844  * PARAMS
06845  *  llIn     [I] Source
06846  *  lcid     [I] LCID for the conversion
06847  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06848  *  pbstrOut [O] Destination
06849  *
06850  * RETURNS
06851  *  Success: S_OK.
06852  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06853  *           E_OUTOFMEMORY, if memory allocation fails.
06854  */
06855 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06856 {
06857   ULONG64 ul64 = llIn;
06858 
06859   if (llIn < 0)
06860   {
06861     ul64 = -llIn;
06862     dwFlags |= VAR_NEGATIVE;
06863   }
06864   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
06865 }
06866 
06867 /************************************************************************
06868  * VarBstrFromUI8 (OLEAUT32.371)
06869  *
06870  * Convert a VT_UI8 to a VT_BSTR.
06871  *
06872  * PARAMS
06873  *  ullIn    [I] Source
06874  *  lcid     [I] LCID for the conversion
06875  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06876  *  pbstrOut [O] Destination
06877  *
06878  * RETURNS
06879  *  Success: S_OK.
06880  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06881  *           E_OUTOFMEMORY, if memory allocation fails.
06882  */
06883 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06884 {
06885   return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
06886 }
06887 
06888 /************************************************************************
06889  * VarBstrFromDisp (OLEAUT32.115)
06890  *
06891  * Convert a VT_DISPATCH to a BSTR.
06892  *
06893  * PARAMS
06894  *  pdispIn [I] Source
06895  *  lcid    [I] LCID for conversion
06896  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
06897  *  pbstrOut  [O] Destination
06898  *
06899  * RETURNS
06900  *  Success: S_OK.
06901  *  Failure: E_INVALIDARG, if the source value is invalid
06902  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
06903  */
06904 HRESULT WINAPI VarBstrFromDisp(IDispatch* pdispIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
06905 {
06906   return VARIANT_FromDisp(pdispIn, lcid, pbstrOut, VT_BSTR, dwFlags);
06907 }
06908 
06909 /**********************************************************************
06910  * VarBstrCat (OLEAUT32.313)
06911  *
06912  * Concatenate two BSTR values.
06913  *
06914  * PARAMS
06915  *  pbstrLeft  [I] Source
06916  *  pbstrRight [I] Value to concatenate
06917  *  pbstrOut   [O] Destination
06918  *
06919  * RETURNS
06920  *  Success: S_OK.
06921  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
06922  *           E_OUTOFMEMORY, if memory allocation fails.
06923  */
06924 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
06925 {
06926   unsigned int lenLeft, lenRight;
06927 
06928   TRACE("%s,%s,%p\n",
06929    debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
06930    debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), pbstrOut);
06931 
06932   if (!pbstrOut)
06933     return E_INVALIDARG;
06934 
06935   /* use byte length here to properly handle ansi-allocated BSTRs */
06936   lenLeft = pbstrLeft ? SysStringByteLen(pbstrLeft) : 0;
06937   lenRight = pbstrRight ? SysStringByteLen(pbstrRight) : 0;
06938 
06939   *pbstrOut = SysAllocStringByteLen(NULL, lenLeft + lenRight);
06940   if (!*pbstrOut)
06941     return E_OUTOFMEMORY;
06942 
06943   (*pbstrOut)[0] = '\0';
06944 
06945   if (pbstrLeft)
06946     memcpy(*pbstrOut, pbstrLeft, lenLeft);
06947 
06948   if (pbstrRight)
06949     memcpy((CHAR*)*pbstrOut + lenLeft, pbstrRight, lenRight);
06950 
06951   TRACE("%s\n", debugstr_wn(*pbstrOut, SysStringLen(*pbstrOut)));
06952   return S_OK;
06953 }
06954 
06955 /**********************************************************************
06956  * VarBstrCmp (OLEAUT32.314)
06957  *
06958  * Compare two BSTR values.
06959  *
06960  * PARAMS
06961  *  pbstrLeft  [I] Source
06962  *  pbstrRight [I] Value to compare
06963  *  lcid       [I] LCID for the comparison
06964  *  dwFlags    [I] Flags to pass directly to CompareStringW().
06965  *
06966  * RETURNS
06967  *  VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
06968  *  than, equal to or greater than pbstrRight respectively.
06969  *
06970  * NOTES
06971  *  VARCMP_NULL is NOT returned if either string is NULL unlike MSDN
06972  *  states. A NULL BSTR pointer is equivalent to an empty string.
06973  *  If LCID is equal to 0, a byte by byte comparison is performed.
06974  */
06975 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
06976 {
06977     HRESULT hres;
06978     int ret;
06979 
06980     TRACE("%s,%s,%d,%08x\n",
06981      debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
06982      debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), lcid, dwFlags);
06983 
06984     if (!pbstrLeft || !*pbstrLeft)
06985     {
06986       if (pbstrRight && *pbstrRight)
06987         return VARCMP_LT;
06988     }
06989     else if (!pbstrRight || !*pbstrRight)
06990         return VARCMP_GT;
06991 
06992     if (lcid == 0)
06993     {
06994       unsigned int lenLeft = SysStringByteLen(pbstrLeft);
06995       unsigned int lenRight = SysStringByteLen(pbstrRight);
06996       ret = memcmp(pbstrLeft, pbstrRight, min(lenLeft, lenRight));
06997       if (ret < 0)
06998         return VARCMP_LT;
06999       if (ret > 0)
07000         return VARCMP_GT;
07001       if (lenLeft < lenRight)
07002         return VARCMP_LT;
07003       if (lenLeft > lenRight)
07004         return VARCMP_GT;
07005       return VARCMP_EQ;
07006     }
07007     else
07008     {
07009       unsigned int lenLeft = SysStringLen(pbstrLeft);
07010       unsigned int lenRight = SysStringLen(pbstrRight);
07011 
07012       if (lenLeft == 0 || lenRight == 0)
07013       {
07014           if (lenLeft == 0 && lenRight == 0) return VARCMP_EQ;
07015           return lenLeft < lenRight ? VARCMP_LT : VARCMP_GT;
07016       }
07017 
07018       hres = CompareStringW(lcid, dwFlags, pbstrLeft, lenLeft,
07019               pbstrRight, lenRight) - 1;
07020       TRACE("%d\n", hres);
07021       return hres;
07022     }
07023 }
07024 
07025 /*
07026  * DATE
07027  */
07028 
07029 /******************************************************************************
07030  * VarDateFromUI1 (OLEAUT32.88)
07031  *
07032  * Convert a VT_UI1 to a VT_DATE.
07033  *
07034  * PARAMS
07035  *  bIn      [I] Source
07036  *  pdateOut [O] Destination
07037  *
07038  * RETURNS
07039  *  S_OK.
07040  */
07041 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
07042 {
07043   return VarR8FromUI1(bIn, pdateOut);
07044 }
07045 
07046 /******************************************************************************
07047  * VarDateFromI2 (OLEAUT32.89)
07048  *
07049  * Convert a VT_I2 to a VT_DATE.
07050  *
07051  * PARAMS
07052  *  sIn      [I] Source
07053  *  pdateOut [O] Destination
07054  *
07055  * RETURNS
07056  *  S_OK.
07057  */
07058 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
07059 {
07060   return VarR8FromI2(sIn, pdateOut);
07061 }
07062 
07063 /******************************************************************************
07064  * VarDateFromI4 (OLEAUT32.90)
07065  *
07066  * Convert a VT_I4 to a VT_DATE.
07067  *
07068  * PARAMS
07069  *  lIn      [I] Source
07070  *  pdateOut [O] Destination
07071  *
07072  * RETURNS
07073  *  S_OK.
07074  */
07075 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
07076 {
07077   return VarDateFromR8(lIn, pdateOut);
07078 }
07079 
07080 /******************************************************************************
07081  * VarDateFromR4 (OLEAUT32.91)
07082  *
07083  * Convert a VT_R4 to a VT_DATE.
07084  *
07085  * PARAMS
07086  *  fltIn    [I] Source
07087  *  pdateOut [O] Destination
07088  *
07089  * RETURNS
07090  *  S_OK.
07091  */
07092 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
07093 {
07094   return VarR8FromR4(fltIn, pdateOut);
07095 }
07096 
07097 /******************************************************************************
07098  * VarDateFromR8 (OLEAUT32.92)
07099  *
07100  * Convert a VT_R8 to a VT_DATE.
07101  *
07102  * PARAMS
07103  *  dblIn    [I] Source
07104  *  pdateOut [O] Destination
07105  *
07106  * RETURNS
07107  *  S_OK.
07108  */
07109 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
07110 {
07111   if (dblIn <= (DATE_MIN - 1.0) || dblIn >= (DATE_MAX + 1.0)) return DISP_E_OVERFLOW;
07112   *pdateOut = (DATE)dblIn;
07113   return S_OK;
07114 }
07115 
07116 /**********************************************************************
07117  * VarDateFromDisp (OLEAUT32.95)
07118  *
07119  * Convert a VT_DISPATCH to a VT_DATE.
07120  *
07121  * PARAMS
07122  *  pdispIn  [I] Source
07123  *  lcid     [I] LCID for conversion
07124  *  pdateOut [O] Destination
07125  *
07126  * RETURNS
07127  *  Success: S_OK.
07128  *  Failure: E_INVALIDARG, if the source value is invalid
07129  *           DISP_E_OVERFLOW, if the value will not fit in the destination
07130  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
07131  */
07132 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
07133 {
07134   return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE, 0);
07135 }
07136 
07137 /******************************************************************************
07138  * VarDateFromBool (OLEAUT32.96)
07139  *
07140  * Convert a VT_BOOL to a VT_DATE.
07141  *
07142  * PARAMS
07143  *  boolIn   [I] Source
07144  *  pdateOut [O] Destination
07145  *
07146  * RETURNS
07147  *  S_OK.
07148  */
07149 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
07150 {
07151   return VarR8FromBool(boolIn, pdateOut);
07152 }
07153 
07154 /**********************************************************************
07155  * VarDateFromCy (OLEAUT32.93)
07156  *
07157  * Convert a VT_CY to a VT_DATE.
07158  *
07159  * PARAMS
07160  *  lIn      [I] Source
07161  *  pdateOut [O] Destination
07162  *
07163  * RETURNS
07164  *  S_OK.
07165  */
07166 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
07167 {
07168   return VarR8FromCy(cyIn, pdateOut);
07169 }
07170 
07171 /* Date string parsing */
07172 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
07173 #define DP_DATESEP 0x02 /* Date separator */
07174 #define DP_MONTH   0x04 /* Month name */
07175 #define DP_AM      0x08 /* AM */
07176 #define DP_PM      0x10 /* PM */
07177 
07178 typedef struct tagDATEPARSE
07179 {
07180     DWORD dwCount;      /* Number of fields found so far (maximum 6) */
07181     DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
07182     DWORD dwFlags[6];   /* Flags for each field */
07183     DWORD dwValues[6];  /* Value of each field */
07184 } DATEPARSE;
07185 
07186 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
07187 
07188 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
07189 
07190 /* Determine if a day is valid in a given month of a given year */
07191 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
07192 {
07193   static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
07194 
07195   if (day && month && month < 13)
07196   {
07197     if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
07198       return TRUE;
07199   }
07200   return FALSE;
07201 }
07202 
07203 /* Possible orders for 3 numbers making up a date */
07204 #define ORDER_MDY 0x01
07205 #define ORDER_YMD 0x02
07206 #define ORDER_YDM 0x04
07207 #define ORDER_DMY 0x08
07208 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
07209 
07210 /* Determine a date for a particular locale, from 3 numbers */
07211 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
07212                                        DWORD offset, SYSTEMTIME *st)
07213 {
07214   DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
07215 
07216   if (!dp->dwCount)
07217   {
07218     v1 = 30; /* Default to (Variant) 0 date part */
07219     v2 = 12;
07220     v3 = 1899;
07221     goto VARIANT_MakeDate_OK;
07222   }
07223 
07224   v1 = dp->dwValues[offset + 0];
07225   v2 = dp->dwValues[offset + 1];
07226   if (dp->dwCount == 2)
07227   {
07228     SYSTEMTIME current;
07229     GetSystemTime(&current);
07230     v3 = current.wYear;
07231   }
07232   else
07233     v3 = dp->dwValues[offset + 2];
07234 
07235   TRACE("(%d,%d,%d,%d,%d)\n", v1, v2, v3, iDate, offset);
07236 
07237   /* If one number must be a month (Because a month name was given), then only
07238    * consider orders with the month in that position.
07239    * If we took the current year as 'v3', then only allow a year in that position.
07240    */
07241   if (dp->dwFlags[offset + 0] & DP_MONTH)
07242   {
07243     dwAllOrders = ORDER_MDY;
07244   }
07245   else if (dp->dwFlags[offset + 1] & DP_MONTH)
07246   {
07247     dwAllOrders = ORDER_DMY;
07248     if (dp->dwCount > 2)
07249       dwAllOrders |= ORDER_YMD;
07250   }
07251   else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
07252   {
07253     dwAllOrders = ORDER_YDM;
07254   }
07255   else
07256   {
07257     dwAllOrders = ORDER_MDY|ORDER_DMY;
07258     if (dp->dwCount > 2)
07259       dwAllOrders |= (ORDER_YMD|ORDER_YDM);
07260   }
07261 
07262 VARIANT_MakeDate_Start:
07263   TRACE("dwAllOrders is 0x%08x\n", dwAllOrders);
07264 
07265   while (dwAllOrders)
07266   {
07267     DWORD dwTemp;
07268 
07269     if (dwCount == 0)
07270     {
07271       /* First: Try the order given by iDate */
07272       switch (iDate)
07273       {
07274       case 0:  dwTry = dwAllOrders & ORDER_MDY; break;
07275       case 1:  dwTry = dwAllOrders & ORDER_DMY; break;
07276       default: dwTry = dwAllOrders & ORDER_YMD; break;
07277       }
07278     }
07279     else if (dwCount == 1)
07280     {
07281       /* Second: Try all the orders compatible with iDate */
07282       switch (iDate)
07283       {
07284       case 0:  dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
07285       case 1:  dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
07286       default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
07287       }
07288     }
07289     else
07290     {
07291       /* Finally: Try any remaining orders */
07292       dwTry = dwAllOrders;
07293     }
07294 
07295     TRACE("Attempt %d, dwTry is 0x%08x\n", dwCount, dwTry);
07296 
07297     dwCount++;
07298     if (!dwTry)
07299       continue;
07300 
07301 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
07302 
07303     if (dwTry & ORDER_MDY)
07304     {
07305       if (VARIANT_IsValidMonthDay(v2,v1,v3))
07306       {
07307         DATE_SWAP(v1,v2);
07308         goto VARIANT_MakeDate_OK;
07309       }
07310       dwAllOrders &= ~ORDER_MDY;
07311     }
07312     if (dwTry & ORDER_YMD)
07313     {
07314       if (VARIANT_IsValidMonthDay(v3,v2,v1))
07315       {
07316         DATE_SWAP(v1,v3);
07317         goto VARIANT_MakeDate_OK;
07318       }
07319       dwAllOrders &= ~ORDER_YMD;
07320     }
07321     if (dwTry & ORDER_YDM)
07322     {
07323       if (VARIANT_IsValidMonthDay(v2,v3,v1))
07324       {
07325         DATE_SWAP(v1,v2);
07326         DATE_SWAP(v2,v3);
07327         goto VARIANT_MakeDate_OK;
07328       }
07329       dwAllOrders &= ~ORDER_YDM;
07330     }
07331     if (dwTry & ORDER_DMY)
07332     {
07333       if (VARIANT_IsValidMonthDay(v1,v2,v3))
07334         goto VARIANT_MakeDate_OK;
07335       dwAllOrders &= ~ORDER_DMY;
07336     }
07337     if (dwTry & ORDER_MYD)
07338     {
07339       /* Only occurs if we are trying a 2 year date as M/Y not D/M */
07340       if (VARIANT_IsValidMonthDay(v3,v1,v2))
07341       {
07342         DATE_SWAP(v1,v3);
07343         DATE_SWAP(v2,v3);
07344         goto VARIANT_MakeDate_OK;
07345       }
07346       dwAllOrders &= ~ORDER_MYD;
07347     }
07348   }
07349 
07350   if (dp->dwCount == 2)
07351   {
07352     /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
07353     v3 = 1; /* 1st of the month */
07354     dwAllOrders = ORDER_YMD|ORDER_MYD;
07355     dp->dwCount = 0; /* Don't return to this code path again */
07356     dwCount = 0;
07357     goto VARIANT_MakeDate_Start;
07358   }
07359 
07360   /* No valid dates were able to be constructed */
07361   return DISP_E_TYPEMISMATCH;
07362 
07363 VARIANT_MakeDate_OK:
07364 
07365   /* Check that the time part is ok */
07366   if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
07367     return DISP_E_TYPEMISMATCH;
07368 
07369   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
07370   if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
07371     st->wHour += 12;
07372   else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
07373     st->wHour = 0;
07374   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
07375 
07376   st->wDay = v1;
07377   st->wMonth = v2;
07378   /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
07379    * be retrieved from:
07380    * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
07381    * But Wine doesn't have/use that key as at the time of writing.
07382    */
07383   st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
07384   TRACE("Returning date %d/%d/%d\n", v1, v2, st->wYear);
07385   return S_OK;
07386 }
07387 
07388 /******************************************************************************
07389  * VarDateFromStr [OLEAUT32.94]
07390  *
07391  * Convert a VT_BSTR to at VT_DATE.
07392  *
07393  * PARAMS
07394  *  strIn    [I] String to convert
07395  *  lcid     [I] Locale identifier for the conversion
07396  *  dwFlags  [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
07397  *  pdateOut [O] Destination for the converted value
07398  *
07399  * RETURNS
07400  *  Success: S_OK. pdateOut contains the converted value.
07401  *  FAILURE: An HRESULT error code indicating the problem.
07402  *
07403  * NOTES
07404  *  Any date format that can be created using the date formats from lcid
07405  *  (Either from kernel Nls functions, variant conversion or formatting) is a
07406  *  valid input to this function. In addition, a few more esoteric formats are
07407  *  also supported for compatibility with the native version. The date is
07408  *  interpreted according to the date settings in the control panel, unless
07409  *  the date is invalid in that format, in which the most compatible format
07410  *  that produces a valid date will be used.
07411  */
07412 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
07413 {
07414   static const USHORT ParseDateTokens[] =
07415   {
07416     LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
07417     LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
07418     LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
07419     LOCALE_SMONTHNAME13,
07420     LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
07421     LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
07422     LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
07423     LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
07424     LOCALE_SABBREVMONTHNAME13,
07425     LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
07426     LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
07427     LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
07428     LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
07429     LOCALE_SABBREVDAYNAME7,
07430     LOCALE_S1159, LOCALE_S2359,
07431     LOCALE_SDATE
07432   };
07433   static const BYTE ParseDateMonths[] =
07434   {
07435     1,2,3,4,5,6,7,8,9,10,11,12,13,
07436     1,2,3,4,5,6,7,8,9,10,11,12,13
07437   };
07438   unsigned int i;
07439   BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
07440   DATEPARSE dp;
07441   DWORD dwDateSeps = 0, iDate = 0;
07442   HRESULT hRet = S_OK;
07443 
07444   if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
07445       (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
07446     return E_INVALIDARG;
07447 
07448   if (!strIn)
07449     return DISP_E_TYPEMISMATCH;
07450 
07451   *pdateOut = 0.0;
07452 
07453   TRACE("(%s,0x%08x,0x%08x,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
07454 
07455   memset(&dp, 0, sizeof(dp));
07456 
07457   GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
07458                  (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
07459   TRACE("iDate is %d\n", iDate);
07460 
07461   /* Get the month/day/am/pm tokens for this locale */
07462   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
07463   {
07464     WCHAR buff[128];
07465     LCTYPE lctype =  ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
07466 
07467     /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
07468      *        GetAltMonthNames(). We should really cache these strings too.
07469      */
07470     buff[0] = '\0';
07471     GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
07472     tokens[i] = SysAllocString(buff);
07473     TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
07474   }
07475 
07476   /* Parse the string into our structure */
07477   while (*strIn)
07478   {
07479     if (dp.dwCount >= 6)
07480       break;
07481 
07482     if (isdigitW(*strIn))
07483     {
07484       dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
07485       dp.dwCount++;
07486       strIn--;
07487     }
07488     else if (isalpha(*strIn))
07489     {
07490       BOOL bFound = FALSE;
07491 
07492       for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
07493       {
07494         DWORD dwLen = strlenW(tokens[i]);
07495         if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
07496         {
07497           if (i <= 25)
07498           {
07499             dp.dwValues[dp.dwCount] = ParseDateMonths[i];
07500             dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
07501             dp.dwCount++;
07502           }
07503           else if (i > 39 && i < 42)
07504           {
07505             if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
07506               hRet = DISP_E_TYPEMISMATCH;
07507             else
07508             {
07509               dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
07510               dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
07511             }
07512           }
07513           strIn += (dwLen - 1);
07514           bFound = TRUE;
07515           break;
07516         }
07517       }
07518 
07519       if (!bFound)
07520       {
07521         if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
07522             (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
07523         {
07524           /* Special case - 'a' and 'p' are recognised as short for am/pm */
07525           if (*strIn == 'a' || *strIn == 'A')
07526           {
07527             dp.dwFlags[dp.dwCount - 1] |= DP_AM;
07528             dp.dwParseFlags |=  DP_AM;
07529           }
07530           else
07531           {
07532             dp.dwFlags[dp.dwCount - 1] |= DP_PM;
07533             dp.dwParseFlags |=  DP_PM;
07534           }
07535           strIn++;
07536         }
07537         else
07538         {
07539           TRACE("No matching token for %s\n", debugstr_w(strIn));
07540           hRet = DISP_E_TYPEMISMATCH;
07541           break;
07542         }
07543       }
07544     }
07545     else if (*strIn == ':' ||  *strIn == '.')
07546     {
07547       if (!dp.dwCount || !strIn[1])
07548         hRet = DISP_E_TYPEMISMATCH;
07549       else
07550         if (tokens[42][0] == *strIn)
07551         {
07552           dwDateSeps++;
07553           if (dwDateSeps > 2)
07554             hRet = DISP_E_TYPEMISMATCH;
07555           else
07556             dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
07557         }
07558         else
07559           dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
07560     }
07561     else if (*strIn == '-' || *strIn == '/')
07562     {
07563       dwDateSeps++;
07564       if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
07565         hRet = DISP_E_TYPEMISMATCH;
07566       else
07567         dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
07568     }
07569     else if (*strIn == ',' || isspaceW(*strIn))
07570     {
07571       if (*strIn == ',' && !strIn[1])
07572         hRet = DISP_E_TYPEMISMATCH;
07573     }
07574     else
07575     {
07576       hRet = DISP_E_TYPEMISMATCH;
07577     }
07578     strIn++;
07579   }
07580 
07581   if (!dp.dwCount || dp.dwCount > 6 ||
07582       (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
07583     hRet = DISP_E_TYPEMISMATCH;
07584 
07585   if (SUCCEEDED(hRet))
07586   {
07587     SYSTEMTIME st;
07588     DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
07589 
07590     st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
07591 
07592     /* Figure out which numbers correspond to which fields.
07593      *
07594      * This switch statement works based on the fact that native interprets any
07595      * fields that are not joined with a time separator ('.' or ':') as date
07596      * fields. Thus we construct a value from 0-32 where each set bit indicates
07597      * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
07598      * For valid permutations, we set dwOffset to point to the first date field
07599      * and shorten dp.dwCount by the number of time fields found. The real
07600      * magic here occurs in VARIANT_MakeDate() above, where we determine what
07601      * each date number must represent in the context of iDate.
07602      */
07603     TRACE("0x%08x\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
07604 
07605     switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
07606     {
07607     case 0x1: /* TT TTDD TTDDD */
07608       if (dp.dwCount > 3 &&
07609           ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
07610           (dp.dwFlags[4] & (DP_AM|DP_PM))))
07611         hRet = DISP_E_TYPEMISMATCH;
07612       else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
07613         hRet = DISP_E_TYPEMISMATCH;
07614       st.wHour = dp.dwValues[0];
07615       st.wMinute  = dp.dwValues[1];
07616       dp.dwCount -= 2;
07617       dwOffset = 2;
07618       break;
07619 
07620     case 0x3: /* TTT TTTDD TTTDDD */
07621       if (dp.dwCount > 4 &&
07622           ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
07623           (dp.dwFlags[5] & (DP_AM|DP_PM))))
07624         hRet = DISP_E_TYPEMISMATCH;
07625       else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
07626         hRet = DISP_E_TYPEMISMATCH;
07627       st.wHour   = dp.dwValues[0];
07628       st.wMinute = dp.dwValues[1];
07629       st.wSecond = dp.dwValues[2];
07630       dwOffset = 3;
07631       dp.dwCount -= 3;
07632       break;
07633 
07634     case 0x4: /* DDTT */
07635       if (dp.dwCount != 4 ||
07636           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
07637         hRet = DISP_E_TYPEMISMATCH;
07638 
07639       st.wHour = dp.dwValues[2];
07640       st.wMinute  = dp.dwValues[3];
07641       dp.dwCount -= 2;
07642       break;
07643 
07644    case 0x0: /* T DD DDD TDDD TDDD */
07645       if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
07646       {
07647         st.wHour = dp.dwValues[0]; /* T */
07648         dp.dwCount = 0;
07649         break;
07650       }
07651       else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
07652       {
07653         hRet = DISP_E_TYPEMISMATCH;
07654       }
07655       else if (dp.dwCount == 3)
07656       {
07657         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
07658         {
07659           dp.dwCount = 2;
07660           st.wHour = dp.dwValues[0];
07661           dwOffset = 1;
07662           break;
07663         }
07664         if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
07665         {
07666           dp.dwCount = 2;
07667           st.wHour = dp.dwValues[2];
07668           break;
07669         }
07670         else if (dp.dwParseFlags & (DP_AM|DP_PM))
07671           hRet = DISP_E_TYPEMISMATCH;
07672       }
07673       else if (dp.dwCount == 4)
07674       {
07675         dp.dwCount = 3;
07676         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
07677         {
07678           st.wHour = dp.dwValues[0];
07679           dwOffset = 1;
07680         }
07681         else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
07682         {
07683           st.wHour = dp.dwValues[3];
07684         }
07685         else
07686           hRet = DISP_E_TYPEMISMATCH;
07687         break;
07688       }
07689       /* .. fall through .. */
07690 
07691     case 0x8: /* DDDTT */
07692       if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
07693           (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
07694            (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
07695            dp.dwCount == 4 || dp.dwCount == 6)
07696         hRet = DISP_E_TYPEMISMATCH;
07697       st.wHour   = dp.dwValues[3];
07698       st.wMinute = dp.dwValues[4];
07699       if (dp.dwCount == 5)
07700         dp.dwCount -= 2;
07701       break;
07702 
07703     case 0xC: /* DDTTT */
07704       if (dp.dwCount != 5 ||
07705           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
07706         hRet = DISP_E_TYPEMISMATCH;
07707       st.wHour   = dp.dwValues[2];
07708       st.wMinute = dp.dwValues[3];
07709       st.wSecond = dp.dwValues[4];
07710       dp.dwCount -= 3;
07711       break;
07712 
07713     case 0x18: /* DDDTTT */
07714       if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
07715           (dp.dwFlags[2] & (DP_AM|DP_PM)))
07716         hRet = DISP_E_TYPEMISMATCH;
07717       st.wHour   = dp.dwValues[3];
07718       st.wMinute = dp.dwValues[4];
07719       st.wSecond = dp.dwValues[5];
07720       dp.dwCount -= 3;
07721       break;
07722 
07723     default:
07724       hRet = DISP_E_TYPEMISMATCH;
07725       break;
07726     }
07727 
07728     if (SUCCEEDED(hRet))
07729     {
07730       hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
07731 
07732       if (dwFlags & VAR_TIMEVALUEONLY)
07733       {
07734         st.wYear = 1899;
07735         st.wMonth = 12;
07736         st.wDay = 30;
07737       }
07738       else if (dwFlags & VAR_DATEVALUEONLY)
07739        st.wHour = st.wMinute = st.wSecond = 0;
07740 
07741       /* Finally, convert the value to a VT_DATE */
07742       if (SUCCEEDED(hRet))
07743         hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
07744     }
07745   }
07746 
07747   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
07748     SysFreeString(tokens[i]);
07749   return hRet;
07750 }
07751 
07752 /******************************************************************************
07753  * VarDateFromI1 (OLEAUT32.221)
07754  *
07755  * Convert a VT_I1 to a VT_DATE.
07756  *
07757  * PARAMS
07758  *  cIn      [I] Source
07759  *  pdateOut [O] Destination
07760  *
07761  * RETURNS
07762  *  S_OK.
07763  */
07764 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
07765 {
07766   return VarR8FromI1(cIn, pdateOut);
07767 }
07768 
07769 /******************************************************************************
07770  * VarDateFromUI2 (OLEAUT32.222)
07771  *
07772  * Convert a VT_UI2 to a VT_DATE.
07773  *
07774  * PARAMS
07775  *  uiIn     [I] Source
07776  *  pdateOut [O] Destination
07777  *
07778  * RETURNS
07779  *  S_OK.
07780  */
07781 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
07782 {
07783   return VarR8FromUI2(uiIn, pdateOut);
07784 }
07785 
07786 /******************************************************************************
07787  * VarDateFromUI4 (OLEAUT32.223)
07788  *
07789  * Convert a VT_UI4 to a VT_DATE.
07790  *
07791  * PARAMS
07792  *  ulIn     [I] Source
07793  *  pdateOut [O] Destination
07794  *
07795  * RETURNS
07796  *  S_OK.
07797  */
07798 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
07799 {
07800   return VarDateFromR8(ulIn, pdateOut);
07801 }
07802 
07803 /**********************************************************************
07804  * VarDateFromDec (OLEAUT32.224)
07805  *
07806  * Convert a VT_DECIMAL to a VT_DATE.
07807  *
07808  * PARAMS
07809  *  pdecIn   [I] Source
07810  *  pdateOut [O] Destination
07811  *
07812  * RETURNS
07813  *  S_OK.
07814  */
07815 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
07816 {
07817   return VarR8FromDec(pdecIn, pdateOut);
07818 }
07819 
07820 /******************************************************************************
07821  * VarDateFromI8 (OLEAUT32.364)
07822  *
07823  * Convert a VT_I8 to a VT_DATE.
07824  *
07825  * PARAMS
07826  *  llIn     [I] Source
07827  *  pdateOut [O] Destination
07828  *
07829  * RETURNS
07830  *  Success: S_OK.
07831  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
07832  */
07833 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
07834 {
07835   if (llIn < DATE_MIN || llIn > DATE_MAX) return DISP_E_OVERFLOW;
07836   *pdateOut = (DATE)llIn;
07837   return S_OK;
07838 }
07839 
07840 /******************************************************************************
07841  * VarDateFromUI8 (OLEAUT32.365)
07842  *
07843  * Convert a VT_UI8 to a VT_DATE.
07844  *
07845  * PARAMS
07846  *  ullIn    [I] Source
07847  *  pdateOut [O] Destination
07848  *
07849  * RETURNS
07850  *  Success: S_OK.
07851  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
07852  */
07853 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
07854 {
07855   if (ullIn > DATE_MAX) return DISP_E_OVERFLOW;
07856   *pdateOut = (DATE)ullIn;
07857   return S_OK;
07858 }

Generated on Sat May 26 2012 04:24:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.