2 * Low level variant functions
4 * Copyright 2003 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
25 #include "wine/debug.h"
26 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(variant
);
35 extern HMODULE OLEAUT32_hModule
;
37 #define CY_MULTIPLIER 10000 /* 4 dp of precision */
38 #define CY_MULTIPLIER_F 10000.0
39 #define CY_HALF (CY_MULTIPLIER/2) /* 0.5 */
40 #define CY_HALF_F (CY_MULTIPLIER_F/2.0)
42 static const WCHAR szFloatFormatW
[] = { '%','.','7','G','\0' };
43 static const WCHAR szDoubleFormatW
[] = { '%','.','1','5','G','\0' };
45 /* Copy data from one variant to another. */
46 static inline void VARIANT_CopyData(const VARIANT
*srcVar
, VARTYPE vt
, void *pOut
)
51 case VT_UI1
: memcpy(pOut
, &V_UI1(srcVar
), sizeof(BYTE
)); break;
54 case VT_UI2
: memcpy(pOut
, &V_UI2(srcVar
), sizeof(SHORT
)); break;
59 case VT_UI4
: memcpy(pOut
, &V_UI4(srcVar
), sizeof (LONG
)); break;
64 case VT_UI8
: memcpy(pOut
, &V_UI8(srcVar
), sizeof (LONG64
)); break;
65 case VT_INT_PTR
: memcpy(pOut
, &V_INT_PTR(srcVar
), sizeof (INT_PTR
)); break;
66 case VT_DECIMAL
: memcpy(pOut
, &V_DECIMAL(srcVar
), sizeof (DECIMAL
)); break;
68 FIXME("VT_ type %d unhandled, please report!\n", vt
);
72 /* Macro to inline conversion from a float or double to any integer type,
73 * rounding according to the 'dutch' convention.
75 #define VARIANT_DutchRound(typ, value, res) do { \
76 double whole = value < 0 ? ceil(value) : floor(value); \
77 double fract = value - whole; \
78 if (fract > 0.5) res = (typ)whole + (typ)1; \
79 else if (fract == 0.5) { typ is_odd = (typ)whole & 1; res = whole + is_odd; } \
80 else if (fract >= 0.0) res = (typ)whole; \
81 else if (fract == -0.5) { typ is_odd = (typ)whole & 1; res = whole - is_odd; } \
82 else if (fract > -0.5) res = (typ)whole; \
83 else res = (typ)whole - (typ)1; \
87 /* Coerce VT_BSTR to a numeric type */
88 static HRESULT
VARIANT_NumberFromBstr(OLECHAR
* pStrIn
, LCID lcid
, ULONG ulFlags
,
89 void* pOut
, VARTYPE vt
)
96 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
97 np
.cDig
= sizeof(rgb
) / sizeof(BYTE
);
98 np
.dwInFlags
= NUMPRS_STD
;
100 hRet
= VarParseNumFromStr(pStrIn
, lcid
, ulFlags
, &np
, rgb
);
104 /* 1 << vt gives us the VTBIT constant for the destination number type */
105 hRet
= VarNumFromParseNum(&np
, rgb
, 1 << vt
, &dstVar
);
107 VARIANT_CopyData(&dstVar
, vt
, pOut
);
112 /* Coerce VT_DISPATCH to another type */
113 static HRESULT
VARIANT_FromDisp(IDispatch
* pdispIn
, LCID lcid
, void* pOut
, VARTYPE vt
)
115 static const DISPPARAMS emptyParams
= { NULL
, NULL
, 0, 0 };
116 VARIANTARG srcVar
, dstVar
;
120 return DISP_E_BADVARTYPE
;
122 /* Get the default 'value' property from the IDispatch */
123 hRet
= IDispatch_Invoke(pdispIn
, DISPID_VALUE
, &IID_NULL
, lcid
, DISPATCH_PROPERTYGET
,
124 (DISPPARAMS
*)&emptyParams
, &srcVar
, NULL
, NULL
);
128 /* Convert the property to the requested type */
129 V_VT(&dstVar
) = VT_EMPTY
;
130 hRet
= VariantChangeTypeEx(&dstVar
, &srcVar
, lcid
, 0, vt
);
131 VariantClear(&srcVar
);
135 VARIANT_CopyData(&dstVar
, vt
, pOut
);
136 VariantClear(&srcVar
);
140 hRet
= DISP_E_TYPEMISMATCH
;
144 /* Inline return type */
145 #define RETTYP inline static HRESULT
148 /* Simple compiler cast from one type to another */
149 #define SIMPLE(dest, src, func) RETTYP _##func(src in, dest* out) { \
150 *out = in; return S_OK; }
152 /* Compiler cast where input cannot be negative */
153 #define NEGTST(dest, src, func) RETTYP _##func(src in, dest* out) { \
154 if (in < (src)0) return DISP_E_OVERFLOW; *out = in; return S_OK; }
156 /* Compiler cast where input cannot be > some number */
157 #define POSTST(dest, src, func, tst) RETTYP _##func(src in, dest* out) { \
158 if (in > (dest)tst) return DISP_E_OVERFLOW; *out = in; return S_OK; }
160 /* Compiler cast where input cannot be < some number or >= some other number */
161 #define BOTHTST(dest, src, func, lo, hi) RETTYP _##func(src in, dest* out) { \
162 if (in < (dest)lo || in > hi) return DISP_E_OVERFLOW; *out = in; return S_OK; }
165 POSTST(signed char, BYTE
, VarI1FromUI1
, I1_MAX
);
166 BOTHTST(signed char, SHORT
, VarI1FromI2
, I1_MIN
, I1_MAX
);
167 BOTHTST(signed char, LONG
, VarI1FromI4
, I1_MIN
, I1_MAX
);
168 SIMPLE(signed char, VARIANT_BOOL
, VarI1FromBool
);
169 POSTST(signed char, USHORT
, VarI1FromUI2
, I1_MAX
);
170 POSTST(signed char, ULONG
, VarI1FromUI4
, I1_MAX
);
171 BOTHTST(signed char, LONG64
, VarI1FromI8
, I1_MIN
, I1_MAX
);
172 POSTST(signed char, ULONG64
, VarI1FromUI8
, I1_MAX
);
175 BOTHTST(BYTE
, SHORT
, VarUI1FromI2
, UI1_MIN
, UI1_MAX
);
176 SIMPLE(BYTE
, VARIANT_BOOL
, VarUI1FromBool
);
177 NEGTST(BYTE
, signed char, VarUI1FromI1
);
178 POSTST(BYTE
, USHORT
, VarUI1FromUI2
, UI1_MAX
);
179 BOTHTST(BYTE
, LONG
, VarUI1FromI4
, UI1_MIN
, UI1_MAX
);
180 POSTST(BYTE
, ULONG
, VarUI1FromUI4
, UI1_MAX
);
181 BOTHTST(BYTE
, LONG64
, VarUI1FromI8
, UI1_MIN
, UI1_MAX
);
182 POSTST(BYTE
, ULONG64
, VarUI1FromUI8
, UI1_MAX
);
185 SIMPLE(SHORT
, BYTE
, VarI2FromUI1
);
186 BOTHTST(SHORT
, LONG
, VarI2FromI4
, I2_MIN
, I2_MAX
);
187 SIMPLE(SHORT
, VARIANT_BOOL
, VarI2FromBool
);
188 SIMPLE(SHORT
, signed char, VarI2FromI1
);
189 POSTST(SHORT
, USHORT
, VarI2FromUI2
, I2_MAX
);
190 POSTST(SHORT
, ULONG
, VarI2FromUI4
, I2_MAX
);
191 BOTHTST(SHORT
, LONG64
, VarI2FromI8
, I2_MIN
, I2_MAX
);
192 POSTST(SHORT
, ULONG64
, VarI2FromUI8
, I2_MAX
);
195 SIMPLE(USHORT
, BYTE
, VarUI2FromUI1
);
196 NEGTST(USHORT
, SHORT
, VarUI2FromI2
);
197 BOTHTST(USHORT
, LONG
, VarUI2FromI4
, UI2_MIN
, UI2_MAX
);
198 SIMPLE(USHORT
, VARIANT_BOOL
, VarUI2FromBool
);
199 NEGTST(USHORT
, signed char, VarUI2FromI1
);
200 POSTST(USHORT
, ULONG
, VarUI2FromUI4
, UI2_MAX
);
201 BOTHTST(USHORT
, LONG64
, VarUI2FromI8
, UI2_MIN
, UI2_MAX
);
202 POSTST(USHORT
, ULONG64
, VarUI2FromUI8
, UI2_MAX
);
205 SIMPLE(LONG
, BYTE
, VarI4FromUI1
);
206 SIMPLE(LONG
, SHORT
, VarI4FromI2
);
207 SIMPLE(LONG
, VARIANT_BOOL
, VarI4FromBool
);
208 SIMPLE(LONG
, signed char, VarI4FromI1
);
209 SIMPLE(LONG
, USHORT
, VarI4FromUI2
);
210 POSTST(LONG
, ULONG
, VarI4FromUI4
, I4_MAX
);
211 BOTHTST(LONG
, LONG64
, VarI4FromI8
, I4_MIN
, I4_MAX
);
212 POSTST(LONG
, ULONG64
, VarI4FromUI8
, I4_MAX
);
215 SIMPLE(ULONG
, BYTE
, VarUI4FromUI1
);
216 NEGTST(ULONG
, SHORT
, VarUI4FromI2
);
217 NEGTST(ULONG
, LONG
, VarUI4FromI4
);
218 SIMPLE(ULONG
, VARIANT_BOOL
, VarUI4FromBool
);
219 NEGTST(ULONG
, signed char, VarUI4FromI1
);
220 SIMPLE(ULONG
, USHORT
, VarUI4FromUI2
);
221 BOTHTST(ULONG
, LONG64
, VarUI4FromI8
, UI4_MIN
, UI4_MAX
);
222 POSTST(ULONG
, ULONG64
, VarUI4FromUI8
, UI4_MAX
);
225 SIMPLE(LONG64
, BYTE
, VarI8FromUI1
);
226 SIMPLE(LONG64
, SHORT
, VarI8FromI2
);
227 SIMPLE(LONG64
, signed char, VarI8FromI1
);
228 SIMPLE(LONG64
, USHORT
, VarI8FromUI2
);
229 SIMPLE(LONG64
, LONG
, VarI8FromI4
);
230 SIMPLE(LONG64
, ULONG
, VarI8FromUI4
);
231 POSTST(LONG64
, ULONG64
, VarI8FromUI8
, I8_MAX
);
234 SIMPLE(ULONG64
, BYTE
, VarUI8FromUI1
);
235 NEGTST(ULONG64
, SHORT
, VarUI8FromI2
);
236 NEGTST(ULONG64
, signed char, VarUI8FromI1
);
237 SIMPLE(ULONG64
, USHORT
, VarUI8FromUI2
);
238 NEGTST(ULONG64
, LONG
, VarUI8FromI4
);
239 SIMPLE(ULONG64
, ULONG
, VarUI8FromUI4
);
240 NEGTST(ULONG64
, LONG64
, VarUI8FromI8
);
243 SIMPLE(float, BYTE
, VarR4FromUI1
);
244 SIMPLE(float, SHORT
, VarR4FromI2
);
245 SIMPLE(float, signed char, VarR4FromI1
);
246 SIMPLE(float, USHORT
, VarR4FromUI2
);
247 SIMPLE(float, LONG
, VarR4FromI4
);
248 SIMPLE(float, ULONG
, VarR4FromUI4
);
249 SIMPLE(float, LONG64
, VarR4FromI8
);
250 SIMPLE(float, ULONG64
, VarR4FromUI8
);
253 SIMPLE(double, BYTE
, VarR8FromUI1
);
254 SIMPLE(double, SHORT
, VarR8FromI2
);
255 SIMPLE(double, float, VarR8FromR4
);
256 RETTYP
_VarR8FromCy(CY i
, double* o
) { *o
= (double)i
.int64
/ CY_MULTIPLIER_F
; return S_OK
; }
257 SIMPLE(double, DATE
, VarR8FromDate
);
258 SIMPLE(double, signed char, VarR8FromI1
);
259 SIMPLE(double, USHORT
, VarR8FromUI2
);
260 SIMPLE(double, LONG
, VarR8FromI4
);
261 SIMPLE(double, ULONG
, VarR8FromUI4
);
262 SIMPLE(double, LONG64
, VarR8FromI8
);
263 SIMPLE(double, ULONG64
, VarR8FromUI8
);
269 /************************************************************************
270 * VarI1FromUI1 (OLEAUT32.244)
272 * Convert a VT_UI1 to a VT_I1.
276 * pcOut [O] Destination
280 * Failure: E_INVALIDARG, if the source value is invalid
281 * DISP_E_OVERFLOW, if the value will not fit in the destination
283 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, signed char* pcOut
)
285 return _VarI1FromUI1(bIn
, pcOut
);
288 /************************************************************************
289 * VarI1FromI2 (OLEAUT32.245)
291 * Convert a VT_I2 to a VT_I1.
295 * pcOut [O] Destination
299 * Failure: E_INVALIDARG, if the source value is invalid
300 * DISP_E_OVERFLOW, if the value will not fit in the destination
302 HRESULT WINAPI
VarI1FromI2(SHORT sIn
, signed char* pcOut
)
304 return _VarI1FromI2(sIn
, pcOut
);
307 /************************************************************************
308 * VarI1FromI4 (OLEAUT32.246)
310 * Convert a VT_I4 to a VT_I1.
314 * pcOut [O] Destination
318 * Failure: E_INVALIDARG, if the source value is invalid
319 * DISP_E_OVERFLOW, if the value will not fit in the destination
321 HRESULT WINAPI
VarI1FromI4(LONG iIn
, signed char* pcOut
)
323 return _VarI1FromI4(iIn
, pcOut
);
326 /************************************************************************
327 * VarI1FromR4 (OLEAUT32.247)
329 * Convert a VT_R4 to a VT_I1.
333 * pcOut [O] Destination
337 * Failure: E_INVALIDARG, if the source value is invalid
338 * DISP_E_OVERFLOW, if the value will not fit in the destination
340 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, signed char* pcOut
)
342 return VarI1FromR8(fltIn
, pcOut
);
345 /************************************************************************
346 * VarI1FromR8 (OLEAUT32.248)
348 * Convert a VT_R8 to a VT_I1.
352 * pcOut [O] Destination
356 * Failure: E_INVALIDARG, if the source value is invalid
357 * DISP_E_OVERFLOW, if the value will not fit in the destination
360 * See VarI8FromR8() for details concerning rounding.
362 HRESULT WINAPI
VarI1FromR8(double dblIn
, signed char* pcOut
)
364 if (dblIn
< (double)I1_MIN
|| dblIn
> (double)I1_MAX
)
365 return DISP_E_OVERFLOW
;
366 VARIANT_DutchRound(CHAR
, dblIn
, *pcOut
);
370 /************************************************************************
371 * VarI1FromDate (OLEAUT32.249)
373 * Convert a VT_DATE to a VT_I1.
377 * pcOut [O] Destination
381 * Failure: E_INVALIDARG, if the source value is invalid
382 * DISP_E_OVERFLOW, if the value will not fit in the destination
384 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, signed char* pcOut
)
386 return VarI1FromR8(dateIn
, pcOut
);
389 /************************************************************************
390 * VarI1FromCy (OLEAUT32.250)
392 * Convert a VT_CY to a VT_I1.
396 * pcOut [O] Destination
400 * Failure: E_INVALIDARG, if the source value is invalid
401 * DISP_E_OVERFLOW, if the value will not fit in the destination
403 HRESULT WINAPI
VarI1FromCy(CY cyIn
, signed char* pcOut
)
407 VarI4FromCy(cyIn
, &i
);
408 return _VarI1FromI4(i
, pcOut
);
411 /************************************************************************
412 * VarI1FromStr (OLEAUT32.251)
414 * Convert a VT_BSTR to a VT_I1.
418 * lcid [I] LCID for the conversion
419 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
420 * pcOut [O] Destination
424 * Failure: E_INVALIDARG, if the source value is invalid
425 * DISP_E_OVERFLOW, if the value will not fit in the destination
426 * DISP_E_TYPEMISMATCH, if the type cannot be converted
428 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, signed char* pcOut
)
430 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pcOut
, VT_I1
);
433 /************************************************************************
434 * VarI1FromDisp (OLEAUT32.252)
436 * Convert a VT_DISPATCH to a VT_I1.
440 * lcid [I] LCID for conversion
441 * pcOut [O] Destination
445 * Failure: E_INVALIDARG, if the source value is invalid
446 * DISP_E_OVERFLOW, if the value will not fit in the destination
447 * DISP_E_TYPEMISMATCH, if the type cannot be converted
449 HRESULT WINAPI
VarI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, signed char* pcOut
)
451 return VARIANT_FromDisp(pdispIn
, lcid
, pcOut
, VT_I1
);
454 /************************************************************************
455 * VarI1FromBool (OLEAUT32.253)
457 * Convert a VT_BOOL to a VT_I1.
461 * pcOut [O] Destination
466 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, signed char* pcOut
)
468 return _VarI1FromBool(boolIn
, pcOut
);
471 /************************************************************************
472 * VarI1FromUI2 (OLEAUT32.254)
474 * Convert a VT_UI2 to a VT_I1.
478 * pcOut [O] Destination
482 * Failure: E_INVALIDARG, if the source value is invalid
483 * DISP_E_OVERFLOW, if the value will not fit in the destination
485 HRESULT WINAPI
VarI1FromUI2(USHORT usIn
, signed char* pcOut
)
487 return _VarI1FromUI2(usIn
, pcOut
);
490 /************************************************************************
491 * VarI1FromUI4 (OLEAUT32.255)
493 * Convert a VT_UI4 to a VT_I1.
497 * pcOut [O] Destination
501 * Failure: E_INVALIDARG, if the source value is invalid
502 * DISP_E_OVERFLOW, if the value will not fit in the destination
503 * DISP_E_TYPEMISMATCH, if the type cannot be converted
505 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, signed char* pcOut
)
507 return _VarI1FromUI4(ulIn
, pcOut
);
510 /************************************************************************
511 * VarI1FromDec (OLEAUT32.256)
513 * Convert a VT_DECIMAL to a VT_I1.
517 * pcOut [O] Destination
521 * Failure: E_INVALIDARG, if the source value is invalid
522 * DISP_E_OVERFLOW, if the value will not fit in the destination
524 HRESULT WINAPI
VarI1FromDec(DECIMAL
*pdecIn
, signed char* pcOut
)
529 hRet
= VarI8FromDec(pdecIn
, &i64
);
532 hRet
= _VarI1FromI8(i64
, pcOut
);
536 /************************************************************************
537 * VarI1FromI8 (OLEAUT32.376)
539 * Convert a VT_I8 to a VT_I1.
543 * pcOut [O] Destination
547 * Failure: E_INVALIDARG, if the source value is invalid
548 * DISP_E_OVERFLOW, if the value will not fit in the destination
550 HRESULT WINAPI
VarI1FromI8(LONG64 llIn
, signed char* pcOut
)
552 return _VarI1FromI8(llIn
, pcOut
);
555 /************************************************************************
556 * VarI1FromUI8 (OLEAUT32.377)
558 * Convert a VT_UI8 to a VT_I1.
562 * pcOut [O] Destination
566 * Failure: E_INVALIDARG, if the source value is invalid
567 * DISP_E_OVERFLOW, if the value will not fit in the destination
569 HRESULT WINAPI
VarI1FromUI8(ULONG64 ullIn
, signed char* pcOut
)
571 return _VarI1FromUI8(ullIn
, pcOut
);
577 /************************************************************************
578 * VarUI1FromI2 (OLEAUT32.130)
580 * Convert a VT_I2 to a VT_UI1.
584 * pbOut [O] Destination
588 * Failure: E_INVALIDARG, if the source value is invalid
589 * DISP_E_OVERFLOW, if the value will not fit in the destination
591 HRESULT WINAPI
VarUI1FromI2(SHORT sIn
, BYTE
* pbOut
)
593 return _VarUI1FromI2(sIn
, pbOut
);
596 /************************************************************************
597 * VarUI1FromI4 (OLEAUT32.131)
599 * Convert a VT_I4 to a VT_UI1.
603 * pbOut [O] Destination
607 * Failure: E_INVALIDARG, if the source value is invalid
608 * DISP_E_OVERFLOW, if the value will not fit in the destination
610 HRESULT WINAPI
VarUI1FromI4(LONG iIn
, BYTE
* pbOut
)
612 return _VarUI1FromI4(iIn
, pbOut
);
615 /************************************************************************
616 * VarUI1FromR4 (OLEAUT32.132)
618 * Convert a VT_R4 to a VT_UI1.
622 * pbOut [O] Destination
626 * Failure: E_INVALIDARG, if the source value is invalid
627 * DISP_E_OVERFLOW, if the value will not fit in the destination
628 * DISP_E_TYPEMISMATCH, if the type cannot be converted
630 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
632 return VarUI1FromR8(fltIn
, pbOut
);
635 /************************************************************************
636 * VarUI1FromR8 (OLEAUT32.133)
638 * Convert a VT_R8 to a VT_UI1.
642 * pbOut [O] Destination
646 * Failure: E_INVALIDARG, if the source value is invalid
647 * DISP_E_OVERFLOW, if the value will not fit in the destination
650 * See VarI8FromR8() for details concerning rounding.
652 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
654 if (dblIn
< -0.5 || dblIn
> (double)UI1_MAX
)
655 return DISP_E_OVERFLOW
;
656 VARIANT_DutchRound(BYTE
, dblIn
, *pbOut
);
660 /************************************************************************
661 * VarUI1FromCy (OLEAUT32.134)
663 * Convert a VT_CY to a VT_UI1.
667 * pbOut [O] Destination
671 * Failure: E_INVALIDARG, if the source value is invalid
672 * DISP_E_OVERFLOW, if the value will not fit in the destination
675 * Negative values >= -5000 will be converted to 0.
677 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
)
679 ULONG i
= UI1_MAX
+ 1;
681 VarUI4FromCy(cyIn
, &i
);
682 return _VarUI1FromUI4(i
, pbOut
);
685 /************************************************************************
686 * VarUI1FromDate (OLEAUT32.135)
688 * Convert a VT_DATE to a VT_UI1.
692 * pbOut [O] Destination
696 * Failure: E_INVALIDARG, if the source value is invalid
697 * DISP_E_OVERFLOW, if the value will not fit in the destination
699 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
701 return VarUI1FromR8(dateIn
, pbOut
);
704 /************************************************************************
705 * VarUI1FromStr (OLEAUT32.136)
707 * Convert a VT_BSTR to a VT_UI1.
711 * lcid [I] LCID for the conversion
712 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
713 * pbOut [O] Destination
717 * Failure: E_INVALIDARG, if the source value is invalid
718 * DISP_E_OVERFLOW, if the value will not fit in the destination
719 * DISP_E_TYPEMISMATCH, if the type cannot be converted
721 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
723 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pbOut
, VT_UI1
);
726 /************************************************************************
727 * VarUI1FromDisp (OLEAUT32.137)
729 * Convert a VT_DISPATCH to a VT_UI1.
733 * lcid [I] LCID for conversion
734 * pbOut [O] Destination
738 * Failure: E_INVALIDARG, if the source value is invalid
739 * DISP_E_OVERFLOW, if the value will not fit in the destination
740 * DISP_E_TYPEMISMATCH, if the type cannot be converted
742 HRESULT WINAPI
VarUI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, BYTE
* pbOut
)
744 return VARIANT_FromDisp(pdispIn
, lcid
, pbOut
, VT_UI1
);
747 /************************************************************************
748 * VarUI1FromBool (OLEAUT32.138)
750 * Convert a VT_BOOL to a VT_UI1.
754 * pbOut [O] Destination
759 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
761 return _VarUI1FromBool(boolIn
, pbOut
);
764 /************************************************************************
765 * VarUI1FromI1 (OLEAUT32.237)
767 * Convert a VT_I1 to a VT_UI1.
771 * pbOut [O] Destination
775 * Failure: E_INVALIDARG, if the source value is invalid
776 * DISP_E_OVERFLOW, if the value will not fit in the destination
778 HRESULT WINAPI
VarUI1FromI1(signed char cIn
, BYTE
* pbOut
)
780 return _VarUI1FromI1(cIn
, pbOut
);
783 /************************************************************************
784 * VarUI1FromUI2 (OLEAUT32.238)
786 * Convert a VT_UI2 to a VT_UI1.
790 * pbOut [O] Destination
794 * Failure: E_INVALIDARG, if the source value is invalid
795 * DISP_E_OVERFLOW, if the value will not fit in the destination
797 HRESULT WINAPI
VarUI1FromUI2(USHORT usIn
, BYTE
* pbOut
)
799 return _VarUI1FromUI2(usIn
, pbOut
);
802 /************************************************************************
803 * VarUI1FromUI4 (OLEAUT32.239)
805 * Convert a VT_UI4 to a VT_UI1.
809 * pbOut [O] Destination
813 * Failure: E_INVALIDARG, if the source value is invalid
814 * DISP_E_OVERFLOW, if the value will not fit in the destination
816 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
818 return _VarUI1FromUI4(ulIn
, pbOut
);
821 /************************************************************************
822 * VarUI1FromDec (OLEAUT32.240)
824 * Convert a VT_DECIMAL to a VT_UI1.
828 * pbOut [O] Destination
832 * Failure: E_INVALIDARG, if the source value is invalid
833 * DISP_E_OVERFLOW, if the value will not fit in the destination
835 HRESULT WINAPI
VarUI1FromDec(DECIMAL
*pdecIn
, BYTE
* pbOut
)
840 hRet
= VarI8FromDec(pdecIn
, &i64
);
843 hRet
= _VarUI1FromI8(i64
, pbOut
);
847 /************************************************************************
848 * VarUI1FromI8 (OLEAUT32.372)
850 * Convert a VT_I8 to a VT_UI1.
854 * pbOut [O] Destination
858 * Failure: E_INVALIDARG, if the source value is invalid
859 * DISP_E_OVERFLOW, if the value will not fit in the destination
861 HRESULT WINAPI
VarUI1FromI8(LONG64 llIn
, BYTE
* pbOut
)
863 return _VarUI1FromI8(llIn
, pbOut
);
866 /************************************************************************
867 * VarUI1FromUI8 (OLEAUT32.373)
869 * Convert a VT_UI8 to a VT_UI1.
873 * pbOut [O] Destination
877 * Failure: E_INVALIDARG, if the source value is invalid
878 * DISP_E_OVERFLOW, if the value will not fit in the destination
880 HRESULT WINAPI
VarUI1FromUI8(ULONG64 ullIn
, BYTE
* pbOut
)
882 return _VarUI1FromUI8(ullIn
, pbOut
);
889 /************************************************************************
890 * VarI2FromUI1 (OLEAUT32.48)
892 * Convert a VT_UI2 to a VT_I2.
896 * psOut [O] Destination
901 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, SHORT
* psOut
)
903 return _VarI2FromUI1(bIn
, psOut
);
906 /************************************************************************
907 * VarI2FromI4 (OLEAUT32.49)
909 * Convert a VT_I4 to a VT_I2.
913 * psOut [O] Destination
917 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
919 HRESULT WINAPI
VarI2FromI4(LONG iIn
, SHORT
* psOut
)
921 return _VarI2FromI4(iIn
, psOut
);
924 /************************************************************************
925 * VarI2FromR4 (OLEAUT32.50)
927 * Convert a VT_R4 to a VT_I2.
931 * psOut [O] Destination
935 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
937 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, SHORT
* psOut
)
939 return VarI2FromR8(fltIn
, psOut
);
942 /************************************************************************
943 * VarI2FromR8 (OLEAUT32.51)
945 * Convert a VT_R8 to a VT_I2.
949 * psOut [O] Destination
953 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
956 * See VarI8FromR8() for details concerning rounding.
958 HRESULT WINAPI
VarI2FromR8(double dblIn
, SHORT
* psOut
)
960 if (dblIn
< (double)I2_MIN
|| dblIn
> (double)I2_MAX
)
961 return DISP_E_OVERFLOW
;
962 VARIANT_DutchRound(SHORT
, dblIn
, *psOut
);
966 /************************************************************************
967 * VarI2FromCy (OLEAUT32.52)
969 * Convert a VT_CY to a VT_I2.
973 * psOut [O] Destination
977 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
979 HRESULT WINAPI
VarI2FromCy(CY cyIn
, SHORT
* psOut
)
983 VarI4FromCy(cyIn
, &i
);
984 return _VarI2FromI4(i
, psOut
);
987 /************************************************************************
988 * VarI2FromDate (OLEAUT32.53)
990 * Convert a VT_DATE to a VT_I2.
994 * psOut [O] Destination
998 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1000 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, SHORT
* psOut
)
1002 return VarI2FromR8(dateIn
, psOut
);
1005 /************************************************************************
1006 * VarI2FromStr (OLEAUT32.54)
1008 * Convert a VT_BSTR to a VT_I2.
1012 * lcid [I] LCID for the conversion
1013 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1014 * psOut [O] Destination
1018 * Failure: E_INVALIDARG, if any parameter is invalid
1019 * DISP_E_OVERFLOW, if the value will not fit in the destination
1020 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1022 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, SHORT
* psOut
)
1024 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, psOut
, VT_I2
);
1027 /************************************************************************
1028 * VarI2FromDisp (OLEAUT32.55)
1030 * Convert a VT_DISPATCH to a VT_I2.
1033 * pdispIn [I] Source
1034 * lcid [I] LCID for conversion
1035 * psOut [O] Destination
1039 * Failure: E_INVALIDARG, if pdispIn is invalid,
1040 * DISP_E_OVERFLOW, if the value will not fit in the destination,
1041 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1043 HRESULT WINAPI
VarI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, SHORT
* psOut
)
1045 return VARIANT_FromDisp(pdispIn
, lcid
, psOut
, VT_I2
);
1048 /************************************************************************
1049 * VarI2FromBool (OLEAUT32.56)
1051 * Convert a VT_BOOL to a VT_I2.
1055 * psOut [O] Destination
1060 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, SHORT
* psOut
)
1062 return _VarI2FromBool(boolIn
, psOut
);
1065 /************************************************************************
1066 * VarI2FromI1 (OLEAUT32.205)
1068 * Convert a VT_I1 to a VT_I2.
1072 * psOut [O] Destination
1077 HRESULT WINAPI
VarI2FromI1(signed char cIn
, SHORT
* psOut
)
1079 return _VarI2FromI1(cIn
, psOut
);
1082 /************************************************************************
1083 * VarI2FromUI2 (OLEAUT32.206)
1085 * Convert a VT_UI2 to a VT_I2.
1089 * psOut [O] Destination
1093 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1095 HRESULT WINAPI
VarI2FromUI2(USHORT usIn
, SHORT
* psOut
)
1097 return _VarI2FromUI2(usIn
, psOut
);
1100 /************************************************************************
1101 * VarI2FromUI4 (OLEAUT32.207)
1103 * Convert a VT_UI4 to a VT_I2.
1107 * psOut [O] Destination
1111 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1113 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, SHORT
* psOut
)
1115 return _VarI2FromUI4(ulIn
, psOut
);
1118 /************************************************************************
1119 * VarI2FromDec (OLEAUT32.208)
1121 * Convert a VT_DECIMAL to a VT_I2.
1125 * psOut [O] Destination
1129 * Failure: E_INVALIDARG, if the source value is invalid
1130 * DISP_E_OVERFLOW, if the value will not fit in the destination
1132 HRESULT WINAPI
VarI2FromDec(DECIMAL
*pdecIn
, SHORT
* psOut
)
1137 hRet
= VarI8FromDec(pdecIn
, &i64
);
1139 if (SUCCEEDED(hRet
))
1140 hRet
= _VarI2FromI8(i64
, psOut
);
1144 /************************************************************************
1145 * VarI2FromI8 (OLEAUT32.346)
1147 * Convert a VT_I8 to a VT_I2.
1151 * psOut [O] Destination
1155 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1157 HRESULT WINAPI
VarI2FromI8(LONG64 llIn
, SHORT
* psOut
)
1159 return _VarI2FromI8(llIn
, psOut
);
1162 /************************************************************************
1163 * VarI2FromUI8 (OLEAUT32.347)
1165 * Convert a VT_UI8 to a VT_I2.
1169 * psOut [O] Destination
1173 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1175 HRESULT WINAPI
VarI2FromUI8(ULONG64 ullIn
, SHORT
* psOut
)
1177 return _VarI2FromUI8(ullIn
, psOut
);
1183 /************************************************************************
1184 * VarUI2FromUI1 (OLEAUT32.257)
1186 * Convert a VT_UI1 to a VT_UI2.
1190 * pusOut [O] Destination
1195 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* pusOut
)
1197 return _VarUI2FromUI1(bIn
, pusOut
);
1200 /************************************************************************
1201 * VarUI2FromI2 (OLEAUT32.258)
1203 * Convert a VT_I2 to a VT_UI2.
1207 * pusOut [O] Destination
1211 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1213 HRESULT WINAPI
VarUI2FromI2(SHORT sIn
, USHORT
* pusOut
)
1215 return _VarUI2FromI2(sIn
, pusOut
);
1218 /************************************************************************
1219 * VarUI2FromI4 (OLEAUT32.259)
1221 * Convert a VT_I4 to a VT_UI2.
1225 * pusOut [O] Destination
1229 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1231 HRESULT WINAPI
VarUI2FromI4(LONG iIn
, USHORT
* pusOut
)
1233 return _VarUI2FromI4(iIn
, pusOut
);
1236 /************************************************************************
1237 * VarUI2FromR4 (OLEAUT32.260)
1239 * Convert a VT_R4 to a VT_UI2.
1243 * pusOut [O] Destination
1247 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1249 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* pusOut
)
1251 return VarUI2FromR8(fltIn
, pusOut
);
1254 /************************************************************************
1255 * VarUI2FromR8 (OLEAUT32.261)
1257 * Convert a VT_R8 to a VT_UI2.
1261 * pusOut [O] Destination
1265 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1268 * See VarI8FromR8() for details concerning rounding.
1270 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* pusOut
)
1272 if (dblIn
< -0.5 || dblIn
> (double)UI2_MAX
)
1273 return DISP_E_OVERFLOW
;
1274 VARIANT_DutchRound(USHORT
, dblIn
, *pusOut
);
1278 /************************************************************************
1279 * VarUI2FromDate (OLEAUT32.262)
1281 * Convert a VT_DATE to a VT_UI2.
1285 * pusOut [O] Destination
1289 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1291 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* pusOut
)
1293 return VarUI2FromR8(dateIn
, pusOut
);
1296 /************************************************************************
1297 * VarUI2FromCy (OLEAUT32.263)
1299 * Convert a VT_CY to a VT_UI2.
1303 * pusOut [O] Destination
1307 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1310 * Negative values >= -5000 will be converted to 0.
1312 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
)
1314 ULONG i
= UI2_MAX
+ 1;
1316 VarUI4FromCy(cyIn
, &i
);
1317 return _VarUI2FromUI4(i
, pusOut
);
1320 /************************************************************************
1321 * VarUI2FromStr (OLEAUT32.264)
1323 * Convert a VT_BSTR to a VT_UI2.
1327 * lcid [I] LCID for the conversion
1328 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1329 * pusOut [O] Destination
1333 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1334 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1336 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* pusOut
)
1338 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pusOut
, VT_UI2
);
1341 /************************************************************************
1342 * VarUI2FromDisp (OLEAUT32.265)
1344 * Convert a VT_DISPATCH to a VT_UI2.
1347 * pdispIn [I] Source
1348 * lcid [I] LCID for conversion
1349 * pusOut [O] Destination
1353 * Failure: E_INVALIDARG, if the source value is invalid
1354 * DISP_E_OVERFLOW, if the value will not fit in the destination
1355 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1357 HRESULT WINAPI
VarUI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, USHORT
* pusOut
)
1359 return VARIANT_FromDisp(pdispIn
, lcid
, pusOut
, VT_UI2
);
1362 /************************************************************************
1363 * VarUI2FromBool (OLEAUT32.266)
1365 * Convert a VT_BOOL to a VT_UI2.
1369 * pusOut [O] Destination
1374 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* pusOut
)
1376 return _VarUI2FromBool(boolIn
, pusOut
);
1379 /************************************************************************
1380 * VarUI2FromI1 (OLEAUT32.267)
1382 * Convert a VT_I1 to a VT_UI2.
1386 * pusOut [O] Destination
1390 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1392 HRESULT WINAPI
VarUI2FromI1(signed char cIn
, USHORT
* pusOut
)
1394 return _VarUI2FromI1(cIn
, pusOut
);
1397 /************************************************************************
1398 * VarUI2FromUI4 (OLEAUT32.268)
1400 * Convert a VT_UI4 to a VT_UI2.
1404 * pusOut [O] Destination
1408 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1410 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* pusOut
)
1412 return _VarUI2FromUI4(ulIn
, pusOut
);
1415 /************************************************************************
1416 * VarUI2FromDec (OLEAUT32.269)
1418 * Convert a VT_DECIMAL to a VT_UI2.
1422 * pusOut [O] Destination
1426 * Failure: E_INVALIDARG, if the source value is invalid
1427 * DISP_E_OVERFLOW, if the value will not fit in the destination
1429 HRESULT WINAPI
VarUI2FromDec(DECIMAL
*pdecIn
, USHORT
* pusOut
)
1434 hRet
= VarI8FromDec(pdecIn
, &i64
);
1436 if (SUCCEEDED(hRet
))
1437 hRet
= _VarUI2FromI8(i64
, pusOut
);
1441 /************************************************************************
1442 * VarUI2FromI8 (OLEAUT32.378)
1444 * Convert a VT_I8 to a VT_UI2.
1448 * pusOut [O] Destination
1452 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1454 HRESULT WINAPI
VarUI2FromI8(LONG64 llIn
, USHORT
* pusOut
)
1456 return _VarUI2FromI8(llIn
, pusOut
);
1459 /************************************************************************
1460 * VarUI2FromUI8 (OLEAUT32.379)
1462 * Convert a VT_UI8 to a VT_UI2.
1466 * pusOut [O] Destination
1470 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1472 HRESULT WINAPI
VarUI2FromUI8(ULONG64 ullIn
, USHORT
* pusOut
)
1474 return _VarUI2FromUI8(ullIn
, pusOut
);
1480 /************************************************************************
1481 * VarI4FromUI1 (OLEAUT32.58)
1483 * Convert a VT_UI1 to a VT_I4.
1487 * piOut [O] Destination
1492 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
*piOut
)
1494 return _VarI4FromUI1(bIn
, piOut
);
1497 /************************************************************************
1498 * VarI4FromI2 (OLEAUT32.59)
1500 * Convert a VT_I2 to a VT_I4.
1504 * piOut [O] Destination
1508 * Failure: E_INVALIDARG, if the source value is invalid
1509 * DISP_E_OVERFLOW, if the value will not fit in the destination
1511 HRESULT WINAPI
VarI4FromI2(SHORT sIn
, LONG
*piOut
)
1513 return _VarI4FromI2(sIn
, piOut
);
1516 /************************************************************************
1517 * VarI4FromR4 (OLEAUT32.60)
1519 * Convert a VT_R4 to a VT_I4.
1523 * piOut [O] Destination
1527 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1529 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
*piOut
)
1531 return VarI4FromR8(fltIn
, piOut
);
1534 /************************************************************************
1535 * VarI4FromR8 (OLEAUT32.61)
1537 * Convert a VT_R8 to a VT_I4.
1541 * piOut [O] Destination
1545 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1548 * See VarI8FromR8() for details concerning rounding.
1550 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
*piOut
)
1552 if (dblIn
< (double)I4_MIN
|| dblIn
> (double)I4_MAX
)
1553 return DISP_E_OVERFLOW
;
1554 VARIANT_DutchRound(LONG
, dblIn
, *piOut
);
1558 /************************************************************************
1559 * VarI4FromCy (OLEAUT32.62)
1561 * Convert a VT_CY to a VT_I4.
1565 * piOut [O] Destination
1569 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1571 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
*piOut
)
1573 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1574 return VarI4FromR8(d
, piOut
);
1577 /************************************************************************
1578 * VarI4FromDate (OLEAUT32.63)
1580 * Convert a VT_DATE to a VT_I4.
1584 * piOut [O] Destination
1588 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1590 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
*piOut
)
1592 return VarI4FromR8(dateIn
, piOut
);
1595 /************************************************************************
1596 * VarI4FromStr (OLEAUT32.64)
1598 * Convert a VT_BSTR to a VT_I4.
1602 * lcid [I] LCID for the conversion
1603 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1604 * piOut [O] Destination
1608 * Failure: E_INVALIDARG, if any parameter is invalid
1609 * DISP_E_OVERFLOW, if the value will not fit in the destination
1610 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1612 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
*piOut
)
1614 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, piOut
, VT_I4
);
1617 /************************************************************************
1618 * VarI4FromDisp (OLEAUT32.65)
1620 * Convert a VT_DISPATCH to a VT_I4.
1623 * pdispIn [I] Source
1624 * lcid [I] LCID for conversion
1625 * piOut [O] Destination
1629 * Failure: E_INVALIDARG, if the source value is invalid
1630 * DISP_E_OVERFLOW, if the value will not fit in the destination
1631 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1633 HRESULT WINAPI
VarI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG
*piOut
)
1635 return VARIANT_FromDisp(pdispIn
, lcid
, piOut
, VT_I4
);
1638 /************************************************************************
1639 * VarI4FromBool (OLEAUT32.66)
1641 * Convert a VT_BOOL to a VT_I4.
1645 * piOut [O] Destination
1650 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
*piOut
)
1652 return _VarI4FromBool(boolIn
, piOut
);
1655 /************************************************************************
1656 * VarI4FromI1 (OLEAUT32.209)
1658 * Convert a VT_I4 to a VT_I4.
1662 * piOut [O] Destination
1667 HRESULT WINAPI
VarI4FromI1(signed char cIn
, LONG
*piOut
)
1669 return _VarI4FromI1(cIn
, piOut
);
1672 /************************************************************************
1673 * VarI4FromUI2 (OLEAUT32.210)
1675 * Convert a VT_UI2 to a VT_I4.
1679 * piOut [O] Destination
1684 HRESULT WINAPI
VarI4FromUI2(USHORT usIn
, LONG
*piOut
)
1686 return _VarI4FromUI2(usIn
, piOut
);
1689 /************************************************************************
1690 * VarI4FromUI4 (OLEAUT32.211)
1692 * Convert a VT_UI4 to a VT_I4.
1696 * piOut [O] Destination
1700 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1702 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
*piOut
)
1704 return _VarI4FromUI4(ulIn
, piOut
);
1707 /************************************************************************
1708 * VarI4FromDec (OLEAUT32.212)
1710 * Convert a VT_DECIMAL to a VT_I4.
1714 * piOut [O] Destination
1718 * Failure: E_INVALIDARG, if pdecIn is invalid
1719 * DISP_E_OVERFLOW, if the value will not fit in the destination
1721 HRESULT WINAPI
VarI4FromDec(DECIMAL
*pdecIn
, LONG
*piOut
)
1726 hRet
= VarI8FromDec(pdecIn
, &i64
);
1728 if (SUCCEEDED(hRet
))
1729 hRet
= _VarI4FromI8(i64
, piOut
);
1733 /************************************************************************
1734 * VarI4FromI8 (OLEAUT32.348)
1736 * Convert a VT_I8 to a VT_I4.
1740 * piOut [O] Destination
1744 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1746 HRESULT WINAPI
VarI4FromI8(LONG64 llIn
, LONG
*piOut
)
1748 return _VarI4FromI8(llIn
, piOut
);
1751 /************************************************************************
1752 * VarI4FromUI8 (OLEAUT32.349)
1754 * Convert a VT_UI8 to a VT_I4.
1758 * piOut [O] Destination
1762 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1764 HRESULT WINAPI
VarI4FromUI8(ULONG64 ullIn
, LONG
*piOut
)
1766 return _VarI4FromUI8(ullIn
, piOut
);
1772 /************************************************************************
1773 * VarUI4FromUI1 (OLEAUT32.270)
1775 * Convert a VT_UI1 to a VT_UI4.
1779 * pulOut [O] Destination
1784 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
*pulOut
)
1786 return _VarUI4FromUI1(bIn
, pulOut
);
1789 /************************************************************************
1790 * VarUI4FromI2 (OLEAUT32.271)
1792 * Convert a VT_I2 to a VT_UI4.
1796 * pulOut [O] Destination
1800 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1802 HRESULT WINAPI
VarUI4FromI2(SHORT sIn
, ULONG
*pulOut
)
1804 return _VarUI4FromI2(sIn
, pulOut
);
1807 /************************************************************************
1808 * VarUI4FromI4 (OLEAUT32.272)
1810 * Convert a VT_I4 to a VT_UI4.
1814 * pulOut [O] Destination
1818 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1820 HRESULT WINAPI
VarUI4FromI4(LONG iIn
, ULONG
*pulOut
)
1822 return _VarUI4FromI4(iIn
, pulOut
);
1825 /************************************************************************
1826 * VarUI4FromR4 (OLEAUT32.273)
1828 * Convert a VT_R4 to a VT_UI4.
1832 * pulOut [O] Destination
1836 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1838 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
*pulOut
)
1840 return VarUI4FromR8(fltIn
, pulOut
);
1843 /************************************************************************
1844 * VarUI4FromR8 (OLEAUT32.274)
1846 * Convert a VT_R8 to a VT_UI4.
1850 * pulOut [O] Destination
1854 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1857 * See VarI8FromR8() for details concerning rounding.
1859 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
*pulOut
)
1861 if (dblIn
< -0.5 || dblIn
> (double)UI4_MAX
)
1862 return DISP_E_OVERFLOW
;
1863 VARIANT_DutchRound(ULONG
, dblIn
, *pulOut
);
1867 /************************************************************************
1868 * VarUI4FromDate (OLEAUT32.275)
1870 * Convert a VT_DATE to a VT_UI4.
1874 * pulOut [O] Destination
1878 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1880 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
*pulOut
)
1882 return VarUI4FromR8(dateIn
, pulOut
);
1885 /************************************************************************
1886 * VarUI4FromCy (OLEAUT32.276)
1888 * Convert a VT_CY to a VT_UI4.
1892 * pulOut [O] Destination
1896 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1898 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
*pulOut
)
1900 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1901 return VarUI4FromR8(d
, pulOut
);
1904 /************************************************************************
1905 * VarUI4FromStr (OLEAUT32.277)
1907 * Convert a VT_BSTR to a VT_UI4.
1911 * lcid [I] LCID for the conversion
1912 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1913 * pulOut [O] Destination
1917 * Failure: E_INVALIDARG, if any parameter is invalid
1918 * DISP_E_OVERFLOW, if the value will not fit in the destination
1919 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1921 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
*pulOut
)
1923 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pulOut
, VT_UI4
);
1926 /************************************************************************
1927 * VarUI4FromDisp (OLEAUT32.278)
1929 * Convert a VT_DISPATCH to a VT_UI4.
1932 * pdispIn [I] Source
1933 * lcid [I] LCID for conversion
1934 * pulOut [O] Destination
1938 * Failure: E_INVALIDARG, if the source value is invalid
1939 * DISP_E_OVERFLOW, if the value will not fit in the destination
1940 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1942 HRESULT WINAPI
VarUI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG
*pulOut
)
1944 return VARIANT_FromDisp(pdispIn
, lcid
, pulOut
, VT_UI4
);
1947 /************************************************************************
1948 * VarUI4FromBool (OLEAUT32.279)
1950 * Convert a VT_BOOL to a VT_UI4.
1954 * pulOut [O] Destination
1959 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
*pulOut
)
1961 return _VarUI4FromBool(boolIn
, pulOut
);
1964 /************************************************************************
1965 * VarUI4FromI1 (OLEAUT32.280)
1967 * Convert a VT_I1 to a VT_UI4.
1971 * pulOut [O] Destination
1975 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1977 HRESULT WINAPI
VarUI4FromI1(signed char cIn
, ULONG
*pulOut
)
1979 return _VarUI4FromI1(cIn
, pulOut
);
1982 /************************************************************************
1983 * VarUI4FromUI2 (OLEAUT32.281)
1985 * Convert a VT_UI2 to a VT_UI4.
1989 * pulOut [O] Destination
1994 HRESULT WINAPI
VarUI4FromUI2(USHORT usIn
, ULONG
*pulOut
)
1996 return _VarUI4FromUI2(usIn
, pulOut
);
1999 /************************************************************************
2000 * VarUI4FromDec (OLEAUT32.282)
2002 * Convert a VT_DECIMAL to a VT_UI4.
2006 * pulOut [O] Destination
2010 * Failure: E_INVALIDARG, if pdecIn is invalid
2011 * DISP_E_OVERFLOW, if the value will not fit in the destination
2013 HRESULT WINAPI
VarUI4FromDec(DECIMAL
*pdecIn
, ULONG
*pulOut
)
2018 hRet
= VarI8FromDec(pdecIn
, &i64
);
2020 if (SUCCEEDED(hRet
))
2021 hRet
= _VarUI4FromI8(i64
, pulOut
);
2025 /************************************************************************
2026 * VarUI4FromI8 (OLEAUT32.425)
2028 * Convert a VT_I8 to a VT_UI4.
2032 * pulOut [O] Destination
2036 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2038 HRESULT WINAPI
VarUI4FromI8(LONG64 llIn
, ULONG
*pulOut
)
2040 return _VarUI4FromI8(llIn
, pulOut
);
2043 /************************************************************************
2044 * VarUI4FromUI8 (OLEAUT32.426)
2046 * Convert a VT_UI8 to a VT_UI4.
2050 * pulOut [O] Destination
2054 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2056 HRESULT WINAPI
VarUI4FromUI8(ULONG64 ullIn
, ULONG
*pulOut
)
2058 return _VarUI4FromUI8(ullIn
, pulOut
);
2064 /************************************************************************
2065 * VarI8FromUI1 (OLEAUT32.333)
2067 * Convert a VT_UI1 to a VT_I8.
2071 * pi64Out [O] Destination
2076 HRESULT WINAPI
VarI8FromUI1(BYTE bIn
, LONG64
* pi64Out
)
2078 return _VarI8FromUI1(bIn
, pi64Out
);
2082 /************************************************************************
2083 * VarI8FromI2 (OLEAUT32.334)
2085 * Convert a VT_I2 to a VT_I8.
2089 * pi64Out [O] Destination
2094 HRESULT WINAPI
VarI8FromI2(SHORT sIn
, LONG64
* pi64Out
)
2096 return _VarI8FromI2(sIn
, pi64Out
);
2099 /************************************************************************
2100 * VarI8FromR4 (OLEAUT32.335)
2102 * Convert a VT_R4 to a VT_I8.
2106 * pi64Out [O] Destination
2110 * Failure: E_INVALIDARG, if the source value is invalid
2111 * DISP_E_OVERFLOW, if the value will not fit in the destination
2113 HRESULT WINAPI
VarI8FromR4(FLOAT fltIn
, LONG64
* pi64Out
)
2115 return VarI8FromR8(fltIn
, pi64Out
);
2118 /************************************************************************
2119 * VarI8FromR8 (OLEAUT32.336)
2121 * Convert a VT_R8 to a VT_I8.
2125 * pi64Out [O] Destination
2129 * Failure: E_INVALIDARG, if the source value is invalid
2130 * DISP_E_OVERFLOW, if the value will not fit in the destination
2133 * Only values that fit into 63 bits are accepted. Due to rounding issues,
2134 * very high or low values will not be accurately converted.
2136 * Numbers are rounded using Dutch rounding, as follows:
2138 *| Fractional Part Sign Direction Example
2139 *| --------------- ---- --------- -------
2140 *| < 0.5 + Down 0.4 -> 0.0
2141 *| < 0.5 - Up -0.4 -> 0.0
2142 *| > 0.5 + Up 0.6 -> 1.0
2143 *| < 0.5 - Up -0.6 -> -1.0
2144 *| = 0.5 + Up/Down Down if even, Up if odd
2145 *| = 0.5 - Up/Down Up if even, Down if odd
2147 * This system is often used in supermarkets.
2149 HRESULT WINAPI
VarI8FromR8(double dblIn
, LONG64
* pi64Out
)
2151 if ( dblIn
< -4611686018427387904.0 || dblIn
>= 4611686018427387904.0)
2152 return DISP_E_OVERFLOW
;
2153 VARIANT_DutchRound(LONG64
, dblIn
, *pi64Out
);
2157 /************************************************************************
2158 * VarI8FromCy (OLEAUT32.337)
2160 * Convert a VT_CY to a VT_I8.
2164 * pi64Out [O] Destination
2170 * All negative numbers are rounded down by 1, including those that are
2171 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2172 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2175 HRESULT WINAPI
VarI8FromCy(CY cyIn
, LONG64
* pi64Out
)
2177 *pi64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2180 (*pi64Out
)--; /* Mimic Win32 bug */
2183 cyIn
.int64
-= *pi64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2185 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pi64Out
& 0x1)))
2191 /************************************************************************
2192 * VarI8FromDate (OLEAUT32.338)
2194 * Convert a VT_DATE to a VT_I8.
2198 * pi64Out [O] Destination
2202 * Failure: E_INVALIDARG, if the source value is invalid
2203 * DISP_E_OVERFLOW, if the value will not fit in the destination
2204 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2206 HRESULT WINAPI
VarI8FromDate(DATE dateIn
, LONG64
* pi64Out
)
2208 return VarI8FromR8(dateIn
, pi64Out
);
2211 /************************************************************************
2212 * VarI8FromStr (OLEAUT32.339)
2214 * Convert a VT_BSTR to a VT_I8.
2218 * lcid [I] LCID for the conversion
2219 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2220 * pi64Out [O] Destination
2224 * Failure: E_INVALIDARG, if the source value is invalid
2225 * DISP_E_OVERFLOW, if the value will not fit in the destination
2226 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2228 HRESULT WINAPI
VarI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG64
* pi64Out
)
2230 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pi64Out
, VT_I8
);
2233 /************************************************************************
2234 * VarI8FromDisp (OLEAUT32.340)
2236 * Convert a VT_DISPATCH to a VT_I8.
2239 * pdispIn [I] Source
2240 * lcid [I] LCID for conversion
2241 * pi64Out [O] Destination
2245 * Failure: E_INVALIDARG, if the source value is invalid
2246 * DISP_E_OVERFLOW, if the value will not fit in the destination
2247 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2249 HRESULT WINAPI
VarI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG64
* pi64Out
)
2251 return VARIANT_FromDisp(pdispIn
, lcid
, pi64Out
, VT_I8
);
2254 /************************************************************************
2255 * VarI8FromBool (OLEAUT32.341)
2257 * Convert a VT_BOOL to a VT_I8.
2261 * pi64Out [O] Destination
2266 HRESULT WINAPI
VarI8FromBool(VARIANT_BOOL boolIn
, LONG64
* pi64Out
)
2268 return VarI8FromI2(boolIn
, pi64Out
);
2271 /************************************************************************
2272 * VarI8FromI1 (OLEAUT32.342)
2274 * Convert a VT_I1 to a VT_I8.
2278 * pi64Out [O] Destination
2283 HRESULT WINAPI
VarI8FromI1(signed char cIn
, LONG64
* pi64Out
)
2285 return _VarI8FromI1(cIn
, pi64Out
);
2288 /************************************************************************
2289 * VarI8FromUI2 (OLEAUT32.343)
2291 * Convert a VT_UI2 to a VT_I8.
2295 * pi64Out [O] Destination
2300 HRESULT WINAPI
VarI8FromUI2(USHORT usIn
, LONG64
* pi64Out
)
2302 return _VarI8FromUI2(usIn
, pi64Out
);
2305 /************************************************************************
2306 * VarI8FromUI4 (OLEAUT32.344)
2308 * Convert a VT_UI4 to a VT_I8.
2312 * pi64Out [O] Destination
2317 HRESULT WINAPI
VarI8FromUI4(ULONG ulIn
, LONG64
* pi64Out
)
2319 return _VarI8FromUI4(ulIn
, pi64Out
);
2322 /************************************************************************
2323 * VarI8FromDec (OLEAUT32.345)
2325 * Convert a VT_DECIMAL to a VT_I8.
2329 * pi64Out [O] Destination
2333 * Failure: E_INVALIDARG, if the source value is invalid
2334 * DISP_E_OVERFLOW, if the value will not fit in the destination
2336 HRESULT WINAPI
VarI8FromDec(DECIMAL
*pdecIn
, LONG64
* pi64Out
)
2338 if (!DEC_SCALE(pdecIn
))
2340 /* This decimal is just a 96 bit integer */
2341 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2342 return E_INVALIDARG
;
2344 if (DEC_HI32(pdecIn
) || DEC_MID32(pdecIn
) & 0x80000000)
2345 return DISP_E_OVERFLOW
;
2347 if (DEC_SIGN(pdecIn
))
2348 *pi64Out
= -DEC_LO64(pdecIn
);
2350 *pi64Out
= DEC_LO64(pdecIn
);
2355 /* Decimal contains a floating point number */
2359 hRet
= VarR8FromDec(pdecIn
, &dbl
);
2360 if (SUCCEEDED(hRet
))
2361 hRet
= VarI8FromR8(dbl
, pi64Out
);
2366 /************************************************************************
2367 * VarI8FromUI8 (OLEAUT32.427)
2369 * Convert a VT_UI8 to a VT_I8.
2373 * pi64Out [O] Destination
2377 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2379 HRESULT WINAPI
VarI8FromUI8(ULONG64 ullIn
, LONG64
* pi64Out
)
2381 return _VarI8FromUI8(ullIn
, pi64Out
);
2387 /************************************************************************
2388 * VarUI8FromI8 (OLEAUT32.428)
2390 * Convert a VT_I8 to a VT_UI8.
2394 * pui64Out [O] Destination
2398 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2400 HRESULT WINAPI
VarUI8FromI8(LONG64 llIn
, ULONG64
* pui64Out
)
2402 return _VarUI8FromI8(llIn
, pui64Out
);
2405 /************************************************************************
2406 * VarUI8FromUI1 (OLEAUT32.429)
2408 * Convert a VT_UI1 to a VT_UI8.
2412 * pui64Out [O] Destination
2417 HRESULT WINAPI
VarUI8FromUI1(BYTE bIn
, ULONG64
* pui64Out
)
2419 return _VarUI8FromUI1(bIn
, pui64Out
);
2422 /************************************************************************
2423 * VarUI8FromI2 (OLEAUT32.430)
2425 * Convert a VT_I2 to a VT_UI8.
2429 * pui64Out [O] Destination
2434 HRESULT WINAPI
VarUI8FromI2(SHORT sIn
, ULONG64
* pui64Out
)
2436 return _VarUI8FromI2(sIn
, pui64Out
);
2439 /************************************************************************
2440 * VarUI8FromR4 (OLEAUT32.431)
2442 * Convert a VT_R4 to a VT_UI8.
2446 * pui64Out [O] Destination
2450 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2452 HRESULT WINAPI
VarUI8FromR4(FLOAT fltIn
, ULONG64
* pui64Out
)
2454 return VarUI8FromR8(fltIn
, pui64Out
);
2457 /************************************************************************
2458 * VarUI8FromR8 (OLEAUT32.432)
2460 * Convert a VT_R8 to a VT_UI8.
2464 * pui64Out [O] Destination
2468 * Failure: E_INVALIDARG, if the source value is invalid
2469 * DISP_E_OVERFLOW, if the value will not fit in the destination
2472 * See VarI8FromR8() for details concerning rounding.
2474 HRESULT WINAPI
VarUI8FromR8(double dblIn
, ULONG64
* pui64Out
)
2476 if (dblIn
< -0.5 || dblIn
> 1.844674407370955e19
)
2477 return DISP_E_OVERFLOW
;
2478 VARIANT_DutchRound(ULONG64
, dblIn
, *pui64Out
);
2482 /************************************************************************
2483 * VarUI8FromCy (OLEAUT32.433)
2485 * Convert a VT_CY to a VT_UI8.
2489 * pui64Out [O] Destination
2493 * Failure: E_INVALIDARG, if the source value is invalid
2494 * DISP_E_OVERFLOW, if the value will not fit in the destination
2497 * Negative values >= -5000 will be converted to 0.
2499 HRESULT WINAPI
VarUI8FromCy(CY cyIn
, ULONG64
* pui64Out
)
2503 if (cyIn
.int64
< -CY_HALF
)
2504 return DISP_E_OVERFLOW
;
2509 *pui64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2511 cyIn
.int64
-= *pui64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2513 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pui64Out
& 0x1)))
2519 /************************************************************************
2520 * VarUI8FromDate (OLEAUT32.434)
2522 * Convert a VT_DATE to a VT_UI8.
2526 * pui64Out [O] Destination
2530 * Failure: E_INVALIDARG, if the source value is invalid
2531 * DISP_E_OVERFLOW, if the value will not fit in the destination
2532 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2534 HRESULT WINAPI
VarUI8FromDate(DATE dateIn
, ULONG64
* pui64Out
)
2536 return VarUI8FromR8(dateIn
, pui64Out
);
2539 /************************************************************************
2540 * VarUI8FromStr (OLEAUT32.435)
2542 * Convert a VT_BSTR to a VT_UI8.
2546 * lcid [I] LCID for the conversion
2547 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2548 * pui64Out [O] Destination
2552 * Failure: E_INVALIDARG, if the source value is invalid
2553 * DISP_E_OVERFLOW, if the value will not fit in the destination
2554 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2556 HRESULT WINAPI
VarUI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG64
* pui64Out
)
2558 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pui64Out
, VT_UI8
);
2561 /************************************************************************
2562 * VarUI8FromDisp (OLEAUT32.436)
2564 * Convert a VT_DISPATCH to a VT_UI8.
2567 * pdispIn [I] Source
2568 * lcid [I] LCID for conversion
2569 * pui64Out [O] Destination
2573 * Failure: E_INVALIDARG, if the source value is invalid
2574 * DISP_E_OVERFLOW, if the value will not fit in the destination
2575 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2577 HRESULT WINAPI
VarUI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG64
* pui64Out
)
2579 return VARIANT_FromDisp(pdispIn
, lcid
, pui64Out
, VT_UI8
);
2582 /************************************************************************
2583 * VarUI8FromBool (OLEAUT32.437)
2585 * Convert a VT_BOOL to a VT_UI8.
2589 * pui64Out [O] Destination
2593 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2595 HRESULT WINAPI
VarUI8FromBool(VARIANT_BOOL boolIn
, ULONG64
* pui64Out
)
2597 return VarI8FromI2(boolIn
, (LONG64
*)pui64Out
);
2599 /************************************************************************
2600 * VarUI8FromI1 (OLEAUT32.438)
2602 * Convert a VT_I1 to a VT_UI8.
2606 * pui64Out [O] Destination
2610 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2612 HRESULT WINAPI
VarUI8FromI1(signed char cIn
, ULONG64
* pui64Out
)
2614 return _VarUI8FromI1(cIn
, pui64Out
);
2617 /************************************************************************
2618 * VarUI8FromUI2 (OLEAUT32.439)
2620 * Convert a VT_UI2 to a VT_UI8.
2624 * pui64Out [O] Destination
2629 HRESULT WINAPI
VarUI8FromUI2(USHORT usIn
, ULONG64
* pui64Out
)
2631 return _VarUI8FromUI2(usIn
, pui64Out
);
2634 /************************************************************************
2635 * VarUI8FromUI4 (OLEAUT32.440)
2637 * Convert a VT_UI4 to a VT_UI8.
2641 * pui64Out [O] Destination
2646 HRESULT WINAPI
VarUI8FromUI4(ULONG ulIn
, ULONG64
* pui64Out
)
2648 return _VarUI8FromUI4(ulIn
, pui64Out
);
2651 /************************************************************************
2652 * VarUI8FromDec (OLEAUT32.441)
2654 * Convert a VT_DECIMAL to a VT_UI8.
2658 * pui64Out [O] Destination
2662 * Failure: E_INVALIDARG, if the source value is invalid
2663 * DISP_E_OVERFLOW, if the value will not fit in the destination
2666 * Under native Win32, if the source value has a scale of 0, its sign is
2667 * ignored, i.e. this function takes the absolute value rather than fail
2668 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2669 * (use VarAbs() on pDecIn first if you really want this behaviour).
2671 HRESULT WINAPI
VarUI8FromDec(DECIMAL
*pdecIn
, ULONG64
* pui64Out
)
2673 if (!DEC_SCALE(pdecIn
))
2675 /* This decimal is just a 96 bit integer */
2676 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2677 return E_INVALIDARG
;
2679 if (DEC_HI32(pdecIn
))
2680 return DISP_E_OVERFLOW
;
2682 if (DEC_SIGN(pdecIn
))
2684 WARN("Sign would be ignored under Win32!\n");
2685 return DISP_E_OVERFLOW
;
2688 *pui64Out
= DEC_LO64(pdecIn
);
2693 /* Decimal contains a floating point number */
2697 hRet
= VarR8FromDec(pdecIn
, &dbl
);
2698 if (SUCCEEDED(hRet
))
2699 hRet
= VarUI8FromR8(dbl
, pui64Out
);
2707 /************************************************************************
2708 * VarR4FromUI1 (OLEAUT32.68)
2710 * Convert a VT_UI1 to a VT_R4.
2714 * pFltOut [O] Destination
2719 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, float *pFltOut
)
2721 return _VarR4FromUI1(bIn
, pFltOut
);
2724 /************************************************************************
2725 * VarR4FromI2 (OLEAUT32.69)
2727 * Convert a VT_I2 to a VT_R4.
2731 * pFltOut [O] Destination
2736 HRESULT WINAPI
VarR4FromI2(SHORT sIn
, float *pFltOut
)
2738 return _VarR4FromI2(sIn
, pFltOut
);
2741 /************************************************************************
2742 * VarR4FromI4 (OLEAUT32.70)
2744 * Convert a VT_I4 to a VT_R4.
2748 * pFltOut [O] Destination
2753 HRESULT WINAPI
VarR4FromI4(LONG lIn
, float *pFltOut
)
2755 return _VarR4FromI4(lIn
, pFltOut
);
2758 /************************************************************************
2759 * VarR4FromR8 (OLEAUT32.71)
2761 * Convert a VT_R8 to a VT_R4.
2765 * pFltOut [O] Destination
2769 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2771 HRESULT WINAPI
VarR4FromR8(double dblIn
, float *pFltOut
)
2773 double d
= dblIn
< 0.0 ? -dblIn
: dblIn
;
2774 if (d
> R4_MAX
) return DISP_E_OVERFLOW
;
2779 /************************************************************************
2780 * VarR4FromCy (OLEAUT32.72)
2782 * Convert a VT_CY to a VT_R4.
2786 * pFltOut [O] Destination
2791 HRESULT WINAPI
VarR4FromCy(CY cyIn
, float *pFltOut
)
2793 *pFltOut
= (double)cyIn
.int64
/ CY_MULTIPLIER_F
;
2797 /************************************************************************
2798 * VarR4FromDate (OLEAUT32.73)
2800 * Convert a VT_DATE to a VT_R4.
2804 * pFltOut [O] Destination
2808 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2810 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, float *pFltOut
)
2812 return VarR4FromR8(dateIn
, pFltOut
);
2815 /************************************************************************
2816 * VarR4FromStr (OLEAUT32.74)
2818 * Convert a VT_BSTR to a VT_R4.
2822 * lcid [I] LCID for the conversion
2823 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2824 * pFltOut [O] Destination
2828 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2829 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2831 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, float *pFltOut
)
2833 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pFltOut
, VT_R4
);
2836 /************************************************************************
2837 * VarR4FromDisp (OLEAUT32.75)
2839 * Convert a VT_DISPATCH to a VT_R4.
2842 * pdispIn [I] Source
2843 * lcid [I] LCID for conversion
2844 * pFltOut [O] Destination
2848 * Failure: E_INVALIDARG, if the source value is invalid
2849 * DISP_E_OVERFLOW, if the value will not fit in the destination
2850 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2852 HRESULT WINAPI
VarR4FromDisp(IDispatch
* pdispIn
, LCID lcid
, float *pFltOut
)
2854 return VARIANT_FromDisp(pdispIn
, lcid
, pFltOut
, VT_R4
);
2857 /************************************************************************
2858 * VarR4FromBool (OLEAUT32.76)
2860 * Convert a VT_BOOL to a VT_R4.
2864 * pFltOut [O] Destination
2869 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, float *pFltOut
)
2871 return VarR4FromI2(boolIn
, pFltOut
);
2874 /************************************************************************
2875 * VarR4FromI1 (OLEAUT32.213)
2877 * Convert a VT_I1 to a VT_R4.
2881 * pFltOut [O] Destination
2885 * Failure: E_INVALIDARG, if the source value is invalid
2886 * DISP_E_OVERFLOW, if the value will not fit in the destination
2887 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2889 HRESULT WINAPI
VarR4FromI1(signed char cIn
, float *pFltOut
)
2891 return _VarR4FromI1(cIn
, pFltOut
);
2894 /************************************************************************
2895 * VarR4FromUI2 (OLEAUT32.214)
2897 * Convert a VT_UI2 to a VT_R4.
2901 * pFltOut [O] Destination
2905 * Failure: E_INVALIDARG, if the source value is invalid
2906 * DISP_E_OVERFLOW, if the value will not fit in the destination
2907 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2909 HRESULT WINAPI
VarR4FromUI2(USHORT usIn
, float *pFltOut
)
2911 return _VarR4FromUI2(usIn
, pFltOut
);
2914 /************************************************************************
2915 * VarR4FromUI4 (OLEAUT32.215)
2917 * Convert a VT_UI4 to a VT_R4.
2921 * pFltOut [O] Destination
2925 * Failure: E_INVALIDARG, if the source value is invalid
2926 * DISP_E_OVERFLOW, if the value will not fit in the destination
2927 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2929 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, float *pFltOut
)
2931 return _VarR4FromUI4(ulIn
, pFltOut
);
2934 /************************************************************************
2935 * VarR4FromDec (OLEAUT32.216)
2937 * Convert a VT_DECIMAL to a VT_R4.
2941 * pFltOut [O] Destination
2945 * Failure: E_INVALIDARG, if the source value is invalid.
2947 HRESULT WINAPI
VarR4FromDec(DECIMAL
* pDecIn
, float *pFltOut
)
2949 BYTE scale
= DEC_SCALE(pDecIn
);
2953 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
2954 return E_INVALIDARG
;
2959 if (DEC_SIGN(pDecIn
))
2962 if (DEC_HI32(pDecIn
))
2964 highPart
= (double)DEC_HI32(pDecIn
) / (double)divisor
;
2965 highPart
*= 4294967296.0F
;
2966 highPart
*= 4294967296.0F
;
2971 *pFltOut
= (double)DEC_LO64(pDecIn
) / (double)divisor
+ highPart
;
2975 /************************************************************************
2976 * VarR4FromI8 (OLEAUT32.360)
2978 * Convert a VT_I8 to a VT_R4.
2982 * pFltOut [O] Destination
2987 HRESULT WINAPI
VarR4FromI8(LONG64 llIn
, float *pFltOut
)
2989 return _VarR4FromI8(llIn
, pFltOut
);
2992 /************************************************************************
2993 * VarR4FromUI8 (OLEAUT32.361)
2995 * Convert a VT_UI8 to a VT_R4.
2999 * pFltOut [O] Destination
3004 HRESULT WINAPI
VarR4FromUI8(ULONG64 ullIn
, float *pFltOut
)
3006 return _VarR4FromUI8(ullIn
, pFltOut
);
3009 /************************************************************************
3010 * VarR4CmpR8 (OLEAUT32.316)
3012 * Compare a VT_R4 to a VT_R8.
3015 * fltLeft [I] Source
3016 * dblRight [I] Value to compare
3019 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
3020 * equal to or greater than dblRight respectively.
3022 HRESULT WINAPI
VarR4CmpR8(float fltLeft
, double dblRight
)
3024 if (fltLeft
< dblRight
)
3026 else if (fltLeft
> dblRight
)
3034 /************************************************************************
3035 * VarR8FromUI1 (OLEAUT32.78)
3037 * Convert a VT_UI1 to a VT_R8.
3041 * pDblOut [O] Destination
3046 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double *pDblOut
)
3048 return _VarR8FromUI1(bIn
, pDblOut
);
3051 /************************************************************************
3052 * VarR8FromI2 (OLEAUT32.79)
3054 * Convert a VT_I2 to a VT_R8.
3058 * pDblOut [O] Destination
3063 HRESULT WINAPI
VarR8FromI2(SHORT sIn
, double *pDblOut
)
3065 return _VarR8FromI2(sIn
, pDblOut
);
3068 /************************************************************************
3069 * VarR8FromI4 (OLEAUT32.80)
3071 * Convert a VT_I4 to a VT_R8.
3075 * pDblOut [O] Destination
3080 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double *pDblOut
)
3082 return _VarR8FromI4(lIn
, pDblOut
);
3085 /************************************************************************
3086 * VarR8FromR4 (OLEAUT32.81)
3088 * Convert a VT_R4 to a VT_R8.
3092 * pDblOut [O] Destination
3097 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double *pDblOut
)
3099 return _VarR8FromR4(fltIn
, pDblOut
);
3102 /************************************************************************
3103 * VarR8FromCy (OLEAUT32.82)
3105 * Convert a VT_CY to a VT_R8.
3109 * pDblOut [O] Destination
3114 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double *pDblOut
)
3116 return _VarR8FromCy(cyIn
, pDblOut
);
3119 /************************************************************************
3120 * VarR8FromDate (OLEAUT32.83)
3122 * Convert a VT_DATE to a VT_R8.
3126 * pDblOut [O] Destination
3131 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double *pDblOut
)
3133 return _VarR8FromDate(dateIn
, pDblOut
);
3136 /************************************************************************
3137 * VarR8FromStr (OLEAUT32.84)
3139 * Convert a VT_BSTR to a VT_R8.
3143 * lcid [I] LCID for the conversion
3144 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3145 * pDblOut [O] Destination
3149 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3150 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3152 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double *pDblOut
)
3154 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pDblOut
, VT_R8
);
3157 /************************************************************************
3158 * VarR8FromDisp (OLEAUT32.85)
3160 * Convert a VT_DISPATCH to a VT_R8.
3163 * pdispIn [I] Source
3164 * lcid [I] LCID for conversion
3165 * pDblOut [O] Destination
3169 * Failure: E_INVALIDARG, if the source value is invalid
3170 * DISP_E_OVERFLOW, if the value will not fit in the destination
3171 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3173 HRESULT WINAPI
VarR8FromDisp(IDispatch
* pdispIn
, LCID lcid
, double *pDblOut
)
3175 return VARIANT_FromDisp(pdispIn
, lcid
, pDblOut
, VT_R8
);
3178 /************************************************************************
3179 * VarR8FromBool (OLEAUT32.86)
3181 * Convert a VT_BOOL to a VT_R8.
3185 * pDblOut [O] Destination
3190 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double *pDblOut
)
3192 return VarR8FromI2(boolIn
, pDblOut
);
3195 /************************************************************************
3196 * VarR8FromI1 (OLEAUT32.217)
3198 * Convert a VT_I1 to a VT_R8.
3202 * pDblOut [O] Destination
3206 * Failure: E_INVALIDARG, if the source value is invalid
3207 * DISP_E_OVERFLOW, if the value will not fit in the destination
3208 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3210 HRESULT WINAPI
VarR8FromI1(signed char cIn
, double *pDblOut
)
3212 return _VarR8FromI1(cIn
, pDblOut
);
3215 /************************************************************************
3216 * VarR8FromUI2 (OLEAUT32.218)
3218 * Convert a VT_UI2 to a VT_R8.
3222 * pDblOut [O] Destination
3226 * Failure: E_INVALIDARG, if the source value is invalid
3227 * DISP_E_OVERFLOW, if the value will not fit in the destination
3228 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3230 HRESULT WINAPI
VarR8FromUI2(USHORT usIn
, double *pDblOut
)
3232 return _VarR8FromUI2(usIn
, pDblOut
);
3235 /************************************************************************
3236 * VarR8FromUI4 (OLEAUT32.219)
3238 * Convert a VT_UI4 to a VT_R8.
3242 * pDblOut [O] Destination
3246 * Failure: E_INVALIDARG, if the source value is invalid
3247 * DISP_E_OVERFLOW, if the value will not fit in the destination
3248 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3250 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double *pDblOut
)
3252 return _VarR8FromUI4(ulIn
, pDblOut
);
3255 /************************************************************************
3256 * VarR8FromDec (OLEAUT32.220)
3258 * Convert a VT_DECIMAL to a VT_R8.
3262 * pDblOut [O] Destination
3266 * Failure: E_INVALIDARG, if the source value is invalid.
3268 HRESULT WINAPI
VarR8FromDec(DECIMAL
* pDecIn
, double *pDblOut
)
3270 BYTE scale
= DEC_SCALE(pDecIn
);
3271 double divisor
= 1.0, highPart
;
3273 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
3274 return E_INVALIDARG
;
3279 if (DEC_SIGN(pDecIn
))
3282 if (DEC_HI32(pDecIn
))
3284 highPart
= (double)DEC_HI32(pDecIn
) / divisor
;
3285 highPart
*= 4294967296.0F
;
3286 highPart
*= 4294967296.0F
;
3291 *pDblOut
= (double)DEC_LO64(pDecIn
) / divisor
+ highPart
;
3295 /************************************************************************
3296 * VarR8FromI8 (OLEAUT32.362)
3298 * Convert a VT_I8 to a VT_R8.
3302 * pDblOut [O] Destination
3307 HRESULT WINAPI
VarR8FromI8(LONG64 llIn
, double *pDblOut
)
3309 return _VarR8FromI8(llIn
, pDblOut
);
3312 /************************************************************************
3313 * VarR8FromUI8 (OLEAUT32.363)
3315 * Convert a VT_UI8 to a VT_R8.
3319 * pDblOut [O] Destination
3324 HRESULT WINAPI
VarR8FromUI8(ULONG64 ullIn
, double *pDblOut
)
3326 return _VarR8FromUI8(ullIn
, pDblOut
);
3329 /************************************************************************
3330 * VarR8Pow (OLEAUT32.315)
3332 * Raise a VT_R8 to a power.
3335 * dblLeft [I] Source
3336 * dblPow [I] Power to raise dblLeft by
3337 * pDblOut [O] Destination
3340 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3342 HRESULT WINAPI
VarR8Pow(double dblLeft
, double dblPow
, double *pDblOut
)
3344 *pDblOut
= pow(dblLeft
, dblPow
);
3348 /************************************************************************
3349 * VarR8Round (OLEAUT32.317)
3351 * Round a VT_R8 to a given number of decimal points.
3355 * nDig [I] Number of decimal points to round to
3356 * pDblOut [O] Destination for rounded number
3359 * Success: S_OK. pDblOut is rounded to nDig digits.
3360 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3363 * The native version of this function rounds using the internal
3364 * binary representation of the number. Wine uses the dutch rounding
3365 * convention, so therefore small differences can occur in the value returned.
3366 * MSDN says that you should use your own rounding function if you want
3367 * rounding to be predictable in your application.
3369 HRESULT WINAPI
VarR8Round(double dblIn
, int nDig
, double *pDblOut
)
3371 double scale
, whole
, fract
;
3374 return E_INVALIDARG
;
3376 scale
= pow(10.0, nDig
);
3379 whole
= dblIn
< 0 ? ceil(dblIn
) : floor(dblIn
);
3380 fract
= dblIn
- whole
;
3383 dblIn
= whole
+ 1.0;
3384 else if (fract
== 0.5)
3385 dblIn
= whole
+ fmod(whole
, 2.0);
3386 else if (fract
>= 0.0)
3388 else if (fract
== -0.5)
3389 dblIn
= whole
- fmod(whole
, 2.0);
3390 else if (fract
> -0.5)
3393 dblIn
= whole
- 1.0;
3395 *pDblOut
= dblIn
/ scale
;
3402 /* Powers of 10 from 0..4 D.P. */
3403 static const int CY_Divisors
[5] = { CY_MULTIPLIER
/10000, CY_MULTIPLIER
/1000,
3404 CY_MULTIPLIER
/100, CY_MULTIPLIER
/10, CY_MULTIPLIER
};
3406 /************************************************************************
3407 * VarCyFromUI1 (OLEAUT32.98)
3409 * Convert a VT_UI1 to a VT_CY.
3413 * pCyOut [O] Destination
3417 * Failure: E_INVALIDARG, if the source value is invalid
3418 * DISP_E_OVERFLOW, if the value will not fit in the destination
3419 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3421 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pCyOut
)
3423 return VarCyFromR8(bIn
, pCyOut
);
3426 /************************************************************************
3427 * VarCyFromI2 (OLEAUT32.99)
3429 * Convert a VT_I2 to a VT_CY.
3433 * pCyOut [O] Destination
3437 * Failure: E_INVALIDARG, if the source value is invalid
3438 * DISP_E_OVERFLOW, if the value will not fit in the destination
3439 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3441 HRESULT WINAPI
VarCyFromI2(SHORT sIn
, CY
* pCyOut
)
3443 return VarCyFromR8(sIn
, pCyOut
);
3446 /************************************************************************
3447 * VarCyFromI4 (OLEAUT32.100)
3449 * Convert a VT_I4 to a VT_CY.
3453 * pCyOut [O] Destination
3457 * Failure: E_INVALIDARG, if the source value is invalid
3458 * DISP_E_OVERFLOW, if the value will not fit in the destination
3459 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3461 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pCyOut
)
3463 return VarCyFromR8(lIn
, pCyOut
);
3466 /************************************************************************
3467 * VarCyFromR4 (OLEAUT32.101)
3469 * Convert a VT_R4 to a VT_CY.
3473 * pCyOut [O] Destination
3477 * Failure: E_INVALIDARG, if the source value is invalid
3478 * DISP_E_OVERFLOW, if the value will not fit in the destination
3479 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3481 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pCyOut
)
3483 return VarCyFromR8(fltIn
, pCyOut
);
3486 /************************************************************************
3487 * VarCyFromR8 (OLEAUT32.102)
3489 * Convert a VT_R8 to a VT_CY.
3493 * pCyOut [O] Destination
3497 * Failure: E_INVALIDARG, if the source value is invalid
3498 * DISP_E_OVERFLOW, if the value will not fit in the destination
3499 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3501 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pCyOut
)
3503 #if defined(__GNUC__) && defined(__i386__)
3504 /* This code gives identical results to Win32 on Intel.
3505 * Here we use fp exceptions to catch overflows when storing the value.
3507 static const unsigned short r8_fpcontrol
= 0x137f;
3508 static const double r8_multiplier
= CY_MULTIPLIER_F
;
3509 unsigned short old_fpcontrol
, result_fpstatus
;
3511 /* Clear exceptions, save the old fp state and load the new state */
3512 __asm__
__volatile__( "fnclex" );
3513 __asm__
__volatile__( "fstcw %0" : "=m" (old_fpcontrol
) : );
3514 __asm__
__volatile__( "fldcw %0" : : "m" (r8_fpcontrol
) );
3515 /* Perform the conversion. */
3516 __asm__
__volatile__( "fldl %0" : : "m" (dblIn
) );
3517 __asm__
__volatile__( "fmull %0" : : "m" (r8_multiplier
) );
3518 __asm__
__volatile__( "fistpll %0" : : "m" (*pCyOut
) );
3519 /* Save the resulting fp state, load the old state and clear exceptions */
3520 __asm__
__volatile__( "fstsw %0" : "=m" (result_fpstatus
) : );
3521 __asm__
__volatile__( "fnclex" );
3522 __asm__
__volatile__( "fldcw %0" : : "m" (old_fpcontrol
) );
3524 if (result_fpstatus
& 0x9) /* Overflow | Invalid */
3525 return DISP_E_OVERFLOW
;
3528 /* This version produces slightly different results for boundary cases */
3529 if (dblIn
< -922337203685477.5807 || dblIn
>= 922337203685477.5807)
3530 return DISP_E_OVERFLOW
;
3531 dblIn
*= CY_MULTIPLIER_F
;
3532 VARIANT_DutchRound(LONG64
, dblIn
, pCyOut
->int64
);
3537 /************************************************************************
3538 * VarCyFromDate (OLEAUT32.103)
3540 * Convert a VT_DATE to a VT_CY.
3544 * pCyOut [O] Destination
3548 * Failure: E_INVALIDARG, if the source value is invalid
3549 * DISP_E_OVERFLOW, if the value will not fit in the destination
3550 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3552 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pCyOut
)
3554 return VarCyFromR8(dateIn
, pCyOut
);
3557 /************************************************************************
3558 * VarCyFromStr (OLEAUT32.104)
3560 * Convert a VT_BSTR to a VT_CY.
3564 * lcid [I] LCID for the conversion
3565 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3566 * pCyOut [O] Destination
3570 * Failure: E_INVALIDARG, if the source value is invalid
3571 * DISP_E_OVERFLOW, if the value will not fit in the destination
3572 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3574 HRESULT WINAPI
VarCyFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CY
* pCyOut
)
3576 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pCyOut
, VT_CY
);
3579 /************************************************************************
3580 * VarCyFromDisp (OLEAUT32.105)
3582 * Convert a VT_DISPATCH to a VT_CY.
3585 * pdispIn [I] Source
3586 * lcid [I] LCID for conversion
3587 * pCyOut [O] Destination
3591 * Failure: E_INVALIDARG, if the source value is invalid
3592 * DISP_E_OVERFLOW, if the value will not fit in the destination
3593 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3595 HRESULT WINAPI
VarCyFromDisp(IDispatch
* pdispIn
, LCID lcid
, CY
* pCyOut
)
3597 return VARIANT_FromDisp(pdispIn
, lcid
, pCyOut
, VT_CY
);
3600 /************************************************************************
3601 * VarCyFromBool (OLEAUT32.106)
3603 * Convert a VT_BOOL to a VT_CY.
3607 * pCyOut [O] Destination
3611 * Failure: E_INVALIDARG, if the source value is invalid
3612 * DISP_E_OVERFLOW, if the value will not fit in the destination
3613 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3616 * While the sign of the boolean is stored in the currency, the value is
3617 * converted to either 0 or 1.
3619 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pCyOut
)
3621 return VarCyFromR8(boolIn
, pCyOut
);
3624 /************************************************************************
3625 * VarCyFromI1 (OLEAUT32.225)
3627 * Convert a VT_I1 to a VT_CY.
3631 * pCyOut [O] Destination
3635 * Failure: E_INVALIDARG, if the source value is invalid
3636 * DISP_E_OVERFLOW, if the value will not fit in the destination
3637 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3639 HRESULT WINAPI
VarCyFromI1(signed char cIn
, CY
* pCyOut
)
3641 return VarCyFromR8(cIn
, pCyOut
);
3644 /************************************************************************
3645 * VarCyFromUI2 (OLEAUT32.226)
3647 * Convert a VT_UI2 to a VT_CY.
3651 * pCyOut [O] Destination
3655 * Failure: E_INVALIDARG, if the source value is invalid
3656 * DISP_E_OVERFLOW, if the value will not fit in the destination
3657 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3659 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pCyOut
)
3661 return VarCyFromR8(usIn
, pCyOut
);
3664 /************************************************************************
3665 * VarCyFromUI4 (OLEAUT32.227)
3667 * Convert a VT_UI4 to a VT_CY.
3671 * pCyOut [O] Destination
3675 * Failure: E_INVALIDARG, if the source value is invalid
3676 * DISP_E_OVERFLOW, if the value will not fit in the destination
3677 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3679 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pCyOut
)
3681 return VarCyFromR8(ulIn
, pCyOut
);
3684 /************************************************************************
3685 * VarCyFromDec (OLEAUT32.228)
3687 * Convert a VT_DECIMAL to a VT_CY.
3691 * pCyOut [O] Destination
3695 * Failure: E_INVALIDARG, if the source value is invalid
3696 * DISP_E_OVERFLOW, if the value will not fit in the destination
3697 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3699 HRESULT WINAPI
VarCyFromDec(DECIMAL
* pdecIn
, CY
* pCyOut
)
3704 hRet
= VarDecRound(pdecIn
, 4, &rounded
);
3706 if (SUCCEEDED(hRet
))
3710 if (DEC_HI32(&rounded
))
3711 return DISP_E_OVERFLOW
;
3713 /* Note: Without the casts this promotes to int64 which loses precision */
3714 d
= (double)DEC_LO64(&rounded
) / (double)CY_Divisors
[DEC_SCALE(&rounded
)];
3715 if (DEC_SIGN(&rounded
))
3717 return VarCyFromR8(d
, pCyOut
);
3722 /************************************************************************
3723 * VarCyFromI8 (OLEAUT32.366)
3725 * Convert a VT_I8 to a VT_CY.
3729 * pCyOut [O] Destination
3733 * Failure: E_INVALIDARG, if the source value is invalid
3734 * DISP_E_OVERFLOW, if the value will not fit in the destination
3735 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3737 HRESULT WINAPI
VarCyFromI8(LONG64 llIn
, CY
* pCyOut
)
3739 if (llIn
<= (I8_MIN
/CY_MULTIPLIER
) || llIn
>= (I8_MAX
/CY_MULTIPLIER
)) return DISP_E_OVERFLOW
;
3740 pCyOut
->int64
= llIn
* CY_MULTIPLIER
;
3744 /************************************************************************
3745 * VarCyFromUI8 (OLEAUT32.375)
3747 * Convert a VT_UI8 to a VT_CY.
3751 * pCyOut [O] Destination
3755 * Failure: E_INVALIDARG, if the source value is invalid
3756 * DISP_E_OVERFLOW, if the value will not fit in the destination
3757 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3759 HRESULT WINAPI
VarCyFromUI8(ULONG64 ullIn
, CY
* pCyOut
)
3761 return VarCyFromR8(ullIn
, pCyOut
);
3764 /************************************************************************
3765 * VarCyAdd (OLEAUT32.299)
3767 * Add one CY to another.
3771 * cyRight [I] Value to add
3772 * pCyOut [O] Destination
3776 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3778 HRESULT WINAPI
VarCyAdd(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3781 _VarR8FromCy(cyLeft
, &l
);
3782 _VarR8FromCy(cyRight
, &r
);
3784 return VarCyFromR8(l
, pCyOut
);
3787 /************************************************************************
3788 * VarCyMul (OLEAUT32.303)
3790 * Multiply one CY by another.
3794 * cyRight [I] Value to multiply by
3795 * pCyOut [O] Destination
3799 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3801 HRESULT WINAPI
VarCyMul(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3804 _VarR8FromCy(cyLeft
, &l
);
3805 _VarR8FromCy(cyRight
, &r
);
3807 return VarCyFromR8(l
, pCyOut
);
3810 /************************************************************************
3811 * VarCyMulI4 (OLEAUT32.304)
3813 * Multiply one CY by a VT_I4.
3817 * lRight [I] Value to multiply by
3818 * pCyOut [O] Destination
3822 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3824 HRESULT WINAPI
VarCyMulI4(const CY cyLeft
, LONG lRight
, CY
* pCyOut
)
3828 _VarR8FromCy(cyLeft
, &d
);
3830 return VarCyFromR8(d
, pCyOut
);
3833 /************************************************************************
3834 * VarCySub (OLEAUT32.305)
3836 * Subtract one CY from another.
3840 * cyRight [I] Value to subtract
3841 * pCyOut [O] Destination
3845 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3847 HRESULT WINAPI
VarCySub(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3850 _VarR8FromCy(cyLeft
, &l
);
3851 _VarR8FromCy(cyRight
, &r
);
3853 return VarCyFromR8(l
, pCyOut
);
3856 /************************************************************************
3857 * VarCyAbs (OLEAUT32.306)
3859 * Convert a VT_CY into its absolute value.
3863 * pCyOut [O] Destination
3866 * Success: S_OK. pCyOut contains the absolute value.
3867 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3869 HRESULT WINAPI
VarCyAbs(const CY cyIn
, CY
* pCyOut
)
3871 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3872 return DISP_E_OVERFLOW
;
3874 pCyOut
->int64
= cyIn
.int64
< 0 ? -cyIn
.int64
: cyIn
.int64
;
3878 /************************************************************************
3879 * VarCyFix (OLEAUT32.307)
3881 * Return the integer part of a VT_CY.
3885 * pCyOut [O] Destination
3889 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3892 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3893 * negative numbers away from 0, while this function rounds them towards zero.
3895 HRESULT WINAPI
VarCyFix(const CY cyIn
, CY
* pCyOut
)
3897 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3898 pCyOut
->int64
*= CY_MULTIPLIER
;
3902 /************************************************************************
3903 * VarCyInt (OLEAUT32.308)
3905 * Return the integer part of a VT_CY.
3909 * pCyOut [O] Destination
3913 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3916 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3917 * negative numbers towards 0, while this function rounds them away from zero.
3919 HRESULT WINAPI
VarCyInt(const CY cyIn
, CY
* pCyOut
)
3921 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3922 pCyOut
->int64
*= CY_MULTIPLIER
;
3924 if (cyIn
.int64
< 0 && cyIn
.int64
% CY_MULTIPLIER
!= 0)
3926 pCyOut
->int64
-= CY_MULTIPLIER
;
3931 /************************************************************************
3932 * VarCyNeg (OLEAUT32.309)
3934 * Change the sign of a VT_CY.
3938 * pCyOut [O] Destination
3942 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3944 HRESULT WINAPI
VarCyNeg(const CY cyIn
, CY
* pCyOut
)
3946 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3947 return DISP_E_OVERFLOW
;
3949 pCyOut
->int64
= -cyIn
.int64
;
3953 /************************************************************************
3954 * VarCyRound (OLEAUT32.310)
3956 * Change the precision of a VT_CY.
3960 * cDecimals [I] New number of decimals to keep
3961 * pCyOut [O] Destination
3965 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3967 HRESULT WINAPI
VarCyRound(const CY cyIn
, int cDecimals
, CY
* pCyOut
)
3970 return E_INVALIDARG
;
3974 /* Rounding to more precision than we have */
3980 double d
, div
= CY_Divisors
[cDecimals
];
3982 _VarR8FromCy(cyIn
, &d
);
3984 VARIANT_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3985 d
= (double)pCyOut
->int64
/ div
* CY_MULTIPLIER_F
;
3986 VARIANT_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3991 /************************************************************************
3992 * VarCyCmp (OLEAUT32.311)
3994 * Compare two VT_CY values.
3998 * cyRight [I] Value to compare
4001 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
4002 * compare is less, equal or greater than source respectively.
4003 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4005 HRESULT WINAPI
VarCyCmp(const CY cyLeft
, const CY cyRight
)
4010 /* Subtract right from left, and compare the result to 0 */
4011 hRet
= VarCySub(cyLeft
, cyRight
, &result
);
4013 if (SUCCEEDED(hRet
))
4015 if (result
.int64
< 0)
4016 hRet
= (HRESULT
)VARCMP_LT
;
4017 else if (result
.int64
> 0)
4018 hRet
= (HRESULT
)VARCMP_GT
;
4020 hRet
= (HRESULT
)VARCMP_EQ
;
4025 /************************************************************************
4026 * VarCyCmpR8 (OLEAUT32.312)
4028 * Compare a VT_CY to a double
4031 * cyLeft [I] Currency Source
4032 * dblRight [I] double to compare to cyLeft
4035 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
4036 * less than, equal to or greater than cyLeft respectively.
4037 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4039 HRESULT WINAPI
VarCyCmpR8(const CY cyLeft
, double dblRight
)
4044 hRet
= VarCyFromR8(dblRight
, &cyRight
);
4046 if (SUCCEEDED(hRet
))
4047 hRet
= VarCyCmp(cyLeft
, cyRight
);
4052 /************************************************************************
4053 * VarCyMulI8 (OLEAUT32.329)
4055 * Multiply a VT_CY by a VT_I8.
4059 * llRight [I] Value to multiply by
4060 * pCyOut [O] Destination
4064 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4066 HRESULT WINAPI
VarCyMulI8(const CY cyLeft
, LONG64 llRight
, CY
* pCyOut
)
4070 _VarR8FromCy(cyLeft
, &d
);
4071 d
= d
* (double)llRight
;
4072 return VarCyFromR8(d
, pCyOut
);
4078 /************************************************************************
4079 * VarDecFromUI1 (OLEAUT32.190)
4081 * Convert a VT_UI1 to a DECIMAL.
4085 * pDecOut [O] Destination
4090 HRESULT WINAPI
VarDecFromUI1(BYTE bIn
, DECIMAL
* pDecOut
)
4092 return VarDecFromUI4(bIn
, pDecOut
);
4095 /************************************************************************
4096 * VarDecFromI2 (OLEAUT32.191)
4098 * Convert a VT_I2 to a DECIMAL.
4102 * pDecOut [O] Destination
4107 HRESULT WINAPI
VarDecFromI2(SHORT sIn
, DECIMAL
* pDecOut
)
4109 return VarDecFromI4(sIn
, pDecOut
);
4112 /************************************************************************
4113 * VarDecFromI4 (OLEAUT32.192)
4115 * Convert a VT_I4 to a DECIMAL.
4119 * pDecOut [O] Destination
4124 HRESULT WINAPI
VarDecFromI4(LONG lIn
, DECIMAL
* pDecOut
)
4126 DEC_HI32(pDecOut
) = 0;
4127 DEC_MID32(pDecOut
) = 0;
4131 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4132 DEC_LO32(pDecOut
) = -lIn
;
4136 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4137 DEC_LO32(pDecOut
) = lIn
;
4142 #define LOCALE_EN_US (MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT))
4144 /************************************************************************
4145 * VarDecFromR4 (OLEAUT32.193)
4147 * Convert a VT_R4 to a DECIMAL.
4151 * pDecOut [O] Destination
4156 HRESULT WINAPI
VarDecFromR4(FLOAT fltIn
, DECIMAL
* pDecOut
)
4160 sprintfW( buff
, szFloatFormatW
, fltIn
);
4161 return VarDecFromStr(buff
, LOCALE_EN_US
, 0, pDecOut
);
4164 /************************************************************************
4165 * VarDecFromR8 (OLEAUT32.194)
4167 * Convert a VT_R8 to a DECIMAL.
4171 * pDecOut [O] Destination
4176 HRESULT WINAPI
VarDecFromR8(double dblIn
, DECIMAL
* pDecOut
)
4180 sprintfW( buff
, szDoubleFormatW
, dblIn
);
4181 return VarDecFromStr(buff
, LOCALE_EN_US
, 0, pDecOut
);
4184 /************************************************************************
4185 * VarDecFromDate (OLEAUT32.195)
4187 * Convert a VT_DATE to a DECIMAL.
4191 * pDecOut [O] Destination
4196 HRESULT WINAPI
VarDecFromDate(DATE dateIn
, DECIMAL
* pDecOut
)
4198 return VarDecFromR8(dateIn
, pDecOut
);
4201 /************************************************************************
4202 * VarDecFromCy (OLEAUT32.196)
4204 * Convert a VT_CY to a DECIMAL.
4208 * pDecOut [O] Destination
4213 HRESULT WINAPI
VarDecFromCy(CY cyIn
, DECIMAL
* pDecOut
)
4215 DEC_HI32(pDecOut
) = 0;
4217 /* Note: This assumes 2s complement integer representation */
4218 if (cyIn
.s
.Hi
& 0x80000000)
4220 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,4);
4221 DEC_LO64(pDecOut
) = -cyIn
.int64
;
4225 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,4);
4226 DEC_MID32(pDecOut
) = cyIn
.s
.Hi
;
4227 DEC_LO32(pDecOut
) = cyIn
.s
.Lo
;
4232 /************************************************************************
4233 * VarDecFromStr (OLEAUT32.197)
4235 * Convert a VT_BSTR to a DECIMAL.
4239 * lcid [I] LCID for the conversion
4240 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4241 * pDecOut [O] Destination
4245 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4247 HRESULT WINAPI
VarDecFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DECIMAL
* pDecOut
)
4249 return VARIANT_NumberFromBstr(strIn
, lcid
, dwFlags
, pDecOut
, VT_DECIMAL
);
4252 /************************************************************************
4253 * VarDecFromDisp (OLEAUT32.198)
4255 * Convert a VT_DISPATCH to a DECIMAL.
4258 * pdispIn [I] Source
4259 * lcid [I] LCID for conversion
4260 * pDecOut [O] Destination
4264 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4266 HRESULT WINAPI
VarDecFromDisp(IDispatch
* pdispIn
, LCID lcid
, DECIMAL
* pDecOut
)
4268 return VARIANT_FromDisp(pdispIn
, lcid
, pDecOut
, VT_DECIMAL
);
4271 /************************************************************************
4272 * VarDecFromBool (OLEAUT32.199)
4274 * Convert a VT_BOOL to a DECIMAL.
4278 * pDecOut [O] Destination
4284 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4286 HRESULT WINAPI
VarDecFromBool(VARIANT_BOOL bIn
, DECIMAL
* pDecOut
)
4288 DEC_HI32(pDecOut
) = 0;
4289 DEC_MID32(pDecOut
) = 0;
4292 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4293 DEC_LO32(pDecOut
) = 1;
4297 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4298 DEC_LO32(pDecOut
) = 0;
4303 /************************************************************************
4304 * VarDecFromI1 (OLEAUT32.241)
4306 * Convert a VT_I1 to a DECIMAL.
4310 * pDecOut [O] Destination
4315 HRESULT WINAPI
VarDecFromI1(signed char cIn
, DECIMAL
* pDecOut
)
4317 return VarDecFromI4(cIn
, pDecOut
);
4320 /************************************************************************
4321 * VarDecFromUI2 (OLEAUT32.242)
4323 * Convert a VT_UI2 to a DECIMAL.
4327 * pDecOut [O] Destination
4332 HRESULT WINAPI
VarDecFromUI2(USHORT usIn
, DECIMAL
* pDecOut
)
4334 return VarDecFromUI4(usIn
, pDecOut
);
4337 /************************************************************************
4338 * VarDecFromUI4 (OLEAUT32.243)
4340 * Convert a VT_UI4 to a DECIMAL.
4344 * pDecOut [O] Destination
4349 HRESULT WINAPI
VarDecFromUI4(ULONG ulIn
, DECIMAL
* pDecOut
)
4351 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4352 DEC_HI32(pDecOut
) = 0;
4353 DEC_MID32(pDecOut
) = 0;
4354 DEC_LO32(pDecOut
) = ulIn
;
4358 /************************************************************************
4359 * VarDecFromI8 (OLEAUT32.374)
4361 * Convert a VT_I8 to a DECIMAL.
4365 * pDecOut [O] Destination
4370 HRESULT WINAPI
VarDecFromI8(LONG64 llIn
, DECIMAL
* pDecOut
)
4372 PULARGE_INTEGER pLi
= (PULARGE_INTEGER
)&llIn
;
4374 DEC_HI32(pDecOut
) = 0;
4376 /* Note: This assumes 2s complement integer representation */
4377 if (pLi
->u
.HighPart
& 0x80000000)
4379 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4380 DEC_LO64(pDecOut
) = -pLi
->QuadPart
;
4384 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4385 DEC_MID32(pDecOut
) = pLi
->u
.HighPart
;
4386 DEC_LO32(pDecOut
) = pLi
->u
.LowPart
;
4391 /************************************************************************
4392 * VarDecFromUI8 (OLEAUT32.375)
4394 * Convert a VT_UI8 to a DECIMAL.
4398 * pDecOut [O] Destination
4403 HRESULT WINAPI
VarDecFromUI8(ULONG64 ullIn
, DECIMAL
* pDecOut
)
4405 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4406 DEC_HI32(pDecOut
) = 0;
4407 DEC_LO64(pDecOut
) = ullIn
;
4411 /* Make two DECIMALS the same scale; used by math functions below */
4412 static HRESULT
VARIANT_DecScale(const DECIMAL
** ppDecLeft
,
4413 const DECIMAL
** ppDecRight
,
4416 static DECIMAL scaleFactor
;
4419 HRESULT hRet
= S_OK
;
4421 if (DEC_SIGN(*ppDecLeft
) & ~DECIMAL_NEG
|| DEC_SIGN(*ppDecRight
) & ~DECIMAL_NEG
)
4422 return E_INVALIDARG
;
4424 DEC_LO32(&scaleFactor
) = 10;
4426 i
= scaleAmount
= DEC_SCALE(*ppDecLeft
) - DEC_SCALE(*ppDecRight
);
4429 return S_OK
; /* Same scale */
4431 if (scaleAmount
> 0)
4433 decTemp
= *(*ppDecRight
); /* Left is bigger - scale the right hand side */
4434 *ppDecRight
= pDecOut
;
4438 decTemp
= *(*ppDecLeft
); /* Right is bigger - scale the left hand side */
4439 *ppDecLeft
= pDecOut
;
4440 i
= scaleAmount
= -scaleAmount
;
4443 if (DEC_SCALE(&decTemp
) + scaleAmount
> DEC_MAX_SCALE
)
4444 return DISP_E_OVERFLOW
; /* Can't scale up */
4446 /* Multiply up the value to be scaled by the correct amount */
4447 while (SUCCEEDED(hRet
) && i
--)
4449 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4450 hRet
= VarDecMul(&decTemp
, &scaleFactor
, pDecOut
);
4453 DEC_SCALE(pDecOut
) += scaleAmount
; /* Set the new scale */
4457 /* Add two unsigned 32 bit values with overflow */
4458 static ULONG
VARIANT_Add(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4460 ULARGE_INTEGER ul64
;
4462 ul64
.QuadPart
= (ULONG64
)ulLeft
+ (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4463 *pulHigh
= ul64
.u
.HighPart
;
4464 return ul64
.u
.LowPart
;
4467 /* Subtract two unsigned 32 bit values with underflow */
4468 static ULONG
VARIANT_Sub(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4471 ULARGE_INTEGER ul64
;
4473 ul64
.QuadPart
= (LONG64
)ulLeft
- (ULONG64
)ulRight
;
4474 if (ulLeft
< ulRight
)
4477 if (ul64
.QuadPart
> (ULONG64
)*pulHigh
)
4478 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4481 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4485 ul64
.u
.HighPart
= -ul64
.u
.HighPart
;
4487 *pulHigh
= ul64
.u
.HighPart
;
4488 return ul64
.u
.LowPart
;
4491 /* Multiply two unsigned 32 bit values with overflow */
4492 static ULONG
VARIANT_Mul(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4494 ULARGE_INTEGER ul64
;
4496 ul64
.QuadPart
= (ULONG64
)ulLeft
* (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4497 *pulHigh
= ul64
.u
.HighPart
;
4498 return ul64
.u
.LowPart
;
4501 /* Compare two decimals that have the same scale */
4502 static inline int VARIANT_DecCmp(const DECIMAL
*pDecLeft
, const DECIMAL
*pDecRight
)
4504 if ( DEC_HI32(pDecLeft
) < DEC_HI32(pDecRight
) ||
4505 (DEC_HI32(pDecLeft
) <= DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) < DEC_LO64(pDecRight
)))
4507 else if (DEC_HI32(pDecLeft
) == DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) == DEC_LO64(pDecRight
))
4512 /************************************************************************
4513 * VarDecAdd (OLEAUT32.177)
4515 * Add one DECIMAL to another.
4518 * pDecLeft [I] Source
4519 * pDecRight [I] Value to add
4520 * pDecOut [O] Destination
4524 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4526 HRESULT WINAPI
VarDecAdd(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4531 hRet
= VARIANT_DecScale(&pDecLeft
, &pDecRight
, &scaled
);
4533 if (SUCCEEDED(hRet
))
4535 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4537 BYTE sign
= DECIMAL_POS
;
4539 /* Correct for the sign of the result */
4540 if (DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4542 /* -x + -y : Negative */
4544 goto VarDecAdd_AsPositive
;
4546 else if (DEC_SIGN(pDecLeft
) && !DEC_SIGN(pDecRight
))
4548 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4550 /* -x + y : Negative if x > y */
4554 VarDecAdd_AsNegative
:
4555 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4556 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4557 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4561 VarDecAdd_AsInvertedNegative
:
4562 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecRight
), DEC_LO32(pDecLeft
), &overflow
);
4563 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecRight
), DEC_MID32(pDecLeft
), &overflow
);
4564 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecRight
), DEC_HI32(pDecLeft
), &overflow
);
4567 else if (!DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4569 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4571 /* x + -y : Negative if x <= y */
4575 goto VarDecAdd_AsInvertedNegative
;
4577 goto VarDecAdd_AsNegative
;
4581 /* x + y : Positive */
4582 VarDecAdd_AsPositive
:
4583 DEC_LO32(pDecOut
) = VARIANT_Add(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4584 DEC_MID32(pDecOut
) = VARIANT_Add(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4585 DEC_HI32(pDecOut
) = VARIANT_Add(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4589 return DISP_E_OVERFLOW
; /* overflowed */
4591 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecLeft
);
4592 DEC_SIGN(pDecOut
) = sign
;
4597 /************************************************************************
4598 * VarDecDiv (OLEAUT32.178)
4600 * Divide one DECIMAL by another.
4603 * pDecLeft [I] Source
4604 * pDecRight [I] Value to divide by
4605 * pDecOut [O] Destination
4609 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4611 HRESULT WINAPI
VarDecDiv(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4613 FIXME("(%p,%p,%p)-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4614 return DISP_E_OVERFLOW
;
4617 /************************************************************************
4618 * VarDecMul (OLEAUT32.179)
4620 * Multiply one DECIMAL by another.
4623 * pDecLeft [I] Source
4624 * pDecRight [I] Value to multiply by
4625 * pDecOut [O] Destination
4629 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4631 HRESULT WINAPI
VarDecMul(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4633 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4635 if (!DEC_SCALE(pDecLeft
) || !DEC_SCALE(pDecRight
))
4637 /* At least one term is an integer */
4638 const DECIMAL
* pDecInteger
= DEC_SCALE(pDecLeft
) ? pDecRight
: pDecLeft
;
4639 const DECIMAL
* pDecOperand
= DEC_SCALE(pDecLeft
) ? pDecLeft
: pDecRight
;
4640 HRESULT hRet
= S_OK
;
4641 unsigned int multiplier
= DEC_LO32(pDecInteger
);
4644 if (DEC_HI32(pDecInteger
) || DEC_MID32(pDecInteger
))
4646 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4647 return DISP_E_OVERFLOW
;
4650 DEC_LO32(pDecOut
) = VARIANT_Mul(DEC_LO32(pDecOperand
), multiplier
, &overflow
);
4651 DEC_MID32(pDecOut
) = VARIANT_Mul(DEC_MID32(pDecOperand
), multiplier
, &overflow
);
4652 DEC_HI32(pDecOut
) = VARIANT_Mul(DEC_HI32(pDecOperand
), multiplier
, &overflow
);
4655 hRet
= DISP_E_OVERFLOW
;
4658 BYTE sign
= DECIMAL_POS
;
4660 if (DEC_SIGN(pDecLeft
) != DEC_SIGN(pDecRight
))
4661 sign
= DECIMAL_NEG
; /* pos * neg => negative */
4662 DEC_SIGN(pDecOut
) = sign
;
4663 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecOperand
);
4667 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4668 return DISP_E_OVERFLOW
;
4671 /************************************************************************
4672 * VarDecSub (OLEAUT32.181)
4674 * Subtract one DECIMAL from another.
4677 * pDecLeft [I] Source
4678 * pDecRight [I] DECIMAL to subtract from pDecLeft
4679 * pDecOut [O] Destination
4682 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4684 HRESULT WINAPI
VarDecSub(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4688 /* Implement as addition of the negative */
4689 VarDecNeg(pDecRight
, &decRight
);
4690 return VarDecAdd(pDecLeft
, &decRight
, pDecOut
);
4693 /************************************************************************
4694 * VarDecAbs (OLEAUT32.182)
4696 * Convert a DECIMAL into its absolute value.
4700 * pDecOut [O] Destination
4703 * S_OK. This function does not fail.
4705 HRESULT WINAPI
VarDecAbs(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4708 DEC_SIGN(pDecOut
) &= ~DECIMAL_NEG
;
4712 /************************************************************************
4713 * VarDecFix (OLEAUT32.187)
4715 * Return the integer portion of a DECIMAL.
4719 * pDecOut [O] Destination
4723 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4726 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4727 * negative numbers away from 0, while this function rounds them towards zero.
4729 HRESULT WINAPI
VarDecFix(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4731 if (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
4732 return E_INVALIDARG
;
4734 if (!DEC_SCALE(pDecIn
))
4736 *pDecOut
= *pDecIn
; /* Already an integer */
4740 FIXME("semi-stub!\n");
4741 return DISP_E_OVERFLOW
;
4744 /************************************************************************
4745 * VarDecInt (OLEAUT32.188)
4747 * Return the integer portion of a DECIMAL.
4751 * pDecOut [O] Destination
4755 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4758 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4759 * negative numbers towards 0, while this function rounds them away from zero.
4761 HRESULT WINAPI
VarDecInt(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4763 if (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
4764 return E_INVALIDARG
;
4766 if (!(DEC_SIGN(pDecIn
) & DECIMAL_NEG
) || !DEC_SCALE(pDecIn
))
4767 return VarDecFix(pDecIn
, pDecOut
); /* The same, if +ve or no fractionals */
4769 FIXME("semi-stub!\n");
4770 return DISP_E_OVERFLOW
;
4773 /************************************************************************
4774 * VarDecNeg (OLEAUT32.189)
4776 * Change the sign of a DECIMAL.
4780 * pDecOut [O] Destination
4783 * S_OK. This function does not fail.
4785 HRESULT WINAPI
VarDecNeg(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4788 DEC_SIGN(pDecOut
) ^= DECIMAL_NEG
;
4792 /************************************************************************
4793 * VarDecRound (OLEAUT32.203)
4795 * Change the precision of a DECIMAL.
4799 * cDecimals [I] New number of decimals to keep
4800 * pDecOut [O] Destination
4803 * Success: S_OK. pDecOut contains the rounded value.
4804 * Failure: E_INVALIDARG if any argument is invalid.
4806 HRESULT WINAPI
VarDecRound(const DECIMAL
* pDecIn
, int cDecimals
, DECIMAL
* pDecOut
)
4808 if (cDecimals
< 0 || (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
) || DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
)
4809 return E_INVALIDARG
;
4811 if (cDecimals
>= DEC_SCALE(pDecIn
))
4813 *pDecOut
= *pDecIn
; /* More precision than we have */
4817 FIXME("semi-stub!\n");
4819 return DISP_E_OVERFLOW
;
4822 /************************************************************************
4823 * VarDecCmp (OLEAUT32.204)
4825 * Compare two DECIMAL values.
4828 * pDecLeft [I] Source
4829 * pDecRight [I] Value to compare
4832 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4833 * is less than, equal to or greater than pDecRight respectively.
4834 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4836 HRESULT WINAPI
VarDecCmp(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
)
4841 /* Subtract right from left, and compare the result to 0 */
4842 hRet
= VarDecSub(pDecLeft
, pDecRight
, &result
);
4844 if (SUCCEEDED(hRet
))
4846 int non_zero
= DEC_HI32(&result
) | DEC_MID32(&result
) | DEC_LO32(&result
);
4848 if ((DEC_SIGN(&result
) & DECIMAL_NEG
) && non_zero
)
4849 hRet
= (HRESULT
)VARCMP_LT
;
4851 hRet
= (HRESULT
)VARCMP_GT
;
4853 hRet
= (HRESULT
)VARCMP_EQ
;
4858 /************************************************************************
4859 * VarDecCmpR8 (OLEAUT32.298)
4861 * Compare a DECIMAL to a double
4864 * pDecLeft [I] DECIMAL Source
4865 * dblRight [I] double to compare to pDecLeft
4868 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4869 * is less than, equal to or greater than pDecLeft respectively.
4870 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4872 HRESULT WINAPI
VarDecCmpR8(const DECIMAL
* pDecLeft
, double dblRight
)
4877 hRet
= VarDecFromR8(dblRight
, &decRight
);
4879 if (SUCCEEDED(hRet
))
4880 hRet
= VarDecCmp(pDecLeft
, &decRight
);
4888 /************************************************************************
4889 * VarBoolFromUI1 (OLEAUT32.118)
4891 * Convert a VT_UI1 to a VT_BOOL.
4895 * pBoolOut [O] Destination
4900 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
*pBoolOut
)
4902 *pBoolOut
= bIn
? VARIANT_TRUE
: VARIANT_FALSE
;
4906 /************************************************************************
4907 * VarBoolFromI2 (OLEAUT32.119)
4909 * Convert a VT_I2 to a VT_BOOL.
4913 * pBoolOut [O] Destination
4918 HRESULT WINAPI
VarBoolFromI2(SHORT sIn
, VARIANT_BOOL
*pBoolOut
)
4920 *pBoolOut
= sIn
? VARIANT_TRUE
: VARIANT_FALSE
;
4924 /************************************************************************
4925 * VarBoolFromI4 (OLEAUT32.120)
4927 * Convert a VT_I4 to a VT_BOOL.
4931 * pBoolOut [O] Destination
4936 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
*pBoolOut
)
4938 *pBoolOut
= lIn
? VARIANT_TRUE
: VARIANT_FALSE
;
4942 /************************************************************************
4943 * VarBoolFromR4 (OLEAUT32.121)
4945 * Convert a VT_R4 to a VT_BOOL.
4949 * pBoolOut [O] Destination
4954 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
*pBoolOut
)
4956 *pBoolOut
= fltIn
? VARIANT_TRUE
: VARIANT_FALSE
;
4960 /************************************************************************
4961 * VarBoolFromR8 (OLEAUT32.122)
4963 * Convert a VT_R8 to a VT_BOOL.
4967 * pBoolOut [O] Destination
4972 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
*pBoolOut
)
4974 *pBoolOut
= dblIn
? VARIANT_TRUE
: VARIANT_FALSE
;
4978 /************************************************************************
4979 * VarBoolFromDate (OLEAUT32.123)
4981 * Convert a VT_DATE to a VT_BOOL.
4985 * pBoolOut [O] Destination
4990 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
*pBoolOut
)
4992 *pBoolOut
= dateIn
? VARIANT_TRUE
: VARIANT_FALSE
;
4996 /************************************************************************
4997 * VarBoolFromCy (OLEAUT32.124)
4999 * Convert a VT_CY to a VT_BOOL.
5003 * pBoolOut [O] Destination
5008 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
*pBoolOut
)
5010 *pBoolOut
= cyIn
.int64
? VARIANT_TRUE
: VARIANT_FALSE
;
5014 static BOOL
VARIANT_GetLocalisedText(LANGID langId
, DWORD dwId
, WCHAR
*lpszDest
)
5018 hrsrc
= FindResourceExW( OLEAUT32_hModule
, (LPWSTR
)RT_STRING
,
5019 MAKEINTRESOURCEW((dwId
>> 4) + 1), langId
);
5022 HGLOBAL hmem
= LoadResource( OLEAUT32_hModule
, hrsrc
);
5029 p
= LockResource( hmem
);
5030 for (i
= 0; i
< (dwId
& 0x0f); i
++) p
+= *p
+ 1;
5032 memcpy( lpszDest
, p
+ 1, *p
* sizeof(WCHAR
) );
5033 lpszDest
[*p
] = '\0';
5034 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest
), langId
);
5041 /************************************************************************
5042 * VarBoolFromStr (OLEAUT32.125)
5044 * Convert a VT_BSTR to a VT_BOOL.
5048 * lcid [I] LCID for the conversion
5049 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5050 * pBoolOut [O] Destination
5054 * Failure: E_INVALIDARG, if pBoolOut is invalid.
5055 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5058 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
5059 * it may contain (in any case mapping) the text "true" or "false".
5060 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
5061 * localised text of "True" or "False" in the language specified by lcid.
5062 * - If none of these matches occur, the string is treated as a numeric string
5063 * and the boolean pBoolOut will be set according to whether the number is zero
5064 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
5065 * - If the text is not numeric and does not match any of the above, then
5066 * DISP_E_TYPEMISMATCH is returned.
5068 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
*pBoolOut
)
5070 /* Any VB/VBA programmers out there should recognise these strings... */
5071 static const WCHAR szFalse
[] = { '#','F','A','L','S','E','#','\0' };
5072 static const WCHAR szTrue
[] = { '#','T','R','U','E','#','\0' };
5074 LANGID langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5075 HRESULT hRes
= S_OK
;
5077 if (!strIn
|| !pBoolOut
)
5078 return DISP_E_TYPEMISMATCH
;
5080 /* Check if we should be comparing against localised text */
5081 if (dwFlags
& VAR_LOCALBOOL
)
5083 /* Convert our LCID into a usable value */
5084 lcid
= ConvertDefaultLocale(lcid
);
5086 langId
= LANGIDFROMLCID(lcid
);
5088 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
5089 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5091 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
5092 * I don't think this is needed unless any of the localised text strings
5093 * contain characters that can be so mapped. In the event that this is
5094 * true for a given language (possibly some Asian languages), then strIn
5095 * should be mapped here _only_ if langId is an Id for which this can occur.
5099 /* Note that if we are not comparing against localised strings, langId
5100 * will have its default value of LANG_ENGLISH. This allows us to mimic
5101 * the native behaviour of always checking against English strings even
5102 * after we've checked for localised ones.
5104 VarBoolFromStr_CheckLocalised
:
5105 if (VARIANT_GetLocalisedText(langId
, IDS_TRUE
, szBuff
))
5107 /* Compare against localised strings, ignoring case */
5108 if (!strcmpiW(strIn
, szBuff
))
5110 *pBoolOut
= VARIANT_TRUE
; /* Matched localised 'true' text */
5113 VARIANT_GetLocalisedText(langId
, IDS_FALSE
, szBuff
);
5114 if (!strcmpiW(strIn
, szBuff
))
5116 *pBoolOut
= VARIANT_FALSE
; /* Matched localised 'false' text */
5121 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
5123 /* We have checked the localised text, now check English */
5124 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5125 goto VarBoolFromStr_CheckLocalised
;
5128 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
5129 if (!strcmpW(strIn
, szFalse
))
5130 *pBoolOut
= VARIANT_FALSE
;
5131 else if (!strcmpW(strIn
, szTrue
))
5132 *pBoolOut
= VARIANT_TRUE
;
5137 /* If this string is a number, convert it as one */
5138 hRes
= VarR8FromStr(strIn
, lcid
, dwFlags
, &d
);
5139 if (SUCCEEDED(hRes
)) *pBoolOut
= d
? VARIANT_TRUE
: VARIANT_FALSE
;
5144 /************************************************************************
5145 * VarBoolFromDisp (OLEAUT32.126)
5147 * Convert a VT_DISPATCH to a VT_BOOL.
5150 * pdispIn [I] Source
5151 * lcid [I] LCID for conversion
5152 * pBoolOut [O] Destination
5156 * Failure: E_INVALIDARG, if the source value is invalid
5157 * DISP_E_OVERFLOW, if the value will not fit in the destination
5158 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5160 HRESULT WINAPI
VarBoolFromDisp(IDispatch
* pdispIn
, LCID lcid
, VARIANT_BOOL
*pBoolOut
)
5162 return VARIANT_FromDisp(pdispIn
, lcid
, pBoolOut
, VT_BOOL
);
5165 /************************************************************************
5166 * VarBoolFromI1 (OLEAUT32.233)
5168 * Convert a VT_I1 to a VT_BOOL.
5172 * pBoolOut [O] Destination
5177 HRESULT WINAPI
VarBoolFromI1(signed char cIn
, VARIANT_BOOL
*pBoolOut
)
5179 *pBoolOut
= cIn
? VARIANT_TRUE
: VARIANT_FALSE
;
5183 /************************************************************************
5184 * VarBoolFromUI2 (OLEAUT32.234)
5186 * Convert a VT_UI2 to a VT_BOOL.
5190 * pBoolOut [O] Destination
5195 HRESULT WINAPI
VarBoolFromUI2(USHORT usIn
, VARIANT_BOOL
*pBoolOut
)
5197 *pBoolOut
= usIn
? VARIANT_TRUE
: VARIANT_FALSE
;
5201 /************************************************************************
5202 * VarBoolFromUI4 (OLEAUT32.235)
5204 * Convert a VT_UI4 to a VT_BOOL.
5208 * pBoolOut [O] Destination
5213 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
*pBoolOut
)
5215 *pBoolOut
= ulIn
? VARIANT_TRUE
: VARIANT_FALSE
;
5219 /************************************************************************
5220 * VarBoolFromDec (OLEAUT32.236)
5222 * Convert a VT_DECIMAL to a VT_BOOL.
5226 * pBoolOut [O] Destination
5230 * Failure: E_INVALIDARG, if pDecIn is invalid.
5232 HRESULT WINAPI
VarBoolFromDec(DECIMAL
* pDecIn
, VARIANT_BOOL
*pBoolOut
)
5234 if (DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
|| (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
))
5235 return E_INVALIDARG
;
5237 if (DEC_HI32(pDecIn
) || DEC_MID32(pDecIn
) || DEC_LO32(pDecIn
))
5238 *pBoolOut
= VARIANT_TRUE
;
5240 *pBoolOut
= VARIANT_FALSE
;
5244 /************************************************************************
5245 * VarBoolFromI8 (OLEAUT32.370)
5247 * Convert a VT_I8 to a VT_BOOL.
5251 * pBoolOut [O] Destination
5256 HRESULT WINAPI
VarBoolFromI8(LONG64 llIn
, VARIANT_BOOL
*pBoolOut
)
5258 *pBoolOut
= llIn
? VARIANT_TRUE
: VARIANT_FALSE
;
5262 /************************************************************************
5263 * VarBoolFromUI8 (OLEAUT32.371)
5265 * Convert a VT_UI8 to a VT_BOOL.
5269 * pBoolOut [O] Destination
5274 HRESULT WINAPI
VarBoolFromUI8(ULONG64 ullIn
, VARIANT_BOOL
*pBoolOut
)
5276 *pBoolOut
= ullIn
? VARIANT_TRUE
: VARIANT_FALSE
;
5283 /* Write a number from a UI8 and sign */
5284 static WCHAR
*VARIANT_WriteNumber(ULONG64 ulVal
, WCHAR
* szOut
)
5288 WCHAR ulNextDigit
= ulVal
% 10;
5290 *szOut
-- = '0' + ulNextDigit
;
5291 ulVal
= (ulVal
- ulNextDigit
) / 10;
5298 /* Create a (possibly localised) BSTR from a UI8 and sign */
5299 static BSTR
VARIANT_MakeBstr(LCID lcid
, DWORD dwFlags
, WCHAR
*szOut
)
5301 WCHAR szConverted
[256];
5303 if (dwFlags
& VAR_NEGATIVE
)
5306 if (dwFlags
& LOCALE_USE_NLS
)
5308 /* Format the number for the locale */
5309 szConverted
[0] = '\0';
5310 GetNumberFormatW(lcid
,
5311 dwFlags
& LOCALE_NOUSEROVERRIDE
,
5312 szOut
, NULL
, szConverted
, sizeof(szConverted
)/sizeof(WCHAR
));
5313 szOut
= szConverted
;
5315 return SysAllocStringByteLen((LPCSTR
)szOut
, strlenW(szOut
) * sizeof(WCHAR
));
5318 /* Create a (possibly localised) BSTR from a UI8 and sign */
5319 static HRESULT
VARIANT_BstrFromUInt(ULONG64 ulVal
, LCID lcid
, DWORD dwFlags
, BSTR
*pbstrOut
)
5321 WCHAR szBuff
[64], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5324 return E_INVALIDARG
;
5326 /* Create the basic number string */
5328 szOut
= VARIANT_WriteNumber(ulVal
, szOut
);
5330 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5331 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5332 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5335 /******************************************************************************
5336 * VarBstrFromUI1 (OLEAUT32.108)
5338 * Convert a VT_UI1 to a VT_BSTR.
5342 * lcid [I] LCID for the conversion
5343 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5344 * pbstrOut [O] Destination
5348 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5349 * E_OUTOFMEMORY, if memory allocation fails.
5351 HRESULT WINAPI
VarBstrFromUI1(BYTE bIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5353 return VARIANT_BstrFromUInt(bIn
, lcid
, dwFlags
, pbstrOut
);
5356 /******************************************************************************
5357 * VarBstrFromI2 (OLEAUT32.109)
5359 * Convert a VT_I2 to a VT_BSTR.
5363 * lcid [I] LCID for the conversion
5364 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5365 * pbstrOut [O] Destination
5369 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5370 * E_OUTOFMEMORY, if memory allocation fails.
5372 HRESULT WINAPI
VarBstrFromI2(short sIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5379 dwFlags
|= VAR_NEGATIVE
;
5381 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5384 /******************************************************************************
5385 * VarBstrFromI4 (OLEAUT32.110)
5387 * Convert a VT_I4 to a VT_BSTR.
5391 * lcid [I] LCID for the conversion
5392 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5393 * pbstrOut [O] Destination
5397 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5398 * E_OUTOFMEMORY, if memory allocation fails.
5400 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5407 dwFlags
|= VAR_NEGATIVE
;
5409 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5412 static HRESULT
VARIANT_BstrFromReal(DOUBLE dblIn
, LCID lcid
, ULONG dwFlags
,
5413 BSTR
* pbstrOut
, LPCWSTR lpszFormat
)
5418 return E_INVALIDARG
;
5420 sprintfW( buff
, lpszFormat
, dblIn
);
5422 /* Negative zeroes are disallowed (some applications depend on this).
5423 If buff starts with a minus, and then nothing follows but zeroes
5424 and/or a period, it is a negative zero and is replaced with a
5425 canonical zero. This duplicates native oleaut32 behavior.
5429 const WCHAR szAccept
[] = {'0', '.', '\0'};
5430 if (strlenW(buff
+ 1) == strspnW(buff
+ 1, szAccept
))
5431 { buff
[0] = '0'; buff
[1] = '\0'; }
5434 TRACE("created string %s\n", debugstr_w(buff
));
5435 if (dwFlags
& LOCALE_USE_NLS
)
5439 /* Format the number for the locale */
5441 GetNumberFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5442 buff
, NULL
, numbuff
, sizeof(numbuff
) / sizeof(WCHAR
));
5443 TRACE("created NLS string %s\n", debugstr_w(numbuff
));
5444 *pbstrOut
= SysAllocString(numbuff
);
5448 WCHAR lpDecimalSep
[16];
5450 /* Native oleaut32 uses the locale-specific decimal separator even in the
5451 absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin
5452 American locales will see "one thousand and one tenth" as "1000,1"
5453 instead of "1000.1" (notice the comma). The following code checks for
5454 the need to replace the decimal separator, and if so, will prepare an
5455 appropriate NUMBERFMTW structure to do the job via GetNumberFormatW().
5457 GetLocaleInfoW(lcid
, LOCALE_SDECIMAL
, lpDecimalSep
, sizeof(lpDecimalSep
) / sizeof(WCHAR
));
5458 if (lpDecimalSep
[0] == '.' && lpDecimalSep
[1] == '\0')
5460 /* locale is compatible with English - return original string */
5461 *pbstrOut
= SysAllocString(buff
);
5467 WCHAR empty
[1] = {'\0'};
5468 NUMBERFMTW minFormat
;
5470 minFormat
.NumDigits
= 0;
5471 minFormat
.LeadingZero
= 0;
5472 minFormat
.Grouping
= 0;
5473 minFormat
.lpDecimalSep
= lpDecimalSep
;
5474 minFormat
.lpThousandSep
= empty
;
5475 minFormat
.NegativeOrder
= 1; /* NLS_NEG_LEFT */
5477 /* count number of decimal digits in string */
5478 p
= strchrW( buff
, '.' );
5479 if (p
) minFormat
.NumDigits
= strlenW(p
+ 1);
5482 if (!GetNumberFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5483 buff
, &minFormat
, numbuff
, sizeof(numbuff
) / sizeof(WCHAR
)))
5485 WARN("GetNumberFormatW() failed, returning raw number string instead\n");
5486 *pbstrOut
= SysAllocString(buff
);
5490 TRACE("created minimal NLS string %s\n", debugstr_w(numbuff
));
5491 *pbstrOut
= SysAllocString(numbuff
);
5495 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5498 /******************************************************************************
5499 * VarBstrFromR4 (OLEAUT32.111)
5501 * Convert a VT_R4 to a VT_BSTR.
5505 * lcid [I] LCID for the conversion
5506 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5507 * pbstrOut [O] Destination
5511 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5512 * E_OUTOFMEMORY, if memory allocation fails.
5514 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5516 return VARIANT_BstrFromReal(fltIn
, lcid
, dwFlags
, pbstrOut
, szFloatFormatW
);
5519 /******************************************************************************
5520 * VarBstrFromR8 (OLEAUT32.112)
5522 * Convert a VT_R8 to a VT_BSTR.
5526 * lcid [I] LCID for the conversion
5527 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5528 * pbstrOut [O] Destination
5532 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5533 * E_OUTOFMEMORY, if memory allocation fails.
5535 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5537 return VARIANT_BstrFromReal(dblIn
, lcid
, dwFlags
, pbstrOut
, szDoubleFormatW
);
5540 /******************************************************************************
5541 * VarBstrFromCy [OLEAUT32.113]
5543 * Convert a VT_CY to a VT_BSTR.
5547 * lcid [I] LCID for the conversion
5548 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5549 * pbstrOut [O] Destination
5553 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5554 * E_OUTOFMEMORY, if memory allocation fails.
5556 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
)
5562 return E_INVALIDARG
;
5564 VarR8FromCy(cyIn
, &dblVal
);
5565 sprintfW(buff
, szDoubleFormatW
, dblVal
);
5567 if (dwFlags
& LOCALE_USE_NLS
)
5571 /* Format the currency for the locale */
5573 GetCurrencyFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5574 buff
, NULL
, cybuff
, sizeof(cybuff
) / sizeof(WCHAR
));
5575 *pbstrOut
= SysAllocString(cybuff
);
5578 *pbstrOut
= SysAllocString(buff
);
5580 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5583 /******************************************************************************
5584 * VarBstrFromDate [OLEAUT32.114]
5586 * Convert a VT_DATE to a VT_BSTR.
5590 * lcid [I] LCID for the conversion
5591 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5592 * pbstrOut [O] Destination
5596 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5597 * E_OUTOFMEMORY, if memory allocation fails.
5599 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5602 DWORD dwFormatFlags
= dwFlags
& LOCALE_NOUSEROVERRIDE
;
5603 WCHAR date
[128], *time
;
5605 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
5607 if (!pbstrOut
|| !VariantTimeToSystemTime(dateIn
, &st
))
5608 return E_INVALIDARG
;
5612 if (dwFlags
& VAR_CALENDAR_THAI
)
5613 st
.wYear
+= 553; /* Use the Thai buddhist calendar year */
5614 else if (dwFlags
& (VAR_CALENDAR_HIJRI
|VAR_CALENDAR_GREGORIAN
))
5615 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5617 if (dwFlags
& LOCALE_USE_NLS
)
5618 dwFlags
&= ~(VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
);
5621 double whole
= dateIn
< 0 ? ceil(dateIn
) : floor(dateIn
);
5622 double partial
= dateIn
- whole
;
5625 dwFlags
|= VAR_TIMEVALUEONLY
;
5626 else if (partial
< 1e-12)
5627 dwFlags
|= VAR_DATEVALUEONLY
;
5630 if (dwFlags
& VAR_TIMEVALUEONLY
)
5633 if (!GetDateFormatW(lcid
, dwFormatFlags
|DATE_SHORTDATE
, &st
, NULL
, date
,
5634 sizeof(date
)/sizeof(WCHAR
)))
5635 return E_INVALIDARG
;
5637 if (!(dwFlags
& VAR_DATEVALUEONLY
))
5639 time
= date
+ strlenW(date
);
5642 if (!GetTimeFormatW(lcid
, dwFormatFlags
, &st
, NULL
, time
,
5643 sizeof(date
)/sizeof(WCHAR
)-(time
-date
)))
5644 return E_INVALIDARG
;
5647 *pbstrOut
= SysAllocString(date
);
5649 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5650 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5653 /******************************************************************************
5654 * VarBstrFromBool (OLEAUT32.116)
5656 * Convert a VT_BOOL to a VT_BSTR.
5660 * lcid [I] LCID for the conversion
5661 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5662 * pbstrOut [O] Destination
5666 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5667 * E_OUTOFMEMORY, if memory allocation fails.
5670 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5671 * localised text of "True" or "False". To convert a bool into a
5672 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5674 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5677 DWORD dwResId
= IDS_TRUE
;
5680 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
5683 return E_INVALIDARG
;
5685 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5686 * for variant formatting */
5687 switch (dwFlags
& (VAR_LOCALBOOL
|VAR_BOOLONOFF
|VAR_BOOLYESNO
))
5698 lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
),SORT_DEFAULT
);
5701 lcid
= ConvertDefaultLocale(lcid
);
5702 langId
= LANGIDFROMLCID(lcid
);
5703 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
5704 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5706 if (boolIn
== VARIANT_FALSE
)
5707 dwResId
++; /* Use negative form */
5709 VarBstrFromBool_GetLocalised
:
5710 if (VARIANT_GetLocalisedText(langId
, dwResId
, szBuff
))
5712 *pbstrOut
= SysAllocString(szBuff
);
5713 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5716 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
5718 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5719 goto VarBstrFromBool_GetLocalised
;
5722 /* Should never get here */
5723 WARN("Failed to load bool text!\n");
5724 return E_OUTOFMEMORY
;
5727 /******************************************************************************
5728 * VarBstrFromI1 (OLEAUT32.229)
5730 * Convert a VT_I1 to a VT_BSTR.
5734 * lcid [I] LCID for the conversion
5735 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5736 * pbstrOut [O] Destination
5740 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5741 * E_OUTOFMEMORY, if memory allocation fails.
5743 HRESULT WINAPI
VarBstrFromI1(signed char cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5750 dwFlags
|= VAR_NEGATIVE
;
5752 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5755 /******************************************************************************
5756 * VarBstrFromUI2 (OLEAUT32.230)
5758 * Convert a VT_UI2 to a VT_BSTR.
5762 * lcid [I] LCID for the conversion
5763 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5764 * pbstrOut [O] Destination
5768 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5769 * E_OUTOFMEMORY, if memory allocation fails.
5771 HRESULT WINAPI
VarBstrFromUI2(USHORT usIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5773 return VARIANT_BstrFromUInt(usIn
, lcid
, dwFlags
, pbstrOut
);
5776 /******************************************************************************
5777 * VarBstrFromUI4 (OLEAUT32.231)
5779 * Convert a VT_UI4 to a VT_BSTR.
5783 * lcid [I] LCID for the conversion
5784 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5785 * pbstrOut [O] Destination
5789 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5790 * E_OUTOFMEMORY, if memory allocation fails.
5792 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5794 return VARIANT_BstrFromUInt(ulIn
, lcid
, dwFlags
, pbstrOut
);
5797 /******************************************************************************
5798 * VarBstrFromDec (OLEAUT32.232)
5800 * Convert a VT_DECIMAL to a VT_BSTR.
5804 * lcid [I] LCID for the conversion
5805 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5806 * pbstrOut [O] Destination
5810 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5811 * E_OUTOFMEMORY, if memory allocation fails.
5813 HRESULT WINAPI
VarBstrFromDec(DECIMAL
* pDecIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5816 return E_INVALIDARG
;
5818 if (!DEC_SCALE(pDecIn
) && !DEC_HI32(pDecIn
))
5820 WCHAR szBuff
[256], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5822 /* Create the basic number string */
5824 szOut
= VARIANT_WriteNumber(DEC_LO64(pDecIn
), szOut
);
5825 if (DEC_SIGN(pDecIn
))
5826 dwFlags
|= VAR_NEGATIVE
;
5828 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5829 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5830 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5832 FIXME("semi-stub\n");
5833 return E_INVALIDARG
;
5836 /************************************************************************
5837 * VarBstrFromI8 (OLEAUT32.370)
5839 * Convert a VT_I8 to a VT_BSTR.
5843 * lcid [I] LCID for the conversion
5844 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5845 * pbstrOut [O] Destination
5849 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5850 * E_OUTOFMEMORY, if memory allocation fails.
5852 HRESULT WINAPI
VarBstrFromI8(LONG64 llIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5854 ULONG64 ul64
= llIn
;
5859 dwFlags
|= VAR_NEGATIVE
;
5861 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5864 /************************************************************************
5865 * VarBstrFromUI8 (OLEAUT32.371)
5867 * Convert a VT_UI8 to a VT_BSTR.
5871 * lcid [I] LCID for the conversion
5872 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5873 * pbstrOut [O] Destination
5877 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5878 * E_OUTOFMEMORY, if memory allocation fails.
5880 HRESULT WINAPI
VarBstrFromUI8(ULONG64 ullIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5882 return VARIANT_BstrFromUInt(ullIn
, lcid
, dwFlags
, pbstrOut
);
5885 /**********************************************************************
5886 * VarBstrCat (OLEAUT32.313)
5888 * Concatenate two BSTR values.
5891 * pbstrLeft [I] Source
5892 * pbstrRight [I] Value to concatenate
5893 * pbstrOut [O] Destination
5897 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5898 * E_OUTOFMEMORY, if memory allocation fails.
5900 HRESULT WINAPI
VarBstrCat(BSTR pbstrLeft
, BSTR pbstrRight
, BSTR
*pbstrOut
)
5905 return E_INVALIDARG
;
5907 len
= pbstrLeft
? strlenW(pbstrLeft
) : 0;
5909 len
+= strlenW(pbstrRight
);
5911 *pbstrOut
= SysAllocStringLen(NULL
, len
);
5913 return E_OUTOFMEMORY
;
5915 (*pbstrOut
)[0] = '\0';
5918 strcpyW(*pbstrOut
, pbstrLeft
);
5921 strcatW(*pbstrOut
, pbstrRight
);
5926 /**********************************************************************
5927 * VarBstrCmp (OLEAUT32.314)
5929 * Compare two BSTR values.
5932 * pbstrLeft [I] Source
5933 * pbstrRight [I] Value to compare
5934 * lcid [I] LCID for the comparison
5935 * dwFlags [I] Flags to pass directly to CompareStringW().
5938 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5939 * than, equal to or greater than pbstrRight respectively.
5940 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5941 * in which case VARCMP_EQ is returned.
5943 HRESULT WINAPI
VarBstrCmp(BSTR pbstrLeft
, BSTR pbstrRight
, LCID lcid
, DWORD dwFlags
)
5947 if (!pbstrRight
|| !*pbstrRight
)
5951 else if (!pbstrRight
)
5958 return CompareStringW(lcid
, dwFlags
, pbstrLeft
, -1, pbstrRight
, -1) - 1;
5965 /******************************************************************************
5966 * VarDateFromUI1 (OLEAUT32.88)
5968 * Convert a VT_UI1 to a VT_DATE.
5972 * pdateOut [O] Destination
5977 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
5979 return VarR8FromUI1(bIn
, pdateOut
);
5982 /******************************************************************************
5983 * VarDateFromI2 (OLEAUT32.89)
5985 * Convert a VT_I2 to a VT_DATE.
5989 * pdateOut [O] Destination
5994 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
5996 return VarR8FromI2(sIn
, pdateOut
);
5999 /******************************************************************************
6000 * VarDateFromI4 (OLEAUT32.90)
6002 * Convert a VT_I4 to a VT_DATE.
6006 * pdateOut [O] Destination
6011 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
6013 return VarDateFromR8(lIn
, pdateOut
);
6016 /******************************************************************************
6017 * VarDateFromR4 (OLEAUT32.91)
6019 * Convert a VT_R4 to a VT_DATE.
6023 * pdateOut [O] Destination
6028 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
6030 return VarR8FromR4(fltIn
, pdateOut
);
6033 /******************************************************************************
6034 * VarDateFromR8 (OLEAUT32.92)
6036 * Convert a VT_R8 to a VT_DATE.
6040 * pdateOut [O] Destination
6045 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
6047 if (dblIn
<= (DATE_MIN
- 1.0) || dblIn
>= (DATE_MAX
+ 1.0)) return DISP_E_OVERFLOW
;
6048 *pdateOut
= (DATE
)dblIn
;
6052 /**********************************************************************
6053 * VarDateFromDisp (OLEAUT32.95)
6055 * Convert a VT_DISPATCH to a VT_DATE.
6058 * pdispIn [I] Source
6059 * lcid [I] LCID for conversion
6060 * pdateOut [O] Destination
6064 * Failure: E_INVALIDARG, if the source value is invalid
6065 * DISP_E_OVERFLOW, if the value will not fit in the destination
6066 * DISP_E_TYPEMISMATCH, if the type cannot be converted
6068 HRESULT WINAPI
VarDateFromDisp(IDispatch
* pdispIn
, LCID lcid
, DATE
* pdateOut
)
6070 return VARIANT_FromDisp(pdispIn
, lcid
, pdateOut
, VT_DATE
);
6073 /******************************************************************************
6074 * VarDateFromBool (OLEAUT32.96)
6076 * Convert a VT_BOOL to a VT_DATE.
6080 * pdateOut [O] Destination
6085 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
6087 return VarR8FromBool(boolIn
, pdateOut
);
6090 /**********************************************************************
6091 * VarDateFromCy (OLEAUT32.93)
6093 * Convert a VT_CY to a VT_DATE.
6097 * pdateOut [O] Destination
6102 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
)
6104 return VarR8FromCy(cyIn
, pdateOut
);
6107 /* Date string parsing */
6108 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
6109 #define DP_DATESEP 0x02 /* Date separator */
6110 #define DP_MONTH 0x04 /* Month name */
6111 #define DP_AM 0x08 /* AM */
6112 #define DP_PM 0x10 /* PM */
6114 typedef struct tagDATEPARSE
6116 DWORD dwCount
; /* Number of fields found so far (maximum 6) */
6117 DWORD dwParseFlags
; /* Global parse flags (DP_ Flags above) */
6118 DWORD dwFlags
[6]; /* Flags for each field */
6119 DWORD dwValues
[6]; /* Value of each field */
6122 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
6124 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
6126 /* Determine if a day is valid in a given month of a given year */
6127 static BOOL
VARIANT_IsValidMonthDay(DWORD day
, DWORD month
, DWORD year
)
6129 static const BYTE days
[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
6131 if (day
&& month
&& month
< 13)
6133 if (day
<= days
[month
] || (month
== 2 && day
== 29 && IsLeapYear(year
)))
6139 /* Possible orders for 3 numbers making up a date */
6140 #define ORDER_MDY 0x01
6141 #define ORDER_YMD 0x02
6142 #define ORDER_YDM 0x04
6143 #define ORDER_DMY 0x08
6144 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
6146 /* Determine a date for a particular locale, from 3 numbers */
6147 static inline HRESULT
VARIANT_MakeDate(DATEPARSE
*dp
, DWORD iDate
,
6148 DWORD offset
, SYSTEMTIME
*st
)
6150 DWORD dwAllOrders
, dwTry
, dwCount
= 0, v1
, v2
, v3
;
6154 v1
= 30; /* Default to (Variant) 0 date part */
6157 goto VARIANT_MakeDate_OK
;
6160 v1
= dp
->dwValues
[offset
+ 0];
6161 v2
= dp
->dwValues
[offset
+ 1];
6162 if (dp
->dwCount
== 2)
6165 GetSystemTime(¤t
);
6169 v3
= dp
->dwValues
[offset
+ 2];
6171 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1
, v2
, v3
, iDate
, offset
);
6173 /* If one number must be a month (Because a month name was given), then only
6174 * consider orders with the month in that position.
6175 * If we took the current year as 'v3', then only allow a year in that position.
6177 if (dp
->dwFlags
[offset
+ 0] & DP_MONTH
)
6179 dwAllOrders
= ORDER_MDY
;
6181 else if (dp
->dwFlags
[offset
+ 1] & DP_MONTH
)
6183 dwAllOrders
= ORDER_DMY
;
6184 if (dp
->dwCount
> 2)
6185 dwAllOrders
|= ORDER_YMD
;
6187 else if (dp
->dwCount
> 2 && dp
->dwFlags
[offset
+ 2] & DP_MONTH
)
6189 dwAllOrders
= ORDER_YDM
;
6193 dwAllOrders
= ORDER_MDY
|ORDER_DMY
;
6194 if (dp
->dwCount
> 2)
6195 dwAllOrders
|= (ORDER_YMD
|ORDER_YDM
);
6198 VARIANT_MakeDate_Start
:
6199 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders
);
6207 /* First: Try the order given by iDate */
6210 case 0: dwTry
= dwAllOrders
& ORDER_MDY
; break;
6211 case 1: dwTry
= dwAllOrders
& ORDER_DMY
; break;
6212 default: dwTry
= dwAllOrders
& ORDER_YMD
; break;
6215 else if (dwCount
== 1)
6217 /* Second: Try all the orders compatible with iDate */
6220 case 0: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
6221 case 1: dwTry
= dwAllOrders
& ~(ORDER_MDY
|ORDER_YMD
|ORDER_MYD
); break;
6222 default: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
6227 /* Finally: Try any remaining orders */
6228 dwTry
= dwAllOrders
;
6231 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount
, dwTry
);
6237 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6239 if (dwTry
& ORDER_MDY
)
6241 if (VARIANT_IsValidMonthDay(v2
,v1
,v3
))
6244 goto VARIANT_MakeDate_OK
;
6246 dwAllOrders
&= ~ORDER_MDY
;
6248 if (dwTry
& ORDER_YMD
)
6250 if (VARIANT_IsValidMonthDay(v3
,v2
,v1
))
6253 goto VARIANT_MakeDate_OK
;
6255 dwAllOrders
&= ~ORDER_YMD
;
6257 if (dwTry
& ORDER_YDM
)
6259 if (VARIANT_IsValidMonthDay(v2
,v3
,v1
))
6263 goto VARIANT_MakeDate_OK
;
6265 dwAllOrders
&= ~ORDER_YDM
;
6267 if (dwTry
& ORDER_DMY
)
6269 if (VARIANT_IsValidMonthDay(v1
,v2
,v3
))
6270 goto VARIANT_MakeDate_OK
;
6271 dwAllOrders
&= ~ORDER_DMY
;
6273 if (dwTry
& ORDER_MYD
)
6275 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6276 if (VARIANT_IsValidMonthDay(v3
,v1
,v2
))
6280 goto VARIANT_MakeDate_OK
;
6282 dwAllOrders
&= ~ORDER_MYD
;
6286 if (dp
->dwCount
== 2)
6288 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6289 v3
= 1; /* 1st of the month */
6290 dwAllOrders
= ORDER_YMD
|ORDER_MYD
;
6291 dp
->dwCount
= 0; /* Don't return to this code path again */
6293 goto VARIANT_MakeDate_Start
;
6296 /* No valid dates were able to be constructed */
6297 return DISP_E_TYPEMISMATCH
;
6299 VARIANT_MakeDate_OK
:
6301 /* Check that the time part is ok */
6302 if (st
->wHour
> 23 || st
->wMinute
> 59 || st
->wSecond
> 59)
6303 return DISP_E_TYPEMISMATCH
;
6305 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6306 if (st
->wHour
< 12 && (dp
->dwParseFlags
& DP_PM
))
6308 else if (st
->wHour
== 12 && (dp
->dwParseFlags
& DP_AM
))
6310 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6314 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6315 * be retrieved from:
6316 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6317 * But Wine doesn't have/use that key as at the time of writing.
6319 st
->wYear
= v3
< 30 ? 2000 + v3
: v3
< 100 ? 1900 + v3
: v3
;
6320 TRACE("Returning date %ld/%ld/%d\n", v1
, v2
, st
->wYear
);
6324 /******************************************************************************
6325 * VarDateFromStr [OLEAUT32.94]
6327 * Convert a VT_BSTR to at VT_DATE.
6330 * strIn [I] String to convert
6331 * lcid [I] Locale identifier for the conversion
6332 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6333 * pdateOut [O] Destination for the converted value
6336 * Success: S_OK. pdateOut contains the converted value.
6337 * FAILURE: An HRESULT error code indicating the prolem.
6340 * Any date format that can be created using the date formats from lcid
6341 * (Either from kernel Nls functions, variant conversion or formatting) is a
6342 * valid input to this function. In addition, a few more esoteric formats are
6343 * also supported for compatibility with the native version. The date is
6344 * interpreted according to the date settings in the control panel, unless
6345 * the date is invalid in that format, in which the most compatible format
6346 * that produces a valid date will be used.
6348 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
6350 static const USHORT ParseDateTokens
[] =
6352 LOCALE_SMONTHNAME1
, LOCALE_SMONTHNAME2
, LOCALE_SMONTHNAME3
, LOCALE_SMONTHNAME4
,
6353 LOCALE_SMONTHNAME5
, LOCALE_SMONTHNAME6
, LOCALE_SMONTHNAME7
, LOCALE_SMONTHNAME8
,
6354 LOCALE_SMONTHNAME9
, LOCALE_SMONTHNAME10
, LOCALE_SMONTHNAME11
, LOCALE_SMONTHNAME12
,
6355 LOCALE_SMONTHNAME13
,
6356 LOCALE_SABBREVMONTHNAME1
, LOCALE_SABBREVMONTHNAME2
, LOCALE_SABBREVMONTHNAME3
,
6357 LOCALE_SABBREVMONTHNAME4
, LOCALE_SABBREVMONTHNAME5
, LOCALE_SABBREVMONTHNAME6
,
6358 LOCALE_SABBREVMONTHNAME7
, LOCALE_SABBREVMONTHNAME8
, LOCALE_SABBREVMONTHNAME9
,
6359 LOCALE_SABBREVMONTHNAME10
, LOCALE_SABBREVMONTHNAME11
, LOCALE_SABBREVMONTHNAME12
,
6360 LOCALE_SABBREVMONTHNAME13
,
6361 LOCALE_SDAYNAME1
, LOCALE_SDAYNAME2
, LOCALE_SDAYNAME3
, LOCALE_SDAYNAME4
,
6362 LOCALE_SDAYNAME5
, LOCALE_SDAYNAME6
, LOCALE_SDAYNAME7
,
6363 LOCALE_SABBREVDAYNAME1
, LOCALE_SABBREVDAYNAME2
, LOCALE_SABBREVDAYNAME3
,
6364 LOCALE_SABBREVDAYNAME4
, LOCALE_SABBREVDAYNAME5
, LOCALE_SABBREVDAYNAME6
,
6365 LOCALE_SABBREVDAYNAME7
,
6366 LOCALE_S1159
, LOCALE_S2359
6368 static const BYTE ParseDateMonths
[] =
6370 1,2,3,4,5,6,7,8,9,10,11,12,13,
6371 1,2,3,4,5,6,7,8,9,10,11,12,13
6374 BSTR tokens
[sizeof(ParseDateTokens
)/sizeof(ParseDateTokens
[0])];
6376 DWORD dwDateSeps
= 0, iDate
= 0;
6377 HRESULT hRet
= S_OK
;
6379 if ((dwFlags
& (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
)) ==
6380 (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
))
6381 return E_INVALIDARG
;
6384 return DISP_E_TYPEMISMATCH
;
6388 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn
), lcid
, dwFlags
, pdateOut
);
6390 memset(&dp
, 0, sizeof(dp
));
6392 GetLocaleInfoW(lcid
, LOCALE_IDATE
|LOCALE_RETURN_NUMBER
|(dwFlags
& LOCALE_NOUSEROVERRIDE
),
6393 (LPWSTR
)&iDate
, sizeof(iDate
)/sizeof(WCHAR
));
6394 TRACE("iDate is %ld\n", iDate
);
6396 /* Get the month/day/am/pm tokens for this locale */
6397 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6400 LCTYPE lctype
= ParseDateTokens
[i
] | (dwFlags
& LOCALE_NOUSEROVERRIDE
);
6402 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6403 * GetAltMonthNames(). We should really cache these strings too.
6406 GetLocaleInfoW(lcid
, lctype
, buff
, sizeof(buff
)/sizeof(WCHAR
));
6407 tokens
[i
] = SysAllocString(buff
);
6408 TRACE("token %d is %s\n", i
, debugstr_w(tokens
[i
]));
6411 /* Parse the string into our structure */
6417 if (isdigitW(*strIn
))
6419 dp
.dwValues
[dp
.dwCount
] = strtoulW(strIn
, &strIn
, 10);
6423 else if (isalpha(*strIn
))
6425 BOOL bFound
= FALSE
;
6427 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6429 DWORD dwLen
= strlenW(tokens
[i
]);
6430 if (dwLen
&& !strncmpiW(strIn
, tokens
[i
], dwLen
))
6434 dp
.dwValues
[dp
.dwCount
] = ParseDateMonths
[i
];
6435 dp
.dwFlags
[dp
.dwCount
] |= (DP_MONTH
|DP_DATESEP
);
6440 if (!dp
.dwCount
|| dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6441 hRet
= DISP_E_TYPEMISMATCH
;
6444 dp
.dwFlags
[dp
.dwCount
- 1] |= (i
== 40 ? DP_AM
: DP_PM
);
6445 dp
.dwParseFlags
|= (i
== 40 ? DP_AM
: DP_PM
);
6448 strIn
+= (dwLen
- 1);
6456 if ((*strIn
== 'a' || *strIn
== 'A' || *strIn
== 'p' || *strIn
== 'P') &&
6457 (dp
.dwCount
&& !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6459 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6460 if (*strIn
== 'a' || *strIn
== 'A')
6462 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_AM
;
6463 dp
.dwParseFlags
|= DP_AM
;
6467 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_PM
;
6468 dp
.dwParseFlags
|= DP_PM
;
6474 TRACE("No matching token for %s\n", debugstr_w(strIn
));
6475 hRet
= DISP_E_TYPEMISMATCH
;
6480 else if (*strIn
== ':' || *strIn
== '.')
6482 if (!dp
.dwCount
|| !strIn
[1])
6483 hRet
= DISP_E_TYPEMISMATCH
;
6485 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_TIMESEP
;
6487 else if (*strIn
== '-' || *strIn
== '/')
6490 if (dwDateSeps
> 2 || !dp
.dwCount
|| !strIn
[1])
6491 hRet
= DISP_E_TYPEMISMATCH
;
6493 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_DATESEP
;
6495 else if (*strIn
== ',' || isspaceW(*strIn
))
6497 if (*strIn
== ',' && !strIn
[1])
6498 hRet
= DISP_E_TYPEMISMATCH
;
6502 hRet
= DISP_E_TYPEMISMATCH
;
6507 if (!dp
.dwCount
|| dp
.dwCount
> 6 ||
6508 (dp
.dwCount
== 1 && !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6509 hRet
= DISP_E_TYPEMISMATCH
;
6511 if (SUCCEEDED(hRet
))
6514 DWORD dwOffset
= 0; /* Start of date fields in dp.dwValues */
6516 st
.wDayOfWeek
= st
.wHour
= st
.wMinute
= st
.wSecond
= st
.wMilliseconds
= 0;
6518 /* Figure out which numbers correspond to which fields.
6520 * This switch statement works based on the fact that native interprets any
6521 * fields that are not joined with a time separator ('.' or ':') as date
6522 * fields. Thus we construct a value from 0-32 where each set bit indicates
6523 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6524 * For valid permutations, we set dwOffset to point to the first date field
6525 * and shorten dp.dwCount by the number of time fields found. The real
6526 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6527 * each date number must represent in the context of iDate.
6529 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6531 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6533 case 0x1: /* TT TTDD TTDDD */
6534 if (dp
.dwCount
> 3 &&
6535 ((dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) ||
6536 (dp
.dwFlags
[4] & (DP_AM
|DP_PM
))))
6537 hRet
= DISP_E_TYPEMISMATCH
;
6538 else if (dp
.dwCount
!= 2 && dp
.dwCount
!= 4 && dp
.dwCount
!= 5)
6539 hRet
= DISP_E_TYPEMISMATCH
;
6540 st
.wHour
= dp
.dwValues
[0];
6541 st
.wMinute
= dp
.dwValues
[1];
6546 case 0x3: /* TTT TTTDD TTTDDD */
6547 if (dp
.dwCount
> 4 &&
6548 ((dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[4] & (DP_AM
|DP_PM
)) ||
6549 (dp
.dwFlags
[5] & (DP_AM
|DP_PM
))))
6550 hRet
= DISP_E_TYPEMISMATCH
;
6551 else if (dp
.dwCount
!= 3 && dp
.dwCount
!= 5 && dp
.dwCount
!= 6)
6552 hRet
= DISP_E_TYPEMISMATCH
;
6553 st
.wHour
= dp
.dwValues
[0];
6554 st
.wMinute
= dp
.dwValues
[1];
6555 st
.wSecond
= dp
.dwValues
[2];
6560 case 0x4: /* DDTT */
6561 if (dp
.dwCount
!= 4 ||
6562 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6563 hRet
= DISP_E_TYPEMISMATCH
;
6565 st
.wHour
= dp
.dwValues
[2];
6566 st
.wMinute
= dp
.dwValues
[3];
6570 case 0x0: /* T DD DDD TDDD TDDD */
6571 if (dp
.dwCount
== 1 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6573 st
.wHour
= dp
.dwValues
[0]; /* T */
6577 else if (dp
.dwCount
> 4 || (dp
.dwCount
< 3 && dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6579 hRet
= DISP_E_TYPEMISMATCH
;
6581 else if (dp
.dwCount
== 3)
6583 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDD */
6586 st
.wHour
= dp
.dwValues
[0];
6590 if (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) /* DDT */
6593 st
.wHour
= dp
.dwValues
[2];
6596 else if (dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6597 hRet
= DISP_E_TYPEMISMATCH
;
6599 else if (dp
.dwCount
== 4)
6602 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDDD */
6604 st
.wHour
= dp
.dwValues
[0];
6607 else if (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) /* DDDT */
6609 st
.wHour
= dp
.dwValues
[3];
6612 hRet
= DISP_E_TYPEMISMATCH
;
6615 /* .. fall through .. */
6617 case 0x8: /* DDDTT */
6618 if ((dp
.dwCount
== 2 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
))) ||
6619 (dp
.dwCount
== 5 && ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) ||
6620 (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))) ||
6621 dp
.dwCount
== 4 || dp
.dwCount
== 6)
6622 hRet
= DISP_E_TYPEMISMATCH
;
6623 st
.wHour
= dp
.dwValues
[3];
6624 st
.wMinute
= dp
.dwValues
[4];
6625 if (dp
.dwCount
== 5)
6629 case 0xC: /* DDTTT */
6630 if (dp
.dwCount
!= 5 ||
6631 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6632 hRet
= DISP_E_TYPEMISMATCH
;
6633 st
.wHour
= dp
.dwValues
[2];
6634 st
.wMinute
= dp
.dwValues
[3];
6635 st
.wSecond
= dp
.dwValues
[4];
6639 case 0x18: /* DDDTTT */
6640 if ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) ||
6641 (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))
6642 hRet
= DISP_E_TYPEMISMATCH
;
6643 st
.wHour
= dp
.dwValues
[3];
6644 st
.wMinute
= dp
.dwValues
[4];
6645 st
.wSecond
= dp
.dwValues
[5];
6650 hRet
= DISP_E_TYPEMISMATCH
;
6654 if (SUCCEEDED(hRet
))
6656 hRet
= VARIANT_MakeDate(&dp
, iDate
, dwOffset
, &st
);
6658 if (dwFlags
& VAR_TIMEVALUEONLY
)
6664 else if (dwFlags
& VAR_DATEVALUEONLY
)
6665 st
.wHour
= st
.wMinute
= st
.wSecond
= 0;
6667 /* Finally, convert the value to a VT_DATE */
6668 if (SUCCEEDED(hRet
))
6669 hRet
= SystemTimeToVariantTime(&st
, pdateOut
) ? S_OK
: DISP_E_TYPEMISMATCH
;
6673 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6674 SysFreeString(tokens
[i
]);
6678 /******************************************************************************
6679 * VarDateFromI1 (OLEAUT32.221)
6681 * Convert a VT_I1 to a VT_DATE.
6685 * pdateOut [O] Destination
6690 HRESULT WINAPI
VarDateFromI1(signed char cIn
, DATE
* pdateOut
)
6692 return VarR8FromI1(cIn
, pdateOut
);
6695 /******************************************************************************
6696 * VarDateFromUI2 (OLEAUT32.222)
6698 * Convert a VT_UI2 to a VT_DATE.
6702 * pdateOut [O] Destination
6707 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
6709 return VarR8FromUI2(uiIn
, pdateOut
);
6712 /******************************************************************************
6713 * VarDateFromUI4 (OLEAUT32.223)
6715 * Convert a VT_UI4 to a VT_DATE.
6719 * pdateOut [O] Destination
6724 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
6726 return VarDateFromR8(ulIn
, pdateOut
);
6729 /**********************************************************************
6730 * VarDateFromDec (OLEAUT32.224)
6732 * Convert a VT_DECIMAL to a VT_DATE.
6736 * pdateOut [O] Destination
6741 HRESULT WINAPI
VarDateFromDec(DECIMAL
*pdecIn
, DATE
* pdateOut
)
6743 return VarR8FromDec(pdecIn
, pdateOut
);
6746 /******************************************************************************
6747 * VarDateFromI8 (OLEAUT32.364)
6749 * Convert a VT_I8 to a VT_DATE.
6753 * pdateOut [O] Destination
6757 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6759 HRESULT WINAPI
VarDateFromI8(LONG64 llIn
, DATE
* pdateOut
)
6761 if (llIn
< DATE_MIN
|| llIn
> DATE_MAX
) return DISP_E_OVERFLOW
;
6762 *pdateOut
= (DATE
)llIn
;
6766 /******************************************************************************
6767 * VarDateFromUI8 (OLEAUT32.365)
6769 * Convert a VT_UI8 to a VT_DATE.
6773 * pdateOut [O] Destination
6777 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6779 HRESULT WINAPI
VarDateFromUI8(ULONG64 ullIn
, DATE
* pdateOut
)
6781 if (ullIn
> DATE_MAX
) return DISP_E_OVERFLOW
;
6782 *pdateOut
= (DATE
)ullIn
;