1 /* 2 * VARIANT 3 * 4 * Copyright 1998 Jean-Claude Cote 5 * Copyright 2003 Jon Griffiths 6 * Copyright 2005 Daniel Remenak 7 * Copyright 2006 Google (Benjamin Arai) 8 * 9 * The algorithm for conversion from Julian days to day/month/year is based on 10 * that devised by Henry Fliegel, as implemented in PostgreSQL, which is 11 * Copyright 1994-7 Regents of the University of California 12 * 13 * This library is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU Lesser General Public 15 * License as published by the Free Software Foundation; either 16 * version 2.1 of the License, or (at your option) any later version. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * Lesser General Public License for more details. 22 * 23 * You should have received a copy of the GNU Lesser General Public 24 * License along with this library; if not, write to the Free Software 25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 26 */ 27 28 #include <string.h> 29 #include <stdlib.h> 30 #include <stdarg.h> 31 32 #define COBJMACROS 33 #define NONAMELESSUNION 34 #define NONAMELESSSTRUCT 35 36 #include "windef.h" 37 #include "winbase.h" 38 #include "winerror.h" 39 #include "variant.h" 40 #include "resource.h" 41 #include "wine/debug.h" 42 43 WINE_DEFAULT_DEBUG_CHANNEL(variant); 44 45 static CRITICAL_SECTION cache_cs; 46 static CRITICAL_SECTION_DEBUG critsect_debug = 47 { 48 0, 0, &cache_cs, 49 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 50 0, 0, { (DWORD_PTR)(__FILE__ ": cache_cs") } 51 }; 52 static CRITICAL_SECTION cache_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; 53 54 /* Convert a variant from one type to another */ 55 static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags, 56 VARIANTARG* ps, VARTYPE vt) 57 { 58 HRESULT res = DISP_E_TYPEMISMATCH; 59 VARTYPE vtFrom = V_TYPE(ps); 60 DWORD dwFlags = 0; 61 62 TRACE("(%s,0x%08x,0x%04x,%s,%s)\n", debugstr_variant(pd), lcid, wFlags, 63 debugstr_variant(ps), debugstr_vt(vt)); 64 65 if (vt == VT_BSTR || vtFrom == VT_BSTR) 66 { 67 /* All flags passed to low level function are only used for 68 * changing to or from strings. Map these here. 69 */ 70 if (wFlags & VARIANT_LOCALBOOL) 71 dwFlags |= VAR_LOCALBOOL; 72 if (wFlags & VARIANT_CALENDAR_HIJRI) 73 dwFlags |= VAR_CALENDAR_HIJRI; 74 if (wFlags & VARIANT_CALENDAR_THAI) 75 dwFlags |= VAR_CALENDAR_THAI; 76 if (wFlags & VARIANT_CALENDAR_GREGORIAN) 77 dwFlags |= VAR_CALENDAR_GREGORIAN; 78 if (wFlags & VARIANT_NOUSEROVERRIDE) 79 dwFlags |= LOCALE_NOUSEROVERRIDE; 80 if (wFlags & VARIANT_USE_NLS) 81 dwFlags |= LOCALE_USE_NLS; 82 } 83 84 /* Map int/uint to i4/ui4 */ 85 if (vt == VT_INT) 86 vt = VT_I4; 87 else if (vt == VT_UINT) 88 vt = VT_UI4; 89 90 if (vtFrom == VT_INT) 91 vtFrom = VT_I4; 92 else if (vtFrom == VT_UINT) 93 vtFrom = VT_UI4; 94 95 if (vt == vtFrom) 96 return VariantCopy(pd, ps); 97 98 if (wFlags & VARIANT_NOVALUEPROP && vtFrom == VT_DISPATCH && vt != VT_UNKNOWN) 99 { 100 /* VARIANT_NOVALUEPROP prevents IDispatch objects from being coerced by 101 * accessing the default object property. 102 */ 103 return DISP_E_TYPEMISMATCH; 104 } 105 106 switch (vt) 107 { 108 case VT_EMPTY: 109 if (vtFrom == VT_NULL) 110 return DISP_E_TYPEMISMATCH; 111 /* ... Fall through */ 112 case VT_NULL: 113 if (vtFrom <= VT_UINT && vtFrom != (VARTYPE)15 && vtFrom != VT_ERROR) 114 { 115 res = VariantClear( pd ); 116 if (vt == VT_NULL && SUCCEEDED(res)) 117 V_VT(pd) = VT_NULL; 118 } 119 return res; 120 121 case VT_I1: 122 switch (vtFrom) 123 { 124 case VT_EMPTY: V_I1(pd) = 0; return S_OK; 125 case VT_I2: return VarI1FromI2(V_I2(ps), &V_I1(pd)); 126 case VT_I4: return VarI1FromI4(V_I4(ps), &V_I1(pd)); 127 case VT_UI1: V_I1(pd) = V_UI1(ps); return S_OK; 128 case VT_UI2: return VarI1FromUI2(V_UI2(ps), &V_I1(pd)); 129 case VT_UI4: return VarI1FromUI4(V_UI4(ps), &V_I1(pd)); 130 case VT_I8: return VarI1FromI8(V_I8(ps), &V_I1(pd)); 131 case VT_UI8: return VarI1FromUI8(V_UI8(ps), &V_I1(pd)); 132 case VT_R4: return VarI1FromR4(V_R4(ps), &V_I1(pd)); 133 case VT_R8: return VarI1FromR8(V_R8(ps), &V_I1(pd)); 134 case VT_DATE: return VarI1FromDate(V_DATE(ps), &V_I1(pd)); 135 case VT_BOOL: return VarI1FromBool(V_BOOL(ps), &V_I1(pd)); 136 case VT_CY: return VarI1FromCy(V_CY(ps), &V_I1(pd)); 137 case VT_DECIMAL: return VarI1FromDec(&V_DECIMAL(ps), &V_I1(pd) ); 138 case VT_DISPATCH: return VarI1FromDisp(V_DISPATCH(ps), lcid, &V_I1(pd) ); 139 case VT_BSTR: return VarI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_I1(pd) ); 140 } 141 break; 142 143 case VT_I2: 144 switch (vtFrom) 145 { 146 case VT_EMPTY: V_I2(pd) = 0; return S_OK; 147 case VT_I1: return VarI2FromI1(V_I1(ps), &V_I2(pd)); 148 case VT_I4: return VarI2FromI4(V_I4(ps), &V_I2(pd)); 149 case VT_UI1: return VarI2FromUI1(V_UI1(ps), &V_I2(pd)); 150 case VT_UI2: V_I2(pd) = V_UI2(ps); return S_OK; 151 case VT_UI4: return VarI2FromUI4(V_UI4(ps), &V_I2(pd)); 152 case VT_I8: return VarI2FromI8(V_I8(ps), &V_I2(pd)); 153 case VT_UI8: return VarI2FromUI8(V_UI8(ps), &V_I2(pd)); 154 case VT_R4: return VarI2FromR4(V_R4(ps), &V_I2(pd)); 155 case VT_R8: return VarI2FromR8(V_R8(ps), &V_I2(pd)); 156 case VT_DATE: return VarI2FromDate(V_DATE(ps), &V_I2(pd)); 157 case VT_BOOL: return VarI2FromBool(V_BOOL(ps), &V_I2(pd)); 158 case VT_CY: return VarI2FromCy(V_CY(ps), &V_I2(pd)); 159 case VT_DECIMAL: return VarI2FromDec(&V_DECIMAL(ps), &V_I2(pd)); 160 case VT_DISPATCH: return VarI2FromDisp(V_DISPATCH(ps), lcid, &V_I2(pd)); 161 case VT_BSTR: return VarI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_I2(pd)); 162 } 163 break; 164 165 case VT_I4: 166 switch (vtFrom) 167 { 168 case VT_EMPTY: V_I4(pd) = 0; return S_OK; 169 case VT_I1: return VarI4FromI1(V_I1(ps), &V_I4(pd)); 170 case VT_I2: return VarI4FromI2(V_I2(ps), &V_I4(pd)); 171 case VT_UI1: return VarI4FromUI1(V_UI1(ps), &V_I4(pd)); 172 case VT_UI2: return VarI4FromUI2(V_UI2(ps), &V_I4(pd)); 173 case VT_UI4: V_I4(pd) = V_UI4(ps); return S_OK; 174 case VT_I8: return VarI4FromI8(V_I8(ps), &V_I4(pd)); 175 case VT_UI8: return VarI4FromUI8(V_UI8(ps), &V_I4(pd)); 176 case VT_R4: return VarI4FromR4(V_R4(ps), &V_I4(pd)); 177 case VT_R8: return VarI4FromR8(V_R8(ps), &V_I4(pd)); 178 case VT_DATE: return VarI4FromDate(V_DATE(ps), &V_I4(pd)); 179 case VT_BOOL: return VarI4FromBool(V_BOOL(ps), &V_I4(pd)); 180 case VT_CY: return VarI4FromCy(V_CY(ps), &V_I4(pd)); 181 case VT_DECIMAL: return VarI4FromDec(&V_DECIMAL(ps), &V_I4(pd)); 182 case VT_DISPATCH: return VarI4FromDisp(V_DISPATCH(ps), lcid, &V_I4(pd)); 183 case VT_BSTR: return VarI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_I4(pd)); 184 } 185 break; 186 187 case VT_UI1: 188 switch (vtFrom) 189 { 190 case VT_EMPTY: V_UI1(pd) = 0; return S_OK; 191 case VT_I1: V_UI1(pd) = V_I1(ps); return S_OK; 192 case VT_I2: return VarUI1FromI2(V_I2(ps), &V_UI1(pd)); 193 case VT_I4: return VarUI1FromI4(V_I4(ps), &V_UI1(pd)); 194 case VT_UI2: return VarUI1FromUI2(V_UI2(ps), &V_UI1(pd)); 195 case VT_UI4: return VarUI1FromUI4(V_UI4(ps), &V_UI1(pd)); 196 case VT_I8: return VarUI1FromI8(V_I8(ps), &V_UI1(pd)); 197 case VT_UI8: return VarUI1FromUI8(V_UI8(ps), &V_UI1(pd)); 198 case VT_R4: return VarUI1FromR4(V_R4(ps), &V_UI1(pd)); 199 case VT_R8: return VarUI1FromR8(V_R8(ps), &V_UI1(pd)); 200 case VT_DATE: return VarUI1FromDate(V_DATE(ps), &V_UI1(pd)); 201 case VT_BOOL: return VarUI1FromBool(V_BOOL(ps), &V_UI1(pd)); 202 case VT_CY: return VarUI1FromCy(V_CY(ps), &V_UI1(pd)); 203 case VT_DECIMAL: return VarUI1FromDec(&V_DECIMAL(ps), &V_UI1(pd)); 204 case VT_DISPATCH: return VarUI1FromDisp(V_DISPATCH(ps), lcid, &V_UI1(pd)); 205 case VT_BSTR: return VarUI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI1(pd)); 206 } 207 break; 208 209 case VT_UI2: 210 switch (vtFrom) 211 { 212 case VT_EMPTY: V_UI2(pd) = 0; return S_OK; 213 case VT_I1: return VarUI2FromI1(V_I1(ps), &V_UI2(pd)); 214 case VT_I2: V_UI2(pd) = V_I2(ps); return S_OK; 215 case VT_I4: return VarUI2FromI4(V_I4(ps), &V_UI2(pd)); 216 case VT_UI1: return VarUI2FromUI1(V_UI1(ps), &V_UI2(pd)); 217 case VT_UI4: return VarUI2FromUI4(V_UI4(ps), &V_UI2(pd)); 218 case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd)); 219 case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd)); 220 case VT_R4: return VarUI2FromR4(V_R4(ps), &V_UI2(pd)); 221 case VT_R8: return VarUI2FromR8(V_R8(ps), &V_UI2(pd)); 222 case VT_DATE: return VarUI2FromDate(V_DATE(ps), &V_UI2(pd)); 223 case VT_BOOL: return VarUI2FromBool(V_BOOL(ps), &V_UI2(pd)); 224 case VT_CY: return VarUI2FromCy(V_CY(ps), &V_UI2(pd)); 225 case VT_DECIMAL: return VarUI2FromDec(&V_DECIMAL(ps), &V_UI2(pd)); 226 case VT_DISPATCH: return VarUI2FromDisp(V_DISPATCH(ps), lcid, &V_UI2(pd)); 227 case VT_BSTR: return VarUI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI2(pd)); 228 } 229 break; 230 231 case VT_UI4: 232 switch (vtFrom) 233 { 234 case VT_EMPTY: V_UI4(pd) = 0; return S_OK; 235 case VT_I1: return VarUI4FromI1(V_I1(ps), &V_UI4(pd)); 236 case VT_I2: return VarUI4FromI2(V_I2(ps), &V_UI4(pd)); 237 case VT_I4: V_UI4(pd) = V_I4(ps); return S_OK; 238 case VT_UI1: return VarUI4FromUI1(V_UI1(ps), &V_UI4(pd)); 239 case VT_UI2: return VarUI4FromUI2(V_UI2(ps), &V_UI4(pd)); 240 case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd)); 241 case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd)); 242 case VT_R4: return VarUI4FromR4(V_R4(ps), &V_UI4(pd)); 243 case VT_R8: return VarUI4FromR8(V_R8(ps), &V_UI4(pd)); 244 case VT_DATE: return VarUI4FromDate(V_DATE(ps), &V_UI4(pd)); 245 case VT_BOOL: return VarUI4FromBool(V_BOOL(ps), &V_UI4(pd)); 246 case VT_CY: return VarUI4FromCy(V_CY(ps), &V_UI4(pd)); 247 case VT_DECIMAL: return VarUI4FromDec(&V_DECIMAL(ps), &V_UI4(pd)); 248 case VT_DISPATCH: return VarUI4FromDisp(V_DISPATCH(ps), lcid, &V_UI4(pd)); 249 case VT_BSTR: return VarUI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI4(pd)); 250 } 251 break; 252 253 case VT_UI8: 254 switch (vtFrom) 255 { 256 case VT_EMPTY: V_UI8(pd) = 0; return S_OK; 257 case VT_I4: if (V_I4(ps) < 0) return DISP_E_OVERFLOW; V_UI8(pd) = V_I4(ps); return S_OK; 258 case VT_I1: return VarUI8FromI1(V_I1(ps), &V_UI8(pd)); 259 case VT_I2: return VarUI8FromI2(V_I2(ps), &V_UI8(pd)); 260 case VT_UI1: return VarUI8FromUI1(V_UI1(ps), &V_UI8(pd)); 261 case VT_UI2: return VarUI8FromUI2(V_UI2(ps), &V_UI8(pd)); 262 case VT_UI4: return VarUI8FromUI4(V_UI4(ps), &V_UI8(pd)); 263 case VT_I8: V_UI8(pd) = V_I8(ps); return S_OK; 264 case VT_R4: return VarUI8FromR4(V_R4(ps), &V_UI8(pd)); 265 case VT_R8: return VarUI8FromR8(V_R8(ps), &V_UI8(pd)); 266 case VT_DATE: return VarUI8FromDate(V_DATE(ps), &V_UI8(pd)); 267 case VT_BOOL: return VarUI8FromBool(V_BOOL(ps), &V_UI8(pd)); 268 case VT_CY: return VarUI8FromCy(V_CY(ps), &V_UI8(pd)); 269 case VT_DECIMAL: return VarUI8FromDec(&V_DECIMAL(ps), &V_UI8(pd)); 270 case VT_DISPATCH: return VarUI8FromDisp(V_DISPATCH(ps), lcid, &V_UI8(pd)); 271 case VT_BSTR: return VarUI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI8(pd)); 272 } 273 break; 274 275 case VT_I8: 276 switch (vtFrom) 277 { 278 case VT_EMPTY: V_I8(pd) = 0; return S_OK; 279 case VT_I4: V_I8(pd) = V_I4(ps); return S_OK; 280 case VT_I1: return VarI8FromI1(V_I1(ps), &V_I8(pd)); 281 case VT_I2: return VarI8FromI2(V_I2(ps), &V_I8(pd)); 282 case VT_UI1: return VarI8FromUI1(V_UI1(ps), &V_I8(pd)); 283 case VT_UI2: return VarI8FromUI2(V_UI2(ps), &V_I8(pd)); 284 case VT_UI4: return VarI8FromUI4(V_UI4(ps), &V_I8(pd)); 285 case VT_UI8: V_I8(pd) = V_UI8(ps); return S_OK; 286 case VT_R4: return VarI8FromR4(V_R4(ps), &V_I8(pd)); 287 case VT_R8: return VarI8FromR8(V_R8(ps), &V_I8(pd)); 288 case VT_DATE: return VarI8FromDate(V_DATE(ps), &V_I8(pd)); 289 case VT_BOOL: return VarI8FromBool(V_BOOL(ps), &V_I8(pd)); 290 case VT_CY: return VarI8FromCy(V_CY(ps), &V_I8(pd)); 291 case VT_DECIMAL: return VarI8FromDec(&V_DECIMAL(ps), &V_I8(pd)); 292 case VT_DISPATCH: return VarI8FromDisp(V_DISPATCH(ps), lcid, &V_I8(pd)); 293 case VT_BSTR: return VarI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_I8(pd)); 294 } 295 break; 296 297 case VT_R4: 298 switch (vtFrom) 299 { 300 case VT_EMPTY: V_R4(pd) = 0.0f; return S_OK; 301 case VT_I1: return VarR4FromI1(V_I1(ps), &V_R4(pd)); 302 case VT_I2: return VarR4FromI2(V_I2(ps), &V_R4(pd)); 303 case VT_I4: return VarR4FromI4(V_I4(ps), &V_R4(pd)); 304 case VT_UI1: return VarR4FromUI1(V_UI1(ps), &V_R4(pd)); 305 case VT_UI2: return VarR4FromUI2(V_UI2(ps), &V_R4(pd)); 306 case VT_UI4: return VarR4FromUI4(V_UI4(ps), &V_R4(pd)); 307 case VT_I8: return VarR4FromI8(V_I8(ps), &V_R4(pd)); 308 case VT_UI8: return VarR4FromUI8(V_UI8(ps), &V_R4(pd)); 309 case VT_R8: return VarR4FromR8(V_R8(ps), &V_R4(pd)); 310 case VT_DATE: return VarR4FromDate(V_DATE(ps), &V_R4(pd)); 311 case VT_BOOL: return VarR4FromBool(V_BOOL(ps), &V_R4(pd)); 312 case VT_CY: return VarR4FromCy(V_CY(ps), &V_R4(pd)); 313 case VT_DECIMAL: return VarR4FromDec(&V_DECIMAL(ps), &V_R4(pd)); 314 case VT_DISPATCH: return VarR4FromDisp(V_DISPATCH(ps), lcid, &V_R4(pd)); 315 case VT_BSTR: return VarR4FromStr(V_BSTR(ps), lcid, dwFlags, &V_R4(pd)); 316 } 317 break; 318 319 case VT_R8: 320 switch (vtFrom) 321 { 322 case VT_EMPTY: V_R8(pd) = 0.0; return S_OK; 323 case VT_I1: return VarR8FromI1(V_I1(ps), &V_R8(pd)); 324 case VT_I2: return VarR8FromI2(V_I2(ps), &V_R8(pd)); 325 case VT_I4: return VarR8FromI4(V_I4(ps), &V_R8(pd)); 326 case VT_UI1: return VarR8FromUI1(V_UI1(ps), &V_R8(pd)); 327 case VT_UI2: return VarR8FromUI2(V_UI2(ps), &V_R8(pd)); 328 case VT_UI4: return VarR8FromUI4(V_UI4(ps), &V_R8(pd)); 329 case VT_I8: return VarR8FromI8(V_I8(ps), &V_R8(pd)); 330 case VT_UI8: return VarR8FromUI8(V_UI8(ps), &V_R8(pd)); 331 case VT_R4: return VarR8FromR4(V_R4(ps), &V_R8(pd)); 332 case VT_DATE: return VarR8FromDate(V_DATE(ps), &V_R8(pd)); 333 case VT_BOOL: return VarR8FromBool(V_BOOL(ps), &V_R8(pd)); 334 case VT_CY: return VarR8FromCy(V_CY(ps), &V_R8(pd)); 335 case VT_DECIMAL: return VarR8FromDec(&V_DECIMAL(ps), &V_R8(pd)); 336 case VT_DISPATCH: return VarR8FromDisp(V_DISPATCH(ps), lcid, &V_R8(pd)); 337 case VT_BSTR: return VarR8FromStr(V_BSTR(ps), lcid, dwFlags, &V_R8(pd)); 338 } 339 break; 340 341 case VT_DATE: 342 switch (vtFrom) 343 { 344 case VT_EMPTY: V_DATE(pd) = 0.0; return S_OK; 345 case VT_I1: return VarDateFromI1(V_I1(ps), &V_DATE(pd)); 346 case VT_I2: return VarDateFromI2(V_I2(ps), &V_DATE(pd)); 347 case VT_I4: return VarDateFromI4(V_I4(ps), &V_DATE(pd)); 348 case VT_UI1: return VarDateFromUI1(V_UI1(ps), &V_DATE(pd)); 349 case VT_UI2: return VarDateFromUI2(V_UI2(ps), &V_DATE(pd)); 350 case VT_UI4: return VarDateFromUI4(V_UI4(ps), &V_DATE(pd)); 351 case VT_I8: return VarDateFromI8(V_I8(ps), &V_DATE(pd)); 352 case VT_UI8: return VarDateFromUI8(V_UI8(ps), &V_DATE(pd)); 353 case VT_R4: return VarDateFromR4(V_R4(ps), &V_DATE(pd)); 354 case VT_R8: return VarDateFromR8(V_R8(ps), &V_DATE(pd)); 355 case VT_BOOL: return VarDateFromBool(V_BOOL(ps), &V_DATE(pd)); 356 case VT_CY: return VarDateFromCy(V_CY(ps), &V_DATE(pd)); 357 case VT_DECIMAL: return VarDateFromDec(&V_DECIMAL(ps), &V_DATE(pd)); 358 case VT_DISPATCH: return VarDateFromDisp(V_DISPATCH(ps), lcid, &V_DATE(pd)); 359 case VT_BSTR: return VarDateFromStr(V_BSTR(ps), lcid, dwFlags, &V_DATE(pd)); 360 } 361 break; 362 363 case VT_BOOL: 364 switch (vtFrom) 365 { 366 case VT_EMPTY: V_BOOL(pd) = 0; return S_OK; 367 case VT_I1: return VarBoolFromI1(V_I1(ps), &V_BOOL(pd)); 368 case VT_I2: return VarBoolFromI2(V_I2(ps), &V_BOOL(pd)); 369 case VT_I4: return VarBoolFromI4(V_I4(ps), &V_BOOL(pd)); 370 case VT_UI1: return VarBoolFromUI1(V_UI1(ps), &V_BOOL(pd)); 371 case VT_UI2: return VarBoolFromUI2(V_UI2(ps), &V_BOOL(pd)); 372 case VT_UI4: return VarBoolFromUI4(V_UI4(ps), &V_BOOL(pd)); 373 case VT_I8: return VarBoolFromI8(V_I8(ps), &V_BOOL(pd)); 374 case VT_UI8: return VarBoolFromUI8(V_UI8(ps), &V_BOOL(pd)); 375 case VT_R4: return VarBoolFromR4(V_R4(ps), &V_BOOL(pd)); 376 case VT_R8: return VarBoolFromR8(V_R8(ps), &V_BOOL(pd)); 377 case VT_DATE: return VarBoolFromDate(V_DATE(ps), &V_BOOL(pd)); 378 case VT_CY: return VarBoolFromCy(V_CY(ps), &V_BOOL(pd)); 379 case VT_DECIMAL: return VarBoolFromDec(&V_DECIMAL(ps), &V_BOOL(pd)); 380 case VT_DISPATCH: return VarBoolFromDisp(V_DISPATCH(ps), lcid, &V_BOOL(pd)); 381 case VT_BSTR: return VarBoolFromStr(V_BSTR(ps), lcid, dwFlags, &V_BOOL(pd)); 382 } 383 break; 384 385 case VT_BSTR: 386 switch (vtFrom) 387 { 388 case VT_EMPTY: 389 V_BSTR(pd) = SysAllocStringLen(NULL, 0); 390 return V_BSTR(pd) ? S_OK : E_OUTOFMEMORY; 391 case VT_BOOL: 392 if (wFlags & (VARIANT_ALPHABOOL|VARIANT_LOCALBOOL)) 393 return VarBstrFromBool(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd)); 394 return VarBstrFromI2(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd)); 395 case VT_I1: return VarBstrFromI1(V_I1(ps), lcid, dwFlags, &V_BSTR(pd)); 396 case VT_I2: return VarBstrFromI2(V_I2(ps), lcid, dwFlags, &V_BSTR(pd)); 397 case VT_I4: return VarBstrFromI4(V_I4(ps), lcid, dwFlags, &V_BSTR(pd)); 398 case VT_UI1: return VarBstrFromUI1(V_UI1(ps), lcid, dwFlags, &V_BSTR(pd)); 399 case VT_UI2: return VarBstrFromUI2(V_UI2(ps), lcid, dwFlags, &V_BSTR(pd)); 400 case VT_UI4: return VarBstrFromUI4(V_UI4(ps), lcid, dwFlags, &V_BSTR(pd)); 401 case VT_I8: return VarBstrFromI8(V_I8(ps), lcid, dwFlags, &V_BSTR(pd)); 402 case VT_UI8: return VarBstrFromUI8(V_UI8(ps), lcid, dwFlags, &V_BSTR(pd)); 403 case VT_R4: return VarBstrFromR4(V_R4(ps), lcid, dwFlags, &V_BSTR(pd)); 404 case VT_R8: return VarBstrFromR8(V_R8(ps), lcid, dwFlags, &V_BSTR(pd)); 405 case VT_DATE: return VarBstrFromDate(V_DATE(ps), lcid, dwFlags, &V_BSTR(pd)); 406 case VT_CY: return VarBstrFromCy(V_CY(ps), lcid, dwFlags, &V_BSTR(pd)); 407 case VT_DECIMAL: return VarBstrFromDec(&V_DECIMAL(ps), lcid, dwFlags, &V_BSTR(pd)); 408 case VT_DISPATCH: return VarBstrFromDisp(V_DISPATCH(ps), lcid, dwFlags, &V_BSTR(pd)); 409 } 410 break; 411 412 case VT_CY: 413 switch (vtFrom) 414 { 415 case VT_EMPTY: V_CY(pd).int64 = 0; return S_OK; 416 case VT_I1: return VarCyFromI1(V_I1(ps), &V_CY(pd)); 417 case VT_I2: return VarCyFromI2(V_I2(ps), &V_CY(pd)); 418 case VT_I4: return VarCyFromI4(V_I4(ps), &V_CY(pd)); 419 case VT_UI1: return VarCyFromUI1(V_UI1(ps), &V_CY(pd)); 420 case VT_UI2: return VarCyFromUI2(V_UI2(ps), &V_CY(pd)); 421 case VT_UI4: return VarCyFromUI4(V_UI4(ps), &V_CY(pd)); 422 case VT_I8: return VarCyFromI8(V_I8(ps), &V_CY(pd)); 423 case VT_UI8: return VarCyFromUI8(V_UI8(ps), &V_CY(pd)); 424 case VT_R4: return VarCyFromR4(V_R4(ps), &V_CY(pd)); 425 case VT_R8: return VarCyFromR8(V_R8(ps), &V_CY(pd)); 426 case VT_DATE: return VarCyFromDate(V_DATE(ps), &V_CY(pd)); 427 case VT_BOOL: return VarCyFromBool(V_BOOL(ps), &V_CY(pd)); 428 case VT_DECIMAL: return VarCyFromDec(&V_DECIMAL(ps), &V_CY(pd)); 429 case VT_DISPATCH: return VarCyFromDisp(V_DISPATCH(ps), lcid, &V_CY(pd)); 430 case VT_BSTR: return VarCyFromStr(V_BSTR(ps), lcid, dwFlags, &V_CY(pd)); 431 } 432 break; 433 434 case VT_DECIMAL: 435 switch (vtFrom) 436 { 437 case VT_EMPTY: 438 case VT_BOOL: 439 DEC_SIGNSCALE(&V_DECIMAL(pd)) = SIGNSCALE(DECIMAL_POS,0); 440 DEC_HI32(&V_DECIMAL(pd)) = 0; 441 DEC_MID32(&V_DECIMAL(pd)) = 0; 442 /* VarDecFromBool() coerces to -1/0, ChangeTypeEx() coerces to 1/0. 443 * VT_NULL and VT_EMPTY always give a 0 value. 444 */ 445 DEC_LO32(&V_DECIMAL(pd)) = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0; 446 return S_OK; 447 case VT_I1: return VarDecFromI1(V_I1(ps), &V_DECIMAL(pd)); 448 case VT_I2: return VarDecFromI2(V_I2(ps), &V_DECIMAL(pd)); 449 case VT_I4: return VarDecFromI4(V_I4(ps), &V_DECIMAL(pd)); 450 case VT_UI1: return VarDecFromUI1(V_UI1(ps), &V_DECIMAL(pd)); 451 case VT_UI2: return VarDecFromUI2(V_UI2(ps), &V_DECIMAL(pd)); 452 case VT_UI4: return VarDecFromUI4(V_UI4(ps), &V_DECIMAL(pd)); 453 case VT_I8: return VarDecFromI8(V_I8(ps), &V_DECIMAL(pd)); 454 case VT_UI8: return VarDecFromUI8(V_UI8(ps), &V_DECIMAL(pd)); 455 case VT_R4: return VarDecFromR4(V_R4(ps), &V_DECIMAL(pd)); 456 case VT_R8: return VarDecFromR8(V_R8(ps), &V_DECIMAL(pd)); 457 case VT_DATE: return VarDecFromDate(V_DATE(ps), &V_DECIMAL(pd)); 458 case VT_CY: return VarDecFromCy(V_CY(ps), &V_DECIMAL(pd)); 459 case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(pd)); 460 case VT_BSTR: return VarDecFromStr(V_BSTR(ps), lcid, dwFlags, &V_DECIMAL(pd)); 461 } 462 break; 463 464 case VT_UNKNOWN: 465 switch (vtFrom) 466 { 467 case VT_DISPATCH: 468 if (V_DISPATCH(ps) == NULL) 469 { 470 V_UNKNOWN(pd) = NULL; 471 res = S_OK; 472 } 473 else 474 res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd)); 475 break; 476 } 477 break; 478 479 case VT_DISPATCH: 480 switch (vtFrom) 481 { 482 case VT_UNKNOWN: 483 if (V_UNKNOWN(ps) == NULL) 484 { 485 V_DISPATCH(pd) = NULL; 486 res = S_OK; 487 } 488 else 489 res = IUnknown_QueryInterface(V_UNKNOWN(ps), &IID_IDispatch, (LPVOID*)&V_DISPATCH(pd)); 490 break; 491 } 492 break; 493 494 case VT_RECORD: 495 break; 496 } 497 return res; 498 } 499 500 /* Coerce to/from an array */ 501 static inline HRESULT VARIANT_CoerceArray(VARIANTARG* pd, VARIANTARG* ps, VARTYPE vt) 502 { 503 if (vt == VT_BSTR && V_VT(ps) == (VT_ARRAY|VT_UI1)) 504 return BstrFromVector(V_ARRAY(ps), &V_BSTR(pd)); 505 506 if (V_VT(ps) == VT_BSTR && vt == (VT_ARRAY|VT_UI1)) 507 return VectorFromBstr(V_BSTR(ps), &V_ARRAY(pd)); 508 509 if (V_VT(ps) == vt) 510 return SafeArrayCopy(V_ARRAY(ps), &V_ARRAY(pd)); 511 512 return DISP_E_TYPEMISMATCH; 513 } 514 515 static HRESULT VARIANT_FetchDispatchValue(LPVARIANT pvDispatch, LPVARIANT pValue) 516 { 517 HRESULT hres; 518 static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 }; 519 520 if ((V_VT(pvDispatch) & VT_TYPEMASK) == VT_DISPATCH) { 521 if (NULL == V_DISPATCH(pvDispatch)) return DISP_E_TYPEMISMATCH; 522 hres = IDispatch_Invoke(V_DISPATCH(pvDispatch), DISPID_VALUE, &IID_NULL, 523 LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, pValue, 524 NULL, NULL); 525 } else { 526 hres = DISP_E_TYPEMISMATCH; 527 } 528 return hres; 529 } 530 531 /****************************************************************************** 532 * Check if a variants type is valid. 533 */ 534 static inline HRESULT VARIANT_ValidateType(VARTYPE vt) 535 { 536 VARTYPE vtExtra = vt & VT_EXTRA_TYPE; 537 538 vt &= VT_TYPEMASK; 539 540 if (!(vtExtra & (VT_VECTOR|VT_RESERVED))) 541 { 542 if (vt < VT_VOID || vt == VT_RECORD || vt == VT_CLSID) 543 { 544 if ((vtExtra & (VT_BYREF|VT_ARRAY)) && vt <= VT_NULL) 545 return DISP_E_BADVARTYPE; 546 if (vt != (VARTYPE)15) 547 return S_OK; 548 } 549 } 550 return DISP_E_BADVARTYPE; 551 } 552 553 /****************************************************************************** 554 * VariantInit [OLEAUT32.8] 555 * 556 * Initialise a variant. 557 * 558 * PARAMS 559 * pVarg [O] Variant to initialise 560 * 561 * RETURNS 562 * Nothing. 563 * 564 * NOTES 565 * This function simply sets the type of the variant to VT_EMPTY. It does not 566 * free any existing value, use VariantClear() for that. 567 */ 568 void WINAPI VariantInit(VARIANTARG* pVarg) 569 { 570 TRACE("(%p)\n", pVarg); 571 572 /* Win8.1 zeroes whole struct. Previous implementations don't set any other fields. */ 573 V_VT(pVarg) = VT_EMPTY; 574 } 575 576 HRESULT VARIANT_ClearInd(VARIANTARG *pVarg) 577 { 578 HRESULT hres; 579 580 TRACE("(%s)\n", debugstr_variant(pVarg)); 581 582 hres = VARIANT_ValidateType(V_VT(pVarg)); 583 if (FAILED(hres)) 584 return hres; 585 586 switch (V_VT(pVarg)) 587 { 588 case VT_DISPATCH: 589 case VT_UNKNOWN: 590 if (V_UNKNOWN(pVarg)) 591 IUnknown_Release(V_UNKNOWN(pVarg)); 592 break; 593 case VT_UNKNOWN | VT_BYREF: 594 case VT_DISPATCH | VT_BYREF: 595 if(*V_UNKNOWNREF(pVarg)) 596 IUnknown_Release(*V_UNKNOWNREF(pVarg)); 597 break; 598 case VT_BSTR: 599 SysFreeString(V_BSTR(pVarg)); 600 break; 601 case VT_BSTR | VT_BYREF: 602 SysFreeString(*V_BSTRREF(pVarg)); 603 break; 604 case VT_VARIANT | VT_BYREF: 605 VariantClear(V_VARIANTREF(pVarg)); 606 break; 607 case VT_RECORD: 608 case VT_RECORD | VT_BYREF: 609 { 610 struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal); 611 if (pBr->pRecInfo) 612 { 613 IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord); 614 IRecordInfo_Release(pBr->pRecInfo); 615 } 616 break; 617 } 618 default: 619 if (V_ISARRAY(pVarg) || (V_VT(pVarg) & ~VT_BYREF) == VT_SAFEARRAY) 620 { 621 if (V_ISBYREF(pVarg)) 622 { 623 if (*V_ARRAYREF(pVarg)) 624 hres = SafeArrayDestroy(*V_ARRAYREF(pVarg)); 625 } 626 else if (V_ARRAY(pVarg)) 627 hres = SafeArrayDestroy(V_ARRAY(pVarg)); 628 } 629 break; 630 } 631 632 V_VT(pVarg) = VT_EMPTY; 633 return hres; 634 } 635 636 /****************************************************************************** 637 * VariantClear [OLEAUT32.9] 638 * 639 * Clear a variant. 640 * 641 * PARAMS 642 * pVarg [I/O] Variant to clear 643 * 644 * RETURNS 645 * Success: S_OK. Any previous value in pVarg is freed and its type is set to VT_EMPTY. 646 * Failure: DISP_E_BADVARTYPE, if the variant is not a valid variant type. 647 */ 648 HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG* pVarg) 649 { 650 HRESULT hres; 651 652 TRACE("(%s)\n", debugstr_variant(pVarg)); 653 654 hres = VARIANT_ValidateType(V_VT(pVarg)); 655 656 if (SUCCEEDED(hres)) 657 { 658 if (!V_ISBYREF(pVarg)) 659 { 660 if (V_ISARRAY(pVarg) || V_VT(pVarg) == VT_SAFEARRAY) 661 { 662 hres = SafeArrayDestroy(V_ARRAY(pVarg)); 663 } 664 else if (V_VT(pVarg) == VT_BSTR) 665 { 666 SysFreeString(V_BSTR(pVarg)); 667 } 668 else if (V_VT(pVarg) == VT_RECORD) 669 { 670 struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal); 671 if (pBr->pRecInfo) 672 { 673 IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord); 674 IRecordInfo_Release(pBr->pRecInfo); 675 } 676 } 677 else if (V_VT(pVarg) == VT_DISPATCH || 678 V_VT(pVarg) == VT_UNKNOWN) 679 { 680 if (V_UNKNOWN(pVarg)) 681 IUnknown_Release(V_UNKNOWN(pVarg)); 682 } 683 } 684 V_VT(pVarg) = VT_EMPTY; 685 } 686 return hres; 687 } 688 689 /****************************************************************************** 690 * Copy an IRecordInfo object contained in a variant. 691 */ 692 static HRESULT VARIANT_CopyIRecordInfo(VARIANT *dest, VARIANT *src) 693 { 694 struct __tagBRECORD *dest_rec = &V_UNION(dest, brecVal); 695 struct __tagBRECORD *src_rec = &V_UNION(src, brecVal); 696 HRESULT hr = S_OK; 697 ULONG size; 698 699 if (!src_rec->pRecInfo) 700 { 701 if (src_rec->pvRecord) return E_INVALIDARG; 702 return S_OK; 703 } 704 705 hr = IRecordInfo_GetSize(src_rec->pRecInfo, &size); 706 if (FAILED(hr)) return hr; 707 708 /* This could look cleaner if only RecordCreate() was used, but native doesn't use it. 709 Memory should be allocated in a same way as RecordCreate() does, so RecordDestroy() 710 could free it later. */ 711 dest_rec->pvRecord = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 712 if (!dest_rec->pvRecord) return E_OUTOFMEMORY; 713 714 dest_rec->pRecInfo = src_rec->pRecInfo; 715 IRecordInfo_AddRef(src_rec->pRecInfo); 716 717 return IRecordInfo_RecordCopy(src_rec->pRecInfo, src_rec->pvRecord, dest_rec->pvRecord); 718 } 719 720 /****************************************************************************** 721 * VariantCopy [OLEAUT32.10] 722 * 723 * Copy a variant. 724 * 725 * PARAMS 726 * pvargDest [O] Destination for copy 727 * pvargSrc [I] Source variant to copy 728 * 729 * RETURNS 730 * Success: S_OK. pvargDest contains a copy of pvargSrc. 731 * Failure: DISP_E_BADVARTYPE, if either variant has an invalid type. 732 * E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an 733 * HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(), 734 * or IRecordInfo_RecordCopy(), depending on the type of pvargSrc. 735 * 736 * NOTES 737 * - If pvargSrc == pvargDest, this function does nothing, and succeeds if 738 * pvargSrc is valid. Otherwise, pvargDest is always cleared using 739 * VariantClear() before pvargSrc is copied to it. If clearing pvargDest 740 * fails, so does this function. 741 * - VT_CLSID is a valid type type for pvargSrc, but not for pvargDest. 742 * - For by-value non-intrinsic types, a deep copy is made, i.e. The whole value 743 * is copied rather than just any pointers to it. 744 * - For by-value object types the object pointer is copied and the objects 745 * reference count increased using IUnknown_AddRef(). 746 * - For all by-reference types, only the referencing pointer is copied. 747 */ 748 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc) 749 { 750 HRESULT hres = S_OK; 751 752 TRACE("(%s,%s)\n", debugstr_variant(pvargDest), debugstr_variant(pvargSrc)); 753 754 if (V_TYPE(pvargSrc) == VT_CLSID || /* VT_CLSID is a special case */ 755 FAILED(VARIANT_ValidateType(V_VT(pvargSrc)))) 756 return DISP_E_BADVARTYPE; 757 758 if (pvargSrc != pvargDest && 759 SUCCEEDED(hres = VariantClear(pvargDest))) 760 { 761 *pvargDest = *pvargSrc; /* Shallow copy the value */ 762 763 if (!V_ISBYREF(pvargSrc)) 764 { 765 switch (V_VT(pvargSrc)) 766 { 767 case VT_BSTR: 768 V_BSTR(pvargDest) = SysAllocStringByteLen((char*)V_BSTR(pvargSrc), SysStringByteLen(V_BSTR(pvargSrc))); 769 if (!V_BSTR(pvargDest)) 770 hres = E_OUTOFMEMORY; 771 break; 772 case VT_RECORD: 773 hres = VARIANT_CopyIRecordInfo(pvargDest, pvargSrc); 774 break; 775 case VT_DISPATCH: 776 case VT_UNKNOWN: 777 V_UNKNOWN(pvargDest) = V_UNKNOWN(pvargSrc); 778 if (V_UNKNOWN(pvargSrc)) 779 IUnknown_AddRef(V_UNKNOWN(pvargSrc)); 780 break; 781 default: 782 if (V_ISARRAY(pvargSrc)) 783 hres = SafeArrayCopy(V_ARRAY(pvargSrc), &V_ARRAY(pvargDest)); 784 } 785 } 786 } 787 return hres; 788 } 789 790 /* Return the byte size of a variants data */ 791 static inline size_t VARIANT_DataSize(const VARIANT* pv) 792 { 793 switch (V_TYPE(pv)) 794 { 795 case VT_I1: 796 case VT_UI1: return sizeof(BYTE); 797 case VT_I2: 798 case VT_UI2: return sizeof(SHORT); 799 case VT_INT: 800 case VT_UINT: 801 case VT_I4: 802 case VT_UI4: return sizeof(LONG); 803 case VT_I8: 804 case VT_UI8: return sizeof(LONGLONG); 805 case VT_R4: return sizeof(float); 806 case VT_R8: return sizeof(double); 807 case VT_DATE: return sizeof(DATE); 808 case VT_BOOL: return sizeof(VARIANT_BOOL); 809 case VT_DISPATCH: 810 case VT_UNKNOWN: 811 case VT_BSTR: return sizeof(void*); 812 case VT_CY: return sizeof(CY); 813 case VT_ERROR: return sizeof(SCODE); 814 } 815 TRACE("Shouldn't be called for variant %s!\n", debugstr_variant(pv)); 816 return 0; 817 } 818 819 /****************************************************************************** 820 * VariantCopyInd [OLEAUT32.11] 821 * 822 * Copy a variant, dereferencing it if it is by-reference. 823 * 824 * PARAMS 825 * pvargDest [O] Destination for copy 826 * pvargSrc [I] Source variant to copy 827 * 828 * RETURNS 829 * Success: S_OK. pvargDest contains a copy of pvargSrc. 830 * Failure: An HRESULT error code indicating the error. 831 * 832 * NOTES 833 * Failure: DISP_E_BADVARTYPE, if either variant has an invalid by-value type. 834 * E_INVALIDARG, if pvargSrc is an invalid by-reference type. 835 * E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an 836 * HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(), 837 * or IRecordInfo_RecordCopy(), depending on the type of pvargSrc. 838 * 839 * NOTES 840 * - If pvargSrc is by-value, this function behaves exactly as VariantCopy(). 841 * - If pvargSrc is by-reference, the value copied to pvargDest is the pointed-to 842 * value. 843 * - if pvargSrc == pvargDest, this function dereferences in place. Otherwise, 844 * pvargDest is always cleared using VariantClear() before pvargSrc is copied 845 * to it. If clearing pvargDest fails, so does this function. 846 */ 847 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc) 848 { 849 VARIANTARG vTmp, *pSrc = pvargSrc; 850 VARTYPE vt; 851 HRESULT hres = S_OK; 852 853 TRACE("(%s,%s)\n", debugstr_variant(pvargDest), debugstr_variant(pvargSrc)); 854 855 if (!V_ISBYREF(pvargSrc)) 856 return VariantCopy(pvargDest, pvargSrc); 857 858 /* Argument checking is more lax than VariantCopy()... */ 859 vt = V_TYPE(pvargSrc); 860 if (V_ISARRAY(pvargSrc) || (V_VT(pvargSrc) == (VT_RECORD|VT_BYREF)) || 861 (vt > VT_NULL && vt != (VARTYPE)15 && vt < VT_VOID && 862 !(V_VT(pvargSrc) & (VT_VECTOR|VT_RESERVED)))) 863 { 864 /* OK */ 865 } 866 else 867 return E_INVALIDARG; /* ...And the return value for invalid types differs too */ 868 869 if (pvargSrc == pvargDest) 870 { 871 /* In place copy. Use a shallow copy of pvargSrc & init pvargDest. 872 * This avoids an expensive VariantCopy() call - e.g. SafeArrayCopy(). 873 */ 874 vTmp = *pvargSrc; 875 pSrc = &vTmp; 876 V_VT(pvargDest) = VT_EMPTY; 877 } 878 else 879 { 880 /* Copy into another variant. Free the variant in pvargDest */ 881 if (FAILED(hres = VariantClear(pvargDest))) 882 { 883 TRACE("VariantClear() of destination failed\n"); 884 return hres; 885 } 886 } 887 888 if (V_ISARRAY(pSrc)) 889 { 890 /* Native doesn't check that *V_ARRAYREF(pSrc) is valid */ 891 hres = SafeArrayCopy(*V_ARRAYREF(pSrc), &V_ARRAY(pvargDest)); 892 } 893 else if (V_VT(pSrc) == (VT_BSTR|VT_BYREF)) 894 { 895 /* Native doesn't check that *V_BSTRREF(pSrc) is valid */ 896 V_BSTR(pvargDest) = SysAllocStringByteLen((char*)*V_BSTRREF(pSrc), SysStringByteLen(*V_BSTRREF(pSrc))); 897 } 898 else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF)) 899 { 900 hres = VARIANT_CopyIRecordInfo(pvargDest, pvargSrc); 901 } 902 else if (V_VT(pSrc) == (VT_DISPATCH|VT_BYREF) || 903 V_VT(pSrc) == (VT_UNKNOWN|VT_BYREF)) 904 { 905 /* Native doesn't check that *V_UNKNOWNREF(pSrc) is valid */ 906 V_UNKNOWN(pvargDest) = *V_UNKNOWNREF(pSrc); 907 if (*V_UNKNOWNREF(pSrc)) 908 IUnknown_AddRef(*V_UNKNOWNREF(pSrc)); 909 } 910 else if (V_VT(pSrc) == (VT_VARIANT|VT_BYREF)) 911 { 912 /* Native doesn't check that *V_VARIANTREF(pSrc) is valid */ 913 if (V_VT(V_VARIANTREF(pSrc)) == (VT_VARIANT|VT_BYREF)) 914 hres = E_INVALIDARG; /* Don't dereference more than one level */ 915 else 916 hres = VariantCopyInd(pvargDest, V_VARIANTREF(pSrc)); 917 918 /* Use the dereferenced variants type value, not VT_VARIANT */ 919 goto VariantCopyInd_Return; 920 } 921 else if (V_VT(pSrc) == (VT_DECIMAL|VT_BYREF)) 922 { 923 memcpy(&DEC_SCALE(&V_DECIMAL(pvargDest)), &DEC_SCALE(V_DECIMALREF(pSrc)), 924 sizeof(DECIMAL) - sizeof(USHORT)); 925 } 926 else 927 { 928 /* Copy the pointed to data into this variant */ 929 memcpy(&V_BYREF(pvargDest), V_BYREF(pSrc), VARIANT_DataSize(pSrc)); 930 } 931 932 V_VT(pvargDest) = V_VT(pSrc) & ~VT_BYREF; 933 934 VariantCopyInd_Return: 935 936 if (pSrc != pvargSrc) 937 VariantClear(pSrc); 938 939 TRACE("returning 0x%08x, %s\n", hres, debugstr_variant(pvargDest)); 940 return hres; 941 } 942 943 /****************************************************************************** 944 * VariantChangeType [OLEAUT32.12] 945 * 946 * Change the type of a variant. 947 * 948 * PARAMS 949 * pvargDest [O] Destination for the converted variant 950 * pvargSrc [O] Source variant to change the type of 951 * wFlags [I] VARIANT_ flags from "oleauto.h" 952 * vt [I] Variant type to change pvargSrc into 953 * 954 * RETURNS 955 * Success: S_OK. pvargDest contains the converted value. 956 * Failure: An HRESULT error code describing the failure. 957 * 958 * NOTES 959 * The LCID used for the conversion is LOCALE_USER_DEFAULT. 960 * See VariantChangeTypeEx. 961 */ 962 HRESULT WINAPI DECLSPEC_HOTPATCH VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc, 963 USHORT wFlags, VARTYPE vt) 964 { 965 return VariantChangeTypeEx( pvargDest, pvargSrc, LOCALE_USER_DEFAULT, wFlags, vt ); 966 } 967 968 /****************************************************************************** 969 * VariantChangeTypeEx [OLEAUT32.147] 970 * 971 * Change the type of a variant. 972 * 973 * PARAMS 974 * pvargDest [O] Destination for the converted variant 975 * pvargSrc [O] Source variant to change the type of 976 * lcid [I] LCID for the conversion 977 * wFlags [I] VARIANT_ flags from "oleauto.h" 978 * vt [I] Variant type to change pvargSrc into 979 * 980 * RETURNS 981 * Success: S_OK. pvargDest contains the converted value. 982 * Failure: An HRESULT error code describing the failure. 983 * 984 * NOTES 985 * pvargDest and pvargSrc can point to the same variant to perform an in-place 986 * conversion. If the conversion is successful, pvargSrc will be freed. 987 */ 988 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc, 989 LCID lcid, USHORT wFlags, VARTYPE vt) 990 { 991 HRESULT res = S_OK; 992 993 TRACE("(%s,%s,0x%08x,0x%04x,%s)\n", debugstr_variant(pvargDest), 994 debugstr_variant(pvargSrc), lcid, wFlags, debugstr_vt(vt)); 995 996 if (vt == VT_CLSID) 997 res = DISP_E_BADVARTYPE; 998 else 999 { 1000 res = VARIANT_ValidateType(V_VT(pvargSrc)); 1001 1002 if (SUCCEEDED(res)) 1003 { 1004 res = VARIANT_ValidateType(vt); 1005 1006 if (SUCCEEDED(res)) 1007 { 1008 VARIANTARG vTmp, vSrcDeref; 1009 1010 if(V_ISBYREF(pvargSrc) && !V_BYREF(pvargSrc)) 1011 res = DISP_E_TYPEMISMATCH; 1012 else 1013 { 1014 V_VT(&vTmp) = VT_EMPTY; 1015 V_VT(&vSrcDeref) = VT_EMPTY; 1016 VariantClear(&vTmp); 1017 VariantClear(&vSrcDeref); 1018 } 1019 1020 if (SUCCEEDED(res)) 1021 { 1022 res = VariantCopyInd(&vSrcDeref, pvargSrc); 1023 if (SUCCEEDED(res)) 1024 { 1025 if (V_ISARRAY(&vSrcDeref) || (vt & VT_ARRAY)) 1026 res = VARIANT_CoerceArray(&vTmp, &vSrcDeref, vt); 1027 else 1028 res = VARIANT_Coerce(&vTmp, lcid, wFlags, &vSrcDeref, vt); 1029 1030 if (SUCCEEDED(res)) { 1031 V_VT(&vTmp) = vt; 1032 res = VariantCopy(pvargDest, &vTmp); 1033 } 1034 VariantClear(&vTmp); 1035 VariantClear(&vSrcDeref); 1036 } 1037 } 1038 } 1039 } 1040 } 1041 1042 TRACE("returning 0x%08x, %s\n", res, debugstr_variant(pvargDest)); 1043 return res; 1044 } 1045 1046 /* Date Conversions */ 1047 1048 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0))) 1049 1050 /* Convert a VT_DATE value to a Julian Date */ 1051 static inline int VARIANT_JulianFromDate(int dateIn) 1052 { 1053 int julianDays = dateIn; 1054 1055 julianDays -= DATE_MIN; /* Convert to + days from 1 Jan 100 AD */ 1056 julianDays += 1757585; /* Convert to + days from 23 Nov 4713 BC (Julian) */ 1057 return julianDays; 1058 } 1059 1060 /* Convert a Julian Date to a VT_DATE value */ 1061 static inline int VARIANT_DateFromJulian(int dateIn) 1062 { 1063 int julianDays = dateIn; 1064 1065 julianDays -= 1757585; /* Convert to + days from 1 Jan 100 AD */ 1066 julianDays += DATE_MIN; /* Convert to +/- days from 1 Jan 1899 AD */ 1067 return julianDays; 1068 } 1069 1070 /* Convert a Julian date to Day/Month/Year - from PostgreSQL */ 1071 static inline void VARIANT_DMYFromJulian(int jd, USHORT *year, USHORT *month, USHORT *day) 1072 { 1073 int j, i, l, n; 1074 1075 l = jd + 68569; 1076 n = l * 4 / 146097; 1077 l -= (n * 146097 + 3) / 4; 1078 i = (4000 * (l + 1)) / 1461001; 1079 l += 31 - (i * 1461) / 4; 1080 j = (l * 80) / 2447; 1081 *day = l - (j * 2447) / 80; 1082 l = j / 11; 1083 *month = (j + 2) - (12 * l); 1084 *year = 100 * (n - 49) + i + l; 1085 } 1086 1087 /* Convert Day/Month/Year to a Julian date - from PostgreSQL */ 1088 static inline double VARIANT_JulianFromDMY(USHORT year, USHORT month, USHORT day) 1089 { 1090 int m12 = (month - 14) / 12; 1091 1092 return ((1461 * (year + 4800 + m12)) / 4 + (367 * (month - 2 - 12 * m12)) / 12 - 1093 (3 * ((year + 4900 + m12) / 100)) / 4 + day - 32075); 1094 } 1095 1096 /* Macros for accessing DOS format date/time fields */ 1097 #define DOS_YEAR(x) (1980 + (x >> 9)) 1098 #define DOS_MONTH(x) ((x >> 5) & 0xf) 1099 #define DOS_DAY(x) (x & 0x1f) 1100 #define DOS_HOUR(x) (x >> 11) 1101 #define DOS_MINUTE(x) ((x >> 5) & 0x3f) 1102 #define DOS_SECOND(x) ((x & 0x1f) << 1) 1103 /* Create a DOS format date/time */ 1104 #define DOS_DATE(d,m,y) (d | (m << 5) | ((y-1980) << 9)) 1105 #define DOS_TIME(h,m,s) ((s >> 1) | (m << 5) | (h << 11)) 1106 1107 /* Roll a date forwards or backwards to correct it */ 1108 static HRESULT VARIANT_RollUdate(UDATE *lpUd) 1109 { 1110 static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 1111 short iYear, iMonth, iDay, iHour, iMinute, iSecond; 1112 1113 /* interpret values signed */ 1114 iYear = lpUd->st.wYear; 1115 iMonth = lpUd->st.wMonth; 1116 iDay = lpUd->st.wDay; 1117 iHour = lpUd->st.wHour; 1118 iMinute = lpUd->st.wMinute; 1119 iSecond = lpUd->st.wSecond; 1120 1121 TRACE("Raw date: %d/%d/%d %d:%d:%d\n", iDay, iMonth, 1122 iYear, iHour, iMinute, iSecond); 1123 1124 if (iYear > 9999 || iYear < -9999) 1125 return E_INVALIDARG; /* Invalid value */ 1126 /* Year 0 to 29 are treated as 2000 + year */ 1127 if (iYear >= 0 && iYear < 30) 1128 iYear += 2000; 1129 /* Remaining years < 100 are treated as 1900 + year */ 1130 else if (iYear >= 30 && iYear < 100) 1131 iYear += 1900; 1132 1133 iMinute += iSecond / 60; 1134 iSecond = iSecond % 60; 1135 iHour += iMinute / 60; 1136 iMinute = iMinute % 60; 1137 iDay += iHour / 24; 1138 iHour = iHour % 24; 1139 iYear += iMonth / 12; 1140 iMonth = iMonth % 12; 1141 if (iMonth<=0) {iMonth+=12; iYear--;} 1142 while (iDay > days[iMonth]) 1143 { 1144 if (iMonth == 2 && IsLeapYear(iYear)) 1145 iDay -= 29; 1146 else 1147 iDay -= days[iMonth]; 1148 iMonth++; 1149 iYear += iMonth / 12; 1150 iMonth = iMonth % 12; 1151 } 1152 while (iDay <= 0) 1153 { 1154 iMonth--; 1155 if (iMonth<=0) {iMonth+=12; iYear--;} 1156 if (iMonth == 2 && IsLeapYear(iYear)) 1157 iDay += 29; 1158 else 1159 iDay += days[iMonth]; 1160 } 1161 1162 if (iSecond<0){iSecond+=60; iMinute--;} 1163 if (iMinute<0){iMinute+=60; iHour--;} 1164 if (iHour<0) {iHour+=24; iDay--;} 1165 if (iYear<=0) iYear+=2000; 1166 1167 lpUd->st.wYear = iYear; 1168 lpUd->st.wMonth = iMonth; 1169 lpUd->st.wDay = iDay; 1170 lpUd->st.wHour = iHour; 1171 lpUd->st.wMinute = iMinute; 1172 lpUd->st.wSecond = iSecond; 1173 1174 TRACE("Rolled date: %d/%d/%d %d:%d:%d\n", lpUd->st.wDay, lpUd->st.wMonth, 1175 lpUd->st.wYear, lpUd->st.wHour, lpUd->st.wMinute, lpUd->st.wSecond); 1176 return S_OK; 1177 } 1178 1179 /********************************************************************** 1180 * DosDateTimeToVariantTime [OLEAUT32.14] 1181 * 1182 * Convert a Dos format date and time into variant VT_DATE format. 1183 * 1184 * PARAMS 1185 * wDosDate [I] Dos format date 1186 * wDosTime [I] Dos format time 1187 * pDateOut [O] Destination for VT_DATE format 1188 * 1189 * RETURNS 1190 * Success: TRUE. pDateOut contains the converted time. 1191 * Failure: FALSE, if wDosDate or wDosTime are invalid (see notes). 1192 * 1193 * NOTES 1194 * - Dos format dates can only hold dates from 1-Jan-1980 to 31-Dec-2099. 1195 * - Dos format times are accurate to only 2 second precision. 1196 * - The format of a Dos Date is: 1197 *| Bits Values Meaning 1198 *| ---- ------ ------- 1199 *| 0-4 1-31 Day of the week. 0 rolls back one day. A value greater than 1200 *| the days in the month rolls forward the extra days. 1201 *| 5-8 1-12 Month of the year. 0 rolls back to December of the previous 1202 *| year. 13-15 are invalid. 1203 *| 9-15 0-119 Year based from 1980 (Max 2099). 120-127 are invalid. 1204 * - The format of a Dos Time is: 1205 *| Bits Values Meaning 1206 *| ---- ------ ------- 1207 *| 0-4 0-29 Seconds/2. 30 and 31 are invalid. 1208 *| 5-10 0-59 Minutes. 60-63 are invalid. 1209 *| 11-15 0-23 Hours (24 hour clock). 24-32 are invalid. 1210 */ 1211 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime, 1212 double *pDateOut) 1213 { 1214 UDATE ud; 1215 1216 TRACE("(0x%x(%d/%d/%d),0x%x(%d:%d:%d),%p)\n", 1217 wDosDate, DOS_YEAR(wDosDate), DOS_MONTH(wDosDate), DOS_DAY(wDosDate), 1218 wDosTime, DOS_HOUR(wDosTime), DOS_MINUTE(wDosTime), DOS_SECOND(wDosTime), 1219 pDateOut); 1220 1221 ud.st.wYear = DOS_YEAR(wDosDate); 1222 ud.st.wMonth = DOS_MONTH(wDosDate); 1223 if (ud.st.wYear > 2099 || ud.st.wMonth > 12) 1224 return FALSE; 1225 ud.st.wDay = DOS_DAY(wDosDate); 1226 ud.st.wHour = DOS_HOUR(wDosTime); 1227 ud.st.wMinute = DOS_MINUTE(wDosTime); 1228 ud.st.wSecond = DOS_SECOND(wDosTime); 1229 ud.st.wDayOfWeek = ud.st.wMilliseconds = 0; 1230 if (ud.st.wHour > 23 || ud.st.wMinute > 59 || ud.st.wSecond > 59) 1231 return FALSE; /* Invalid values in Dos*/ 1232 1233 return VarDateFromUdate(&ud, 0, pDateOut) == S_OK; 1234 } 1235 1236 /********************************************************************** 1237 * VariantTimeToDosDateTime [OLEAUT32.13] 1238 * 1239 * Convert a variant format date into a Dos format date and time. 1240 * 1241 * dateIn [I] VT_DATE time format 1242 * pwDosDate [O] Destination for Dos format date 1243 * pwDosTime [O] Destination for Dos format time 1244 * 1245 * RETURNS 1246 * Success: TRUE. pwDosDate and pwDosTime contains the converted values. 1247 * Failure: FALSE, if dateIn cannot be represented in Dos format. 1248 * 1249 * NOTES 1250 * See DosDateTimeToVariantTime() for Dos format details and bugs. 1251 */ 1252 INT WINAPI VariantTimeToDosDateTime(double dateIn, USHORT *pwDosDate, USHORT *pwDosTime) 1253 { 1254 UDATE ud; 1255 1256 TRACE("(%g,%p,%p)\n", dateIn, pwDosDate, pwDosTime); 1257 1258 if (FAILED(VarUdateFromDate(dateIn, 0, &ud))) 1259 return FALSE; 1260 1261 if (ud.st.wYear < 1980 || ud.st.wYear > 2099) 1262 return FALSE; 1263 1264 *pwDosDate = DOS_DATE(ud.st.wDay, ud.st.wMonth, ud.st.wYear); 1265 *pwDosTime = DOS_TIME(ud.st.wHour, ud.st.wMinute, ud.st.wSecond); 1266 1267 TRACE("Returning 0x%x(%d/%d/%d), 0x%x(%d:%d:%d)\n", 1268 *pwDosDate, DOS_YEAR(*pwDosDate), DOS_MONTH(*pwDosDate), DOS_DAY(*pwDosDate), 1269 *pwDosTime, DOS_HOUR(*pwDosTime), DOS_MINUTE(*pwDosTime), DOS_SECOND(*pwDosTime)); 1270 return TRUE; 1271 } 1272 1273 /*********************************************************************** 1274 * SystemTimeToVariantTime [OLEAUT32.184] 1275 * 1276 * Convert a System format date and time into variant VT_DATE format. 1277 * 1278 * PARAMS 1279 * lpSt [I] System format date and time 1280 * pDateOut [O] Destination for VT_DATE format date 1281 * 1282 * RETURNS 1283 * Success: TRUE. *pDateOut contains the converted value. 1284 * Failure: FALSE, if lpSt cannot be represented in VT_DATE format. 1285 */ 1286 INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut) 1287 { 1288 UDATE ud; 1289 1290 TRACE("(%p->%d/%d/%d %d:%d:%d,%p)\n", lpSt, lpSt->wDay, lpSt->wMonth, 1291 lpSt->wYear, lpSt->wHour, lpSt->wMinute, lpSt->wSecond, pDateOut); 1292 1293 if (lpSt->wMonth > 12) 1294 return FALSE; 1295 if (lpSt->wDay > 31) 1296 return FALSE; 1297 if ((short)lpSt->wYear < 0) 1298 return FALSE; 1299 1300 ud.st = *lpSt; 1301 return VarDateFromUdate(&ud, 0, pDateOut) == S_OK; 1302 } 1303 1304 /*********************************************************************** 1305 * VariantTimeToSystemTime [OLEAUT32.185] 1306 * 1307 * Convert a variant VT_DATE into a System format date and time. 1308 * 1309 * PARAMS 1310 * datein [I] Variant VT_DATE format date 1311 * lpSt [O] Destination for System format date and time 1312 * 1313 * RETURNS 1314 * Success: TRUE. *lpSt contains the converted value. 1315 * Failure: FALSE, if dateIn is too large or small. 1316 */ 1317 INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt) 1318 { 1319 UDATE ud; 1320 1321 TRACE("(%g,%p)\n", dateIn, lpSt); 1322 1323 if (FAILED(VarUdateFromDate(dateIn, 0, &ud))) 1324 return FALSE; 1325 1326 *lpSt = ud.st; 1327 return TRUE; 1328 } 1329 1330 /*********************************************************************** 1331 * VarDateFromUdateEx [OLEAUT32.319] 1332 * 1333 * Convert an unpacked format date and time to a variant VT_DATE. 1334 * 1335 * PARAMS 1336 * pUdateIn [I] Unpacked format date and time to convert 1337 * lcid [I] Locale identifier for the conversion 1338 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h") 1339 * pDateOut [O] Destination for variant VT_DATE. 1340 * 1341 * RETURNS 1342 * Success: S_OK. *pDateOut contains the converted value. 1343 * Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format. 1344 */ 1345 HRESULT WINAPI VarDateFromUdateEx(UDATE *pUdateIn, LCID lcid, ULONG dwFlags, DATE *pDateOut) 1346 { 1347 UDATE ud; 1348 double dateVal = 0; 1349 1350 TRACE("(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08x,0x%08x,%p)\n", pUdateIn, 1351 pUdateIn->st.wMonth, pUdateIn->st.wDay, pUdateIn->st.wYear, 1352 pUdateIn->st.wHour, pUdateIn->st.wMinute, pUdateIn->st.wSecond, 1353 pUdateIn->st.wMilliseconds, pUdateIn->st.wDayOfWeek, 1354 pUdateIn->wDayOfYear, lcid, dwFlags, pDateOut); 1355 1356 if (lcid != MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)) 1357 FIXME("lcid possibly not handled, treating as en-us\n"); 1358 if (dwFlags & ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) 1359 FIXME("unsupported flags: %x\n", dwFlags); 1360 1361 ud = *pUdateIn; 1362 1363 if (dwFlags & VAR_VALIDDATE) 1364 WARN("Ignoring VAR_VALIDDATE\n"); 1365 1366 if (FAILED(VARIANT_RollUdate(&ud))) 1367 return E_INVALIDARG; 1368 1369 /* Date */ 1370 if (!(dwFlags & VAR_TIMEVALUEONLY)) 1371 dateVal = VARIANT_DateFromJulian(VARIANT_JulianFromDMY(ud.st.wYear, ud.st.wMonth, ud.st.wDay)); 1372 1373 if ((dwFlags & VAR_TIMEVALUEONLY) || !(dwFlags & VAR_DATEVALUEONLY)) 1374 { 1375 double dateSign = (dateVal < 0.0) ? -1.0 : 1.0; 1376 1377 /* Time */ 1378 dateVal += ud.st.wHour / 24.0 * dateSign; 1379 dateVal += ud.st.wMinute / 1440.0 * dateSign; 1380 dateVal += ud.st.wSecond / 86400.0 * dateSign; 1381 } 1382 1383 TRACE("Returning %g\n", dateVal); 1384 *pDateOut = dateVal; 1385 return S_OK; 1386 } 1387 1388 /*********************************************************************** 1389 * VarDateFromUdate [OLEAUT32.330] 1390 * 1391 * Convert an unpacked format date and time to a variant VT_DATE. 1392 * 1393 * PARAMS 1394 * pUdateIn [I] Unpacked format date and time to convert 1395 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h") 1396 * pDateOut [O] Destination for variant VT_DATE. 1397 * 1398 * RETURNS 1399 * Success: S_OK. *pDateOut contains the converted value. 1400 * Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format. 1401 * 1402 * NOTES 1403 * This function uses the United States English locale for the conversion. Use 1404 * VarDateFromUdateEx() for alternate locales. 1405 */ 1406 HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut) 1407 { 1408 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); 1409 1410 return VarDateFromUdateEx(pUdateIn, lcid, dwFlags, pDateOut); 1411 } 1412 1413 /*********************************************************************** 1414 * VarUdateFromDate [OLEAUT32.331] 1415 * 1416 * Convert a variant VT_DATE into an unpacked format date and time. 1417 * 1418 * PARAMS 1419 * datein [I] Variant VT_DATE format date 1420 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h") 1421 * lpUdate [O] Destination for unpacked format date and time 1422 * 1423 * RETURNS 1424 * Success: S_OK. *lpUdate contains the converted value. 1425 * Failure: E_INVALIDARG, if dateIn is too large or small. 1426 */ 1427 HRESULT WINAPI VarUdateFromDate(DATE dateIn, ULONG dwFlags, UDATE *lpUdate) 1428 { 1429 /* Cumulative totals of days per month */ 1430 static const USHORT cumulativeDays[] = 1431 { 1432 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 1433 }; 1434 double datePart, timePart; 1435 int julianDays; 1436 1437 TRACE("(%g,0x%08x,%p)\n", dateIn, dwFlags, lpUdate); 1438 1439 if (dateIn <= (DATE_MIN - 1.0) || dateIn >= (DATE_MAX + 1.0)) 1440 return E_INVALIDARG; 1441 1442 datePart = dateIn < 0.0 ? ceil(dateIn) : floor(dateIn); 1443 /* Compensate for int truncation (always downwards) */ 1444 timePart = fabs(dateIn - datePart) + 0.00000000001; 1445 if (timePart >= 1.0) 1446 timePart -= 0.00000000001; 1447 1448 /* Date */ 1449 julianDays = VARIANT_JulianFromDate(dateIn); 1450 VARIANT_DMYFromJulian(julianDays, &lpUdate->st.wYear, &lpUdate->st.wMonth, 1451 &lpUdate->st.wDay); 1452 1453 datePart = (datePart + 1.5) / 7.0; 1454 lpUdate->st.wDayOfWeek = (datePart - floor(datePart)) * 7; 1455 if (lpUdate->st.wDayOfWeek == 0) 1456 lpUdate->st.wDayOfWeek = 5; 1457 else if (lpUdate->st.wDayOfWeek == 1) 1458 lpUdate->st.wDayOfWeek = 6; 1459 else 1460 lpUdate->st.wDayOfWeek -= 2; 1461 1462 if (lpUdate->st.wMonth > 2 && IsLeapYear(lpUdate->st.wYear)) 1463 lpUdate->wDayOfYear = 1; /* After February, in a leap year */ 1464 else 1465 lpUdate->wDayOfYear = 0; 1466 1467 lpUdate->wDayOfYear += cumulativeDays[lpUdate->st.wMonth]; 1468 lpUdate->wDayOfYear += lpUdate->st.wDay; 1469 1470 /* Time */ 1471 timePart *= 24.0; 1472 lpUdate->st.wHour = timePart; 1473 timePart -= lpUdate->st.wHour; 1474 timePart *= 60.0; 1475 lpUdate->st.wMinute = timePart; 1476 timePart -= lpUdate->st.wMinute; 1477 timePart *= 60.0; 1478 lpUdate->st.wSecond = timePart; 1479 timePart -= lpUdate->st.wSecond; 1480 lpUdate->st.wMilliseconds = 0; 1481 if (timePart > 0.5) 1482 { 1483 /* Round the milliseconds, adjusting the time/date forward if needed */ 1484 if (lpUdate->st.wSecond < 59) 1485 lpUdate->st.wSecond++; 1486 else 1487 { 1488 lpUdate->st.wSecond = 0; 1489 if (lpUdate->st.wMinute < 59) 1490 lpUdate->st.wMinute++; 1491 else 1492 { 1493 lpUdate->st.wMinute = 0; 1494 if (lpUdate->st.wHour < 23) 1495 lpUdate->st.wHour++; 1496 else 1497 { 1498 lpUdate->st.wHour = 0; 1499 /* Roll over a whole day */ 1500 if (++lpUdate->st.wDay > 28) 1501 VARIANT_RollUdate(lpUdate); 1502 } 1503 } 1504 } 1505 } 1506 return S_OK; 1507 } 1508 1509 #define GET_NUMBER_TEXT(fld,name) \ 1510 buff[0] = 0; \ 1511 if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \ 1512 WARN("buffer too small for " #fld "\n"); \ 1513 else \ 1514 if (buff[0]) lpChars->name = buff[0]; \ 1515 TRACE("lcid 0x%x, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name) 1516 1517 /* Get the valid number characters for an lcid */ 1518 static void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags) 1519 { 1520 static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',',','$',0,'.',',' }; 1521 static VARIANT_NUMBER_CHARS lastChars; 1522 static LCID lastLcid = -1; 1523 static DWORD lastFlags = 0; 1524 LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE; 1525 WCHAR buff[4]; 1526 1527 /* To make caching thread-safe, a critical section is needed */ 1528 EnterCriticalSection(&cache_cs); 1529 1530 /* Asking for default locale entries is very expensive: It is a registry 1531 server call. So cache one locally, as Microsoft does it too */ 1532 if(lcid == lastLcid && dwFlags == lastFlags) 1533 { 1534 memcpy(lpChars, &lastChars, sizeof(defaultChars)); 1535 LeaveCriticalSection(&cache_cs); 1536 return; 1537 } 1538 1539 memcpy(lpChars, &defaultChars, sizeof(defaultChars)); 1540 GET_NUMBER_TEXT(LOCALE_SNEGATIVESIGN, cNegativeSymbol); 1541 GET_NUMBER_TEXT(LOCALE_SPOSITIVESIGN, cPositiveSymbol); 1542 GET_NUMBER_TEXT(LOCALE_SDECIMAL, cDecimalPoint); 1543 GET_NUMBER_TEXT(LOCALE_STHOUSAND, cDigitSeparator); 1544 GET_NUMBER_TEXT(LOCALE_SMONDECIMALSEP, cCurrencyDecimalPoint); 1545 GET_NUMBER_TEXT(LOCALE_SMONTHOUSANDSEP, cCurrencyDigitSeparator); 1546 1547 /* Local currency symbols are often 2 characters */ 1548 lpChars->cCurrencyLocal2 = '\0'; 1549 switch(GetLocaleInfoW(lcid, lctype|LOCALE_SCURRENCY, buff, ARRAY_SIZE(buff))) 1550 { 1551 case 3: lpChars->cCurrencyLocal2 = buff[1]; /* Fall through */ 1552 case 2: lpChars->cCurrencyLocal = buff[0]; 1553 break; 1554 default: WARN("buffer too small for LOCALE_SCURRENCY\n"); 1555 } 1556 TRACE("lcid 0x%x, cCurrencyLocal =%d,%d '%c','%c'\n", lcid, lpChars->cCurrencyLocal, 1557 lpChars->cCurrencyLocal2, lpChars->cCurrencyLocal, lpChars->cCurrencyLocal2); 1558 1559 memcpy(&lastChars, lpChars, sizeof(defaultChars)); 1560 lastLcid = lcid; 1561 lastFlags = dwFlags; 1562 LeaveCriticalSection(&cache_cs); 1563 } 1564 1565 /* Number Parsing States */ 1566 #define B_PROCESSING_EXPONENT 0x1 1567 #define B_NEGATIVE_EXPONENT 0x2 1568 #define B_EXPONENT_START 0x4 1569 #define B_INEXACT_ZEROS 0x8 1570 #define B_LEADING_ZERO 0x10 1571 #define B_PROCESSING_HEX 0x20 1572 #define B_PROCESSING_OCT 0x40 1573 1574 /********************************************************************** 1575 * VarParseNumFromStr [OLEAUT32.46] 1576 * 1577 * Parse a string containing a number into a NUMPARSE structure. 1578 * 1579 * PARAMS 1580 * lpszStr [I] String to parse number from 1581 * lcid [I] Locale Id for the conversion 1582 * dwFlags [I] 0, or LOCALE_NOUSEROVERRIDE to use system default number chars 1583 * pNumprs [I/O] Destination for parsed number 1584 * rgbDig [O] Destination for digits read in 1585 * 1586 * RETURNS 1587 * Success: S_OK. pNumprs and rgbDig contain the parsed representation of 1588 * the number. 1589 * Failure: E_INVALIDARG, if any parameter is invalid. 1590 * DISP_E_TYPEMISMATCH, if the string is not a number or is formatted 1591 * incorrectly. 1592 * DISP_E_OVERFLOW, if rgbDig is too small to hold the number. 1593 * 1594 * NOTES 1595 * pNumprs must have the following fields set: 1596 * cDig: Set to the size of rgbDig. 1597 * dwInFlags: Set to the allowable syntax of the number using NUMPRS_ flags 1598 * from "oleauto.h". 1599 * 1600 * FIXME 1601 * - I am unsure if this function should parse non-Arabic (e.g. Thai) 1602 * numerals, so this has not been implemented. 1603 */ 1604 HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, 1605 NUMPARSE *pNumprs, BYTE *rgbDig) 1606 { 1607 VARIANT_NUMBER_CHARS chars; 1608 BYTE rgbTmp[1024]; 1609 DWORD dwState = B_EXPONENT_START|B_INEXACT_ZEROS; 1610 int iMaxDigits = ARRAY_SIZE(rgbTmp); 1611 int cchUsed = 0; 1612 1613 TRACE("(%s,%d,0x%08x,%p,%p)\n", debugstr_w(lpszStr), lcid, dwFlags, pNumprs, rgbDig); 1614 1615 if (!pNumprs || !rgbDig) 1616 return E_INVALIDARG; 1617 1618 if (pNumprs->cDig < iMaxDigits) 1619 iMaxDigits = pNumprs->cDig; 1620 1621 pNumprs->cDig = 0; 1622 pNumprs->dwOutFlags = 0; 1623 pNumprs->cchUsed = 0; 1624 pNumprs->nBaseShift = 0; 1625 pNumprs->nPwr10 = 0; 1626 1627 if (!lpszStr) 1628 return DISP_E_TYPEMISMATCH; 1629 1630 VARIANT_GetLocalisedNumberChars(&chars, lcid, dwFlags); 1631 1632 /* First consume all the leading symbols and space from the string */ 1633 while (1) 1634 { 1635 if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && iswspace(*lpszStr)) 1636 { 1637 pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE; 1638 do 1639 { 1640 cchUsed++; 1641 lpszStr++; 1642 } while (iswspace(*lpszStr)); 1643 } 1644 else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS && 1645 *lpszStr == chars.cPositiveSymbol && 1646 !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS)) 1647 { 1648 pNumprs->dwOutFlags |= NUMPRS_LEADING_PLUS; 1649 cchUsed++; 1650 lpszStr++; 1651 } 1652 else if (pNumprs->dwInFlags & NUMPRS_LEADING_MINUS && 1653 *lpszStr == chars.cNegativeSymbol && 1654 !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS)) 1655 { 1656 pNumprs->dwOutFlags |= (NUMPRS_LEADING_MINUS|NUMPRS_NEG); 1657 cchUsed++; 1658 lpszStr++; 1659 } 1660 else if (pNumprs->dwInFlags & NUMPRS_CURRENCY && 1661 !(pNumprs->dwOutFlags & NUMPRS_CURRENCY) && 1662 *lpszStr == chars.cCurrencyLocal && 1663 (!chars.cCurrencyLocal2 || lpszStr[1] == chars.cCurrencyLocal2)) 1664 { 1665 pNumprs->dwOutFlags |= NUMPRS_CURRENCY; 1666 cchUsed++; 1667 lpszStr++; 1668 /* Only accept currency characters */ 1669 chars.cDecimalPoint = chars.cCurrencyDecimalPoint; 1670 chars.cDigitSeparator = chars.cCurrencyDigitSeparator; 1671 } 1672 else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' && 1673 !(pNumprs->dwOutFlags & NUMPRS_PARENS)) 1674 { 1675 pNumprs->dwOutFlags |= NUMPRS_PARENS; 1676 cchUsed++; 1677 lpszStr++; 1678 } 1679 else 1680 break; 1681 } 1682 1683 if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY)) 1684 { 1685 /* Only accept non-currency characters */ 1686 chars.cCurrencyDecimalPoint = chars.cDecimalPoint; 1687 chars.cCurrencyDigitSeparator = chars.cDigitSeparator; 1688 } 1689 1690 if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) && 1691 pNumprs->dwInFlags & NUMPRS_HEX_OCT) 1692 { 1693 dwState |= B_PROCESSING_HEX; 1694 pNumprs->dwOutFlags |= NUMPRS_HEX_OCT; 1695 cchUsed=cchUsed+2; 1696 lpszStr=lpszStr+2; 1697 } 1698 else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) && 1699 pNumprs->dwInFlags & NUMPRS_HEX_OCT) 1700 { 1701 dwState |= B_PROCESSING_OCT; 1702 pNumprs->dwOutFlags |= NUMPRS_HEX_OCT; 1703 cchUsed=cchUsed+2; 1704 lpszStr=lpszStr+2; 1705 } 1706 1707 /* Strip Leading zeros */ 1708 while (*lpszStr == '0') 1709 { 1710 dwState |= B_LEADING_ZERO; 1711 cchUsed++; 1712 lpszStr++; 1713 } 1714 1715 while (*lpszStr) 1716 { 1717 if (iswdigit(*lpszStr)) 1718 { 1719 if (dwState & B_PROCESSING_EXPONENT) 1720 { 1721 int exponentSize = 0; 1722 if (dwState & B_EXPONENT_START) 1723 { 1724 if (!iswdigit(*lpszStr)) 1725 break; /* No exponent digits - invalid */ 1726 while (*lpszStr == '0') 1727 { 1728 /* Skip leading zero's in the exponent */ 1729 cchUsed++; 1730 lpszStr++; 1731 } 1732 } 1733 1734 while (iswdigit(*lpszStr)) 1735 { 1736 exponentSize *= 10; 1737 exponentSize += *lpszStr - '0'; 1738 cchUsed++; 1739 lpszStr++; 1740 } 1741 if (dwState & B_NEGATIVE_EXPONENT) 1742 exponentSize = -exponentSize; 1743 /* Add the exponent into the powers of 10 */ 1744 pNumprs->nPwr10 += exponentSize; 1745 dwState &= ~(B_PROCESSING_EXPONENT|B_EXPONENT_START); 1746 lpszStr--; /* back up to allow processing of next char */ 1747 } 1748 else 1749 { 1750 if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX) 1751 && !(dwState & B_PROCESSING_OCT)) 1752 { 1753 pNumprs->dwOutFlags |= NUMPRS_INEXACT; 1754 1755 if (*lpszStr != '0') 1756 dwState &= ~B_INEXACT_ZEROS; /* Inexact number with non-trailing zeros */ 1757 1758 /* This digit can't be represented, but count it in nPwr10 */ 1759 if (pNumprs->dwOutFlags & NUMPRS_DECIMAL) 1760 pNumprs->nPwr10--; 1761 else 1762 pNumprs->nPwr10++; 1763 } 1764 else 1765 { 1766 if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) 1767 break; 1768 1769 if (pNumprs->dwOutFlags & NUMPRS_DECIMAL) 1770 pNumprs->nPwr10--; /* Count decimal points in nPwr10 */ 1771 1772 rgbTmp[pNumprs->cDig] = *lpszStr - '0'; 1773 } 1774 pNumprs->cDig++; 1775 cchUsed++; 1776 } 1777 } 1778 else if (*lpszStr == chars.cDigitSeparator && pNumprs->dwInFlags & NUMPRS_THOUSANDS) 1779 { 1780 pNumprs->dwOutFlags |= NUMPRS_THOUSANDS; 1781 cchUsed++; 1782 } 1783 else if (*lpszStr == chars.cDecimalPoint && 1784 pNumprs->dwInFlags & NUMPRS_DECIMAL && 1785 !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT))) 1786 { 1787 pNumprs->dwOutFlags |= NUMPRS_DECIMAL; 1788 cchUsed++; 1789 1790 /* If we have no digits so far, skip leading zeros */ 1791 if (!pNumprs->cDig) 1792 { 1793 while (lpszStr[1] == '0') 1794 { 1795 dwState |= B_LEADING_ZERO; 1796 cchUsed++; 1797 lpszStr++; 1798 pNumprs->nPwr10--; 1799 } 1800 } 1801 } 1802 else if (((*lpszStr >= 'a' && *lpszStr <= 'f') || 1803 (*lpszStr >= 'A' && *lpszStr <= 'F')) && 1804 dwState & B_PROCESSING_HEX) 1805 { 1806 if (pNumprs->cDig >= iMaxDigits) 1807 { 1808 return DISP_E_OVERFLOW; 1809 } 1810 else 1811 { 1812 if (*lpszStr >= 'a') 1813 rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10; 1814 else 1815 rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10; 1816 } 1817 pNumprs->cDig++; 1818 cchUsed++; 1819 } 1820 else if ((*lpszStr == 'e' || *lpszStr == 'E') && 1821 pNumprs->dwInFlags & NUMPRS_EXPONENT && 1822 !(pNumprs->dwOutFlags & NUMPRS_EXPONENT)) 1823 { 1824 dwState |= B_PROCESSING_EXPONENT; 1825 pNumprs->dwOutFlags |= NUMPRS_EXPONENT; 1826 cchUsed++; 1827 } 1828 else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cPositiveSymbol) 1829 { 1830 cchUsed++; /* Ignore positive exponent */ 1831 } 1832 else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cNegativeSymbol) 1833 { 1834 dwState |= B_NEGATIVE_EXPONENT; 1835 cchUsed++; 1836 } 1837 else 1838 break; /* Stop at an unrecognised character */ 1839 1840 lpszStr++; 1841 } 1842 1843 if (!pNumprs->cDig && dwState & B_LEADING_ZERO) 1844 { 1845 /* Ensure a 0 on its own gets stored */ 1846 pNumprs->cDig = 1; 1847 rgbTmp[0] = 0; 1848 } 1849 1850 if (pNumprs->dwOutFlags & NUMPRS_EXPONENT && dwState & B_PROCESSING_EXPONENT) 1851 { 1852 pNumprs->cchUsed = cchUsed; 1853 WARN("didn't completely parse exponent\n"); 1854 return DISP_E_TYPEMISMATCH; /* Failed to completely parse the exponent */ 1855 } 1856 1857 if (pNumprs->dwOutFlags & NUMPRS_INEXACT) 1858 { 1859 if (dwState & B_INEXACT_ZEROS) 1860 pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* All zeros doesn't set NUMPRS_INEXACT */ 1861 } else if(pNumprs->dwInFlags & NUMPRS_HEX_OCT) 1862 { 1863 /* copy all of the digits into the output digit buffer */ 1864 /* this is exactly what windows does although it also returns */ 1865 /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */ 1866 memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE)); 1867 1868 if (dwState & B_PROCESSING_HEX) { 1869 /* hex numbers have always the same format */ 1870 pNumprs->nPwr10=0; 1871 pNumprs->nBaseShift=4; 1872 } else { 1873 if (dwState & B_PROCESSING_OCT) { 1874 /* oct numbers have always the same format */ 1875 pNumprs->nPwr10=0; 1876 pNumprs->nBaseShift=3; 1877 } else { 1878 while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1]) 1879 { 1880 pNumprs->nPwr10++; 1881 pNumprs->cDig--; 1882 } 1883 } 1884 } 1885 } else 1886 { 1887 /* Remove trailing zeros from the last (whole number or decimal) part */ 1888 while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1]) 1889 { 1890 pNumprs->nPwr10++; 1891 pNumprs->cDig--; 1892 } 1893 } 1894 1895 if (pNumprs->cDig <= iMaxDigits) 1896 pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* Ignore stripped zeros for NUMPRS_INEXACT */ 1897 else 1898 pNumprs->cDig = iMaxDigits; /* Only return iMaxDigits worth of digits */ 1899 1900 /* Copy the digits we processed into rgbDig */ 1901 memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE)); 1902 1903 /* Consume any trailing symbols and space */ 1904 while (1) 1905 { 1906 if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && iswspace(*lpszStr)) 1907 { 1908 pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE; 1909 do 1910 { 1911 cchUsed++; 1912 lpszStr++; 1913 } while (iswspace(*lpszStr)); 1914 } 1915 else if (pNumprs->dwInFlags & NUMPRS_TRAILING_PLUS && 1916 !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS) && 1917 *lpszStr == chars.cPositiveSymbol) 1918 { 1919 pNumprs->dwOutFlags |= NUMPRS_TRAILING_PLUS; 1920 cchUsed++; 1921 lpszStr++; 1922 } 1923 else if (pNumprs->dwInFlags & NUMPRS_TRAILING_MINUS && 1924 !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS) && 1925 *lpszStr == chars.cNegativeSymbol) 1926 { 1927 pNumprs->dwOutFlags |= (NUMPRS_TRAILING_MINUS|NUMPRS_NEG); 1928 cchUsed++; 1929 lpszStr++; 1930 } 1931 else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == ')' && 1932 pNumprs->dwOutFlags & NUMPRS_PARENS) 1933 { 1934 cchUsed++; 1935 lpszStr++; 1936 pNumprs->dwOutFlags |= NUMPRS_NEG; 1937 } 1938 else 1939 break; 1940 } 1941 1942 if (pNumprs->dwOutFlags & NUMPRS_PARENS && !(pNumprs->dwOutFlags & NUMPRS_NEG)) 1943 { 1944 pNumprs->cchUsed = cchUsed; 1945 return DISP_E_TYPEMISMATCH; /* Opening parenthesis not matched */ 1946 } 1947 1948 if (pNumprs->dwInFlags & NUMPRS_USE_ALL && *lpszStr != '\0') 1949 return DISP_E_TYPEMISMATCH; /* Not all chars were consumed */ 1950 1951 if (!pNumprs->cDig) 1952 return DISP_E_TYPEMISMATCH; /* No Number found */ 1953 1954 pNumprs->cchUsed = cchUsed; 1955 return S_OK; 1956 } 1957 1958 /* VTBIT flags indicating an integer value */ 1959 #define INTEGER_VTBITS (VTBIT_I1|VTBIT_UI1|VTBIT_I2|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_I8|VTBIT_UI8) 1960 /* VTBIT flags indicating a real number value */ 1961 #define REAL_VTBITS (VTBIT_R4|VTBIT_R8|VTBIT_CY) 1962 1963 /* Helper macros to check whether bit pattern fits in VARIANT (x is a ULONG64 ) */ 1964 #define FITS_AS_I1(x) ((x) >> 8 == 0) 1965 #define FITS_AS_I2(x) ((x) >> 16 == 0) 1966 #define FITS_AS_I4(x) ((x) >> 32 == 0) 1967 1968 /********************************************************************** 1969 * VarNumFromParseNum [OLEAUT32.47] 1970 * 1971 * Convert a NUMPARSE structure into a numeric Variant type. 1972 * 1973 * PARAMS 1974 * pNumprs [I] Source for parsed number. cDig must be set to the size of rgbDig 1975 * rgbDig [I] Source for the numbers digits 1976 * dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types 1977 * pVarDst [O] Destination for the converted Variant value. 1978 * 1979 * RETURNS 1980 * Success: S_OK. pVarDst contains the converted value. 1981 * Failure: E_INVALIDARG, if any parameter is invalid. 1982 * DISP_E_OVERFLOW, if the number is too big for the types set in dwVtBits. 1983 * 1984 * NOTES 1985 * - The smallest favoured type present in dwVtBits that can represent the 1986 * number in pNumprs without losing precision is used. 1987 * - Signed types are preferred over unsigned types of the same size. 1988 * - Preferred types in order are: integer, float, double, currency then decimal. 1989 * - Rounding (dropping of decimal points) occurs without error. See VarI8FromR8() 1990 * for details of the rounding method. 1991 * - pVarDst is not cleared before the result is stored in it. 1992 * - WinXP and Win2003 support VTBIT_I8, VTBIT_UI8 but that's buggy (by 1993 * design?): If some other VTBIT's for integers are specified together 1994 * with VTBIT_I8 and the number will fit only in a VT_I8 Windows will "cast" 1995 * the number to the smallest requested integer truncating this way the 1996 * number. Wine doesn't implement this "feature" (yet?). 1997 */ 1998 HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig, 1999 ULONG dwVtBits, VARIANT *pVarDst) 2000 { 2001 /* Scale factors and limits for double arithmetic */ 2002 static const double dblMultipliers[11] = { 2003 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 2004 1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0 2005 }; 2006 static const double dblMinimums[11] = { 2007 R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0, 2008 R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0, 2009 R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0 2010 }; 2011 static const double dblMaximums[11] = { 2012 R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0, 2013 R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0, 2014 R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0 2015 }; 2016 2017 int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0; 2018 2019 TRACE("(%p,%p,0x%x,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst); 2020 2021 if (pNumprs->nBaseShift) 2022 { 2023 /* nBaseShift indicates a hex or octal number */ 2024 ULONG64 ul64 = 0; 2025 LONG64 l64; 2026 int i; 2027 2028 /* Convert the hex or octal number string into a UI64 */ 2029 for (i = 0; i < pNumprs->cDig; i++) 2030 { 2031 if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i])) 2032 { 2033 TRACE("Overflow multiplying digits\n"); 2034 return DISP_E_OVERFLOW; 2035 } 2036 ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i]; 2037 } 2038 2039 /* also make a negative representation */ 2040 l64=-ul64; 2041 2042 /* Try signed and unsigned types in size order */ 2043 if (dwVtBits & VTBIT_I1 && FITS_AS_I1(ul64)) 2044 { 2045 V_VT(pVarDst) = VT_I1; 2046 V_I1(pVarDst) = ul64; 2047 return S_OK; 2048 } 2049 else if (dwVtBits & VTBIT_UI1 && FITS_AS_I1(ul64)) 2050 { 2051 V_VT(pVarDst) = VT_UI1; 2052 V_UI1(pVarDst) = ul64; 2053 return S_OK; 2054 } 2055 else if (dwVtBits & VTBIT_I2 && FITS_AS_I2(ul64)) 2056 { 2057 V_VT(pVarDst) = VT_I2; 2058 V_I2(pVarDst) = ul64; 2059 return S_OK; 2060 } 2061 else if (dwVtBits & VTBIT_UI2 && FITS_AS_I2(ul64)) 2062 { 2063 V_VT(pVarDst) = VT_UI2; 2064 V_UI2(pVarDst) = ul64; 2065 return S_OK; 2066 } 2067 else if (dwVtBits & VTBIT_I4 && FITS_AS_I4(ul64)) 2068 { 2069 V_VT(pVarDst) = VT_I4; 2070 V_I4(pVarDst) = ul64; 2071 return S_OK; 2072 } 2073 else if (dwVtBits & VTBIT_UI4 && FITS_AS_I4(ul64)) 2074 { 2075 V_VT(pVarDst) = VT_UI4; 2076 V_UI4(pVarDst) = ul64; 2077 return S_OK; 2078 } 2079 else if (dwVtBits & VTBIT_I8 && ((ul64 <= I8_MAX)||(l64>=I8_MIN))) 2080 { 2081 V_VT(pVarDst) = VT_I8; 2082 V_I8(pVarDst) = ul64; 2083 return S_OK; 2084 } 2085 else if (dwVtBits & VTBIT_UI8) 2086 { 2087 V_VT(pVarDst) = VT_UI8; 2088 V_UI8(pVarDst) = ul64; 2089 return S_OK; 2090 } 2091 else if ((dwVtBits & VTBIT_DECIMAL) == VTBIT_DECIMAL) 2092 { 2093 V_VT(pVarDst) = VT_DECIMAL; 2094 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0); 2095 DEC_HI32(&V_DECIMAL(pVarDst)) = 0; 2096 DEC_LO64(&V_DECIMAL(pVarDst)) = ul64; 2097 return S_OK; 2098 } 2099 else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) 2100 { 2101 V_VT(pVarDst) = VT_R4; 2102 if (ul64 <= I4_MAX) 2103 V_R4(pVarDst) = ul64; 2104 else 2105 V_R4(pVarDst) = l64; 2106 return S_OK; 2107 } 2108 else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) 2109 { 2110 V_VT(pVarDst) = VT_R8; 2111 if (ul64 <= I4_MAX) 2112 V_R8(pVarDst) = ul64; 2113 else 2114 V_R8(pVarDst) = l64; 2115 return S_OK; 2116 } 2117 2118 TRACE("Overflow: possible return types: 0x%x, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64)); 2119 return DISP_E_OVERFLOW; 2120 } 2121 2122 /* Count the number of relevant fractional and whole digits stored, 2123 * And compute the divisor/multiplier to scale the number by. 2124 */ 2125 if (pNumprs->nPwr10 < 0) 2126 { 2127 if (-pNumprs->nPwr10 >= pNumprs->cDig) 2128 { 2129 /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */ 2130 wholeNumberDigits = 0; 2131 fractionalDigits = pNumprs->cDig; 2132 divisor10 = -pNumprs->nPwr10; 2133 } 2134 else 2135 { 2136 /* An exactly represented real number e.g. 1.024 */ 2137 wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10; 2138 fractionalDigits = pNumprs->cDig - wholeNumberDigits; 2139 divisor10 = pNumprs->cDig - wholeNumberDigits; 2140 } 2141 } 2142 else if (pNumprs->nPwr10 == 0) 2143 { 2144 /* An exactly represented whole number e.g. 1024 */ 2145 wholeNumberDigits = pNumprs->cDig; 2146 fractionalDigits = 0; 2147 } 2148 else /* pNumprs->nPwr10 > 0 */ 2149 { 2150 /* A whole number followed by nPwr10 0's e.g. 102400 */ 2151 wholeNumberDigits = pNumprs->cDig; 2152 fractionalDigits = 0; 2153 multiplier10 = pNumprs->nPwr10; 2154 } 2155 2156 TRACE("cDig %d; nPwr10 %d, whole %d, frac %d mult %d; div %d\n", 2157 pNumprs->cDig, pNumprs->nPwr10, wholeNumberDigits, fractionalDigits, 2158 multiplier10, divisor10); 2159 2160 if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) && 2161 (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_DECIMAL)))) 2162 { 2163 /* We have one or more integer output choices, and either: 2164 * 1) An integer input value, or 2165 * 2) A real number input value but no floating output choices. 2166 * Alternately, we have a DECIMAL output available and an integer input. 2167 * 2168 * So, place the integer value into pVarDst, using the smallest type 2169 * possible and preferring signed over unsigned types. 2170 */ 2171 BOOL bOverflow = FALSE, bNegative; 2172 ULONG64 ul64 = 0; 2173 int i; 2174 2175 /* Convert the integer part of the number into a UI8 */ 2176 for (i = 0; i < wholeNumberDigits; i++) 2177 { 2178 if (ul64 > UI8_MAX / 10 || (ul64 == UI8_MAX / 10 && rgbDig[i] > UI8_MAX % 10)) 2179 { 2180 TRACE("Overflow multiplying digits\n"); 2181 bOverflow = TRUE; 2182 break; 2183 } 2184 ul64 = ul64 * 10 + rgbDig[i]; 2185 } 2186 2187 /* Account for the scale of the number */ 2188 if (!bOverflow && multiplier10) 2189 { 2190 for (i = 0; i < multiplier10; i++) 2191 { 2192 if (ul64 > (UI8_MAX / 10)) 2193 { 2194 TRACE("Overflow scaling number\n"); 2195 bOverflow = TRUE; 2196 break; 2197 } 2198 ul64 = ul64 * 10; 2199 } 2200 } 2201 2202 /* If we have any fractional digits, round the value. 2203 * Note we don't have to do this if divisor10 is < 1, 2204 * because this means the fractional part must be < 0.5 2205 */ 2206 if (!bOverflow && fractionalDigits && divisor10 > 0) 2207 { 2208 const BYTE* fracDig = rgbDig + wholeNumberDigits; 2209 BOOL bAdjust = FALSE; 2210 2211 TRACE("first decimal value is %d\n", *fracDig); 2212 2213 if (*fracDig > 5) 2214 bAdjust = TRUE; /* > 0.5 */ 2215 else if (*fracDig == 5) 2216 { 2217 for (i = 1; i < fractionalDigits; i++) 2218 { 2219 if (fracDig[i]) 2220 { 2221 bAdjust = TRUE; /* > 0.5 */ 2222 break; 2223 } 2224 } 2225 /* If exactly 0.5, round only odd values */ 2226 if (i == fractionalDigits && (ul64 & 1)) 2227 bAdjust = TRUE; 2228 } 2229 2230 if (bAdjust) 2231 { 2232 if (ul64 == UI8_MAX) 2233 { 2234 TRACE("Overflow after rounding\n"); 2235 bOverflow = TRUE; 2236 } 2237 ul64++; 2238 } 2239 } 2240 2241 /* Zero is not a negative number */ 2242 bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64; 2243 2244 TRACE("Integer value is 0x%s, bNeg %d\n", wine_dbgstr_longlong(ul64), bNegative); 2245 2246 /* For negative integers, try the signed types in size order */ 2247 if (!bOverflow && bNegative) 2248 { 2249 if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8)) 2250 { 2251 if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN) 2252 { 2253 V_VT(pVarDst) = VT_I1; 2254 V_I1(pVarDst) = -ul64; 2255 return S_OK; 2256 } 2257 else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN) 2258 { 2259 V_VT(pVarDst) = VT_I2; 2260 V_I2(pVarDst) = -ul64; 2261 return S_OK; 2262 } 2263 else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN)) 2264 { 2265 V_VT(pVarDst) = VT_I4; 2266 V_I4(pVarDst) = -ul64; 2267 return S_OK; 2268 } 2269 else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1) 2270 { 2271 V_VT(pVarDst) = VT_I8; 2272 V_I8(pVarDst) = -ul64; 2273 return S_OK; 2274 } 2275 else if ((dwVtBits & (REAL_VTBITS|VTBIT_DECIMAL)) == VTBIT_DECIMAL) 2276 { 2277 /* Decimal is only output choice left - fast path */ 2278 V_VT(pVarDst) = VT_DECIMAL; 2279 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0); 2280 DEC_HI32(&V_DECIMAL(pVarDst)) = 0; 2281 DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64; 2282 return S_OK; 2283 } 2284 } 2285 } 2286 else if (!bOverflow) 2287 { 2288 /* For positive integers, try signed then unsigned types in size order */ 2289 if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX) 2290 { 2291 V_VT(pVarDst) = VT_I1; 2292 V_I1(pVarDst) = ul64; 2293 return S_OK; 2294 } 2295 else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX) 2296 { 2297 V_VT(pVarDst) = VT_UI1; 2298 V_UI1(pVarDst) = ul64; 2299 return S_OK; 2300 } 2301 else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX) 2302 { 2303 V_VT(pVarDst) = VT_I2; 2304 V_I2(pVarDst) = ul64; 2305 return S_OK; 2306 } 2307 else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX) 2308 { 2309 V_VT(pVarDst) = VT_UI2; 2310 V_UI2(pVarDst) = ul64; 2311 return S_OK; 2312 } 2313 else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX) 2314 { 2315 V_VT(pVarDst) = VT_I4; 2316 V_I4(pVarDst) = ul64; 2317 return S_OK; 2318 } 2319 else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX) 2320 { 2321 V_VT(pVarDst) = VT_UI4; 2322 V_UI4(pVarDst) = ul64; 2323 return S_OK; 2324 } 2325 else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX) 2326 { 2327 V_VT(pVarDst) = VT_I8; 2328 V_I8(pVarDst) = ul64; 2329 return S_OK; 2330 } 2331 else if (dwVtBits & VTBIT_UI8) 2332 { 2333 V_VT(pVarDst) = VT_UI8; 2334 V_UI8(pVarDst) = ul64; 2335 return S_OK; 2336 } 2337 else if ((dwVtBits & (REAL_VTBITS|VTBIT_DECIMAL)) == VTBIT_DECIMAL) 2338 { 2339 /* Decimal is only output choice left - fast path */ 2340 V_VT(pVarDst) = VT_DECIMAL; 2341 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0); 2342 DEC_HI32(&V_DECIMAL(pVarDst)) = 0; 2343 DEC_LO64(&V_DECIMAL(pVarDst)) = ul64; 2344 return S_OK; 2345 } 2346 } 2347 } 2348 2349 if (dwVtBits & REAL_VTBITS) 2350 { 2351 /* Try to put the number into a float or real */ 2352 BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG; 2353 double whole = 0.0; 2354 int i; 2355 2356 /* Convert the number into a double */ 2357 for (i = 0; i < pNumprs->cDig; i++) 2358 whole = whole * 10.0 + rgbDig[i]; 2359 2360 TRACE("Whole double value is %16.16g\n", whole); 2361 2362 /* Account for the scale */ 2363 while (multiplier10 > 10) 2364 { 2365 if (whole > dblMaximums[10]) 2366 { 2367 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); 2368 bOverflow = TRUE; 2369 break; 2370 } 2371 whole = whole * dblMultipliers[10]; 2372 multiplier10 -= 10; 2373 } 2374 if (multiplier10 && !bOverflow) 2375 { 2376 if (whole > dblMaximums[multiplier10]) 2377 { 2378 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); 2379 bOverflow = TRUE; 2380 } 2381 else 2382 whole = whole * dblMultipliers[multiplier10]; 2383 } 2384 2385 if (!bOverflow) 2386 TRACE("Scaled double value is %16.16g\n", whole); 2387 2388 while (divisor10 > 10 && !bOverflow) 2389 { 2390 if (whole < dblMinimums[10] && whole != 0) 2391 { 2392 whole = 0; /* ignore underflow */ 2393 divisor10 = 0; 2394 break; 2395 } 2396 whole = whole / dblMultipliers[10]; 2397 divisor10 -= 10; 2398 } 2399 if (divisor10 && !bOverflow) 2400 { 2401 if (whole < dblMinimums[divisor10] && whole != 0) 2402 { 2403 whole = 0; /* ignore underflow */ 2404 divisor10 = 0; 2405 } 2406 else 2407 whole = whole / dblMultipliers[divisor10]; 2408 } 2409 if (!bOverflow) 2410 TRACE("Final double value is %16.16g\n", whole); 2411 2412 if (dwVtBits & VTBIT_R4 && 2413 ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0)) 2414 { 2415 TRACE("Set R4 to final value\n"); 2416 V_VT(pVarDst) = VT_R4; /* Fits into a float */ 2417 V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole; 2418 return S_OK; 2419 } 2420 2421 if (dwVtBits & VTBIT_R8) 2422 { 2423 TRACE("Set R8 to final value\n"); 2424 V_VT(pVarDst) = VT_R8; /* Fits into a double */ 2425 V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole; 2426 return S_OK; 2427 } 2428 2429 if (dwVtBits & VTBIT_CY) 2430 { 2431 if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst)))) 2432 { 2433 V_VT(pVarDst) = VT_CY; /* Fits into a currency */ 2434 TRACE("Set CY to final value\n"); 2435 return S_OK; 2436 } 2437 TRACE("Value Overflows CY\n"); 2438 } 2439 } 2440 2441 if (dwVtBits & VTBIT_DECIMAL) 2442 { 2443 int i; 2444 ULONG carry; 2445 ULONG64 tmp; 2446 DECIMAL* pDec = &V_DECIMAL(pVarDst); 2447 2448 DECIMAL_SETZERO(*pDec); 2449 DEC_LO32(pDec) = 0; 2450 2451 if (pNumprs->dwOutFlags & NUMPRS_NEG) 2452 DEC_SIGN(pDec) = DECIMAL_NEG; 2453 else 2454 DEC_SIGN(pDec) = DECIMAL_POS; 2455 2456 /* Factor the significant digits */ 2457 for (i = 0; i < pNumprs->cDig; i++) 2458 { 2459 tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i]; 2460 carry = (ULONG)(tmp >> 32); 2461 DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX); 2462 tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry; 2463 carry = (ULONG)(tmp >> 32); 2464 DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX); 2465 tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry; 2466 DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX); 2467 2468 if (tmp >> 32 & UI4_MAX) 2469 { 2470 VarNumFromParseNum_DecOverflow: 2471 TRACE("Overflow\n"); 2472 DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX; 2473 return DISP_E_OVERFLOW; 2474 } 2475 } 2476 2477 /* Account for the scale of the number */ 2478 while (multiplier10 > 0) 2479 { 2480 tmp = (ULONG64)DEC_LO32(pDec) * 10; 2481 carry = (ULONG)(tmp >> 32); 2482 DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX); 2483 tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry; 2484 carry = (ULONG)(tmp >> 32); 2485 DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX); 2486 tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry; 2487 DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX); 2488 2489 if (tmp >> 32 & UI4_MAX) 2490 goto VarNumFromParseNum_DecOverflow; 2491 multiplier10--; 2492 } 2493 DEC_SCALE(pDec) = divisor10; 2494 2495 V_VT(pVarDst) = VT_DECIMAL; 2496 return S_OK; 2497 } 2498 return DISP_E_OVERFLOW; /* No more output choices */ 2499 } 2500 2501 /********************************************************************** 2502 * VarCat [OLEAUT32.318] 2503 * 2504 * Concatenates one variant onto another. 2505 * 2506 * PARAMS 2507 * left [I] First variant 2508 * right [I] Second variant 2509 * result [O] Result variant 2510 * 2511 * RETURNS 2512 * Success: S_OK. 2513 * Failure: An HRESULT error code indicating the error. 2514 */ 2515 HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out) 2516 { 2517 BSTR left_str = NULL, right_str = NULL; 2518 VARTYPE leftvt, rightvt; 2519 HRESULT hres; 2520 2521 TRACE("%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), out); 2522 2523 leftvt = V_VT(left); 2524 rightvt = V_VT(right); 2525 2526 /* when both left and right are NULL the result is NULL */ 2527 if (leftvt == VT_NULL && rightvt == VT_NULL) 2528 { 2529 V_VT(out) = VT_NULL; 2530 return S_OK; 2531 } 2532 2533 /* There are many special case for errors and return types */ 2534 if (leftvt == VT_VARIANT && (rightvt == VT_ERROR || 2535 rightvt == VT_DATE || rightvt == VT_DECIMAL)) 2536 hres = DISP_E_TYPEMISMATCH; 2537 else if ((leftvt == VT_I2 || leftvt == VT_I4 || 2538 leftvt == VT_R4 || leftvt == VT_R8 || 2539 leftvt == VT_CY || leftvt == VT_BOOL || 2540 leftvt == VT_BSTR || leftvt == VT_I1 || 2541 leftvt == VT_UI1 || leftvt == VT_UI2 || 2542 leftvt == VT_UI4 || leftvt == VT_I8 || 2543 leftvt == VT_UI8 || leftvt == VT_INT || 2544 leftvt == VT_UINT || leftvt == VT_EMPTY || 2545 leftvt == VT_NULL || leftvt == VT_DATE || 2546 leftvt == VT_DECIMAL || leftvt == VT_DISPATCH) 2547 && 2548 (rightvt == VT_I2 || rightvt == VT_I4 || 2549 rightvt == VT_R4 || rightvt == VT_R8 || 2550 rightvt == VT_CY || rightvt == VT_BOOL || 2551 rightvt == VT_BSTR || rightvt == VT_I1 || 2552 rightvt == VT_UI1 || rightvt == VT_UI2 || 2553 rightvt == VT_UI4 || rightvt == VT_I8 || 2554 rightvt == VT_UI8 || rightvt == VT_INT || 2555 rightvt == VT_UINT || rightvt == VT_EMPTY || 2556 rightvt == VT_NULL || rightvt == VT_DATE || 2557 rightvt == VT_DECIMAL || rightvt == VT_DISPATCH)) 2558 hres = S_OK; 2559 else if (rightvt == VT_ERROR && leftvt < VT_VOID) 2560 hres = DISP_E_TYPEMISMATCH; 2561 else if (leftvt == VT_ERROR && (rightvt == VT_DATE || 2562 rightvt == VT_ERROR || rightvt == VT_DECIMAL)) 2563 hres = DISP_E_TYPEMISMATCH; 2564 else if (rightvt == VT_DATE || rightvt == VT_ERROR || 2565 rightvt == VT_DECIMAL) 2566 hres = DISP_E_BADVARTYPE; 2567 else if (leftvt == VT_ERROR || rightvt == VT_ERROR) 2568 hres = DISP_E_TYPEMISMATCH; 2569 else if (leftvt == VT_VARIANT) 2570 hres = DISP_E_TYPEMISMATCH; 2571 else if (rightvt == VT_VARIANT && (leftvt == VT_EMPTY || 2572 leftvt == VT_NULL || leftvt == VT_I2 || 2573 leftvt == VT_I4 || leftvt == VT_R4 || 2574 leftvt == VT_R8 || leftvt == VT_CY || 2575 leftvt == VT_DATE || leftvt == VT_BSTR || 2576 leftvt == VT_BOOL || leftvt == VT_DECIMAL || 2577 leftvt == VT_I1 || leftvt == VT_UI1 || 2578 leftvt == VT_UI2 || leftvt == VT_UI4 || 2579 leftvt == VT_I8 || leftvt == VT_UI8 || 2580 leftvt == VT_INT || leftvt == VT_UINT)) 2581 hres = DISP_E_TYPEMISMATCH; 2582 else 2583 hres = DISP_E_BADVARTYPE; 2584 2585 /* if result type is not S_OK, then no need to go further */ 2586 if (hres != S_OK) 2587 { 2588 V_VT(out) = VT_EMPTY; 2589 return hres; 2590 } 2591 2592 if (leftvt == VT_BSTR) 2593 left_str = V_BSTR(left); 2594 else 2595 { 2596 VARIANT converted, *tmp = left; 2597 2598 VariantInit(&converted); 2599 if(leftvt == VT_DISPATCH) 2600 { 2601 hres = VARIANT_FetchDispatchValue(left, &converted); 2602 if(FAILED(hres)) 2603 goto failed; 2604 2605 tmp = &converted; 2606 } 2607 2608 hres = VariantChangeTypeEx(&converted, tmp, 0, VARIANT_ALPHABOOL|VARIANT_LOCALBOOL, VT_BSTR); 2609 if (SUCCEEDED(hres)) 2610 left_str = V_BSTR(&converted); 2611 else if (hres != DISP_E_TYPEMISMATCH) 2612 { 2613 VariantClear(&converted); 2614 goto failed; 2615 } 2616 } 2617 2618 if (rightvt == VT_BSTR) 2619 right_str = V_BSTR(right); 2620 else 2621 { 2622 VARIANT converted, *tmp = right; 2623 2624 VariantInit(&converted); 2625 if(rightvt == VT_DISPATCH) 2626 { 2627 hres = VARIANT_FetchDispatchValue(right, &converted); 2628 if(FAILED(hres)) 2629 goto failed; 2630 2631 tmp = &converted; 2632 } 2633 2634 hres = VariantChangeTypeEx(&converted, tmp, 0, VARIANT_ALPHABOOL|VARIANT_LOCALBOOL, VT_BSTR); 2635 if (SUCCEEDED(hres)) 2636 right_str = V_BSTR(&converted); 2637 else if (hres != DISP_E_TYPEMISMATCH) 2638 { 2639 VariantClear(&converted); 2640 goto failed; 2641 } 2642 } 2643 2644 2645 V_VT(out) = VT_BSTR; 2646 hres = VarBstrCat(left_str, right_str, &V_BSTR(out)); 2647 2648 failed: 2649 if(V_VT(left) != VT_BSTR) 2650 SysFreeString(left_str); 2651 if(V_VT(right) != VT_BSTR) 2652 SysFreeString(right_str); 2653 return hres; 2654 } 2655 2656 2657 /* Wrapper around VariantChangeTypeEx() which permits changing a 2658 variant with VT_RESERVED flag set. Needed by VarCmp. */ 2659 static HRESULT _VarChangeTypeExWrap (VARIANTARG* pvargDest, 2660 VARIANTARG* pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt) 2661 { 2662 VARIANTARG vtmpsrc = *pvargSrc; 2663 2664 V_VT(&vtmpsrc) &= ~VT_RESERVED; 2665 return VariantChangeTypeEx(pvargDest,&vtmpsrc,lcid,wFlags,vt); 2666 } 2667 2668 /********************************************************************** 2669 * VarCmp [OLEAUT32.176] 2670 * 2671 * Compare two variants. 2672 * 2673 * PARAMS 2674 * left [I] First variant 2675 * right [I] Second variant 2676 * lcid [I] LCID (locale identifier) for the comparison 2677 * flags [I] Flags to be used in the comparison: 2678 * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS, 2679 * NORM_IGNOREWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA 2680 * 2681 * RETURNS 2682 * VARCMP_LT: left variant is less than right variant. 2683 * VARCMP_EQ: input variants are equal. 2684 * VARCMP_GT: left variant is greater than right variant. 2685 * VARCMP_NULL: either one of the input variants is NULL. 2686 * Failure: An HRESULT error code indicating the error. 2687 * 2688 * NOTES 2689 * Native VarCmp up to and including WinXP doesn't like I1, UI2, VT_UI4, 2690 * UI8 and UINT as input variants. INT is accepted only as left variant. 2691 * 2692 * If both input variants are ERROR then VARCMP_EQ will be returned, else 2693 * an ERROR variant will trigger an error. 2694 * 2695 * Both input variants can have VT_RESERVED flag set which is ignored 2696 * unless one and only one of the variants is a BSTR and the other one 2697 * is not an EMPTY variant. All four VT_RESERVED combinations have a 2698 * different meaning: 2699 * - BSTR and other: BSTR is always greater than the other variant. 2700 * - BSTR|VT_RESERVED and other: a string comparison is performed. 2701 * - BSTR and other|VT_RESERVED: If the BSTR is a number a numeric 2702 * comparison will take place else the BSTR is always greater. 2703 * - BSTR|VT_RESERVED and other|VT_RESERVED: It seems that the other 2704 * variant is ignored and the return value depends only on the sign 2705 * of the BSTR if it is a number else the BSTR is always greater. A 2706 * positive BSTR is greater, a negative one is smaller than the other 2707 * variant. 2708 * 2709 * SEE 2710 * VarBstrCmp for the lcid and flags usage. 2711 */ 2712 HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags) 2713 { 2714 VARTYPE lvt, rvt, vt; 2715 VARIANT rv,lv; 2716 DWORD xmask; 2717 HRESULT rc; 2718 2719 TRACE("(%s,%s,0x%08x,0x%08x)\n", debugstr_variant(left), debugstr_variant(right), lcid, flags); 2720 2721 lvt = V_VT(left) & VT_TYPEMASK; 2722 rvt = V_VT(right) & VT_TYPEMASK; 2723 xmask = (1 << lvt) | (1 << rvt); 2724 2725 /* If we have any flag set except VT_RESERVED bail out. 2726 Same for the left input variant type > VT_INT and for the 2727 right input variant type > VT_I8. Yes, VT_INT is only supported 2728 as left variant. Go figure */ 2729 if (((V_VT(left) | V_VT(right)) & ~VT_TYPEMASK & ~VT_RESERVED) || 2730 lvt > VT_INT || rvt > VT_I8) { 2731 return DISP_E_BADVARTYPE; 2732 } 2733 2734 /* Don't ask me why but native VarCmp cannot handle: VT_I1, VT_UI2, VT_UI4, 2735 VT_UINT and VT_UI8. Tested with DCOM98, Win2k, WinXP */ 2736 if (rvt == VT_INT || xmask & (VTBIT_I1 | VTBIT_UI2 | VTBIT_UI4 | VTBIT_UI8 | 2737 VTBIT_DISPATCH | VTBIT_VARIANT | VTBIT_UNKNOWN | VTBIT_15)) 2738 return DISP_E_TYPEMISMATCH; 2739 2740 /* If both variants are VT_ERROR return VARCMP_EQ */ 2741 if (xmask == VTBIT_ERROR) 2742 return VARCMP_EQ; 2743 else if (xmask & VTBIT_ERROR) 2744 return DISP_E_TYPEMISMATCH; 2745 2746 if (xmask & VTBIT_NULL) 2747 return VARCMP_NULL; 2748 2749 VariantInit(&lv); 2750 VariantInit(&rv); 2751 2752 /* Two BSTRs, ignore VT_RESERVED */ 2753 if (xmask == VTBIT_BSTR) 2754 return VarBstrCmp(V_BSTR(left), V_BSTR(right), lcid, flags); 2755 2756 /* A BSTR and another variant; we have to take care of VT_RESERVED */ 2757 if (xmask & VTBIT_BSTR) { 2758 VARIANT *bstrv, *nonbv; 2759 VARTYPE nonbvt; 2760 int swap = 0; 2761 2762 /* Swap the variants so the BSTR is always on the left */ 2763 if (lvt == VT_BSTR) { 2764 bstrv = left; 2765 nonbv = right; 2766 nonbvt = rvt; 2767 } else { 2768 swap = 1; 2769 bstrv = right; 2770 nonbv = left; 2771 nonbvt = lvt; 2772 } 2773 2774 /* BSTR and EMPTY: ignore VT_RESERVED */ 2775 if (nonbvt == VT_EMPTY) 2776 rc = (!V_BSTR(bstrv) || !*V_BSTR(bstrv)) ? VARCMP_EQ : VARCMP_GT; 2777 else { 2778 VARTYPE breserv = V_VT(bstrv) & ~VT_TYPEMASK; 2779 VARTYPE nreserv = V_VT(nonbv) & ~VT_TYPEMASK; 2780 2781 if (!breserv && !nreserv) 2782 /* No VT_RESERVED set ==> BSTR always greater */ 2783 rc = VARCMP_GT; 2784 else if (breserv && !nreserv) { 2785 /* BSTR has VT_RESERVED set. Do a string comparison */ 2786 rc = VariantChangeTypeEx(&rv,nonbv,lcid,0,VT_BSTR); 2787 if (FAILED(rc)) 2788 return rc; 2789 rc = VarBstrCmp(V_BSTR(bstrv), V_BSTR(&rv), lcid, flags); 2790 VariantClear(&rv); 2791 } else if (V_BSTR(bstrv) && *V_BSTR(bstrv)) { 2792 /* Non NULL nor empty BSTR */ 2793 /* If the BSTR is not a number the BSTR is greater */ 2794 rc = _VarChangeTypeExWrap(&lv,bstrv,lcid,0,VT_R8); 2795 if (FAILED(rc)) 2796 rc = VARCMP_GT; 2797 else if (breserv && nreserv) 2798 /* FIXME: This is strange: with both VT_RESERVED set it 2799 looks like the result depends only on the sign of 2800 the BSTR number */ 2801 rc = (V_R8(&lv) >= 0) ? VARCMP_GT : VARCMP_LT; 2802 else 2803 /* Numeric comparison, will be handled below. 2804 VARCMP_NULL used only to break out. */ 2805 rc = VARCMP_NULL; 2806 VariantClear(&lv); 2807 VariantClear(&rv); 2808 } else 2809 /* Empty or NULL BSTR */ 2810 rc = VARCMP_GT; 2811 } 2812 /* Fixup the return code if we swapped left and right */ 2813 if (swap) { 2814 if (rc == VARCMP_GT) 2815 rc = VARCMP_LT; 2816 else if (rc == VARCMP_LT) 2817 rc = VARCMP_GT; 2818 } 2819 if (rc != VARCMP_NULL) 2820 return rc; 2821 } 2822 2823 if (xmask & VTBIT_DECIMAL) 2824 vt = VT_DECIMAL; 2825 else if (xmask & VTBIT_BSTR) 2826 vt = VT_R8; 2827 else if (xmask & VTBIT_R4) 2828 vt = VT_R4; 2829 else if (xmask & (VTBIT_R8 | VTBIT_DATE)) 2830 vt = VT_R8; 2831 else if (xmask & VTBIT_CY) 2832 vt = VT_CY; 2833 else 2834 /* default to I8 */ 2835 vt = VT_I8; 2836 2837 /* Coerce the variants */ 2838 rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt); 2839 if (rc == DISP_E_OVERFLOW && vt != VT_R8) { 2840 /* Overflow, change to R8 */ 2841 vt = VT_R8; 2842 rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt); 2843 } 2844 if (FAILED(rc)) 2845 return rc; 2846 rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt); 2847 if (rc == DISP_E_OVERFLOW && vt != VT_R8) { 2848 /* Overflow, change to R8 */ 2849 vt = VT_R8; 2850 rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt); 2851 if (FAILED(rc)) 2852 return rc; 2853 rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt); 2854 } 2855 if (FAILED(rc)) 2856 return rc; 2857 2858 #define _VARCMP(a,b) \ 2859 (((a) == (b)) ? VARCMP_EQ : (((a) < (b)) ? VARCMP_LT : VARCMP_GT)) 2860 2861 switch (vt) { 2862 case VT_CY: 2863 return VarCyCmp(V_CY(&lv), V_CY(&rv)); 2864 case VT_DECIMAL: 2865 return VarDecCmp(&V_DECIMAL(&lv), &V_DECIMAL(&rv)); 2866 case VT_I8: 2867 return _VARCMP(V_I8(&lv), V_I8(&rv)); 2868 case VT_R4: 2869 return _VARCMP(V_R4(&lv), V_R4(&rv)); 2870 case VT_R8: 2871 return _VARCMP(V_R8(&lv), V_R8(&rv)); 2872 default: 2873 /* We should never get here */ 2874 return E_FAIL; 2875 } 2876 #undef _VARCMP 2877 } 2878 2879 /********************************************************************** 2880 * VarAnd [OLEAUT32.142] 2881 * 2882 * Computes the logical AND of two variants. 2883 * 2884 * PARAMS 2885 * left [I] First variant 2886 * right [I] Second variant 2887 * result [O] Result variant 2888 * 2889 * RETURNS 2890 * Success: S_OK. 2891 * Failure: An HRESULT error code indicating the error. 2892 */ 2893 HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result) 2894 { 2895 HRESULT hres = S_OK; 2896 VARTYPE resvt = VT_EMPTY; 2897 VARTYPE leftvt,rightvt; 2898 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; 2899 VARIANT varLeft, varRight; 2900 VARIANT tempLeft, tempRight; 2901 2902 VariantInit(&varLeft); 2903 VariantInit(&varRight); 2904 VariantInit(&tempLeft); 2905 VariantInit(&tempRight); 2906 2907 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 2908 2909 /* Handle VT_DISPATCH by storing and taking address of returned value */ 2910 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) 2911 { 2912 hres = VARIANT_FetchDispatchValue(left, &tempLeft); 2913 if (FAILED(hres)) goto VarAnd_Exit; 2914 left = &tempLeft; 2915 } 2916 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) 2917 { 2918 hres = VARIANT_FetchDispatchValue(right, &tempRight); 2919 if (FAILED(hres)) goto VarAnd_Exit; 2920 right = &tempRight; 2921 } 2922 2923 leftvt = V_VT(left)&VT_TYPEMASK; 2924 rightvt = V_VT(right)&VT_TYPEMASK; 2925 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); 2926 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK); 2927 2928 if (leftExtraFlags != rightExtraFlags) 2929 { 2930 hres = DISP_E_BADVARTYPE; 2931 goto VarAnd_Exit; 2932 } 2933 ExtraFlags = leftExtraFlags; 2934 2935 /* Native VarAnd always returns an error when using extra 2936 * flags or if the variant combination is I8 and INT. 2937 */ 2938 if ((leftvt == VT_I8 && rightvt == VT_INT) || 2939 (leftvt == VT_INT && rightvt == VT_I8) || 2940 ExtraFlags != 0) 2941 { 2942 hres = DISP_E_BADVARTYPE; 2943 goto VarAnd_Exit; 2944 } 2945 2946 /* Determine return type */ 2947 else if (leftvt == VT_I8 || rightvt == VT_I8) 2948 resvt = VT_I8; 2949 else if (leftvt == VT_I4 || rightvt == VT_I4 || 2950 leftvt == VT_UINT || rightvt == VT_UINT || 2951 leftvt == VT_INT || rightvt == VT_INT || 2952 leftvt == VT_R4 || rightvt == VT_R4 || 2953 leftvt == VT_R8 || rightvt == VT_R8 || 2954 leftvt == VT_CY || rightvt == VT_CY || 2955 leftvt == VT_DATE || rightvt == VT_DATE || 2956 leftvt == VT_I1 || rightvt == VT_I1 || 2957 leftvt == VT_UI2 || rightvt == VT_UI2 || 2958 leftvt == VT_UI4 || rightvt == VT_UI4 || 2959 leftvt == VT_UI8 || rightvt == VT_UI8 || 2960 leftvt == VT_DECIMAL || rightvt == VT_DECIMAL) 2961 resvt = VT_I4; 2962 else if (leftvt == VT_UI1 || rightvt == VT_UI1 || 2963 leftvt == VT_I2 || rightvt == VT_I2 || 2964 leftvt == VT_EMPTY || rightvt == VT_EMPTY) 2965 if ((leftvt == VT_NULL && rightvt == VT_UI1) || 2966 (leftvt == VT_UI1 && rightvt == VT_NULL) || 2967 (leftvt == VT_UI1 && rightvt == VT_UI1)) 2968 resvt = VT_UI1; 2969 else 2970 resvt = VT_I2; 2971 else if (leftvt == VT_BOOL || rightvt == VT_BOOL || 2972 (leftvt == VT_BSTR && rightvt == VT_BSTR)) 2973 resvt = VT_BOOL; 2974 else if (leftvt == VT_NULL || rightvt == VT_NULL || 2975 leftvt == VT_BSTR || rightvt == VT_BSTR) 2976 resvt = VT_NULL; 2977 else 2978 { 2979 hres = DISP_E_BADVARTYPE; 2980 goto VarAnd_Exit; 2981 } 2982 2983 if (leftvt == VT_NULL || rightvt == VT_NULL) 2984 { 2985 /* 2986 * Special cases for when left variant is VT_NULL 2987 * (VT_NULL & 0 = VT_NULL, VT_NULL & value = value) 2988 */ 2989 if (leftvt == VT_NULL) 2990 { 2991 VARIANT_BOOL b; 2992 switch(rightvt) 2993 { 2994 case VT_I1: if (V_I1(right)) resvt = VT_NULL; break; 2995 case VT_UI1: if (V_UI1(right)) resvt = VT_NULL; break; 2996 case VT_I2: if (V_I2(right)) resvt = VT_NULL; break; 2997 case VT_UI2: if (V_UI2(right)) resvt = VT_NULL; break; 2998 case VT_I4: if (V_I4(right)) resvt = VT_NULL; break; 2999 case VT_UI4: if (V_UI4(right)) resvt = VT_NULL; break; 3000 case VT_I8: if (V_I8(right)) resvt = VT_NULL; break; 3001 case VT_UI8: if (V_UI8(right)) resvt = VT_NULL; break; 3002 case VT_INT: if (V_INT(right)) resvt = VT_NULL; break; 3003 case VT_UINT: if (V_UINT(right)) resvt = VT_NULL; break; 3004 case VT_BOOL: if (V_BOOL(right)) resvt = VT_NULL; break; 3005 case VT_R4: if (V_R4(right)) resvt = VT_NULL; break; 3006 case VT_R8: if (V_R8(right)) resvt = VT_NULL; break; 3007 case VT_CY: 3008 if(V_CY(right).int64) 3009 resvt = VT_NULL; 3010 break; 3011 case VT_DECIMAL: 3012 if (DEC_HI32(&V_DECIMAL(right)) || 3013 DEC_LO64(&V_DECIMAL(right))) 3014 resvt = VT_NULL; 3015 break; 3016 case VT_BSTR: 3017 hres = VarBoolFromStr(V_BSTR(right), 3018 LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b); 3019 if (FAILED(hres)) 3020 return hres; 3021 else if (b) 3022 V_VT(result) = VT_NULL; 3023 else 3024 { 3025 V_VT(result) = VT_BOOL; 3026 V_BOOL(result) = b; 3027 } 3028 goto VarAnd_Exit; 3029 } 3030 } 3031 V_VT(result) = resvt; 3032 goto VarAnd_Exit; 3033 } 3034 3035 hres = VariantCopy(&varLeft, left); 3036 if (FAILED(hres)) goto VarAnd_Exit; 3037 3038 hres = VariantCopy(&varRight, right); 3039 if (FAILED(hres)) goto VarAnd_Exit; 3040 3041 if (resvt == VT_I4 && V_VT(&varLeft) == VT_UI4) 3042 V_VT(&varLeft) = VT_I4; /* Don't overflow */ 3043 else 3044 { 3045 double d; 3046 3047 if (V_VT(&varLeft) == VT_BSTR && 3048 FAILED(VarR8FromStr(V_BSTR(&varLeft), 3049 LOCALE_USER_DEFAULT, 0, &d))) 3050 hres = VariantChangeType(&varLeft,&varLeft, 3051 VARIANT_LOCALBOOL, VT_BOOL); 3052 if (SUCCEEDED(hres) && V_VT(&varLeft) != resvt) 3053 hres = VariantChangeType(&varLeft,&varLeft,0,resvt); 3054 if (FAILED(hres)) goto VarAnd_Exit; 3055 } 3056 3057 if (resvt == VT_I4 && V_VT(&varRight) == VT_UI4) 3058 V_VT(&varRight) = VT_I4; /* Don't overflow */ 3059 else 3060 { 3061 double d; 3062 3063 if (V_VT(&varRight) == VT_BSTR && 3064 FAILED(VarR8FromStr(V_BSTR(&varRight), 3065 LOCALE_USER_DEFAULT, 0, &d))) 3066 hres = VariantChangeType(&varRight, &varRight, 3067 VARIANT_LOCALBOOL, VT_BOOL); 3068 if (SUCCEEDED(hres) && V_VT(&varRight) != resvt) 3069 hres = VariantChangeType(&varRight, &varRight, 0, resvt); 3070 if (FAILED(hres)) goto VarAnd_Exit; 3071 } 3072 3073 V_VT(result) = resvt; 3074 switch(resvt) 3075 { 3076 case VT_I8: 3077 V_I8(result) = V_I8(&varLeft) & V_I8(&varRight); 3078 break; 3079 case VT_I4: 3080 V_I4(result) = V_I4(&varLeft) & V_I4(&varRight); 3081 break; 3082 case VT_I2: 3083 V_I2(result) = V_I2(&varLeft) & V_I2(&varRight); 3084 break; 3085 case VT_UI1: 3086 V_UI1(result) = V_UI1(&varLeft) & V_UI1(&varRight); 3087 break; 3088 case VT_BOOL: 3089 V_BOOL(result) = V_BOOL(&varLeft) & V_BOOL(&varRight); 3090 break; 3091 default: 3092 FIXME("Couldn't bitwise AND variant types %d,%d\n", 3093 leftvt,rightvt); 3094 } 3095 3096 VarAnd_Exit: 3097 VariantClear(&varLeft); 3098 VariantClear(&varRight); 3099 VariantClear(&tempLeft); 3100 VariantClear(&tempRight); 3101 3102 return hres; 3103 } 3104 3105 /********************************************************************** 3106 * VarAdd [OLEAUT32.141] 3107 * 3108 * Add two variants. 3109 * 3110 * PARAMS 3111 * left [I] First variant 3112 * right [I] Second variant 3113 * result [O] Result variant 3114 * 3115 * RETURNS 3116 * Success: S_OK. 3117 * Failure: An HRESULT error code indicating the error. 3118 * 3119 * NOTES 3120 * Native VarAdd up to and including WinXP doesn't like I1, UI2, UI4, 3121 * UI8, INT and UINT as input variants. 3122 * 3123 * Native VarAdd doesn't check for NULL in/out pointers and crashes. We do the 3124 * same here. 3125 * 3126 * FIXME 3127 * Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that 3128 * case. 3129 */ 3130 HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result) 3131 { 3132 HRESULT hres; 3133 VARTYPE lvt, rvt, resvt, tvt; 3134 VARIANT lv, rv, tv; 3135 VARIANT tempLeft, tempRight; 3136 double r8res; 3137 3138 /* Variant priority for coercion. Sorted from lowest to highest. 3139 VT_ERROR shows an invalid input variant type. */ 3140 enum coerceprio { vt_EMPTY, vt_UI1, vt_I2, vt_I4, vt_I8, vt_BSTR,vt_R4, 3141 vt_R8, vt_CY, vt_DATE, vt_DECIMAL, vt_DISPATCH, vt_NULL, 3142 vt_ERROR }; 3143 /* Mapping from priority to variant type. Keep in sync with coerceprio! */ 3144 static const VARTYPE prio2vt[] = { VT_EMPTY, VT_UI1, VT_I2, VT_I4, VT_I8, VT_BSTR, VT_R4, 3145 VT_R8, VT_CY, VT_DATE, VT_DECIMAL, VT_DISPATCH, 3146 VT_NULL, VT_ERROR }; 3147 3148 /* Mapping for coercion from input variant to priority of result variant. */ 3149 static const VARTYPE coerce[] = { 3150 /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */ 3151 vt_EMPTY, vt_NULL, vt_I2, vt_I4, vt_R4, 3152 /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */ 3153 vt_R8, vt_CY, vt_DATE, vt_BSTR, vt_DISPATCH, 3154 /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */ 3155 vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL, 3156 /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */ 3157 vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8 3158 }; 3159 3160 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 3161 3162 VariantInit(&lv); 3163 VariantInit(&rv); 3164 VariantInit(&tv); 3165 VariantInit(&tempLeft); 3166 VariantInit(&tempRight); 3167 3168 /* Handle VT_DISPATCH by storing and taking address of returned value */ 3169 if ((V_VT(left) & VT_TYPEMASK) != VT_NULL && (V_VT(right) & VT_TYPEMASK) != VT_NULL) 3170 { 3171 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) 3172 { 3173 hres = VARIANT_FetchDispatchValue(left, &tempLeft); 3174 if (FAILED(hres)) goto end; 3175 left = &tempLeft; 3176 } 3177 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) 3178 { 3179 hres = VARIANT_FetchDispatchValue(right, &tempRight); 3180 if (FAILED(hres)) goto end; 3181 right = &tempRight; 3182 } 3183 } 3184 3185 lvt = V_VT(left)&VT_TYPEMASK; 3186 rvt = V_VT(right)&VT_TYPEMASK; 3187 3188 /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out. 3189 Same for any input variant type > VT_I8 */ 3190 if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK || 3191 lvt > VT_I8 || rvt > VT_I8) { 3192 hres = DISP_E_BADVARTYPE; 3193 goto end; 3194 } 3195 3196 /* Determine the variant type to coerce to. */ 3197 if (coerce[lvt] > coerce[rvt]) { 3198 resvt = prio2vt[coerce[lvt]]; 3199 tvt = prio2vt[coerce[rvt]]; 3200 } else { 3201 resvt = prio2vt[coerce[rvt]]; 3202 tvt = prio2vt[coerce[lvt]]; 3203 } 3204 3205 /* Special cases where the result variant type is defined by both 3206 input variants and not only that with the highest priority */ 3207 if (resvt == VT_BSTR) { 3208 if (tvt == VT_EMPTY || tvt == VT_BSTR) 3209 resvt = VT_BSTR; 3210 else 3211 resvt = VT_R8; 3212 } 3213 if (resvt == VT_R4 && (tvt == VT_BSTR || tvt == VT_I8 || tvt == VT_I4)) 3214 resvt = VT_R8; 3215 3216 /* For overflow detection use the biggest compatible type for the 3217 addition */ 3218 switch (resvt) { 3219 case VT_ERROR: 3220 hres = DISP_E_BADVARTYPE; 3221 goto end; 3222 case VT_NULL: 3223 hres = S_OK; 3224 V_VT(result) = VT_NULL; 3225 goto end; 3226 case VT_DISPATCH: 3227 FIXME("cannot handle variant type VT_DISPATCH\n"); 3228 hres = DISP_E_TYPEMISMATCH; 3229 goto end; 3230 case VT_EMPTY: 3231 resvt = VT_I2; 3232 /* Fall through */ 3233 case VT_UI1: 3234 case VT_I2: 3235 case VT_I4: 3236 case VT_I8: 3237 tvt = VT_I8; 3238 break; 3239 case VT_DATE: 3240 case VT_R4: 3241 tvt = VT_R8; 3242 break; 3243 default: 3244 tvt = resvt; 3245 } 3246 3247 /* Now coerce the variants */ 3248 hres = VariantChangeType(&lv, left, 0, tvt); 3249 if (FAILED(hres)) 3250 goto end; 3251 hres = VariantChangeType(&rv, right, 0, tvt); 3252 if (FAILED(hres)) 3253 goto end; 3254 3255 /* Do the math */ 3256 hres = S_OK; 3257 V_VT(result) = resvt; 3258 switch (tvt) { 3259 case VT_DECIMAL: 3260 hres = VarDecAdd(&V_DECIMAL(&lv), &V_DECIMAL(&rv), 3261 &V_DECIMAL(result)); 3262 goto end; 3263 case VT_CY: 3264 hres = VarCyAdd(V_CY(&lv), V_CY(&rv), &V_CY(result)); 3265 goto end; 3266 case VT_BSTR: 3267 /* We do not add those, we concatenate them. */ 3268 hres = VarBstrCat(V_BSTR(&lv), V_BSTR(&rv), &V_BSTR(result)); 3269 goto end; 3270 case VT_I8: 3271 /* Overflow detection */ 3272 r8res = (double)V_I8(&lv) + (double)V_I8(&rv); 3273 if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) { 3274 V_VT(result) = VT_R8; 3275 V_R8(result) = r8res; 3276 goto end; 3277 } else { 3278 V_VT(&tv) = tvt; 3279 V_I8(&tv) = V_I8(&lv) + V_I8(&rv); 3280 } 3281 break; 3282 case VT_R8: 3283 V_VT(&tv) = tvt; 3284 /* FIXME: overflow detection */ 3285 V_R8(&tv) = V_R8(&lv) + V_R8(&rv); 3286 break; 3287 default: 3288 ERR("We shouldn't get here! tvt = %d!\n", tvt); 3289 break; 3290 } 3291 if (resvt != tvt) { 3292 if ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) { 3293 /* Overflow! Change to the vartype with the next higher priority. 3294 With one exception: I4 ==> R8 even if it would fit in I8 */ 3295 if (resvt == VT_I4) 3296 resvt = VT_R8; 3297 else 3298 resvt = prio2vt[coerce[resvt] + 1]; 3299 hres = VariantChangeType(result, &tv, 0, resvt); 3300 } 3301 } else 3302 hres = VariantCopy(result, &tv); 3303 3304 end: 3305 if (hres != S_OK) { 3306 V_VT(result) = VT_EMPTY; 3307 V_I4(result) = 0; /* No V_EMPTY */ 3308 } 3309 VariantClear(&lv); 3310 VariantClear(&rv); 3311 VariantClear(&tv); 3312 VariantClear(&tempLeft); 3313 VariantClear(&tempRight); 3314 TRACE("returning 0x%8x %s\n", hres, debugstr_variant(result)); 3315 return hres; 3316 } 3317 3318 /********************************************************************** 3319 * VarMul [OLEAUT32.156] 3320 * 3321 * Multiply two variants. 3322 * 3323 * PARAMS 3324 * left [I] First variant 3325 * right [I] Second variant 3326 * result [O] Result variant 3327 * 3328 * RETURNS 3329 * Success: S_OK. 3330 * Failure: An HRESULT error code indicating the error. 3331 * 3332 * NOTES 3333 * Native VarMul up to and including WinXP doesn't like I1, UI2, UI4, 3334 * UI8, INT and UINT as input variants. But it can multiply apples with oranges. 3335 * 3336 * Native VarMul doesn't check for NULL in/out pointers and crashes. We do the 3337 * same here. 3338 * 3339 * FIXME 3340 * Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that 3341 * case. 3342 */ 3343 HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result) 3344 { 3345 HRESULT hres; 3346 VARTYPE lvt, rvt, resvt, tvt; 3347 VARIANT lv, rv, tv; 3348 VARIANT tempLeft, tempRight; 3349 double r8res; 3350 3351 /* Variant priority for coercion. Sorted from lowest to highest. 3352 VT_ERROR shows an invalid input variant type. */ 3353 enum coerceprio { vt_UI1 = 0, vt_I2, vt_I4, vt_I8, vt_CY, vt_R4, vt_R8, 3354 vt_DECIMAL, vt_NULL, vt_ERROR }; 3355 /* Mapping from priority to variant type. Keep in sync with coerceprio! */ 3356 static const VARTYPE prio2vt[] = { VT_UI1, VT_I2, VT_I4, VT_I8, VT_CY, VT_R4, VT_R8, 3357 VT_DECIMAL, VT_NULL, VT_ERROR }; 3358 3359 /* Mapping for coercion from input variant to priority of result variant. */ 3360 static const VARTYPE coerce[] = { 3361 /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */ 3362 vt_UI1, vt_NULL, vt_I2, vt_I4, vt_R4, 3363 /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */ 3364 vt_R8, vt_CY, vt_R8, vt_R8, vt_ERROR, 3365 /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */ 3366 vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL, 3367 /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */ 3368 vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8 3369 }; 3370 3371 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 3372 3373 VariantInit(&lv); 3374 VariantInit(&rv); 3375 VariantInit(&tv); 3376 VariantInit(&tempLeft); 3377 VariantInit(&tempRight); 3378 3379 /* Handle VT_DISPATCH by storing and taking address of returned value */ 3380 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) 3381 { 3382 hres = VARIANT_FetchDispatchValue(left, &tempLeft); 3383 if (FAILED(hres)) goto end; 3384 left = &tempLeft; 3385 } 3386 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) 3387 { 3388 hres = VARIANT_FetchDispatchValue(right, &tempRight); 3389 if (FAILED(hres)) goto end; 3390 right = &tempRight; 3391 } 3392 3393 lvt = V_VT(left)&VT_TYPEMASK; 3394 rvt = V_VT(right)&VT_TYPEMASK; 3395 3396 /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out. 3397 Same for any input variant type > VT_I8 */ 3398 if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK || 3399 lvt > VT_I8 || rvt > VT_I8) { 3400 hres = DISP_E_BADVARTYPE; 3401 goto end; 3402 } 3403 3404 /* Determine the variant type to coerce to. */ 3405 if (coerce[lvt] > coerce[rvt]) { 3406 resvt = prio2vt[coerce[lvt]]; 3407 tvt = prio2vt[coerce[rvt]]; 3408 } else { 3409 resvt = prio2vt[coerce[rvt]]; 3410 tvt = prio2vt[coerce[lvt]]; 3411 } 3412 3413 /* Special cases where the result variant type is defined by both 3414 input variants and not only that with the highest priority */ 3415 if (resvt == VT_R4 && (tvt == VT_CY || tvt == VT_I8 || tvt == VT_I4)) 3416 resvt = VT_R8; 3417 if (lvt == VT_EMPTY && rvt == VT_EMPTY) 3418 resvt = VT_I2; 3419 3420 /* For overflow detection use the biggest compatible type for the 3421 multiplication */ 3422 switch (resvt) { 3423 case VT_ERROR: 3424 hres = DISP_E_BADVARTYPE; 3425 goto end; 3426 case VT_NULL: 3427 hres = S_OK; 3428 V_VT(result) = VT_NULL; 3429 goto end; 3430 case VT_UI1: 3431 case VT_I2: 3432 case VT_I4: 3433 case VT_I8: 3434 tvt = VT_I8; 3435 break; 3436 case VT_R4: 3437 tvt = VT_R8; 3438 break; 3439 default: 3440 tvt = resvt; 3441 } 3442 3443 /* Now coerce the variants */ 3444 hres = VariantChangeType(&lv, left, 0, tvt); 3445 if (FAILED(hres)) 3446 goto end; 3447 hres = VariantChangeType(&rv, right, 0, tvt); 3448 if (FAILED(hres)) 3449 goto end; 3450 3451 /* Do the math */ 3452 hres = S_OK; 3453 V_VT(&tv) = tvt; 3454 V_VT(result) = resvt; 3455 switch (tvt) { 3456 case VT_DECIMAL: 3457 hres = VarDecMul(&V_DECIMAL(&lv), &V_DECIMAL(&rv), 3458 &V_DECIMAL(result)); 3459 goto end; 3460 case VT_CY: 3461 hres = VarCyMul(V_CY(&lv), V_CY(&rv), &V_CY(result)); 3462 goto end; 3463 case VT_I8: 3464 /* Overflow detection */ 3465 r8res = (double)V_I8(&lv) * (double)V_I8(&rv); 3466 if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) { 3467 V_VT(result) = VT_R8; 3468 V_R8(result) = r8res; 3469 goto end; 3470 } else 3471 V_I8(&tv) = V_I8(&lv) * V_I8(&rv); 3472 break; 3473 case VT_R8: 3474 /* FIXME: overflow detection */ 3475 V_R8(&tv) = V_R8(&lv) * V_R8(&rv); 3476 break; 3477 default: 3478 ERR("We shouldn't get here! tvt = %d!\n", tvt); 3479 break; 3480 } 3481 if (resvt != tvt) { 3482 while ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) { 3483 /* Overflow! Change to the vartype with the next higher priority. 3484 With one exception: I4 ==> R8 even if it would fit in I8 */ 3485 if (resvt == VT_I4) 3486 resvt = VT_R8; 3487 else 3488 resvt = prio2vt[coerce[resvt] + 1]; 3489 } 3490 } else 3491 hres = VariantCopy(result, &tv); 3492 3493 end: 3494 if (hres != S_OK) { 3495 V_VT(result) = VT_EMPTY; 3496 V_I4(result) = 0; /* No V_EMPTY */ 3497 } 3498 VariantClear(&lv); 3499 VariantClear(&rv); 3500 VariantClear(&tv); 3501 VariantClear(&tempLeft); 3502 VariantClear(&tempRight); 3503 TRACE("returning 0x%8x %s\n", hres, debugstr_variant(result)); 3504 return hres; 3505 } 3506 3507 /********************************************************************** 3508 * VarDiv [OLEAUT32.143] 3509 * 3510 * Divides one variant with another. 3511 * 3512 * PARAMS 3513 * left [I] First variant 3514 * right [I] Second variant 3515 * result [O] Result variant 3516 * 3517 * RETURNS 3518 * Success: S_OK. 3519 * Failure: An HRESULT error code indicating the error. 3520 */ 3521 HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result) 3522 { 3523 HRESULT hres = S_OK; 3524 VARTYPE resvt = VT_EMPTY; 3525 VARTYPE leftvt,rightvt; 3526 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; 3527 VARIANT lv,rv; 3528 VARIANT tempLeft, tempRight; 3529 3530 VariantInit(&tempLeft); 3531 VariantInit(&tempRight); 3532 VariantInit(&lv); 3533 VariantInit(&rv); 3534 3535 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 3536 3537 /* Handle VT_DISPATCH by storing and taking address of returned value */ 3538 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) 3539 { 3540 hres = VARIANT_FetchDispatchValue(left, &tempLeft); 3541 if (FAILED(hres)) goto end; 3542 left = &tempLeft; 3543 } 3544 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) 3545 { 3546 hres = VARIANT_FetchDispatchValue(right, &tempRight); 3547 if (FAILED(hres)) goto end; 3548 right = &tempRight; 3549 } 3550 3551 leftvt = V_VT(left)&VT_TYPEMASK; 3552 rightvt = V_VT(right)&VT_TYPEMASK; 3553 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); 3554 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK); 3555 3556 if (leftExtraFlags != rightExtraFlags) 3557 { 3558 hres = DISP_E_BADVARTYPE; 3559 goto end; 3560 } 3561 ExtraFlags = leftExtraFlags; 3562 3563 /* Native VarDiv always returns an error when using extra flags */ 3564 if (ExtraFlags != 0) 3565 { 3566 hres = DISP_E_BADVARTYPE; 3567 goto end; 3568 } 3569 3570 /* Determine return type */ 3571 if (rightvt != VT_EMPTY) 3572 { 3573 if (leftvt == VT_NULL || rightvt == VT_NULL) 3574 { 3575 V_VT(result) = VT_NULL; 3576 hres = S_OK; 3577 goto end; 3578 } 3579 else if (leftvt == VT_DECIMAL || rightvt == VT_DECIMAL) 3580 resvt = VT_DECIMAL; 3581 else if (leftvt == VT_I8 || rightvt == VT_I8 || 3582 leftvt == VT_CY || rightvt == VT_CY || 3583 leftvt == VT_DATE || rightvt == VT_DATE || 3584 leftvt == VT_I4 || rightvt == VT_I4 || 3585 leftvt == VT_BSTR || rightvt == VT_BSTR || 3586 leftvt == VT_I2 || rightvt == VT_I2 || 3587 leftvt == VT_BOOL || rightvt == VT_BOOL || 3588 leftvt == VT_R8 || rightvt == VT_R8 || 3589 leftvt == VT_UI1 || rightvt == VT_UI1) 3590 { 3591 if ((leftvt == VT_UI1 && rightvt == VT_R4) || 3592 (leftvt == VT_R4 && rightvt == VT_UI1)) 3593 resvt = VT_R4; 3594 else if ((leftvt == VT_R4 && (rightvt == VT_BOOL || 3595 rightvt == VT_I2)) || (rightvt == VT_R4 && 3596 (leftvt == VT_BOOL || leftvt == VT_I2))) 3597 resvt = VT_R4; 3598 else 3599 resvt = VT_R8; 3600 } 3601 else if (leftvt == VT_R4 || rightvt == VT_R4) 3602 resvt = VT_R4; 3603 } 3604 else if (leftvt == VT_NULL) 3605 { 3606 V_VT(result) = VT_NULL; 3607 hres = S_OK; 3608 goto end; 3609 } 3610 else 3611 { 3612 hres = DISP_E_BADVARTYPE; 3613 goto end; 3614 } 3615 3616 /* coerce to the result type */ 3617 hres = VariantChangeType(&lv, left, 0, resvt); 3618 if (hres != S_OK) goto end; 3619 3620 hres = VariantChangeType(&rv, right, 0, resvt); 3621 if (hres != S_OK) goto end; 3622 3623 /* do the math */ 3624 V_VT(result) = resvt; 3625 switch (resvt) 3626 { 3627 case VT_R4: 3628 if (V_R4(&lv) == 0.0 && V_R4(&rv) == 0.0) 3629 { 3630 hres = DISP_E_OVERFLOW; 3631 V_VT(result) = VT_EMPTY; 3632 } 3633 else if (V_R4(&rv) == 0.0) 3634 { 3635 hres = DISP_E_DIVBYZERO; 3636 V_VT(result) = VT_EMPTY; 3637 } 3638 else 3639 V_R4(result) = V_R4(&lv) / V_R4(&rv); 3640 break; 3641 case VT_R8: 3642 if (V_R8(&lv) == 0.0 && V_R8(&rv) == 0.0) 3643 { 3644 hres = DISP_E_OVERFLOW; 3645 V_VT(result) = VT_EMPTY; 3646 } 3647 else if (V_R8(&rv) == 0.0) 3648 { 3649 hres = DISP_E_DIVBYZERO; 3650 V_VT(result) = VT_EMPTY; 3651 } 3652 else 3653 V_R8(result) = V_R8(&lv) / V_R8(&rv); 3654 break; 3655 case VT_DECIMAL: 3656 hres = VarDecDiv(&(V_DECIMAL(&lv)), &(V_DECIMAL(&rv)), &(V_DECIMAL(result))); 3657 break; 3658 } 3659 3660 end: 3661 VariantClear(&lv); 3662 VariantClear(&rv); 3663 VariantClear(&tempLeft); 3664 VariantClear(&tempRight); 3665 TRACE("returning 0x%8x %s\n", hres, debugstr_variant(result)); 3666 return hres; 3667 } 3668 3669 /********************************************************************** 3670 * VarSub [OLEAUT32.159] 3671 * 3672 * Subtract two variants. 3673 * 3674 * PARAMS 3675 * left [I] First variant 3676 * right [I] Second variant 3677 * result [O] Result variant 3678 * 3679 * RETURNS 3680 * Success: S_OK. 3681 * Failure: An HRESULT error code indicating the error. 3682 */ 3683 HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) 3684 { 3685 HRESULT hres = S_OK; 3686 VARTYPE resvt = VT_EMPTY; 3687 VARTYPE leftvt,rightvt; 3688 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; 3689 VARIANT lv,rv; 3690 VARIANT tempLeft, tempRight; 3691 3692 VariantInit(&lv); 3693 VariantInit(&rv); 3694 VariantInit(&tempLeft); 3695 VariantInit(&tempRight); 3696 3697 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 3698 3699 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH && 3700 (V_VT(left)&(~VT_TYPEMASK)) == 0 && 3701 (V_VT(right) & VT_TYPEMASK) != VT_NULL) 3702 { 3703 if (NULL == V_DISPATCH(left)) { 3704 if ((V_VT(right) & VT_TYPEMASK) >= VT_INT_PTR) 3705 hres = DISP_E_BADVARTYPE; 3706 else if ((V_VT(right) & VT_TYPEMASK) >= VT_UI8 && 3707 (V_VT(right) & VT_TYPEMASK) < VT_RECORD) 3708 hres = DISP_E_BADVARTYPE; 3709 else switch (V_VT(right) & VT_TYPEMASK) 3710 { 3711 case VT_VARIANT: 3712 case VT_UNKNOWN: 3713 case 15: 3714 case VT_I1: 3715 case VT_UI2: 3716 case VT_UI4: 3717 hres = DISP_E_BADVARTYPE; 3718 } 3719 if (FAILED(hres)) goto end; 3720 } 3721 hres = VARIANT_FetchDispatchValue(left, &tempLeft); 3722 if (FAILED(hres)) goto end; 3723 left = &tempLeft; 3724 } 3725 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH && 3726 (V_VT(right)&(~VT_TYPEMASK)) == 0 && 3727 (V_VT(left) & VT_TYPEMASK) != VT_NULL) 3728 { 3729 if (NULL == V_DISPATCH(right)) 3730 { 3731 if ((V_VT(left) & VT_TYPEMASK) >= VT_INT_PTR) 3732 hres = DISP_E_BADVARTYPE; 3733 else if ((V_VT(left) & VT_TYPEMASK) >= VT_UI8 && 3734 (V_VT(left) & VT_TYPEMASK) < VT_RECORD) 3735 hres = DISP_E_BADVARTYPE; 3736 else switch (V_VT(left) & VT_TYPEMASK) 3737 { 3738 case VT_VARIANT: 3739 case VT_UNKNOWN: 3740 case 15: 3741 case VT_I1: 3742 case VT_UI2: 3743 case VT_UI4: 3744 hres = DISP_E_BADVARTYPE; 3745 } 3746 if (FAILED(hres)) goto end; 3747 } 3748 hres = VARIANT_FetchDispatchValue(right, &tempRight); 3749 if (FAILED(hres)) goto end; 3750 right = &tempRight; 3751 } 3752 3753 leftvt = V_VT(left)&VT_TYPEMASK; 3754 rightvt = V_VT(right)&VT_TYPEMASK; 3755 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); 3756 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK); 3757 3758 if (leftExtraFlags != rightExtraFlags) 3759 { 3760 hres = DISP_E_BADVARTYPE; 3761 goto end; 3762 } 3763 ExtraFlags = leftExtraFlags; 3764 3765 /* determine return type and return code */ 3766 /* All extra flags produce errors */ 3767 if (ExtraFlags == (VT_VECTOR|VT_BYREF|VT_RESERVED) || 3768 ExtraFlags == (VT_VECTOR|VT_RESERVED) || 3769 ExtraFlags == (VT_VECTOR|VT_BYREF) || 3770 ExtraFlags == (VT_BYREF|VT_RESERVED) || 3771 ExtraFlags == VT_VECTOR || 3772 ExtraFlags == VT_BYREF || 3773 ExtraFlags == VT_RESERVED) 3774 { 3775 hres = DISP_E_BADVARTYPE; 3776 goto end; 3777 } 3778 else if (ExtraFlags >= VT_ARRAY) 3779 { 3780 hres = DISP_E_TYPEMISMATCH; 3781 goto end; 3782 } 3783 /* Native VarSub cannot handle: VT_I1, VT_UI2, VT_UI4, 3784 VT_INT, VT_UINT and VT_UI8. Tested with WinXP */ 3785 else if (leftvt == VT_CLSID || rightvt == VT_CLSID || 3786 leftvt == VT_VARIANT || rightvt == VT_VARIANT || 3787 leftvt == VT_I1 || rightvt == VT_I1 || 3788 leftvt == VT_UI2 || rightvt == VT_UI2 || 3789 leftvt == VT_UI4 || rightvt == VT_UI4 || 3790 leftvt == VT_UI8 || rightvt == VT_UI8 || 3791 leftvt == VT_INT || rightvt == VT_INT || 3792 leftvt == VT_UINT || rightvt == VT_UINT || 3793 leftvt == VT_UNKNOWN || rightvt == VT_UNKNOWN || 3794 leftvt == VT_RECORD || rightvt == VT_RECORD) 3795 { 3796 if (leftvt == VT_RECORD && rightvt == VT_I8) 3797 hres = DISP_E_TYPEMISMATCH; 3798 else if (leftvt < VT_UI1 && rightvt == VT_RECORD) 3799 hres = DISP_E_TYPEMISMATCH; 3800 else if (leftvt >= VT_UI1 && rightvt == VT_RECORD) 3801 hres = DISP_E_TYPEMISMATCH; 3802 else if (leftvt == VT_RECORD && rightvt <= VT_UI1) 3803 hres = DISP_E_TYPEMISMATCH; 3804 else if (leftvt == VT_RECORD && rightvt > VT_UI1) 3805 hres = DISP_E_BADVARTYPE; 3806 else 3807 hres = DISP_E_BADVARTYPE; 3808 goto end; 3809 } 3810 /* The following flags/types are invalid for left variant */ 3811 else if (!((leftvt <= VT_LPWSTR || leftvt == VT_RECORD || 3812 leftvt == VT_CLSID) && leftvt != (VARTYPE)15 /* undefined vt */ && 3813 (leftvt < VT_VOID || leftvt > VT_LPWSTR))) 3814 { 3815 hres = DISP_E_BADVARTYPE; 3816 goto end; 3817 } 3818 /* The following flags/types are invalid for right variant */ 3819 else if (!((rightvt <= VT_LPWSTR || rightvt == VT_RECORD || 3820 rightvt == VT_CLSID) && rightvt != (VARTYPE)15 /* undefined vt */ && 3821 (rightvt < VT_VOID || rightvt > VT_LPWSTR))) 3822 { 3823 hres = DISP_E_BADVARTYPE; 3824 goto end; 3825 } 3826 else if ((leftvt == VT_NULL && rightvt == VT_DISPATCH) || 3827 (leftvt == VT_DISPATCH && rightvt == VT_NULL)) 3828 resvt = VT_NULL; 3829 else if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH || 3830 leftvt == VT_ERROR || rightvt == VT_ERROR) 3831 { 3832 hres = DISP_E_TYPEMISMATCH; 3833 goto end; 3834 } 3835 else if (leftvt == VT_NULL || rightvt == VT_NULL) 3836 resvt = VT_NULL; 3837 else if ((leftvt == VT_EMPTY && rightvt == VT_BSTR) || 3838 (leftvt == VT_DATE && rightvt == VT_DATE) || 3839 (leftvt == VT_BSTR && rightvt == VT_EMPTY) || 3840 (leftvt == VT_BSTR && rightvt == VT_BSTR)) 3841 resvt = VT_R8; 3842 else if (leftvt == VT_DECIMAL || rightvt == VT_DECIMAL) 3843 resvt = VT_DECIMAL; 3844 else if (leftvt == VT_DATE || rightvt == VT_DATE) 3845 resvt = VT_DATE; 3846 else if (leftvt == VT_CY || rightvt == VT_CY) 3847 resvt = VT_CY; 3848 else if (leftvt == VT_R8 || rightvt == VT_R8) 3849 resvt = VT_R8; 3850 else if (leftvt == VT_BSTR || rightvt == VT_BSTR) 3851 resvt = VT_R8; 3852 else if (leftvt == VT_R4 || rightvt == VT_R4) 3853 { 3854 if (leftvt == VT_I4 || rightvt == VT_I4 || 3855 leftvt == VT_I8 || rightvt == VT_I8) 3856 resvt = VT_R8; 3857 else 3858 resvt = VT_R4; 3859 } 3860 else if (leftvt == VT_I8 || rightvt == VT_I8) 3861 resvt = VT_I8; 3862 else if (leftvt == VT_I4 || rightvt == VT_I4) 3863 resvt = VT_I4; 3864 else if (leftvt == VT_I2 || rightvt == VT_I2 || 3865 leftvt == VT_BOOL || rightvt == VT_BOOL || 3866 (leftvt == VT_EMPTY && rightvt == VT_EMPTY)) 3867 resvt = VT_I2; 3868 else if (leftvt == VT_UI1 || rightvt == VT_UI1) 3869 resvt = VT_UI1; 3870 else 3871 { 3872 hres = DISP_E_TYPEMISMATCH; 3873 goto end; 3874 } 3875 3876 /* coerce to the result type */ 3877 if (leftvt == VT_BSTR && rightvt == VT_DATE) 3878 hres = VariantChangeType(&lv, left, 0, VT_R8); 3879 else 3880 hres = VariantChangeType(&lv, left, 0, resvt); 3881 if (hres != S_OK) goto end; 3882 if (leftvt == VT_DATE && rightvt == VT_BSTR) 3883 hres = VariantChangeType(&rv, right, 0, VT_R8); 3884 else 3885 hres = VariantChangeType(&rv, right, 0, resvt); 3886 if (hres != S_OK) goto end; 3887 3888 /* do the math */ 3889 V_VT(result) = resvt; 3890 switch (resvt) 3891 { 3892 case VT_NULL: 3893 break; 3894 case VT_DATE: 3895 V_DATE(result) = V_DATE(&lv) - V_DATE(&rv); 3896 break; 3897 case VT_CY: 3898 hres = VarCySub(V_CY(&lv), V_CY(&rv), &(V_CY(result))); 3899 break; 3900 case VT_R4: 3901 V_R4(result) = V_R4(&lv) - V_R4(&rv); 3902 break; 3903 case VT_I8: 3904 V_I8(result) = V_I8(&lv) - V_I8(&rv); 3905 break; 3906 case VT_I4: 3907 V_I4(result) = V_I4(&lv) - V_I4(&rv); 3908 break; 3909 case VT_I2: 3910 V_I2(result) = V_I2(&lv) - V_I2(&rv); 3911 break; 3912 case VT_UI1: 3913 V_UI1(result) = V_UI2(&lv) - V_UI1(&rv); 3914 break; 3915 case VT_R8: 3916 V_R8(result) = V_R8(&lv) - V_R8(&rv); 3917 break; 3918 case VT_DECIMAL: 3919 hres = VarDecSub(&(V_DECIMAL(&lv)), &(V_DECIMAL(&rv)), &(V_DECIMAL(result))); 3920 break; 3921 } 3922 3923 end: 3924 VariantClear(&lv); 3925 VariantClear(&rv); 3926 VariantClear(&tempLeft); 3927 VariantClear(&tempRight); 3928 TRACE("returning 0x%8x %s\n", hres, debugstr_variant(result)); 3929 return hres; 3930 } 3931 3932 3933 /********************************************************************** 3934 * VarOr [OLEAUT32.157] 3935 * 3936 * Perform a logical or (OR) operation on two variants. 3937 * 3938 * PARAMS 3939 * pVarLeft [I] First variant 3940 * pVarRight [I] Variant to OR with pVarLeft 3941 * pVarOut [O] Destination for OR result 3942 * 3943 * RETURNS 3944 * Success: S_OK. pVarOut contains the result of the operation with its type 3945 * taken from the table listed under VarXor(). 3946 * Failure: An HRESULT error code indicating the error. 3947 * 3948 * NOTES 3949 * See the Notes section of VarXor() for further information. 3950 */ 3951 HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut) 3952 { 3953 VARTYPE vt = VT_I4; 3954 VARIANT varLeft, varRight, varStr; 3955 HRESULT hRet; 3956 VARIANT tempLeft, tempRight; 3957 3958 VariantInit(&tempLeft); 3959 VariantInit(&tempRight); 3960 VariantInit(&varLeft); 3961 VariantInit(&varRight); 3962 VariantInit(&varStr); 3963 3964 TRACE("(%s,%s,%p)\n", debugstr_variant(pVarLeft), debugstr_variant(pVarRight), pVarOut); 3965 3966 /* Handle VT_DISPATCH by storing and taking address of returned value */ 3967 if ((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH) 3968 { 3969 hRet = VARIANT_FetchDispatchValue(pVarLeft, &tempLeft); 3970 if (FAILED(hRet)) goto VarOr_Exit; 3971 pVarLeft = &tempLeft; 3972 } 3973 if ((V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH) 3974 { 3975 hRet = VARIANT_FetchDispatchValue(pVarRight, &tempRight); 3976 if (FAILED(hRet)) goto VarOr_Exit; 3977 pVarRight = &tempRight; 3978 } 3979 3980 if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) || 3981 V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN || 3982 V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH || 3983 V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD) 3984 { 3985 hRet = DISP_E_BADVARTYPE; 3986 goto VarOr_Exit; 3987 } 3988 3989 V_VT(&varLeft) = V_VT(&varRight) = V_VT(&varStr) = VT_EMPTY; 3990 3991 if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL) 3992 { 3993 /* NULL OR Zero is NULL, NULL OR value is value */ 3994 if (V_VT(pVarLeft) == VT_NULL) 3995 pVarLeft = pVarRight; /* point to the non-NULL var */ 3996 3997 V_VT(pVarOut) = VT_NULL; 3998 V_I4(pVarOut) = 0; 3999 4000 switch (V_VT(pVarLeft)) 4001 { 4002 case VT_DATE: case VT_R8: 4003 if (V_R8(pVarLeft)) 4004 goto VarOr_AsEmpty; 4005 hRet = S_OK; 4006 goto VarOr_Exit; 4007 case VT_BOOL: 4008 if (V_BOOL(pVarLeft)) 4009 *pVarOut = *pVarLeft; 4010 hRet = S_OK; 4011 goto VarOr_Exit; 4012 case VT_I2: case VT_UI2: 4013 if (V_I2(pVarLeft)) 4014 goto VarOr_AsEmpty; 4015 hRet = S_OK; 4016 goto VarOr_Exit; 4017 case VT_I1: 4018 if (V_I1(pVarLeft)) 4019 goto VarOr_AsEmpty; 4020 hRet = S_OK; 4021 goto VarOr_Exit; 4022 case VT_UI1: 4023 if (V_UI1(pVarLeft)) 4024 *pVarOut = *pVarLeft; 4025 hRet = S_OK; 4026 goto VarOr_Exit; 4027 case VT_R4: 4028 if (V_R4(pVarLeft)) 4029 goto VarOr_AsEmpty; 4030 hRet = S_OK; 4031 goto VarOr_Exit; 4032 case VT_I4: case VT_UI4: case VT_INT: case VT_UINT: 4033 if (V_I4(pVarLeft)) 4034 goto VarOr_AsEmpty; 4035 hRet = S_OK; 4036 goto VarOr_Exit; 4037 case VT_CY: 4038 if (V_CY(pVarLeft).int64) 4039 goto VarOr_AsEmpty; 4040 hRet = S_OK; 4041 goto VarOr_Exit; 4042 case VT_I8: case VT_UI8: 4043 if (V_I8(pVarLeft)) 4044 goto VarOr_AsEmpty; 4045 hRet = S_OK; 4046 goto VarOr_Exit; 4047 case VT_DECIMAL: 4048 if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft))) 4049 goto VarOr_AsEmpty; 4050 hRet = S_OK; 4051 goto VarOr_Exit; 4052 case VT_BSTR: 4053 { 4054 VARIANT_BOOL b; 4055 4056 if (!V_BSTR(pVarLeft)) 4057 { 4058 hRet = DISP_E_BADVARTYPE; 4059 goto VarOr_Exit; 4060 } 4061 4062 hRet = VarBoolFromStr(V_BSTR(pVarLeft), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b); 4063 if (SUCCEEDED(hRet) && b) 4064 { 4065 V_VT(pVarOut) = VT_BOOL; 4066 V_BOOL(pVarOut) = b; 4067 } 4068 goto VarOr_Exit; 4069 } 4070 case VT_NULL: case VT_EMPTY: 4071 V_VT(pVarOut) = VT_NULL; 4072 hRet = S_OK; 4073 goto VarOr_Exit; 4074 default: 4075 hRet = DISP_E_BADVARTYPE; 4076 goto VarOr_Exit; 4077 } 4078 } 4079 4080 if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY) 4081 { 4082 if (V_VT(pVarLeft) == VT_EMPTY) 4083 pVarLeft = pVarRight; /* point to the non-EMPTY var */ 4084 4085 VarOr_AsEmpty: 4086 /* Since one argument is empty (0), OR'ing it with the other simply 4087 * gives the others value (as 0|x => x). So just convert the other 4088 * argument to the required result type. 4089 */ 4090 switch (V_VT(pVarLeft)) 4091 { 4092 case VT_BSTR: 4093 if (!V_BSTR(pVarLeft)) 4094 { 4095 hRet = DISP_E_BADVARTYPE; 4096 goto VarOr_Exit; 4097 } 4098 4099 hRet = VariantCopy(&varStr, pVarLeft); 4100 if (FAILED(hRet)) 4101 goto VarOr_Exit; 4102 pVarLeft = &varStr; 4103 hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL); 4104 if (FAILED(hRet)) 4105 goto VarOr_Exit; 4106 /* Fall Through ... */ 4107 case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2: 4108 V_VT(pVarOut) = VT_I2; 4109 break; 4110 case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8: 4111 case VT_I1: case VT_UI2: case VT_I4: case VT_UI4: 4112 case VT_INT: case VT_UINT: case VT_UI8: 4113 V_VT(pVarOut) = VT_I4; 4114 break; 4115 case VT_I8: 4116 V_VT(pVarOut) = VT_I8; 4117 break; 4118 default: 4119 hRet = DISP_E_BADVARTYPE; 4120 goto VarOr_Exit; 4121 } 4122 hRet = VariantCopy(&varLeft, pVarLeft); 4123 if (FAILED(hRet)) 4124 goto VarOr_Exit; 4125 pVarLeft = &varLeft; 4126 hRet = VariantChangeType(pVarOut, pVarLeft, 0, V_VT(pVarOut)); 4127 goto VarOr_Exit; 4128 } 4129 4130 if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL) 4131 { 4132 V_VT(pVarOut) = VT_BOOL; 4133 V_BOOL(pVarOut) = V_BOOL(pVarLeft) | V_BOOL(pVarRight); 4134 hRet = S_OK; 4135 goto VarOr_Exit; 4136 } 4137 4138 if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1) 4139 { 4140 V_VT(pVarOut) = VT_UI1; 4141 V_UI1(pVarOut) = V_UI1(pVarLeft) | V_UI1(pVarRight); 4142 hRet = S_OK; 4143 goto VarOr_Exit; 4144 } 4145 4146 if (V_VT(pVarLeft) == VT_BSTR) 4147 { 4148 hRet = VariantCopy(&varStr, pVarLeft); 4149 if (FAILED(hRet)) 4150 goto VarOr_Exit; 4151 pVarLeft = &varStr; 4152 hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL); 4153 if (FAILED(hRet)) 4154 goto VarOr_Exit; 4155 } 4156 4157 if (V_VT(pVarLeft) == VT_BOOL && 4158 (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_BSTR)) 4159 { 4160 vt = VT_BOOL; 4161 } 4162 else if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 || 4163 V_VT(pVarLeft) == VT_I2 || V_VT(pVarLeft) == VT_BSTR) && 4164 (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 || 4165 V_VT(pVarRight) == VT_I2 || V_VT(pVarRight) == VT_BSTR)) 4166 { 4167 vt = VT_I2; 4168 } 4169 else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8) 4170 { 4171 if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT) 4172 { 4173 hRet = DISP_E_TYPEMISMATCH; 4174 goto VarOr_Exit; 4175 } 4176 vt = VT_I8; 4177 } 4178 4179 hRet = VariantCopy(&varLeft, pVarLeft); 4180 if (FAILED(hRet)) 4181 goto VarOr_Exit; 4182 4183 hRet = VariantCopy(&varRight, pVarRight); 4184 if (FAILED(hRet)) 4185 goto VarOr_Exit; 4186 4187 if (vt == VT_I4 && V_VT(&varLeft) == VT_UI4) 4188 V_VT(&varLeft) = VT_I4; /* Don't overflow */ 4189 else 4190 { 4191 double d; 4192 4193 if (V_VT(&varLeft) == VT_BSTR && 4194 FAILED(VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d))) 4195 hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, VT_BOOL); 4196 if (SUCCEEDED(hRet) && V_VT(&varLeft) != vt) 4197 hRet = VariantChangeType(&varLeft, &varLeft, 0, vt); 4198 if (FAILED(hRet)) 4199 goto VarOr_Exit; 4200 } 4201 4202 if (vt == VT_I4 && V_VT(&varRight) == VT_UI4) 4203 V_VT(&varRight) = VT_I4; /* Don't overflow */ 4204 else 4205 { 4206 double d; 4207 4208 if (V_VT(&varRight) == VT_BSTR && 4209 FAILED(VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d))) 4210 hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, VT_BOOL); 4211 if (SUCCEEDED(hRet) && V_VT(&varRight) != vt) 4212 hRet = VariantChangeType(&varRight, &varRight, 0, vt); 4213 if (FAILED(hRet)) 4214 goto VarOr_Exit; 4215 } 4216 4217 V_VT(pVarOut) = vt; 4218 if (vt == VT_I8) 4219 { 4220 V_I8(pVarOut) = V_I8(&varLeft) | V_I8(&varRight); 4221 } 4222 else if (vt == VT_I4) 4223 { 4224 V_I4(pVarOut) = V_I4(&varLeft) | V_I4(&varRight); 4225 } 4226 else 4227 { 4228 V_I2(pVarOut) = V_I2(&varLeft) | V_I2(&varRight); 4229 } 4230 4231 VarOr_Exit: 4232 VariantClear(&varStr); 4233 VariantClear(&varLeft); 4234 VariantClear(&varRight); 4235 VariantClear(&tempLeft); 4236 VariantClear(&tempRight); 4237 return hRet; 4238 } 4239 4240 /********************************************************************** 4241 * VarAbs [OLEAUT32.168] 4242 * 4243 * Convert a variant to its absolute value. 4244 * 4245 * PARAMS 4246 * pVarIn [I] Source variant 4247 * pVarOut [O] Destination for converted value 4248 * 4249 * RETURNS 4250 * Success: S_OK. pVarOut contains the absolute value of pVarIn. 4251 * Failure: An HRESULT error code indicating the error. 4252 * 4253 * NOTES 4254 * - This function does not process by-reference variants. 4255 * - The type of the value stored in pVarOut depends on the type of pVarIn, 4256 * according to the following table: 4257 *| Input Type Output Type 4258 *| ---------- ----------- 4259 *| VT_BOOL VT_I2 4260 *| VT_BSTR VT_R8 4261 *| (All others) Unchanged 4262 */ 4263 HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut) 4264 { 4265 VARIANT varIn; 4266 HRESULT hRet = S_OK; 4267 VARIANT temp; 4268 4269 VariantInit(&temp); 4270 4271 TRACE("(%s,%p)\n", debugstr_variant(pVarIn), pVarOut); 4272 4273 /* Handle VT_DISPATCH by storing and taking address of returned value */ 4274 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) 4275 { 4276 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); 4277 if (FAILED(hRet)) goto VarAbs_Exit; 4278 pVarIn = &temp; 4279 } 4280 4281 if (V_ISARRAY(pVarIn) || V_VT(pVarIn) == VT_UNKNOWN || 4282 V_VT(pVarIn) == VT_DISPATCH || V_VT(pVarIn) == VT_RECORD || 4283 V_VT(pVarIn) == VT_ERROR) 4284 { 4285 hRet = DISP_E_TYPEMISMATCH; 4286 goto VarAbs_Exit; 4287 } 4288 *pVarOut = *pVarIn; /* Shallow copy the value, and invert it if needed */ 4289 4290 #define ABS_CASE(typ,min) \ 4291 case VT_##typ: if (V_##typ(pVarIn) == min) hRet = DISP_E_OVERFLOW; \ 4292 else if (V_##typ(pVarIn) < 0) V_##typ(pVarOut) = -V_##typ(pVarIn); \ 4293 break 4294 4295 switch (V_VT(pVarIn)) 4296 { 4297 ABS_CASE(I1,I1_MIN); 4298 case VT_BOOL: 4299 V_VT(pVarOut) = VT_I2; 4300 /* BOOL->I2, Fall through ... */ 4301 ABS_CASE(I2,I2_MIN); 4302 case VT_INT: 4303 ABS_CASE(I4,I4_MIN); 4304 ABS_CASE(I8,I8_MIN); 4305 ABS_CASE(R4,R4_MIN); 4306 case VT_BSTR: 4307 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn)); 4308 if (FAILED(hRet)) 4309 break; 4310 V_VT(pVarOut) = VT_R8; 4311 pVarIn = &varIn; 4312 /* Fall through ... */ 4313 case VT_DATE: 4314 ABS_CASE(R8,R8_MIN); 4315 case VT_CY: 4316 hRet = VarCyAbs(V_CY(pVarIn), & V_CY(pVarOut)); 4317 break; 4318 case VT_DECIMAL: 4319 DEC_SIGN(&V_DECIMAL(pVarOut)) &= ~DECIMAL_NEG; 4320 break; 4321 case VT_UI1: 4322 case VT_UI2: 4323 case VT_UINT: 4324 case VT_UI4: 4325 case VT_UI8: 4326 /* No-Op */ 4327 break; 4328 case VT_EMPTY: 4329 V_VT(pVarOut) = VT_I2; 4330 case VT_NULL: 4331 V_I2(pVarOut) = 0; 4332 break; 4333 default: 4334 hRet = DISP_E_BADVARTYPE; 4335 } 4336 4337 VarAbs_Exit: 4338 VariantClear(&temp); 4339 return hRet; 4340 } 4341 4342 /********************************************************************** 4343 * VarFix [OLEAUT32.169] 4344 * 4345 * Truncate a variants value to a whole number. 4346 * 4347 * PARAMS 4348 * pVarIn [I] Source variant 4349 * pVarOut [O] Destination for converted value 4350 * 4351 * RETURNS 4352 * Success: S_OK. pVarOut contains the converted value. 4353 * Failure: An HRESULT error code indicating the error. 4354 * 4355 * NOTES 4356 * - The type of the value stored in pVarOut depends on the type of pVarIn, 4357 * according to the following table: 4358 *| Input Type Output Type 4359 *| ---------- ----------- 4360 *| VT_BOOL VT_I2 4361 *| VT_EMPTY VT_I2 4362 *| VT_BSTR VT_R8 4363 *| All Others Unchanged 4364 * - The difference between this function and VarInt() is that VarInt() rounds 4365 * negative numbers away from 0, while this function rounds them towards zero. 4366 */ 4367 HRESULT WINAPI VarFix(LPVARIANT pVarIn, LPVARIANT pVarOut) 4368 { 4369 HRESULT hRet = S_OK; 4370 VARIANT temp; 4371 4372 VariantInit(&temp); 4373 4374 TRACE("(%s,%p)\n", debugstr_variant(pVarIn), pVarOut); 4375 4376 /* Handle VT_DISPATCH by storing and taking address of returned value */ 4377 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) 4378 { 4379 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); 4380 if (FAILED(hRet)) goto VarFix_Exit; 4381 pVarIn = &temp; 4382 } 4383 V_VT(pVarOut) = V_VT(pVarIn); 4384 4385 switch (V_VT(pVarIn)) 4386 { 4387 case VT_UI1: 4388 V_UI1(pVarOut) = V_UI1(pVarIn); 4389 break; 4390 case VT_BOOL: 4391 V_VT(pVarOut) = VT_I2; 4392 /* Fall through */ 4393 case VT_I2: 4394 V_I2(pVarOut) = V_I2(pVarIn); 4395 break; 4396 case VT_I4: 4397 V_I4(pVarOut) = V_I4(pVarIn); 4398 break; 4399 case VT_I8: 4400 V_I8(pVarOut) = V_I8(pVarIn); 4401 break; 4402 case VT_R4: 4403 if (V_R4(pVarIn) < 0.0f) 4404 V_R4(pVarOut) = (float)ceil(V_R4(pVarIn)); 4405 else 4406 V_R4(pVarOut) = (float)floor(V_R4(pVarIn)); 4407 break; 4408 case VT_BSTR: 4409 V_VT(pVarOut) = VT_R8; 4410 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut)); 4411 pVarIn = pVarOut; 4412 /* Fall through */ 4413 case VT_DATE: 4414 case VT_R8: 4415 if (V_R8(pVarIn) < 0.0) 4416 V_R8(pVarOut) = ceil(V_R8(pVarIn)); 4417 else 4418 V_R8(pVarOut) = floor(V_R8(pVarIn)); 4419 break; 4420 case VT_CY: 4421 hRet = VarCyFix(V_CY(pVarIn), &V_CY(pVarOut)); 4422 break; 4423 case VT_DECIMAL: 4424 hRet = VarDecFix(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut)); 4425 break; 4426 case VT_EMPTY: 4427 V_VT(pVarOut) = VT_I2; 4428 V_I2(pVarOut) = 0; 4429 break; 4430 case VT_NULL: 4431 /* No-Op */ 4432 break; 4433 default: 4434 if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */ 4435 FAILED(VARIANT_ValidateType(V_VT(pVarIn)))) 4436 hRet = DISP_E_BADVARTYPE; 4437 else 4438 hRet = DISP_E_TYPEMISMATCH; 4439 } 4440 VarFix_Exit: 4441 if (FAILED(hRet)) 4442 V_VT(pVarOut) = VT_EMPTY; 4443 VariantClear(&temp); 4444 4445 return hRet; 4446 } 4447 4448 /********************************************************************** 4449 * VarInt [OLEAUT32.172] 4450 * 4451 * Truncate a variants value to a whole number. 4452 * 4453 * PARAMS 4454 * pVarIn [I] Source variant 4455 * pVarOut [O] Destination for converted value 4456 * 4457 * RETURNS 4458 * Success: S_OK. pVarOut contains the converted value. 4459 * Failure: An HRESULT error code indicating the error. 4460 * 4461 * NOTES 4462 * - The type of the value stored in pVarOut depends on the type of pVarIn, 4463 * according to the following table: 4464 *| Input Type Output Type 4465 *| ---------- ----------- 4466 *| VT_BOOL VT_I2 4467 *| VT_EMPTY VT_I2 4468 *| VT_BSTR VT_R8 4469 *| All Others Unchanged 4470 * - The difference between this function and VarFix() is that VarFix() rounds 4471 * negative numbers towards 0, while this function rounds them away from zero. 4472 */ 4473 HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut) 4474 { 4475 HRESULT hRet = S_OK; 4476 VARIANT temp; 4477 4478 VariantInit(&temp); 4479 4480 TRACE("(%s,%p)\n", debugstr_variant(pVarIn), pVarOut); 4481 4482 /* Handle VT_DISPATCH by storing and taking address of returned value */ 4483 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) 4484 { 4485 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); 4486 if (FAILED(hRet)) goto VarInt_Exit; 4487 pVarIn = &temp; 4488 } 4489 V_VT(pVarOut) = V_VT(pVarIn); 4490 4491 switch (V_VT(pVarIn)) 4492 { 4493 case VT_R4: 4494 V_R4(pVarOut) = (float)floor(V_R4(pVarIn)); 4495 break; 4496 case VT_BSTR: 4497 V_VT(pVarOut) = VT_R8; 4498 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut)); 4499 pVarIn = pVarOut; 4500 /* Fall through */ 4501 case VT_DATE: 4502 case VT_R8: 4503 V_R8(pVarOut) = floor(V_R8(pVarIn)); 4504 break; 4505 case VT_CY: 4506 hRet = VarCyInt(V_CY(pVarIn), &V_CY(pVarOut)); 4507 break; 4508 case VT_DECIMAL: 4509 hRet = VarDecInt(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut)); 4510 break; 4511 default: 4512 hRet = VarFix(pVarIn, pVarOut); 4513 } 4514 VarInt_Exit: 4515 VariantClear(&temp); 4516 4517 return hRet; 4518 } 4519 4520 /********************************************************************** 4521 * VarXor [OLEAUT32.167] 4522 * 4523 * Perform a logical exclusive-or (XOR) operation on two variants. 4524 * 4525 * PARAMS 4526 * pVarLeft [I] First variant 4527 * pVarRight [I] Variant to XOR with pVarLeft 4528 * pVarOut [O] Destination for XOR result 4529 * 4530 * RETURNS 4531 * Success: S_OK. pVarOut contains the result of the operation with its type 4532 * taken from the table below). 4533 * Failure: An HRESULT error code indicating the error. 4534 * 4535 * NOTES 4536 * - Neither pVarLeft or pVarRight are modified by this function. 4537 * - This function does not process by-reference variants. 4538 * - Input types of VT_BSTR may be numeric strings or boolean text. 4539 * - The type of result stored in pVarOut depends on the types of pVarLeft 4540 * and pVarRight, and will be one of VT_UI1, VT_I2, VT_I4, VT_I8, VT_BOOL, 4541 * or VT_NULL if the function succeeds. 4542 * - Type promotion is inconsistent and as a result certain combinations of 4543 * values will return DISP_E_OVERFLOW even when they could be represented. 4544 * This matches the behaviour of native oleaut32. 4545 */ 4546 HRESULT WINAPI VarXor(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut) 4547 { 4548 VARTYPE vt; 4549 VARIANT varLeft, varRight; 4550 VARIANT tempLeft, tempRight; 4551 double d; 4552 HRESULT hRet; 4553 4554 TRACE("(%s,%s,%p)\n", debugstr_variant(pVarLeft), debugstr_variant(pVarRight), pVarOut); 4555 4556 if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) || 4557 V_VT(pVarLeft) > VT_UINT || V_VT(pVarRight) > VT_UINT || 4558 V_VT(pVarLeft) == VT_VARIANT || V_VT(pVarRight) == VT_VARIANT || 4559 V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN || 4560 V_VT(pVarLeft) == (VARTYPE)15 || V_VT(pVarRight) == (VARTYPE)15 || 4561 V_VT(pVarLeft) == VT_ERROR || V_VT(pVarRight) == VT_ERROR) 4562 return DISP_E_BADVARTYPE; 4563 4564 if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL) 4565 { 4566 /* NULL XOR anything valid is NULL */ 4567 V_VT(pVarOut) = VT_NULL; 4568 return S_OK; 4569 } 4570 4571 VariantInit(&tempLeft); 4572 VariantInit(&tempRight); 4573 4574 /* Handle VT_DISPATCH by storing and taking address of returned value */ 4575 if ((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH) 4576 { 4577 hRet = VARIANT_FetchDispatchValue(pVarLeft, &tempLeft); 4578 if (FAILED(hRet)) goto VarXor_Exit; 4579 pVarLeft = &tempLeft; 4580 } 4581 if ((V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH) 4582 { 4583 hRet = VARIANT_FetchDispatchValue(pVarRight, &tempRight); 4584 if (FAILED(hRet)) goto VarXor_Exit; 4585 pVarRight = &tempRight; 4586 } 4587 4588 /* Copy our inputs so we don't disturb anything */ 4589 V_VT(&varLeft) = V_VT(&varRight) = VT_EMPTY; 4590 4591 hRet = VariantCopy(&varLeft, pVarLeft); 4592 if (FAILED(hRet)) 4593 goto VarXor_Exit; 4594 4595 hRet = VariantCopy(&varRight, pVarRight); 4596 if (FAILED(hRet)) 4597 goto VarXor_Exit; 4598 4599 /* Try any strings first as numbers, then as VT_BOOL */ 4600 if (V_VT(&varLeft) == VT_BSTR) 4601 { 4602 hRet = VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d); 4603 hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, 4604 FAILED(hRet) ? VT_BOOL : VT_I4); 4605 if (FAILED(hRet)) 4606 goto VarXor_Exit; 4607 } 4608 4609 if (V_VT(&varRight) == VT_BSTR) 4610 { 4611 hRet = VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d); 4612 hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, 4613 FAILED(hRet) ? VT_BOOL : VT_I4); 4614 if (FAILED(hRet)) 4615 goto VarXor_Exit; 4616 } 4617 4618 /* Determine the result type */ 4619 if (V_VT(&varLeft) == VT_I8 || V_VT(&varRight) == VT_I8) 4620 { 4621 if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT) 4622 { 4623 hRet = DISP_E_TYPEMISMATCH; 4624 goto VarXor_Exit; 4625 } 4626 vt = VT_I8; 4627 } 4628 else 4629 { 4630 switch ((V_VT(&varLeft) << 16) | V_VT(&varRight)) 4631 { 4632 case (VT_BOOL << 16) | VT_BOOL: 4633 vt = VT_BOOL; 4634 break; 4635 case (VT_UI1 << 16) | VT_UI1: 4636 vt = VT_UI1; 4637 break; 4638 case (VT_EMPTY << 16) | VT_EMPTY: 4639 case (VT_EMPTY << 16) | VT_UI1: 4640 case (VT_EMPTY << 16) | VT_I2: 4641 case (VT_EMPTY << 16) | VT_BOOL: 4642 case (VT_UI1 << 16) | VT_EMPTY: 4643 case (VT_UI1 << 16) | VT_I2: 4644 case (VT_UI1 << 16) | VT_BOOL: 4645 case (VT_I2 << 16) | VT_EMPTY: 4646 case (VT_I2 << 16) | VT_UI1: 4647 case (VT_I2 << 16) | VT_I2: 4648 case (VT_I2 << 16) | VT_BOOL: 4649 case (VT_BOOL << 16) | VT_EMPTY: 4650 case (VT_BOOL << 16) | VT_UI1: 4651 case (VT_BOOL << 16) | VT_I2: 4652 vt = VT_I2; 4653 break; 4654 default: 4655 vt = VT_I4; 4656 break; 4657 } 4658 } 4659 4660 /* VT_UI4 does not overflow */ 4661 if (vt != VT_I8) 4662 { 4663 if (V_VT(&varLeft) == VT_UI4) 4664 V_VT(&varLeft) = VT_I4; 4665 if (V_VT(&varRight) == VT_UI4) 4666 V_VT(&varRight) = VT_I4; 4667 } 4668 4669 /* Convert our input copies to the result type */ 4670 if (V_VT(&varLeft) != vt) 4671 hRet = VariantChangeType(&varLeft, &varLeft, 0, vt); 4672 if (FAILED(hRet)) 4673 goto VarXor_Exit; 4674 4675 if (V_VT(&varRight) != vt) 4676 hRet = VariantChangeType(&varRight, &varRight, 0, vt); 4677 if (FAILED(hRet)) 4678 goto VarXor_Exit; 4679 4680 V_VT(pVarOut) = vt; 4681 4682 /* Calculate the result */ 4683 switch (vt) 4684 { 4685 case VT_I8: 4686 V_I8(pVarOut) = V_I8(&varLeft) ^ V_I8(&varRight); 4687 break; 4688 case VT_I4: 4689 V_I4(pVarOut) = V_I4(&varLeft) ^ V_I4(&varRight); 4690 break; 4691 case VT_BOOL: 4692 case VT_I2: 4693 V_I2(pVarOut) = V_I2(&varLeft) ^ V_I2(&varRight); 4694 break; 4695 case VT_UI1: 4696 V_UI1(pVarOut) = V_UI1(&varLeft) ^ V_UI1(&varRight); 4697 break; 4698 } 4699 4700 VarXor_Exit: 4701 VariantClear(&varLeft); 4702 VariantClear(&varRight); 4703 VariantClear(&tempLeft); 4704 VariantClear(&tempRight); 4705 return hRet; 4706 } 4707 4708 /********************************************************************** 4709 * VarEqv [OLEAUT32.172] 4710 * 4711 * Determine if two variants contain the same value. 4712 * 4713 * PARAMS 4714 * pVarLeft [I] First variant to compare 4715 * pVarRight [I] Variant to compare to pVarLeft 4716 * pVarOut [O] Destination for comparison result 4717 * 4718 * RETURNS 4719 * Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE 4720 * if equivalent or non-zero otherwise. 4721 * Failure: An HRESULT error code indicating the error. 4722 * 4723 * NOTES 4724 * - This function simply calls VarXor() on pVarLeft and pVarRight and inverts 4725 * the result. 4726 */ 4727 HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut) 4728 { 4729 HRESULT hRet; 4730 4731 TRACE("(%s,%s,%p)\n", debugstr_variant(pVarLeft), debugstr_variant(pVarRight), pVarOut); 4732 4733 hRet = VarXor(pVarLeft, pVarRight, pVarOut); 4734 if (SUCCEEDED(hRet)) 4735 { 4736 if (V_VT(pVarOut) == VT_I8) 4737 V_I8(pVarOut) = ~V_I8(pVarOut); 4738 else 4739 V_UI4(pVarOut) = ~V_UI4(pVarOut); 4740 } 4741 return hRet; 4742 } 4743 4744 /********************************************************************** 4745 * VarNeg [OLEAUT32.173] 4746 * 4747 * Negate the value of a variant. 4748 * 4749 * PARAMS 4750 * pVarIn [I] Source variant 4751 * pVarOut [O] Destination for converted value 4752 * 4753 * RETURNS 4754 * Success: S_OK. pVarOut contains the converted value. 4755 * Failure: An HRESULT error code indicating the error. 4756 * 4757 * NOTES 4758 * - The type of the value stored in pVarOut depends on the type of pVarIn, 4759 * according to the following table: 4760 *| Input Type Output Type 4761 *| ---------- ----------- 4762 *| VT_EMPTY VT_I2 4763 *| VT_UI1 VT_I2 4764 *| VT_BOOL VT_I2 4765 *| VT_BSTR VT_R8 4766 *| All Others Unchanged (unless promoted) 4767 * - Where the negated value of a variant does not fit in its base type, the type 4768 * is promoted according to the following table: 4769 *| Input Type Promoted To 4770 *| ---------- ----------- 4771 *| VT_I2 VT_I4 4772 *| VT_I4 VT_R8 4773 *| VT_I8 VT_R8 4774 * - The native version of this function returns DISP_E_BADVARTYPE for valid 4775 * variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH 4776 * for types which are not valid. Since this is in contravention of the 4777 * meaning of those error codes and unlikely to be relied on by applications, 4778 * this implementation returns errors consistent with the other high level 4779 * variant math functions. 4780 */ 4781 HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut) 4782 { 4783 HRESULT hRet = S_OK; 4784 VARIANT temp; 4785 4786 VariantInit(&temp); 4787 4788 TRACE("(%s,%p)\n", debugstr_variant(pVarIn), pVarOut); 4789 4790 /* Handle VT_DISPATCH by storing and taking address of returned value */ 4791 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) 4792 { 4793 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); 4794 if (FAILED(hRet)) goto VarNeg_Exit; 4795 pVarIn = &temp; 4796 } 4797 V_VT(pVarOut) = V_VT(pVarIn); 4798 4799 switch (V_VT(pVarIn)) 4800 { 4801 case VT_UI1: 4802 V_VT(pVarOut) = VT_I2; 4803 V_I2(pVarOut) = -V_UI1(pVarIn); 4804 break; 4805 case VT_BOOL: 4806 V_VT(pVarOut) = VT_I2; 4807 /* Fall through */ 4808 case VT_I2: 4809 if (V_I2(pVarIn) == I2_MIN) 4810 { 4811 V_VT(pVarOut) = VT_I4; 4812 V_I4(pVarOut) = -(int)V_I2(pVarIn); 4813 } 4814 else 4815 V_I2(pVarOut) = -V_I2(pVarIn); 4816 break; 4817 case VT_I4: 4818 if (V_I4(pVarIn) == I4_MIN) 4819 { 4820 V_VT(pVarOut) = VT_R8; 4821 V_R8(pVarOut) = -(double)V_I4(pVarIn); 4822 } 4823 else 4824 V_I4(pVarOut) = -V_I4(pVarIn); 4825 break; 4826 case VT_I8: 4827 if (V_I8(pVarIn) == I8_MIN) 4828 { 4829 V_VT(pVarOut) = VT_R8; 4830 hRet = VarR8FromI8(V_I8(pVarIn), &V_R8(pVarOut)); 4831 V_R8(pVarOut) *= -1.0; 4832 } 4833 else 4834 V_I8(pVarOut) = -V_I8(pVarIn); 4835 break; 4836 case VT_R4: 4837 V_R4(pVarOut) = -V_R4(pVarIn); 4838 break; 4839 case VT_DATE: 4840 case VT_R8: 4841 V_R8(pVarOut) = -V_R8(pVarIn); 4842 break; 4843 case VT_CY: 4844 hRet = VarCyNeg(V_CY(pVarIn), &V_CY(pVarOut)); 4845 break; 4846 case VT_DECIMAL: 4847 hRet = VarDecNeg(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut)); 4848 break; 4849 case VT_BSTR: 4850 V_VT(pVarOut) = VT_R8; 4851 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut)); 4852 V_R8(pVarOut) = -V_R8(pVarOut); 4853 break; 4854 case VT_EMPTY: 4855 V_VT(pVarOut) = VT_I2; 4856 V_I2(pVarOut) = 0; 4857 break; 4858 case VT_NULL: 4859 /* No-Op */ 4860 break; 4861 default: 4862 if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */ 4863 FAILED(VARIANT_ValidateType(V_VT(pVarIn)))) 4864 hRet = DISP_E_BADVARTYPE; 4865 else 4866 hRet = DISP_E_TYPEMISMATCH; 4867 } 4868 VarNeg_Exit: 4869 if (FAILED(hRet)) 4870 V_VT(pVarOut) = VT_EMPTY; 4871 VariantClear(&temp); 4872 4873 return hRet; 4874 } 4875 4876 /********************************************************************** 4877 * VarNot [OLEAUT32.174] 4878 * 4879 * Perform a not operation on a variant. 4880 * 4881 * PARAMS 4882 * pVarIn [I] Source variant 4883 * pVarOut [O] Destination for converted value 4884 * 4885 * RETURNS 4886 * Success: S_OK. pVarOut contains the converted value. 4887 * Failure: An HRESULT error code indicating the error. 4888 * 4889 * NOTES 4890 * - Strictly speaking, this function performs a bitwise ones complement 4891 * on the variants value (after possibly converting to VT_I4, see below). 4892 * This only behaves like a boolean not operation if the value in 4893 * pVarIn is either VARIANT_TRUE or VARIANT_FALSE and the type is signed. 4894 * - To perform a genuine not operation, convert the variant to a VT_BOOL 4895 * before calling this function. 4896 * - This function does not process by-reference variants. 4897 * - The type of the value stored in pVarOut depends on the type of pVarIn, 4898 * according to the following table: 4899 *| Input Type Output Type 4900 *| ---------- ----------- 4901 *| VT_EMPTY VT_I2 4902 *| VT_R4 VT_I4 4903 *| VT_R8 VT_I4 4904 *| VT_BSTR VT_I4 4905 *| VT_DECIMAL VT_I4 4906 *| VT_CY VT_I4 4907 *| (All others) Unchanged 4908 */ 4909 HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut) 4910 { 4911 VARIANT varIn; 4912 HRESULT hRet = S_OK; 4913 VARIANT temp; 4914 4915 VariantInit(&temp); 4916 4917 TRACE("(%s,%p)\n", debugstr_variant(pVarIn), pVarOut); 4918 4919 /* Handle VT_DISPATCH by storing and taking address of returned value */ 4920 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) 4921 { 4922 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); 4923 if (FAILED(hRet)) goto VarNot_Exit; 4924 pVarIn = &temp; 4925 } 4926 4927 if (V_VT(pVarIn) == VT_BSTR) 4928 { 4929 V_VT(&varIn) = VT_R8; 4930 hRet = VarR8FromStr( V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn) ); 4931 if (FAILED(hRet)) 4932 { 4933 V_VT(&varIn) = VT_BOOL; 4934 hRet = VarBoolFromStr( V_BSTR(pVarIn), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &V_BOOL(&varIn) ); 4935 } 4936 if (FAILED(hRet)) goto VarNot_Exit; 4937 pVarIn = &varIn; 4938 } 4939 4940 V_VT(pVarOut) = V_VT(pVarIn); 4941 4942 switch (V_VT(pVarIn)) 4943 { 4944 case VT_I1: 4945 V_I4(pVarOut) = ~V_I1(pVarIn); 4946 V_VT(pVarOut) = VT_I4; 4947 break; 4948 case VT_UI1: V_UI1(pVarOut) = ~V_UI1(pVarIn); break; 4949 case VT_BOOL: 4950 case VT_I2: V_I2(pVarOut) = ~V_I2(pVarIn); break; 4951 case VT_UI2: 4952 V_I4(pVarOut) = ~V_UI2(pVarIn); 4953 V_VT(pVarOut) = VT_I4; 4954 break; 4955 case VT_DECIMAL: 4956 hRet = VarI4FromDec(&V_DECIMAL(pVarIn), &V_I4(&varIn)); 4957 if (FAILED(hRet)) 4958 break; 4959 pVarIn = &varIn; 4960 /* Fall through ... */ 4961 case VT_INT: 4962 V_VT(pVarOut) = VT_I4; 4963 /* Fall through ... */ 4964 case VT_I4: V_I4(pVarOut) = ~V_I4(pVarIn); break; 4965 case VT_UINT: 4966 case VT_UI4: 4967 V_I4(pVarOut) = ~V_UI4(pVarIn); 4968 V_VT(pVarOut) = VT_I4; 4969 break; 4970 case VT_I8: V_I8(pVarOut) = ~V_I8(pVarIn); break; 4971 case VT_UI8: 4972 V_I4(pVarOut) = ~V_UI8(pVarIn); 4973 V_VT(pVarOut) = VT_I4; 4974 break; 4975 case VT_R4: 4976 hRet = VarI4FromR4(V_R4(pVarIn), &V_I4(pVarOut)); 4977 V_I4(pVarOut) = ~V_I4(pVarOut); 4978 V_VT(pVarOut) = VT_I4; 4979 break; 4980 case VT_DATE: 4981 case VT_R8: 4982 hRet = VarI4FromR8(V_R8(pVarIn), &V_I4(pVarOut)); 4983 V_I4(pVarOut) = ~V_I4(pVarOut); 4984 V_VT(pVarOut) = VT_I4; 4985 break; 4986 case VT_CY: 4987 hRet = VarI4FromCy(V_CY(pVarIn), &V_I4(pVarOut)); 4988 V_I4(pVarOut) = ~V_I4(pVarOut); 4989 V_VT(pVarOut) = VT_I4; 4990 break; 4991 case VT_EMPTY: 4992 V_I2(pVarOut) = ~0; 4993 V_VT(pVarOut) = VT_I2; 4994 break; 4995 case VT_NULL: 4996 /* No-Op */ 4997 break; 4998 default: 4999 if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */ 5000 FAILED(VARIANT_ValidateType(V_VT(pVarIn)))) 5001 hRet = DISP_E_BADVARTYPE; 5002 else 5003 hRet = DISP_E_TYPEMISMATCH; 5004 } 5005 VarNot_Exit: 5006 if (FAILED(hRet)) 5007 V_VT(pVarOut) = VT_EMPTY; 5008 VariantClear(&temp); 5009 5010 return hRet; 5011 } 5012 5013 /********************************************************************** 5014 * VarRound [OLEAUT32.175] 5015 * 5016 * Perform a round operation on a variant. 5017 * 5018 * PARAMS 5019 * pVarIn [I] Source variant 5020 * deci [I] Number of decimals to round to 5021 * pVarOut [O] Destination for converted value 5022 * 5023 * RETURNS 5024 * Success: S_OK. pVarOut contains the converted value. 5025 * Failure: An HRESULT error code indicating the error. 5026 * 5027 * NOTES 5028 * - Floating point values are rounded to the desired number of decimals. 5029 * - Some integer types are just copied to the return variable. 5030 * - Some other integer types are not handled and fail. 5031 */ 5032 HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut) 5033 { 5034 VARIANT varIn; 5035 HRESULT hRet = S_OK; 5036 float factor; 5037 VARIANT temp; 5038 5039 VariantInit(&temp); 5040 5041 TRACE("(%s,%d)\n", debugstr_variant(pVarIn), deci); 5042 5043 /* Handle VT_DISPATCH by storing and taking address of returned value */ 5044 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0)) 5045 { 5046 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp); 5047 if (FAILED(hRet)) goto VarRound_Exit; 5048 pVarIn = &temp; 5049 } 5050 5051 switch (V_VT(pVarIn)) 5052 { 5053 /* cases that fail on windows */ 5054 case VT_I1: 5055 case VT_I8: 5056 case VT_UI2: 5057 case VT_UI4: 5058 hRet = DISP_E_BADVARTYPE; 5059 break; 5060 5061 /* cases just copying in to out */ 5062 case VT_UI1: 5063 V_VT(pVarOut) = V_VT(pVarIn); 5064 V_UI1(pVarOut) = V_UI1(pVarIn); 5065 break; 5066 case VT_I2: 5067 V_VT(pVarOut) = V_VT(pVarIn); 5068 V_I2(pVarOut) = V_I2(pVarIn); 5069 break; 5070 case VT_I4: 5071 V_VT(pVarOut) = V_VT(pVarIn); 5072 V_I4(pVarOut) = V_I4(pVarIn); 5073 break; 5074 case VT_NULL: 5075 V_VT(pVarOut) = V_VT(pVarIn); 5076 /* value unchanged */ 5077 break; 5078 5079 /* cases that change type */ 5080 case VT_EMPTY: 5081 V_VT(pVarOut) = VT_I2; 5082 V_I2(pVarOut) = 0; 5083 break; 5084 case VT_BOOL: 5085 V_VT(pVarOut) = VT_I2; 5086 V_I2(pVarOut) = V_BOOL(pVarIn); 5087 break; 5088 case VT_BSTR: 5089 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn)); 5090 if (FAILED(hRet)) 5091 break; 5092 V_VT(&varIn)=VT_R8; 5093 pVarIn = &varIn; 5094 /* Fall through ... */ 5095 5096 /* cases we need to do math */ 5097 case VT_R8: 5098 if (V_R8(pVarIn)>0) { 5099 V_R8(pVarOut)=floor(V_R8(pVarIn)*pow(10, deci)+0.5)/pow(10, deci); 5100 } else { 5101 V_R8(pVarOut)=ceil(V_R8(pVarIn)*pow(10, deci)-0.5)/pow(10, deci); 5102 } 5103 V_VT(pVarOut) = V_VT(pVarIn); 5104 break; 5105 case VT_R4: 5106 if (V_R4(pVarIn)>0) { 5107 V_R4(pVarOut)=floor(V_R4(pVarIn)*pow(10, deci)+0.5)/pow(10, deci); 5108 } else { 5109 V_R4(pVarOut)=ceil(V_R4(pVarIn)*pow(10, deci)-0.5)/pow(10, deci); 5110 } 5111 V_VT(pVarOut) = V_VT(pVarIn); 5112 break; 5113 case VT_DATE: 5114 if (V_DATE(pVarIn)>0) { 5115 V_DATE(pVarOut)=floor(V_DATE(pVarIn)*pow(10, deci)+0.5)/pow(10, deci); 5116 } else { 5117 V_DATE(pVarOut)=ceil(V_DATE(pVarIn)*pow(10, deci)-0.5)/pow(10, deci); 5118 } 5119 V_VT(pVarOut) = V_VT(pVarIn); 5120 break; 5121 case VT_CY: 5122 if (deci>3) 5123 factor=1; 5124 else 5125 factor=pow(10, 4-deci); 5126 5127 if (V_CY(pVarIn).int64>0) { 5128 V_CY(pVarOut).int64=floor(V_CY(pVarIn).int64/factor)*factor; 5129 } else { 5130 V_CY(pVarOut).int64=ceil(V_CY(pVarIn).int64/factor)*factor; 5131 } 5132 V_VT(pVarOut) = V_VT(pVarIn); 5133 break; 5134 case VT_DECIMAL: 5135 { 5136 double dbl; 5137 5138 hRet = VarR8FromDec(&V_DECIMAL(pVarIn), &dbl); 5139 if (FAILED(hRet)) 5140 break; 5141 5142 if (dbl>0.0f) 5143 dbl = floor(dbl*pow(10,deci)+0.5); 5144 else 5145 dbl = ceil(dbl*pow(10,deci)-0.5); 5146 5147 V_VT(pVarOut)=VT_DECIMAL; 5148 hRet = VarDecFromR8(dbl, &V_DECIMAL(pVarOut)); 5149 break; 5150 } 5151 /* cases we don't know yet */ 5152 default: 5153 FIXME("unimplemented part, V_VT(pVarIn) == 0x%X, deci == %d\n", 5154 V_VT(pVarIn) & VT_TYPEMASK, deci); 5155 hRet = DISP_E_BADVARTYPE; 5156 } 5157 VarRound_Exit: 5158 if (FAILED(hRet)) 5159 V_VT(pVarOut) = VT_EMPTY; 5160 VariantClear(&temp); 5161 5162 TRACE("returning 0x%08x %s\n", hRet, debugstr_variant(pVarOut)); 5163 return hRet; 5164 } 5165 5166 /********************************************************************** 5167 * VarIdiv [OLEAUT32.153] 5168 * 5169 * Converts input variants to integers and divides them. 5170 * 5171 * PARAMS 5172 * left [I] Left hand variant 5173 * right [I] Right hand variant 5174 * result [O] Destination for quotient 5175 * 5176 * RETURNS 5177 * Success: S_OK. result contains the quotient. 5178 * Failure: An HRESULT error code indicating the error. 5179 * 5180 * NOTES 5181 * If either expression is null, null is returned, as per MSDN 5182 */ 5183 HRESULT WINAPI VarIdiv(LPVARIANT left, LPVARIANT right, LPVARIANT result) 5184 { 5185 HRESULT hres = S_OK; 5186 VARTYPE resvt = VT_EMPTY; 5187 VARTYPE leftvt,rightvt; 5188 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; 5189 VARIANT lv,rv; 5190 VARIANT tempLeft, tempRight; 5191 5192 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 5193 5194 VariantInit(&lv); 5195 VariantInit(&rv); 5196 VariantInit(&tempLeft); 5197 VariantInit(&tempRight); 5198 5199 leftvt = V_VT(left)&VT_TYPEMASK; 5200 rightvt = V_VT(right)&VT_TYPEMASK; 5201 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); 5202 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK); 5203 5204 if (leftExtraFlags != rightExtraFlags) 5205 { 5206 hres = DISP_E_BADVARTYPE; 5207 goto end; 5208 } 5209 ExtraFlags = leftExtraFlags; 5210 5211 /* Native VarIdiv always returns an error when using extra 5212 * flags or if the variant combination is I8 and INT. 5213 */ 5214 if ((leftvt == VT_I8 && rightvt == VT_INT) || 5215 (leftvt == VT_INT && rightvt == VT_I8) || 5216 (rightvt == VT_EMPTY && leftvt != VT_NULL) || 5217 ExtraFlags != 0) 5218 { 5219 hres = DISP_E_BADVARTYPE; 5220 goto end; 5221 } 5222 5223 /* Determine variant type */ 5224 else if (leftvt == VT_NULL || rightvt == VT_NULL) 5225 { 5226 V_VT(result) = VT_NULL; 5227 hres = S_OK; 5228 goto end; 5229 } 5230 else if (leftvt == VT_I8 || rightvt == VT_I8) 5231 resvt = VT_I8; 5232 else if (leftvt == VT_I4 || rightvt == VT_I4 || 5233 leftvt == VT_INT || rightvt == VT_INT || 5234 leftvt == VT_UINT || rightvt == VT_UINT || 5235 leftvt == VT_UI8 || rightvt == VT_UI8 || 5236 leftvt == VT_UI4 || rightvt == VT_UI4 || 5237 leftvt == VT_UI2 || rightvt == VT_UI2 || 5238 leftvt == VT_I1 || rightvt == VT_I1 || 5239 leftvt == VT_BSTR || rightvt == VT_BSTR || 5240 leftvt == VT_DATE || rightvt == VT_DATE || 5241 leftvt == VT_CY || rightvt == VT_CY || 5242 leftvt == VT_DECIMAL || rightvt == VT_DECIMAL || 5243 leftvt == VT_R8 || rightvt == VT_R8 || 5244 leftvt == VT_R4 || rightvt == VT_R4) 5245 resvt = VT_I4; 5246 else if (leftvt == VT_I2 || rightvt == VT_I2 || 5247 leftvt == VT_BOOL || rightvt == VT_BOOL || 5248 leftvt == VT_EMPTY) 5249 resvt = VT_I2; 5250 else if (leftvt == VT_UI1 || rightvt == VT_UI1) 5251 resvt = VT_UI1; 5252 else 5253 { 5254 hres = DISP_E_BADVARTYPE; 5255 goto end; 5256 } 5257 5258 /* coerce to the result type */ 5259 hres = VariantChangeType(&lv, left, 0, resvt); 5260 if (hres != S_OK) goto end; 5261 hres = VariantChangeType(&rv, right, 0, resvt); 5262 if (hres != S_OK) goto end; 5263 5264 /* do the math */ 5265 V_VT(result) = resvt; 5266 switch (resvt) 5267 { 5268 case VT_UI1: 5269 if (V_UI1(&rv) == 0) 5270 { 5271 hres = DISP_E_DIVBYZERO; 5272 V_VT(result) = VT_EMPTY; 5273 } 5274 else 5275 V_UI1(result) = V_UI1(&lv) / V_UI1(&rv); 5276 break; 5277 case VT_I2: 5278 if (V_I2(&rv) == 0) 5279 { 5280 hres = DISP_E_DIVBYZERO; 5281 V_VT(result) = VT_EMPTY; 5282 } 5283 else 5284 V_I2(result) = V_I2(&lv) / V_I2(&rv); 5285 break; 5286 case VT_I4: 5287 if (V_I4(&rv) == 0) 5288 { 5289 hres = DISP_E_DIVBYZERO; 5290 V_VT(result) = VT_EMPTY; 5291 } 5292 else 5293 V_I4(result) = V_I4(&lv) / V_I4(&rv); 5294 break; 5295 case VT_I8: 5296 if (V_I8(&rv) == 0) 5297 { 5298 hres = DISP_E_DIVBYZERO; 5299 V_VT(result) = VT_EMPTY; 5300 } 5301 else 5302 V_I8(result) = V_I8(&lv) / V_I8(&rv); 5303 break; 5304 default: 5305 FIXME("Couldn't integer divide variant types %d,%d\n", 5306 leftvt,rightvt); 5307 } 5308 5309 end: 5310 VariantClear(&lv); 5311 VariantClear(&rv); 5312 VariantClear(&tempLeft); 5313 VariantClear(&tempRight); 5314 5315 return hres; 5316 } 5317 5318 5319 /********************************************************************** 5320 * VarMod [OLEAUT32.155] 5321 * 5322 * Perform the modulus operation of the right hand variant on the left 5323 * 5324 * PARAMS 5325 * left [I] Left hand variant 5326 * right [I] Right hand variant 5327 * result [O] Destination for converted value 5328 * 5329 * RETURNS 5330 * Success: S_OK. result contains the remainder. 5331 * Failure: An HRESULT error code indicating the error. 5332 * 5333 * NOTE: 5334 * If an error occurs the type of result will be modified but the value will not be. 5335 * Doesn't support arrays or any special flags yet. 5336 */ 5337 HRESULT WINAPI VarMod(LPVARIANT left, LPVARIANT right, LPVARIANT result) 5338 { 5339 BOOL lOk = TRUE; 5340 HRESULT rc = E_FAIL; 5341 int resT = 0; 5342 VARIANT lv,rv; 5343 VARIANT tempLeft, tempRight; 5344 5345 VariantInit(&tempLeft); 5346 VariantInit(&tempRight); 5347 VariantInit(&lv); 5348 VariantInit(&rv); 5349 5350 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 5351 5352 /* Handle VT_DISPATCH by storing and taking address of returned value */ 5353 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) 5354 { 5355 rc = VARIANT_FetchDispatchValue(left, &tempLeft); 5356 if (FAILED(rc)) goto end; 5357 left = &tempLeft; 5358 } 5359 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) 5360 { 5361 rc = VARIANT_FetchDispatchValue(right, &tempRight); 5362 if (FAILED(rc)) goto end; 5363 right = &tempRight; 5364 } 5365 5366 /* check for invalid inputs */ 5367 lOk = TRUE; 5368 switch (V_VT(left) & VT_TYPEMASK) { 5369 case VT_BOOL : 5370 case VT_I1 : 5371 case VT_I2 : 5372 case VT_I4 : 5373 case VT_I8 : 5374 case VT_INT : 5375 case VT_UI1 : 5376 case VT_UI2 : 5377 case VT_UI4 : 5378 case VT_UI8 : 5379 case VT_UINT : 5380 case VT_R4 : 5381 case VT_R8 : 5382 case VT_CY : 5383 case VT_EMPTY: 5384 case VT_DATE : 5385 case VT_BSTR : 5386 case VT_DECIMAL: 5387 break; 5388 case VT_VARIANT: 5389 case VT_UNKNOWN: 5390 V_VT(result) = VT_EMPTY; 5391 rc = DISP_E_TYPEMISMATCH; 5392 goto end; 5393 case VT_ERROR: 5394 rc = DISP_E_TYPEMISMATCH; 5395 goto end; 5396 case VT_RECORD: 5397 V_VT(result) = VT_EMPTY; 5398 rc = DISP_E_TYPEMISMATCH; 5399 goto end; 5400 case VT_NULL: 5401 break; 5402 default: 5403 V_VT(result) = VT_EMPTY; 5404 rc = DISP_E_BADVARTYPE; 5405 goto end; 5406 } 5407 5408 5409 switch (V_VT(right) & VT_TYPEMASK) { 5410 case VT_BOOL : 5411 case VT_I1 : 5412 case VT_I2 : 5413 case VT_I4 : 5414 case VT_I8 : 5415 if((V_VT(left) == VT_INT) && (V_VT(right) == VT_I8)) 5416 { 5417 V_VT(result) = VT_EMPTY; 5418 rc = DISP_E_TYPEMISMATCH; 5419 goto end; 5420 } 5421 case VT_INT : 5422 if((V_VT(right) == VT_INT) && (V_VT(left) == VT_I8)) 5423 { 5424 V_VT(result) = VT_EMPTY; 5425 rc = DISP_E_TYPEMISMATCH; 5426 goto end; 5427 } 5428 case VT_UI1 : 5429 case VT_UI2 : 5430 case VT_UI4 : 5431 case VT_UI8 : 5432 case VT_UINT : 5433 case VT_R4 : 5434 case VT_R8 : 5435 case VT_CY : 5436 if(V_VT(left) == VT_EMPTY) 5437 { 5438 V_VT(result) = VT_I4; 5439 rc = S_OK; 5440 goto end; 5441 } 5442 case VT_EMPTY: 5443 case VT_DATE : 5444 case VT_DECIMAL: 5445 if(V_VT(left) == VT_ERROR) 5446 { 5447 V_VT(result) = VT_EMPTY; 5448 rc = DISP_E_TYPEMISMATCH; 5449 goto end; 5450 } 5451 case VT_BSTR: 5452 if(V_VT(left) == VT_NULL) 5453 { 5454 V_VT(result) = VT_NULL; 5455 rc = S_OK; 5456 goto end; 5457 } 5458 break; 5459 5460 case VT_VOID: 5461 V_VT(result) = VT_EMPTY; 5462 rc = DISP_E_BADVARTYPE; 5463 goto end; 5464 case VT_NULL: 5465 if(V_VT(left) == VT_VOID) 5466 { 5467 V_VT(result) = VT_EMPTY; 5468 rc = DISP_E_BADVARTYPE; 5469 } else if((V_VT(left) == VT_NULL) || (V_VT(left) == VT_EMPTY) || (V_VT(left) == VT_ERROR) || 5470 lOk) 5471 { 5472 V_VT(result) = VT_NULL; 5473 rc = S_OK; 5474 } else 5475 { 5476 V_VT(result) = VT_NULL; 5477 rc = DISP_E_BADVARTYPE; 5478 } 5479 goto end; 5480 case VT_VARIANT: 5481 case VT_UNKNOWN: 5482 V_VT(result) = VT_EMPTY; 5483 rc = DISP_E_TYPEMISMATCH; 5484 goto end; 5485 case VT_ERROR: 5486 rc = DISP_E_TYPEMISMATCH; 5487 goto end; 5488 case VT_RECORD: 5489 if((V_VT(left) == 15) || ((V_VT(left) >= 24) && (V_VT(left) <= 35)) || !lOk) 5490 { 5491 V_VT(result) = VT_EMPTY; 5492 rc = DISP_E_BADVARTYPE; 5493 } else 5494 { 5495 V_VT(result) = VT_EMPTY; 5496 rc = DISP_E_TYPEMISMATCH; 5497 } 5498 goto end; 5499 default: 5500 V_VT(result) = VT_EMPTY; 5501 rc = DISP_E_BADVARTYPE; 5502 goto end; 5503 } 5504 5505 /* determine the result type */ 5506 if((V_VT(left) == VT_I8) || (V_VT(right) == VT_I8)) resT = VT_I8; 5507 else if((V_VT(left) == VT_UI1) && (V_VT(right) == VT_BOOL)) resT = VT_I2; 5508 else if((V_VT(left) == VT_UI1) && (V_VT(right) == VT_UI1)) resT = VT_UI1; 5509 else if((V_VT(left) == VT_UI1) && (V_VT(right) == VT_I2)) resT = VT_I2; 5510 else if((V_VT(left) == VT_I2) && (V_VT(right) == VT_BOOL)) resT = VT_I2; 5511 else if((V_VT(left) == VT_I2) && (V_VT(right) == VT_UI1)) resT = VT_I2; 5512 else if((V_VT(left) == VT_I2) && (V_VT(right) == VT_I2)) resT = VT_I2; 5513 else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_BOOL)) resT = VT_I2; 5514 else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_UI1)) resT = VT_I2; 5515 else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_I2)) resT = VT_I2; 5516 else resT = VT_I4; /* most outputs are I4 */ 5517 5518 /* convert to I8 for the modulo */ 5519 rc = VariantChangeType(&lv, left, 0, VT_I8); 5520 if(FAILED(rc)) 5521 { 5522 FIXME("Could not convert left type %d to %d? rc == 0x%X\n", V_VT(left), VT_I8, rc); 5523 goto end; 5524 } 5525 5526 rc = VariantChangeType(&rv, right, 0, VT_I8); 5527 if(FAILED(rc)) 5528 { 5529 FIXME("Could not convert right type %d to %d? rc == 0x%X\n", V_VT(right), VT_I8, rc); 5530 goto end; 5531 } 5532 5533 /* if right is zero set VT_EMPTY and return divide by zero */ 5534 if(V_I8(&rv) == 0) 5535 { 5536 V_VT(result) = VT_EMPTY; 5537 rc = DISP_E_DIVBYZERO; 5538 goto end; 5539 } 5540 5541 /* perform the modulo operation */ 5542 V_VT(result) = VT_I8; 5543 V_I8(result) = V_I8(&lv) % V_I8(&rv); 5544 5545 TRACE("V_I8(left) == %s, V_I8(right) == %s, V_I8(result) == %s\n", 5546 wine_dbgstr_longlong(V_I8(&lv)), wine_dbgstr_longlong(V_I8(&rv)), 5547 wine_dbgstr_longlong(V_I8(result))); 5548 5549 /* convert left and right to the destination type */ 5550 rc = VariantChangeType(result, result, 0, resT); 5551 if(FAILED(rc)) 5552 { 5553 FIXME("Could not convert 0x%x to %d?\n", V_VT(result), resT); 5554 /* fall to end of function */ 5555 } 5556 5557 end: 5558 VariantClear(&lv); 5559 VariantClear(&rv); 5560 VariantClear(&tempLeft); 5561 VariantClear(&tempRight); 5562 return rc; 5563 } 5564 5565 /********************************************************************** 5566 * VarPow [OLEAUT32.158] 5567 * 5568 * Computes the power of one variant to another variant. 5569 * 5570 * PARAMS 5571 * left [I] First variant 5572 * right [I] Second variant 5573 * result [O] Result variant 5574 * 5575 * RETURNS 5576 * Success: S_OK. 5577 * Failure: An HRESULT error code indicating the error. 5578 */ 5579 HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result) 5580 { 5581 HRESULT hr = S_OK; 5582 VARIANT dl,dr; 5583 VARTYPE resvt = VT_EMPTY; 5584 VARTYPE leftvt,rightvt; 5585 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; 5586 VARIANT tempLeft, tempRight; 5587 5588 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 5589 5590 VariantInit(&dl); 5591 VariantInit(&dr); 5592 VariantInit(&tempLeft); 5593 VariantInit(&tempRight); 5594 5595 /* Handle VT_DISPATCH by storing and taking address of returned value */ 5596 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) 5597 { 5598 hr = VARIANT_FetchDispatchValue(left, &tempLeft); 5599 if (FAILED(hr)) goto end; 5600 left = &tempLeft; 5601 } 5602 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) 5603 { 5604 hr = VARIANT_FetchDispatchValue(right, &tempRight); 5605 if (FAILED(hr)) goto end; 5606 right = &tempRight; 5607 } 5608 5609 leftvt = V_VT(left)&VT_TYPEMASK; 5610 rightvt = V_VT(right)&VT_TYPEMASK; 5611 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); 5612 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK); 5613 5614 if (leftExtraFlags != rightExtraFlags) 5615 { 5616 hr = DISP_E_BADVARTYPE; 5617 goto end; 5618 } 5619 ExtraFlags = leftExtraFlags; 5620 5621 /* Native VarPow always returns an error when using extra flags */ 5622 if (ExtraFlags != 0) 5623 { 5624 hr = DISP_E_BADVARTYPE; 5625 goto end; 5626 } 5627 5628 /* Determine return type */ 5629 else if (leftvt == VT_NULL || rightvt == VT_NULL) { 5630 V_VT(result) = VT_NULL; 5631 hr = S_OK; 5632 goto end; 5633 } 5634 else if ((leftvt == VT_EMPTY || leftvt == VT_I2 || 5635 leftvt == VT_I4 || leftvt == VT_R4 || 5636 leftvt == VT_R8 || leftvt == VT_CY || 5637 leftvt == VT_DATE || leftvt == VT_BSTR || 5638 leftvt == VT_BOOL || leftvt == VT_DECIMAL || 5639 (leftvt >= VT_I1 && leftvt <= VT_UINT)) && 5640 (rightvt == VT_EMPTY || rightvt == VT_I2 || 5641 rightvt == VT_I4 || rightvt == VT_R4 || 5642 rightvt == VT_R8 || rightvt == VT_CY || 5643 rightvt == VT_DATE || rightvt == VT_BSTR || 5644 rightvt == VT_BOOL || rightvt == VT_DECIMAL || 5645 (rightvt >= VT_I1 && rightvt <= VT_UINT))) 5646 resvt = VT_R8; 5647 else 5648 { 5649 hr = DISP_E_BADVARTYPE; 5650 goto end; 5651 } 5652 5653 hr = VariantChangeType(&dl,left,0,resvt); 5654 if (FAILED(hr)) { 5655 ERR("Could not change passed left argument to VT_R8, handle it differently.\n"); 5656 hr = E_FAIL; 5657 goto end; 5658 } 5659 5660 hr = VariantChangeType(&dr,right,0,resvt); 5661 if (FAILED(hr)) { 5662 ERR("Could not change passed right argument to VT_R8, handle it differently.\n"); 5663 hr = E_FAIL; 5664 goto end; 5665 } 5666 5667 V_VT(result) = VT_R8; 5668 V_R8(result) = pow(V_R8(&dl),V_R8(&dr)); 5669 5670 end: 5671 VariantClear(&dl); 5672 VariantClear(&dr); 5673 VariantClear(&tempLeft); 5674 VariantClear(&tempRight); 5675 5676 return hr; 5677 } 5678 5679 /********************************************************************** 5680 * VarImp [OLEAUT32.154] 5681 * 5682 * Bitwise implication of two variants. 5683 * 5684 * PARAMS 5685 * left [I] First variant 5686 * right [I] Second variant 5687 * result [O] Result variant 5688 * 5689 * RETURNS 5690 * Success: S_OK. 5691 * Failure: An HRESULT error code indicating the error. 5692 */ 5693 HRESULT WINAPI VarImp(LPVARIANT left, LPVARIANT right, LPVARIANT result) 5694 { 5695 HRESULT hres = S_OK; 5696 VARTYPE resvt = VT_EMPTY; 5697 VARTYPE leftvt,rightvt; 5698 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags; 5699 VARIANT lv,rv; 5700 double d; 5701 VARIANT tempLeft, tempRight; 5702 5703 VariantInit(&lv); 5704 VariantInit(&rv); 5705 VariantInit(&tempLeft); 5706 VariantInit(&tempRight); 5707 5708 TRACE("(%s,%s,%p)\n", debugstr_variant(left), debugstr_variant(right), result); 5709 5710 /* Handle VT_DISPATCH by storing and taking address of returned value */ 5711 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH) 5712 { 5713 hres = VARIANT_FetchDispatchValue(left, &tempLeft); 5714 if (FAILED(hres)) goto VarImp_Exit; 5715 left = &tempLeft; 5716 } 5717 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH) 5718 { 5719 hres = VARIANT_FetchDispatchValue(right, &tempRight); 5720 if (FAILED(hres)) goto VarImp_Exit; 5721 right = &tempRight; 5722 } 5723 5724 leftvt = V_VT(left)&VT_TYPEMASK; 5725 rightvt = V_VT(right)&VT_TYPEMASK; 5726 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK); 5727 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK); 5728 5729 if (leftExtraFlags != rightExtraFlags) 5730 { 5731 hres = DISP_E_BADVARTYPE; 5732 goto VarImp_Exit; 5733 } 5734 ExtraFlags = leftExtraFlags; 5735 5736 /* Native VarImp always returns an error when using extra 5737 * flags or if the variants are I8 and INT. 5738 */ 5739 if ((leftvt == VT_I8 && rightvt == VT_INT) || 5740 ExtraFlags != 0) 5741 { 5742 hres = DISP_E_BADVARTYPE; 5743 goto VarImp_Exit; 5744 } 5745 5746 /* Determine result type */ 5747 else if ((leftvt == VT_NULL && rightvt == VT_NULL) || 5748 (leftvt == VT_NULL && rightvt == VT_EMPTY)) 5749 { 5750 V_VT(result) = VT_NULL; 5751 hres = S_OK; 5752 goto VarImp_Exit; 5753 } 5754 else if (leftvt == VT_I8 || rightvt == VT_I8) 5755 resvt = VT_I8; 5756 else if (leftvt == VT_I4 || rightvt == VT_I4 || 5757 leftvt == VT_INT || rightvt == VT_INT || 5758 leftvt == VT_UINT || rightvt == VT_UINT || 5759 leftvt == VT_UI4 || rightvt == VT_UI4 || 5760 leftvt == VT_UI8 || rightvt == VT_UI8 || 5761 leftvt == VT_UI2 || rightvt == VT_UI2 || 5762 leftvt == VT_DECIMAL || rightvt == VT_DECIMAL || 5763 leftvt == VT_DATE || rightvt == VT_DATE || 5764 leftvt == VT_CY || rightvt == VT_CY || 5765 leftvt == VT_R8 || rightvt == VT_R8 || 5766 leftvt == VT_R4 || rightvt == VT_R4 || 5767 leftvt == VT_I1 || rightvt == VT_I1) 5768 resvt = VT_I4; 5769 else if ((leftvt == VT_UI1 && rightvt == VT_UI1) || 5770 (leftvt == VT_UI1 && rightvt == VT_NULL) || 5771 (leftvt == VT_NULL && rightvt == VT_UI1)) 5772 resvt = VT_UI1; 5773 else if (leftvt == VT_EMPTY || rightvt == VT_EMPTY || 5774 leftvt == VT_I2 || rightvt == VT_I2 || 5775 leftvt == VT_UI1 || rightvt == VT_UI1) 5776 resvt = VT_I2; 5777 else if (leftvt == VT_BOOL || rightvt == VT_BOOL || 5778 leftvt == VT_BSTR || rightvt == VT_BSTR) 5779 resvt = VT_BOOL; 5780 5781 /* VT_NULL requires special handling for when the opposite 5782 * variant is equal to something other than -1. 5783 * (NULL Imp 0 = NULL, NULL Imp n = n) 5784 */ 5785 if (leftvt == VT_NULL) 5786 { 5787 VARIANT_BOOL b; 5788 switch(rightvt) 5789 { 5790 case VT_I1: if (!V_I1(right)) resvt = VT_NULL; break; 5791 case VT_UI1: if (!V_UI1(right)) resvt = VT_NULL; break; 5792 case VT_I2: if (!V_I2(right)) resvt = VT_NULL; break; 5793 case VT_UI2: if (!V_UI2(right)) resvt = VT_NULL; break; 5794 case VT_I4: if (!V_I4(right)) resvt = VT_NULL; break; 5795 case VT_UI4: if (!V_UI4(right)) resvt = VT_NULL; break; 5796 case VT_I8: if (!V_I8(right)) resvt = VT_NULL; break; 5797 case VT_UI8: if (!V_UI8(right)) resvt = VT_NULL; break; 5798 case VT_INT: if (!V_INT(right)) resvt = VT_NULL; break; 5799 case VT_UINT: if (!V_UINT(right)) resvt = VT_NULL; break; 5800 case VT_BOOL: if (!V_BOOL(right)) resvt = VT_NULL; break; 5801 case VT_R4: if (!V_R4(right)) resvt = VT_NULL; break; 5802 case VT_R8: if (!V_R8(right)) resvt = VT_NULL; break; 5803 case VT_DATE: if (!V_DATE(right)) resvt = VT_NULL; break; 5804 case VT_CY: if (!V_CY(right).int64) resvt = VT_NULL; break; 5805 case VT_DECIMAL: 5806 if (!(DEC_HI32(&V_DECIMAL(right)) || DEC_LO64(&V_DECIMAL(right)))) 5807 resvt = VT_NULL; 5808 break; 5809 case VT_BSTR: 5810 hres = VarBoolFromStr(V_BSTR(right),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b); 5811 if (FAILED(hres)) goto VarImp_Exit; 5812 else if (!b) 5813 V_VT(result) = VT_NULL; 5814 else 5815 { 5816 V_VT(result) = VT_BOOL; 5817 V_BOOL(result) = b; 5818 } 5819 goto VarImp_Exit; 5820 } 5821 if (resvt == VT_NULL) 5822 { 5823 V_VT(result) = resvt; 5824 goto VarImp_Exit; 5825 } 5826 else 5827 { 5828 hres = VariantChangeType(result,right,0,resvt); 5829 goto VarImp_Exit; 5830 } 5831 } 5832 5833 /* Special handling is required when NULL is the right variant. 5834 * (-1 Imp NULL = NULL, n Imp NULL = n Imp 0) 5835 */ 5836 else if (rightvt == VT_NULL) 5837 { 5838 VARIANT_BOOL b; 5839 switch(leftvt) 5840 { 5841 case VT_I1: if (V_I1(left) == -1) resvt = VT_NULL; break; 5842 case VT_UI1: if (V_UI1(left) == 0xff) resvt = VT_NULL; break; 5843 case VT_I2: if (V_I2(left) == -1) resvt = VT_NULL; break; 5844 case VT_UI2: if (V_UI2(left) == 0xffff) resvt = VT_NULL; break; 5845 case VT_INT: if (V_INT(left) == -1) resvt = VT_NULL; break; 5846 case VT_UINT: if (V_UINT(left) == ~0u) resvt = VT_NULL; break; 5847 case VT_I4: if (V_I4(left) == -1) resvt = VT_NULL; break; 5848 case VT_UI4: if (V_UI4(left) == ~0u) resvt = VT_NULL; break; 5849 case VT_I8: if (V_I8(left) == -1) resvt = VT_NULL; break; 5850 case VT_UI8: if (V_UI8(left) == ~(ULONGLONG)0) resvt = VT_NULL; break; 5851 case VT_BOOL: if (V_BOOL(left) == VARIANT_TRUE) resvt = VT_NULL; break; 5852 case VT_R4: if (V_R4(left) == -1.0) resvt = VT_NULL; break; 5853 case VT_R8: if (V_R8(left) == -1.0) resvt = VT_NULL; break; 5854 case VT_CY: if (V_CY(left).int64 == -1) resvt = VT_NULL; break; 5855 case VT_DECIMAL: 5856 if (DEC_HI32(&V_DECIMAL(left)) == 0xffffffff) 5857 resvt = VT_NULL; 5858 break; 5859 case VT_BSTR: 5860 hres = VarBoolFromStr(V_BSTR(left),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b); 5861 if (FAILED(hres)) goto VarImp_Exit; 5862 else if (b == VARIANT_TRUE) 5863 resvt = VT_NULL; 5864 } 5865 if (resvt == VT_NULL) 5866 { 5867 V_VT(result) = resvt; 5868 goto VarImp_Exit; 5869 } 5870 } 5871 5872 hres = VariantCopy(&lv, left); 5873 if (FAILED(hres)) goto VarImp_Exit; 5874 5875 if (rightvt == VT_NULL) 5876 { 5877 memset( &rv, 0, sizeof(rv) ); 5878 V_VT(&rv) = resvt; 5879 } 5880 else 5881 { 5882 hres = VariantCopy(&rv, right); 5883 if (FAILED(hres)) goto VarImp_Exit; 5884 } 5885 5886 if (V_VT(&lv) == VT_BSTR && 5887 FAILED(VarR8FromStr(V_BSTR(&lv),LOCALE_USER_DEFAULT, 0, &d))) 5888 hres = VariantChangeType(&lv,&lv,VARIANT_LOCALBOOL, VT_BOOL); 5889 if (SUCCEEDED(hres) && V_VT(&lv) != resvt) 5890 hres = VariantChangeType(&lv,&lv,0,resvt); 5891 if (FAILED(hres)) goto VarImp_Exit; 5892 5893 if (V_VT(&rv) == VT_BSTR && 5894 FAILED(VarR8FromStr(V_BSTR(&rv),LOCALE_USER_DEFAULT, 0, &d))) 5895 hres = VariantChangeType(&rv, &rv,VARIANT_LOCALBOOL, VT_BOOL); 5896 if (SUCCEEDED(hres) && V_VT(&rv) != resvt) 5897 hres = VariantChangeType(&rv, &rv, 0, resvt); 5898 if (FAILED(hres)) goto VarImp_Exit; 5899 5900 /* do the math */ 5901 V_VT(result) = resvt; 5902 switch (resvt) 5903 { 5904 case VT_I8: 5905 V_I8(result) = (~V_I8(&lv)) | V_I8(&rv); 5906 break; 5907 case VT_I4: 5908 V_I4(result) = (~V_I4(&lv)) | V_I4(&rv); 5909 break; 5910 case VT_I2: 5911 V_I2(result) = (~V_I2(&lv)) | V_I2(&rv); 5912 break; 5913 case VT_UI1: 5914 V_UI1(result) = (~V_UI1(&lv)) | V_UI1(&rv); 5915 break; 5916 case VT_BOOL: 5917 V_BOOL(result) = (~V_BOOL(&lv)) | V_BOOL(&rv); 5918 break; 5919 default: 5920 FIXME("Couldn't perform bitwise implication on variant types %d,%d\n", 5921 leftvt,rightvt); 5922 } 5923 5924 VarImp_Exit: 5925 5926 VariantClear(&lv); 5927 VariantClear(&rv); 5928 VariantClear(&tempLeft); 5929 VariantClear(&tempRight); 5930 5931 return hres; 5932 } 5933