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