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

variant.c
Go to the documentation of this file.
00001 /*
00002  * VARIANT
00003  *
00004  * Copyright 1998 Jean-Claude Cote
00005  * Copyright 2003 Jon Griffiths
00006  * Copyright 2005 Daniel Remenak
00007  * Copyright 2006 Google (Benjamin Arai)
00008  *
00009  * The algorithm for conversion from Julian days to day/month/year is based on
00010  * that devised by Henry Fliegel, as implemented in PostgreSQL, which is
00011  * Copyright 1994-7 Regents of the University of California
00012  *
00013  * This library is free software; you can redistribute it and/or
00014  * modify it under the terms of the GNU Lesser General Public
00015  * License as published by the Free Software Foundation; either
00016  * version 2.1 of the License, or (at your option) any later version.
00017  *
00018  * This library is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021  * Lesser General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public
00024  * License along with this library; if not, write to the Free Software
00025  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00026  */
00027 
00028 #include "config.h"
00029 
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #include <stdarg.h>
00033 
00034 #define COBJMACROS
00035 #define NONAMELESSUNION
00036 #define NONAMELESSSTRUCT
00037 
00038 #include "windef.h"
00039 #include "winbase.h"
00040 #include "wine/unicode.h"
00041 #include "winerror.h"
00042 #include "variant.h"
00043 #include "resource.h"
00044 #include "wine/debug.h"
00045 
00046 WINE_DEFAULT_DEBUG_CHANNEL(variant);
00047 
00048 const char * const wine_vtypes[VT_CLSID+1] =
00049 {
00050   "VT_EMPTY","VT_NULL","VT_I2","VT_I4","VT_R4","VT_R8","VT_CY","VT_DATE",
00051   "VT_BSTR","VT_DISPATCH","VT_ERROR","VT_BOOL","VT_VARIANT","VT_UNKNOWN",
00052   "VT_DECIMAL","15","VT_I1","VT_UI1","VT_UI2","VT_UI4","VT_I8","VT_UI8",
00053   "VT_INT","VT_UINT","VT_VOID","VT_HRESULT","VT_PTR","VT_SAFEARRAY",
00054   "VT_CARRAY","VT_USERDEFINED","VT_LPSTR","VT_LPWSTR","32","33","34","35",
00055   "VT_RECORD","VT_INT_PTR","VT_UINT_PTR","39","40","41","42","43","44","45",
00056   "46","47","48","49","50","51","52","53","54","55","56","57","58","59","60",
00057   "61","62","63","VT_FILETIME","VT_BLOB","VT_STREAM","VT_STORAGE",
00058   "VT_STREAMED_OBJECT","VT_STORED_OBJECT","VT_BLOB_OBJECT","VT_CF","VT_CLSID"
00059 };
00060 
00061 const char * const wine_vflags[16] =
00062 {
00063  "",
00064  "|VT_VECTOR",
00065  "|VT_ARRAY",
00066  "|VT_VECTOR|VT_ARRAY",
00067  "|VT_BYREF",
00068  "|VT_VECTOR|VT_ARRAY",
00069  "|VT_ARRAY|VT_BYREF",
00070  "|VT_VECTOR|VT_ARRAY|VT_BYREF",
00071  "|VT_HARDTYPE",
00072  "|VT_VECTOR|VT_HARDTYPE",
00073  "|VT_ARRAY|VT_HARDTYPE",
00074  "|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
00075  "|VT_BYREF|VT_HARDTYPE",
00076  "|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
00077  "|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
00078  "|VT_VECTOR|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
00079 };
00080 
00081 /* Convert a variant from one type to another */
00082 static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
00083                                      VARIANTARG* ps, VARTYPE vt)
00084 {
00085   HRESULT res = DISP_E_TYPEMISMATCH;
00086   VARTYPE vtFrom =  V_TYPE(ps);
00087   DWORD dwFlags = 0;
00088 
00089   TRACE("(%p->(%s%s),0x%08x,0x%04x,%p->(%s%s),%s%s)\n", pd, debugstr_VT(pd),
00090         debugstr_VF(pd), lcid, wFlags, ps, debugstr_VT(ps), debugstr_VF(ps),
00091         debugstr_vt(vt), debugstr_vf(vt));
00092 
00093   if (vt == VT_BSTR || vtFrom == VT_BSTR)
00094   {
00095     /* All flags passed to low level function are only used for
00096      * changing to or from strings. Map these here.
00097      */
00098     if (wFlags & VARIANT_LOCALBOOL)
00099       dwFlags |= VAR_LOCALBOOL;
00100     if (wFlags & VARIANT_CALENDAR_HIJRI)
00101       dwFlags |= VAR_CALENDAR_HIJRI;
00102     if (wFlags & VARIANT_CALENDAR_THAI)
00103       dwFlags |= VAR_CALENDAR_THAI;
00104     if (wFlags & VARIANT_CALENDAR_GREGORIAN)
00105       dwFlags |= VAR_CALENDAR_GREGORIAN;
00106     if (wFlags & VARIANT_NOUSEROVERRIDE)
00107       dwFlags |= LOCALE_NOUSEROVERRIDE;
00108     if (wFlags & VARIANT_USE_NLS)
00109       dwFlags |= LOCALE_USE_NLS;
00110   }
00111 
00112   /* Map int/uint to i4/ui4 */
00113   if (vt == VT_INT)
00114     vt = VT_I4;
00115   else if (vt == VT_UINT)
00116     vt = VT_UI4;
00117 
00118   if (vtFrom == VT_INT)
00119     vtFrom = VT_I4;
00120   else if (vtFrom == VT_UINT)
00121     vtFrom = VT_UI4;
00122 
00123   if (vt == vtFrom)
00124      return VariantCopy(pd, ps);
00125 
00126   if (wFlags & VARIANT_NOVALUEPROP && vtFrom == VT_DISPATCH && vt != VT_UNKNOWN)
00127   {
00128     /* VARIANT_NOVALUEPROP prevents IDispatch objects from being coerced by
00129      * accessing the default object property.
00130      */
00131     return DISP_E_TYPEMISMATCH;
00132   }
00133 
00134   switch (vt)
00135   {
00136   case VT_EMPTY:
00137     if (vtFrom == VT_NULL)
00138       return DISP_E_TYPEMISMATCH;
00139     /* ... Fall through */
00140   case VT_NULL:
00141     if (vtFrom <= VT_UINT && vtFrom != (VARTYPE)15 && vtFrom != VT_ERROR)
00142     {
00143       res = VariantClear( pd );
00144       if (vt == VT_NULL && SUCCEEDED(res))
00145         V_VT(pd) = VT_NULL;
00146     }
00147     return res;
00148 
00149   case VT_I1:
00150     switch (vtFrom)
00151     {
00152     case VT_EMPTY:    V_I1(pd) = 0; return S_OK;
00153     case VT_I2:       return VarI1FromI2(V_I2(ps), &V_I1(pd));
00154     case VT_I4:       return VarI1FromI4(V_I4(ps), &V_I1(pd));
00155     case VT_UI1:      V_I1(pd) = V_UI1(ps); return S_OK;
00156     case VT_UI2:      return VarI1FromUI2(V_UI2(ps), &V_I1(pd));
00157     case VT_UI4:      return VarI1FromUI4(V_UI4(ps), &V_I1(pd));
00158     case VT_I8:       return VarI1FromI8(V_I8(ps), &V_I1(pd));
00159     case VT_UI8:      return VarI1FromUI8(V_UI8(ps), &V_I1(pd));
00160     case VT_R4:       return VarI1FromR4(V_R4(ps), &V_I1(pd));
00161     case VT_R8:       return VarI1FromR8(V_R8(ps), &V_I1(pd));
00162     case VT_DATE:     return VarI1FromDate(V_DATE(ps), &V_I1(pd));
00163     case VT_BOOL:     return VarI1FromBool(V_BOOL(ps), &V_I1(pd));
00164     case VT_CY:       return VarI1FromCy(V_CY(ps), &V_I1(pd));
00165     case VT_DECIMAL:  return VarI1FromDec(&V_DECIMAL(ps), &V_I1(pd) );
00166     case VT_DISPATCH: return VarI1FromDisp(V_DISPATCH(ps), lcid, &V_I1(pd) );
00167     case VT_BSTR:     return VarI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_I1(pd) );
00168     }
00169     break;
00170 
00171   case VT_I2:
00172     switch (vtFrom)
00173     {
00174     case VT_EMPTY:    V_I2(pd) = 0; return S_OK;
00175     case VT_I1:       return VarI2FromI1(V_I1(ps), &V_I2(pd));
00176     case VT_I4:       return VarI2FromI4(V_I4(ps), &V_I2(pd));
00177     case VT_UI1:      return VarI2FromUI1(V_UI1(ps), &V_I2(pd));
00178     case VT_UI2:      V_I2(pd) = V_UI2(ps); return S_OK;
00179     case VT_UI4:      return VarI2FromUI4(V_UI4(ps), &V_I2(pd));
00180     case VT_I8:       return VarI2FromI8(V_I8(ps), &V_I2(pd));
00181     case VT_UI8:      return VarI2FromUI8(V_UI8(ps), &V_I2(pd));
00182     case VT_R4:       return VarI2FromR4(V_R4(ps), &V_I2(pd));
00183     case VT_R8:       return VarI2FromR8(V_R8(ps), &V_I2(pd));
00184     case VT_DATE:     return VarI2FromDate(V_DATE(ps), &V_I2(pd));
00185     case VT_BOOL:     return VarI2FromBool(V_BOOL(ps), &V_I2(pd));
00186     case VT_CY:       return VarI2FromCy(V_CY(ps), &V_I2(pd));
00187     case VT_DECIMAL:  return VarI2FromDec(&V_DECIMAL(ps), &V_I2(pd));
00188     case VT_DISPATCH: return VarI2FromDisp(V_DISPATCH(ps), lcid, &V_I2(pd));
00189     case VT_BSTR:     return VarI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_I2(pd));
00190     }
00191     break;
00192 
00193   case VT_I4:
00194     switch (vtFrom)
00195     {
00196     case VT_EMPTY:    V_I4(pd) = 0; return S_OK;
00197     case VT_I1:       return VarI4FromI1(V_I1(ps), &V_I4(pd));
00198     case VT_I2:       return VarI4FromI2(V_I2(ps), &V_I4(pd));
00199     case VT_UI1:      return VarI4FromUI1(V_UI1(ps), &V_I4(pd));
00200     case VT_UI2:      return VarI4FromUI2(V_UI2(ps), &V_I4(pd));
00201     case VT_UI4:      V_I4(pd) = V_UI4(ps); return S_OK;
00202     case VT_I8:       return VarI4FromI8(V_I8(ps), &V_I4(pd));
00203     case VT_UI8:      return VarI4FromUI8(V_UI8(ps), &V_I4(pd));
00204     case VT_R4:       return VarI4FromR4(V_R4(ps), &V_I4(pd));
00205     case VT_R8:       return VarI4FromR8(V_R8(ps), &V_I4(pd));
00206     case VT_DATE:     return VarI4FromDate(V_DATE(ps), &V_I4(pd));
00207     case VT_BOOL:     return VarI4FromBool(V_BOOL(ps), &V_I4(pd));
00208     case VT_CY:       return VarI4FromCy(V_CY(ps), &V_I4(pd));
00209     case VT_DECIMAL:  return VarI4FromDec(&V_DECIMAL(ps), &V_I4(pd));
00210     case VT_DISPATCH: return VarI4FromDisp(V_DISPATCH(ps), lcid, &V_I4(pd));
00211     case VT_BSTR:     return VarI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_I4(pd));
00212     }
00213     break;
00214 
00215   case VT_UI1:
00216     switch (vtFrom)
00217     {
00218     case VT_EMPTY:    V_UI1(pd) = 0; return S_OK;
00219     case VT_I1:       V_UI1(pd) = V_I1(ps); return S_OK;
00220     case VT_I2:       return VarUI1FromI2(V_I2(ps), &V_UI1(pd));
00221     case VT_I4:       return VarUI1FromI4(V_I4(ps), &V_UI1(pd));
00222     case VT_UI2:      return VarUI1FromUI2(V_UI2(ps), &V_UI1(pd));
00223     case VT_UI4:      return VarUI1FromUI4(V_UI4(ps), &V_UI1(pd));
00224     case VT_I8:       return VarUI1FromI8(V_I8(ps), &V_UI1(pd));
00225     case VT_UI8:      return VarUI1FromUI8(V_UI8(ps), &V_UI1(pd));
00226     case VT_R4:       return VarUI1FromR4(V_R4(ps), &V_UI1(pd));
00227     case VT_R8:       return VarUI1FromR8(V_R8(ps), &V_UI1(pd));
00228     case VT_DATE:     return VarUI1FromDate(V_DATE(ps), &V_UI1(pd));
00229     case VT_BOOL:     return VarUI1FromBool(V_BOOL(ps), &V_UI1(pd));
00230     case VT_CY:       return VarUI1FromCy(V_CY(ps), &V_UI1(pd));
00231     case VT_DECIMAL:  return VarUI1FromDec(&V_DECIMAL(ps), &V_UI1(pd));
00232     case VT_DISPATCH: return VarUI1FromDisp(V_DISPATCH(ps), lcid, &V_UI1(pd));
00233     case VT_BSTR:     return VarUI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI1(pd));
00234     }
00235     break;
00236 
00237   case VT_UI2:
00238     switch (vtFrom)
00239     {
00240     case VT_EMPTY:    V_UI2(pd) = 0; return S_OK;
00241     case VT_I1:       return VarUI2FromI1(V_I1(ps), &V_UI2(pd));
00242     case VT_I2:       V_UI2(pd) = V_I2(ps); return S_OK;
00243     case VT_I4:       return VarUI2FromI4(V_I4(ps), &V_UI2(pd));
00244     case VT_UI1:      return VarUI2FromUI1(V_UI1(ps), &V_UI2(pd));
00245     case VT_UI4:      return VarUI2FromUI4(V_UI4(ps), &V_UI2(pd));
00246     case VT_I8:       return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
00247     case VT_UI8:      return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
00248     case VT_R4:       return VarUI2FromR4(V_R4(ps), &V_UI2(pd));
00249     case VT_R8:       return VarUI2FromR8(V_R8(ps), &V_UI2(pd));
00250     case VT_DATE:     return VarUI2FromDate(V_DATE(ps), &V_UI2(pd));
00251     case VT_BOOL:     return VarUI2FromBool(V_BOOL(ps), &V_UI2(pd));
00252     case VT_CY:       return VarUI2FromCy(V_CY(ps), &V_UI2(pd));
00253     case VT_DECIMAL:  return VarUI2FromDec(&V_DECIMAL(ps), &V_UI2(pd));
00254     case VT_DISPATCH: return VarUI2FromDisp(V_DISPATCH(ps), lcid, &V_UI2(pd));
00255     case VT_BSTR:     return VarUI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI2(pd));
00256     }
00257     break;
00258 
00259   case VT_UI4:
00260     switch (vtFrom)
00261     {
00262     case VT_EMPTY:    V_UI4(pd) = 0; return S_OK;
00263     case VT_I1:       return VarUI4FromI1(V_I1(ps), &V_UI4(pd));
00264     case VT_I2:       return VarUI4FromI2(V_I2(ps), &V_UI4(pd));
00265     case VT_I4:       V_UI4(pd) = V_I4(ps); return S_OK;
00266     case VT_UI1:      return VarUI4FromUI1(V_UI1(ps), &V_UI4(pd));
00267     case VT_UI2:      return VarUI4FromUI2(V_UI2(ps), &V_UI4(pd));
00268     case VT_I8:       return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
00269     case VT_UI8:      return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
00270     case VT_R4:       return VarUI4FromR4(V_R4(ps), &V_UI4(pd));
00271     case VT_R8:       return VarUI4FromR8(V_R8(ps), &V_UI4(pd));
00272     case VT_DATE:     return VarUI4FromDate(V_DATE(ps), &V_UI4(pd));
00273     case VT_BOOL:     return VarUI4FromBool(V_BOOL(ps), &V_UI4(pd));
00274     case VT_CY:       return VarUI4FromCy(V_CY(ps), &V_UI4(pd));
00275     case VT_DECIMAL:  return VarUI4FromDec(&V_DECIMAL(ps), &V_UI4(pd));
00276     case VT_DISPATCH: return VarUI4FromDisp(V_DISPATCH(ps), lcid, &V_UI4(pd));
00277     case VT_BSTR:     return VarUI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI4(pd));
00278     }
00279     break;
00280 
00281   case VT_UI8:
00282     switch (vtFrom)
00283     {
00284     case VT_EMPTY:    V_UI8(pd) = 0; return S_OK;
00285     case VT_I4:       if (V_I4(ps) < 0) return DISP_E_OVERFLOW; V_UI8(pd) = V_I4(ps); return S_OK;
00286     case VT_I1:       return VarUI8FromI1(V_I1(ps), &V_UI8(pd));
00287     case VT_I2:       return VarUI8FromI2(V_I2(ps), &V_UI8(pd));
00288     case VT_UI1:      return VarUI8FromUI1(V_UI1(ps), &V_UI8(pd));
00289     case VT_UI2:      return VarUI8FromUI2(V_UI2(ps), &V_UI8(pd));
00290     case VT_UI4:      return VarUI8FromUI4(V_UI4(ps), &V_UI8(pd));
00291     case VT_I8:       V_UI8(pd) = V_I8(ps); return S_OK;
00292     case VT_R4:       return VarUI8FromR4(V_R4(ps), &V_UI8(pd));
00293     case VT_R8:       return VarUI8FromR8(V_R8(ps), &V_UI8(pd));
00294     case VT_DATE:     return VarUI8FromDate(V_DATE(ps), &V_UI8(pd));
00295     case VT_BOOL:     return VarUI8FromBool(V_BOOL(ps), &V_UI8(pd));
00296     case VT_CY:       return VarUI8FromCy(V_CY(ps), &V_UI8(pd));
00297     case VT_DECIMAL:  return VarUI8FromDec(&V_DECIMAL(ps), &V_UI8(pd));
00298     case VT_DISPATCH: return VarUI8FromDisp(V_DISPATCH(ps), lcid, &V_UI8(pd));
00299     case VT_BSTR:     return VarUI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI8(pd));
00300     }
00301     break;
00302 
00303   case VT_I8:
00304     switch (vtFrom)
00305     {
00306     case VT_EMPTY:    V_I8(pd) = 0; return S_OK;
00307     case VT_I4:       V_I8(pd) = V_I4(ps); return S_OK;
00308     case VT_I1:       return VarI8FromI1(V_I1(ps), &V_I8(pd));
00309     case VT_I2:       return VarI8FromI2(V_I2(ps), &V_I8(pd));
00310     case VT_UI1:      return VarI8FromUI1(V_UI1(ps), &V_I8(pd));
00311     case VT_UI2:      return VarI8FromUI2(V_UI2(ps), &V_I8(pd));
00312     case VT_UI4:      return VarI8FromUI4(V_UI4(ps), &V_I8(pd));
00313     case VT_UI8:      V_I8(pd) = V_UI8(ps); return S_OK;
00314     case VT_R4:       return VarI8FromR4(V_R4(ps), &V_I8(pd));
00315     case VT_R8:       return VarI8FromR8(V_R8(ps), &V_I8(pd));
00316     case VT_DATE:     return VarI8FromDate(V_DATE(ps), &V_I8(pd));
00317     case VT_BOOL:     return VarI8FromBool(V_BOOL(ps), &V_I8(pd));
00318     case VT_CY:       return VarI8FromCy(V_CY(ps), &V_I8(pd));
00319     case VT_DECIMAL:  return VarI8FromDec(&V_DECIMAL(ps), &V_I8(pd));
00320     case VT_DISPATCH: return VarI8FromDisp(V_DISPATCH(ps), lcid, &V_I8(pd));
00321     case VT_BSTR:     return VarI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_I8(pd));
00322     }
00323     break;
00324 
00325   case VT_R4:
00326     switch (vtFrom)
00327     {
00328     case VT_EMPTY:    V_R4(pd) = 0.0f; return S_OK;
00329     case VT_I1:       return VarR4FromI1(V_I1(ps), &V_R4(pd));
00330     case VT_I2:       return VarR4FromI2(V_I2(ps), &V_R4(pd));
00331     case VT_I4:       return VarR4FromI4(V_I4(ps), &V_R4(pd));
00332     case VT_UI1:      return VarR4FromUI1(V_UI1(ps), &V_R4(pd));
00333     case VT_UI2:      return VarR4FromUI2(V_UI2(ps), &V_R4(pd));
00334     case VT_UI4:      return VarR4FromUI4(V_UI4(ps), &V_R4(pd));
00335     case VT_I8:       return VarR4FromI8(V_I8(ps), &V_R4(pd));
00336     case VT_UI8:      return VarR4FromUI8(V_UI8(ps), &V_R4(pd));
00337     case VT_R8:       return VarR4FromR8(V_R8(ps), &V_R4(pd));
00338     case VT_DATE:     return VarR4FromDate(V_DATE(ps), &V_R4(pd));
00339     case VT_BOOL:     return VarR4FromBool(V_BOOL(ps), &V_R4(pd));
00340     case VT_CY:       return VarR4FromCy(V_CY(ps), &V_R4(pd));
00341     case VT_DECIMAL:  return VarR4FromDec(&V_DECIMAL(ps), &V_R4(pd));
00342     case VT_DISPATCH: return VarR4FromDisp(V_DISPATCH(ps), lcid, &V_R4(pd));
00343     case VT_BSTR:     return VarR4FromStr(V_BSTR(ps), lcid, dwFlags, &V_R4(pd));
00344     }
00345     break;
00346 
00347   case VT_R8:
00348     switch (vtFrom)
00349     {
00350     case VT_EMPTY:    V_R8(pd) = 0.0; return S_OK;
00351     case VT_I1:       return VarR8FromI1(V_I1(ps), &V_R8(pd));
00352     case VT_I2:       return VarR8FromI2(V_I2(ps), &V_R8(pd));
00353     case VT_I4:       return VarR8FromI4(V_I4(ps), &V_R8(pd));
00354     case VT_UI1:      return VarR8FromUI1(V_UI1(ps), &V_R8(pd));
00355     case VT_UI2:      return VarR8FromUI2(V_UI2(ps), &V_R8(pd));
00356     case VT_UI4:      return VarR8FromUI4(V_UI4(ps), &V_R8(pd));
00357     case VT_I8:       return VarR8FromI8(V_I8(ps), &V_R8(pd));
00358     case VT_UI8:      return VarR8FromUI8(V_UI8(ps), &V_R8(pd));
00359     case VT_R4:       return VarR8FromR4(V_R4(ps), &V_R8(pd));
00360     case VT_DATE:     return VarR8FromDate(V_DATE(ps), &V_R8(pd));
00361     case VT_BOOL:     return VarR8FromBool(V_BOOL(ps), &V_R8(pd));
00362     case VT_CY:       return VarR8FromCy(V_CY(ps), &V_R8(pd));
00363     case VT_DECIMAL:  return VarR8FromDec(&V_DECIMAL(ps), &V_R8(pd));
00364     case VT_DISPATCH: return VarR8FromDisp(V_DISPATCH(ps), lcid, &V_R8(pd));
00365     case VT_BSTR:     return VarR8FromStr(V_BSTR(ps), lcid, dwFlags, &V_R8(pd));
00366     }
00367     break;
00368 
00369   case VT_DATE:
00370     switch (vtFrom)
00371     {
00372     case VT_EMPTY:    V_DATE(pd) = 0.0; return S_OK;
00373     case VT_I1:       return VarDateFromI1(V_I1(ps), &V_DATE(pd));
00374     case VT_I2:       return VarDateFromI2(V_I2(ps), &V_DATE(pd));
00375     case VT_I4:       return VarDateFromI4(V_I4(ps), &V_DATE(pd));
00376     case VT_UI1:      return VarDateFromUI1(V_UI1(ps), &V_DATE(pd));
00377     case VT_UI2:      return VarDateFromUI2(V_UI2(ps), &V_DATE(pd));
00378     case VT_UI4:      return VarDateFromUI4(V_UI4(ps), &V_DATE(pd));
00379     case VT_I8:       return VarDateFromI8(V_I8(ps), &V_DATE(pd));
00380     case VT_UI8:      return VarDateFromUI8(V_UI8(ps), &V_DATE(pd));
00381     case VT_R4:       return VarDateFromR4(V_R4(ps), &V_DATE(pd));
00382     case VT_R8:       return VarDateFromR8(V_R8(ps), &V_DATE(pd));
00383     case VT_BOOL:     return VarDateFromBool(V_BOOL(ps), &V_DATE(pd));
00384     case VT_CY:       return VarDateFromCy(V_CY(ps), &V_DATE(pd));
00385     case VT_DECIMAL:  return VarDateFromDec(&V_DECIMAL(ps), &V_DATE(pd));
00386     case VT_DISPATCH: return VarDateFromDisp(V_DISPATCH(ps), lcid, &V_DATE(pd));
00387     case VT_BSTR:     return VarDateFromStr(V_BSTR(ps), lcid, dwFlags, &V_DATE(pd));
00388     }
00389     break;
00390 
00391   case VT_BOOL:
00392     switch (vtFrom)
00393     {
00394     case VT_EMPTY:    V_BOOL(pd) = 0; return S_OK;
00395     case VT_I1:       return VarBoolFromI1(V_I1(ps), &V_BOOL(pd));
00396     case VT_I2:       return VarBoolFromI2(V_I2(ps), &V_BOOL(pd));
00397     case VT_I4:       return VarBoolFromI4(V_I4(ps), &V_BOOL(pd));
00398     case VT_UI1:      return VarBoolFromUI1(V_UI1(ps), &V_BOOL(pd));
00399     case VT_UI2:      return VarBoolFromUI2(V_UI2(ps), &V_BOOL(pd));
00400     case VT_UI4:      return VarBoolFromUI4(V_UI4(ps), &V_BOOL(pd));
00401     case VT_I8:       return VarBoolFromI8(V_I8(ps), &V_BOOL(pd));
00402     case VT_UI8:      return VarBoolFromUI8(V_UI8(ps), &V_BOOL(pd));
00403     case VT_R4:       return VarBoolFromR4(V_R4(ps), &V_BOOL(pd));
00404     case VT_R8:       return VarBoolFromR8(V_R8(ps), &V_BOOL(pd));
00405     case VT_DATE:     return VarBoolFromDate(V_DATE(ps), &V_BOOL(pd));
00406     case VT_CY:       return VarBoolFromCy(V_CY(ps), &V_BOOL(pd));
00407     case VT_DECIMAL:  return VarBoolFromDec(&V_DECIMAL(ps), &V_BOOL(pd));
00408     case VT_DISPATCH: return VarBoolFromDisp(V_DISPATCH(ps), lcid, &V_BOOL(pd));
00409     case VT_BSTR:     return VarBoolFromStr(V_BSTR(ps), lcid, dwFlags, &V_BOOL(pd));
00410     }
00411     break;
00412 
00413   case VT_BSTR:
00414     switch (vtFrom)
00415     {
00416     case VT_EMPTY:
00417       V_BSTR(pd) = SysAllocStringLen(NULL, 0);
00418       return V_BSTR(pd) ? S_OK : E_OUTOFMEMORY;
00419     case VT_BOOL:
00420       if (wFlags & (VARIANT_ALPHABOOL|VARIANT_LOCALBOOL))
00421          return VarBstrFromBool(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
00422       return VarBstrFromI2(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
00423     case VT_I1:       return VarBstrFromI1(V_I1(ps), lcid, dwFlags, &V_BSTR(pd));
00424     case VT_I2:       return VarBstrFromI2(V_I2(ps), lcid, dwFlags, &V_BSTR(pd));
00425     case VT_I4:       return VarBstrFromI4(V_I4(ps), lcid, dwFlags, &V_BSTR(pd));
00426     case VT_UI1:      return VarBstrFromUI1(V_UI1(ps), lcid, dwFlags, &V_BSTR(pd));
00427     case VT_UI2:      return VarBstrFromUI2(V_UI2(ps), lcid, dwFlags, &V_BSTR(pd));
00428     case VT_UI4:      return VarBstrFromUI4(V_UI4(ps), lcid, dwFlags, &V_BSTR(pd));
00429     case VT_I8:       return VarBstrFromI8(V_I8(ps), lcid, dwFlags, &V_BSTR(pd));
00430     case VT_UI8:      return VarBstrFromUI8(V_UI8(ps), lcid, dwFlags, &V_BSTR(pd));
00431     case VT_R4:       return VarBstrFromR4(V_R4(ps), lcid, dwFlags, &V_BSTR(pd));
00432     case VT_R8:       return VarBstrFromR8(V_R8(ps), lcid, dwFlags, &V_BSTR(pd));
00433     case VT_DATE:     return VarBstrFromDate(V_DATE(ps), lcid, dwFlags, &V_BSTR(pd));
00434     case VT_CY:       return VarBstrFromCy(V_CY(ps), lcid, dwFlags, &V_BSTR(pd));
00435     case VT_DECIMAL:  return VarBstrFromDec(&V_DECIMAL(ps), lcid, dwFlags, &V_BSTR(pd));
00436     case VT_DISPATCH: return VarBstrFromDisp(V_DISPATCH(ps), lcid, dwFlags, &V_BSTR(pd));
00437     }
00438     break;
00439 
00440   case VT_CY:
00441     switch (vtFrom)
00442     {
00443     case VT_EMPTY:    V_CY(pd).int64 = 0; return S_OK;
00444     case VT_I1:       return VarCyFromI1(V_I1(ps), &V_CY(pd));
00445     case VT_I2:       return VarCyFromI2(V_I2(ps), &V_CY(pd));
00446     case VT_I4:       return VarCyFromI4(V_I4(ps), &V_CY(pd));
00447     case VT_UI1:      return VarCyFromUI1(V_UI1(ps), &V_CY(pd));
00448     case VT_UI2:      return VarCyFromUI2(V_UI2(ps), &V_CY(pd));
00449     case VT_UI4:      return VarCyFromUI4(V_UI4(ps), &V_CY(pd));
00450     case VT_I8:       return VarCyFromI8(V_I8(ps), &V_CY(pd));
00451     case VT_UI8:      return VarCyFromUI8(V_UI8(ps), &V_CY(pd));
00452     case VT_R4:       return VarCyFromR4(V_R4(ps), &V_CY(pd));
00453     case VT_R8:       return VarCyFromR8(V_R8(ps), &V_CY(pd));
00454     case VT_DATE:     return VarCyFromDate(V_DATE(ps), &V_CY(pd));
00455     case VT_BOOL:     return VarCyFromBool(V_BOOL(ps), &V_CY(pd));
00456     case VT_DECIMAL:  return VarCyFromDec(&V_DECIMAL(ps), &V_CY(pd));
00457     case VT_DISPATCH: return VarCyFromDisp(V_DISPATCH(ps), lcid, &V_CY(pd));
00458     case VT_BSTR:     return VarCyFromStr(V_BSTR(ps), lcid, dwFlags, &V_CY(pd));
00459     }
00460     break;
00461 
00462   case VT_DECIMAL:
00463     switch (vtFrom)
00464     {
00465     case VT_EMPTY:
00466     case VT_BOOL:
00467        DEC_SIGNSCALE(&V_DECIMAL(pd)) = SIGNSCALE(DECIMAL_POS,0);
00468        DEC_HI32(&V_DECIMAL(pd)) = 0;
00469        DEC_MID32(&V_DECIMAL(pd)) = 0;
00470         /* VarDecFromBool() coerces to -1/0, ChangeTypeEx() coerces to 1/0.
00471          * VT_NULL and VT_EMPTY always give a 0 value.
00472          */
00473        DEC_LO32(&V_DECIMAL(pd)) = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0;
00474        return S_OK;
00475     case VT_I1:       return VarDecFromI1(V_I1(ps), &V_DECIMAL(pd));
00476     case VT_I2:       return VarDecFromI2(V_I2(ps), &V_DECIMAL(pd));
00477     case VT_I4:       return VarDecFromI4(V_I4(ps), &V_DECIMAL(pd));
00478     case VT_UI1:      return VarDecFromUI1(V_UI1(ps), &V_DECIMAL(pd));
00479     case VT_UI2:      return VarDecFromUI2(V_UI2(ps), &V_DECIMAL(pd));
00480     case VT_UI4:      return VarDecFromUI4(V_UI4(ps), &V_DECIMAL(pd));
00481     case VT_I8:       return VarDecFromI8(V_I8(ps), &V_DECIMAL(pd));
00482     case VT_UI8:      return VarDecFromUI8(V_UI8(ps), &V_DECIMAL(pd));
00483     case VT_R4:       return VarDecFromR4(V_R4(ps), &V_DECIMAL(pd));
00484     case VT_R8:       return VarDecFromR8(V_R8(ps), &V_DECIMAL(pd));
00485     case VT_DATE:     return VarDecFromDate(V_DATE(ps), &V_DECIMAL(pd));
00486     case VT_CY:       return VarDecFromCy(V_CY(ps), &V_DECIMAL(pd));
00487     case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(pd));
00488     case VT_BSTR:     return VarDecFromStr(V_BSTR(ps), lcid, dwFlags, &V_DECIMAL(pd));
00489     }
00490     break;
00491 
00492   case VT_UNKNOWN:
00493     switch (vtFrom)
00494     {
00495     case VT_DISPATCH:
00496       if (V_DISPATCH(ps) == NULL)
00497         V_UNKNOWN(pd) = NULL;
00498       else
00499         res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd));
00500       break;
00501     }
00502     break;
00503 
00504   case VT_DISPATCH:
00505     switch (vtFrom)
00506     {
00507     case VT_UNKNOWN:
00508       if (V_UNKNOWN(ps) == NULL)
00509         V_DISPATCH(pd) = NULL;
00510       else
00511         res = IUnknown_QueryInterface(V_UNKNOWN(ps), &IID_IDispatch, (LPVOID*)&V_DISPATCH(pd));
00512       break;
00513     }
00514     break;
00515 
00516   case VT_RECORD:
00517     break;
00518   }
00519   return res;
00520 }
00521 
00522 /* Coerce to/from an array */
00523 static inline HRESULT VARIANT_CoerceArray(VARIANTARG* pd, VARIANTARG* ps, VARTYPE vt)
00524 {
00525   if (vt == VT_BSTR && V_VT(ps) == (VT_ARRAY|VT_UI1))
00526     return BstrFromVector(V_ARRAY(ps), &V_BSTR(pd));
00527 
00528   if (V_VT(ps) == VT_BSTR && vt == (VT_ARRAY|VT_UI1))
00529     return VectorFromBstr(V_BSTR(ps), &V_ARRAY(ps));
00530 
00531   if (V_VT(ps) == vt)
00532     return SafeArrayCopy(V_ARRAY(ps), &V_ARRAY(pd));
00533 
00534   return DISP_E_TYPEMISMATCH;
00535 }
00536 
00537 /******************************************************************************
00538  * Check if a variants type is valid.
00539  */
00540 static inline HRESULT VARIANT_ValidateType(VARTYPE vt)
00541 {
00542   VARTYPE vtExtra = vt & VT_EXTRA_TYPE;
00543 
00544   vt &= VT_TYPEMASK;
00545 
00546   if (!(vtExtra & (VT_VECTOR|VT_RESERVED)))
00547   {
00548     if (vt < VT_VOID || vt == VT_RECORD || vt == VT_CLSID)
00549     {
00550       if ((vtExtra & (VT_BYREF|VT_ARRAY)) && vt <= VT_NULL)
00551         return DISP_E_BADVARTYPE;
00552       if (vt != (VARTYPE)15)
00553         return S_OK;
00554     }
00555   }
00556   return DISP_E_BADVARTYPE;
00557 }
00558 
00559 /******************************************************************************
00560  *      VariantInit [OLEAUT32.8]
00561  *
00562  * Initialise a variant.
00563  *
00564  * PARAMS
00565  *  pVarg [O] Variant to initialise
00566  *
00567  * RETURNS
00568  *  Nothing.
00569  *
00570  * NOTES
00571  *  This function simply sets the type of the variant to VT_EMPTY. It does not
00572  *  free any existing value, use VariantClear() for that.
00573  */
00574 void WINAPI VariantInit(VARIANTARG* pVarg)
00575 {
00576   TRACE("(%p)\n", pVarg);
00577 
00578   V_VT(pVarg) = VT_EMPTY; /* Native doesn't set any other fields */
00579 }
00580 
00581 HRESULT VARIANT_ClearInd(VARIANTARG *pVarg)
00582 {
00583     HRESULT hres;
00584 
00585     TRACE("(%p->(%s%s))\n", pVarg, debugstr_VT(pVarg), debugstr_VF(pVarg));
00586 
00587     hres = VARIANT_ValidateType(V_VT(pVarg));
00588     if (FAILED(hres))
00589         return hres;
00590 
00591     switch (V_VT(pVarg))
00592     {
00593     case VT_DISPATCH:
00594     case VT_UNKNOWN:
00595         if (V_UNKNOWN(pVarg))
00596             IUnknown_Release(V_UNKNOWN(pVarg));
00597         break;
00598     case VT_UNKNOWN | VT_BYREF:
00599     case VT_DISPATCH | VT_BYREF:
00600         if(*V_UNKNOWNREF(pVarg))
00601             IUnknown_Release(*V_UNKNOWNREF(pVarg));
00602         break;
00603     case VT_BSTR:
00604         SysFreeString(V_BSTR(pVarg));
00605         break;
00606     case VT_BSTR | VT_BYREF:
00607         SysFreeString(*V_BSTRREF(pVarg));
00608         break;
00609     case VT_VARIANT | VT_BYREF:
00610         VariantClear(V_VARIANTREF(pVarg));
00611         break;
00612     case VT_RECORD:
00613     case VT_RECORD | VT_BYREF:
00614     {
00615         struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal);
00616         if (pBr->pRecInfo)
00617         {
00618             IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord);
00619             IRecordInfo_Release(pBr->pRecInfo);
00620         }
00621         break;
00622     }
00623     default:
00624         if (V_ISARRAY(pVarg) || (V_VT(pVarg) & ~VT_BYREF) == VT_SAFEARRAY)
00625         {
00626             if (V_ISBYREF(pVarg))
00627             {
00628                 if (*V_ARRAYREF(pVarg))
00629                     hres = SafeArrayDestroy(*V_ARRAYREF(pVarg));
00630             }
00631             else if (V_ARRAY(pVarg))
00632                 hres = SafeArrayDestroy(V_ARRAY(pVarg));
00633         }
00634         break;
00635     }
00636 
00637     V_VT(pVarg) = VT_EMPTY;
00638     return hres;
00639 }
00640 
00641 /******************************************************************************
00642  *      VariantClear    [OLEAUT32.9]
00643  *
00644  * Clear a variant.
00645  *
00646  * PARAMS
00647  *  pVarg [I/O] Variant to clear
00648  *
00649  * RETURNS
00650  *  Success: S_OK. Any previous value in pVarg is freed and its type is set to VT_EMPTY.
00651  *  Failure: DISP_E_BADVARTYPE, if the variant is not a valid variant type.
00652  */
00653 HRESULT WINAPI VariantClear(VARIANTARG* pVarg)
00654 {
00655   HRESULT hres = S_OK;
00656 
00657   TRACE("(%p->(%s%s))\n", pVarg, debugstr_VT(pVarg), debugstr_VF(pVarg));
00658 
00659   hres = VARIANT_ValidateType(V_VT(pVarg));
00660 
00661   if (SUCCEEDED(hres))
00662   {
00663     if (!V_ISBYREF(pVarg))
00664     {
00665       if (V_ISARRAY(pVarg) || V_VT(pVarg) == VT_SAFEARRAY)
00666       {
00667         if (V_ARRAY(pVarg))
00668           hres = SafeArrayDestroy(V_ARRAY(pVarg));
00669       }
00670       else if (V_VT(pVarg) == VT_BSTR)
00671       {
00672         SysFreeString(V_BSTR(pVarg));
00673       }
00674       else if (V_VT(pVarg) == VT_RECORD)
00675       {
00676         struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal);
00677         if (pBr->pRecInfo)
00678         {
00679           IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord);
00680           IRecordInfo_Release(pBr->pRecInfo);
00681         }
00682       }
00683       else if (V_VT(pVarg) == VT_DISPATCH ||
00684                V_VT(pVarg) == VT_UNKNOWN)
00685       {
00686         if (V_UNKNOWN(pVarg))
00687           IUnknown_Release(V_UNKNOWN(pVarg));
00688       }
00689     }
00690     V_VT(pVarg) = VT_EMPTY;
00691   }
00692   return hres;
00693 }
00694 
00695 /******************************************************************************
00696  * Copy an IRecordInfo object contained in a variant.
00697  */
00698 static HRESULT VARIANT_CopyIRecordInfo(struct __tagBRECORD* pBr)
00699 {
00700   HRESULT hres = S_OK;
00701 
00702   if (pBr->pRecInfo)
00703   {
00704     ULONG ulSize;
00705 
00706     hres = IRecordInfo_GetSize(pBr->pRecInfo, &ulSize);
00707     if (SUCCEEDED(hres))
00708     {
00709       PVOID pvRecord = HeapAlloc(GetProcessHeap(), 0, ulSize);
00710       if (!pvRecord)
00711         hres = E_OUTOFMEMORY;
00712       else
00713       {
00714         memcpy(pvRecord, pBr->pvRecord, ulSize);
00715         pBr->pvRecord = pvRecord;
00716 
00717         hres = IRecordInfo_RecordCopy(pBr->pRecInfo, pvRecord, pvRecord);
00718         if (SUCCEEDED(hres))
00719           IRecordInfo_AddRef(pBr->pRecInfo);
00720       }
00721     }
00722   }
00723   else if (pBr->pvRecord)
00724     hres = E_INVALIDARG;
00725   return hres;
00726 }
00727 
00728 /******************************************************************************
00729  *    VariantCopy  [OLEAUT32.10]
00730  *
00731  * Copy a variant.
00732  *
00733  * PARAMS
00734  *  pvargDest [O] Destination for copy
00735  *  pvargSrc  [I] Source variant to copy
00736  *
00737  * RETURNS
00738  *  Success: S_OK. pvargDest contains a copy of pvargSrc.
00739  *  Failure: DISP_E_BADVARTYPE, if either variant has an invalid type.
00740  *           E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an
00741  *           HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(),
00742  *           or IRecordInfo_RecordCopy(), depending on the type of pvargSrc.
00743  *
00744  * NOTES
00745  *  - If pvargSrc == pvargDest, this function does nothing, and succeeds if
00746  *    pvargSrc is valid. Otherwise, pvargDest is always cleared using
00747  *    VariantClear() before pvargSrc is copied to it. If clearing pvargDest
00748  *    fails, so does this function.
00749  *  - VT_CLSID is a valid type type for pvargSrc, but not for pvargDest.
00750  *  - For by-value non-intrinsic types, a deep copy is made, i.e. The whole value
00751  *    is copied rather than just any pointers to it.
00752  *  - For by-value object types the object pointer is copied and the objects
00753  *    reference count increased using IUnknown_AddRef().
00754  *  - For all by-reference types, only the referencing pointer is copied.
00755  */
00756 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
00757 {
00758   HRESULT hres = S_OK;
00759 
00760   TRACE("(%p->(%s%s),%p->(%s%s))\n", pvargDest, debugstr_VT(pvargDest),
00761         debugstr_VF(pvargDest), pvargSrc, debugstr_VT(pvargSrc),
00762         debugstr_VF(pvargSrc));
00763 
00764   if (V_TYPE(pvargSrc) == VT_CLSID || /* VT_CLSID is a special case */
00765       FAILED(VARIANT_ValidateType(V_VT(pvargSrc))))
00766     return DISP_E_BADVARTYPE;
00767 
00768   if (pvargSrc != pvargDest &&
00769       SUCCEEDED(hres = VariantClear(pvargDest)))
00770   {
00771     *pvargDest = *pvargSrc; /* Shallow copy the value */
00772 
00773     if (!V_ISBYREF(pvargSrc))
00774     {
00775       if (V_ISARRAY(pvargSrc))
00776       {
00777         if (V_ARRAY(pvargSrc))
00778           hres = SafeArrayCopy(V_ARRAY(pvargSrc), &V_ARRAY(pvargDest));
00779       }
00780       else if (V_VT(pvargSrc) == VT_BSTR)
00781       {
00782         V_BSTR(pvargDest) = SysAllocStringByteLen((char*)V_BSTR(pvargSrc), SysStringByteLen(V_BSTR(pvargSrc)));
00783         if (!V_BSTR(pvargDest))
00784     {
00785       TRACE("!V_BSTR(pvargDest), SysAllocStringByteLen() failed to allocate %d bytes\n", SysStringByteLen(V_BSTR(pvargSrc)));
00786           hres = E_OUTOFMEMORY;
00787     }
00788       }
00789       else if (V_VT(pvargSrc) == VT_RECORD)
00790       {
00791         hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
00792       }
00793       else if (V_VT(pvargSrc) == VT_DISPATCH ||
00794                V_VT(pvargSrc) == VT_UNKNOWN)
00795       {
00796         if (V_UNKNOWN(pvargSrc))
00797           IUnknown_AddRef(V_UNKNOWN(pvargSrc));
00798       }
00799     }
00800   }
00801   return hres;
00802 }
00803 
00804 /* Return the byte size of a variants data */
00805 static inline size_t VARIANT_DataSize(const VARIANT* pv)
00806 {
00807   switch (V_TYPE(pv))
00808   {
00809   case VT_I1:
00810   case VT_UI1:   return sizeof(BYTE);
00811   case VT_I2:
00812   case VT_UI2:   return sizeof(SHORT);
00813   case VT_INT:
00814   case VT_UINT:
00815   case VT_I4:
00816   case VT_UI4:   return sizeof(LONG);
00817   case VT_I8:
00818   case VT_UI8:   return sizeof(LONGLONG);
00819   case VT_R4:    return sizeof(float);
00820   case VT_R8:    return sizeof(double);
00821   case VT_DATE:  return sizeof(DATE);
00822   case VT_BOOL:  return sizeof(VARIANT_BOOL);
00823   case VT_DISPATCH:
00824   case VT_UNKNOWN:
00825   case VT_BSTR:  return sizeof(void*);
00826   case VT_CY:    return sizeof(CY);
00827   case VT_ERROR: return sizeof(SCODE);
00828   }
00829   TRACE("Shouldn't be called for vt %s%s!\n", debugstr_VT(pv), debugstr_VF(pv));
00830   return 0;
00831 }
00832 
00833 /******************************************************************************
00834  *    VariantCopyInd  [OLEAUT32.11]
00835  *
00836  * Copy a variant, dereferencing it if it is by-reference.
00837  *
00838  * PARAMS
00839  *  pvargDest [O] Destination for copy
00840  *  pvargSrc  [I] Source variant to copy
00841  *
00842  * RETURNS
00843  *  Success: S_OK. pvargDest contains a copy of pvargSrc.
00844  *  Failure: An HRESULT error code indicating the error.
00845  *
00846  * NOTES
00847  *  Failure: DISP_E_BADVARTYPE, if either variant has an invalid by-value type.
00848  *           E_INVALIDARG, if pvargSrc  is an invalid by-reference type.
00849  *           E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an
00850  *           HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(),
00851  *           or IRecordInfo_RecordCopy(), depending on the type of pvargSrc.
00852  *
00853  * NOTES
00854  *  - If pvargSrc is by-value, this function behaves exactly as VariantCopy().
00855  *  - If pvargSrc is by-reference, the value copied to pvargDest is the pointed-to
00856  *    value.
00857  *  - if pvargSrc == pvargDest, this function dereferences in place. Otherwise,
00858  *    pvargDest is always cleared using VariantClear() before pvargSrc is copied
00859  *    to it. If clearing pvargDest fails, so does this function.
00860  */
00861 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
00862 {
00863   VARIANTARG vTmp, *pSrc = pvargSrc;
00864   VARTYPE vt;
00865   HRESULT hres = S_OK;
00866 
00867   TRACE("(%p->(%s%s),%p->(%s%s))\n", pvargDest, debugstr_VT(pvargDest),
00868         debugstr_VF(pvargDest), pvargSrc, debugstr_VT(pvargSrc),
00869         debugstr_VF(pvargSrc));
00870 
00871   if (!V_ISBYREF(pvargSrc))
00872     return VariantCopy(pvargDest, pvargSrc);
00873 
00874   /* Argument checking is more lax than VariantCopy()... */
00875   vt = V_TYPE(pvargSrc);
00876   if (V_ISARRAY(pvargSrc) ||
00877      (vt > VT_NULL && vt != (VARTYPE)15 && vt < VT_VOID &&
00878      !(V_VT(pvargSrc) & (VT_VECTOR|VT_RESERVED))))
00879   {
00880     /* OK */
00881   }
00882   else
00883     return E_INVALIDARG; /* ...And the return value for invalid types differs too */
00884 
00885   if (pvargSrc == pvargDest)
00886   {
00887     /* In place copy. Use a shallow copy of pvargSrc & init pvargDest.
00888      * This avoids an expensive VariantCopy() call - e.g. SafeArrayCopy().
00889      */
00890     vTmp = *pvargSrc;
00891     pSrc = &vTmp;
00892     V_VT(pvargDest) = VT_EMPTY;
00893   }
00894   else
00895   {
00896     /* Copy into another variant. Free the variant in pvargDest */
00897     if (FAILED(hres = VariantClear(pvargDest)))
00898     {
00899       TRACE("VariantClear() of destination failed\n");
00900       return hres;
00901     }
00902   }
00903 
00904   if (V_ISARRAY(pSrc))
00905   {
00906     /* Native doesn't check that *V_ARRAYREF(pSrc) is valid */
00907     hres = SafeArrayCopy(*V_ARRAYREF(pSrc), &V_ARRAY(pvargDest));
00908   }
00909   else if (V_VT(pSrc) == (VT_BSTR|VT_BYREF))
00910   {
00911     /* Native doesn't check that *V_BSTRREF(pSrc) is valid */
00912     V_BSTR(pvargDest) = SysAllocStringByteLen((char*)*V_BSTRREF(pSrc), SysStringByteLen(*V_BSTRREF(pSrc)));
00913   }
00914   else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF))
00915   {
00916     V_UNION(pvargDest,brecVal) = V_UNION(pvargSrc,brecVal);
00917     hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
00918   }
00919   else if (V_VT(pSrc) == (VT_DISPATCH|VT_BYREF) ||
00920            V_VT(pSrc) == (VT_UNKNOWN|VT_BYREF))
00921   {
00922     /* Native doesn't check that *V_UNKNOWNREF(pSrc) is valid */
00923     V_UNKNOWN(pvargDest) = *V_UNKNOWNREF(pSrc);
00924     if (*V_UNKNOWNREF(pSrc))
00925       IUnknown_AddRef(*V_UNKNOWNREF(pSrc));
00926   }
00927   else if (V_VT(pSrc) == (VT_VARIANT|VT_BYREF))
00928   {
00929     /* Native doesn't check that *V_VARIANTREF(pSrc) is valid */
00930     if (V_VT(V_VARIANTREF(pSrc)) == (VT_VARIANT|VT_BYREF))
00931       hres = E_INVALIDARG; /* Don't dereference more than one level */
00932     else
00933       hres = VariantCopyInd(pvargDest, V_VARIANTREF(pSrc));
00934 
00935     /* Use the dereferenced variants type value, not VT_VARIANT */
00936     goto VariantCopyInd_Return;
00937   }
00938   else if (V_VT(pSrc) == (VT_DECIMAL|VT_BYREF))
00939   {
00940     memcpy(&DEC_SCALE(&V_DECIMAL(pvargDest)), &DEC_SCALE(V_DECIMALREF(pSrc)),
00941            sizeof(DECIMAL) - sizeof(USHORT));
00942   }
00943   else
00944   {
00945     /* Copy the pointed to data into this variant */
00946     memcpy(&V_BYREF(pvargDest), V_BYREF(pSrc), VARIANT_DataSize(pSrc));
00947   }
00948 
00949   V_VT(pvargDest) = V_VT(pSrc) & ~VT_BYREF;
00950 
00951 VariantCopyInd_Return:
00952 
00953   if (pSrc != pvargSrc)
00954     VariantClear(pSrc);
00955 
00956   TRACE("returning 0x%08x, %p->(%s%s)\n", hres, pvargDest,
00957         debugstr_VT(pvargDest), debugstr_VF(pvargDest));
00958   return hres;
00959 }
00960 
00961 /******************************************************************************
00962  *    VariantChangeType  [OLEAUT32.12]
00963  *
00964  * Change the type of a variant.
00965  *
00966  * PARAMS
00967  *  pvargDest [O] Destination for the converted variant
00968  *  pvargSrc  [O] Source variant to change the type of
00969  *  wFlags    [I] VARIANT_ flags from "oleauto.h"
00970  *  vt        [I] Variant type to change pvargSrc into
00971  *
00972  * RETURNS
00973  *  Success: S_OK. pvargDest contains the converted value.
00974  *  Failure: An HRESULT error code describing the failure.
00975  *
00976  * NOTES
00977  *  The LCID used for the conversion is LOCALE_USER_DEFAULT.
00978  *  See VariantChangeTypeEx.
00979  */
00980 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
00981                                  USHORT wFlags, VARTYPE vt)
00982 {
00983   return VariantChangeTypeEx( pvargDest, pvargSrc, LOCALE_USER_DEFAULT, wFlags, vt );
00984 }
00985 
00986 /******************************************************************************
00987  *    VariantChangeTypeEx  [OLEAUT32.147]
00988  *
00989  * Change the type of a variant.
00990  *
00991  * PARAMS
00992  *  pvargDest [O] Destination for the converted variant
00993  *  pvargSrc  [O] Source variant to change the type of
00994  *  lcid      [I] LCID for the conversion
00995  *  wFlags    [I] VARIANT_ flags from "oleauto.h"
00996  *  vt        [I] Variant type to change pvargSrc into
00997  *
00998  * RETURNS
00999  *  Success: S_OK. pvargDest contains the converted value.
01000  *  Failure: An HRESULT error code describing the failure.
01001  *
01002  * NOTES
01003  *  pvargDest and pvargSrc can point to the same variant to perform an in-place
01004  *  conversion. If the conversion is successful, pvargSrc will be freed.
01005  */
01006 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
01007                                    LCID lcid, USHORT wFlags, VARTYPE vt)
01008 {
01009   HRESULT res = S_OK;
01010 
01011   TRACE("(%p->(%s%s),%p->(%s%s),0x%08x,0x%04x,%s%s)\n", pvargDest,
01012         debugstr_VT(pvargDest), debugstr_VF(pvargDest), pvargSrc,
01013         debugstr_VT(pvargSrc), debugstr_VF(pvargSrc), lcid, wFlags,
01014         debugstr_vt(vt), debugstr_vf(vt));
01015 
01016   if (vt == VT_CLSID)
01017     res = DISP_E_BADVARTYPE;
01018   else
01019   {
01020     res = VARIANT_ValidateType(V_VT(pvargSrc));
01021 
01022     if (SUCCEEDED(res))
01023     {
01024       res = VARIANT_ValidateType(vt);
01025 
01026       if (SUCCEEDED(res))
01027       {
01028         VARIANTARG vTmp, vSrcDeref;
01029 
01030         if(V_ISBYREF(pvargSrc) && !V_BYREF(pvargSrc))
01031           res = DISP_E_TYPEMISMATCH;
01032         else
01033         {
01034           V_VT(&vTmp) = VT_EMPTY;
01035           V_VT(&vSrcDeref) = VT_EMPTY;
01036           VariantClear(&vTmp);
01037           VariantClear(&vSrcDeref);
01038         }
01039 
01040         if (SUCCEEDED(res))
01041         {
01042           res = VariantCopyInd(&vSrcDeref, pvargSrc);
01043           if (SUCCEEDED(res))
01044           {
01045             if (V_ISARRAY(&vSrcDeref) || (vt & VT_ARRAY))
01046               res = VARIANT_CoerceArray(&vTmp, &vSrcDeref, vt);
01047             else
01048               res = VARIANT_Coerce(&vTmp, lcid, wFlags, &vSrcDeref, vt);
01049 
01050             if (SUCCEEDED(res)) {
01051                 V_VT(&vTmp) = vt;
01052                 VariantCopy(pvargDest, &vTmp);
01053             }
01054             VariantClear(&vTmp);
01055             VariantClear(&vSrcDeref);
01056           }
01057         }
01058       }
01059     }
01060   }
01061 
01062   TRACE("returning 0x%08x, %p->(%s%s)\n", res, pvargDest,
01063         debugstr_VT(pvargDest), debugstr_VF(pvargDest));
01064   return res;
01065 }
01066 
01067 /* Date Conversions */
01068 
01069 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
01070 
01071 /* Convert a VT_DATE value to a Julian Date */
01072 static inline int VARIANT_JulianFromDate(int dateIn)
01073 {
01074   int julianDays = dateIn;
01075 
01076   julianDays -= DATE_MIN; /* Convert to + days from 1 Jan 100 AD */
01077   julianDays += 1757585;  /* Convert to + days from 23 Nov 4713 BC (Julian) */
01078   return julianDays;
01079 }
01080 
01081 /* Convert a Julian Date to a VT_DATE value */
01082 static inline int VARIANT_DateFromJulian(int dateIn)
01083 {
01084   int julianDays = dateIn;
01085 
01086   julianDays -= 1757585;  /* Convert to + days from 1 Jan 100 AD */
01087   julianDays += DATE_MIN; /* Convert to +/- days from 1 Jan 1899 AD */
01088   return julianDays;
01089 }
01090 
01091 /* Convert a Julian date to Day/Month/Year - from PostgreSQL */
01092 static inline void VARIANT_DMYFromJulian(int jd, USHORT *year, USHORT *month, USHORT *day)
01093 {
01094   int j, i, l, n;
01095 
01096   l = jd + 68569;
01097   n = l * 4 / 146097;
01098   l -= (n * 146097 + 3) / 4;
01099   i = (4000 * (l + 1)) / 1461001;
01100   l += 31 - (i * 1461) / 4;
01101   j = (l * 80) / 2447;
01102   *day = l - (j * 2447) / 80;
01103   l = j / 11;
01104   *month = (j + 2) - (12 * l);
01105   *year = 100 * (n - 49) + i + l;
01106 }
01107 
01108 /* Convert Day/Month/Year to a Julian date - from PostgreSQL */
01109 static inline double VARIANT_JulianFromDMY(USHORT year, USHORT month, USHORT day)
01110 {
01111   int m12 = (month - 14) / 12;
01112 
01113   return ((1461 * (year + 4800 + m12)) / 4 + (367 * (month - 2 - 12 * m12)) / 12 -
01114            (3 * ((year + 4900 + m12) / 100)) / 4 + day - 32075);
01115 }
01116 
01117 /* Macros for accessing DOS format date/time fields */
01118 #define DOS_YEAR(x)   (1980 + (x >> 9))
01119 #define DOS_MONTH(x)  ((x >> 5) & 0xf)
01120 #define DOS_DAY(x)    (x & 0x1f)
01121 #define DOS_HOUR(x)   (x >> 11)
01122 #define DOS_MINUTE(x) ((x >> 5) & 0x3f)
01123 #define DOS_SECOND(x) ((x & 0x1f) << 1)
01124 /* Create a DOS format date/time */
01125 #define DOS_DATE(d,m,y) (d | (m << 5) | ((y-1980) << 9))
01126 #define DOS_TIME(h,m,s) ((s >> 1) | (m << 5) | (h << 11))
01127 
01128 /* Roll a date forwards or backwards to correct it */
01129 static HRESULT VARIANT_RollUdate(UDATE *lpUd)
01130 {
01131   static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
01132   short iYear, iMonth, iDay, iHour, iMinute, iSecond;
01133 
01134   /* interpret values signed */
01135   iYear   = lpUd->st.wYear;
01136   iMonth  = lpUd->st.wMonth;
01137   iDay    = lpUd->st.wDay;
01138   iHour   = lpUd->st.wHour;
01139   iMinute = lpUd->st.wMinute;
01140   iSecond = lpUd->st.wSecond;
01141 
01142   TRACE("Raw date: %d/%d/%d %d:%d:%d\n", iDay, iMonth,
01143         iYear, iHour, iMinute, iSecond);
01144 
01145   if (iYear > 9999 || iYear < -9999)
01146     return E_INVALIDARG; /* Invalid value */
01147   /* Years < 100 are treated as 1900 + year */
01148   if (iYear > 0 && iYear < 100)
01149     iYear += 1900;
01150 
01151   iMinute += iSecond / 60;
01152   iSecond  = iSecond % 60;
01153   iHour   += iMinute / 60;
01154   iMinute  = iMinute % 60;
01155   iDay    += iHour / 24;
01156   iHour    = iHour % 24;
01157   iYear   += iMonth / 12;
01158   iMonth   = iMonth % 12;
01159   if (iMonth<=0) {iMonth+=12; iYear--;}
01160   while (iDay > days[iMonth])
01161   {
01162     if (iMonth == 2 && IsLeapYear(iYear))
01163       iDay -= 29;
01164     else
01165       iDay -= days[iMonth];
01166     iMonth++;
01167     iYear += iMonth / 12;
01168     iMonth = iMonth % 12;
01169   }
01170   while (iDay <= 0)
01171   {
01172     iMonth--;
01173     if (iMonth<=0) {iMonth+=12; iYear--;}
01174     if (iMonth == 2 && IsLeapYear(iYear))
01175       iDay += 29;
01176     else
01177       iDay += days[iMonth];
01178   }
01179 
01180   if (iSecond<0){iSecond+=60; iMinute--;}
01181   if (iMinute<0){iMinute+=60; iHour--;}
01182   if (iHour<0)  {iHour+=24; iDay--;}
01183   if (iYear<=0)  iYear+=2000;
01184 
01185   lpUd->st.wYear   = iYear;
01186   lpUd->st.wMonth  = iMonth;
01187   lpUd->st.wDay    = iDay;
01188   lpUd->st.wHour   = iHour;
01189   lpUd->st.wMinute = iMinute;
01190   lpUd->st.wSecond = iSecond;
01191 
01192   TRACE("Rolled date: %d/%d/%d %d:%d:%d\n", lpUd->st.wDay, lpUd->st.wMonth,
01193         lpUd->st.wYear, lpUd->st.wHour, lpUd->st.wMinute, lpUd->st.wSecond);
01194   return S_OK;
01195 }
01196 
01197 /**********************************************************************
01198  *              DosDateTimeToVariantTime [OLEAUT32.14]
01199  *
01200  * Convert a Dos format date and time into variant VT_DATE format.
01201  *
01202  * PARAMS
01203  *  wDosDate [I] Dos format date
01204  *  wDosTime [I] Dos format time
01205  *  pDateOut [O] Destination for VT_DATE format
01206  *
01207  * RETURNS
01208  *  Success: TRUE. pDateOut contains the converted time.
01209  *  Failure: FALSE, if wDosDate or wDosTime are invalid (see notes).
01210  *
01211  * NOTES
01212  * - Dos format dates can only hold dates from 1-Jan-1980 to 31-Dec-2099.
01213  * - Dos format times are accurate to only 2 second precision.
01214  * - The format of a Dos Date is:
01215  *| Bits   Values  Meaning
01216  *| ----   ------  -------
01217  *| 0-4    1-31    Day of the week. 0 rolls back one day. A value greater than
01218  *|                the days in the month rolls forward the extra days.
01219  *| 5-8    1-12    Month of the year. 0 rolls back to December of the previous
01220  *|                year. 13-15 are invalid.
01221  *| 9-15   0-119   Year based from 1980 (Max 2099). 120-127 are invalid.
01222  * - The format of a Dos Time is:
01223  *| Bits   Values  Meaning
01224  *| ----   ------  -------
01225  *| 0-4    0-29    Seconds/2. 30 and 31 are invalid.
01226  *| 5-10   0-59    Minutes. 60-63 are invalid.
01227  *| 11-15  0-23    Hours (24 hour clock). 24-32 are invalid.
01228  */
01229 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
01230                                     double *pDateOut)
01231 {
01232   UDATE ud;
01233 
01234   TRACE("(0x%x(%d/%d/%d),0x%x(%d:%d:%d),%p)\n",
01235         wDosDate, DOS_YEAR(wDosDate), DOS_MONTH(wDosDate), DOS_DAY(wDosDate),
01236         wDosTime, DOS_HOUR(wDosTime), DOS_MINUTE(wDosTime), DOS_SECOND(wDosTime),
01237         pDateOut);
01238 
01239   ud.st.wYear = DOS_YEAR(wDosDate);
01240   ud.st.wMonth = DOS_MONTH(wDosDate);
01241   if (ud.st.wYear > 2099 || ud.st.wMonth > 12)
01242     return FALSE;
01243   ud.st.wDay = DOS_DAY(wDosDate);
01244   ud.st.wHour = DOS_HOUR(wDosTime);
01245   ud.st.wMinute = DOS_MINUTE(wDosTime);
01246   ud.st.wSecond = DOS_SECOND(wDosTime);
01247   ud.st.wDayOfWeek = ud.st.wMilliseconds = 0;
01248   if (ud.st.wHour > 23 || ud.st.wMinute > 59 || ud.st.wSecond > 59)
01249     return FALSE; /* Invalid values in Dos*/
01250 
01251   return VarDateFromUdate(&ud, 0, pDateOut) == S_OK;
01252 }
01253 
01254 /**********************************************************************
01255  *              VariantTimeToDosDateTime [OLEAUT32.13]
01256  *
01257  * Convert a variant format date into a Dos format date and time.
01258  *
01259  *  dateIn    [I] VT_DATE time format
01260  *  pwDosDate [O] Destination for Dos format date
01261  *  pwDosTime [O] Destination for Dos format time
01262  *
01263  * RETURNS
01264  *  Success: TRUE. pwDosDate and pwDosTime contains the converted values.
01265  *  Failure: FALSE, if dateIn cannot be represented in Dos format.
01266  *
01267  * NOTES
01268  *   See DosDateTimeToVariantTime() for Dos format details and bugs.
01269  */
01270 INT WINAPI VariantTimeToDosDateTime(double dateIn, USHORT *pwDosDate, USHORT *pwDosTime)
01271 {
01272   UDATE ud;
01273 
01274   TRACE("(%g,%p,%p)\n", dateIn, pwDosDate, pwDosTime);
01275 
01276   if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
01277     return FALSE;
01278 
01279   if (ud.st.wYear < 1980 || ud.st.wYear > 2099)
01280     return FALSE;
01281 
01282   *pwDosDate = DOS_DATE(ud.st.wDay, ud.st.wMonth, ud.st.wYear);
01283   *pwDosTime = DOS_TIME(ud.st.wHour, ud.st.wMinute, ud.st.wSecond);
01284 
01285   TRACE("Returning 0x%x(%d/%d/%d), 0x%x(%d:%d:%d)\n",
01286         *pwDosDate, DOS_YEAR(*pwDosDate), DOS_MONTH(*pwDosDate), DOS_DAY(*pwDosDate),
01287         *pwDosTime, DOS_HOUR(*pwDosTime), DOS_MINUTE(*pwDosTime), DOS_SECOND(*pwDosTime));
01288   return TRUE;
01289 }
01290 
01291 /***********************************************************************
01292  *              SystemTimeToVariantTime [OLEAUT32.184]
01293  *
01294  * Convert a System format date and time into variant VT_DATE format.
01295  *
01296  * PARAMS
01297  *  lpSt     [I] System format date and time
01298  *  pDateOut [O] Destination for VT_DATE format date
01299  *
01300  * RETURNS
01301  *  Success: TRUE. *pDateOut contains the converted value.
01302  *  Failure: FALSE, if lpSt cannot be represented in VT_DATE format.
01303  */
01304 INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut)
01305 {
01306   UDATE ud;
01307 
01308   TRACE("(%p->%d/%d/%d %d:%d:%d,%p)\n", lpSt, lpSt->wDay, lpSt->wMonth,
01309         lpSt->wYear, lpSt->wHour, lpSt->wMinute, lpSt->wSecond, pDateOut);
01310 
01311   if (lpSt->wMonth > 12)
01312     return FALSE;
01313 
01314   ud.st = *lpSt;
01315   return VarDateFromUdate(&ud, 0, pDateOut) == S_OK;
01316 }
01317 
01318 /***********************************************************************
01319  *              VariantTimeToSystemTime [OLEAUT32.185]
01320  *
01321  * Convert a variant VT_DATE into a System format date and time.
01322  *
01323  * PARAMS
01324  *  datein [I] Variant VT_DATE format date
01325  *  lpSt   [O] Destination for System format date and time
01326  *
01327  * RETURNS
01328  *  Success: TRUE. *lpSt contains the converted value.
01329  *  Failure: FALSE, if dateIn is too large or small.
01330  */
01331 INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt)
01332 {
01333   UDATE ud;
01334 
01335   TRACE("(%g,%p)\n", dateIn, lpSt);
01336 
01337   if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
01338     return FALSE;
01339 
01340   *lpSt = ud.st;
01341   return TRUE;
01342 }
01343 
01344 /***********************************************************************
01345  *              VarDateFromUdateEx [OLEAUT32.319]
01346  *
01347  * Convert an unpacked format date and time to a variant VT_DATE.
01348  *
01349  * PARAMS
01350  *  pUdateIn [I] Unpacked format date and time to convert
01351  *  lcid     [I] Locale identifier for the conversion
01352  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
01353  *  pDateOut [O] Destination for variant VT_DATE.
01354  *
01355  * RETURNS
01356  *  Success: S_OK. *pDateOut contains the converted value.
01357  *  Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
01358  */
01359 HRESULT WINAPI VarDateFromUdateEx(UDATE *pUdateIn, LCID lcid, ULONG dwFlags, DATE *pDateOut)
01360 {
01361   UDATE ud;
01362   double dateVal;
01363 
01364   TRACE("(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08x,0x%08x,%p)\n", pUdateIn,
01365         pUdateIn->st.wMonth, pUdateIn->st.wDay, pUdateIn->st.wYear,
01366         pUdateIn->st.wHour, pUdateIn->st.wMinute, pUdateIn->st.wSecond,
01367         pUdateIn->st.wMilliseconds, pUdateIn->st.wDayOfWeek,
01368         pUdateIn->wDayOfYear, lcid, dwFlags, pDateOut);
01369 
01370   if (lcid != MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT))
01371     FIXME("lcid possibly not handled, treating as en-us\n");
01372 
01373   ud = *pUdateIn;
01374 
01375   if (dwFlags & VAR_VALIDDATE)
01376     WARN("Ignoring VAR_VALIDDATE\n");
01377 
01378   if (FAILED(VARIANT_RollUdate(&ud)))
01379     return E_INVALIDARG;
01380 
01381   /* Date */
01382   dateVal = VARIANT_DateFromJulian(VARIANT_JulianFromDMY(ud.st.wYear, ud.st.wMonth, ud.st.wDay));
01383 
01384   /* Time */
01385   dateVal += ud.st.wHour / 24.0;
01386   dateVal += ud.st.wMinute / 1440.0;
01387   dateVal += ud.st.wSecond / 86400.0;
01388 
01389   TRACE("Returning %g\n", dateVal);
01390   *pDateOut = dateVal;
01391   return S_OK;
01392 }
01393 
01394 /***********************************************************************
01395  *              VarDateFromUdate [OLEAUT32.330]
01396  *
01397  * Convert an unpacked format date and time to a variant VT_DATE.
01398  *
01399  * PARAMS
01400  *  pUdateIn [I] Unpacked format date and time to convert
01401  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
01402  *  pDateOut [O] Destination for variant VT_DATE.
01403  *
01404  * RETURNS
01405  *  Success: S_OK. *pDateOut contains the converted value.
01406  *  Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
01407  *
01408  * NOTES
01409  *  This function uses the United States English locale for the conversion. Use
01410  *  VarDateFromUdateEx() for alternate locales.
01411  */
01412 HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut)
01413 {
01414   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
01415   
01416   return VarDateFromUdateEx(pUdateIn, lcid, dwFlags, pDateOut);
01417 }
01418 
01419 /***********************************************************************
01420  *              VarUdateFromDate [OLEAUT32.331]
01421  *
01422  * Convert a variant VT_DATE into an unpacked format date and time.
01423  *
01424  * PARAMS
01425  *  datein    [I] Variant VT_DATE format date
01426  *  dwFlags   [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
01427  *  lpUdate   [O] Destination for unpacked format date and time
01428  *
01429  * RETURNS
01430  *  Success: S_OK. *lpUdate contains the converted value.
01431  *  Failure: E_INVALIDARG, if dateIn is too large or small.
01432  */
01433 HRESULT WINAPI VarUdateFromDate(DATE dateIn, ULONG dwFlags, UDATE *lpUdate)
01434 {
01435   /* Cumulative totals of days per month */
01436   static const USHORT cumulativeDays[] =
01437   {
01438     0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
01439   };
01440   double datePart, timePart;
01441   int julianDays;
01442 
01443   TRACE("(%g,0x%08x,%p)\n", dateIn, dwFlags, lpUdate);
01444 
01445   if (dateIn <= (DATE_MIN - 1.0) || dateIn >= (DATE_MAX + 1.0))
01446     return E_INVALIDARG;
01447 
01448   datePart = dateIn < 0.0 ? ceil(dateIn) : floor(dateIn);
01449   /* Compensate for int truncation (always downwards) */
01450   timePart = dateIn - datePart + 0.00000000001;
01451   if (timePart >= 1.0)
01452     timePart -= 0.00000000001;
01453 
01454   /* Date */
01455   julianDays = VARIANT_JulianFromDate(dateIn);
01456   VARIANT_DMYFromJulian(julianDays, &lpUdate->st.wYear, &lpUdate->st.wMonth,
01457                         &lpUdate->st.wDay);
01458 
01459   datePart = (datePart + 1.5) / 7.0;
01460   lpUdate->st.wDayOfWeek = (datePart - floor(datePart)) * 7;
01461   if (lpUdate->st.wDayOfWeek == 0)
01462     lpUdate->st.wDayOfWeek = 5;
01463   else if (lpUdate->st.wDayOfWeek == 1)
01464     lpUdate->st.wDayOfWeek = 6;
01465   else
01466     lpUdate->st.wDayOfWeek -= 2;
01467 
01468   if (lpUdate->st.wMonth > 2 && IsLeapYear(lpUdate->st.wYear))
01469     lpUdate->wDayOfYear = 1; /* After February, in a leap year */
01470   else
01471     lpUdate->wDayOfYear = 0;
01472 
01473   lpUdate->wDayOfYear += cumulativeDays[lpUdate->st.wMonth];
01474   lpUdate->wDayOfYear += lpUdate->st.wDay;
01475 
01476   /* Time */
01477   timePart *= 24.0;
01478   lpUdate->st.wHour = timePart;
01479   timePart -= lpUdate->st.wHour;
01480   timePart *= 60.0;
01481   lpUdate->st.wMinute = timePart;
01482   timePart -= lpUdate->st.wMinute;
01483   timePart *= 60.0;
01484   lpUdate->st.wSecond = timePart;
01485   timePart -= lpUdate->st.wSecond;
01486   lpUdate->st.wMilliseconds = 0;
01487   if (timePart > 0.5)
01488   {
01489     /* Round the milliseconds, adjusting the time/date forward if needed */
01490     if (lpUdate->st.wSecond < 59)
01491       lpUdate->st.wSecond++;
01492     else
01493     {
01494       lpUdate->st.wSecond = 0;
01495       if (lpUdate->st.wMinute < 59)
01496         lpUdate->st.wMinute++;
01497       else
01498       {
01499         lpUdate->st.wMinute = 0;
01500         if (lpUdate->st.wHour < 23)
01501           lpUdate->st.wHour++;
01502         else
01503         {
01504           lpUdate->st.wHour = 0;
01505           /* Roll over a whole day */
01506           if (++lpUdate->st.wDay > 28)
01507             VARIANT_RollUdate(lpUdate);
01508         }
01509       }
01510     }
01511   }
01512   return S_OK;
01513 }
01514 
01515 #define GET_NUMBER_TEXT(fld,name) \
01516   buff[0] = 0; \
01517   if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \
01518     WARN("buffer too small for " #fld "\n"); \
01519   else \
01520     if (buff[0]) lpChars->name = buff[0]; \
01521   TRACE("lcid 0x%x, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name)
01522 
01523 /* Get the valid number characters for an lcid */
01524 static void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
01525 {
01526   static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',',','$',0,'.',',' };
01527   static CRITICAL_SECTION csLastChars = { NULL, -1, 0, 0, 0, 0 };
01528   static VARIANT_NUMBER_CHARS lastChars;
01529   static LCID lastLcid = -1;
01530   static DWORD lastFlags = 0;
01531   LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
01532   WCHAR buff[4];
01533 
01534   /* To make caching thread-safe, a critical section is needed */
01535   EnterCriticalSection(&csLastChars);
01536 
01537   /* Asking for default locale entries is very expensive: It is a registry
01538      server call. So cache one locally, as Microsoft does it too */
01539   if(lcid == lastLcid && dwFlags == lastFlags)
01540   {
01541     memcpy(lpChars, &lastChars, sizeof(defaultChars));
01542     LeaveCriticalSection(&csLastChars);
01543     return;
01544   }
01545 
01546   memcpy(lpChars, &defaultChars, sizeof(defaultChars));
01547   GET_NUMBER_TEXT(LOCALE_SNEGATIVESIGN, cNegativeSymbol);
01548   GET_NUMBER_TEXT(LOCALE_SPOSITIVESIGN, cPositiveSymbol);
01549   GET_NUMBER_TEXT(LOCALE_SDECIMAL, cDecimalPoint);
01550   GET_NUMBER_TEXT(LOCALE_STHOUSAND, cDigitSeparator);
01551   GET_NUMBER_TEXT(LOCALE_SMONDECIMALSEP, cCurrencyDecimalPoint);
01552   GET_NUMBER_TEXT(LOCALE_SMONTHOUSANDSEP, cCurrencyDigitSeparator);
01553 
01554   /* Local currency symbols are often 2 characters */
01555   lpChars->cCurrencyLocal2 = '\0';
01556   switch(GetLocaleInfoW(lcid, lctype|LOCALE_SCURRENCY, buff, sizeof(buff)/sizeof(WCHAR)))
01557   {
01558     case 3: lpChars->cCurrencyLocal2 = buff[1]; /* Fall through */
01559     case 2: lpChars->cCurrencyLocal  = buff[0];
01560             break;
01561     default: WARN("buffer too small for LOCALE_SCURRENCY\n");
01562   }
01563   TRACE("lcid 0x%x, cCurrencyLocal =%d,%d '%c','%c'\n", lcid, lpChars->cCurrencyLocal,
01564         lpChars->cCurrencyLocal2, lpChars->cCurrencyLocal, lpChars->cCurrencyLocal2);
01565 
01566   memcpy(&lastChars, lpChars, sizeof(defaultChars));
01567   lastLcid = lcid;
01568   lastFlags = dwFlags;
01569   LeaveCriticalSection(&csLastChars);
01570 }
01571 
01572 /* Number Parsing States */
01573 #define B_PROCESSING_EXPONENT 0x1
01574 #define B_NEGATIVE_EXPONENT   0x2
01575 #define B_EXPONENT_START      0x4
01576 #define B_INEXACT_ZEROS       0x8
01577 #define B_LEADING_ZERO        0x10
01578 #define B_PROCESSING_HEX      0x20
01579 #define B_PROCESSING_OCT      0x40
01580 
01581 /**********************************************************************
01582  *              VarParseNumFromStr [OLEAUT32.46]
01583  *
01584  * Parse a string containing a number into a NUMPARSE structure.
01585  *
01586  * PARAMS
01587  *  lpszStr [I]   String to parse number from
01588  *  lcid    [I]   Locale Id for the conversion
01589  *  dwFlags [I]   0, or LOCALE_NOUSEROVERRIDE to use system default number chars
01590  *  pNumprs [I/O] Destination for parsed number
01591  *  rgbDig  [O]   Destination for digits read in
01592  *
01593  * RETURNS
01594  *  Success: S_OK. pNumprs and rgbDig contain the parsed representation of
01595  *           the number.
01596  *  Failure: E_INVALIDARG, if any parameter is invalid.
01597  *           DISP_E_TYPEMISMATCH, if the string is not a number or is formatted
01598  *           incorrectly.
01599  *           DISP_E_OVERFLOW, if rgbDig is too small to hold the number.
01600  *
01601  * NOTES
01602  *  pNumprs must have the following fields set:
01603  *   cDig: Set to the size of rgbDig.
01604  *   dwInFlags: Set to the allowable syntax of the number using NUMPRS_ flags
01605  *            from "oleauto.h".
01606  *
01607  * FIXME
01608  *  - I am unsure if this function should parse non-arabic (e.g. Thai)
01609  *   numerals, so this has not been implemented.
01610  */
01611 HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
01612                                   NUMPARSE *pNumprs, BYTE *rgbDig)
01613 {
01614   VARIANT_NUMBER_CHARS chars;
01615   BYTE rgbTmp[1024];
01616   DWORD dwState = B_EXPONENT_START|B_INEXACT_ZEROS;
01617   int iMaxDigits = sizeof(rgbTmp) / sizeof(BYTE);
01618   int cchUsed = 0;
01619 
01620   TRACE("(%s,%d,0x%08x,%p,%p)\n", debugstr_w(lpszStr), lcid, dwFlags, pNumprs, rgbDig);
01621 
01622   if (!pNumprs || !rgbDig)
01623     return E_INVALIDARG;
01624 
01625   if (pNumprs->cDig < iMaxDigits)
01626     iMaxDigits = pNumprs->cDig;
01627 
01628   pNumprs->cDig = 0;
01629   pNumprs->dwOutFlags = 0;
01630   pNumprs->cchUsed = 0;
01631   pNumprs->nBaseShift = 0;
01632   pNumprs->nPwr10 = 0;
01633 
01634   if (!lpszStr)
01635     return DISP_E_TYPEMISMATCH;
01636 
01637   VARIANT_GetLocalisedNumberChars(&chars, lcid, dwFlags);
01638 
01639   /* First consume all the leading symbols and space from the string */
01640   while (1)
01641   {
01642     if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && isspaceW(*lpszStr))
01643     {
01644       pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE;
01645       do
01646       {
01647         cchUsed++;
01648         lpszStr++;
01649       } while (isspaceW(*lpszStr));
01650     }
01651     else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS &&
01652              *lpszStr == chars.cPositiveSymbol &&
01653              !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS))
01654     {
01655       pNumprs->dwOutFlags |= NUMPRS_LEADING_PLUS;
01656       cchUsed++;
01657       lpszStr++;
01658     }
01659     else if (pNumprs->dwInFlags & NUMPRS_LEADING_MINUS &&
01660              *lpszStr == chars.cNegativeSymbol &&
01661              !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS))
01662     {
01663       pNumprs->dwOutFlags |= (NUMPRS_LEADING_MINUS|NUMPRS_NEG);
01664       cchUsed++;
01665       lpszStr++;
01666     }
01667     else if (pNumprs->dwInFlags & NUMPRS_CURRENCY &&
01668              !(pNumprs->dwOutFlags & NUMPRS_CURRENCY) &&
01669              *lpszStr == chars.cCurrencyLocal &&
01670              (!chars.cCurrencyLocal2 || lpszStr[1] == chars.cCurrencyLocal2))
01671     {
01672       pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
01673       cchUsed++;
01674       lpszStr++;
01675       /* Only accept currency characters */
01676       chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
01677       chars.cDigitSeparator = chars.cCurrencyDigitSeparator;
01678     }
01679     else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
01680              !(pNumprs->dwOutFlags & NUMPRS_PARENS))
01681     {
01682       pNumprs->dwOutFlags |= NUMPRS_PARENS;
01683       cchUsed++;
01684       lpszStr++;
01685     }
01686     else
01687       break;
01688   }
01689 
01690   if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY))
01691   {
01692     /* Only accept non-currency characters */
01693     chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
01694     chars.cCurrencyDigitSeparator = chars.cDigitSeparator;
01695   }
01696 
01697   if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
01698     pNumprs->dwInFlags & NUMPRS_HEX_OCT)
01699   {
01700       dwState |= B_PROCESSING_HEX;
01701       pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
01702       cchUsed=cchUsed+2;
01703       lpszStr=lpszStr+2;
01704   }
01705   else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
01706     pNumprs->dwInFlags & NUMPRS_HEX_OCT)
01707   {
01708       dwState |= B_PROCESSING_OCT;
01709       pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
01710       cchUsed=cchUsed+2;
01711       lpszStr=lpszStr+2;
01712   }
01713 
01714   /* Strip Leading zeros */
01715   while (*lpszStr == '0')
01716   {
01717     dwState |= B_LEADING_ZERO;
01718     cchUsed++;
01719     lpszStr++;
01720   }
01721 
01722   while (*lpszStr)
01723   {
01724     if (isdigitW(*lpszStr))
01725     {
01726       if (dwState & B_PROCESSING_EXPONENT)
01727       {
01728         int exponentSize = 0;
01729         if (dwState & B_EXPONENT_START)
01730         {
01731           if (!isdigitW(*lpszStr))
01732             break; /* No exponent digits - invalid */
01733           while (*lpszStr == '0')
01734           {
01735             /* Skip leading zero's in the exponent */
01736             cchUsed++;
01737             lpszStr++;
01738           }
01739         }
01740 
01741         while (isdigitW(*lpszStr))
01742         {
01743           exponentSize *= 10;
01744           exponentSize += *lpszStr - '0';
01745           cchUsed++;
01746           lpszStr++;
01747         }
01748         if (dwState & B_NEGATIVE_EXPONENT)
01749           exponentSize = -exponentSize;
01750         /* Add the exponent into the powers of 10 */
01751         pNumprs->nPwr10 += exponentSize;
01752         dwState &= ~(B_PROCESSING_EXPONENT|B_EXPONENT_START);
01753         lpszStr--; /* back up to allow processing of next char */
01754       }
01755       else
01756       {
01757         if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
01758           && !(dwState & B_PROCESSING_OCT))
01759         {
01760           pNumprs->dwOutFlags |= NUMPRS_INEXACT;
01761 
01762           if (*lpszStr != '0')
01763             dwState &= ~B_INEXACT_ZEROS; /* Inexact number with non-trailing zeros */
01764 
01765           /* This digit can't be represented, but count it in nPwr10 */
01766           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
01767             pNumprs->nPwr10--;
01768           else
01769             pNumprs->nPwr10++;
01770         }
01771         else
01772         {
01773           if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
01774             return DISP_E_TYPEMISMATCH;
01775           }
01776 
01777           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
01778             pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
01779 
01780           rgbTmp[pNumprs->cDig] = *lpszStr - '0';
01781         }
01782         pNumprs->cDig++;
01783         cchUsed++;
01784       }
01785     }
01786     else if (*lpszStr == chars.cDigitSeparator && pNumprs->dwInFlags & NUMPRS_THOUSANDS)
01787     {
01788       pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
01789       cchUsed++;
01790     }
01791     else if (*lpszStr == chars.cDecimalPoint &&
01792              pNumprs->dwInFlags & NUMPRS_DECIMAL &&
01793              !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
01794     {
01795       pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
01796       cchUsed++;
01797 
01798       /* If we have no digits so far, skip leading zeros */
01799       if (!pNumprs->cDig)
01800       {
01801         while (lpszStr[1] == '0')
01802         {
01803           dwState |= B_LEADING_ZERO;
01804           cchUsed++;
01805           lpszStr++;
01806           pNumprs->nPwr10--;
01807         }
01808       }
01809     }
01810     else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
01811              (*lpszStr >= 'A' && *lpszStr <= 'F')) &&
01812              dwState & B_PROCESSING_HEX)
01813     {
01814       if (pNumprs->cDig >= iMaxDigits)
01815       {
01816         return DISP_E_OVERFLOW;
01817       }
01818       else
01819       {
01820         if (*lpszStr >= 'a')
01821           rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
01822         else
01823           rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
01824       }
01825       pNumprs->cDig++;
01826       cchUsed++;
01827     }
01828     else if ((*lpszStr == 'e' || *lpszStr == 'E') &&
01829              pNumprs->dwInFlags & NUMPRS_EXPONENT &&
01830              !(pNumprs->dwOutFlags & NUMPRS_EXPONENT))
01831     {
01832       dwState |= B_PROCESSING_EXPONENT;
01833       pNumprs->dwOutFlags |= NUMPRS_EXPONENT;
01834       cchUsed++;
01835     }
01836     else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cPositiveSymbol)
01837     {
01838       cchUsed++; /* Ignore positive exponent */
01839     }
01840     else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cNegativeSymbol)
01841     {
01842       dwState |= B_NEGATIVE_EXPONENT;
01843       cchUsed++;
01844     }
01845     else
01846       break; /* Stop at an unrecognised character */
01847 
01848     lpszStr++;
01849   }
01850 
01851   if (!pNumprs->cDig && dwState & B_LEADING_ZERO)
01852   {
01853     /* Ensure a 0 on its own gets stored */
01854     pNumprs->cDig = 1;
01855     rgbTmp[0] = 0;
01856   }
01857 
01858   if (pNumprs->dwOutFlags & NUMPRS_EXPONENT && dwState & B_PROCESSING_EXPONENT)
01859   {
01860     pNumprs->cchUsed = cchUsed;
01861     WARN("didn't completely parse exponent\n");
01862     return DISP_E_TYPEMISMATCH; /* Failed to completely parse the exponent */
01863   }
01864 
01865   if (pNumprs->dwOutFlags & NUMPRS_INEXACT)
01866   {
01867     if (dwState & B_INEXACT_ZEROS)
01868       pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* All zeros doesn't set NUMPRS_INEXACT */
01869   } else if(pNumprs->dwInFlags & NUMPRS_HEX_OCT)
01870   {
01871     /* copy all of the digits into the output digit buffer */
01872     /* this is exactly what windows does although it also returns */
01873     /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
01874     memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
01875 
01876     if (dwState & B_PROCESSING_HEX) {
01877       /* hex numbers have always the same format */
01878       pNumprs->nPwr10=0;
01879       pNumprs->nBaseShift=4;
01880     } else {
01881       if (dwState & B_PROCESSING_OCT) {
01882         /* oct numbers have always the same format */
01883         pNumprs->nPwr10=0;
01884         pNumprs->nBaseShift=3;
01885       } else {
01886         while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
01887         {
01888           pNumprs->nPwr10++;
01889           pNumprs->cDig--;
01890         }
01891       }
01892     }
01893   } else
01894   {
01895     /* Remove trailing zeros from the last (whole number or decimal) part */
01896     while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
01897     {
01898       pNumprs->nPwr10++;
01899       pNumprs->cDig--;
01900     }
01901   }
01902 
01903   if (pNumprs->cDig <= iMaxDigits)
01904     pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* Ignore stripped zeros for NUMPRS_INEXACT */
01905   else
01906     pNumprs->cDig = iMaxDigits; /* Only return iMaxDigits worth of digits */
01907 
01908   /* Copy the digits we processed into rgbDig */
01909   memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
01910 
01911   /* Consume any trailing symbols and space */
01912   while (1)
01913   {
01914     if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && isspaceW(*lpszStr))
01915     {
01916       pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE;
01917       do
01918       {
01919         cchUsed++;
01920         lpszStr++;
01921       } while (isspaceW(*lpszStr));
01922     }
01923     else if (pNumprs->dwInFlags & NUMPRS_TRAILING_PLUS &&
01924              !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS) &&
01925              *lpszStr == chars.cPositiveSymbol)
01926     {
01927       pNumprs->dwOutFlags |= NUMPRS_TRAILING_PLUS;
01928       cchUsed++;
01929       lpszStr++;
01930     }
01931     else if (pNumprs->dwInFlags & NUMPRS_TRAILING_MINUS &&
01932              !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS) &&
01933              *lpszStr == chars.cNegativeSymbol)
01934     {
01935       pNumprs->dwOutFlags |= (NUMPRS_TRAILING_MINUS|NUMPRS_NEG);
01936       cchUsed++;
01937       lpszStr++;
01938     }
01939     else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == ')' &&
01940              pNumprs->dwOutFlags & NUMPRS_PARENS)
01941     {
01942       cchUsed++;
01943       lpszStr++;
01944       pNumprs->dwOutFlags |= NUMPRS_NEG;
01945     }
01946     else
01947       break;
01948   }
01949 
01950   if (pNumprs->dwOutFlags & NUMPRS_PARENS && !(pNumprs->dwOutFlags & NUMPRS_NEG))
01951   {
01952     pNumprs->cchUsed = cchUsed;
01953     return DISP_E_TYPEMISMATCH; /* Opening parenthesis not matched */
01954   }
01955 
01956   if (pNumprs->dwInFlags & NUMPRS_USE_ALL && *lpszStr != '\0')
01957     return DISP_E_TYPEMISMATCH; /* Not all chars were consumed */
01958 
01959   if (!pNumprs->cDig)
01960     return DISP_E_TYPEMISMATCH; /* No Number found */
01961 
01962   pNumprs->cchUsed = cchUsed;
01963   return S_OK;
01964 }
01965 
01966 /* VTBIT flags indicating an integer value */
01967 #define INTEGER_VTBITS (VTBIT_I1|VTBIT_UI1|VTBIT_I2|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_I8|VTBIT_UI8)
01968 /* VTBIT flags indicating a real number value */
01969 #define REAL_VTBITS (VTBIT_R4|VTBIT_R8|VTBIT_CY)
01970 
01971 /* Helper macros to check whether bit pattern fits in VARIANT (x is a ULONG64 ) */
01972 #define FITS_AS_I1(x) ((x) >> 8 == 0)
01973 #define FITS_AS_I2(x) ((x) >> 16 == 0)
01974 #define FITS_AS_I4(x) ((x) >> 32 == 0)
01975 
01976 /**********************************************************************
01977  *              VarNumFromParseNum [OLEAUT32.47]
01978  *
01979  * Convert a NUMPARSE structure into a numeric Variant type.
01980  *
01981  * PARAMS
01982  *  pNumprs  [I] Source for parsed number. cDig must be set to the size of rgbDig
01983  *  rgbDig   [I] Source for the numbers digits
01984  *  dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types
01985  *  pVarDst  [O] Destination for the converted Variant value.
01986  *
01987  * RETURNS
01988  *  Success: S_OK. pVarDst contains the converted value.
01989  *  Failure: E_INVALIDARG, if any parameter is invalid.
01990  *           DISP_E_OVERFLOW, if the number is too big for the types set in dwVtBits.
01991  *
01992  * NOTES
01993  *  - The smallest favoured type present in dwVtBits that can represent the
01994  *    number in pNumprs without losing precision is used.
01995  *  - Signed types are preferred over unsigned types of the same size.
01996  *  - Preferred types in order are: integer, float, double, currency then decimal.
01997  *  - Rounding (dropping of decimal points) occurs without error. See VarI8FromR8()
01998  *    for details of the rounding method.
01999  *  - pVarDst is not cleared before the result is stored in it.
02000  *  - WinXP and Win2003 support VTBIT_I8, VTBIT_UI8 but that's buggy (by
02001  *    design?): If some other VTBIT's for integers are specified together
02002  *    with VTBIT_I8 and the number will fit only in a VT_I8 Windows will "cast"
02003  *    the number to the smallest requested integer truncating this way the
02004  *    number.  Wine doesn't implement this "feature" (yet?).
02005  */
02006 HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
02007                                   ULONG dwVtBits, VARIANT *pVarDst)
02008 {
02009   /* Scale factors and limits for double arithmetic */
02010   static const double dblMultipliers[11] = {
02011     1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0,
02012     1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0
02013   };
02014   static const double dblMinimums[11] = {
02015     R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0,
02016     R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0,
02017     R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0
02018   };
02019   static const double dblMaximums[11] = {
02020     R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0,
02021     R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0,
02022     R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0
02023   };
02024 
02025   int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0;
02026 
02027   TRACE("(%p,%p,0x%x,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst);
02028 
02029   if (pNumprs->nBaseShift)
02030   {
02031     /* nBaseShift indicates a hex or octal number */
02032     ULONG64 ul64 = 0;
02033     LONG64 l64;
02034     int i;
02035 
02036     /* Convert the hex or octal number string into a UI64 */
02037     for (i = 0; i < pNumprs->cDig; i++)
02038     {
02039       if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
02040       {
02041         TRACE("Overflow multiplying digits\n");
02042         return DISP_E_OVERFLOW;
02043       }
02044       ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
02045     }
02046 
02047     /* also make a negative representation */
02048     l64=-ul64;
02049 
02050     /* Try signed and unsigned types in size order */
02051     if (dwVtBits & VTBIT_I1 && FITS_AS_I1(ul64))
02052     {
02053       V_VT(pVarDst) = VT_I1;
02054       V_I1(pVarDst) = ul64;
02055       return S_OK;
02056     }
02057     else if (dwVtBits & VTBIT_UI1 && FITS_AS_I1(ul64))
02058     {
02059       V_VT(pVarDst) = VT_UI1;
02060       V_UI1(pVarDst) = ul64;
02061       return S_OK;
02062     }
02063     else if (dwVtBits & VTBIT_I2 && FITS_AS_I2(ul64))
02064     {
02065       V_VT(pVarDst) = VT_I2;
02066       V_I2(pVarDst) = ul64;
02067       return S_OK;
02068     }
02069     else if (dwVtBits & VTBIT_UI2 && FITS_AS_I2(ul64))
02070     {
02071       V_VT(pVarDst) = VT_UI2;
02072       V_UI2(pVarDst) = ul64;
02073       return S_OK;
02074     }
02075     else if (dwVtBits & VTBIT_I4 && FITS_AS_I4(ul64))
02076     {
02077       V_VT(pVarDst) = VT_I4;
02078       V_I4(pVarDst) = ul64;
02079       return S_OK;
02080     }
02081     else if (dwVtBits & VTBIT_UI4 && FITS_AS_I4(ul64))
02082     {
02083       V_VT(pVarDst) = VT_UI4;
02084       V_UI4(pVarDst) = ul64;
02085       return S_OK;
02086     }
02087     else if (dwVtBits & VTBIT_I8 && ((ul64 <= I8_MAX)||(l64>=I8_MIN)))
02088     {
02089       V_VT(pVarDst) = VT_I8;
02090       V_I8(pVarDst) = ul64;
02091       return S_OK;
02092     }
02093     else if (dwVtBits & VTBIT_UI8)
02094     {
02095       V_VT(pVarDst) = VT_UI8;
02096       V_UI8(pVarDst) = ul64;
02097       return S_OK;
02098     }
02099     else if ((dwVtBits & VTBIT_DECIMAL) == VTBIT_DECIMAL)
02100     {
02101       V_VT(pVarDst) = VT_DECIMAL;
02102       DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
02103       DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
02104       DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
02105       return S_OK;
02106     }
02107     else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
02108     {
02109       V_VT(pVarDst) = VT_R4;
02110       if (ul64 <= I4_MAX)
02111           V_R4(pVarDst) = ul64;
02112       else
02113           V_R4(pVarDst) = l64;
02114       return S_OK;
02115     }
02116     else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
02117     {
02118       V_VT(pVarDst) = VT_R8;
02119       if (ul64 <= I4_MAX)
02120           V_R8(pVarDst) = ul64;
02121       else
02122           V_R8(pVarDst) = l64;
02123       return S_OK;
02124     }
02125 
02126     TRACE("Overflow: possible return types: 0x%x, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
02127     return DISP_E_OVERFLOW;
02128   }
02129 
02130   /* Count the number of relevant fractional and whole digits stored,
02131    * And compute the divisor/multiplier to scale the number by.
02132    */
02133   if (pNumprs->nPwr10 < 0)
02134   {
02135     if (-pNumprs->nPwr10 >= pNumprs->cDig)
02136     {
02137       /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
02138       wholeNumberDigits = 0;
02139       fractionalDigits = pNumprs->cDig;
02140       divisor10 = -pNumprs->nPwr10;
02141     }
02142     else
02143     {
02144       /* An exactly represented real number e.g. 1.024 */
02145       wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10;
02146       fractionalDigits = pNumprs->cDig - wholeNumberDigits;
02147       divisor10 = pNumprs->cDig - wholeNumberDigits;
02148     }
02149   }
02150   else if (pNumprs->nPwr10 == 0)
02151   {
02152     /* An exactly represented whole number e.g. 1024 */
02153     wholeNumberDigits = pNumprs->cDig;
02154     fractionalDigits = 0;
02155   }
02156   else /* pNumprs->nPwr10 > 0 */
02157   {
02158     /* A whole number followed by nPwr10 0's e.g. 102400 */
02159     wholeNumberDigits = pNumprs->cDig;
02160     fractionalDigits = 0;
02161     multiplier10 = pNumprs->nPwr10;
02162   }
02163 
02164   TRACE("cDig %d; nPwr10 %d, whole %d, frac %d mult %d; div %d\n",
02165         pNumprs->cDig, pNumprs->nPwr10, wholeNumberDigits, fractionalDigits,
02166         multiplier10, divisor10);
02167 
02168   if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) &&
02169       (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL))))
02170   {
02171     /* We have one or more integer output choices, and either:
02172      *  1) An integer input value, or
02173      *  2) A real number input value but no floating output choices.
02174      * Alternately, we have a DECIMAL output available and an integer input.
02175      *
02176      * So, place the integer value into pVarDst, using the smallest type
02177      * possible and preferring signed over unsigned types.
02178      */
02179     BOOL bOverflow = FALSE, bNegative;
02180     ULONG64 ul64 = 0;
02181     int i;
02182 
02183     /* Convert the integer part of the number into a UI8 */
02184     for (i = 0; i < wholeNumberDigits; i++)
02185     {
02186       if (ul64 > (UI8_MAX / 10 - rgbDig[i]))
02187       {
02188         TRACE("Overflow multiplying digits\n");
02189         bOverflow = TRUE;
02190         break;
02191       }
02192       ul64 = ul64 * 10 + rgbDig[i];
02193     }
02194 
02195     /* Account for the scale of the number */
02196     if (!bOverflow && multiplier10)
02197     {
02198       for (i = 0; i < multiplier10; i++)
02199       {
02200         if (ul64 > (UI8_MAX / 10))
02201         {
02202           TRACE("Overflow scaling number\n");
02203           bOverflow = TRUE;
02204           break;
02205         }
02206         ul64 = ul64 * 10;
02207       }
02208     }
02209 
02210     /* If we have any fractional digits, round the value.
02211      * Note we don't have to do this if divisor10 is < 1,
02212      * because this means the fractional part must be < 0.5
02213      */
02214     if (!bOverflow && fractionalDigits && divisor10 > 0)
02215     {
02216       const BYTE* fracDig = rgbDig + wholeNumberDigits;
02217       BOOL bAdjust = FALSE;
02218 
02219       TRACE("first decimal value is %d\n", *fracDig);
02220 
02221       if (*fracDig > 5)
02222         bAdjust = TRUE; /* > 0.5 */
02223       else if (*fracDig == 5)
02224       {
02225         for (i = 1; i < fractionalDigits; i++)
02226         {
02227           if (fracDig[i])
02228           {
02229             bAdjust = TRUE; /* > 0.5 */
02230             break;
02231           }
02232         }
02233         /* If exactly 0.5, round only odd values */
02234         if (i == fractionalDigits && (ul64 & 1))
02235           bAdjust = TRUE;
02236       }
02237 
02238       if (bAdjust)
02239       {
02240         if (ul64 == UI8_MAX)
02241         {
02242           TRACE("Overflow after rounding\n");
02243           bOverflow = TRUE;
02244         }
02245         ul64++;
02246       }
02247     }
02248 
02249     /* Zero is not a negative number */
02250     bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64 ? TRUE : FALSE;
02251 
02252     TRACE("Integer value is 0x%s, bNeg %d\n", wine_dbgstr_longlong(ul64), bNegative);
02253 
02254     /* For negative integers, try the signed types in size order */
02255     if (!bOverflow && bNegative)
02256     {
02257       if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8))
02258       {
02259         if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN)
02260         {
02261           V_VT(pVarDst) = VT_I1;
02262           V_I1(pVarDst) = -ul64;
02263           return S_OK;
02264         }
02265         else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN)
02266         {
02267           V_VT(pVarDst) = VT_I2;
02268           V_I2(pVarDst) = -ul64;
02269           return S_OK;
02270         }
02271         else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN))
02272         {
02273           V_VT(pVarDst) = VT_I4;
02274           V_I4(pVarDst) = -ul64;
02275           return S_OK;
02276         }
02277         else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1)
02278         {
02279           V_VT(pVarDst) = VT_I8;
02280           V_I8(pVarDst) = -ul64;
02281           return S_OK;
02282         }
02283         else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
02284         {
02285           /* Decimal is only output choice left - fast path */
02286           V_VT(pVarDst) = VT_DECIMAL;
02287           DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
02288           DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
02289           DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
02290           return S_OK;
02291         }
02292       }
02293     }
02294     else if (!bOverflow)
02295     {
02296       /* For positive integers, try signed then unsigned types in size order */
02297       if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX)
02298       {
02299         V_VT(pVarDst) = VT_I1;
02300         V_I1(pVarDst) = ul64;
02301         return S_OK;
02302       }
02303       else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
02304       {
02305         V_VT(pVarDst) = VT_UI1;
02306         V_UI1(pVarDst) = ul64;
02307         return S_OK;
02308       }
02309       else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
02310       {
02311         V_VT(pVarDst) = VT_I2;
02312         V_I2(pVarDst) = ul64;
02313         return S_OK;
02314       }
02315       else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
02316       {
02317         V_VT(pVarDst) = VT_UI2;
02318         V_UI2(pVarDst) = ul64;
02319         return S_OK;
02320       }
02321       else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
02322       {
02323         V_VT(pVarDst) = VT_I4;
02324         V_I4(pVarDst) = ul64;
02325         return S_OK;
02326       }
02327       else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
02328       {
02329         V_VT(pVarDst) = VT_UI4;
02330         V_UI4(pVarDst) = ul64;
02331         return S_OK;
02332       }
02333       else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
02334       {
02335         V_VT(pVarDst) = VT_I8;
02336         V_I8(pVarDst) = ul64;
02337         return S_OK;
02338       }
02339       else if (dwVtBits & VTBIT_UI8)
02340       {
02341         V_VT(pVarDst) = VT_UI8;
02342         V_UI8(pVarDst) = ul64;
02343         return S_OK;
02344       }
02345       else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
02346       {
02347         /* Decimal is only output choice left - fast path */
02348         V_VT(pVarDst) = VT_DECIMAL;
02349         DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
02350         DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
02351         DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
02352         return S_OK;
02353       }
02354     }
02355   }
02356 
02357   if (dwVtBits & REAL_VTBITS)
02358   {
02359     /* Try to put the number into a float or real */
02360     BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG;
02361     double whole = 0.0;
02362     int i;
02363 
02364     /* Convert the number into a double */
02365     for (i = 0; i < pNumprs->cDig; i++)
02366       whole = whole * 10.0 + rgbDig[i];
02367 
02368     TRACE("Whole double value is %16.16g\n", whole);
02369 
02370     /* Account for the scale */
02371     while (multiplier10 > 10)
02372     {
02373       if (whole > dblMaximums[10])
02374       {
02375         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
02376         bOverflow = TRUE;
02377         break;
02378       }
02379       whole = whole * dblMultipliers[10];
02380       multiplier10 -= 10;
02381     }
02382     if (multiplier10 && !bOverflow)
02383     {
02384       if (whole > dblMaximums[multiplier10])
02385       {
02386         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
02387         bOverflow = TRUE;
02388       }
02389       else
02390         whole = whole * dblMultipliers[multiplier10];
02391     }
02392 
02393     if (!bOverflow)
02394         TRACE("Scaled double value is %16.16g\n", whole);
02395 
02396     while (divisor10 > 10 && !bOverflow)
02397     {
02398       if (whole < dblMinimums[10] && whole != 0)
02399       {
02400         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
02401         bOverflow = TRUE;
02402         break;
02403       }
02404       whole = whole / dblMultipliers[10];
02405       divisor10 -= 10;
02406     }
02407     if (divisor10 && !bOverflow)
02408     {
02409       if (whole < dblMinimums[divisor10] && whole != 0)
02410       {
02411         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
02412         bOverflow = TRUE;
02413       }
02414       else
02415         whole = whole / dblMultipliers[divisor10];
02416     }
02417     if (!bOverflow)
02418       TRACE("Final double value is %16.16g\n", whole);
02419 
02420     if (dwVtBits & VTBIT_R4 &&
02421         ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0))
02422     {
02423       TRACE("Set R4 to final value\n");
02424       V_VT(pVarDst) = VT_R4; /* Fits into a float */
02425       V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
02426       return S_OK;
02427     }
02428 
02429     if (dwVtBits & VTBIT_R8)
02430     {
02431       TRACE("Set R8 to final value\n");
02432       V_VT(pVarDst) = VT_R8; /* Fits into a double */
02433       V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
02434       return S_OK;
02435     }
02436 
02437     if (dwVtBits & VTBIT_CY)
02438     {
02439       if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst))))
02440       {
02441         V_VT(pVarDst) = VT_CY; /* Fits into a currency */
02442         TRACE("Set CY to final value\n");
02443         return S_OK;
02444       }
02445       TRACE("Value Overflows CY\n");
02446     }
02447   }
02448 
02449   if (dwVtBits & VTBIT_DECIMAL)
02450   {
02451     int i;
02452     ULONG carry;
02453     ULONG64 tmp;
02454     DECIMAL* pDec = &V_DECIMAL(pVarDst);
02455 
02456     DECIMAL_SETZERO(*pDec);
02457     DEC_LO32(pDec) = 0;
02458 
02459     if (pNumprs->dwOutFlags & NUMPRS_NEG)
02460       DEC_SIGN(pDec) = DECIMAL_NEG;
02461     else
02462       DEC_SIGN(pDec) = DECIMAL_POS;
02463 
02464     /* Factor the significant digits */
02465     for (i = 0; i < pNumprs->cDig; i++)
02466     {
02467       tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
02468       carry = (ULONG)(tmp >> 32);
02469       DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
02470       tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
02471       carry = (ULONG)(tmp >> 32);
02472       DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
02473       tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
02474       DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
02475 
02476       if (tmp >> 32 & UI4_MAX)
02477       {
02478 VarNumFromParseNum_DecOverflow:
02479         TRACE("Overflow\n");
02480         DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
02481         return DISP_E_OVERFLOW;
02482       }
02483     }
02484 
02485     /* Account for the scale of the number */
02486     while (multiplier10 > 0)
02487     {
02488       tmp = (ULONG64)DEC_LO32(pDec) * 10;
02489       carry = (ULONG)(tmp >> 32);
02490       DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
02491       tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
02492       carry = (ULONG)(tmp >> 32);
02493       DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
02494       tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
02495       DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
02496 
02497       if (tmp >> 32 & UI4_MAX)
02498         goto VarNumFromParseNum_DecOverflow;
02499       multiplier10--;
02500     }
02501     DEC_SCALE(pDec) = divisor10;
02502 
02503     V_VT(pVarDst) = VT_DECIMAL;
02504     return S_OK;
02505   }
02506   return DISP_E_OVERFLOW; /* No more output choices */
02507 }
02508 
02509 /**********************************************************************
02510  *              VarCat [OLEAUT32.318]
02511  *
02512  * Concatenates one variant onto another.
02513  *
02514  * PARAMS
02515  *  left    [I] First variant
02516  *  right   [I] Second variant
02517  *  result  [O] Result variant
02518  *
02519  * RETURNS
02520  *  Success: S_OK.
02521  *  Failure: An HRESULT error code indicating the error.
02522  */
02523 HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
02524 {
02525     VARTYPE leftvt,rightvt,resultvt;
02526     HRESULT hres;
02527     static WCHAR str_true[32];
02528     static WCHAR str_false[32];
02529     static const WCHAR sz_empty[] = {'\0'};
02530     leftvt = V_VT(left);
02531     rightvt = V_VT(right);
02532 
02533     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
02534           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), out);
02535 
02536     if (!str_true[0]) {
02537         VARIANT_GetLocalisedText(LOCALE_USER_DEFAULT, IDS_FALSE, str_false);
02538         VARIANT_GetLocalisedText(LOCALE_USER_DEFAULT, IDS_TRUE, str_true);
02539     }
02540 
02541     /* when both left and right are NULL the result is NULL */
02542     if (leftvt == VT_NULL && rightvt == VT_NULL)
02543     {
02544         V_VT(out) = VT_NULL;
02545         return S_OK;
02546     }
02547 
02548     hres = S_OK;
02549     resultvt = VT_EMPTY;
02550 
02551     /* There are many special case for errors and return types */
02552     if (leftvt == VT_VARIANT && (rightvt == VT_ERROR ||
02553         rightvt == VT_DATE || rightvt == VT_DECIMAL))
02554         hres = DISP_E_TYPEMISMATCH;
02555     else if ((leftvt == VT_I2 || leftvt == VT_I4 ||
02556         leftvt == VT_R4 || leftvt == VT_R8 ||
02557         leftvt == VT_CY || leftvt == VT_BOOL ||
02558         leftvt == VT_BSTR || leftvt == VT_I1 ||
02559         leftvt == VT_UI1 || leftvt == VT_UI2 ||
02560         leftvt == VT_UI4 || leftvt == VT_I8 ||
02561         leftvt == VT_UI8 || leftvt == VT_INT ||
02562         leftvt == VT_UINT || leftvt == VT_EMPTY ||
02563         leftvt == VT_NULL || leftvt == VT_DATE ||
02564         leftvt == VT_DECIMAL || leftvt == VT_DISPATCH)
02565         &&
02566         (rightvt == VT_I2 || rightvt == VT_I4 ||
02567         rightvt == VT_R4 || rightvt == VT_R8 ||
02568         rightvt == VT_CY || rightvt == VT_BOOL ||
02569         rightvt == VT_BSTR || rightvt == VT_I1 ||
02570         rightvt == VT_UI1 || rightvt == VT_UI2 ||
02571         rightvt == VT_UI4 || rightvt == VT_I8 ||
02572         rightvt == VT_UI8 || rightvt == VT_INT ||
02573         rightvt == VT_UINT || rightvt == VT_EMPTY ||
02574         rightvt == VT_NULL || rightvt == VT_DATE ||
02575         rightvt == VT_DECIMAL || rightvt == VT_DISPATCH))
02576         resultvt = VT_BSTR;
02577     else if (rightvt == VT_ERROR && leftvt < VT_VOID)
02578         hres = DISP_E_TYPEMISMATCH;
02579     else if (leftvt == VT_ERROR && (rightvt == VT_DATE ||
02580         rightvt == VT_ERROR || rightvt == VT_DECIMAL))
02581         hres = DISP_E_TYPEMISMATCH;
02582     else if (rightvt == VT_DATE || rightvt == VT_ERROR ||
02583         rightvt == VT_DECIMAL)
02584         hres = DISP_E_BADVARTYPE;
02585     else if (leftvt == VT_ERROR || rightvt == VT_ERROR)
02586         hres = DISP_E_TYPEMISMATCH;
02587     else if (leftvt == VT_VARIANT)
02588         hres = DISP_E_TYPEMISMATCH;
02589     else if (rightvt == VT_VARIANT && (leftvt == VT_EMPTY ||
02590         leftvt == VT_NULL || leftvt ==  VT_I2 ||
02591         leftvt == VT_I4 || leftvt == VT_R4 ||
02592         leftvt == VT_R8 || leftvt == VT_CY ||
02593         leftvt == VT_DATE || leftvt == VT_BSTR ||
02594         leftvt == VT_BOOL ||  leftvt == VT_DECIMAL ||
02595         leftvt == VT_I1 || leftvt == VT_UI1 ||
02596         leftvt == VT_UI2 || leftvt == VT_UI4 ||
02597         leftvt == VT_I8 || leftvt == VT_UI8 ||
02598         leftvt == VT_INT || leftvt == VT_UINT))
02599         hres = DISP_E_TYPEMISMATCH;
02600     else
02601         hres = DISP_E_BADVARTYPE;
02602 
02603     /* if result type is not S_OK, then no need to go further */
02604     if (hres != S_OK)
02605     {
02606         V_VT(out) = resultvt;
02607         return hres;
02608     }
02609     /* Else proceed with formatting inputs to strings */
02610     else
02611     {
02612         VARIANT bstrvar_left, bstrvar_right;
02613         V_VT(out) = VT_BSTR;
02614 
02615         VariantInit(&bstrvar_left);
02616         VariantInit(&bstrvar_right);
02617 
02618         /* Convert left side variant to string */
02619         if (leftvt != VT_BSTR)
02620         {
02621             if (leftvt == VT_BOOL)
02622             {
02623                 /* Bools are handled as localized True/False strings instead of 0/-1 as in MSDN */
02624                 V_VT(&bstrvar_left) = VT_BSTR;
02625                 if (V_BOOL(left) == TRUE)
02626                     V_BSTR(&bstrvar_left) = SysAllocString(str_true);
02627                 else
02628                     V_BSTR(&bstrvar_left) = SysAllocString(str_false);
02629             }
02630             /* Fill with empty string for later concat with right side */
02631             else if (leftvt == VT_NULL)
02632             {
02633                 V_VT(&bstrvar_left) = VT_BSTR;
02634                 V_BSTR(&bstrvar_left) = SysAllocString(sz_empty);
02635             }
02636             else
02637             {
02638                 hres = VariantChangeTypeEx(&bstrvar_left,left,0,0,VT_BSTR);
02639                 if (hres != S_OK) {
02640                     VariantClear(&bstrvar_left);
02641                     VariantClear(&bstrvar_right);
02642                     if (leftvt == VT_NULL && (rightvt == VT_EMPTY ||
02643                         rightvt == VT_NULL || rightvt ==  VT_I2 ||
02644                         rightvt == VT_I4 || rightvt == VT_R4 ||
02645                         rightvt == VT_R8 || rightvt == VT_CY ||
02646                         rightvt == VT_DATE || rightvt == VT_BSTR ||
02647                         rightvt == VT_BOOL ||  rightvt == VT_DECIMAL ||
02648                         rightvt == VT_I1 || rightvt == VT_UI1 ||
02649                         rightvt == VT_UI2 || rightvt == VT_UI4 ||
02650                         rightvt == VT_I8 || rightvt == VT_UI8 ||
02651                         rightvt == VT_INT || rightvt == VT_UINT))
02652                         return DISP_E_BADVARTYPE;
02653                     return hres;
02654                 }
02655             }
02656         }
02657 
02658         /* convert right side variant to string */
02659         if (rightvt != VT_BSTR)
02660         {
02661             if (rightvt == VT_BOOL)
02662             {
02663                 /* Bools are handled as localized True/False strings instead of 0/-1 as in MSDN */
02664                 V_VT(&bstrvar_right) = VT_BSTR;
02665                 if (V_BOOL(right) == TRUE)
02666                     V_BSTR(&bstrvar_right) = SysAllocString(str_true);
02667                 else
02668                     V_BSTR(&bstrvar_right) = SysAllocString(str_false);
02669             }
02670             /* Fill with empty string for later concat with right side */
02671             else if (rightvt == VT_NULL)
02672             {
02673                 V_VT(&bstrvar_right) = VT_BSTR;
02674                 V_BSTR(&bstrvar_right) = SysAllocString(sz_empty);
02675             }
02676             else
02677             {
02678                 hres = VariantChangeTypeEx(&bstrvar_right,right,0,0,VT_BSTR);
02679                 if (hres != S_OK) {
02680                     VariantClear(&bstrvar_left);
02681                     VariantClear(&bstrvar_right);
02682                     if (rightvt == VT_NULL && (leftvt == VT_EMPTY ||
02683                         leftvt == VT_NULL || leftvt ==  VT_I2 ||
02684                         leftvt == VT_I4 || leftvt == VT_R4 ||
02685                         leftvt == VT_R8 || leftvt == VT_CY ||
02686                         leftvt == VT_DATE || leftvt == VT_BSTR ||
02687                         leftvt == VT_BOOL ||  leftvt == VT_DECIMAL ||
02688                         leftvt == VT_I1 || leftvt == VT_UI1 ||
02689                         leftvt == VT_UI2 || leftvt == VT_UI4 ||
02690                         leftvt == VT_I8 || leftvt == VT_UI8 ||
02691                         leftvt == VT_INT || leftvt == VT_UINT))
02692                         return DISP_E_BADVARTYPE;
02693                     return hres;
02694                 }
02695             }
02696         }
02697 
02698         /* Concat the resulting strings together */
02699         if (leftvt == VT_BSTR && rightvt == VT_BSTR)
02700             VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out));
02701         else if (leftvt != VT_BSTR && rightvt != VT_BSTR)
02702             VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(&bstrvar_right), &V_BSTR(out));
02703         else if (leftvt != VT_BSTR && rightvt == VT_BSTR)
02704             VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(right), &V_BSTR(out));
02705         else if (leftvt == VT_BSTR && rightvt != VT_BSTR)
02706             VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar_right), &V_BSTR(out));
02707 
02708         VariantClear(&bstrvar_left);
02709         VariantClear(&bstrvar_right);
02710         return S_OK;
02711     }
02712 }
02713 
02714 
02715 /* Wrapper around VariantChangeTypeEx() which permits changing a
02716    variant with VT_RESERVED flag set. Needed by VarCmp. */
02717 static HRESULT _VarChangeTypeExWrap (VARIANTARG* pvargDest,
02718                     VARIANTARG* pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
02719 {
02720     HRESULT res;
02721     VARTYPE flags;
02722 
02723     flags = V_VT(pvargSrc) & ~VT_TYPEMASK;
02724     V_VT(pvargSrc) &= ~VT_RESERVED;
02725     res = VariantChangeTypeEx(pvargDest,pvargSrc,lcid,wFlags,vt);
02726     V_VT(pvargSrc) |= flags;
02727 
02728     return res;
02729 }
02730 
02731 /**********************************************************************
02732  *              VarCmp [OLEAUT32.176]
02733  *
02734  * Compare two variants.
02735  *
02736  * PARAMS
02737  *  left    [I] First variant
02738  *  right   [I] Second variant
02739  *  lcid    [I] LCID (locale identifier) for the comparison
02740  *  flags   [I] Flags to be used in the comparison:
02741  *              NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS,
02742  *              NORM_IGNOREWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA
02743  *
02744  * RETURNS
02745  *  VARCMP_LT:   left variant is less than right variant.
02746  *  VARCMP_EQ:   input variants are equal.
02747  *  VARCMP_GT:   left variant is greater than right variant.
02748  *  VARCMP_NULL: either one of the input variants is NULL.
02749  *  Failure:     An HRESULT error code indicating the error.
02750  *
02751  * NOTES
02752  *  Native VarCmp up to and including WinXP doesn't like I1, UI2, VT_UI4,
02753  *  UI8 and UINT as input variants. INT is accepted only as left variant.
02754  *
02755  *  If both input variants are ERROR then VARCMP_EQ will be returned, else
02756  *  an ERROR variant will trigger an error.
02757  *
02758  *  Both input variants can have VT_RESERVED flag set which is ignored
02759  *  unless one and only one of the variants is a BSTR and the other one
02760  *  is not an EMPTY variant. All four VT_RESERVED combinations have a
02761  *  different meaning:
02762  *   - BSTR and other: BSTR is always greater than the other variant.
02763  *   - BSTR|VT_RESERVED and other: a string comparison is performed.
02764  *   - BSTR and other|VT_RESERVED: If the BSTR is a number a numeric
02765  *     comparison will take place else the BSTR is always greater.
02766  *   - BSTR|VT_RESERVED and other|VT_RESERVED: It seems that the other
02767  *     variant is ignored and the return value depends only on the sign
02768  *     of the BSTR if it is a number else the BSTR is always greater. A
02769  *     positive BSTR is greater, a negative one is smaller than the other
02770  *     variant.
02771  *
02772  * SEE
02773  *  VarBstrCmp for the lcid and flags usage.
02774  */
02775 HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
02776 {
02777     VARTYPE     lvt, rvt, vt;
02778     VARIANT     rv,lv;
02779     DWORD       xmask;
02780     HRESULT     rc;
02781 
02782     TRACE("(%p->(%s%s),%p->(%s%s),0x%08x,0x%08x)\n", left, debugstr_VT(left),
02783           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), lcid, flags);
02784 
02785     lvt = V_VT(left) & VT_TYPEMASK;
02786     rvt = V_VT(right) & VT_TYPEMASK;
02787     xmask = (1 << lvt) | (1 << rvt);
02788 
02789     /* If we have any flag set except VT_RESERVED bail out.
02790        Same for the left input variant type > VT_INT and for the
02791        right input variant type > VT_I8. Yes, VT_INT is only supported
02792        as left variant. Go figure */
02793     if (((V_VT(left) | V_VT(right)) & ~VT_TYPEMASK & ~VT_RESERVED) ||
02794             lvt > VT_INT || rvt > VT_I8) {
02795         return DISP_E_BADVARTYPE;
02796     }
02797 
02798     /* Don't ask me why but native VarCmp cannot handle: VT_I1, VT_UI2, VT_UI4,
02799        VT_UINT and VT_UI8. Tested with DCOM98, Win2k, WinXP */
02800     if (rvt == VT_INT || xmask & (VTBIT_I1 | VTBIT_UI2 | VTBIT_UI4 | VTBIT_UI8 |
02801                 VTBIT_DISPATCH | VTBIT_VARIANT | VTBIT_UNKNOWN | VTBIT_15))
02802         return DISP_E_TYPEMISMATCH;
02803 
02804     /* If both variants are VT_ERROR return VARCMP_EQ */
02805     if (xmask == VTBIT_ERROR)
02806         return VARCMP_EQ;
02807     else if (xmask & VTBIT_ERROR)
02808         return DISP_E_TYPEMISMATCH;
02809 
02810     if (xmask & VTBIT_NULL)
02811         return VARCMP_NULL;
02812 
02813     VariantInit(&lv);
02814     VariantInit(&rv);
02815 
02816     /* Two BSTRs, ignore VT_RESERVED */
02817     if (xmask == VTBIT_BSTR)
02818         return VarBstrCmp(V_BSTR(left), V_BSTR(right), lcid, flags);
02819 
02820     /* A BSTR and an other variant; we have to take care of VT_RESERVED */
02821     if (xmask & VTBIT_BSTR) {
02822         VARIANT *bstrv, *nonbv;
02823         VARTYPE nonbvt;
02824         int swap = 0;
02825 
02826         /* Swap the variants so the BSTR is always on the left */
02827         if (lvt == VT_BSTR) {
02828             bstrv = left;
02829             nonbv = right;
02830             nonbvt = rvt;
02831         } else {
02832             swap = 1;
02833             bstrv = right;
02834             nonbv = left;
02835             nonbvt = lvt;
02836         }
02837 
02838         /* BSTR and EMPTY: ignore VT_RESERVED */
02839         if (nonbvt == VT_EMPTY)
02840             rc = (!V_BSTR(bstrv) || !*V_BSTR(bstrv)) ? VARCMP_EQ : VARCMP_GT;
02841         else {
02842             VARTYPE breserv = V_VT(bstrv) & ~VT_TYPEMASK;
02843             VARTYPE nreserv = V_VT(nonbv) & ~VT_TYPEMASK;
02844 
02845             if (!breserv && !nreserv) 
02846                 /* No VT_RESERVED set ==> BSTR always greater */
02847                 rc = VARCMP_GT;
02848             else if (breserv && !nreserv) {
02849                 /* BSTR has VT_RESERVED set. Do a string comparison */
02850                 rc = VariantChangeTypeEx(&rv,nonbv,lcid,0,VT_BSTR);
02851                 if (FAILED(rc))
02852                     return rc;
02853                 rc = VarBstrCmp(V_BSTR(bstrv), V_BSTR(&rv), lcid, flags);
02854                 VariantClear(&rv);
02855             } else if (V_BSTR(bstrv) && *V_BSTR(bstrv)) {
02856             /* Non NULL nor empty BSTR */
02857                 /* If the BSTR is not a number the BSTR is greater */
02858                 rc = _VarChangeTypeExWrap(&lv,bstrv,lcid,0,VT_R8);
02859                 if (FAILED(rc))
02860                     rc = VARCMP_GT;
02861                 else if (breserv && nreserv)
02862                     /* FIXME: This is strange: with both VT_RESERVED set it
02863                        looks like the result depends only on the sign of
02864                        the BSTR number */
02865                     rc = (V_R8(&lv) >= 0) ? VARCMP_GT : VARCMP_LT;
02866                 else
02867                     /* Numeric comparison, will be handled below.
02868                        VARCMP_NULL used only to break out. */
02869                     rc = VARCMP_NULL;
02870                 VariantClear(&lv);
02871                 VariantClear(&rv);
02872             } else
02873                 /* Empty or NULL BSTR */
02874                 rc = VARCMP_GT;
02875         }
02876         /* Fixup the return code if we swapped left and right */
02877         if (swap) {
02878             if (rc == VARCMP_GT)
02879                 rc = VARCMP_LT;
02880             else if (rc == VARCMP_LT)
02881                 rc = VARCMP_GT;
02882         }
02883         if (rc != VARCMP_NULL)
02884             return rc;
02885     }
02886 
02887     if (xmask & VTBIT_DECIMAL)
02888         vt = VT_DECIMAL;
02889     else if (xmask & VTBIT_BSTR)
02890         vt = VT_R8;
02891     else if (xmask & VTBIT_R4)
02892         vt = VT_R4;
02893     else if (xmask & (VTBIT_R8 | VTBIT_DATE))
02894         vt = VT_R8;
02895     else if (xmask & VTBIT_CY)
02896         vt = VT_CY;
02897     else
02898         /* default to I8 */
02899         vt = VT_I8;
02900 
02901     /* Coerce the variants */
02902     rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt);
02903     if (rc == DISP_E_OVERFLOW && vt != VT_R8) {
02904         /* Overflow, change to R8 */
02905         vt = VT_R8;
02906         rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt);
02907     }
02908     if (FAILED(rc))
02909         return rc;
02910     rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt);
02911     if (rc == DISP_E_OVERFLOW && vt != VT_R8) {
02912         /* Overflow, change to R8 */
02913         vt = VT_R8;
02914         rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt);
02915         if (FAILED(rc))
02916             return rc;
02917         rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt);
02918     }
02919     if (FAILED(rc))
02920         return rc;
02921 
02922 #define _VARCMP(a,b) \
02923     (((a) == (b)) ? VARCMP_EQ : (((a) < (b)) ? VARCMP_LT : VARCMP_GT))
02924 
02925     switch (vt) {
02926         case VT_CY:
02927             return VarCyCmp(V_CY(&lv), V_CY(&rv));
02928         case VT_DECIMAL:
02929             return VarDecCmp(&V_DECIMAL(&lv), &V_DECIMAL(&rv));
02930         case VT_I8:
02931             return _VARCMP(V_I8(&lv), V_I8(&rv));
02932         case VT_R4:
02933             return _VARCMP(V_R4(&lv), V_R4(&rv));
02934         case VT_R8:
02935             return _VARCMP(V_R8(&lv), V_R8(&rv));
02936         default:
02937             /* We should never get here */
02938             return E_FAIL;
02939     }
02940 #undef _VARCMP
02941 }
02942 
02943 static HRESULT VARIANT_FetchDispatchValue(LPVARIANT pvDispatch, LPVARIANT pValue)
02944 {
02945     HRESULT hres;
02946     static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
02947 
02948     if ((V_VT(pvDispatch) & VT_TYPEMASK) == VT_DISPATCH) {
02949         if (NULL == V_DISPATCH(pvDispatch)) return DISP_E_TYPEMISMATCH;
02950         hres = IDispatch_Invoke(V_DISPATCH(pvDispatch), DISPID_VALUE, &IID_NULL,
02951             LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, pValue,
02952             NULL, NULL);
02953     } else {
02954         hres = DISP_E_TYPEMISMATCH;
02955     }
02956     return hres;
02957 }
02958 
02959 /**********************************************************************
02960  *              VarAnd [OLEAUT32.142]
02961  *
02962  * Computes the logical AND of two variants.
02963  *
02964  * PARAMS
02965  *  left    [I] First variant
02966  *  right   [I] Second variant
02967  *  result  [O] Result variant
02968  *
02969  * RETURNS
02970  *  Success: S_OK.
02971  *  Failure: An HRESULT error code indicating the error.
02972  */
02973 HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
02974 {
02975     HRESULT hres = S_OK;
02976     VARTYPE resvt = VT_EMPTY;
02977     VARTYPE leftvt,rightvt;
02978     VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
02979     VARIANT varLeft, varRight;
02980     VARIANT tempLeft, tempRight;
02981 
02982     VariantInit(&varLeft);
02983     VariantInit(&varRight);
02984     VariantInit(&tempLeft);
02985     VariantInit(&tempRight);
02986 
02987     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
02988           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
02989 
02990     /* Handle VT_DISPATCH by storing and taking address of returned value */
02991     if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
02992     {
02993         hres = VARIANT_FetchDispatchValue(left, &tempLeft);
02994         if (FAILED(hres)) goto VarAnd_Exit;
02995         left = &tempLeft;
02996     }
02997     if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
02998     {
02999         hres = VARIANT_FetchDispatchValue(right, &tempRight);
03000         if (FAILED(hres)) goto VarAnd_Exit;
03001         right = &tempRight;
03002     }
03003 
03004     leftvt = V_VT(left)&VT_TYPEMASK;
03005     rightvt = V_VT(right)&VT_TYPEMASK;
03006     leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
03007     rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
03008 
03009     if (leftExtraFlags != rightExtraFlags)
03010     {
03011         hres = DISP_E_BADVARTYPE;
03012         goto VarAnd_Exit;
03013     }
03014     ExtraFlags = leftExtraFlags;
03015 
03016     /* Native VarAnd always returns an error when using extra
03017      * flags or if the variant combination is I8 and INT.
03018      */
03019     if ((leftvt == VT_I8 && rightvt == VT_INT) ||
03020         (leftvt == VT_INT && rightvt == VT_I8) ||
03021         ExtraFlags != 0)
03022     {
03023         hres = DISP_E_BADVARTYPE;
03024         goto VarAnd_Exit;
03025     }
03026 
03027     /* Determine return type */
03028     else if (leftvt == VT_I8 || rightvt == VT_I8)
03029         resvt = VT_I8;
03030     else if (leftvt == VT_I4 || rightvt == VT_I4 ||
03031         leftvt == VT_UINT || rightvt == VT_UINT ||
03032         leftvt == VT_INT || rightvt == VT_INT ||
03033         leftvt == VT_UINT || rightvt == VT_UINT ||
03034         leftvt == VT_R4 || rightvt == VT_R4 ||
03035         leftvt == VT_R8 || rightvt == VT_R8 ||
03036         leftvt == VT_CY || rightvt == VT_CY ||
03037         leftvt == VT_DATE || rightvt == VT_DATE ||
03038         leftvt == VT_I1 || rightvt == VT_I1 ||
03039         leftvt == VT_UI2 || rightvt == VT_UI2 ||
03040         leftvt == VT_UI4 || rightvt == VT_UI4 ||
03041         leftvt == VT_UI8 || rightvt == VT_UI8 ||
03042         leftvt == VT_DECIMAL || rightvt == VT_DECIMAL)
03043         resvt = VT_I4;
03044     else if (leftvt == VT_UI1 || rightvt == VT_UI1 ||
03045         leftvt == VT_I2 || rightvt == VT_I2 ||
03046         leftvt == VT_EMPTY || rightvt == VT_EMPTY)
03047         if ((leftvt == VT_NULL && rightvt == VT_UI1) ||
03048             (leftvt == VT_UI1 && rightvt == VT_NULL) ||
03049             (leftvt == VT_UI1 && rightvt == VT_UI1))
03050             resvt = VT_UI1;
03051         else
03052             resvt = VT_I2;
03053     else if (leftvt == VT_BOOL || rightvt == VT_BOOL ||
03054         (leftvt == VT_BSTR && rightvt == VT_BSTR))
03055         resvt = VT_BOOL;
03056     else if (leftvt == VT_NULL || rightvt == VT_NULL ||
03057         leftvt == VT_BSTR || rightvt == VT_BSTR)
03058         resvt = VT_NULL;
03059     else
03060     {
03061         hres = DISP_E_BADVARTYPE;
03062         goto VarAnd_Exit;
03063     }
03064 
03065     if (leftvt == VT_NULL || rightvt == VT_NULL)
03066     {
03067         /*
03068          * Special cases for when left variant is VT_NULL
03069          * (VT_NULL & 0 = VT_NULL, VT_NULL & value = value)
03070          */
03071         if (leftvt == VT_NULL)
03072         {
03073             VARIANT_BOOL b;
03074             switch(rightvt)
03075             {
03076             case VT_I1:   if (V_I1(right)) resvt = VT_NULL; break;
03077             case VT_UI1:  if (V_UI1(right)) resvt = VT_NULL; break;
03078             case VT_I2:   if (V_I2(right)) resvt = VT_NULL; break;
03079             case VT_UI2:  if (V_UI2(right)) resvt = VT_NULL; break;
03080             case VT_I4:   if (V_I4(right)) resvt = VT_NULL; break;
03081             case VT_UI4:  if (V_UI4(right)) resvt = VT_NULL; break;
03082             case VT_I8:   if (V_I8(right)) resvt = VT_NULL; break;
03083             case VT_UI8:  if (V_UI8(right)) resvt = VT_NULL; break;
03084             case VT_INT:  if (V_INT(right)) resvt = VT_NULL; break;
03085             case VT_UINT: if (V_UINT(right)) resvt = VT_NULL; break;
03086             case VT_BOOL: if (V_BOOL(right)) resvt = VT_NULL; break;
03087             case VT_R4:   if (V_R4(right)) resvt = VT_NULL; break;
03088             case VT_R8:   if (V_R8(right)) resvt = VT_NULL; break;
03089             case VT_CY:
03090                 if(V_CY(right).int64)
03091                     resvt = VT_NULL;
03092                 break;
03093             case VT_DECIMAL:
03094                 if (DEC_HI32(&V_DECIMAL(right)) ||
03095                     DEC_LO64(&V_DECIMAL(right)))
03096                     resvt = VT_NULL;
03097                 break;
03098             case VT_BSTR:
03099                 hres = VarBoolFromStr(V_BSTR(right),
03100                 LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
03101                 if (FAILED(hres))
03102                     return hres;
03103                 else if (b)
03104                     V_VT(result) = VT_NULL;
03105                 else
03106                 {
03107                     V_VT(result) = VT_BOOL;
03108                     V_BOOL(result) = b;
03109                 }
03110                 goto VarAnd_Exit;
03111             }
03112         }
03113         V_VT(result) = resvt;
03114         goto VarAnd_Exit;
03115     }
03116 
03117     hres = VariantCopy(&varLeft, left);
03118     if (FAILED(hres)) goto VarAnd_Exit;
03119 
03120     hres = VariantCopy(&varRight, right);
03121     if (FAILED(hres)) goto VarAnd_Exit;
03122 
03123     if (resvt == VT_I4 && V_VT(&varLeft) == VT_UI4)
03124         V_VT(&varLeft) = VT_I4; /* Don't overflow */
03125     else
03126     {
03127         double d;
03128 
03129         if (V_VT(&varLeft) == VT_BSTR &&
03130             FAILED(VarR8FromStr(V_BSTR(&varLeft),
03131             LOCALE_USER_DEFAULT, 0, &d)))
03132             hres = VariantChangeType(&varLeft,&varLeft,
03133             VARIANT_LOCALBOOL, VT_BOOL);
03134             if (SUCCEEDED(hres) && V_VT(&varLeft) != resvt)
03135                 hres = VariantChangeType(&varLeft,&varLeft,0,resvt);
03136             if (FAILED(hres)) goto VarAnd_Exit;
03137     }
03138 
03139     if (resvt == VT_I4 && V_VT(&varRight) == VT_UI4)
03140         V_VT(&varRight) = VT_I4; /* Don't overflow */
03141     else
03142     {
03143         double d;
03144 
03145         if (V_VT(&varRight) == VT_BSTR &&
03146             FAILED(VarR8FromStr(V_BSTR(&varRight),
03147             LOCALE_USER_DEFAULT, 0, &d)))
03148             hres = VariantChangeType(&varRight, &varRight,
03149                 VARIANT_LOCALBOOL, VT_BOOL);
03150         if (SUCCEEDED(hres) && V_VT(&varRight) != resvt)
03151             hres = VariantChangeType(&varRight, &varRight, 0, resvt);
03152         if (FAILED(hres)) goto VarAnd_Exit;
03153     }
03154 
03155     V_VT(result) = resvt;
03156     switch(resvt)
03157     {
03158     case VT_I8:
03159         V_I8(result) = V_I8(&varLeft) & V_I8(&varRight);
03160         break;
03161     case VT_I4:
03162         V_I4(result) = V_I4(&varLeft) & V_I4(&varRight);
03163         break;
03164     case VT_I2:
03165         V_I2(result) = V_I2(&varLeft) & V_I2(&varRight);
03166         break;
03167     case VT_UI1:
03168         V_UI1(result) = V_UI1(&varLeft) & V_UI1(&varRight);
03169         break;
03170     case VT_BOOL:
03171         V_BOOL(result) = V_BOOL(&varLeft) & V_BOOL(&varRight);
03172         break;
03173     default:
03174         FIXME("Couldn't bitwise AND variant types %d,%d\n",
03175             leftvt,rightvt);
03176     }
03177 
03178 VarAnd_Exit:
03179     VariantClear(&varLeft);
03180     VariantClear(&varRight);
03181     VariantClear(&tempLeft);
03182     VariantClear(&tempRight);
03183 
03184     return hres;
03185 }
03186 
03187 /**********************************************************************
03188  *              VarAdd [OLEAUT32.141]
03189  *
03190  * Add two variants.
03191  *
03192  * PARAMS
03193  *  left    [I] First variant
03194  *  right   [I] Second variant
03195  *  result  [O] Result variant
03196  *
03197  * RETURNS
03198  *  Success: S_OK.
03199  *  Failure: An HRESULT error code indicating the error.
03200  *
03201  * NOTES
03202  *  Native VarAdd up to and including WinXP doesn't like I1, UI2, UI4,
03203  *  UI8, INT and UINT as input variants.
03204  *
03205  *  Native VarAdd doesn't check for NULL in/out pointers and crashes. We do the
03206  *  same here.
03207  *
03208  * FIXME
03209  *  Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that
03210  *  case.
03211  */
03212 HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
03213 {
03214     HRESULT hres;
03215     VARTYPE lvt, rvt, resvt, tvt;
03216     VARIANT lv, rv, tv;
03217     VARIANT tempLeft, tempRight;
03218     double r8res;
03219 
03220     /* Variant priority for coercion. Sorted from lowest to highest.
03221        VT_ERROR shows an invalid input variant type. */
03222     enum coerceprio { vt_EMPTY, vt_UI1, vt_I2, vt_I4, vt_I8, vt_BSTR,vt_R4,
03223                       vt_R8, vt_CY, vt_DATE, vt_DECIMAL, vt_DISPATCH, vt_NULL,
03224                       vt_ERROR };
03225     /* Mapping from priority to variant type. Keep in sync with coerceprio! */
03226     static const VARTYPE prio2vt[] = { VT_EMPTY, VT_UI1, VT_I2, VT_I4, VT_I8, VT_BSTR, VT_R4,
03227                           VT_R8, VT_CY, VT_DATE, VT_DECIMAL, VT_DISPATCH,
03228                           VT_NULL, VT_ERROR };
03229 
03230     /* Mapping for coercion from input variant to priority of result variant. */
03231     static const VARTYPE coerce[] = {
03232         /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */
03233         vt_EMPTY, vt_NULL, vt_I2, vt_I4, vt_R4,
03234         /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */
03235         vt_R8, vt_CY, vt_DATE, vt_BSTR, vt_DISPATCH,
03236         /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */
03237         vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL,
03238         /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */
03239         vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8
03240     };
03241 
03242     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
03243           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
03244           result);
03245 
03246     VariantInit(&lv);
03247     VariantInit(&rv);
03248     VariantInit(&tv);
03249     VariantInit(&tempLeft);
03250     VariantInit(&tempRight);
03251 
03252     /* Handle VT_DISPATCH by storing and taking address of returned value */
03253     if ((V_VT(left) & VT_TYPEMASK) != VT_NULL && (V_VT(right) & VT_TYPEMASK) != VT_NULL)
03254     {
03255         if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
03256         {
03257             hres = VARIANT_FetchDispatchValue(left, &tempLeft);
03258             if (FAILED(hres)) goto end;
03259             left = &tempLeft;
03260         }
03261         if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
03262         {
03263             hres = VARIANT_FetchDispatchValue(right, &tempRight);
03264             if (FAILED(hres)) goto end;
03265             right = &tempRight;
03266         }
03267     }
03268 
03269     lvt = V_VT(left)&VT_TYPEMASK;
03270     rvt = V_VT(right)&VT_TYPEMASK;
03271 
03272     /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out.
03273        Same for any input variant type > VT_I8 */
03274     if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK ||
03275         lvt > VT_I8 || rvt > VT_I8) {
03276         hres = DISP_E_BADVARTYPE;
03277         goto end;
03278     }
03279 
03280     /* Determine the variant type to coerce to. */
03281     if (coerce[lvt] > coerce[rvt]) {
03282         resvt = prio2vt[coerce[lvt]];
03283         tvt = prio2vt[coerce[rvt]];
03284     } else {
03285         resvt = prio2vt[coerce[rvt]];
03286         tvt = prio2vt[coerce[lvt]];
03287     }
03288 
03289     /* Special cases where the result variant type is defined by both
03290        input variants and not only that with the highest priority */
03291     if (resvt == VT_BSTR) {
03292         if (tvt == VT_EMPTY || tvt == VT_BSTR)
03293             resvt = VT_BSTR;
03294         else
03295             resvt = VT_R8;
03296     }
03297     if (resvt == VT_R4 && (tvt == VT_BSTR || tvt == VT_I8 || tvt == VT_I4))
03298         resvt = VT_R8;
03299 
03300     /* For overflow detection use the biggest compatible type for the
03301        addition */
03302     switch (resvt) {
03303         case VT_ERROR:
03304             hres = DISP_E_BADVARTYPE;
03305             goto end;
03306         case VT_NULL:
03307             hres = S_OK;
03308             V_VT(result) = VT_NULL;
03309             goto end;
03310         case VT_DISPATCH:
03311             FIXME("cannot handle variant type VT_DISPATCH\n");
03312             hres = DISP_E_TYPEMISMATCH;
03313             goto end;
03314         case VT_EMPTY:
03315             resvt = VT_I2;
03316             /* Fall through */
03317         case VT_UI1:
03318         case VT_I2:
03319         case VT_I4:
03320         case VT_I8:
03321             tvt = VT_I8;
03322             break;
03323         case VT_DATE:
03324         case VT_R4:
03325             tvt = VT_R8;
03326             break;
03327         default:
03328             tvt = resvt;
03329     }
03330 
03331     /* Now coerce the variants */
03332     hres = VariantChangeType(&lv, left, 0, tvt);
03333     if (FAILED(hres))
03334         goto end;
03335     hres = VariantChangeType(&rv, right, 0, tvt);
03336     if (FAILED(hres))
03337         goto end;
03338 
03339     /* Do the math */
03340     hres = S_OK;
03341     V_VT(result) = resvt;
03342     switch (tvt) {
03343         case VT_DECIMAL:
03344             hres = VarDecAdd(&V_DECIMAL(&lv), &V_DECIMAL(&rv),
03345                              &V_DECIMAL(result));
03346             goto end;
03347         case VT_CY:
03348             hres = VarCyAdd(V_CY(&lv), V_CY(&rv), &V_CY(result));
03349             goto end;
03350         case VT_BSTR:
03351             /* We do not add those, we concatenate them. */
03352             hres = VarBstrCat(V_BSTR(&lv), V_BSTR(&rv), &V_BSTR(result));
03353             goto end;
03354         case VT_I8:
03355             /* Overflow detection */
03356             r8res = (double)V_I8(&lv) + (double)V_I8(&rv);
03357             if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) {
03358                 V_VT(result) = VT_R8;
03359                 V_R8(result) = r8res;
03360                 goto end;
03361             } else {
03362                 V_VT(&tv) = tvt;
03363                 V_I8(&tv) = V_I8(&lv) + V_I8(&rv);
03364             }
03365             break;
03366         case VT_R8:
03367             V_VT(&tv) = tvt;
03368             /* FIXME: overflow detection */
03369             V_R8(&tv) = V_R8(&lv) + V_R8(&rv);
03370             break;
03371         default:
03372             ERR("We shouldn't get here! tvt = %d!\n", tvt);
03373             break;
03374     }
03375     if (resvt != tvt) {
03376         if ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) {
03377             /* Overflow! Change to the vartype with the next higher priority.
03378                With one exception: I4 ==> R8 even if it would fit in I8 */
03379             if (resvt == VT_I4)
03380                 resvt = VT_R8;
03381             else
03382                 resvt = prio2vt[coerce[resvt] + 1];
03383             hres = VariantChangeType(result, &tv, 0, resvt);
03384         }
03385     } else
03386         hres = VariantCopy(result, &tv);
03387 
03388 end:
03389     if (hres != S_OK) {
03390         V_VT(result) = VT_EMPTY;
03391         V_I4(result) = 0;       /* No V_EMPTY */
03392     }
03393     VariantClear(&lv);
03394     VariantClear(&rv);
03395     VariantClear(&tv);
03396     VariantClear(&tempLeft);
03397     VariantClear(&tempRight);
03398     TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
03399     return hres;
03400 }
03401 
03402 /**********************************************************************
03403  *              VarMul [OLEAUT32.156]
03404  *
03405  * Multiply two variants.
03406  *
03407  * PARAMS
03408  *  left    [I] First variant
03409  *  right   [I] Second variant
03410  *  result  [O] Result variant
03411  *
03412  * RETURNS
03413  *  Success: S_OK.
03414  *  Failure: An HRESULT error code indicating the error.
03415  *
03416  * NOTES
03417  *  Native VarMul up to and including WinXP doesn't like I1, UI2, UI4,
03418  *  UI8, INT and UINT as input variants. But it can multiply apples with oranges.
03419  *
03420  *  Native VarMul doesn't check for NULL in/out pointers and crashes. We do the
03421  *  same here.
03422  *
03423  * FIXME
03424  *  Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that
03425  *  case.
03426  */
03427 HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
03428 {
03429     HRESULT hres;
03430     VARTYPE lvt, rvt, resvt, tvt;
03431     VARIANT lv, rv, tv;
03432     VARIANT tempLeft, tempRight;
03433     double r8res;
03434 
03435     /* Variant priority for coercion. Sorted from lowest to highest.
03436        VT_ERROR shows an invalid input variant type. */
03437     enum coerceprio { vt_UI1 = 0, vt_I2, vt_I4, vt_I8, vt_CY, vt_R4, vt_R8,
03438                       vt_DECIMAL, vt_NULL, vt_ERROR };
03439     /* Mapping from priority to variant type. Keep in sync with coerceprio! */
03440     static const VARTYPE prio2vt[] = { VT_UI1, VT_I2, VT_I4, VT_I8, VT_CY, VT_R4, VT_R8,
03441                           VT_DECIMAL, VT_NULL, VT_ERROR };
03442 
03443     /* Mapping for coercion from input variant to priority of result variant. */
03444     static const VARTYPE coerce[] = {
03445         /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */
03446         vt_UI1, vt_NULL, vt_I2, vt_I4, vt_R4,
03447         /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */
03448         vt_R8, vt_CY, vt_R8, vt_R8, vt_ERROR,
03449         /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */
03450         vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL,
03451         /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */
03452         vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8
03453     };
03454 
03455     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
03456           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
03457           result);
03458 
03459     VariantInit(&lv);
03460     VariantInit(&rv);
03461     VariantInit(&tv);
03462     VariantInit(&tempLeft);
03463     VariantInit(&tempRight);
03464 
03465     /* Handle VT_DISPATCH by storing and taking address of returned value */
03466     if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
03467     {
03468         hres = VARIANT_FetchDispatchValue(left, &tempLeft);
03469         if (FAILED(hres)) goto end;
03470         left = &tempLeft;
03471     }
03472     if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
03473     {
03474         hres = VARIANT_FetchDispatchValue(right, &tempRight);
03475         if (FAILED(hres)) goto end;
03476         right = &tempRight;
03477     }
03478 
03479     lvt = V_VT(left)&VT_TYPEMASK;
03480     rvt = V_VT(right)&VT_TYPEMASK;
03481 
03482     /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out.
03483        Same for any input variant type > VT_I8 */
03484     if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK ||
03485         lvt > VT_I8 || rvt > VT_I8) {
03486         hres = DISP_E_BADVARTYPE;
03487         goto end;
03488     }
03489 
03490     /* Determine the variant type to coerce to. */
03491     if (coerce[lvt] > coerce[rvt]) {
03492         resvt = prio2vt[coerce[lvt]];
03493         tvt = prio2vt[coerce[rvt]];
03494     } else {
03495         resvt = prio2vt[coerce[rvt]];
03496         tvt = prio2vt[coerce[lvt]];
03497     }
03498 
03499     /* Special cases where the result variant type is defined by both
03500        input variants and not only that with the highest priority */
03501     if (resvt == VT_R4 && (tvt == VT_CY || tvt == VT_I8 || tvt == VT_I4))
03502         resvt = VT_R8;
03503     if (lvt == VT_EMPTY && rvt == VT_EMPTY)
03504         resvt = VT_I2;
03505 
03506     /* For overflow detection use the biggest compatible type for the
03507        multiplication */
03508     switch (resvt) {
03509         case VT_ERROR:
03510             hres = DISP_E_BADVARTYPE;
03511             goto end;
03512         case VT_NULL:
03513             hres = S_OK;
03514             V_VT(result) = VT_NULL;
03515             goto end;
03516         case VT_UI1:
03517         case VT_I2:
03518         case VT_I4:
03519         case VT_I8:
03520             tvt = VT_I8;
03521             break;
03522         case VT_R4:
03523             tvt = VT_R8;
03524             break;
03525         default:
03526             tvt = resvt;
03527     }
03528 
03529     /* Now coerce the variants */
03530     hres = VariantChangeType(&lv, left, 0, tvt);
03531     if (FAILED(hres))
03532         goto end;
03533     hres = VariantChangeType(&rv, right, 0, tvt);
03534     if (FAILED(hres))
03535         goto end;
03536 
03537     /* Do the math */
03538     hres = S_OK;
03539     V_VT(&tv) = tvt;
03540     V_VT(result) = resvt;
03541     switch (tvt) {
03542         case VT_DECIMAL:
03543             hres = VarDecMul(&V_DECIMAL(&lv), &V_DECIMAL(&rv),
03544                              &V_DECIMAL(result));
03545             goto end;
03546         case VT_CY:
03547             hres = VarCyMul(V_CY(&lv), V_CY(&rv), &V_CY(result));
03548             goto end;
03549         case VT_I8:
03550             /* Overflow detection */
03551             r8res = (double)V_I8(&lv) * (double)V_I8(&rv);
03552             if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) {
03553                 V_VT(result) = VT_R8;
03554                 V_R8(result) = r8res;
03555                 goto end;
03556             } else
03557                 V_I8(&tv) = V_I8(&lv) * V_I8(&rv);
03558             break;
03559         case VT_R8:
03560             /* FIXME: overflow detection */
03561             V_R8(&tv) = V_R8(&lv) * V_R8(&rv);
03562             break;
03563         default:
03564             ERR("We shouldn't get here! tvt = %d!\n", tvt);
03565             break;
03566     }
03567     if (resvt != tvt) {
03568         while ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) {
03569             /* Overflow! Change to the vartype with the next higher priority.
03570                With one exception: I4 ==> R8 even if it would fit in I8 */
03571             if (resvt == VT_I4)
03572                 resvt = VT_R8;
03573             else
03574                 resvt = prio2vt[coerce[resvt] + 1];
03575         }
03576     } else
03577         hres = VariantCopy(result, &tv);
03578 
03579 end:
03580     if (hres != S_OK) {
03581         V_VT(result) = VT_EMPTY;
03582         V_I4(result) = 0;       /* No V_EMPTY */
03583     }
03584     VariantClear(&lv);
03585     VariantClear(&rv);
03586     VariantClear(&tv);
03587     VariantClear(&tempLeft);
03588     VariantClear(&tempRight);
03589     TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
03590     return hres;
03591 }
03592 
03593 /**********************************************************************
03594  *              VarDiv [OLEAUT32.143]
03595  *
03596  * Divides one variant with another.
03597  *
03598  * PARAMS
03599  *  left    [I] First variant
03600  *  right   [I] Second variant
03601  *  result  [O] Result variant
03602  *
03603  * RETURNS
03604  *  Success: S_OK.
03605  *  Failure: An HRESULT error code indicating the error.
03606  */
03607 HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
03608 {
03609     HRESULT hres = S_OK;
03610     VARTYPE resvt = VT_EMPTY;
03611     VARTYPE leftvt,rightvt;
03612     VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
03613     VARIANT lv,rv;
03614     VARIANT tempLeft, tempRight;
03615 
03616     VariantInit(&tempLeft);
03617     VariantInit(&tempRight);
03618     VariantInit(&lv);
03619     VariantInit(&rv);
03620 
03621     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
03622           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
03623 
03624     /* Handle VT_DISPATCH by storing and taking address of returned value */
03625     if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
03626     {
03627         hres = VARIANT_FetchDispatchValue(left, &tempLeft);
03628         if (FAILED(hres)) goto end;
03629         left = &tempLeft;
03630     }
03631     if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
03632     {
03633         hres = VARIANT_FetchDispatchValue(right, &tempRight);
03634         if (FAILED(hres)) goto end;
03635         right = &tempRight;
03636     }
03637 
03638     leftvt = V_VT(left)&VT_TYPEMASK;
03639     rightvt = V_VT(right)&VT_TYPEMASK;
03640     leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
03641     rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
03642 
03643     if (leftExtraFlags != rightExtraFlags)
03644     {
03645         hres = DISP_E_BADVARTYPE;
03646         goto end;
03647     }
03648     ExtraFlags = leftExtraFlags;
03649 
03650     /* Native VarDiv always returns an error when using extra flags */
03651     if (ExtraFlags != 0)
03652     {
03653         hres = DISP_E_BADVARTYPE;
03654         goto end;
03655     }
03656 
03657     /* Determine return type */
03658     if (!(rightvt == VT_EMPTY))
03659     {
03660         if (leftvt == VT_NULL || rightvt == VT_NULL)
03661         {
03662             V_VT(result) = VT_NULL;
03663             hres = S_OK;
03664             goto end;
03665         }
03666         else if (leftvt == VT_DECIMAL || rightvt == VT_DECIMAL)
03667             resvt = VT_DECIMAL;
03668         else if (leftvt == VT_I8 || rightvt == VT_I8 ||
03669             leftvt == VT_CY || rightvt == VT_CY ||
03670             leftvt == VT_DATE || rightvt == VT_DATE ||
03671             leftvt == VT_I4 || rightvt == VT_I4 ||
03672             leftvt == VT_BSTR || rightvt == VT_BSTR ||
03673             leftvt == VT_I2 || rightvt == VT_I2 ||
03674             leftvt == VT_BOOL || rightvt == VT_BOOL ||
03675             leftvt == VT_R8 || rightvt == VT_R8 ||
03676             leftvt == VT_UI1 || rightvt == VT_UI1)
03677         {
03678             if ((leftvt == VT_UI1 && rightvt == VT_R4) ||
03679                 (leftvt == VT_R4 && rightvt == VT_UI1))
03680                 resvt = VT_R4;
03681             else if ((leftvt == VT_R4 && (rightvt == VT_BOOL ||
03682                 rightvt == VT_I2)) || (rightvt == VT_R4 &&
03683                 (leftvt == VT_BOOL || leftvt == VT_I2)))
03684                 resvt = VT_R4;
03685             else
03686                 resvt = VT_R8;
03687         }
03688         else if (leftvt == VT_R4 || rightvt == VT_R4)
03689             resvt = VT_R4;
03690     }
03691     else if (leftvt == VT_NULL && rightvt == VT_EMPTY)
03692     {
03693         V_VT(result) = VT_NULL;
03694         hres = S_OK;
03695         goto end;
03696     }
03697     else
03698     {
03699         hres = DISP_E_BADVARTYPE;
03700         goto end;
03701     }
03702 
03703     /* coerce to the result type */
03704     hres = VariantChangeType(&lv, left, 0, resvt);
03705     if (hres != S_OK) goto end;
03706 
03707     hres = VariantChangeType(&rv, right, 0, resvt);
03708     if (hres != S_OK) goto end;
03709 
03710     /* do the math */
03711     V_VT(result) = resvt;
03712     switch (resvt)
03713     {
03714     case VT_R4:
03715     if (V_R4(&lv) == 0.0 && V_R4(&rv) == 0.0)
03716     {
03717         hres = DISP_E_OVERFLOW;
03718         V_VT(result) = VT_EMPTY;
03719     }
03720     else if (V_R4(&rv) == 0.0)
03721     {
03722         hres = DISP_E_DIVBYZERO;
03723         V_VT(result) = VT_EMPTY;
03724     }
03725     else
03726         V_R4(result) = V_R4(&lv) / V_R4(&rv);
03727     break;
03728     case VT_R8:
03729     if (V_R8(&lv) == 0.0 && V_R8(&rv) == 0.0)
03730     {
03731         hres = DISP_E_OVERFLOW;
03732         V_VT(result) = VT_EMPTY;
03733     }
03734     else if (V_R8(&rv) == 0.0)
03735     {
03736         hres = DISP_E_DIVBYZERO;
03737         V_VT(result) = VT_EMPTY;
03738     }
03739     else
03740         V_R8(result) = V_R8(&lv) / V_R8(&rv);
03741     break;
03742     case VT_DECIMAL:
03743     hres = VarDecDiv(&(V_DECIMAL(&lv)), &(V_DECIMAL(&rv)), &(V_DECIMAL(result)));
03744     break;
03745     }
03746 
03747 end:
03748     VariantClear(&lv);
03749     VariantClear(&rv);
03750     VariantClear(&tempLeft);
03751     VariantClear(&tempRight);
03752     TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
03753     return hres;
03754 }
03755 
03756 /**********************************************************************
03757  *              VarSub [OLEAUT32.159]
03758  *
03759  * Subtract two variants.
03760  *
03761  * PARAMS
03762  *  left    [I] First variant
03763  *  right   [I] Second variant
03764  *  result  [O] Result variant
03765  *
03766  * RETURNS
03767  *  Success: S_OK.
03768  *  Failure: An HRESULT error code indicating the error.
03769  */
03770 HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
03771 {
03772     HRESULT hres = S_OK;
03773     VARTYPE resvt = VT_EMPTY;
03774     VARTYPE leftvt,rightvt;
03775     VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
03776     VARIANT lv,rv;
03777     VARIANT tempLeft, tempRight;
03778 
03779     VariantInit(&lv);
03780     VariantInit(&rv);
03781     VariantInit(&tempLeft);
03782     VariantInit(&tempRight);
03783 
03784     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
03785           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
03786 
03787     if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH &&
03788         (V_VT(left)&(~VT_TYPEMASK)) == 0 &&
03789         (V_VT(right) & VT_TYPEMASK) != VT_NULL)
03790     {
03791         if (NULL == V_DISPATCH(left)) {
03792             if ((V_VT(right) & VT_TYPEMASK) >= VT_INT_PTR)
03793                 hres = DISP_E_BADVARTYPE;
03794             else if ((V_VT(right) & VT_TYPEMASK) >= VT_UI8 &&
03795                 (V_VT(right) & VT_TYPEMASK) < VT_RECORD)
03796                 hres = DISP_E_BADVARTYPE;
03797             else switch (V_VT(right) & VT_TYPEMASK)
03798             {
03799             case VT_VARIANT:
03800             case VT_UNKNOWN:
03801             case 15:
03802             case VT_I1:
03803             case VT_UI2:
03804             case VT_UI4:
03805                 hres = DISP_E_BADVARTYPE;
03806             }
03807             if (FAILED(hres)) goto end;
03808         }
03809         hres = VARIANT_FetchDispatchValue(left, &tempLeft);
03810         if (FAILED(hres)) goto end;
03811         left = &tempLeft;
03812     }
03813     if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH &&
03814         (V_VT(right)&(~VT_TYPEMASK)) == 0 &&
03815         (V_VT(left) & VT_TYPEMASK) != VT_NULL)
03816     {
03817         if (NULL == V_DISPATCH(right))
03818         {
03819             if ((V_VT(left) & VT_TYPEMASK) >= VT_INT_PTR)
03820                 hres = DISP_E_BADVARTYPE;
03821             else if ((V_VT(left) & VT_TYPEMASK) >= VT_UI8 &&
03822                 (V_VT(left) & VT_TYPEMASK) < VT_RECORD)
03823                 hres = DISP_E_BADVARTYPE;
03824             else switch (V_VT(left) & VT_TYPEMASK)
03825             {
03826             case VT_VARIANT:
03827             case VT_UNKNOWN:
03828             case 15:
03829             case VT_I1:
03830             case VT_UI2:
03831             case VT_UI4:
03832                 hres = DISP_E_BADVARTYPE;
03833             }
03834             if (FAILED(hres)) goto end;
03835         }
03836         hres = VARIANT_FetchDispatchValue(right, &tempRight);
03837         if (FAILED(hres)) goto end;
03838         right = &tempRight;
03839     }
03840 
03841     leftvt = V_VT(left)&VT_TYPEMASK;
03842     rightvt = V_VT(right)&VT_TYPEMASK;
03843     leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
03844     rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
03845 
03846     if (leftExtraFlags != rightExtraFlags)
03847     {
03848         hres = DISP_E_BADVARTYPE;
03849         goto end;
03850     }
03851     ExtraFlags = leftExtraFlags;
03852 
03853     /* determine return type and return code */
03854     /* All extra flags produce errors */
03855     if (ExtraFlags == (VT_VECTOR|VT_BYREF|VT_RESERVED) ||
03856         ExtraFlags == (VT_VECTOR|VT_RESERVED) ||
03857         ExtraFlags == (VT_VECTOR|VT_BYREF) ||
03858         ExtraFlags == (VT_BYREF|VT_RESERVED) ||
03859         ExtraFlags == VT_VECTOR ||
03860         ExtraFlags == VT_BYREF ||
03861         ExtraFlags == VT_RESERVED)
03862     {
03863         hres = DISP_E_BADVARTYPE;
03864         goto end;
03865     }
03866     else if (ExtraFlags >= VT_ARRAY)
03867     {
03868         hres = DISP_E_TYPEMISMATCH;
03869         goto end;
03870     }
03871     /* Native VarSub cannot handle: VT_I1, VT_UI2, VT_UI4,
03872        VT_INT, VT_UINT and VT_UI8. Tested with WinXP */
03873     else if (leftvt == VT_CLSID || rightvt == VT_CLSID ||
03874         leftvt == VT_VARIANT || rightvt == VT_VARIANT ||
03875         leftvt == VT_I1 || rightvt == VT_I1 ||
03876         leftvt == VT_UI2 || rightvt == VT_UI2 ||
03877         leftvt == VT_UI4 || rightvt == VT_UI4 ||
03878         leftvt == VT_UI8 || rightvt == VT_UI8 ||
03879         leftvt == VT_INT || rightvt == VT_INT ||
03880         leftvt == VT_UINT || rightvt == VT_UINT ||
03881         leftvt == VT_UNKNOWN || rightvt == VT_UNKNOWN ||
03882         leftvt == VT_RECORD || rightvt == VT_RECORD)
03883     {
03884         if (leftvt == VT_RECORD && rightvt == VT_I8)
03885             hres = DISP_E_TYPEMISMATCH;
03886         else if (leftvt < VT_UI1 && rightvt == VT_RECORD)
03887             hres = DISP_E_TYPEMISMATCH;
03888         else if (leftvt >= VT_UI1 && rightvt == VT_RECORD)
03889             hres = DISP_E_TYPEMISMATCH;
03890         else if (leftvt == VT_RECORD && rightvt <= VT_UI1)
03891             hres = DISP_E_TYPEMISMATCH;
03892         else if (leftvt == VT_RECORD && rightvt > VT_UI1)
03893             hres = DISP_E_BADVARTYPE;
03894         else
03895             hres = DISP_E_BADVARTYPE;
03896         goto end;
03897     }
03898     /*  The following flags/types are invalid for left variant */
03899     else if (!((leftvt <= VT_LPWSTR || leftvt == VT_RECORD ||
03900         leftvt == VT_CLSID) && leftvt != (VARTYPE)15 /* undefined vt */ &&
03901         (leftvt < VT_VOID || leftvt > VT_LPWSTR)))
03902     {
03903         hres = DISP_E_BADVARTYPE;
03904         goto end;
03905     }
03906     /*  The following flags/types are invalid for right variant */
03907     else if (!((rightvt <= VT_LPWSTR || rightvt == VT_RECORD ||
03908         rightvt == VT_CLSID) && rightvt != (VARTYPE)15 /* undefined vt */ &&
03909         (rightvt < VT_VOID || rightvt > VT_LPWSTR)))
03910     {
03911         hres = DISP_E_BADVARTYPE;
03912         goto end;
03913     }
03914     else if ((leftvt == VT_NULL && rightvt == VT_DISPATCH) ||
03915         (leftvt == VT_DISPATCH && rightvt == VT_NULL))
03916         resvt = VT_NULL;
03917     else if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH ||
03918         leftvt == VT_ERROR || rightvt == VT_ERROR)
03919     {
03920         hres = DISP_E_TYPEMISMATCH;
03921         goto end;
03922     }
03923     else if (leftvt == VT_NULL || rightvt == VT_NULL)
03924         resvt = VT_NULL;
03925     else if ((leftvt == VT_EMPTY && rightvt == VT_BSTR) ||
03926         (leftvt == VT_DATE && rightvt == VT_DATE) ||
03927         (leftvt == VT_BSTR && rightvt == VT_EMPTY) ||
03928         (leftvt == VT_BSTR && rightvt == VT_BSTR))
03929         resvt = VT_R8;
03930     else if (leftvt == VT_DECIMAL || rightvt == VT_DECIMAL)
03931         resvt = VT_DECIMAL;
03932     else if (leftvt == VT_DATE || rightvt == VT_DATE)
03933         resvt = VT_DATE;
03934     else if (leftvt == VT_CY || rightvt == VT_CY)
03935         resvt = VT_CY;
03936     else if (leftvt == VT_R8 || rightvt == VT_R8)
03937         resvt = VT_R8;
03938     else if (leftvt == VT_BSTR || rightvt == VT_BSTR)
03939         resvt = VT_R8;
03940     else if (leftvt == VT_R4 || rightvt == VT_R4)
03941     {
03942         if (leftvt == VT_I4 || rightvt == VT_I4 ||
03943             leftvt == VT_I8 || rightvt == VT_I8)
03944             resvt = VT_R8;
03945         else
03946             resvt = VT_R4;
03947     }
03948     else if (leftvt == VT_I8 || rightvt == VT_I8)
03949         resvt = VT_I8;
03950     else if (leftvt == VT_I4 || rightvt == VT_I4)
03951         resvt = VT_I4;
03952     else if (leftvt == VT_I2 || rightvt == VT_I2 ||
03953         leftvt == VT_BOOL || rightvt == VT_BOOL ||
03954         (leftvt == VT_EMPTY && rightvt == VT_EMPTY))
03955         resvt = VT_I2;
03956     else if (leftvt == VT_UI1 || rightvt == VT_UI1)
03957         resvt = VT_UI1;
03958     else
03959     {
03960         hres = DISP_E_TYPEMISMATCH;
03961         goto end;
03962     }
03963 
03964     /* coerce to the result type */
03965     if (leftvt == VT_BSTR && rightvt == VT_DATE)
03966         hres = VariantChangeType(&lv, left, 0, VT_R8);
03967     else
03968         hres = VariantChangeType(&lv, left, 0, resvt);
03969     if (hres != S_OK) goto end;
03970     if (leftvt == VT_DATE && rightvt == VT_BSTR)
03971         hres = VariantChangeType(&rv, right, 0, VT_R8);
03972     else
03973         hres = VariantChangeType(&rv, right, 0, resvt);
03974     if (hres != S_OK) goto end;
03975 
03976     /* do the math */
03977     V_VT(result) = resvt;
03978     switch (resvt)
03979     {
03980     case VT_NULL:
03981     break;
03982     case VT_DATE:
03983     V_DATE(result) = V_DATE(&lv) - V_DATE(&rv);
03984     break;
03985     case VT_CY:
03986     hres = VarCySub(V_CY(&lv), V_CY(&rv), &(V_CY(result)));
03987     break;
03988     case VT_R4:
03989     V_R4(result) = V_R4(&lv) - V_R4(&rv);
03990     break;
03991     case VT_I8:
03992     V_I8(result) = V_I8(&lv) - V_I8(&rv);
03993     break;
03994     case VT_I4:
03995     V_I4(result) = V_I4(&lv) - V_I4(&rv);
03996     break;
03997     case VT_I2:
03998     V_I2(result) = V_I2(&lv) - V_I2(&rv);
03999     break;
04000     case VT_I1:
04001     V_I1(result) = V_I1(&lv) - V_I1(&rv);
04002     break;
04003     case VT_UI1:
04004     V_UI1(result) = V_UI2(&lv) - V_UI1(&rv);
04005     break;
04006     case VT_R8:
04007     V_R8(result) = V_R8(&lv) - V_R8(&rv);
04008     break;
04009     case VT_DECIMAL:
04010     hres = VarDecSub(&(V_DECIMAL(&lv)), &(V_DECIMAL(&rv)), &(V_DECIMAL(result)));
04011     break;
04012     }
04013 
04014 end:
04015     VariantClear(&lv);
04016     VariantClear(&rv);
04017     VariantClear(&tempLeft);
04018     VariantClear(&tempRight);
04019     TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
04020     return hres;
04021 }
04022 
04023 
04024 /**********************************************************************
04025  *              VarOr [OLEAUT32.157]
04026  *
04027  * Perform a logical or (OR) operation on two variants.
04028  *
04029  * PARAMS
04030  *  pVarLeft  [I] First variant
04031  *  pVarRight [I] Variant to OR with pVarLeft
04032  *  pVarOut   [O] Destination for OR result
04033  *
04034  * RETURNS
04035  *  Success: S_OK. pVarOut contains the result of the operation with its type
04036  *           taken from the table listed under VarXor().
04037  *  Failure: An HRESULT error code indicating the error.
04038  *
04039  * NOTES
04040  *  See the Notes section of VarXor() for further information.
04041  */
04042 HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
04043 {
04044     VARTYPE vt = VT_I4;
04045     VARIANT varLeft, varRight, varStr;
04046     HRESULT hRet;
04047     VARIANT tempLeft, tempRight;
04048 
04049     VariantInit(&tempLeft);
04050     VariantInit(&tempRight);
04051     VariantInit(&varLeft);
04052     VariantInit(&varRight);
04053     VariantInit(&varStr);
04054 
04055     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
04056           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
04057           debugstr_VF(pVarRight), pVarOut);
04058 
04059     /* Handle VT_DISPATCH by storing and taking address of returned value */
04060     if ((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH)
04061     {
04062         hRet = VARIANT_FetchDispatchValue(pVarLeft, &tempLeft);
04063         if (FAILED(hRet)) goto VarOr_Exit;
04064         pVarLeft = &tempLeft;
04065     }
04066     if ((V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH)
04067     {
04068         hRet = VARIANT_FetchDispatchValue(pVarRight, &tempRight);
04069         if (FAILED(hRet)) goto VarOr_Exit;
04070         pVarRight = &tempRight;
04071     }
04072 
04073     if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
04074         V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
04075         V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH ||
04076         V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD)
04077     {
04078         hRet = DISP_E_BADVARTYPE;
04079         goto VarOr_Exit;
04080     }
04081 
04082     V_VT(&varLeft) = V_VT(&varRight) = V_VT(&varStr) = VT_EMPTY;
04083 
04084     if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
04085     {
04086         /* NULL OR Zero is NULL, NULL OR value is value */
04087         if (V_VT(pVarLeft) == VT_NULL)
04088             pVarLeft = pVarRight; /* point to the non-NULL var */
04089 
04090         V_VT(pVarOut) = VT_NULL;
04091         V_I4(pVarOut) = 0;
04092 
04093         switch (V_VT(pVarLeft))
04094         {
04095         case VT_DATE: case VT_R8:
04096             if (V_R8(pVarLeft))
04097                 goto VarOr_AsEmpty;
04098             hRet = S_OK;
04099             goto VarOr_Exit;
04100         case VT_BOOL:
04101             if (V_BOOL(pVarLeft))
04102                 *pVarOut = *pVarLeft;
04103             hRet = S_OK;
04104             goto VarOr_Exit;
04105          case VT_I2: case VT_UI2:
04106             if (V_I2(pVarLeft))
04107                 goto VarOr_AsEmpty;
04108             hRet = S_OK;
04109             goto VarOr_Exit;
04110         case VT_I1:
04111             if (V_I1(pVarLeft))
04112                 goto VarOr_AsEmpty;
04113             hRet = S_OK;
04114             goto VarOr_Exit;
04115         case VT_UI1:
04116             if (V_UI1(pVarLeft))
04117                 *pVarOut = *pVarLeft;
04118             hRet = S_OK;
04119             goto VarOr_Exit;
04120         case VT_R4:
04121             if (V_R4(pVarLeft))
04122                 goto VarOr_AsEmpty;
04123             hRet = S_OK;
04124             goto VarOr_Exit;
04125         case VT_I4: case VT_UI4: case VT_INT: case VT_UINT:
04126             if (V_I4(pVarLeft))
04127                 goto VarOr_AsEmpty;
04128             hRet = S_OK;
04129             goto VarOr_Exit;
04130         case VT_CY:
04131             if (V_CY(pVarLeft).int64)
04132                 goto VarOr_AsEmpty;
04133             hRet = S_OK;
04134             goto VarOr_Exit;
04135         case VT_I8: case VT_UI8:
04136             if (V_I8(pVarLeft))
04137                 goto VarOr_AsEmpty;
04138             hRet = S_OK;
04139             goto VarOr_Exit;
04140         case VT_DECIMAL:
04141             if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft)))
04142                 goto VarOr_AsEmpty;
04143             hRet = S_OK;
04144             goto VarOr_Exit;
04145         case VT_BSTR:
04146         {
04147             VARIANT_BOOL b;
04148 
04149             if (!V_BSTR(pVarLeft))
04150             {
04151                 hRet = DISP_E_BADVARTYPE;
04152                 goto VarOr_Exit;
04153             }
04154 
04155             hRet = VarBoolFromStr(V_BSTR(pVarLeft), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
04156             if (SUCCEEDED(hRet) && b)
04157             {
04158                 V_VT(pVarOut) = VT_BOOL;
04159                 V_BOOL(pVarOut) = b;
04160             }
04161             goto VarOr_Exit;
04162         }
04163         case VT_NULL: case VT_EMPTY:
04164             V_VT(pVarOut) = VT_NULL;
04165             hRet = S_OK;
04166             goto VarOr_Exit;
04167         default:
04168             hRet = DISP_E_BADVARTYPE;
04169             goto VarOr_Exit;
04170         }
04171     }
04172 
04173     if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY)
04174     {
04175         if (V_VT(pVarLeft) == VT_EMPTY)
04176             pVarLeft = pVarRight; /* point to the non-EMPTY var */
04177 
04178 VarOr_AsEmpty:
04179         /* Since one argument is empty (0), OR'ing it with the other simply
04180          * gives the others value (as 0|x => x). So just convert the other
04181          * argument to the required result type.
04182          */
04183         switch (V_VT(pVarLeft))
04184         {
04185         case VT_BSTR:
04186             if (!V_BSTR(pVarLeft))
04187             {
04188                 hRet = DISP_E_BADVARTYPE;
04189                 goto VarOr_Exit;
04190             }
04191 
04192             hRet = VariantCopy(&varStr, pVarLeft);
04193             if (FAILED(hRet))
04194                 goto VarOr_Exit;
04195             pVarLeft = &varStr;
04196             hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
04197             if (FAILED(hRet))
04198                 goto VarOr_Exit;
04199             /* Fall Through ... */
04200         case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2:
04201             V_VT(pVarOut) = VT_I2;
04202             break;
04203         case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8:
04204         case VT_I1: case VT_UI2: case VT_I4: case VT_UI4:
04205         case VT_INT: case VT_UINT: case VT_UI8:
04206             V_VT(pVarOut) = VT_I4;
04207             break;
04208         case VT_I8:
04209             V_VT(pVarOut) = VT_I8;
04210             break;
04211         default:
04212             hRet = DISP_E_BADVARTYPE;
04213             goto VarOr_Exit;
04214         }
04215         hRet = VariantCopy(&varLeft, pVarLeft);
04216         if (FAILED(hRet))
04217             goto VarOr_Exit;
04218         pVarLeft = &varLeft;
04219         hRet = VariantChangeType(pVarOut, pVarLeft, 0, V_VT(pVarOut));
04220         goto VarOr_Exit;
04221     }
04222 
04223     if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL)
04224     {
04225         V_VT(pVarOut) = VT_BOOL;
04226         V_BOOL(pVarOut) = V_BOOL(pVarLeft) | V_BOOL(pVarRight);
04227         hRet = S_OK;
04228         goto VarOr_Exit;
04229     }
04230 
04231     if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1)
04232     {
04233         V_VT(pVarOut) = VT_UI1;
04234         V_UI1(pVarOut) = V_UI1(pVarLeft) | V_UI1(pVarRight);
04235         hRet = S_OK;
04236         goto VarOr_Exit;
04237     }
04238 
04239     if (V_VT(pVarLeft) == VT_BSTR)
04240     {
04241         hRet = VariantCopy(&varStr, pVarLeft);
04242         if (FAILED(hRet))
04243             goto VarOr_Exit;
04244         pVarLeft = &varStr;
04245         hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
04246         if (FAILED(hRet))
04247             goto VarOr_Exit;
04248     }
04249 
04250     if (V_VT(pVarLeft) == VT_BOOL &&
04251         (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_BSTR))
04252     {
04253         vt = VT_BOOL;
04254     }
04255     else if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 ||
04256         V_VT(pVarLeft) == VT_I2 || V_VT(pVarLeft) == VT_BSTR) &&
04257         (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 ||
04258         V_VT(pVarRight) == VT_I2 || V_VT(pVarRight) == VT_BSTR))
04259     {
04260         vt = VT_I2;
04261     }
04262     else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8)
04263     {
04264         if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
04265         {
04266             hRet = DISP_E_TYPEMISMATCH;
04267             goto VarOr_Exit;
04268         }
04269         vt = VT_I8;
04270     }
04271 
04272     hRet = VariantCopy(&varLeft, pVarLeft);
04273     if (FAILED(hRet))
04274         goto VarOr_Exit;
04275 
04276     hRet = VariantCopy(&varRight, pVarRight);
04277     if (FAILED(hRet))
04278         goto VarOr_Exit;
04279 
04280     if (vt == VT_I4 && V_VT(&varLeft) == VT_UI4)
04281         V_VT(&varLeft) = VT_I4; /* Don't overflow */
04282     else
04283     {
04284         double d;
04285 
04286         if (V_VT(&varLeft) == VT_BSTR &&
04287             FAILED(VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d)))
04288             hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, VT_BOOL);
04289         if (SUCCEEDED(hRet) && V_VT(&varLeft) != vt)
04290             hRet = VariantChangeType(&varLeft, &varLeft, 0, vt);
04291         if (FAILED(hRet))
04292             goto VarOr_Exit;
04293     }
04294 
04295     if (vt == VT_I4 && V_VT(&varRight) == VT_UI4)
04296         V_VT(&varRight) = VT_I4; /* Don't overflow */
04297     else
04298     {
04299         double d;
04300 
04301         if (V_VT(&varRight) == VT_BSTR &&
04302             FAILED(VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d)))
04303             hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, VT_BOOL);
04304         if (SUCCEEDED(hRet) && V_VT(&varRight) != vt)
04305             hRet = VariantChangeType(&varRight, &varRight, 0, vt);
04306         if (FAILED(hRet))
04307             goto VarOr_Exit;
04308     }
04309 
04310     V_VT(pVarOut) = vt;
04311     if (vt == VT_I8)
04312     {
04313         V_I8(pVarOut) = V_I8(&varLeft) | V_I8(&varRight);
04314     }
04315     else if (vt == VT_I4)
04316     {
04317         V_I4(pVarOut) = V_I4(&varLeft) | V_I4(&varRight);
04318     }
04319     else
04320     {
04321         V_I2(pVarOut) = V_I2(&varLeft) | V_I2(&varRight);
04322     }
04323 
04324 VarOr_Exit:
04325     VariantClear(&varStr);
04326     VariantClear(&varLeft);
04327     VariantClear(&varRight);
04328     VariantClear(&tempLeft);
04329     VariantClear(&tempRight);
04330     return hRet;
04331 }
04332 
04333 /**********************************************************************
04334  * VarAbs [OLEAUT32.168]
04335  *
04336  * Convert a variant to its absolute value.
04337  *
04338  * PARAMS
04339  *  pVarIn  [I] Source variant
04340  *  pVarOut [O] Destination for converted value
04341  *
04342  * RETURNS
04343  *  Success: S_OK. pVarOut contains the absolute value of pVarIn.
04344  *  Failure: An HRESULT error code indicating the error.
04345  *
04346  * NOTES
04347  *  - This function does not process by-reference variants.
04348  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
04349  *    according to the following table:
04350  *| Input Type       Output Type
04351  *| ----------       -----------
04352  *| VT_BOOL          VT_I2
04353  *| VT_BSTR          VT_R8
04354  *| (All others)     Unchanged
04355  */
04356 HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut)
04357 {
04358     VARIANT varIn;
04359     HRESULT hRet = S_OK;
04360     VARIANT temp;
04361 
04362     VariantInit(&temp);
04363 
04364     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
04365           debugstr_VF(pVarIn), pVarOut);
04366 
04367     /* Handle VT_DISPATCH by storing and taking address of returned value */
04368     if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
04369     {
04370         hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
04371         if (FAILED(hRet)) goto VarAbs_Exit;
04372         pVarIn = &temp;
04373     }
04374 
04375     if (V_ISARRAY(pVarIn) || V_VT(pVarIn) == VT_UNKNOWN ||
04376         V_VT(pVarIn) == VT_DISPATCH || V_VT(pVarIn) == VT_RECORD ||
04377         V_VT(pVarIn) == VT_ERROR)
04378     {
04379         hRet = DISP_E_TYPEMISMATCH;
04380         goto VarAbs_Exit;
04381     }
04382     *pVarOut = *pVarIn; /* Shallow copy the value, and invert it if needed */
04383 
04384 #define ABS_CASE(typ,min) \
04385     case VT_##typ: if (V_##typ(pVarIn) == min) hRet = DISP_E_OVERFLOW; \
04386                   else if (V_##typ(pVarIn) < 0) V_##typ(pVarOut) = -V_##typ(pVarIn); \
04387                   break
04388 
04389     switch (V_VT(pVarIn))
04390     {
04391     ABS_CASE(I1,I1_MIN);
04392     case VT_BOOL:
04393         V_VT(pVarOut) = VT_I2;
04394         /* BOOL->I2, Fall through ... */
04395     ABS_CASE(I2,I2_MIN);
04396     case VT_INT:
04397     ABS_CASE(I4,I4_MIN);
04398     ABS_CASE(I8,I8_MIN);
04399     ABS_CASE(R4,R4_MIN);
04400     case VT_BSTR:
04401         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
04402         if (FAILED(hRet))
04403             break;
04404         V_VT(pVarOut) = VT_R8;
04405         pVarIn = &varIn;
04406         /* Fall through ... */
04407     case VT_DATE:
04408     ABS_CASE(R8,R8_MIN);
04409     case VT_CY:
04410         hRet = VarCyAbs(V_CY(pVarIn), & V_CY(pVarOut));
04411         break;
04412     case VT_DECIMAL:
04413         DEC_SIGN(&V_DECIMAL(pVarOut)) &= ~DECIMAL_NEG;
04414         break;
04415     case VT_UI1:
04416     case VT_UI2:
04417     case VT_UINT:
04418     case VT_UI4:
04419     case VT_UI8:
04420         /* No-Op */
04421         break;
04422     case VT_EMPTY:
04423         V_VT(pVarOut) = VT_I2;
04424     case VT_NULL:
04425         V_I2(pVarOut) = 0;
04426         break;
04427     default:
04428         hRet = DISP_E_BADVARTYPE;
04429     }
04430 
04431 VarAbs_Exit:
04432     VariantClear(&temp);
04433     return hRet;
04434 }
04435 
04436 /**********************************************************************
04437  *              VarFix [OLEAUT32.169]
04438  *
04439  * Truncate a variants value to a whole number.
04440  *
04441  * PARAMS
04442  *  pVarIn  [I] Source variant
04443  *  pVarOut [O] Destination for converted value
04444  *
04445  * RETURNS
04446  *  Success: S_OK. pVarOut contains the converted value.
04447  *  Failure: An HRESULT error code indicating the error.
04448  *
04449  * NOTES
04450  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
04451  *    according to the following table:
04452  *| Input Type       Output Type
04453  *| ----------       -----------
04454  *|  VT_BOOL          VT_I2
04455  *|  VT_EMPTY         VT_I2
04456  *|  VT_BSTR          VT_R8
04457  *|  All Others       Unchanged
04458  *  - The difference between this function and VarInt() is that VarInt() rounds
04459  *    negative numbers away from 0, while this function rounds them towards zero.
04460  */
04461 HRESULT WINAPI VarFix(LPVARIANT pVarIn, LPVARIANT pVarOut)
04462 {
04463     HRESULT hRet = S_OK;
04464     VARIANT temp;
04465 
04466     VariantInit(&temp);
04467 
04468     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
04469           debugstr_VF(pVarIn), pVarOut);
04470 
04471     /* Handle VT_DISPATCH by storing and taking address of returned value */
04472     if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
04473     {
04474         hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
04475         if (FAILED(hRet)) goto VarFix_Exit;
04476         pVarIn = &temp;
04477     }
04478     V_VT(pVarOut) = V_VT(pVarIn);
04479 
04480     switch (V_VT(pVarIn))
04481     {
04482     case VT_UI1:
04483         V_UI1(pVarOut) = V_UI1(pVarIn);
04484         break;
04485     case VT_BOOL:
04486         V_VT(pVarOut) = VT_I2;
04487         /* Fall through */
04488      case VT_I2:
04489         V_I2(pVarOut) = V_I2(pVarIn);
04490         break;
04491      case VT_I4:
04492         V_I4(pVarOut) = V_I4(pVarIn);
04493         break;
04494      case VT_I8:
04495         V_I8(pVarOut) = V_I8(pVarIn);
04496         break;
04497     case VT_R4:
04498         if (V_R4(pVarIn) < 0.0f)
04499             V_R4(pVarOut) = (float)ceil(V_R4(pVarIn));
04500         else
04501             V_R4(pVarOut) = (float)floor(V_R4(pVarIn));
04502         break;
04503     case VT_BSTR:
04504         V_VT(pVarOut) = VT_R8;
04505         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
04506         pVarIn = pVarOut;
04507         /* Fall through */
04508     case VT_DATE:
04509     case VT_R8:
04510         if (V_R8(pVarIn) < 0.0)
04511             V_R8(pVarOut) = ceil(V_R8(pVarIn));
04512         else
04513             V_R8(pVarOut) = floor(V_R8(pVarIn));
04514         break;
04515     case VT_CY:
04516         hRet = VarCyFix(V_CY(pVarIn), &V_CY(pVarOut));
04517         break;
04518     case VT_DECIMAL:
04519         hRet = VarDecFix(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
04520         break;
04521     case VT_EMPTY:
04522         V_VT(pVarOut) = VT_I2;
04523         V_I2(pVarOut) = 0;
04524         break;
04525     case VT_NULL:
04526         /* No-Op */
04527         break;
04528     default:
04529         if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
04530             FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
04531             hRet = DISP_E_BADVARTYPE;
04532         else
04533             hRet = DISP_E_TYPEMISMATCH;
04534     }
04535 VarFix_Exit:
04536     if (FAILED(hRet))
04537       V_VT(pVarOut) = VT_EMPTY;
04538     VariantClear(&temp);
04539 
04540     return hRet;
04541 }
04542 
04543 /**********************************************************************
04544  *              VarInt [OLEAUT32.172]
04545  *
04546  * Truncate a variants value to a whole number.
04547  *
04548  * PARAMS
04549  *  pVarIn  [I] Source variant
04550  *  pVarOut [O] Destination for converted value
04551  *
04552  * RETURNS
04553  *  Success: S_OK. pVarOut contains the converted value.
04554  *  Failure: An HRESULT error code indicating the error.
04555  *
04556  * NOTES
04557  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
04558  *    according to the following table:
04559  *| Input Type       Output Type
04560  *| ----------       -----------
04561  *|  VT_BOOL          VT_I2
04562  *|  VT_EMPTY         VT_I2
04563  *|  VT_BSTR          VT_R8
04564  *|  All Others       Unchanged
04565  *  - The difference between this function and VarFix() is that VarFix() rounds
04566  *    negative numbers towards 0, while this function rounds them away from zero.
04567  */
04568 HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut)
04569 {
04570     HRESULT hRet = S_OK;
04571     VARIANT temp;
04572 
04573     VariantInit(&temp);
04574 
04575     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
04576           debugstr_VF(pVarIn), pVarOut);
04577 
04578     /* Handle VT_DISPATCH by storing and taking address of returned value */
04579     if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
04580     {
04581         hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
04582         if (FAILED(hRet)) goto VarInt_Exit;
04583         pVarIn = &temp;
04584     }
04585     V_VT(pVarOut) = V_VT(pVarIn);
04586 
04587     switch (V_VT(pVarIn))
04588     {
04589     case VT_R4:
04590         V_R4(pVarOut) = (float)floor(V_R4(pVarIn));
04591         break;
04592     case VT_BSTR:
04593         V_VT(pVarOut) = VT_R8;
04594         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
04595         pVarIn = pVarOut;
04596         /* Fall through */
04597     case VT_DATE:
04598     case VT_R8:
04599         V_R8(pVarOut) = floor(V_R8(pVarIn));
04600         break;
04601     case VT_CY:
04602         hRet = VarCyInt(V_CY(pVarIn), &V_CY(pVarOut));
04603         break;
04604     case VT_DECIMAL:
04605         hRet = VarDecInt(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
04606         break;
04607     default:
04608         hRet = VarFix(pVarIn, pVarOut);
04609     }
04610 VarInt_Exit:
04611     VariantClear(&temp);
04612 
04613     return hRet;
04614 }
04615 
04616 /**********************************************************************
04617  *              VarXor [OLEAUT32.167]
04618  *
04619  * Perform a logical exclusive-or (XOR) operation on two variants.
04620  *
04621  * PARAMS
04622  *  pVarLeft  [I] First variant
04623  *  pVarRight [I] Variant to XOR with pVarLeft
04624  *  pVarOut   [O] Destination for XOR result
04625  *
04626  * RETURNS
04627  *  Success: S_OK. pVarOut contains the result of the operation with its type
04628  *           taken from the table below).
04629  *  Failure: An HRESULT error code indicating the error.
04630  *
04631  * NOTES
04632  *  - Neither pVarLeft or pVarRight are modified by this function.
04633  *  - This function does not process by-reference variants.
04634  *  - Input types of VT_BSTR may be numeric strings or boolean text.
04635  *  - The type of result stored in pVarOut depends on the types of pVarLeft
04636  *    and pVarRight, and will be one of VT_UI1, VT_I2, VT_I4, VT_I8, VT_BOOL,
04637  *    or VT_NULL if the function succeeds.
04638  *  - Type promotion is inconsistent and as a result certain combinations of
04639  *    values will return DISP_E_OVERFLOW even when they could be represented.
04640  *    This matches the behaviour of native oleaut32.
04641  */
04642 HRESULT WINAPI VarXor(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
04643 {
04644     VARTYPE vt;
04645     VARIANT varLeft, varRight;
04646     VARIANT tempLeft, tempRight;
04647     double d;
04648     HRESULT hRet;
04649 
04650     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
04651           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
04652           debugstr_VF(pVarRight), pVarOut);
04653 
04654     if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
04655         V_VT(pVarLeft) > VT_UINT || V_VT(pVarRight) > VT_UINT ||
04656         V_VT(pVarLeft) == VT_VARIANT || V_VT(pVarRight) == VT_VARIANT ||
04657         V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
04658         V_VT(pVarLeft) == (VARTYPE)15 || V_VT(pVarRight) == (VARTYPE)15 ||
04659         V_VT(pVarLeft) == VT_ERROR || V_VT(pVarRight) == VT_ERROR)
04660         return DISP_E_BADVARTYPE;
04661 
04662     if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
04663     {
04664         /* NULL XOR anything valid is NULL */
04665         V_VT(pVarOut) = VT_NULL;
04666         return S_OK;
04667     }
04668 
04669     VariantInit(&tempLeft);
04670     VariantInit(&tempRight);
04671 
04672     /* Handle VT_DISPATCH by storing and taking address of returned value */
04673     if ((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH)
04674     {
04675         hRet = VARIANT_FetchDispatchValue(pVarLeft, &tempLeft);
04676         if (FAILED(hRet)) goto VarXor_Exit;
04677         pVarLeft = &tempLeft;
04678     }
04679     if ((V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH)
04680     {
04681         hRet = VARIANT_FetchDispatchValue(pVarRight, &tempRight);
04682         if (FAILED(hRet)) goto VarXor_Exit;
04683         pVarRight = &tempRight;
04684     }
04685 
04686     /* Copy our inputs so we don't disturb anything */
04687     V_VT(&varLeft) = V_VT(&varRight) = VT_EMPTY;
04688 
04689     hRet = VariantCopy(&varLeft, pVarLeft);
04690     if (FAILED(hRet))
04691         goto VarXor_Exit;
04692 
04693     hRet = VariantCopy(&varRight, pVarRight);
04694     if (FAILED(hRet))
04695         goto VarXor_Exit;
04696 
04697     /* Try any strings first as numbers, then as VT_BOOL */
04698     if (V_VT(&varLeft) == VT_BSTR)
04699     {
04700         hRet = VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d);
04701         hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL,
04702                                  FAILED(hRet) ? VT_BOOL : VT_I4);
04703         if (FAILED(hRet))
04704             goto VarXor_Exit;
04705     }
04706 
04707     if (V_VT(&varRight) == VT_BSTR)
04708     {
04709         hRet = VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d);
04710         hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL,
04711                                  FAILED(hRet) ? VT_BOOL : VT_I4);
04712         if (FAILED(hRet))
04713             goto VarXor_Exit;
04714     }
04715 
04716     /* Determine the result type */
04717     if (V_VT(&varLeft) == VT_I8 || V_VT(&varRight) == VT_I8)
04718     {
04719         if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
04720         {
04721             hRet = DISP_E_TYPEMISMATCH;
04722             goto VarXor_Exit;
04723         }
04724         vt = VT_I8;
04725     }
04726     else
04727     {
04728         switch ((V_VT(&varLeft) << 16) | V_VT(&varRight))
04729         {
04730         case (VT_BOOL  << 16) | VT_BOOL:
04731             vt = VT_BOOL;
04732             break;
04733         case (VT_UI1   << 16) | VT_UI1:
04734             vt = VT_UI1;
04735             break;
04736         case (VT_EMPTY << 16) | VT_EMPTY:
04737         case (VT_EMPTY << 16) | VT_UI1:
04738         case (VT_EMPTY << 16) | VT_I2:
04739         case (VT_EMPTY << 16) | VT_BOOL:
04740         case (VT_UI1   << 16) | VT_EMPTY:
04741         case (VT_UI1   << 16) | VT_I2:
04742         case (VT_UI1   << 16) | VT_BOOL:
04743         case (VT_I2    << 16) | VT_EMPTY:
04744         case (VT_I2    << 16) | VT_UI1:
04745         case (VT_I2    << 16) | VT_I2:
04746         case (VT_I2    << 16) | VT_BOOL:
04747         case (VT_BOOL  << 16) | VT_EMPTY:
04748         case (VT_BOOL  << 16) | VT_UI1:
04749         case (VT_BOOL  << 16) | VT_I2:
04750             vt = VT_I2;
04751             break;
04752         default:
04753             vt = VT_I4;
04754             break;
04755         }
04756     }
04757 
04758     /* VT_UI4 does not overflow */
04759     if (vt != VT_I8)
04760     {
04761         if (V_VT(&varLeft) == VT_UI4)
04762             V_VT(&varLeft) = VT_I4;
04763         if (V_VT(&varRight) == VT_UI4)
04764             V_VT(&varRight) = VT_I4;
04765     }
04766 
04767     /* Convert our input copies to the result type */
04768     if (V_VT(&varLeft) != vt)
04769         hRet = VariantChangeType(&varLeft, &varLeft, 0, vt);
04770     if (FAILED(hRet))
04771         goto VarXor_Exit;
04772 
04773     if (V_VT(&varRight) != vt)
04774         hRet = VariantChangeType(&varRight, &varRight, 0, vt);
04775     if (FAILED(hRet))
04776         goto VarXor_Exit;
04777 
04778     V_VT(pVarOut) = vt;
04779 
04780     /* Calculate the result */
04781     switch (vt)
04782     {
04783     case VT_I8:
04784         V_I8(pVarOut) = V_I8(&varLeft) ^ V_I8(&varRight);
04785         break;
04786     case VT_I4:
04787         V_I4(pVarOut) = V_I4(&varLeft) ^ V_I4(&varRight);
04788         break;
04789     case VT_BOOL:
04790     case VT_I2:
04791         V_I2(pVarOut) = V_I2(&varLeft) ^ V_I2(&varRight);
04792         break;
04793     case VT_UI1:
04794         V_UI1(pVarOut) = V_UI1(&varLeft) ^ V_UI1(&varRight);
04795         break;
04796     }
04797 
04798 VarXor_Exit:
04799     VariantClear(&varLeft);
04800     VariantClear(&varRight);
04801     VariantClear(&tempLeft);
04802     VariantClear(&tempRight);
04803     return hRet;
04804 }
04805 
04806 /**********************************************************************
04807  *              VarEqv [OLEAUT32.172]
04808  *
04809  * Determine if two variants contain the same value.
04810  *
04811  * PARAMS
04812  *  pVarLeft  [I] First variant to compare
04813  *  pVarRight [I] Variant to compare to pVarLeft
04814  *  pVarOut   [O] Destination for comparison result
04815  *
04816  * RETURNS
04817  *  Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE
04818  *           if equivalent or non-zero otherwise.
04819  *  Failure: An HRESULT error code indicating the error.
04820  *
04821  * NOTES
04822  *  - This function simply calls VarXor() on pVarLeft and pVarRight and inverts
04823  *    the result.
04824  */
04825 HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
04826 {
04827     HRESULT hRet;
04828 
04829     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
04830           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
04831           debugstr_VF(pVarRight), pVarOut);
04832 
04833     hRet = VarXor(pVarLeft, pVarRight, pVarOut);
04834     if (SUCCEEDED(hRet))
04835     {
04836         if (V_VT(pVarOut) == VT_I8)
04837             V_I8(pVarOut) = ~V_I8(pVarOut);
04838         else
04839             V_UI4(pVarOut) = ~V_UI4(pVarOut);
04840     }
04841     return hRet;
04842 }
04843 
04844 /**********************************************************************
04845  *              VarNeg [OLEAUT32.173]
04846  *
04847  * Negate the value of a variant.
04848  *
04849  * PARAMS
04850  *  pVarIn  [I] Source variant
04851  *  pVarOut [O] Destination for converted value
04852  *
04853  * RETURNS
04854  *  Success: S_OK. pVarOut contains the converted value.
04855  *  Failure: An HRESULT error code indicating the error.
04856  *
04857  * NOTES
04858  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
04859  *    according to the following table:
04860  *| Input Type       Output Type
04861  *| ----------       -----------
04862  *|  VT_EMPTY         VT_I2
04863  *|  VT_UI1           VT_I2
04864  *|  VT_BOOL          VT_I2
04865  *|  VT_BSTR          VT_R8
04866  *|  All Others       Unchanged (unless promoted)
04867  *  - Where the negated value of a variant does not fit in its base type, the type
04868  *    is promoted according to the following table:
04869  *| Input Type       Promoted To
04870  *| ----------       -----------
04871  *|   VT_I2            VT_I4
04872  *|   VT_I4            VT_R8
04873  *|   VT_I8            VT_R8
04874  *  - The native version of this function returns DISP_E_BADVARTYPE for valid
04875  *    variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH
04876  *    for types which are not valid. Since this is in contravention of the
04877  *    meaning of those error codes and unlikely to be relied on by applications,
04878  *    this implementation returns errors consistent with the other high level
04879  *    variant math functions.
04880  */
04881 HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut)
04882 {
04883     HRESULT hRet = S_OK;
04884     VARIANT temp;
04885 
04886     VariantInit(&temp);
04887 
04888     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
04889           debugstr_VF(pVarIn), pVarOut);
04890 
04891     /* Handle VT_DISPATCH by storing and taking address of returned value */
04892     if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
04893     {
04894         hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
04895         if (FAILED(hRet)) goto VarNeg_Exit;
04896         pVarIn = &temp;
04897     }
04898     V_VT(pVarOut) = V_VT(pVarIn);
04899 
04900     switch (V_VT(pVarIn))
04901     {
04902     case VT_UI1:
04903         V_VT(pVarOut) = VT_I2;
04904         V_I2(pVarOut) = -V_UI1(pVarIn);
04905         break;
04906     case VT_BOOL:
04907         V_VT(pVarOut) = VT_I2;
04908         /* Fall through */
04909     case VT_I2:
04910         if (V_I2(pVarIn) == I2_MIN)
04911         {
04912             V_VT(pVarOut) = VT_I4;
04913             V_I4(pVarOut) = -(int)V_I2(pVarIn);
04914         }
04915         else
04916             V_I2(pVarOut) = -V_I2(pVarIn);
04917         break;
04918     case VT_I4:
04919         if (V_I4(pVarIn) == I4_MIN)
04920         {
04921             V_VT(pVarOut) = VT_R8;
04922             V_R8(pVarOut) = -(double)V_I4(pVarIn);
04923         }
04924         else
04925             V_I4(pVarOut) = -V_I4(pVarIn);
04926         break;
04927     case VT_I8:
04928         if (V_I8(pVarIn) == I8_MIN)
04929         {
04930             V_VT(pVarOut) = VT_R8;
04931             hRet = VarR8FromI8(V_I8(pVarIn), &V_R8(pVarOut));
04932             V_R8(pVarOut) *= -1.0;
04933         }
04934         else
04935             V_I8(pVarOut) = -V_I8(pVarIn);
04936         break;
04937     case VT_R4:
04938         V_R4(pVarOut) = -V_R4(pVarIn);
04939         break;
04940     case VT_DATE:
04941     case VT_R8:
04942         V_R8(pVarOut) = -V_R8(pVarIn);
04943         break;
04944     case VT_CY:
04945         hRet = VarCyNeg(V_CY(pVarIn), &V_CY(pVarOut));
04946         break;
04947     case VT_DECIMAL:
04948         hRet = VarDecNeg(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
04949         break;
04950     case VT_BSTR:
04951         V_VT(pVarOut) = VT_R8;
04952         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
04953         V_R8(pVarOut) = -V_R8(pVarOut);
04954         break;
04955     case VT_EMPTY:
04956         V_VT(pVarOut) = VT_I2;
04957         V_I2(pVarOut) = 0;
04958         break;
04959     case VT_NULL:
04960         /* No-Op */
04961         break;
04962     default:
04963         if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
04964             FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
04965             hRet = DISP_E_BADVARTYPE;
04966         else
04967             hRet = DISP_E_TYPEMISMATCH;
04968     }
04969 VarNeg_Exit:
04970     if (FAILED(hRet))
04971       V_VT(pVarOut) = VT_EMPTY;
04972     VariantClear(&temp);
04973 
04974     return hRet;
04975 }
04976 
04977 /**********************************************************************
04978  *              VarNot [OLEAUT32.174]
04979  *
04980  * Perform a not operation on a variant.
04981  *
04982  * PARAMS
04983  *  pVarIn  [I] Source variant
04984  *  pVarOut [O] Destination for converted value
04985  *
04986  * RETURNS
04987  *  Success: S_OK. pVarOut contains the converted value.
04988  *  Failure: An HRESULT error code indicating the error.
04989  *
04990  * NOTES
04991  *  - Strictly speaking, this function performs a bitwise ones complement
04992  *    on the variants value (after possibly converting to VT_I4, see below).
04993  *    This only behaves like a boolean not operation if the value in
04994  *    pVarIn is either VARIANT_TRUE or VARIANT_FALSE and the type is signed.
04995  *  - To perform a genuine not operation, convert the variant to a VT_BOOL
04996  *    before calling this function.
04997  *  - This function does not process by-reference variants.
04998  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
04999  *    according to the following table:
05000  *| Input Type       Output Type
05001  *| ----------       -----------
05002  *| VT_EMPTY         VT_I2
05003  *| VT_R4            VT_I4
05004  *| VT_R8            VT_I4
05005  *| VT_BSTR          VT_I4
05006  *| VT_DECIMAL       VT_I4
05007  *| VT_CY            VT_I4
05008  *| (All others)     Unchanged
05009  */
05010 HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut)
05011 {
05012     VARIANT varIn;
05013     HRESULT hRet = S_OK;
05014     VARIANT temp;
05015 
05016     VariantInit(&temp);
05017 
05018     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
05019           debugstr_VF(pVarIn), pVarOut);
05020 
05021     /* Handle VT_DISPATCH by storing and taking address of returned value */
05022     if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
05023     {
05024         hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
05025         if (FAILED(hRet)) goto VarNot_Exit;
05026         pVarIn = &temp;
05027     }
05028 
05029     V_VT(pVarOut) = V_VT(pVarIn);
05030 
05031     switch (V_VT(pVarIn))
05032     {
05033     case VT_I1:
05034         V_I4(pVarOut) = ~V_I1(pVarIn);
05035         V_VT(pVarOut) = VT_I4;
05036         break;
05037     case VT_UI1: V_UI1(pVarOut) = ~V_UI1(pVarIn); break;
05038     case VT_BOOL:
05039     case VT_I2:  V_I2(pVarOut) = ~V_I2(pVarIn); break;
05040     case VT_UI2:
05041         V_I4(pVarOut) = ~V_UI2(pVarIn);
05042         V_VT(pVarOut) = VT_I4;
05043         break;
05044     case VT_DECIMAL:
05045         hRet = VarI4FromDec(&V_DECIMAL(pVarIn), &V_I4(&varIn));
05046         if (FAILED(hRet))
05047             break;
05048         pVarIn = &varIn;
05049         /* Fall through ... */
05050     case VT_INT:
05051         V_VT(pVarOut) = VT_I4;
05052         /* Fall through ... */
05053     case VT_I4:  V_I4(pVarOut) = ~V_I4(pVarIn); break;
05054     case VT_UINT:
05055     case VT_UI4:
05056         V_I4(pVarOut) = ~V_UI4(pVarIn);
05057         V_VT(pVarOut) = VT_I4;
05058         break;
05059     case VT_I8:  V_I8(pVarOut) = ~V_I8(pVarIn); break;
05060     case VT_UI8:
05061         V_I4(pVarOut) = ~V_UI8(pVarIn);
05062         V_VT(pVarOut) = VT_I4;
05063         break;
05064     case VT_R4:
05065         hRet = VarI4FromR4(V_R4(pVarIn), &V_I4(pVarOut));
05066         V_I4(pVarOut) = ~V_I4(pVarOut);
05067         V_VT(pVarOut) = VT_I4;
05068         break;
05069     case VT_BSTR:
05070         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
05071         if (FAILED(hRet))
05072             break;
05073         pVarIn = &varIn;
05074         /* Fall through ... */
05075     case VT_DATE:
05076     case VT_R8:
05077         hRet = VarI4FromR8(V_R8(pVarIn), &V_I4(pVarOut));
05078         V_I4(pVarOut) = ~V_I4(pVarOut);
05079         V_VT(pVarOut) = VT_I4;
05080         break;
05081     case VT_CY:
05082         hRet = VarI4FromCy(V_CY(pVarIn), &V_I4(pVarOut));
05083         V_I4(pVarOut) = ~V_I4(pVarOut);
05084         V_VT(pVarOut) = VT_I4;
05085         break;
05086     case VT_EMPTY:
05087         V_I2(pVarOut) = ~0;
05088         V_VT(pVarOut) = VT_I2;
05089         break;
05090     case VT_NULL:
05091         /* No-Op */
05092         break;
05093     default:
05094         if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
05095             FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
05096             hRet = DISP_E_BADVARTYPE;
05097         else
05098             hRet = DISP_E_TYPEMISMATCH;
05099     }
05100 VarNot_Exit:
05101     if (FAILED(hRet))
05102       V_VT(pVarOut) = VT_EMPTY;
05103     VariantClear(&temp);
05104 
05105     return hRet;
05106 }
05107 
05108 /**********************************************************************
05109  *              VarRound [OLEAUT32.175]
05110  *
05111  * Perform a round operation on a variant.
05112  *
05113  * PARAMS
05114  *  pVarIn  [I] Source variant
05115  *  deci    [I] Number of decimals to round to
05116  *  pVarOut [O] Destination for converted value
05117  *
05118  * RETURNS
05119  *  Success: S_OK. pVarOut contains the converted value.
05120  *  Failure: An HRESULT error code indicating the error.
05121  *
05122  * NOTES
05123  *  - Floating point values are rounded to the desired number of decimals.
05124  *  - Some integer types are just copied to the return variable.
05125  *  - Some other integer types are not handled and fail.
05126  */
05127 HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut)
05128 {
05129     VARIANT varIn;
05130     HRESULT hRet = S_OK;
05131     float factor;
05132     VARIANT temp;
05133 
05134     VariantInit(&temp);
05135 
05136     TRACE("(%p->(%s%s),%d)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), deci);
05137 
05138     /* Handle VT_DISPATCH by storing and taking address of returned value */
05139     if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
05140     {
05141         hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
05142         if (FAILED(hRet)) goto VarRound_Exit;
05143         pVarIn = &temp;
05144     }
05145 
05146     switch (V_VT(pVarIn))
05147     {
05148     /* cases that fail on windows */
05149     case VT_I1:
05150     case VT_I8:
05151     case VT_UI2:
05152     case VT_UI4:
05153     hRet = DISP_E_BADVARTYPE;
05154     break;
05155 
05156     /* cases just copying in to out */
05157     case VT_UI1:
05158     V_VT(pVarOut) = V_VT(pVarIn);
05159     V_UI1(pVarOut) = V_UI1(pVarIn);
05160     break;
05161     case VT_I2:
05162     V_VT(pVarOut) = V_VT(pVarIn);
05163     V_I2(pVarOut) = V_I2(pVarIn);
05164     break;
05165     case VT_I4:
05166     V_VT(pVarOut) = V_VT(pVarIn);
05167     V_I4(pVarOut) = V_I4(pVarIn);
05168     break;
05169     case VT_NULL:
05170     V_VT(pVarOut) = V_VT(pVarIn);
05171     /* value unchanged */
05172     break;
05173 
05174     /* cases that change type */
05175     case VT_EMPTY:
05176     V_VT(pVarOut) = VT_I2;
05177     V_I2(pVarOut) = 0;
05178     break;
05179     case VT_BOOL:
05180     V_VT(pVarOut) = VT_I2;
05181     V_I2(pVarOut) = V_BOOL(pVarIn);
05182     break;
05183     case VT_BSTR:
05184     hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
05185     if (FAILED(hRet))
05186         break;
05187     V_VT(&varIn)=VT_R8;
05188     pVarIn = &varIn;
05189     /* Fall through ... */
05190 
05191     /* cases we need to do math */
05192     case VT_R8:
05193     if (V_R8(pVarIn)>0) {
05194         V_R8(pVarOut)=floor(V_R8(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
05195     } else {
05196         V_R8(pVarOut)=ceil(V_R8(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
05197     }
05198     V_VT(pVarOut) = V_VT(pVarIn);
05199     break;
05200     case VT_R4:
05201     if (V_R4(pVarIn)>0) {
05202         V_R4(pVarOut)=floor(V_R4(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
05203     } else {
05204         V_R4(pVarOut)=ceil(V_R4(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
05205     }
05206     V_VT(pVarOut) = V_VT(pVarIn);
05207     break;
05208     case VT_DATE:
05209     if (V_DATE(pVarIn)>0) {
05210         V_DATE(pVarOut)=floor(V_DATE(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
05211     } else {
05212         V_DATE(pVarOut)=ceil(V_DATE(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
05213     }
05214     V_VT(pVarOut) = V_VT(pVarIn);
05215     break;
05216     case VT_CY:
05217     if (deci>3)
05218         factor=1;
05219     else
05220         factor=pow(10, 4-deci);
05221 
05222     if (V_CY(pVarIn).int64>0) {
05223         V_CY(pVarOut).int64=floor(V_CY(pVarIn).int64/factor)*factor;
05224     } else {
05225         V_CY(pVarOut).int64=ceil(V_CY(pVarIn).int64/factor)*factor;
05226     }
05227     V_VT(pVarOut) = V_VT(pVarIn);
05228     break;
05229 
05230     /* cases we don't know yet */
05231     default:
05232     FIXME("unimplemented part, V_VT(pVarIn) == 0x%X, deci == %d\n",
05233         V_VT(pVarIn) & VT_TYPEMASK, deci);
05234     hRet = DISP_E_BADVARTYPE;
05235     }
05236 VarRound_Exit:
05237     if (FAILED(hRet))
05238       V_VT(pVarOut) = VT_EMPTY;
05239     VariantClear(&temp);
05240 
05241     TRACE("returning 0x%08x (%s%s),%f\n", hRet, debugstr_VT(pVarOut),
05242     debugstr_VF(pVarOut), (V_VT(pVarOut) == VT_R4) ? V_R4(pVarOut) :
05243     (V_VT(pVarOut) == VT_R8) ? V_R8(pVarOut) : 0);
05244 
05245     return hRet;
05246 }
05247 
05248 /**********************************************************************
05249  *              VarIdiv [OLEAUT32.153]
05250  *
05251  * Converts input variants to integers and divides them. 
05252  *
05253  * PARAMS
05254  *  left     [I] Left hand variant
05255  *  right    [I] Right hand variant
05256  *  result   [O] Destination for quotient
05257  *
05258  * RETURNS
05259  *  Success: S_OK.  result contains the quotient.
05260  *  Failure: An HRESULT error code indicating the error.
05261  *
05262  * NOTES
05263  *  If either expression is null, null is returned, as per MSDN
05264  */
05265 HRESULT WINAPI VarIdiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
05266 {
05267     HRESULT hres = S_OK;
05268     VARTYPE resvt = VT_EMPTY;
05269     VARTYPE leftvt,rightvt;
05270     VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
05271     VARIANT lv,rv;
05272     VARIANT tempLeft, tempRight;
05273 
05274     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
05275           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
05276 
05277     VariantInit(&lv);
05278     VariantInit(&rv);
05279     VariantInit(&tempLeft);
05280     VariantInit(&tempRight);
05281 
05282     leftvt = V_VT(left)&VT_TYPEMASK;
05283     rightvt = V_VT(right)&VT_TYPEMASK;
05284     leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
05285     rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
05286 
05287     if (leftExtraFlags != rightExtraFlags)
05288     {
05289         hres = DISP_E_BADVARTYPE;
05290         goto end;
05291     }
05292     ExtraFlags = leftExtraFlags;
05293 
05294     /* Native VarIdiv always returns an error when using extra
05295      * flags or if the variant combination is I8 and INT.
05296      */
05297     if ((leftvt == VT_I8 && rightvt == VT_INT) ||
05298         (leftvt == VT_INT && rightvt == VT_I8) ||
05299         (rightvt == VT_EMPTY && leftvt != VT_NULL) ||
05300         ExtraFlags != 0)
05301     {
05302         hres = DISP_E_BADVARTYPE;
05303         goto end;
05304     }
05305 
05306     /* Determine variant type */
05307     else if (leftvt == VT_NULL || rightvt == VT_NULL)
05308     {
05309         V_VT(result) = VT_NULL;
05310         hres = S_OK;
05311         goto end;
05312     }
05313     else if (leftvt == VT_I8 || rightvt == VT_I8)
05314         resvt = VT_I8;
05315     else if (leftvt == VT_I4 || rightvt == VT_I4 ||
05316         leftvt == VT_INT || rightvt == VT_INT ||
05317         leftvt == VT_UINT || rightvt == VT_UINT ||
05318         leftvt == VT_UI8 || rightvt == VT_UI8 ||
05319         leftvt == VT_UI4 || rightvt == VT_UI4 ||
05320         leftvt == VT_UI2 || rightvt == VT_UI2 ||
05321         leftvt == VT_I1 || rightvt == VT_I1 ||
05322         leftvt == VT_BSTR || rightvt == VT_BSTR ||
05323         leftvt == VT_DATE || rightvt == VT_DATE ||
05324         leftvt == VT_CY || rightvt == VT_CY ||
05325         leftvt == VT_DECIMAL || rightvt == VT_DECIMAL ||
05326         leftvt == VT_R8 || rightvt == VT_R8 ||
05327         leftvt == VT_R4 || rightvt == VT_R4)
05328         resvt = VT_I4;
05329     else if (leftvt == VT_I2 || rightvt == VT_I2 ||
05330         leftvt == VT_BOOL || rightvt == VT_BOOL ||
05331         leftvt == VT_EMPTY)
05332         resvt = VT_I2;
05333     else if (leftvt == VT_UI1 || rightvt == VT_UI1)
05334         resvt = VT_UI1;
05335     else
05336     {
05337         hres = DISP_E_BADVARTYPE;
05338         goto end;
05339     }
05340 
05341     /* coerce to the result type */
05342     hres = VariantChangeType(&lv, left, 0, resvt);
05343     if (hres != S_OK) goto end;
05344     hres = VariantChangeType(&rv, right, 0, resvt);
05345     if (hres != S_OK) goto end;
05346 
05347     /* do the math */
05348     V_VT(result) = resvt;
05349     switch (resvt)
05350     {
05351     case VT_UI1:
05352     if (V_UI1(&rv) == 0)
05353     {
05354         hres = DISP_E_DIVBYZERO;
05355         V_VT(result) = VT_EMPTY;
05356     }
05357     else
05358         V_UI1(result) = V_UI1(&lv) / V_UI1(&rv);
05359     break;
05360     case VT_I2:
05361     if (V_I2(&rv) == 0)
05362     {
05363         hres = DISP_E_DIVBYZERO;
05364         V_VT(result) = VT_EMPTY;
05365     }
05366     else
05367         V_I2(result) = V_I2(&lv) / V_I2(&rv);
05368     break;
05369     case VT_I4:
05370     if (V_I4(&rv) == 0)
05371     {
05372         hres = DISP_E_DIVBYZERO;
05373         V_VT(result) = VT_EMPTY;
05374     }
05375     else
05376         V_I4(result) = V_I4(&lv) / V_I4(&rv);
05377     break;
05378     case VT_I8:
05379     if (V_I8(&rv) == 0)
05380     {
05381         hres = DISP_E_DIVBYZERO;
05382         V_VT(result) = VT_EMPTY;
05383     }
05384     else
05385         V_I8(result) = V_I8(&lv) / V_I8(&rv);
05386     break;
05387     default:
05388         FIXME("Couldn't integer divide variant types %d,%d\n",
05389             leftvt,rightvt);
05390     }
05391 
05392 end:
05393     VariantClear(&lv);
05394     VariantClear(&rv);
05395     VariantClear(&tempLeft);
05396     VariantClear(&tempRight);
05397 
05398     return hres;
05399 }
05400 
05401 
05402 /**********************************************************************
05403  *              VarMod [OLEAUT32.155]
05404  *
05405  * Perform the modulus operation of the right hand variant on the left
05406  *
05407  * PARAMS
05408  *  left     [I] Left hand variant
05409  *  right    [I] Right hand variant
05410  *  result   [O] Destination for converted value
05411  *
05412  * RETURNS
05413  *  Success: S_OK. result contains the remainder.
05414  *  Failure: An HRESULT error code indicating the error.
05415  *
05416  * NOTE:
05417  *   If an error occurs the type of result will be modified but the value will not be.
05418  *   Doesn't support arrays or any special flags yet.
05419  */
05420 HRESULT WINAPI VarMod(LPVARIANT left, LPVARIANT right, LPVARIANT result)
05421 {
05422     BOOL         lOk        = TRUE;
05423     HRESULT      rc         = E_FAIL;
05424     int          resT = 0;
05425     VARIANT      lv,rv;
05426     VARIANT tempLeft, tempRight;
05427 
05428     VariantInit(&tempLeft);
05429     VariantInit(&tempRight);
05430     VariantInit(&lv);
05431     VariantInit(&rv);
05432 
05433     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
05434           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
05435 
05436     /* Handle VT_DISPATCH by storing and taking address of returned value */
05437     if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
05438     {
05439         rc = VARIANT_FetchDispatchValue(left, &tempLeft);
05440         if (FAILED(rc)) goto end;
05441         left = &tempLeft;
05442     }
05443     if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
05444     {
05445         rc = VARIANT_FetchDispatchValue(right, &tempRight);
05446         if (FAILED(rc)) goto end;
05447         right = &tempRight;
05448     }
05449 
05450     /* check for invalid inputs */
05451     lOk = TRUE;
05452     switch (V_VT(left) & VT_TYPEMASK) {
05453     case VT_BOOL :
05454     case VT_I1   :
05455     case VT_I2   :
05456     case VT_I4   :
05457     case VT_I8   :
05458     case VT_INT  :
05459     case VT_UI1  :
05460     case VT_UI2  :
05461     case VT_UI4  :
05462     case VT_UI8  :
05463     case VT_UINT :
05464     case VT_R4   :
05465     case VT_R8   :
05466     case VT_CY   :
05467     case VT_EMPTY:
05468     case VT_DATE :
05469     case VT_BSTR :
05470     case VT_DECIMAL:
05471       break;
05472     case VT_VARIANT:
05473     case VT_UNKNOWN:
05474       V_VT(result) = VT_EMPTY;
05475       rc = DISP_E_TYPEMISMATCH;
05476       goto end;
05477     case VT_ERROR:
05478       rc = DISP_E_TYPEMISMATCH;
05479       goto end;
05480     case VT_RECORD:
05481       V_VT(result) = VT_EMPTY;
05482       rc = DISP_E_TYPEMISMATCH;
05483       goto end;
05484     case VT_NULL:
05485       break;
05486     default:
05487       V_VT(result) = VT_EMPTY;
05488       rc = DISP_E_BADVARTYPE;
05489       goto end;
05490     }
05491 
05492 
05493     switch (V_VT(right) & VT_TYPEMASK) {
05494     case VT_BOOL :
05495     case VT_I1   :
05496     case VT_I2   :
05497     case VT_I4   :
05498     case VT_I8   :
05499       if((V_VT(left) == VT_INT) && (V_VT(right) == VT_I8))
05500       {
05501     V_VT(result) = VT_EMPTY;
05502         rc = DISP_E_TYPEMISMATCH;
05503         goto end;
05504       }
05505     case VT_INT  :
05506       if((V_VT(right) == VT_INT) && (V_VT(left) == VT_I8))
05507       {
05508     V_VT(result) = VT_EMPTY;
05509         rc = DISP_E_TYPEMISMATCH;
05510         goto end;
05511       }
05512     case VT_UI1  :
05513     case VT_UI2  :
05514     case VT_UI4  :
05515     case VT_UI8  :
05516     case VT_UINT :
05517     case VT_R4   :
05518     case VT_R8   :
05519     case VT_CY   :
05520       if(V_VT(left) == VT_EMPTY)
05521       {
05522     V_VT(result) = VT_I4;
05523         rc = S_OK;
05524         goto end;
05525       }
05526     case VT_EMPTY:
05527     case VT_DATE :
05528     case VT_DECIMAL:
05529       if(V_VT(left) == VT_ERROR)
05530       {
05531     V_VT(result) = VT_EMPTY;
05532         rc = DISP_E_TYPEMISMATCH;
05533         goto end;
05534       }
05535     case VT_BSTR:
05536       if(V_VT(left) == VT_NULL)
05537       {
05538     V_VT(result) = VT_NULL;
05539         rc = S_OK;
05540         goto end;
05541       }
05542       break;
05543 
05544     case VT_VOID:
05545       V_VT(result) = VT_EMPTY;
05546       rc = DISP_E_BADVARTYPE;
05547       goto end;
05548     case VT_NULL:
05549       if(V_VT(left) == VT_VOID)
05550       {
05551     V_VT(result) = VT_EMPTY;
05552         rc = DISP_E_BADVARTYPE;
05553       } else if((V_VT(left) == VT_NULL) || (V_VT(left) == VT_EMPTY) || (V_VT(left) == VT_ERROR) ||
05554         lOk)
05555       {
05556         V_VT(result) = VT_NULL;
05557         rc = S_OK;
05558       } else
05559       {
05560     V_VT(result) = VT_NULL;
05561         rc = DISP_E_BADVARTYPE;
05562       }
05563       goto end;
05564     case VT_VARIANT:
05565     case VT_UNKNOWN:
05566       V_VT(result) = VT_EMPTY;
05567       rc = DISP_E_TYPEMISMATCH;
05568       goto end;
05569     case VT_ERROR:
05570       rc = DISP_E_TYPEMISMATCH;
05571       goto end;
05572     case VT_RECORD:
05573       if((V_VT(left) == 15) || ((V_VT(left) >= 24) && (V_VT(left) <= 35)) || !lOk)
05574       {
05575     V_VT(result) = VT_EMPTY;
05576         rc = DISP_E_BADVARTYPE;
05577       } else
05578       {
05579     V_VT(result) = VT_EMPTY;
05580         rc = DISP_E_TYPEMISMATCH;
05581       }
05582       goto end;
05583     default:
05584       V_VT(result) = VT_EMPTY;
05585       rc = DISP_E_BADVARTYPE;
05586       goto end;
05587     }
05588 
05589     /* determine the result type */
05590     if((V_VT(left) == VT_I8)        || (V_VT(right) == VT_I8))   resT = VT_I8;
05591     else if((V_VT(left) == VT_UI1)  && (V_VT(right) == VT_BOOL)) resT = VT_I2;
05592     else if((V_VT(left) == VT_UI1)  && (V_VT(right) == VT_UI1))  resT = VT_UI1;
05593     else if((V_VT(left) == VT_UI1)  && (V_VT(right) == VT_I2))   resT = VT_I2;
05594     else if((V_VT(left) == VT_I2)   && (V_VT(right) == VT_BOOL)) resT = VT_I2;
05595     else if((V_VT(left) == VT_I2)   && (V_VT(right) == VT_UI1))  resT = VT_I2;
05596     else if((V_VT(left) == VT_I2)   && (V_VT(right) == VT_I2))   resT = VT_I2;
05597     else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_BOOL)) resT = VT_I2;
05598     else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_UI1))  resT = VT_I2;
05599     else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_I2))   resT = VT_I2;
05600     else resT = VT_I4; /* most outputs are I4 */
05601 
05602     /* convert to I8 for the modulo */
05603     rc = VariantChangeType(&lv, left, 0, VT_I8);
05604     if(FAILED(rc))
05605     {
05606       FIXME("Could not convert left type %d to %d? rc == 0x%X\n", V_VT(left), VT_I8, rc);
05607       goto end;
05608     }
05609 
05610     rc = VariantChangeType(&rv, right, 0, VT_I8);
05611     if(FAILED(rc))
05612     {
05613       FIXME("Could not convert right type %d to %d? rc == 0x%X\n", V_VT(right), VT_I8, rc);
05614       goto end;
05615     }
05616 
05617     /* if right is zero set VT_EMPTY and return divide by zero */
05618     if(V_I8(&rv) == 0)
05619     {
05620       V_VT(result) = VT_EMPTY;
05621       rc = DISP_E_DIVBYZERO;
05622       goto end;
05623     }
05624 
05625     /* perform the modulo operation */
05626     V_VT(result) = VT_I8;
05627     V_I8(result) = V_I8(&lv) % V_I8(&rv);
05628 
05629     TRACE("V_I8(left) == %s, V_I8(right) == %s, V_I8(result) == %s\n",
05630           wine_dbgstr_longlong(V_I8(&lv)), wine_dbgstr_longlong(V_I8(&rv)),
05631           wine_dbgstr_longlong(V_I8(result)));
05632 
05633     /* convert left and right to the destination type */
05634     rc = VariantChangeType(result, result, 0, resT);
05635     if(FAILED(rc))
05636     {
05637       FIXME("Could not convert 0x%x to %d?\n", V_VT(result), resT);
05638       /* fall to end of function */
05639     }
05640 
05641 end:
05642     VariantClear(&lv);
05643     VariantClear(&rv);
05644     VariantClear(&tempLeft);
05645     VariantClear(&tempRight);
05646     return rc;
05647 }
05648 
05649 /**********************************************************************
05650  *              VarPow [OLEAUT32.158]
05651  *
05652  * Computes the power of one variant to another variant.
05653  *
05654  * PARAMS
05655  *  left    [I] First variant
05656  *  right   [I] Second variant
05657  *  result  [O] Result variant
05658  *
05659  * RETURNS
05660  *  Success: S_OK.
05661  *  Failure: An HRESULT error code indicating the error.
05662  */
05663 HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result)
05664 {
05665     HRESULT hr = S_OK;
05666     VARIANT dl,dr;
05667     VARTYPE resvt = VT_EMPTY;
05668     VARTYPE leftvt,rightvt;
05669     VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
05670     VARIANT tempLeft, tempRight;
05671 
05672     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left),
05673           right, debugstr_VT(right), debugstr_VF(right), result);
05674 
05675     VariantInit(&dl);
05676     VariantInit(&dr);
05677     VariantInit(&tempLeft);
05678     VariantInit(&tempRight);
05679 
05680     /* Handle VT_DISPATCH by storing and taking address of returned value */
05681     if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
05682     {
05683         hr = VARIANT_FetchDispatchValue(left, &tempLeft);
05684         if (FAILED(hr)) goto end;
05685         left = &tempLeft;
05686     }
05687     if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
05688     {
05689         hr = VARIANT_FetchDispatchValue(right, &tempRight);
05690         if (FAILED(hr)) goto end;
05691         right = &tempRight;
05692     }
05693 
05694     leftvt = V_VT(left)&VT_TYPEMASK;
05695     rightvt = V_VT(right)&VT_TYPEMASK;
05696     leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
05697     rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
05698 
05699     if (leftExtraFlags != rightExtraFlags)
05700     {
05701         hr = DISP_E_BADVARTYPE;
05702         goto end;
05703     }
05704     ExtraFlags = leftExtraFlags;
05705 
05706     /* Native VarPow always returns an error when using extra flags */
05707     if (ExtraFlags != 0)
05708     {
05709         hr = DISP_E_BADVARTYPE;
05710         goto end;
05711     }
05712 
05713     /* Determine return type */
05714     else if (leftvt == VT_NULL || rightvt == VT_NULL) {
05715         V_VT(result) = VT_NULL;
05716         hr = S_OK;
05717         goto end;
05718     }
05719     else if ((leftvt == VT_EMPTY || leftvt == VT_I2 ||
05720         leftvt == VT_I4 || leftvt == VT_R4 ||
05721         leftvt == VT_R8 || leftvt == VT_CY ||
05722         leftvt == VT_DATE || leftvt == VT_BSTR ||
05723         leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
05724         (leftvt >= VT_I1 && leftvt <= VT_UINT)) &&
05725         (rightvt == VT_EMPTY || rightvt == VT_I2 ||
05726         rightvt == VT_I4 || rightvt == VT_R4 ||
05727         rightvt == VT_R8 || rightvt == VT_CY ||
05728         rightvt == VT_DATE || rightvt == VT_BSTR ||
05729         rightvt == VT_BOOL || rightvt == VT_DECIMAL ||
05730         (rightvt >= VT_I1 && rightvt <= VT_UINT)))
05731         resvt = VT_R8;
05732     else
05733     {
05734         hr = DISP_E_BADVARTYPE;
05735         goto end;
05736     }
05737 
05738     hr = VariantChangeType(&dl,left,0,resvt);
05739     if (FAILED(hr)) {
05740         ERR("Could not change passed left argument to VT_R8, handle it differently.\n");
05741         hr = E_FAIL;
05742         goto end;
05743     }
05744 
05745     hr = VariantChangeType(&dr,right,0,resvt);
05746     if (FAILED(hr)) {
05747         ERR("Could not change passed right argument to VT_R8, handle it differently.\n");
05748         hr = E_FAIL;
05749         goto end;
05750     }
05751 
05752     V_VT(result) = VT_R8;
05753     V_R8(result) = pow(V_R8(&dl),V_R8(&dr));
05754 
05755 end:
05756     VariantClear(&dl);
05757     VariantClear(&dr);
05758     VariantClear(&tempLeft);
05759     VariantClear(&tempRight);
05760 
05761     return hr;
05762 }
05763 
05764 /**********************************************************************
05765  *              VarImp [OLEAUT32.154]
05766  *
05767  * Bitwise implication of two variants.
05768  *
05769  * PARAMS
05770  *  left    [I] First variant
05771  *  right   [I] Second variant
05772  *  result  [O] Result variant
05773  *
05774  * RETURNS
05775  *  Success: S_OK.
05776  *  Failure: An HRESULT error code indicating the error.
05777  */
05778 HRESULT WINAPI VarImp(LPVARIANT left, LPVARIANT right, LPVARIANT result)
05779 {
05780     HRESULT hres = S_OK;
05781     VARTYPE resvt = VT_EMPTY;
05782     VARTYPE leftvt,rightvt;
05783     VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
05784     VARIANT lv,rv;
05785     double d;
05786     VARIANT tempLeft, tempRight;
05787 
05788     VariantInit(&lv);
05789     VariantInit(&rv);
05790     VariantInit(&tempLeft);
05791     VariantInit(&tempRight);
05792 
05793     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
05794           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
05795 
05796     /* Handle VT_DISPATCH by storing and taking address of returned value */
05797     if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
05798     {
05799         hres = VARIANT_FetchDispatchValue(left, &tempLeft);
05800         if (FAILED(hres)) goto VarImp_Exit;
05801         left = &tempLeft;
05802     }
05803     if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
05804     {
05805         hres = VARIANT_FetchDispatchValue(right, &tempRight);
05806         if (FAILED(hres)) goto VarImp_Exit;
05807         right = &tempRight;
05808     }
05809 
05810     leftvt = V_VT(left)&VT_TYPEMASK;
05811     rightvt = V_VT(right)&VT_TYPEMASK;
05812     leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
05813     rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
05814 
05815     if (leftExtraFlags != rightExtraFlags)
05816     {
05817         hres = DISP_E_BADVARTYPE;
05818         goto VarImp_Exit;
05819     }
05820     ExtraFlags = leftExtraFlags;
05821 
05822     /* Native VarImp always returns an error when using extra
05823      * flags or if the variants are I8 and INT.
05824      */
05825     if ((leftvt == VT_I8 && rightvt == VT_INT) ||
05826         ExtraFlags != 0)
05827     {
05828         hres = DISP_E_BADVARTYPE;
05829         goto VarImp_Exit;
05830     }
05831 
05832     /* Determine result type */
05833     else if ((leftvt == VT_NULL && rightvt == VT_NULL) ||
05834         (leftvt == VT_NULL && rightvt == VT_EMPTY))
05835     {
05836         V_VT(result) = VT_NULL;
05837         hres = S_OK;
05838         goto VarImp_Exit;
05839     }
05840     else if (leftvt == VT_I8 || rightvt == VT_I8)
05841         resvt = VT_I8;
05842     else if (leftvt == VT_I4 || rightvt == VT_I4 ||
05843         leftvt == VT_INT || rightvt == VT_INT ||
05844         leftvt == VT_UINT || rightvt == VT_UINT ||
05845         leftvt == VT_UI4 || rightvt == VT_UI4 ||
05846         leftvt == VT_UI8 || rightvt == VT_UI8 ||
05847         leftvt == VT_UI2 || rightvt == VT_UI2 ||
05848         leftvt == VT_DECIMAL || rightvt == VT_DECIMAL ||
05849         leftvt == VT_DATE || rightvt == VT_DATE ||
05850         leftvt == VT_CY || rightvt == VT_CY ||
05851         leftvt == VT_R8 || rightvt == VT_R8 ||
05852         leftvt == VT_R4 || rightvt == VT_R4 ||
05853         leftvt == VT_I1 || rightvt == VT_I1)
05854         resvt = VT_I4;
05855     else if ((leftvt == VT_UI1 && rightvt == VT_UI1) ||
05856         (leftvt == VT_UI1 && rightvt == VT_NULL) ||
05857         (leftvt == VT_NULL && rightvt == VT_UI1))
05858         resvt = VT_UI1;
05859     else if (leftvt == VT_EMPTY || rightvt == VT_EMPTY ||
05860         leftvt == VT_I2 || rightvt == VT_I2 ||
05861         leftvt == VT_UI1 || rightvt == VT_UI1)
05862         resvt = VT_I2;
05863     else if (leftvt == VT_BOOL || rightvt == VT_BOOL ||
05864         leftvt == VT_BSTR || rightvt == VT_BSTR)
05865         resvt = VT_BOOL;
05866 
05867     /* VT_NULL requires special handling for when the opposite
05868      * variant is equal to something other than -1.
05869      * (NULL Imp 0 = NULL, NULL Imp n = n)
05870      */
05871     if (leftvt == VT_NULL)
05872     {
05873         VARIANT_BOOL b;
05874         switch(rightvt)
05875         {
05876         case VT_I1:   if (!V_I1(right)) resvt = VT_NULL; break;
05877         case VT_UI1:  if (!V_UI1(right)) resvt = VT_NULL; break;
05878         case VT_I2:   if (!V_I2(right)) resvt = VT_NULL; break;
05879         case VT_UI2:  if (!V_UI2(right)) resvt = VT_NULL; break;
05880         case VT_I4:   if (!V_I4(right)) resvt = VT_NULL; break;
05881         case VT_UI4:  if (!V_UI4(right)) resvt = VT_NULL; break;
05882         case VT_I8:   if (!V_I8(right)) resvt = VT_NULL; break;
05883         case VT_UI8:  if (!V_UI8(right)) resvt = VT_NULL; break;
05884         case VT_INT:  if (!V_INT(right)) resvt = VT_NULL; break;
05885         case VT_UINT: if (!V_UINT(right)) resvt = VT_NULL; break;
05886         case VT_BOOL: if (!V_BOOL(right)) resvt = VT_NULL; break;
05887         case VT_R4:   if (!V_R4(right)) resvt = VT_NULL; break;
05888         case VT_R8:   if (!V_R8(right)) resvt = VT_NULL; break;
05889         case VT_DATE: if (!V_DATE(right)) resvt = VT_NULL; break;
05890         case VT_CY:   if (!V_CY(right).int64) resvt = VT_NULL; break;
05891         case VT_DECIMAL:
05892             if (!(DEC_HI32(&V_DECIMAL(right)) || DEC_LO64(&V_DECIMAL(right))))
05893                 resvt = VT_NULL;
05894             break;
05895         case VT_BSTR:
05896             hres = VarBoolFromStr(V_BSTR(right),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
05897             if (FAILED(hres)) goto VarImp_Exit;
05898             else if (!b)
05899                 V_VT(result) = VT_NULL;
05900             else
05901             {
05902                 V_VT(result) = VT_BOOL;
05903                 V_BOOL(result) = b;
05904             }
05905             goto VarImp_Exit;
05906         }
05907         if (resvt == VT_NULL)
05908         {
05909             V_VT(result) = resvt;
05910             goto VarImp_Exit;
05911         }
05912         else
05913         {
05914             hres = VariantChangeType(result,right,0,resvt);
05915             goto VarImp_Exit;
05916         }
05917     }
05918 
05919     /* Special handling is required when NULL is the right variant.
05920      * (-1 Imp NULL = NULL, n Imp NULL = n Imp 0)
05921      */
05922     else if (rightvt == VT_NULL)
05923     {
05924         VARIANT_BOOL b;
05925         switch(leftvt)
05926         {
05927         case VT_I1:     if (V_I1(left) == -1) resvt = VT_NULL; break;
05928         case VT_UI1:    if (V_UI1(left) == 0xff) resvt = VT_NULL; break;
05929         case VT_I2:     if (V_I2(left) == -1) resvt = VT_NULL; break;
05930         case VT_UI2:    if (V_UI2(left) == 0xffff) resvt = VT_NULL; break;
05931         case VT_INT:    if (V_INT(left) == -1) resvt = VT_NULL; break;
05932         case VT_UINT:   if (V_UINT(left) == ~0u) resvt = VT_NULL; break;
05933         case VT_I4:     if (V_I4(left) == -1) resvt = VT_NULL; break;
05934         case VT_UI4:    if (V_UI4(left) == ~0u) resvt = VT_NULL; break;
05935         case VT_I8:     if (V_I8(left) == -1) resvt = VT_NULL; break;
05936         case VT_UI8:    if (V_UI8(left) == ~(ULONGLONG)0) resvt = VT_NULL; break;
05937         case VT_BOOL:   if (V_BOOL(left) == VARIANT_TRUE) resvt = VT_NULL; break;
05938         case VT_R4:     if (V_R4(left) == -1.0) resvt = VT_NULL; break;
05939         case VT_R8:     if (V_R8(left) == -1.0) resvt = VT_NULL; break;
05940         case VT_CY:     if (V_CY(left).int64 == -1) resvt = VT_NULL; break;
05941         case VT_DECIMAL:
05942             if (DEC_HI32(&V_DECIMAL(left)) == 0xffffffff)
05943                 resvt = VT_NULL;
05944             break;
05945         case VT_BSTR:
05946             hres = VarBoolFromStr(V_BSTR(left),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
05947             if (FAILED(hres)) goto VarImp_Exit;
05948             else if (b == VARIANT_TRUE)
05949                 resvt = VT_NULL;
05950         }
05951         if (resvt == VT_NULL)
05952         {
05953             V_VT(result) = resvt;
05954             goto VarImp_Exit;
05955         }
05956     }
05957 
05958     hres = VariantCopy(&lv, left);
05959     if (FAILED(hres)) goto VarImp_Exit;
05960 
05961     if (rightvt == VT_NULL)
05962     {
05963         memset( &rv, 0, sizeof(rv) );
05964         V_VT(&rv) = resvt;
05965     }
05966     else
05967     {
05968         hres = VariantCopy(&rv, right);
05969         if (FAILED(hres)) goto VarImp_Exit;
05970     }
05971 
05972     if (V_VT(&lv) == VT_BSTR &&
05973         FAILED(VarR8FromStr(V_BSTR(&lv),LOCALE_USER_DEFAULT, 0, &d)))
05974         hres = VariantChangeType(&lv,&lv,VARIANT_LOCALBOOL, VT_BOOL);
05975     if (SUCCEEDED(hres) && V_VT(&lv) != resvt)
05976         hres = VariantChangeType(&lv,&lv,0,resvt);
05977     if (FAILED(hres)) goto VarImp_Exit;
05978 
05979     if (V_VT(&rv) == VT_BSTR &&
05980         FAILED(VarR8FromStr(V_BSTR(&rv),LOCALE_USER_DEFAULT, 0, &d)))
05981         hres = VariantChangeType(&rv, &rv,VARIANT_LOCALBOOL, VT_BOOL);
05982     if (SUCCEEDED(hres) && V_VT(&rv) != resvt)
05983         hres = VariantChangeType(&rv, &rv, 0, resvt);
05984     if (FAILED(hres)) goto VarImp_Exit;
05985 
05986     /* do the math */
05987     V_VT(result) = resvt;
05988     switch (resvt)
05989     {
05990     case VT_I8:
05991     V_I8(result) = (~V_I8(&lv)) | V_I8(&rv);
05992     break;
05993     case VT_I4:
05994     V_I4(result) = (~V_I4(&lv)) | V_I4(&rv);
05995     break;
05996     case VT_I2:
05997     V_I2(result) = (~V_I2(&lv)) | V_I2(&rv);
05998     break;
05999     case VT_UI1:
06000     V_UI1(result) = (~V_UI1(&lv)) | V_UI1(&rv);
06001     break;
06002     case VT_BOOL:
06003     V_BOOL(result) = (~V_BOOL(&lv)) | V_BOOL(&rv);
06004     break;
06005     default:
06006     FIXME("Couldn't perform bitwise implication on variant types %d,%d\n",
06007         leftvt,rightvt);
06008     }
06009 
06010 VarImp_Exit:
06011 
06012     VariantClear(&lv);
06013     VariantClear(&rv);
06014     VariantClear(&tempLeft);
06015     VariantClear(&tempRight);
06016 
06017     return hres;
06018 }

Generated on Mon May 28 2012 04:25:32 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.