Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvariant.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
1.7.6.1
|