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 static const WCHAR szFloatFormatW
[] = { '%','.','7','G','\0' };
38 static const WCHAR szDoubleFormatW
[] = { '%','.','1','5','G','\0' };
40 /* Copy data from one variant to another. */
41 static inline void VARIANT_CopyData(const VARIANT
*srcVar
, VARTYPE vt
, void *pOut
)
46 case VT_UI1
: memcpy(pOut
, &V_UI1(srcVar
), sizeof(BYTE
)); break;
49 case VT_UI2
: memcpy(pOut
, &V_UI2(srcVar
), sizeof(SHORT
)); break;
54 case VT_UI4
: memcpy(pOut
, &V_UI4(srcVar
), sizeof (LONG
)); break;
59 case VT_UI8
: memcpy(pOut
, &V_UI8(srcVar
), sizeof (LONG64
)); break;
60 case VT_INT_PTR
: memcpy(pOut
, &V_INT_PTR(srcVar
), sizeof (INT_PTR
)); break;
61 case VT_DECIMAL
: memcpy(pOut
, &V_DECIMAL(srcVar
), sizeof (DECIMAL
)); break;
63 FIXME("VT_ type %d unhandled, please report!\n", vt
);
68 /* Coerce VT_BSTR to a numeric type */
69 HRESULT
VARIANT_NumberFromBstr(OLECHAR
* pStrIn
, LCID lcid
, ULONG ulFlags
,
70 void* pOut
, VARTYPE vt
)
77 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
78 np
.cDig
= sizeof(rgb
) / sizeof(BYTE
);
79 np
.dwInFlags
= NUMPRS_STD
;
81 hRet
= VarParseNumFromStr(pStrIn
, lcid
, ulFlags
, &np
, rgb
);
85 /* 1 << vt gives us the VTBIT constant for the destination number type */
86 hRet
= VarNumFromParseNum(&np
, rgb
, 1 << vt
, &dstVar
);
88 VARIANT_CopyData(&dstVar
, vt
, pOut
);
93 /* Coerce VT_DISPATCH to another type */
94 HRESULT
VARIANT_FromDisp(IDispatch
* pdispIn
, LCID lcid
, void* pOut
, VARTYPE vt
)
96 static const DISPPARAMS emptyParams
= { NULL
, NULL
, 0, 0 };
97 VARIANTARG srcVar
, dstVar
;
101 return DISP_E_BADVARTYPE
;
103 /* Get the default 'value' property from the IDispatch */
104 hRet
= IDispatch_Invoke(pdispIn
, DISPID_VALUE
, &IID_NULL
, lcid
, DISPATCH_PROPERTYGET
,
105 (DISPPARAMS
*)&emptyParams
, &srcVar
, NULL
, NULL
);
109 /* Convert the property to the requested type */
110 V_VT(&dstVar
) = VT_EMPTY
;
111 hRet
= VariantChangeTypeEx(&dstVar
, &srcVar
, lcid
, 0, vt
);
112 VariantClear(&srcVar
);
116 VARIANT_CopyData(&dstVar
, vt
, pOut
);
117 VariantClear(&srcVar
);
121 hRet
= DISP_E_TYPEMISMATCH
;
128 /************************************************************************
129 * VarI1FromUI1 (OLEAUT32.244)
131 * Convert a VT_UI1 to a VT_I1.
135 * pcOut [O] Destination
139 * Failure: E_INVALIDARG, if the source value is invalid
140 * DISP_E_OVERFLOW, if the value will not fit in the destination
142 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, signed char* pcOut
)
144 return _VarI1FromUI1(bIn
, pcOut
);
147 /************************************************************************
148 * VarI1FromI2 (OLEAUT32.245)
150 * Convert a VT_I2 to a VT_I1.
154 * pcOut [O] Destination
158 * Failure: E_INVALIDARG, if the source value is invalid
159 * DISP_E_OVERFLOW, if the value will not fit in the destination
161 HRESULT WINAPI
VarI1FromI2(SHORT sIn
, signed char* pcOut
)
163 return _VarI1FromI2(sIn
, pcOut
);
166 /************************************************************************
167 * VarI1FromI4 (OLEAUT32.246)
169 * Convert a VT_I4 to a VT_I1.
173 * pcOut [O] Destination
177 * Failure: E_INVALIDARG, if the source value is invalid
178 * DISP_E_OVERFLOW, if the value will not fit in the destination
180 HRESULT WINAPI
VarI1FromI4(LONG iIn
, signed char* pcOut
)
182 return _VarI1FromI4(iIn
, pcOut
);
185 /************************************************************************
186 * VarI1FromR4 (OLEAUT32.247)
188 * Convert a VT_R4 to a VT_I1.
192 * pcOut [O] Destination
196 * Failure: E_INVALIDARG, if the source value is invalid
197 * DISP_E_OVERFLOW, if the value will not fit in the destination
199 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, signed char* pcOut
)
201 return _VarI1FromR4(fltIn
, pcOut
);
204 /************************************************************************
205 * VarI1FromR8 (OLEAUT32.248)
207 * Convert a VT_R8 to a VT_I1.
211 * pcOut [O] Destination
215 * Failure: E_INVALIDARG, if the source value is invalid
216 * DISP_E_OVERFLOW, if the value will not fit in the destination
219 * See VarI8FromR8() for details concerning rounding.
221 HRESULT WINAPI
VarI1FromR8(double dblIn
, signed char* pcOut
)
223 if (dblIn
< (double)I1_MIN
|| dblIn
> (double)I1_MAX
)
224 return DISP_E_OVERFLOW
;
225 OLEAUT32_DutchRound(CHAR
, dblIn
, *pcOut
);
229 /************************************************************************
230 * VarI1FromDate (OLEAUT32.249)
232 * Convert a VT_DATE to a VT_I1.
236 * pcOut [O] Destination
240 * Failure: E_INVALIDARG, if the source value is invalid
241 * DISP_E_OVERFLOW, if the value will not fit in the destination
243 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, signed char* pcOut
)
245 return _VarI1FromDate(dateIn
, pcOut
);
248 /************************************************************************
249 * VarI1FromCy (OLEAUT32.250)
251 * Convert a VT_CY to a VT_I1.
255 * pcOut [O] Destination
259 * Failure: E_INVALIDARG, if the source value is invalid
260 * DISP_E_OVERFLOW, if the value will not fit in the destination
262 HRESULT WINAPI
VarI1FromCy(CY cyIn
, signed char* pcOut
)
266 _VarI4FromCy(cyIn
, &i
);
267 return _VarI1FromI4(i
, pcOut
);
270 /************************************************************************
271 * VarI1FromStr (OLEAUT32.251)
273 * Convert a VT_BSTR to a VT_I1.
277 * lcid [I] LCID for the conversion
278 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
279 * pcOut [O] Destination
283 * Failure: E_INVALIDARG, if the source value is invalid
284 * DISP_E_OVERFLOW, if the value will not fit in the destination
285 * DISP_E_TYPEMISMATCH, if the type cannot be converted
287 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, signed char* pcOut
)
289 return _VarI1FromStr(strIn
, lcid
, dwFlags
, pcOut
);
292 /************************************************************************
293 * VarI1FromDisp (OLEAUT32.252)
295 * Convert a VT_DISPATCH to a VT_I1.
299 * lcid [I] LCID for conversion
300 * pcOut [O] Destination
304 * Failure: E_INVALIDARG, if the source value is invalid
305 * DISP_E_OVERFLOW, if the value will not fit in the destination
306 * DISP_E_TYPEMISMATCH, if the type cannot be converted
308 HRESULT WINAPI
VarI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, signed char* pcOut
)
310 return _VarI1FromDisp(pdispIn
, lcid
, pcOut
);
313 /************************************************************************
314 * VarI1FromBool (OLEAUT32.253)
316 * Convert a VT_BOOL to a VT_I1.
320 * pcOut [O] Destination
325 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, signed char* pcOut
)
327 return _VarI1FromBool(boolIn
, pcOut
);
330 /************************************************************************
331 * VarI1FromUI2 (OLEAUT32.254)
333 * Convert a VT_UI2 to a VT_I1.
337 * pcOut [O] Destination
341 * Failure: E_INVALIDARG, if the source value is invalid
342 * DISP_E_OVERFLOW, if the value will not fit in the destination
344 HRESULT WINAPI
VarI1FromUI2(USHORT usIn
, signed char* pcOut
)
346 return _VarI1FromUI2(usIn
, pcOut
);
349 /************************************************************************
350 * VarI1FromUI4 (OLEAUT32.255)
352 * Convert a VT_UI4 to a VT_I1.
356 * pcOut [O] Destination
360 * Failure: E_INVALIDARG, if the source value is invalid
361 * DISP_E_OVERFLOW, if the value will not fit in the destination
362 * DISP_E_TYPEMISMATCH, if the type cannot be converted
364 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, signed char* pcOut
)
366 return _VarI1FromUI4(ulIn
, pcOut
);
369 /************************************************************************
370 * VarI1FromDec (OLEAUT32.256)
372 * Convert a VT_DECIMAL to a VT_I1.
376 * pcOut [O] Destination
380 * Failure: E_INVALIDARG, if the source value is invalid
381 * DISP_E_OVERFLOW, if the value will not fit in the destination
383 HRESULT WINAPI
VarI1FromDec(DECIMAL
*pdecIn
, signed char* pcOut
)
388 hRet
= _VarI8FromDec(pdecIn
, &i64
);
391 hRet
= _VarI1FromI8(i64
, pcOut
);
395 /************************************************************************
396 * VarI1FromI8 (OLEAUT32.376)
398 * Convert a VT_I8 to a VT_I1.
402 * pcOut [O] Destination
406 * Failure: E_INVALIDARG, if the source value is invalid
407 * DISP_E_OVERFLOW, if the value will not fit in the destination
409 HRESULT WINAPI
VarI1FromI8(LONG64 llIn
, signed char* pcOut
)
411 return _VarI1FromI8(llIn
, pcOut
);
414 /************************************************************************
415 * VarI1FromUI8 (OLEAUT32.377)
417 * Convert a VT_UI8 to a VT_I1.
421 * pcOut [O] Destination
425 * Failure: E_INVALIDARG, if the source value is invalid
426 * DISP_E_OVERFLOW, if the value will not fit in the destination
428 HRESULT WINAPI
VarI1FromUI8(ULONG64 ullIn
, signed char* pcOut
)
430 return _VarI1FromUI8(ullIn
, pcOut
);
436 /************************************************************************
437 * VarUI1FromI2 (OLEAUT32.130)
439 * Convert a VT_I2 to a VT_UI1.
443 * pbOut [O] Destination
447 * Failure: E_INVALIDARG, if the source value is invalid
448 * DISP_E_OVERFLOW, if the value will not fit in the destination
450 HRESULT WINAPI
VarUI1FromI2(SHORT sIn
, BYTE
* pbOut
)
452 return _VarUI1FromI2(sIn
, pbOut
);
455 /************************************************************************
456 * VarUI1FromI4 (OLEAUT32.131)
458 * Convert a VT_I4 to a VT_UI1.
462 * pbOut [O] Destination
466 * Failure: E_INVALIDARG, if the source value is invalid
467 * DISP_E_OVERFLOW, if the value will not fit in the destination
469 HRESULT WINAPI
VarUI1FromI4(LONG iIn
, BYTE
* pbOut
)
471 return _VarUI1FromI4(iIn
, pbOut
);
474 /************************************************************************
475 * VarUI1FromR4 (OLEAUT32.132)
477 * Convert a VT_R4 to a VT_UI1.
481 * pbOut [O] Destination
485 * Failure: E_INVALIDARG, if the source value is invalid
486 * DISP_E_OVERFLOW, if the value will not fit in the destination
487 * DISP_E_TYPEMISMATCH, if the type cannot be converted
489 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
491 return _VarUI1FromR4(fltIn
, pbOut
);
494 /************************************************************************
495 * VarUI1FromR8 (OLEAUT32.133)
497 * Convert a VT_R8 to a VT_UI1.
501 * pbOut [O] Destination
505 * Failure: E_INVALIDARG, if the source value is invalid
506 * DISP_E_OVERFLOW, if the value will not fit in the destination
509 * See VarI8FromR8() for details concerning rounding.
511 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
513 if (dblIn
< -0.5 || dblIn
> (double)UI1_MAX
)
514 return DISP_E_OVERFLOW
;
515 OLEAUT32_DutchRound(BYTE
, dblIn
, *pbOut
);
519 /************************************************************************
520 * VarUI1FromCy (OLEAUT32.134)
522 * Convert a VT_CY to a VT_UI1.
526 * pbOut [O] Destination
530 * Failure: E_INVALIDARG, if the source value is invalid
531 * DISP_E_OVERFLOW, if the value will not fit in the destination
534 * Negative values >= -5000 will be converted to 0.
536 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
)
538 ULONG i
= UI1_MAX
+ 1;
540 _VarUI4FromCy(cyIn
, &i
);
541 return _VarUI1FromUI4(i
, pbOut
);
544 /************************************************************************
545 * VarUI1FromDate (OLEAUT32.135)
547 * Convert a VT_DATE to a VT_UI1.
551 * pbOut [O] Destination
555 * Failure: E_INVALIDARG, if the source value is invalid
556 * DISP_E_OVERFLOW, if the value will not fit in the destination
558 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
560 return _VarUI1FromDate(dateIn
, pbOut
);
563 /************************************************************************
564 * VarUI1FromStr (OLEAUT32.136)
566 * Convert a VT_BSTR to a VT_UI1.
570 * lcid [I] LCID for the conversion
571 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
572 * pbOut [O] Destination
576 * Failure: E_INVALIDARG, if the source value is invalid
577 * DISP_E_OVERFLOW, if the value will not fit in the destination
578 * DISP_E_TYPEMISMATCH, if the type cannot be converted
580 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
582 return _VarUI1FromStr(strIn
, lcid
, dwFlags
, pbOut
);
585 /************************************************************************
586 * VarUI1FromDisp (OLEAUT32.137)
588 * Convert a VT_DISPATCH to a VT_UI1.
592 * lcid [I] LCID for conversion
593 * pbOut [O] Destination
597 * Failure: E_INVALIDARG, if the source value is invalid
598 * DISP_E_OVERFLOW, if the value will not fit in the destination
599 * DISP_E_TYPEMISMATCH, if the type cannot be converted
601 HRESULT WINAPI
VarUI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, BYTE
* pbOut
)
603 return _VarUI1FromDisp(pdispIn
, lcid
, pbOut
);
606 /************************************************************************
607 * VarUI1FromBool (OLEAUT32.138)
609 * Convert a VT_BOOL to a VT_UI1.
613 * pbOut [O] Destination
618 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
620 return _VarUI1FromBool(boolIn
, pbOut
);
623 /************************************************************************
624 * VarUI1FromI1 (OLEAUT32.237)
626 * Convert a VT_I1 to a VT_UI1.
630 * pbOut [O] Destination
634 * Failure: E_INVALIDARG, if the source value is invalid
635 * DISP_E_OVERFLOW, if the value will not fit in the destination
637 HRESULT WINAPI
VarUI1FromI1(signed char cIn
, BYTE
* pbOut
)
639 return _VarUI1FromI1(cIn
, pbOut
);
642 /************************************************************************
643 * VarUI1FromUI2 (OLEAUT32.238)
645 * Convert a VT_UI2 to a VT_UI1.
649 * pbOut [O] Destination
653 * Failure: E_INVALIDARG, if the source value is invalid
654 * DISP_E_OVERFLOW, if the value will not fit in the destination
656 HRESULT WINAPI
VarUI1FromUI2(USHORT usIn
, BYTE
* pbOut
)
658 return _VarUI1FromUI2(usIn
, pbOut
);
661 /************************************************************************
662 * VarUI1FromUI4 (OLEAUT32.239)
664 * Convert a VT_UI4 to a VT_UI1.
668 * pbOut [O] Destination
672 * Failure: E_INVALIDARG, if the source value is invalid
673 * DISP_E_OVERFLOW, if the value will not fit in the destination
675 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
677 return _VarUI1FromUI4(ulIn
, pbOut
);
680 /************************************************************************
681 * VarUI1FromDec (OLEAUT32.240)
683 * Convert a VT_DECIMAL to a VT_UI1.
687 * pbOut [O] Destination
691 * Failure: E_INVALIDARG, if the source value is invalid
692 * DISP_E_OVERFLOW, if the value will not fit in the destination
694 HRESULT WINAPI
VarUI1FromDec(DECIMAL
*pdecIn
, BYTE
* pbOut
)
699 hRet
= _VarI8FromDec(pdecIn
, &i64
);
702 hRet
= _VarUI1FromI8(i64
, pbOut
);
706 /************************************************************************
707 * VarUI1FromI8 (OLEAUT32.372)
709 * Convert a VT_I8 to a VT_UI1.
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
720 HRESULT WINAPI
VarUI1FromI8(LONG64 llIn
, BYTE
* pbOut
)
722 return _VarUI1FromI8(llIn
, pbOut
);
725 /************************************************************************
726 * VarUI1FromUI8 (OLEAUT32.373)
728 * Convert a VT_UI8 to a VT_UI1.
732 * pbOut [O] Destination
736 * Failure: E_INVALIDARG, if the source value is invalid
737 * DISP_E_OVERFLOW, if the value will not fit in the destination
739 HRESULT WINAPI
VarUI1FromUI8(ULONG64 ullIn
, BYTE
* pbOut
)
741 return _VarUI1FromUI8(ullIn
, pbOut
);
748 /************************************************************************
749 * VarI2FromUI1 (OLEAUT32.48)
751 * Convert a VT_UI2 to a VT_I2.
755 * psOut [O] Destination
760 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, SHORT
* psOut
)
762 return _VarI2FromUI1(bIn
, psOut
);
765 /************************************************************************
766 * VarI2FromI4 (OLEAUT32.49)
768 * Convert a VT_I4 to a VT_I2.
772 * psOut [O] Destination
776 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
778 HRESULT WINAPI
VarI2FromI4(LONG iIn
, SHORT
* psOut
)
780 return _VarI2FromI4(iIn
, psOut
);
783 /************************************************************************
784 * VarI2FromR4 (OLEAUT32.50)
786 * Convert a VT_R4 to a VT_I2.
790 * psOut [O] Destination
794 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
796 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, SHORT
* psOut
)
798 return _VarI2FromR4(fltIn
, psOut
);
801 /************************************************************************
802 * VarI2FromR8 (OLEAUT32.51)
804 * Convert a VT_R8 to a VT_I2.
808 * psOut [O] Destination
812 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
815 * See VarI8FromR8() for details concerning rounding.
817 HRESULT WINAPI
VarI2FromR8(double dblIn
, SHORT
* psOut
)
819 if (dblIn
< (double)I2_MIN
|| dblIn
> (double)I2_MAX
)
820 return DISP_E_OVERFLOW
;
821 OLEAUT32_DutchRound(SHORT
, dblIn
, *psOut
);
825 /************************************************************************
826 * VarI2FromCy (OLEAUT32.52)
828 * Convert a VT_CY to a VT_I2.
832 * psOut [O] Destination
836 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
838 HRESULT WINAPI
VarI2FromCy(CY cyIn
, SHORT
* psOut
)
842 _VarI4FromCy(cyIn
, &i
);
843 return _VarI2FromI4(i
, psOut
);
846 /************************************************************************
847 * VarI2FromDate (OLEAUT32.53)
849 * Convert a VT_DATE to a VT_I2.
853 * psOut [O] Destination
857 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
859 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, SHORT
* psOut
)
861 return _VarI2FromDate(dateIn
, psOut
);
864 /************************************************************************
865 * VarI2FromStr (OLEAUT32.54)
867 * Convert a VT_BSTR to a VT_I2.
871 * lcid [I] LCID for the conversion
872 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
873 * psOut [O] Destination
877 * Failure: E_INVALIDARG, if any parameter is invalid
878 * DISP_E_OVERFLOW, if the value will not fit in the destination
879 * DISP_E_TYPEMISMATCH, if the type cannot be converted
881 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, SHORT
* psOut
)
883 return _VarI2FromStr(strIn
, lcid
, dwFlags
, psOut
);
886 /************************************************************************
887 * VarI2FromDisp (OLEAUT32.55)
889 * Convert a VT_DISPATCH to a VT_I2.
893 * lcid [I] LCID for conversion
894 * psOut [O] Destination
898 * Failure: E_INVALIDARG, if pdispIn is invalid,
899 * DISP_E_OVERFLOW, if the value will not fit in the destination,
900 * DISP_E_TYPEMISMATCH, if the type cannot be converted
902 HRESULT WINAPI
VarI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, SHORT
* psOut
)
904 return _VarI2FromDisp(pdispIn
, lcid
, psOut
);
907 /************************************************************************
908 * VarI2FromBool (OLEAUT32.56)
910 * Convert a VT_BOOL to a VT_I2.
914 * psOut [O] Destination
919 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, SHORT
* psOut
)
921 return _VarI2FromBool(boolIn
, psOut
);
924 /************************************************************************
925 * VarI2FromI1 (OLEAUT32.205)
927 * Convert a VT_I1 to a VT_I2.
931 * psOut [O] Destination
936 HRESULT WINAPI
VarI2FromI1(signed char cIn
, SHORT
* psOut
)
938 return _VarI2FromI1(cIn
, psOut
);
941 /************************************************************************
942 * VarI2FromUI2 (OLEAUT32.206)
944 * Convert a VT_UI2 to a VT_I2.
948 * psOut [O] Destination
952 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
954 HRESULT WINAPI
VarI2FromUI2(USHORT usIn
, SHORT
* psOut
)
956 return _VarI2FromUI2(usIn
, psOut
);
959 /************************************************************************
960 * VarI2FromUI4 (OLEAUT32.207)
962 * Convert a VT_UI4 to a VT_I2.
966 * psOut [O] Destination
970 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
972 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, SHORT
* psOut
)
974 return _VarI2FromUI4(ulIn
, psOut
);
977 /************************************************************************
978 * VarI2FromDec (OLEAUT32.208)
980 * Convert a VT_DECIMAL to a VT_I2.
984 * psOut [O] Destination
988 * Failure: E_INVALIDARG, if the source value is invalid
989 * DISP_E_OVERFLOW, if the value will not fit in the destination
991 HRESULT WINAPI
VarI2FromDec(DECIMAL
*pdecIn
, SHORT
* psOut
)
996 hRet
= _VarI8FromDec(pdecIn
, &i64
);
999 hRet
= _VarI2FromI8(i64
, psOut
);
1003 /************************************************************************
1004 * VarI2FromI8 (OLEAUT32.346)
1006 * Convert a VT_I8 to a VT_I2.
1010 * psOut [O] Destination
1014 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1016 HRESULT WINAPI
VarI2FromI8(LONG64 llIn
, SHORT
* psOut
)
1018 return _VarI2FromI8(llIn
, psOut
);
1021 /************************************************************************
1022 * VarI2FromUI8 (OLEAUT32.347)
1024 * Convert a VT_UI8 to a VT_I2.
1028 * psOut [O] Destination
1032 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1034 HRESULT WINAPI
VarI2FromUI8(ULONG64 ullIn
, SHORT
* psOut
)
1036 return _VarI2FromUI8(ullIn
, psOut
);
1042 /************************************************************************
1043 * VarUI2FromUI1 (OLEAUT32.257)
1045 * Convert a VT_UI1 to a VT_UI2.
1049 * pusOut [O] Destination
1054 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* pusOut
)
1056 return _VarUI2FromUI1(bIn
, pusOut
);
1059 /************************************************************************
1060 * VarUI2FromI2 (OLEAUT32.258)
1062 * Convert a VT_I2 to a VT_UI2.
1066 * pusOut [O] Destination
1070 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1072 HRESULT WINAPI
VarUI2FromI2(SHORT sIn
, USHORT
* pusOut
)
1074 return _VarUI2FromI2(sIn
, pusOut
);
1077 /************************************************************************
1078 * VarUI2FromI4 (OLEAUT32.259)
1080 * Convert a VT_I4 to a VT_UI2.
1084 * pusOut [O] Destination
1088 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1090 HRESULT WINAPI
VarUI2FromI4(LONG iIn
, USHORT
* pusOut
)
1092 return _VarUI2FromI4(iIn
, pusOut
);
1095 /************************************************************************
1096 * VarUI2FromR4 (OLEAUT32.260)
1098 * Convert a VT_R4 to a VT_UI2.
1102 * pusOut [O] Destination
1106 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1108 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* pusOut
)
1110 return _VarUI2FromR4(fltIn
, pusOut
);
1113 /************************************************************************
1114 * VarUI2FromR8 (OLEAUT32.261)
1116 * Convert a VT_R8 to a VT_UI2.
1120 * pusOut [O] Destination
1124 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1127 * See VarI8FromR8() for details concerning rounding.
1129 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* pusOut
)
1131 if (dblIn
< -0.5 || dblIn
> (double)UI2_MAX
)
1132 return DISP_E_OVERFLOW
;
1133 OLEAUT32_DutchRound(USHORT
, dblIn
, *pusOut
);
1137 /************************************************************************
1138 * VarUI2FromDate (OLEAUT32.262)
1140 * Convert a VT_DATE to a VT_UI2.
1144 * pusOut [O] Destination
1148 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1150 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* pusOut
)
1152 return _VarUI2FromDate(dateIn
, pusOut
);
1155 /************************************************************************
1156 * VarUI2FromCy (OLEAUT32.263)
1158 * Convert a VT_CY to a VT_UI2.
1162 * pusOut [O] Destination
1166 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1169 * Negative values >= -5000 will be converted to 0.
1171 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
)
1173 ULONG i
= UI2_MAX
+ 1;
1175 _VarUI4FromCy(cyIn
, &i
);
1176 return _VarUI2FromUI4(i
, pusOut
);
1179 /************************************************************************
1180 * VarUI2FromStr (OLEAUT32.264)
1182 * Convert a VT_BSTR to a VT_UI2.
1186 * lcid [I] LCID for the conversion
1187 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1188 * pusOut [O] Destination
1192 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1193 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1195 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* pusOut
)
1197 return _VarUI2FromStr(strIn
, lcid
, dwFlags
, pusOut
);
1200 /************************************************************************
1201 * VarUI2FromDisp (OLEAUT32.265)
1203 * Convert a VT_DISPATCH to a VT_UI2.
1206 * pdispIn [I] Source
1207 * lcid [I] LCID for conversion
1208 * pusOut [O] Destination
1212 * Failure: E_INVALIDARG, if the source value is invalid
1213 * DISP_E_OVERFLOW, if the value will not fit in the destination
1214 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1216 HRESULT WINAPI
VarUI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, USHORT
* pusOut
)
1218 return _VarUI2FromDisp(pdispIn
, lcid
, pusOut
);
1221 /************************************************************************
1222 * VarUI2FromBool (OLEAUT32.266)
1224 * Convert a VT_BOOL to a VT_UI2.
1228 * pusOut [O] Destination
1233 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* pusOut
)
1235 return _VarUI2FromBool(boolIn
, pusOut
);
1238 /************************************************************************
1239 * VarUI2FromI1 (OLEAUT32.267)
1241 * Convert a VT_I1 to a VT_UI2.
1245 * pusOut [O] Destination
1249 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1251 HRESULT WINAPI
VarUI2FromI1(signed char cIn
, USHORT
* pusOut
)
1253 return _VarUI2FromI1(cIn
, pusOut
);
1256 /************************************************************************
1257 * VarUI2FromUI4 (OLEAUT32.268)
1259 * Convert a VT_UI4 to a VT_UI2.
1263 * pusOut [O] Destination
1267 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1269 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* pusOut
)
1271 return _VarUI2FromUI4(ulIn
, pusOut
);
1274 /************************************************************************
1275 * VarUI2FromDec (OLEAUT32.269)
1277 * Convert a VT_DECIMAL to a VT_UI2.
1281 * pusOut [O] Destination
1285 * Failure: E_INVALIDARG, if the source value is invalid
1286 * DISP_E_OVERFLOW, if the value will not fit in the destination
1288 HRESULT WINAPI
VarUI2FromDec(DECIMAL
*pdecIn
, USHORT
* pusOut
)
1293 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1295 if (SUCCEEDED(hRet
))
1296 hRet
= _VarUI2FromI8(i64
, pusOut
);
1300 /************************************************************************
1301 * VarUI2FromI8 (OLEAUT32.378)
1303 * Convert a VT_I8 to a VT_UI2.
1307 * pusOut [O] Destination
1311 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1313 HRESULT WINAPI
VarUI2FromI8(LONG64 llIn
, USHORT
* pusOut
)
1315 return _VarUI2FromI8(llIn
, pusOut
);
1318 /************************************************************************
1319 * VarUI2FromUI8 (OLEAUT32.379)
1321 * Convert a VT_UI8 to a VT_UI2.
1325 * pusOut [O] Destination
1329 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1331 HRESULT WINAPI
VarUI2FromUI8(ULONG64 ullIn
, USHORT
* pusOut
)
1333 return _VarUI2FromUI8(ullIn
, pusOut
);
1339 /************************************************************************
1340 * VarI4FromUI1 (OLEAUT32.58)
1342 * Convert a VT_UI1 to a VT_I4.
1346 * piOut [O] Destination
1351 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
*piOut
)
1353 return _VarI4FromUI1(bIn
, piOut
);
1356 /************************************************************************
1357 * VarI4FromI2 (OLEAUT32.59)
1359 * Convert a VT_I2 to a VT_I4.
1363 * piOut [O] Destination
1367 * Failure: E_INVALIDARG, if the source value is invalid
1368 * DISP_E_OVERFLOW, if the value will not fit in the destination
1370 HRESULT WINAPI
VarI4FromI2(SHORT sIn
, LONG
*piOut
)
1372 return _VarI4FromI2(sIn
, piOut
);
1375 /************************************************************************
1376 * VarI4FromR4 (OLEAUT32.60)
1378 * Convert a VT_R4 to a VT_I4.
1382 * piOut [O] Destination
1386 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1388 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
*piOut
)
1390 return _VarI4FromR4(fltIn
, piOut
);
1393 /************************************************************************
1394 * VarI4FromR8 (OLEAUT32.61)
1396 * Convert a VT_R8 to a VT_I4.
1400 * piOut [O] Destination
1404 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1407 * See VarI8FromR8() for details concerning rounding.
1409 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
*piOut
)
1411 if (dblIn
< (double)I4_MIN
|| dblIn
> (double)I4_MAX
)
1412 return DISP_E_OVERFLOW
;
1413 OLEAUT32_DutchRound(LONG
, dblIn
, *piOut
);
1417 /************************************************************************
1418 * VarI4FromCy (OLEAUT32.62)
1420 * Convert a VT_CY to a VT_I4.
1424 * piOut [O] Destination
1428 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1430 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
*piOut
)
1432 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1433 return _VarI4FromR8(d
, piOut
);
1436 /************************************************************************
1437 * VarI4FromDate (OLEAUT32.63)
1439 * Convert a VT_DATE to a VT_I4.
1443 * piOut [O] Destination
1447 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1449 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
*piOut
)
1451 return _VarI4FromDate(dateIn
, piOut
);
1454 /************************************************************************
1455 * VarI4FromStr (OLEAUT32.64)
1457 * Convert a VT_BSTR to a VT_I4.
1461 * lcid [I] LCID for the conversion
1462 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1463 * piOut [O] Destination
1467 * Failure: E_INVALIDARG, if any parameter is invalid
1468 * DISP_E_OVERFLOW, if the value will not fit in the destination
1469 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1471 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
*piOut
)
1473 return _VarI4FromStr(strIn
, lcid
, dwFlags
, piOut
);
1476 /************************************************************************
1477 * VarI4FromDisp (OLEAUT32.65)
1479 * Convert a VT_DISPATCH to a VT_I4.
1482 * pdispIn [I] Source
1483 * lcid [I] LCID for conversion
1484 * piOut [O] Destination
1488 * Failure: E_INVALIDARG, if the source value is invalid
1489 * DISP_E_OVERFLOW, if the value will not fit in the destination
1490 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1492 HRESULT WINAPI
VarI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG
*piOut
)
1494 return _VarI4FromDisp(pdispIn
, lcid
, piOut
);
1497 /************************************************************************
1498 * VarI4FromBool (OLEAUT32.66)
1500 * Convert a VT_BOOL to a VT_I4.
1504 * piOut [O] Destination
1509 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
*piOut
)
1511 return _VarI4FromBool(boolIn
, piOut
);
1514 /************************************************************************
1515 * VarI4FromI1 (OLEAUT32.209)
1517 * Convert a VT_I4 to a VT_I4.
1521 * piOut [O] Destination
1526 HRESULT WINAPI
VarI4FromI1(signed char cIn
, LONG
*piOut
)
1528 return _VarI4FromI1(cIn
, piOut
);
1531 /************************************************************************
1532 * VarI4FromUI2 (OLEAUT32.210)
1534 * Convert a VT_UI2 to a VT_I4.
1538 * piOut [O] Destination
1543 HRESULT WINAPI
VarI4FromUI2(USHORT usIn
, LONG
*piOut
)
1545 return _VarI4FromUI2(usIn
, piOut
);
1548 /************************************************************************
1549 * VarI4FromUI4 (OLEAUT32.211)
1551 * Convert a VT_UI4 to a VT_I4.
1555 * piOut [O] Destination
1559 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1561 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
*piOut
)
1563 return _VarI4FromUI4(ulIn
, piOut
);
1566 /************************************************************************
1567 * VarI4FromDec (OLEAUT32.212)
1569 * Convert a VT_DECIMAL to a VT_I4.
1573 * piOut [O] Destination
1577 * Failure: E_INVALIDARG, if pdecIn is invalid
1578 * DISP_E_OVERFLOW, if the value will not fit in the destination
1580 HRESULT WINAPI
VarI4FromDec(DECIMAL
*pdecIn
, LONG
*piOut
)
1585 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1587 if (SUCCEEDED(hRet
))
1588 hRet
= _VarI4FromI8(i64
, piOut
);
1592 /************************************************************************
1593 * VarI4FromI8 (OLEAUT32.348)
1595 * Convert a VT_I8 to a VT_I4.
1599 * piOut [O] Destination
1603 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1605 HRESULT WINAPI
VarI4FromI8(LONG64 llIn
, LONG
*piOut
)
1607 return _VarI4FromI8(llIn
, piOut
);
1610 /************************************************************************
1611 * VarI4FromUI8 (OLEAUT32.349)
1613 * Convert a VT_UI8 to a VT_I4.
1617 * piOut [O] Destination
1621 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1623 HRESULT WINAPI
VarI4FromUI8(ULONG64 ullIn
, LONG
*piOut
)
1625 return _VarI4FromUI8(ullIn
, piOut
);
1631 /************************************************************************
1632 * VarUI4FromUI1 (OLEAUT32.270)
1634 * Convert a VT_UI1 to a VT_UI4.
1638 * pulOut [O] Destination
1643 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
*pulOut
)
1645 return _VarUI4FromUI1(bIn
, pulOut
);
1648 /************************************************************************
1649 * VarUI4FromI2 (OLEAUT32.271)
1651 * Convert a VT_I2 to a VT_UI4.
1655 * pulOut [O] Destination
1659 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1661 HRESULT WINAPI
VarUI4FromI2(SHORT sIn
, ULONG
*pulOut
)
1663 return _VarUI4FromI2(sIn
, pulOut
);
1666 /************************************************************************
1667 * VarUI4FromI4 (OLEAUT32.272)
1669 * Convert a VT_I4 to a VT_UI4.
1673 * pulOut [O] Destination
1677 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1679 HRESULT WINAPI
VarUI4FromI4(LONG iIn
, ULONG
*pulOut
)
1681 return _VarUI4FromI4(iIn
, pulOut
);
1684 /************************************************************************
1685 * VarUI4FromR4 (OLEAUT32.273)
1687 * Convert a VT_R4 to a VT_UI4.
1691 * pulOut [O] Destination
1695 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1697 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
*pulOut
)
1699 return _VarUI4FromR4(fltIn
, pulOut
);
1702 /************************************************************************
1703 * VarUI4FromR8 (OLEAUT32.274)
1705 * Convert a VT_R8 to a VT_UI4.
1709 * pulOut [O] Destination
1713 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1716 * See VarI8FromR8() for details concerning rounding.
1718 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
*pulOut
)
1720 if (dblIn
< -0.5 || dblIn
> (double)UI4_MAX
)
1721 return DISP_E_OVERFLOW
;
1722 OLEAUT32_DutchRound(ULONG
, dblIn
, *pulOut
);
1726 /************************************************************************
1727 * VarUI4FromDate (OLEAUT32.275)
1729 * Convert a VT_DATE to a VT_UI4.
1733 * pulOut [O] Destination
1737 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1739 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
*pulOut
)
1741 return _VarUI4FromDate(dateIn
, pulOut
);
1744 /************************************************************************
1745 * VarUI4FromCy (OLEAUT32.276)
1747 * Convert a VT_CY to a VT_UI4.
1751 * pulOut [O] Destination
1755 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1757 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
*pulOut
)
1759 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1760 return _VarUI4FromR8(d
, pulOut
);
1763 /************************************************************************
1764 * VarUI4FromStr (OLEAUT32.277)
1766 * Convert a VT_BSTR to a VT_UI4.
1770 * lcid [I] LCID for the conversion
1771 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1772 * pulOut [O] Destination
1776 * Failure: E_INVALIDARG, if any parameter is invalid
1777 * DISP_E_OVERFLOW, if the value will not fit in the destination
1778 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1780 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
*pulOut
)
1782 return _VarUI4FromStr(strIn
, lcid
, dwFlags
, pulOut
);
1785 /************************************************************************
1786 * VarUI4FromDisp (OLEAUT32.278)
1788 * Convert a VT_DISPATCH to a VT_UI4.
1791 * pdispIn [I] Source
1792 * lcid [I] LCID for conversion
1793 * pulOut [O] Destination
1797 * Failure: E_INVALIDARG, if the source value is invalid
1798 * DISP_E_OVERFLOW, if the value will not fit in the destination
1799 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1801 HRESULT WINAPI
VarUI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG
*pulOut
)
1803 return _VarUI4FromDisp(pdispIn
, lcid
, pulOut
);
1806 /************************************************************************
1807 * VarUI4FromBool (OLEAUT32.279)
1809 * Convert a VT_BOOL to a VT_UI4.
1813 * pulOut [O] Destination
1818 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
*pulOut
)
1820 return _VarUI4FromBool(boolIn
, pulOut
);
1823 /************************************************************************
1824 * VarUI4FromI1 (OLEAUT32.280)
1826 * Convert a VT_I1 to a VT_UI4.
1830 * pulOut [O] Destination
1834 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1836 HRESULT WINAPI
VarUI4FromI1(signed char cIn
, ULONG
*pulOut
)
1838 return _VarUI4FromI1(cIn
, pulOut
);
1841 /************************************************************************
1842 * VarUI4FromUI2 (OLEAUT32.281)
1844 * Convert a VT_UI2 to a VT_UI4.
1848 * pulOut [O] Destination
1853 HRESULT WINAPI
VarUI4FromUI2(USHORT usIn
, ULONG
*pulOut
)
1855 return _VarUI4FromUI2(usIn
, pulOut
);
1858 /************************************************************************
1859 * VarUI4FromDec (OLEAUT32.282)
1861 * Convert a VT_DECIMAL to a VT_UI4.
1865 * pulOut [O] Destination
1869 * Failure: E_INVALIDARG, if pdecIn is invalid
1870 * DISP_E_OVERFLOW, if the value will not fit in the destination
1872 HRESULT WINAPI
VarUI4FromDec(DECIMAL
*pdecIn
, ULONG
*pulOut
)
1877 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1879 if (SUCCEEDED(hRet
))
1880 hRet
= _VarUI4FromI8(i64
, pulOut
);
1884 /************************************************************************
1885 * VarUI4FromI8 (OLEAUT32.425)
1887 * Convert a VT_I8 to a VT_UI4.
1891 * pulOut [O] Destination
1895 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1897 HRESULT WINAPI
VarUI4FromI8(LONG64 llIn
, ULONG
*pulOut
)
1899 return _VarUI4FromI8(llIn
, pulOut
);
1902 /************************************************************************
1903 * VarUI4FromUI8 (OLEAUT32.426)
1905 * Convert a VT_UI8 to a VT_UI4.
1909 * pulOut [O] Destination
1913 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1915 HRESULT WINAPI
VarUI4FromUI8(ULONG64 ullIn
, ULONG
*pulOut
)
1917 return _VarUI4FromUI8(ullIn
, pulOut
);
1923 /************************************************************************
1924 * VarI8FromUI1 (OLEAUT32.333)
1926 * Convert a VT_UI1 to a VT_I8.
1930 * pi64Out [O] Destination
1935 HRESULT WINAPI
VarI8FromUI1(BYTE bIn
, LONG64
* pi64Out
)
1937 return _VarI8FromUI1(bIn
, pi64Out
);
1941 /************************************************************************
1942 * VarI8FromI2 (OLEAUT32.334)
1944 * Convert a VT_I2 to a VT_I8.
1948 * pi64Out [O] Destination
1953 HRESULT WINAPI
VarI8FromI2(SHORT sIn
, LONG64
* pi64Out
)
1955 return _VarI8FromI2(sIn
, pi64Out
);
1958 /************************************************************************
1959 * VarI8FromR4 (OLEAUT32.335)
1961 * Convert a VT_R4 to a VT_I8.
1965 * pi64Out [O] Destination
1969 * Failure: E_INVALIDARG, if the source value is invalid
1970 * DISP_E_OVERFLOW, if the value will not fit in the destination
1972 HRESULT WINAPI
VarI8FromR4(FLOAT fltIn
, LONG64
* pi64Out
)
1974 return _VarI8FromR4(fltIn
, pi64Out
);
1977 /************************************************************************
1978 * VarI8FromR8 (OLEAUT32.336)
1980 * Convert a VT_R8 to a VT_I8.
1984 * pi64Out [O] Destination
1988 * Failure: E_INVALIDARG, if the source value is invalid
1989 * DISP_E_OVERFLOW, if the value will not fit in the destination
1992 * Only values that fit into 63 bits are accepted. Due to rounding issues,
1993 * very high or low values will not be accurately converted.
1995 * Numbers are rounded using Dutch rounding, as follows:
1997 *| Fractional Part Sign Direction Example
1998 *| --------------- ---- --------- -------
1999 *| < 0.5 + Down 0.4 -> 0.0
2000 *| < 0.5 - Up -0.4 -> 0.0
2001 *| > 0.5 + Up 0.6 -> 1.0
2002 *| < 0.5 - Up -0.6 -> -1.0
2003 *| = 0.5 + Up/Down Down if even, Up if odd
2004 *| = 0.5 - Up/Down Up if even, Down if odd
2006 * This system is often used in supermarkets.
2008 HRESULT WINAPI
VarI8FromR8(double dblIn
, LONG64
* pi64Out
)
2010 if ( dblIn
< -4611686018427387904.0 || dblIn
>= 4611686018427387904.0)
2011 return DISP_E_OVERFLOW
;
2012 OLEAUT32_DutchRound(LONG64
, dblIn
, *pi64Out
);
2016 /************************************************************************
2017 * VarI8FromCy (OLEAUT32.337)
2019 * Convert a VT_CY to a VT_I8.
2023 * pi64Out [O] Destination
2029 * All negative numbers are rounded down by 1, including those that are
2030 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2031 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2034 HRESULT WINAPI
VarI8FromCy(CY cyIn
, LONG64
* pi64Out
)
2036 *pi64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2039 (*pi64Out
)--; /* Mimic Win32 bug */
2042 cyIn
.int64
-= *pi64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2044 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pi64Out
& 0x1)))
2050 /************************************************************************
2051 * VarI8FromDate (OLEAUT32.338)
2053 * Convert a VT_DATE to a VT_I8.
2057 * pi64Out [O] Destination
2061 * Failure: E_INVALIDARG, if the source value is invalid
2062 * DISP_E_OVERFLOW, if the value will not fit in the destination
2063 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2065 HRESULT WINAPI
VarI8FromDate(DATE dateIn
, LONG64
* pi64Out
)
2067 return _VarI8FromDate(dateIn
, pi64Out
);
2070 /************************************************************************
2071 * VarI8FromStr (OLEAUT32.339)
2073 * Convert a VT_BSTR to a VT_I8.
2077 * lcid [I] LCID for the conversion
2078 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2079 * pi64Out [O] Destination
2083 * Failure: E_INVALIDARG, if the source value is invalid
2084 * DISP_E_OVERFLOW, if the value will not fit in the destination
2085 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2087 HRESULT WINAPI
VarI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG64
* pi64Out
)
2089 return _VarI8FromStr(strIn
, lcid
, dwFlags
, pi64Out
);
2092 /************************************************************************
2093 * VarI8FromDisp (OLEAUT32.340)
2095 * Convert a VT_DISPATCH to a VT_I8.
2098 * pdispIn [I] Source
2099 * lcid [I] LCID for conversion
2100 * pi64Out [O] Destination
2104 * Failure: E_INVALIDARG, if the source value is invalid
2105 * DISP_E_OVERFLOW, if the value will not fit in the destination
2106 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2108 HRESULT WINAPI
VarI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG64
* pi64Out
)
2110 return _VarI8FromDisp(pdispIn
, lcid
, pi64Out
);
2113 /************************************************************************
2114 * VarI8FromBool (OLEAUT32.341)
2116 * Convert a VT_BOOL to a VT_I8.
2120 * pi64Out [O] Destination
2125 HRESULT WINAPI
VarI8FromBool(VARIANT_BOOL boolIn
, LONG64
* pi64Out
)
2127 return _VarI8FromBool(boolIn
, pi64Out
);
2130 /************************************************************************
2131 * VarI8FromI1 (OLEAUT32.342)
2133 * Convert a VT_I1 to a VT_I8.
2137 * pi64Out [O] Destination
2142 HRESULT WINAPI
VarI8FromI1(signed char cIn
, LONG64
* pi64Out
)
2144 return _VarI8FromI1(cIn
, pi64Out
);
2147 /************************************************************************
2148 * VarI8FromUI2 (OLEAUT32.343)
2150 * Convert a VT_UI2 to a VT_I8.
2154 * pi64Out [O] Destination
2159 HRESULT WINAPI
VarI8FromUI2(USHORT usIn
, LONG64
* pi64Out
)
2161 return _VarI8FromUI2(usIn
, pi64Out
);
2164 /************************************************************************
2165 * VarI8FromUI4 (OLEAUT32.344)
2167 * Convert a VT_UI4 to a VT_I8.
2171 * pi64Out [O] Destination
2176 HRESULT WINAPI
VarI8FromUI4(ULONG ulIn
, LONG64
* pi64Out
)
2178 return _VarI8FromUI4(ulIn
, pi64Out
);
2181 /************************************************************************
2182 * VarI8FromDec (OLEAUT32.345)
2184 * Convert a VT_DECIMAL to a VT_I8.
2188 * pi64Out [O] Destination
2192 * Failure: E_INVALIDARG, if the source value is invalid
2193 * DISP_E_OVERFLOW, if the value will not fit in the destination
2195 HRESULT WINAPI
VarI8FromDec(DECIMAL
*pdecIn
, LONG64
* pi64Out
)
2197 if (!DEC_SCALE(pdecIn
))
2199 /* This decimal is just a 96 bit integer */
2200 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2201 return E_INVALIDARG
;
2203 if (DEC_HI32(pdecIn
) || DEC_MID32(pdecIn
) & 0x80000000)
2204 return DISP_E_OVERFLOW
;
2206 if (DEC_SIGN(pdecIn
))
2207 *pi64Out
= -DEC_LO64(pdecIn
);
2209 *pi64Out
= DEC_LO64(pdecIn
);
2214 /* Decimal contains a floating point number */
2218 hRet
= _VarR8FromDec(pdecIn
, &dbl
);
2219 if (SUCCEEDED(hRet
))
2220 hRet
= VarI8FromR8(dbl
, pi64Out
);
2225 /************************************************************************
2226 * VarI8FromUI8 (OLEAUT32.427)
2228 * Convert a VT_UI8 to a VT_I8.
2232 * pi64Out [O] Destination
2236 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2238 HRESULT WINAPI
VarI8FromUI8(ULONG64 ullIn
, LONG64
* pi64Out
)
2240 return _VarI8FromUI8(ullIn
, pi64Out
);
2246 /************************************************************************
2247 * VarUI8FromI8 (OLEAUT32.428)
2249 * Convert a VT_I8 to a VT_UI8.
2253 * pui64Out [O] Destination
2257 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2259 HRESULT WINAPI
VarUI8FromI8(LONG64 llIn
, ULONG64
* pui64Out
)
2261 return _VarUI8FromI8(llIn
, pui64Out
);
2264 /************************************************************************
2265 * VarUI8FromUI1 (OLEAUT32.429)
2267 * Convert a VT_UI1 to a VT_UI8.
2271 * pui64Out [O] Destination
2276 HRESULT WINAPI
VarUI8FromUI1(BYTE bIn
, ULONG64
* pui64Out
)
2278 return _VarUI8FromUI1(bIn
, pui64Out
);
2281 /************************************************************************
2282 * VarUI8FromI2 (OLEAUT32.430)
2284 * Convert a VT_I2 to a VT_UI8.
2288 * pui64Out [O] Destination
2293 HRESULT WINAPI
VarUI8FromI2(SHORT sIn
, ULONG64
* pui64Out
)
2295 return _VarUI8FromI2(sIn
, pui64Out
);
2298 /************************************************************************
2299 * VarUI8FromR4 (OLEAUT32.431)
2301 * Convert a VT_R4 to a VT_UI8.
2305 * pui64Out [O] Destination
2309 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2311 HRESULT WINAPI
VarUI8FromR4(FLOAT fltIn
, ULONG64
* pui64Out
)
2313 return _VarUI8FromR4(fltIn
, pui64Out
);
2316 /************************************************************************
2317 * VarUI8FromR8 (OLEAUT32.432)
2319 * Convert a VT_R8 to a VT_UI8.
2323 * pui64Out [O] Destination
2327 * Failure: E_INVALIDARG, if the source value is invalid
2328 * DISP_E_OVERFLOW, if the value will not fit in the destination
2331 * See VarI8FromR8() for details concerning rounding.
2333 HRESULT WINAPI
VarUI8FromR8(double dblIn
, ULONG64
* pui64Out
)
2335 if (dblIn
< -0.5 || dblIn
> 1.844674407370955e19
)
2336 return DISP_E_OVERFLOW
;
2337 OLEAUT32_DutchRound(ULONG64
, dblIn
, *pui64Out
);
2341 /************************************************************************
2342 * VarUI8FromCy (OLEAUT32.433)
2344 * Convert a VT_CY to a VT_UI8.
2348 * pui64Out [O] Destination
2352 * Failure: E_INVALIDARG, if the source value is invalid
2353 * DISP_E_OVERFLOW, if the value will not fit in the destination
2356 * Negative values >= -5000 will be converted to 0.
2358 HRESULT WINAPI
VarUI8FromCy(CY cyIn
, ULONG64
* pui64Out
)
2362 if (cyIn
.int64
< -CY_HALF
)
2363 return DISP_E_OVERFLOW
;
2368 *pui64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2370 cyIn
.int64
-= *pui64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2372 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pui64Out
& 0x1)))
2378 /************************************************************************
2379 * VarUI8FromDate (OLEAUT32.434)
2381 * Convert a VT_DATE to a VT_UI8.
2385 * pui64Out [O] Destination
2389 * Failure: E_INVALIDARG, if the source value is invalid
2390 * DISP_E_OVERFLOW, if the value will not fit in the destination
2391 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2393 HRESULT WINAPI
VarUI8FromDate(DATE dateIn
, ULONG64
* pui64Out
)
2395 return _VarUI8FromDate(dateIn
, pui64Out
);
2398 /************************************************************************
2399 * VarUI8FromStr (OLEAUT32.435)
2401 * Convert a VT_BSTR to a VT_UI8.
2405 * lcid [I] LCID for the conversion
2406 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2407 * pui64Out [O] Destination
2411 * Failure: E_INVALIDARG, if the source value is invalid
2412 * DISP_E_OVERFLOW, if the value will not fit in the destination
2413 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2415 HRESULT WINAPI
VarUI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG64
* pui64Out
)
2417 return _VarUI8FromStr(strIn
, lcid
, dwFlags
, pui64Out
);
2420 /************************************************************************
2421 * VarUI8FromDisp (OLEAUT32.436)
2423 * Convert a VT_DISPATCH to a VT_UI8.
2426 * pdispIn [I] Source
2427 * lcid [I] LCID for conversion
2428 * pui64Out [O] Destination
2432 * Failure: E_INVALIDARG, if the source value is invalid
2433 * DISP_E_OVERFLOW, if the value will not fit in the destination
2434 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2436 HRESULT WINAPI
VarUI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG64
* pui64Out
)
2438 return _VarUI8FromDisp(pdispIn
, lcid
, pui64Out
);
2441 /************************************************************************
2442 * VarUI8FromBool (OLEAUT32.437)
2444 * Convert a VT_BOOL to a VT_UI8.
2448 * pui64Out [O] Destination
2452 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2454 HRESULT WINAPI
VarUI8FromBool(VARIANT_BOOL boolIn
, ULONG64
* pui64Out
)
2456 return _VarUI8FromBool(boolIn
, pui64Out
);
2458 /************************************************************************
2459 * VarUI8FromI1 (OLEAUT32.438)
2461 * Convert a VT_I1 to a VT_UI8.
2465 * pui64Out [O] Destination
2469 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2471 HRESULT WINAPI
VarUI8FromI1(signed char cIn
, ULONG64
* pui64Out
)
2473 return _VarUI8FromI1(cIn
, pui64Out
);
2476 /************************************************************************
2477 * VarUI8FromUI2 (OLEAUT32.439)
2479 * Convert a VT_UI2 to a VT_UI8.
2483 * pui64Out [O] Destination
2488 HRESULT WINAPI
VarUI8FromUI2(USHORT usIn
, ULONG64
* pui64Out
)
2490 return _VarUI8FromUI2(usIn
, pui64Out
);
2493 /************************************************************************
2494 * VarUI8FromUI4 (OLEAUT32.440)
2496 * Convert a VT_UI4 to a VT_UI8.
2500 * pui64Out [O] Destination
2505 HRESULT WINAPI
VarUI8FromUI4(ULONG ulIn
, ULONG64
* pui64Out
)
2507 return _VarUI8FromUI4(ulIn
, pui64Out
);
2510 /************************************************************************
2511 * VarUI8FromDec (OLEAUT32.441)
2513 * Convert a VT_DECIMAL to a VT_UI8.
2517 * pui64Out [O] Destination
2521 * Failure: E_INVALIDARG, if the source value is invalid
2522 * DISP_E_OVERFLOW, if the value will not fit in the destination
2525 * Under native Win32, if the source value has a scale of 0, its sign is
2526 * ignored, i.e. this function takes the absolute value rather than fail
2527 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2528 * (use VarAbs() on pDecIn first if you really want this behaviour).
2530 HRESULT WINAPI
VarUI8FromDec(DECIMAL
*pdecIn
, ULONG64
* pui64Out
)
2532 if (!DEC_SCALE(pdecIn
))
2534 /* This decimal is just a 96 bit integer */
2535 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2536 return E_INVALIDARG
;
2538 if (DEC_HI32(pdecIn
))
2539 return DISP_E_OVERFLOW
;
2541 if (DEC_SIGN(pdecIn
))
2543 WARN("Sign would be ignored under Win32!\n");
2544 return DISP_E_OVERFLOW
;
2547 *pui64Out
= DEC_LO64(pdecIn
);
2552 /* Decimal contains a floating point number */
2556 hRet
= _VarR8FromDec(pdecIn
, &dbl
);
2557 if (SUCCEEDED(hRet
))
2558 hRet
= VarUI8FromR8(dbl
, pui64Out
);
2566 /************************************************************************
2567 * VarR4FromUI1 (OLEAUT32.68)
2569 * Convert a VT_UI1 to a VT_R4.
2573 * pFltOut [O] Destination
2578 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, float *pFltOut
)
2580 return _VarR4FromUI1(bIn
, pFltOut
);
2583 /************************************************************************
2584 * VarR4FromI2 (OLEAUT32.69)
2586 * Convert a VT_I2 to a VT_R4.
2590 * pFltOut [O] Destination
2595 HRESULT WINAPI
VarR4FromI2(SHORT sIn
, float *pFltOut
)
2597 return _VarR4FromI2(sIn
, pFltOut
);
2600 /************************************************************************
2601 * VarR4FromI4 (OLEAUT32.70)
2603 * Convert a VT_I4 to a VT_R4.
2607 * pFltOut [O] Destination
2612 HRESULT WINAPI
VarR4FromI4(LONG lIn
, float *pFltOut
)
2614 return _VarR4FromI4(lIn
, pFltOut
);
2617 /************************************************************************
2618 * VarR4FromR8 (OLEAUT32.71)
2620 * Convert a VT_R8 to a VT_R4.
2624 * pFltOut [O] Destination
2628 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2630 HRESULT WINAPI
VarR4FromR8(double dblIn
, float *pFltOut
)
2632 return _VarR4FromR8(dblIn
, pFltOut
);
2635 /************************************************************************
2636 * VarR4FromCy (OLEAUT32.72)
2638 * Convert a VT_CY to a VT_R4.
2642 * pFltOut [O] Destination
2647 HRESULT WINAPI
VarR4FromCy(CY cyIn
, float *pFltOut
)
2649 return _VarR4FromCy(cyIn
, pFltOut
);
2652 /************************************************************************
2653 * VarR4FromDate (OLEAUT32.73)
2655 * Convert a VT_DATE to a VT_R4.
2659 * pFltOut [O] Destination
2663 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2665 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, float *pFltOut
)
2667 return _VarR4FromDate(dateIn
, pFltOut
);
2670 /************************************************************************
2671 * VarR4FromStr (OLEAUT32.74)
2673 * Convert a VT_BSTR to a VT_R4.
2677 * lcid [I] LCID for the conversion
2678 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2679 * pFltOut [O] Destination
2683 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2684 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2686 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, float *pFltOut
)
2688 return _VarR4FromStr(strIn
, lcid
, dwFlags
, pFltOut
);
2691 /************************************************************************
2692 * VarR4FromDisp (OLEAUT32.75)
2694 * Convert a VT_DISPATCH to a VT_R4.
2697 * pdispIn [I] Source
2698 * lcid [I] LCID for conversion
2699 * pFltOut [O] Destination
2703 * Failure: E_INVALIDARG, if the source value is invalid
2704 * DISP_E_OVERFLOW, if the value will not fit in the destination
2705 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2707 HRESULT WINAPI
VarR4FromDisp(IDispatch
* pdispIn
, LCID lcid
, float *pFltOut
)
2709 return _VarR4FromDisp(pdispIn
, lcid
, pFltOut
);
2712 /************************************************************************
2713 * VarR4FromBool (OLEAUT32.76)
2715 * Convert a VT_BOOL to a VT_R4.
2719 * pFltOut [O] Destination
2724 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, float *pFltOut
)
2726 return _VarR4FromBool(boolIn
, pFltOut
);
2729 /************************************************************************
2730 * VarR4FromI1 (OLEAUT32.213)
2732 * Convert a VT_I1 to a VT_R4.
2736 * pFltOut [O] Destination
2740 * Failure: E_INVALIDARG, if the source value is invalid
2741 * DISP_E_OVERFLOW, if the value will not fit in the destination
2742 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2744 HRESULT WINAPI
VarR4FromI1(signed char cIn
, float *pFltOut
)
2746 return _VarR4FromI1(cIn
, pFltOut
);
2749 /************************************************************************
2750 * VarR4FromUI2 (OLEAUT32.214)
2752 * Convert a VT_UI2 to a VT_R4.
2756 * pFltOut [O] Destination
2760 * Failure: E_INVALIDARG, if the source value is invalid
2761 * DISP_E_OVERFLOW, if the value will not fit in the destination
2762 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2764 HRESULT WINAPI
VarR4FromUI2(USHORT usIn
, float *pFltOut
)
2766 return _VarR4FromUI2(usIn
, pFltOut
);
2769 /************************************************************************
2770 * VarR4FromUI4 (OLEAUT32.215)
2772 * Convert a VT_UI4 to a VT_R4.
2776 * pFltOut [O] Destination
2780 * Failure: E_INVALIDARG, if the source value is invalid
2781 * DISP_E_OVERFLOW, if the value will not fit in the destination
2782 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2784 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, float *pFltOut
)
2786 return _VarR4FromUI4(ulIn
, pFltOut
);
2789 /************************************************************************
2790 * VarR4FromDec (OLEAUT32.216)
2792 * Convert a VT_DECIMAL to a VT_R4.
2796 * pFltOut [O] Destination
2800 * Failure: E_INVALIDARG, if the source value is invalid.
2802 HRESULT WINAPI
VarR4FromDec(DECIMAL
* pDecIn
, float *pFltOut
)
2804 BYTE scale
= DEC_SCALE(pDecIn
);
2808 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
2809 return E_INVALIDARG
;
2814 if (DEC_SIGN(pDecIn
))
2817 if (DEC_HI32(pDecIn
))
2819 highPart
= (double)DEC_HI32(pDecIn
) / (double)divisor
;
2825 *pFltOut
= (double)DEC_LO64(pDecIn
) / (double)divisor
+ highPart
;
2829 /************************************************************************
2830 * VarR4FromI8 (OLEAUT32.360)
2832 * Convert a VT_I8 to a VT_R4.
2836 * pFltOut [O] Destination
2841 HRESULT WINAPI
VarR4FromI8(LONG64 llIn
, float *pFltOut
)
2843 return _VarR4FromI8(llIn
, pFltOut
);
2846 /************************************************************************
2847 * VarR4FromUI8 (OLEAUT32.361)
2849 * Convert a VT_UI8 to a VT_R4.
2853 * pFltOut [O] Destination
2858 HRESULT WINAPI
VarR4FromUI8(ULONG64 ullIn
, float *pFltOut
)
2860 return _VarR4FromUI8(ullIn
, pFltOut
);
2863 /************************************************************************
2864 * VarR4CmpR8 (OLEAUT32.316)
2866 * Compare a VT_R4 to a VT_R8.
2869 * fltLeft [I] Source
2870 * dblRight [I] Value to compare
2873 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
2874 * equal to or greater than dblRight respectively.
2876 HRESULT WINAPI
VarR4CmpR8(float fltLeft
, double dblRight
)
2878 if (fltLeft
< dblRight
)
2880 else if (fltLeft
> dblRight
)
2888 /************************************************************************
2889 * VarR8FromUI1 (OLEAUT32.78)
2891 * Convert a VT_UI1 to a VT_R8.
2895 * pDblOut [O] Destination
2900 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double *pDblOut
)
2902 return _VarR8FromUI1(bIn
, pDblOut
);
2905 /************************************************************************
2906 * VarR8FromI2 (OLEAUT32.79)
2908 * Convert a VT_I2 to a VT_R8.
2912 * pDblOut [O] Destination
2917 HRESULT WINAPI
VarR8FromI2(SHORT sIn
, double *pDblOut
)
2919 return _VarR8FromI2(sIn
, pDblOut
);
2922 /************************************************************************
2923 * VarR8FromI4 (OLEAUT32.80)
2925 * Convert a VT_I4 to a VT_R8.
2929 * pDblOut [O] Destination
2934 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double *pDblOut
)
2936 return _VarR8FromI4(lIn
, pDblOut
);
2939 /************************************************************************
2940 * VarR8FromR4 (OLEAUT32.81)
2942 * Convert a VT_R4 to a VT_R8.
2946 * pDblOut [O] Destination
2951 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double *pDblOut
)
2953 return _VarR8FromR4(fltIn
, pDblOut
);
2956 /************************************************************************
2957 * VarR8FromCy (OLEAUT32.82)
2959 * Convert a VT_CY to a VT_R8.
2963 * pDblOut [O] Destination
2968 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double *pDblOut
)
2970 return _VarR8FromCy(cyIn
, pDblOut
);
2973 /************************************************************************
2974 * VarR8FromDate (OLEAUT32.83)
2976 * Convert a VT_DATE to a VT_R8.
2980 * pDblOut [O] Destination
2985 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double *pDblOut
)
2987 return _VarR8FromDate(dateIn
, pDblOut
);
2990 /************************************************************************
2991 * VarR8FromStr (OLEAUT32.84)
2993 * Convert a VT_BSTR to a VT_R8.
2997 * lcid [I] LCID for the conversion
2998 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2999 * pDblOut [O] Destination
3003 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3004 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3006 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double *pDblOut
)
3008 return _VarR8FromStr(strIn
, lcid
, dwFlags
, pDblOut
);
3011 /************************************************************************
3012 * VarR8FromDisp (OLEAUT32.85)
3014 * Convert a VT_DISPATCH to a VT_R8.
3017 * pdispIn [I] Source
3018 * lcid [I] LCID for conversion
3019 * pDblOut [O] Destination
3023 * Failure: E_INVALIDARG, if the source value is invalid
3024 * DISP_E_OVERFLOW, if the value will not fit in the destination
3025 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3027 HRESULT WINAPI
VarR8FromDisp(IDispatch
* pdispIn
, LCID lcid
, double *pDblOut
)
3029 return _VarR8FromDisp(pdispIn
, lcid
, pDblOut
);
3032 /************************************************************************
3033 * VarR8FromBool (OLEAUT32.86)
3035 * Convert a VT_BOOL to a VT_R8.
3039 * pDblOut [O] Destination
3044 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double *pDblOut
)
3046 return _VarR8FromBool(boolIn
, pDblOut
);
3049 /************************************************************************
3050 * VarR8FromI1 (OLEAUT32.217)
3052 * Convert a VT_I1 to a VT_R8.
3056 * pDblOut [O] Destination
3060 * Failure: E_INVALIDARG, if the source value is invalid
3061 * DISP_E_OVERFLOW, if the value will not fit in the destination
3062 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3064 HRESULT WINAPI
VarR8FromI1(signed char cIn
, double *pDblOut
)
3066 return _VarR8FromI1(cIn
, pDblOut
);
3069 /************************************************************************
3070 * VarR8FromUI2 (OLEAUT32.218)
3072 * Convert a VT_UI2 to a VT_R8.
3076 * pDblOut [O] Destination
3080 * Failure: E_INVALIDARG, if the source value is invalid
3081 * DISP_E_OVERFLOW, if the value will not fit in the destination
3082 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3084 HRESULT WINAPI
VarR8FromUI2(USHORT usIn
, double *pDblOut
)
3086 return _VarR8FromUI2(usIn
, pDblOut
);
3089 /************************************************************************
3090 * VarR8FromUI4 (OLEAUT32.219)
3092 * Convert a VT_UI4 to a VT_R8.
3096 * pDblOut [O] Destination
3100 * Failure: E_INVALIDARG, if the source value is invalid
3101 * DISP_E_OVERFLOW, if the value will not fit in the destination
3102 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3104 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double *pDblOut
)
3106 return _VarR8FromUI4(ulIn
, pDblOut
);
3109 /************************************************************************
3110 * VarR8FromDec (OLEAUT32.220)
3112 * Convert a VT_DECIMAL to a VT_R8.
3116 * pDblOut [O] Destination
3120 * Failure: E_INVALIDARG, if the source value is invalid.
3122 HRESULT WINAPI
VarR8FromDec(DECIMAL
* pDecIn
, double *pDblOut
)
3124 BYTE scale
= DEC_SCALE(pDecIn
);
3125 double divisor
= 1.0, highPart
;
3127 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
3128 return E_INVALIDARG
;
3133 if (DEC_SIGN(pDecIn
))
3136 if (DEC_HI32(pDecIn
))
3138 highPart
= (double)DEC_HI32(pDecIn
) / divisor
;
3144 *pDblOut
= (double)DEC_LO64(pDecIn
) / divisor
+ highPart
;
3148 /************************************************************************
3149 * VarR8FromI8 (OLEAUT32.362)
3151 * Convert a VT_I8 to a VT_R8.
3155 * pDblOut [O] Destination
3160 HRESULT WINAPI
VarR8FromI8(LONG64 llIn
, double *pDblOut
)
3162 return _VarR8FromI8(llIn
, pDblOut
);
3165 /************************************************************************
3166 * VarR8FromUI8 (OLEAUT32.363)
3168 * Convert a VT_UI8 to a VT_R8.
3172 * pDblOut [O] Destination
3177 HRESULT WINAPI
VarR8FromUI8(ULONG64 ullIn
, double *pDblOut
)
3179 return _VarR8FromUI8(ullIn
, pDblOut
);
3182 /************************************************************************
3183 * VarR8Pow (OLEAUT32.315)
3185 * Raise a VT_R8 to a power.
3188 * dblLeft [I] Source
3189 * dblPow [I] Power to raise dblLeft by
3190 * pDblOut [O] Destination
3193 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3195 HRESULT WINAPI
VarR8Pow(double dblLeft
, double dblPow
, double *pDblOut
)
3197 *pDblOut
= pow(dblLeft
, dblPow
);
3201 /************************************************************************
3202 * VarR8Round (OLEAUT32.317)
3204 * Round a VT_R8 to a given number of decimal points.
3208 * nDig [I] Number of decimal points to round to
3209 * pDblOut [O] Destination for rounded number
3212 * Success: S_OK. pDblOut is rounded to nDig digits.
3213 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3216 * The native version of this function rounds using the internal
3217 * binary representation of the number. Wine uses the dutch rounding
3218 * convention, so therefore small differences can occur in the value returned.
3219 * MSDN says that you should use your own rounding function if you want
3220 * rounding to be predictable in your application.
3222 HRESULT WINAPI
VarR8Round(double dblIn
, int nDig
, double *pDblOut
)
3224 double scale
, whole
, fract
;
3227 return E_INVALIDARG
;
3229 scale
= pow(10.0, nDig
);
3232 whole
= dblIn
< 0 ? ceil(dblIn
) : floor(dblIn
);
3233 fract
= dblIn
- whole
;
3236 dblIn
= whole
+ 1.0;
3237 else if (fract
== 0.5)
3238 dblIn
= whole
+ fmod(whole
, 2.0);
3239 else if (fract
>= 0.0)
3241 else if (fract
== -0.5)
3242 dblIn
= whole
- fmod(whole
, 2.0);
3243 else if (fract
> -0.5)
3246 dblIn
= whole
- 1.0;
3248 *pDblOut
= dblIn
/ scale
;
3255 /* Powers of 10 from 0..4 D.P. */
3256 static const int CY_Divisors
[5] = { CY_MULTIPLIER
/10000, CY_MULTIPLIER
/1000,
3257 CY_MULTIPLIER
/100, CY_MULTIPLIER
/10, CY_MULTIPLIER
};
3259 /************************************************************************
3260 * VarCyFromUI1 (OLEAUT32.98)
3262 * Convert a VT_UI1 to a VT_CY.
3266 * pCyOut [O] Destination
3270 * Failure: E_INVALIDARG, if the source value is invalid
3271 * DISP_E_OVERFLOW, if the value will not fit in the destination
3272 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3274 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pCyOut
)
3276 return _VarCyFromUI1(bIn
, pCyOut
);
3279 /************************************************************************
3280 * VarCyFromI2 (OLEAUT32.99)
3282 * Convert a VT_I2 to a VT_CY.
3286 * pCyOut [O] Destination
3290 * Failure: E_INVALIDARG, if the source value is invalid
3291 * DISP_E_OVERFLOW, if the value will not fit in the destination
3292 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3294 HRESULT WINAPI
VarCyFromI2(SHORT sIn
, CY
* pCyOut
)
3296 return _VarCyFromI2(sIn
, pCyOut
);
3299 /************************************************************************
3300 * VarCyFromI4 (OLEAUT32.100)
3302 * Convert a VT_I4 to a VT_CY.
3306 * pCyOut [O] Destination
3310 * Failure: E_INVALIDARG, if the source value is invalid
3311 * DISP_E_OVERFLOW, if the value will not fit in the destination
3312 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3314 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pCyOut
)
3316 return _VarCyFromI4(lIn
, pCyOut
);
3319 /************************************************************************
3320 * VarCyFromR4 (OLEAUT32.101)
3322 * Convert a VT_R4 to a VT_CY.
3326 * pCyOut [O] Destination
3330 * Failure: E_INVALIDARG, if the source value is invalid
3331 * DISP_E_OVERFLOW, if the value will not fit in the destination
3332 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3334 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pCyOut
)
3336 return _VarCyFromR4(fltIn
, pCyOut
);
3339 /************************************************************************
3340 * VarCyFromR8 (OLEAUT32.102)
3342 * Convert a VT_R8 to a VT_CY.
3346 * pCyOut [O] Destination
3350 * Failure: E_INVALIDARG, if the source value is invalid
3351 * DISP_E_OVERFLOW, if the value will not fit in the destination
3352 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3354 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pCyOut
)
3356 #if defined(__GNUC__) && defined(__i386__)
3357 /* This code gives identical results to Win32 on Intel.
3358 * Here we use fp exceptions to catch overflows when storing the value.
3360 static const unsigned short r8_fpcontrol
= 0x137f;
3361 static const double r8_multiplier
= CY_MULTIPLIER_F
;
3362 unsigned short old_fpcontrol
, result_fpstatus
;
3364 /* Clear exceptions, save the old fp state and load the new state */
3365 __asm__
__volatile__( "fnclex" );
3366 __asm__
__volatile__( "fstcw %0" : "=m" (old_fpcontrol
) : );
3367 __asm__
__volatile__( "fldcw %0" : : "m" (r8_fpcontrol
) );
3368 /* Perform the conversion. */
3369 __asm__
__volatile__( "fldl %0" : : "m" (dblIn
) );
3370 __asm__
__volatile__( "fmull %0" : : "m" (r8_multiplier
) );
3371 __asm__
__volatile__( "fistpll %0" : : "m" (*pCyOut
) );
3372 /* Save the resulting fp state, load the old state and clear exceptions */
3373 __asm__
__volatile__( "fstsw %0" : "=m" (result_fpstatus
) : );
3374 __asm__
__volatile__( "fnclex" );
3375 __asm__
__volatile__( "fldcw %0" : : "m" (old_fpcontrol
) );
3377 if (result_fpstatus
& 0x9) /* Overflow | Invalid */
3378 return DISP_E_OVERFLOW
;
3381 /* This version produces slightly different results for boundary cases */
3382 if (dblIn
< -922337203685477.5807 || dblIn
>= 922337203685477.5807)
3383 return DISP_E_OVERFLOW
;
3384 dblIn
*= CY_MULTIPLIER_F
;
3385 OLEAUT32_DutchRound(LONG64
, dblIn
, pCyOut
->int64
);
3390 /************************************************************************
3391 * VarCyFromDate (OLEAUT32.103)
3393 * Convert a VT_DATE to a VT_CY.
3397 * pCyOut [O] Destination
3401 * Failure: E_INVALIDARG, if the source value is invalid
3402 * DISP_E_OVERFLOW, if the value will not fit in the destination
3403 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3405 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pCyOut
)
3407 return _VarCyFromDate(dateIn
, pCyOut
);
3410 /************************************************************************
3411 * VarCyFromStr (OLEAUT32.104)
3413 * Convert a VT_BSTR to a VT_CY.
3417 * lcid [I] LCID for the conversion
3418 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3419 * pCyOut [O] Destination
3423 * Failure: E_INVALIDARG, if the source value is invalid
3424 * DISP_E_OVERFLOW, if the value will not fit in the destination
3425 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3427 HRESULT WINAPI
VarCyFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CY
* pCyOut
)
3429 return _VarCyFromStr(strIn
, lcid
, dwFlags
, pCyOut
);
3432 /************************************************************************
3433 * VarCyFromDisp (OLEAUT32.105)
3435 * Convert a VT_DISPATCH to a VT_CY.
3438 * pdispIn [I] Source
3439 * lcid [I] LCID for conversion
3440 * pCyOut [O] Destination
3444 * Failure: E_INVALIDARG, if the source value is invalid
3445 * DISP_E_OVERFLOW, if the value will not fit in the destination
3446 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3448 HRESULT WINAPI
VarCyFromDisp(IDispatch
* pdispIn
, LCID lcid
, CY
* pCyOut
)
3450 return _VarCyFromDisp(pdispIn
, lcid
, pCyOut
);
3453 /************************************************************************
3454 * VarCyFromBool (OLEAUT32.106)
3456 * Convert a VT_BOOL to a VT_CY.
3460 * pCyOut [O] Destination
3464 * Failure: E_INVALIDARG, if the source value is invalid
3465 * DISP_E_OVERFLOW, if the value will not fit in the destination
3466 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3469 * While the sign of the boolean is stored in the currency, the value is
3470 * converted to either 0 or 1.
3472 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pCyOut
)
3474 return _VarCyFromBool(boolIn
, pCyOut
);
3477 /************************************************************************
3478 * VarCyFromI1 (OLEAUT32.225)
3480 * Convert a VT_I1 to a VT_CY.
3484 * pCyOut [O] Destination
3488 * Failure: E_INVALIDARG, if the source value is invalid
3489 * DISP_E_OVERFLOW, if the value will not fit in the destination
3490 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3492 HRESULT WINAPI
VarCyFromI1(signed char cIn
, CY
* pCyOut
)
3494 return _VarCyFromI1(cIn
, pCyOut
);
3497 /************************************************************************
3498 * VarCyFromUI2 (OLEAUT32.226)
3500 * Convert a VT_UI2 to a VT_CY.
3504 * pCyOut [O] Destination
3508 * Failure: E_INVALIDARG, if the source value is invalid
3509 * DISP_E_OVERFLOW, if the value will not fit in the destination
3510 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3512 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pCyOut
)
3514 return _VarCyFromUI2(usIn
, pCyOut
);
3517 /************************************************************************
3518 * VarCyFromUI4 (OLEAUT32.227)
3520 * Convert a VT_UI4 to a VT_CY.
3524 * pCyOut [O] Destination
3528 * Failure: E_INVALIDARG, if the source value is invalid
3529 * DISP_E_OVERFLOW, if the value will not fit in the destination
3530 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3532 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pCyOut
)
3534 return _VarCyFromUI4(ulIn
, pCyOut
);
3537 /************************************************************************
3538 * VarCyFromDec (OLEAUT32.228)
3540 * Convert a VT_DECIMAL 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
VarCyFromDec(DECIMAL
* pdecIn
, CY
* pCyOut
)
3557 hRet
= VarDecRound(pdecIn
, 4, &rounded
);
3559 if (SUCCEEDED(hRet
))
3563 if (DEC_HI32(&rounded
))
3564 return DISP_E_OVERFLOW
;
3566 /* Note: Without the casts this promotes to int64 which loses precision */
3567 d
= (double)DEC_LO64(&rounded
) / (double)CY_Divisors
[DEC_SCALE(&rounded
)];
3568 if (DEC_SIGN(&rounded
))
3570 return _VarCyFromR8(d
, pCyOut
);
3575 /************************************************************************
3576 * VarCyFromI8 (OLEAUT32.366)
3578 * Convert a VT_I8 to a VT_CY.
3582 * pCyOut [O] Destination
3586 * Failure: E_INVALIDARG, if the source value is invalid
3587 * DISP_E_OVERFLOW, if the value will not fit in the destination
3588 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3590 HRESULT WINAPI
VarCyFromI8(LONG64 llIn
, CY
* pCyOut
)
3592 return _VarCyFromI8(llIn
, pCyOut
);
3595 /************************************************************************
3596 * VarCyFromUI8 (OLEAUT32.375)
3598 * Convert a VT_UI8 to a VT_CY.
3602 * pCyOut [O] Destination
3606 * Failure: E_INVALIDARG, if the source value is invalid
3607 * DISP_E_OVERFLOW, if the value will not fit in the destination
3608 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3610 HRESULT WINAPI
VarCyFromUI8(ULONG64 ullIn
, CY
* pCyOut
)
3612 return _VarCyFromUI8(ullIn
, pCyOut
);
3615 /************************************************************************
3616 * VarCyAdd (OLEAUT32.299)
3618 * Add one CY to another.
3622 * cyRight [I] Value to add
3623 * pCyOut [O] Destination
3627 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3629 HRESULT WINAPI
VarCyAdd(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3632 _VarR8FromCy(cyLeft
, &l
);
3633 _VarR8FromCy(cyRight
, &r
);
3635 return _VarCyFromR8(l
, pCyOut
);
3638 /************************************************************************
3639 * VarCyMul (OLEAUT32.303)
3641 * Multiply one CY by another.
3645 * cyRight [I] Value to multiply by
3646 * pCyOut [O] Destination
3650 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3652 HRESULT WINAPI
VarCyMul(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3655 _VarR8FromCy(cyLeft
, &l
);
3656 _VarR8FromCy(cyRight
, &r
);
3658 return _VarCyFromR8(l
, pCyOut
);
3661 /************************************************************************
3662 * VarCyMulI4 (OLEAUT32.304)
3664 * Multiply one CY by a VT_I4.
3668 * lRight [I] Value to multiply by
3669 * pCyOut [O] Destination
3673 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3675 HRESULT WINAPI
VarCyMulI4(const CY cyLeft
, LONG lRight
, CY
* pCyOut
)
3679 _VarR8FromCy(cyLeft
, &d
);
3681 return _VarCyFromR8(d
, pCyOut
);
3684 /************************************************************************
3685 * VarCySub (OLEAUT32.305)
3687 * Subtract one CY from another.
3691 * cyRight [I] Value to subtract
3692 * pCyOut [O] Destination
3696 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3698 HRESULT WINAPI
VarCySub(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3701 _VarR8FromCy(cyLeft
, &l
);
3702 _VarR8FromCy(cyRight
, &r
);
3704 return _VarCyFromR8(l
, pCyOut
);
3707 /************************************************************************
3708 * VarCyAbs (OLEAUT32.306)
3710 * Convert a VT_CY into its absolute value.
3714 * pCyOut [O] Destination
3717 * Success: S_OK. pCyOut contains the absolute value.
3718 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3720 HRESULT WINAPI
VarCyAbs(const CY cyIn
, CY
* pCyOut
)
3722 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3723 return DISP_E_OVERFLOW
;
3725 pCyOut
->int64
= cyIn
.int64
< 0 ? -cyIn
.int64
: cyIn
.int64
;
3729 /************************************************************************
3730 * VarCyFix (OLEAUT32.307)
3732 * Return the integer part of a VT_CY.
3736 * pCyOut [O] Destination
3740 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3743 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3744 * negative numbers away from 0, while this function rounds them towards zero.
3746 HRESULT WINAPI
VarCyFix(const CY cyIn
, CY
* pCyOut
)
3748 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3749 pCyOut
->int64
*= CY_MULTIPLIER
;
3753 /************************************************************************
3754 * VarCyInt (OLEAUT32.308)
3756 * Return the integer part of a VT_CY.
3760 * pCyOut [O] Destination
3764 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3767 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3768 * negative numbers towards 0, while this function rounds them away from zero.
3770 HRESULT WINAPI
VarCyInt(const CY cyIn
, CY
* pCyOut
)
3772 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3773 pCyOut
->int64
*= CY_MULTIPLIER
;
3775 if (cyIn
.int64
< 0 && cyIn
.int64
% CY_MULTIPLIER
!= 0)
3777 pCyOut
->int64
-= CY_MULTIPLIER
;
3782 /************************************************************************
3783 * VarCyNeg (OLEAUT32.309)
3785 * Change the sign of a VT_CY.
3789 * pCyOut [O] Destination
3793 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3795 HRESULT WINAPI
VarCyNeg(const CY cyIn
, CY
* pCyOut
)
3797 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3798 return DISP_E_OVERFLOW
;
3800 pCyOut
->int64
= -cyIn
.int64
;
3804 /************************************************************************
3805 * VarCyRound (OLEAUT32.310)
3807 * Change the precision of a VT_CY.
3811 * cDecimals [I] New number of decimals to keep
3812 * pCyOut [O] Destination
3816 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3818 HRESULT WINAPI
VarCyRound(const CY cyIn
, int cDecimals
, CY
* pCyOut
)
3821 return E_INVALIDARG
;
3825 /* Rounding to more precision than we have */
3831 double d
, div
= CY_Divisors
[cDecimals
];
3833 _VarR8FromCy(cyIn
, &d
);
3835 OLEAUT32_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3836 d
= (double)pCyOut
->int64
/ div
* CY_MULTIPLIER_F
;
3837 OLEAUT32_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3842 /************************************************************************
3843 * VarCyCmp (OLEAUT32.311)
3845 * Compare two VT_CY values.
3849 * cyRight [I] Value to compare
3852 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
3853 * compare is less, equal or greater than source respectively.
3854 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
3856 HRESULT WINAPI
VarCyCmp(const CY cyLeft
, const CY cyRight
)
3861 /* Subtract right from left, and compare the result to 0 */
3862 hRet
= VarCySub(cyLeft
, cyRight
, &result
);
3864 if (SUCCEEDED(hRet
))
3866 if (result
.int64
< 0)
3867 hRet
= (HRESULT
)VARCMP_LT
;
3868 else if (result
.int64
> 0)
3869 hRet
= (HRESULT
)VARCMP_GT
;
3871 hRet
= (HRESULT
)VARCMP_EQ
;
3876 /************************************************************************
3877 * VarCyCmpR8 (OLEAUT32.312)
3879 * Compare a VT_CY to a double
3882 * cyLeft [I] Currency Source
3883 * dblRight [I] double to compare to cyLeft
3886 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
3887 * less than, equal to or greater than cyLeft respectively.
3888 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
3890 HRESULT WINAPI
VarCyCmpR8(const CY cyLeft
, double dblRight
)
3895 hRet
= _VarCyFromR8(dblRight
, &cyRight
);
3897 if (SUCCEEDED(hRet
))
3898 hRet
= VarCyCmp(cyLeft
, cyRight
);
3903 /************************************************************************
3904 * VarCyMulI8 (OLEAUT32.329)
3906 * Multiply a VT_CY by a VT_I8.
3910 * llRight [I] Value to multiply by
3911 * pCyOut [O] Destination
3915 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3917 HRESULT WINAPI
VarCyMulI8(const CY cyLeft
, LONG64 llRight
, CY
* pCyOut
)
3921 _VarR8FromCy(cyLeft
, &d
);
3922 d
= d
* (double)llRight
;
3923 return _VarCyFromR8(d
, pCyOut
);
3929 /************************************************************************
3930 * VarDecFromUI1 (OLEAUT32.190)
3932 * Convert a VT_UI1 to a DECIMAL.
3936 * pDecOut [O] Destination
3941 HRESULT WINAPI
VarDecFromUI1(BYTE bIn
, DECIMAL
* pDecOut
)
3943 return _VarDecFromUI1(bIn
, pDecOut
);
3946 /************************************************************************
3947 * VarDecFromI2 (OLEAUT32.191)
3949 * Convert a VT_I2 to a DECIMAL.
3953 * pDecOut [O] Destination
3958 HRESULT WINAPI
VarDecFromI2(SHORT sIn
, DECIMAL
* pDecOut
)
3960 return _VarDecFromI2(sIn
, pDecOut
);
3963 /************************************************************************
3964 * VarDecFromI4 (OLEAUT32.192)
3966 * Convert a VT_I4 to a DECIMAL.
3970 * pDecOut [O] Destination
3975 HRESULT WINAPI
VarDecFromI4(LONG lIn
, DECIMAL
* pDecOut
)
3977 DEC_HI32(pDecOut
) = 0;
3978 DEC_MID32(pDecOut
) = 0;
3982 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
3983 DEC_LO32(pDecOut
) = -lIn
;
3987 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
3988 DEC_LO32(pDecOut
) = lIn
;
3993 #define LOCALE_EN_US (MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT))
3995 /************************************************************************
3996 * VarDecFromR4 (OLEAUT32.193)
3998 * Convert a VT_R4 to a DECIMAL.
4002 * pDecOut [O] Destination
4007 HRESULT WINAPI
VarDecFromR4(FLOAT fltIn
, DECIMAL
* pDecOut
)
4011 sprintfW( buff
, szFloatFormatW
, fltIn
);
4012 return _VarDecFromStr(buff
, LOCALE_EN_US
, 0, pDecOut
);
4015 /************************************************************************
4016 * VarDecFromR8 (OLEAUT32.194)
4018 * Convert a VT_R8 to a DECIMAL.
4022 * pDecOut [O] Destination
4027 HRESULT WINAPI
VarDecFromR8(double dblIn
, DECIMAL
* pDecOut
)
4031 sprintfW( buff
, szDoubleFormatW
, dblIn
);
4032 return _VarDecFromStr(buff
, LOCALE_EN_US
, 0, pDecOut
);
4035 /************************************************************************
4036 * VarDecFromDate (OLEAUT32.195)
4038 * Convert a VT_DATE to a DECIMAL.
4042 * pDecOut [O] Destination
4047 HRESULT WINAPI
VarDecFromDate(DATE dateIn
, DECIMAL
* pDecOut
)
4049 return _VarDecFromDate(dateIn
, pDecOut
);
4052 /************************************************************************
4053 * VarDecFromCy (OLEAUT32.196)
4055 * Convert a VT_CY to a DECIMAL.
4059 * pDecOut [O] Destination
4064 HRESULT WINAPI
VarDecFromCy(CY cyIn
, DECIMAL
* pDecOut
)
4066 DEC_HI32(pDecOut
) = 0;
4068 /* Note: This assumes 2s complement integer representation */
4069 if (cyIn
.s
.Hi
& 0x80000000)
4071 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,4);
4072 DEC_LO64(pDecOut
) = -cyIn
.int64
;
4076 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,4);
4077 DEC_MID32(pDecOut
) = cyIn
.s
.Hi
;
4078 DEC_LO32(pDecOut
) = cyIn
.s
.Lo
;
4083 /************************************************************************
4084 * VarDecFromStr (OLEAUT32.197)
4086 * Convert a VT_BSTR to a DECIMAL.
4090 * lcid [I] LCID for the conversion
4091 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4092 * pDecOut [O] Destination
4096 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4098 HRESULT WINAPI
VarDecFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DECIMAL
* pDecOut
)
4100 return _VarDecFromStr(strIn
, lcid
, dwFlags
, pDecOut
);
4103 /************************************************************************
4104 * VarDecFromDisp (OLEAUT32.198)
4106 * Convert a VT_DISPATCH to a DECIMAL.
4109 * pdispIn [I] Source
4110 * lcid [I] LCID for conversion
4111 * pDecOut [O] Destination
4115 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4117 HRESULT WINAPI
VarDecFromDisp(IDispatch
* pdispIn
, LCID lcid
, DECIMAL
* pDecOut
)
4119 return _VarDecFromDisp(pdispIn
, lcid
, pDecOut
);
4122 /************************************************************************
4123 * VarDecFromBool (OLEAUT32.199)
4125 * Convert a VT_BOOL to a DECIMAL.
4129 * pDecOut [O] Destination
4135 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4137 HRESULT WINAPI
VarDecFromBool(VARIANT_BOOL bIn
, DECIMAL
* pDecOut
)
4139 DEC_HI32(pDecOut
) = 0;
4140 DEC_MID32(pDecOut
) = 0;
4143 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4144 DEC_LO32(pDecOut
) = 1;
4148 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4149 DEC_LO32(pDecOut
) = 0;
4154 /************************************************************************
4155 * VarDecFromI1 (OLEAUT32.241)
4157 * Convert a VT_I1 to a DECIMAL.
4161 * pDecOut [O] Destination
4166 HRESULT WINAPI
VarDecFromI1(signed char cIn
, DECIMAL
* pDecOut
)
4168 return _VarDecFromI1(cIn
, pDecOut
);
4171 /************************************************************************
4172 * VarDecFromUI2 (OLEAUT32.242)
4174 * Convert a VT_UI2 to a DECIMAL.
4178 * pDecOut [O] Destination
4183 HRESULT WINAPI
VarDecFromUI2(USHORT usIn
, DECIMAL
* pDecOut
)
4185 return _VarDecFromUI2(usIn
, pDecOut
);
4188 /************************************************************************
4189 * VarDecFromUI4 (OLEAUT32.243)
4191 * Convert a VT_UI4 to a DECIMAL.
4195 * pDecOut [O] Destination
4200 HRESULT WINAPI
VarDecFromUI4(ULONG ulIn
, DECIMAL
* pDecOut
)
4202 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4203 DEC_HI32(pDecOut
) = 0;
4204 DEC_MID32(pDecOut
) = 0;
4205 DEC_LO32(pDecOut
) = ulIn
;
4209 /************************************************************************
4210 * VarDecFromI8 (OLEAUT32.374)
4212 * Convert a VT_I8 to a DECIMAL.
4216 * pDecOut [O] Destination
4221 HRESULT WINAPI
VarDecFromI8(LONG64 llIn
, DECIMAL
* pDecOut
)
4223 PULARGE_INTEGER pLi
= (PULARGE_INTEGER
)&llIn
;
4225 DEC_HI32(pDecOut
) = 0;
4227 /* Note: This assumes 2s complement integer representation */
4228 if (pLi
->u
.HighPart
& 0x80000000)
4230 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4231 DEC_LO64(pDecOut
) = -pLi
->QuadPart
;
4235 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4236 DEC_MID32(pDecOut
) = pLi
->u
.HighPart
;
4237 DEC_LO32(pDecOut
) = pLi
->u
.LowPart
;
4242 /************************************************************************
4243 * VarDecFromUI8 (OLEAUT32.375)
4245 * Convert a VT_UI8 to a DECIMAL.
4249 * pDecOut [O] Destination
4254 HRESULT WINAPI
VarDecFromUI8(ULONG64 ullIn
, DECIMAL
* pDecOut
)
4256 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4257 DEC_HI32(pDecOut
) = 0;
4258 DEC_LO64(pDecOut
) = ullIn
;
4262 /* Make two DECIMALS the same scale; used by math functions below */
4263 static HRESULT
VARIANT_DecScale(const DECIMAL
** ppDecLeft
,
4264 const DECIMAL
** ppDecRight
,
4267 static DECIMAL scaleFactor
;
4270 HRESULT hRet
= S_OK
;
4272 if (DEC_SIGN(*ppDecLeft
) & ~DECIMAL_NEG
|| DEC_SIGN(*ppDecRight
) & ~DECIMAL_NEG
)
4273 return E_INVALIDARG
;
4275 DEC_LO32(&scaleFactor
) = 10;
4277 i
= scaleAmount
= DEC_SCALE(*ppDecLeft
) - DEC_SCALE(*ppDecRight
);
4280 return S_OK
; /* Same scale */
4282 if (scaleAmount
> 0)
4284 decTemp
= *(*ppDecRight
); /* Left is bigger - scale the right hand side */
4285 *ppDecRight
= pDecOut
;
4289 decTemp
= *(*ppDecLeft
); /* Right is bigger - scale the left hand side */
4290 *ppDecLeft
= pDecOut
;
4291 i
= scaleAmount
= -scaleAmount
;
4294 if (DEC_SCALE(&decTemp
) + scaleAmount
> DEC_MAX_SCALE
)
4295 return DISP_E_OVERFLOW
; /* Can't scale up */
4297 /* Multiply up the value to be scaled by the correct amount */
4298 while (SUCCEEDED(hRet
) && i
--)
4300 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4301 hRet
= VarDecMul(&decTemp
, &scaleFactor
, pDecOut
);
4304 DEC_SCALE(pDecOut
) += scaleAmount
; /* Set the new scale */
4308 /* Add two unsigned 32 bit values with overflow */
4309 static ULONG
VARIANT_Add(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4311 ULARGE_INTEGER ul64
;
4313 ul64
.QuadPart
= (ULONG64
)ulLeft
+ (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4314 *pulHigh
= ul64
.u
.HighPart
;
4315 return ul64
.u
.LowPart
;
4318 /* Subtract two unsigned 32 bit values with underflow */
4319 static ULONG
VARIANT_Sub(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4322 ULARGE_INTEGER ul64
;
4324 ul64
.QuadPart
= (LONG64
)ulLeft
- (ULONG64
)ulRight
;
4325 if (ulLeft
< ulRight
)
4328 if (ul64
.QuadPart
> (ULONG64
)*pulHigh
)
4329 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4332 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4336 ul64
.u
.HighPart
= -ul64
.u
.HighPart
;
4338 *pulHigh
= ul64
.u
.HighPart
;
4339 return ul64
.u
.LowPart
;
4342 /* Multiply two unsigned 32 bit values with overflow */
4343 static ULONG
VARIANT_Mul(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4345 ULARGE_INTEGER ul64
;
4347 ul64
.QuadPart
= (ULONG64
)ulLeft
* (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4348 *pulHigh
= ul64
.u
.HighPart
;
4349 return ul64
.u
.LowPart
;
4352 /* Compare two decimals that have the same scale */
4353 static inline int VARIANT_DecCmp(const DECIMAL
*pDecLeft
, const DECIMAL
*pDecRight
)
4355 if ( DEC_HI32(pDecLeft
) < DEC_HI32(pDecRight
) ||
4356 (DEC_HI32(pDecLeft
) <= DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) < DEC_LO64(pDecRight
)))
4358 else if (DEC_HI32(pDecLeft
) == DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) == DEC_LO64(pDecRight
))
4363 /************************************************************************
4364 * VarDecAdd (OLEAUT32.177)
4366 * Add one DECIMAL to another.
4369 * pDecLeft [I] Source
4370 * pDecRight [I] Value to add
4371 * pDecOut [O] Destination
4375 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4377 HRESULT WINAPI
VarDecAdd(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4382 hRet
= VARIANT_DecScale(&pDecLeft
, &pDecRight
, &scaled
);
4384 if (SUCCEEDED(hRet
))
4386 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4388 BYTE sign
= DECIMAL_POS
;
4390 /* Correct for the sign of the result */
4391 if (DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4393 /* -x + -y : Negative */
4395 goto VarDecAdd_AsPositive
;
4397 else if (DEC_SIGN(pDecLeft
) && !DEC_SIGN(pDecRight
))
4399 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4401 /* -x + y : Negative if x > y */
4405 VarDecAdd_AsNegative
:
4406 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4407 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4408 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4412 VarDecAdd_AsInvertedNegative
:
4413 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecRight
), DEC_LO32(pDecLeft
), &overflow
);
4414 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecRight
), DEC_MID32(pDecLeft
), &overflow
);
4415 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecRight
), DEC_HI32(pDecLeft
), &overflow
);
4418 else if (!DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4420 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4422 /* x + -y : Negative if x <= y */
4426 goto VarDecAdd_AsInvertedNegative
;
4428 goto VarDecAdd_AsNegative
;
4432 /* x + y : Positive */
4433 VarDecAdd_AsPositive
:
4434 DEC_LO32(pDecOut
) = VARIANT_Add(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4435 DEC_MID32(pDecOut
) = VARIANT_Add(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4436 DEC_HI32(pDecOut
) = VARIANT_Add(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4440 return DISP_E_OVERFLOW
; /* overflowed */
4442 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecLeft
);
4443 DEC_SIGN(pDecOut
) = sign
;
4448 /************************************************************************
4449 * VarDecDiv (OLEAUT32.178)
4451 * Divide one DECIMAL by another.
4454 * pDecLeft [I] Source
4455 * pDecRight [I] Value to divide by
4456 * pDecOut [O] Destination
4460 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4462 HRESULT WINAPI
VarDecDiv(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4464 FIXME("(%p,%p,%p)-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4465 return DISP_E_OVERFLOW
;
4468 /************************************************************************
4469 * VarDecMul (OLEAUT32.179)
4471 * Multiply one DECIMAL by another.
4474 * pDecLeft [I] Source
4475 * pDecRight [I] Value to multiply by
4476 * pDecOut [O] Destination
4480 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4482 HRESULT WINAPI
VarDecMul(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4484 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4486 if (!DEC_SCALE(pDecLeft
) || !DEC_SCALE(pDecRight
))
4488 /* At least one term is an integer */
4489 const DECIMAL
* pDecInteger
= DEC_SCALE(pDecLeft
) ? pDecRight
: pDecLeft
;
4490 const DECIMAL
* pDecOperand
= DEC_SCALE(pDecLeft
) ? pDecLeft
: pDecRight
;
4491 HRESULT hRet
= S_OK
;
4492 unsigned int multiplier
= DEC_LO32(pDecInteger
);
4495 if (DEC_HI32(pDecInteger
) || DEC_MID32(pDecInteger
))
4497 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4498 return DISP_E_OVERFLOW
;
4501 DEC_LO32(pDecOut
) = VARIANT_Mul(DEC_LO32(pDecOperand
), multiplier
, &overflow
);
4502 DEC_MID32(pDecOut
) = VARIANT_Mul(DEC_MID32(pDecOperand
), multiplier
, &overflow
);
4503 DEC_HI32(pDecOut
) = VARIANT_Mul(DEC_HI32(pDecOperand
), multiplier
, &overflow
);
4506 hRet
= DISP_E_OVERFLOW
;
4509 BYTE sign
= DECIMAL_POS
;
4511 if (DEC_SIGN(pDecLeft
) != DEC_SIGN(pDecRight
))
4512 sign
= DECIMAL_NEG
; /* pos * neg => negative */
4513 DEC_SIGN(pDecOut
) = sign
;
4514 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecOperand
);
4518 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4519 return DISP_E_OVERFLOW
;
4522 /************************************************************************
4523 * VarDecSub (OLEAUT32.181)
4525 * Subtract one DECIMAL from another.
4528 * pDecLeft [I] Source
4529 * pDecRight [I] DECIMAL to subtract from pDecLeft
4530 * pDecOut [O] Destination
4533 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4535 HRESULT WINAPI
VarDecSub(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4539 /* Implement as addition of the negative */
4540 VarDecNeg(pDecRight
, &decRight
);
4541 return VarDecAdd(pDecLeft
, &decRight
, pDecOut
);
4544 /************************************************************************
4545 * VarDecAbs (OLEAUT32.182)
4547 * Convert a DECIMAL into its absolute value.
4551 * pDecOut [O] Destination
4554 * S_OK. This function does not fail.
4556 HRESULT WINAPI
VarDecAbs(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4559 DEC_SIGN(pDecOut
) &= ~DECIMAL_NEG
;
4563 /************************************************************************
4564 * VarDecFix (OLEAUT32.187)
4566 * Return the integer portion of a DECIMAL.
4570 * pDecOut [O] Destination
4574 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4577 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4578 * negative numbers away from 0, while this function rounds them towards zero.
4580 HRESULT WINAPI
VarDecFix(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4582 if (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
4583 return E_INVALIDARG
;
4585 if (!DEC_SCALE(pDecIn
))
4587 *pDecOut
= *pDecIn
; /* Already an integer */
4591 FIXME("semi-stub!\n");
4592 return DISP_E_OVERFLOW
;
4595 /************************************************************************
4596 * VarDecInt (OLEAUT32.188)
4598 * Return the integer portion of a DECIMAL.
4602 * pDecOut [O] Destination
4606 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4609 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4610 * negative numbers towards 0, while this function rounds them away from zero.
4612 HRESULT WINAPI
VarDecInt(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4614 if (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
4615 return E_INVALIDARG
;
4617 if (!(DEC_SIGN(pDecIn
) & DECIMAL_NEG
) || !DEC_SCALE(pDecIn
))
4618 return VarDecFix(pDecIn
, pDecOut
); /* The same, if +ve or no fractionals */
4620 FIXME("semi-stub!\n");
4621 return DISP_E_OVERFLOW
;
4624 /************************************************************************
4625 * VarDecNeg (OLEAUT32.189)
4627 * Change the sign of a DECIMAL.
4631 * pDecOut [O] Destination
4634 * S_OK. This function does not fail.
4636 HRESULT WINAPI
VarDecNeg(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4639 DEC_SIGN(pDecOut
) ^= DECIMAL_NEG
;
4643 /************************************************************************
4644 * VarDecRound (OLEAUT32.203)
4646 * Change the precision of a DECIMAL.
4650 * cDecimals [I] New number of decimals to keep
4651 * pDecOut [O] Destination
4654 * Success: S_OK. pDecOut contains the rounded value.
4655 * Failure: E_INVALIDARG if any argument is invalid.
4657 HRESULT WINAPI
VarDecRound(const DECIMAL
* pDecIn
, int cDecimals
, DECIMAL
* pDecOut
)
4659 if (cDecimals
< 0 || (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
) || DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
)
4660 return E_INVALIDARG
;
4662 if (cDecimals
>= DEC_SCALE(pDecIn
))
4664 *pDecOut
= *pDecIn
; /* More precision than we have */
4668 FIXME("semi-stub!\n");
4670 return DISP_E_OVERFLOW
;
4673 /************************************************************************
4674 * VarDecCmp (OLEAUT32.204)
4676 * Compare two DECIMAL values.
4679 * pDecLeft [I] Source
4680 * pDecRight [I] Value to compare
4683 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4684 * is less than, equal to or greater than pDecRight respectively.
4685 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4687 HRESULT WINAPI
VarDecCmp(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
)
4692 /* Subtract right from left, and compare the result to 0 */
4693 hRet
= VarDecSub(pDecLeft
, pDecRight
, &result
);
4695 if (SUCCEEDED(hRet
))
4697 int non_zero
= DEC_HI32(&result
) | DEC_MID32(&result
) | DEC_LO32(&result
);
4699 if ((DEC_SIGN(&result
) & DECIMAL_NEG
) && non_zero
)
4700 hRet
= (HRESULT
)VARCMP_LT
;
4702 hRet
= (HRESULT
)VARCMP_GT
;
4704 hRet
= (HRESULT
)VARCMP_EQ
;
4709 /************************************************************************
4710 * VarDecCmpR8 (OLEAUT32.298)
4712 * Compare a DECIMAL to a double
4715 * pDecLeft [I] DECIMAL Source
4716 * dblRight [I] double to compare to pDecLeft
4719 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4720 * is less than, equal to or greater than pDecLeft respectively.
4721 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4723 HRESULT WINAPI
VarDecCmpR8(const DECIMAL
* pDecLeft
, double dblRight
)
4728 hRet
= VarDecFromR8(dblRight
, &decRight
);
4730 if (SUCCEEDED(hRet
))
4731 hRet
= VarDecCmp(pDecLeft
, &decRight
);
4739 /************************************************************************
4740 * VarBoolFromUI1 (OLEAUT32.118)
4742 * Convert a VT_UI1 to a VT_BOOL.
4746 * pBoolOut [O] Destination
4751 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
*pBoolOut
)
4753 return _VarBoolFromUI1(bIn
, pBoolOut
);
4756 /************************************************************************
4757 * VarBoolFromI2 (OLEAUT32.119)
4759 * Convert a VT_I2 to a VT_BOOL.
4763 * pBoolOut [O] Destination
4768 HRESULT WINAPI
VarBoolFromI2(SHORT sIn
, VARIANT_BOOL
*pBoolOut
)
4770 return _VarBoolFromI2(sIn
, pBoolOut
);
4773 /************************************************************************
4774 * VarBoolFromI4 (OLEAUT32.120)
4776 * Convert a VT_I4 to a VT_BOOL.
4780 * pBoolOut [O] Destination
4785 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
*pBoolOut
)
4787 return _VarBoolFromI4(lIn
, pBoolOut
);
4790 /************************************************************************
4791 * VarBoolFromR4 (OLEAUT32.121)
4793 * Convert a VT_R4 to a VT_BOOL.
4797 * pBoolOut [O] Destination
4802 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
*pBoolOut
)
4804 return _VarBoolFromR4(fltIn
, pBoolOut
);
4807 /************************************************************************
4808 * VarBoolFromR8 (OLEAUT32.122)
4810 * Convert a VT_R8 to a VT_BOOL.
4814 * pBoolOut [O] Destination
4819 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
*pBoolOut
)
4821 return _VarBoolFromR8(dblIn
, pBoolOut
);
4824 /************************************************************************
4825 * VarBoolFromDate (OLEAUT32.123)
4827 * Convert a VT_DATE to a VT_BOOL.
4831 * pBoolOut [O] Destination
4836 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
*pBoolOut
)
4838 return _VarBoolFromDate(dateIn
, pBoolOut
);
4841 /************************************************************************
4842 * VarBoolFromCy (OLEAUT32.124)
4844 * Convert a VT_CY to a VT_BOOL.
4848 * pBoolOut [O] Destination
4853 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
*pBoolOut
)
4855 return _VarBoolFromCy(cyIn
, pBoolOut
);
4858 static BOOL
VARIANT_GetLocalisedText(LANGID langId
, DWORD dwId
, WCHAR
*lpszDest
)
4862 hrsrc
= FindResourceExW( OLEAUT32_hModule
, (LPWSTR
)RT_STRING
,
4863 (LPCWSTR
)((dwId
>> 4) + 1), langId
);
4866 HGLOBAL hmem
= LoadResource( OLEAUT32_hModule
, hrsrc
);
4873 p
= LockResource( hmem
);
4874 for (i
= 0; i
< (dwId
& 0x0f); i
++) p
+= *p
+ 1;
4876 memcpy( lpszDest
, p
+ 1, *p
* sizeof(WCHAR
) );
4877 lpszDest
[*p
] = '\0';
4878 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest
), langId
);
4885 /************************************************************************
4886 * VarBoolFromStr (OLEAUT32.125)
4888 * Convert a VT_BSTR to a VT_BOOL.
4892 * lcid [I] LCID for the conversion
4893 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4894 * pBoolOut [O] Destination
4898 * Failure: E_INVALIDARG, if pBoolOut is invalid.
4899 * DISP_E_TYPEMISMATCH, if the type cannot be converted
4902 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
4903 * it may contain (in any case mapping) the text "true" or "false".
4904 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
4905 * localised text of "True" or "False" in the language specified by lcid.
4906 * - If none of these matches occur, the string is treated as a numeric string
4907 * and the boolean pBoolOut will be set according to whether the number is zero
4908 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
4909 * - If the text is not numeric and does not match any of the above, then
4910 * DISP_E_TYPEMISMATCH is returned.
4912 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
*pBoolOut
)
4914 /* Any VB/VBA programmers out there should recognise these strings... */
4915 static const WCHAR szFalse
[] = { '#','F','A','L','S','E','#','\0' };
4916 static const WCHAR szTrue
[] = { '#','T','R','U','E','#','\0' };
4918 LANGID langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4919 HRESULT hRes
= S_OK
;
4921 if (!strIn
|| !pBoolOut
)
4922 return DISP_E_TYPEMISMATCH
;
4924 /* Check if we should be comparing against localised text */
4925 if (dwFlags
& VAR_LOCALBOOL
)
4927 /* Convert our LCID into a usable value */
4928 lcid
= ConvertDefaultLocale(lcid
);
4930 langId
= LANGIDFROMLCID(lcid
);
4932 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
4933 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4935 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
4936 * I don't think this is needed unless any of the localised text strings
4937 * contain characters that can be so mapped. In the event that this is
4938 * true for a given language (possibly some Asian languages), then strIn
4939 * should be mapped here _only_ if langId is an Id for which this can occur.
4943 /* Note that if we are not comparing against localised strings, langId
4944 * will have its default value of LANG_ENGLISH. This allows us to mimic
4945 * the native behaviour of always checking against English strings even
4946 * after we've checked for localised ones.
4948 VarBoolFromStr_CheckLocalised
:
4949 if (VARIANT_GetLocalisedText(langId
, IDS_TRUE
, szBuff
))
4951 /* Compare against localised strings, ignoring case */
4952 if (!strcmpiW(strIn
, szBuff
))
4954 *pBoolOut
= VARIANT_TRUE
; /* Matched localised 'true' text */
4957 VARIANT_GetLocalisedText(langId
, IDS_FALSE
, szBuff
);
4958 if (!strcmpiW(strIn
, szBuff
))
4960 *pBoolOut
= VARIANT_FALSE
; /* Matched localised 'false' text */
4965 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
4967 /* We have checked the localised text, now check English */
4968 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4969 goto VarBoolFromStr_CheckLocalised
;
4972 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
4973 if (!strcmpW(strIn
, szFalse
))
4974 *pBoolOut
= VARIANT_FALSE
;
4975 else if (!strcmpW(strIn
, szTrue
))
4976 *pBoolOut
= VARIANT_TRUE
;
4981 /* If this string is a number, convert it as one */
4982 hRes
= _VarR8FromStr(strIn
, lcid
, dwFlags
, &d
);
4983 if (SUCCEEDED(hRes
))
4984 hRes
= _VarBoolFromR8(d
, pBoolOut
);
4989 /************************************************************************
4990 * VarBoolFromDisp (OLEAUT32.126)
4992 * Convert a VT_DISPATCH to a VT_BOOL.
4995 * pdispIn [I] Source
4996 * lcid [I] LCID for conversion
4997 * pBoolOut [O] Destination
5001 * Failure: E_INVALIDARG, if the source value is invalid
5002 * DISP_E_OVERFLOW, if the value will not fit in the destination
5003 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5005 HRESULT WINAPI
VarBoolFromDisp(IDispatch
* pdispIn
, LCID lcid
, VARIANT_BOOL
*pBoolOut
)
5007 return _VarBoolFromDisp(pdispIn
, lcid
, pBoolOut
);
5010 /************************************************************************
5011 * VarBoolFromI1 (OLEAUT32.233)
5013 * Convert a VT_I1 to a VT_BOOL.
5017 * pBoolOut [O] Destination
5022 HRESULT WINAPI
VarBoolFromI1(signed char cIn
, VARIANT_BOOL
*pBoolOut
)
5024 return _VarBoolFromI1(cIn
, pBoolOut
);
5027 /************************************************************************
5028 * VarBoolFromUI2 (OLEAUT32.234)
5030 * Convert a VT_UI2 to a VT_BOOL.
5034 * pBoolOut [O] Destination
5039 HRESULT WINAPI
VarBoolFromUI2(USHORT usIn
, VARIANT_BOOL
*pBoolOut
)
5041 return _VarBoolFromUI2(usIn
, pBoolOut
);
5044 /************************************************************************
5045 * VarBoolFromUI4 (OLEAUT32.235)
5047 * Convert a VT_UI4 to a VT_BOOL.
5051 * pBoolOut [O] Destination
5056 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
*pBoolOut
)
5058 return _VarBoolFromUI4(ulIn
, pBoolOut
);
5061 /************************************************************************
5062 * VarBoolFromDec (OLEAUT32.236)
5064 * Convert a VT_DECIMAL to a VT_BOOL.
5068 * pBoolOut [O] Destination
5072 * Failure: E_INVALIDARG, if pDecIn is invalid.
5074 HRESULT WINAPI
VarBoolFromDec(DECIMAL
* pDecIn
, VARIANT_BOOL
*pBoolOut
)
5076 if (DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
|| (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
))
5077 return E_INVALIDARG
;
5079 if (DEC_HI32(pDecIn
) || DEC_MID32(pDecIn
) || DEC_LO32(pDecIn
))
5080 *pBoolOut
= VARIANT_TRUE
;
5082 *pBoolOut
= VARIANT_FALSE
;
5086 /************************************************************************
5087 * VarBoolFromI8 (OLEAUT32.370)
5089 * Convert a VT_I8 to a VT_BOOL.
5093 * pBoolOut [O] Destination
5098 HRESULT WINAPI
VarBoolFromI8(LONG64 llIn
, VARIANT_BOOL
*pBoolOut
)
5100 return _VarBoolFromI8(llIn
, pBoolOut
);
5103 /************************************************************************
5104 * VarBoolFromUI8 (OLEAUT32.371)
5106 * Convert a VT_UI8 to a VT_BOOL.
5110 * pBoolOut [O] Destination
5115 HRESULT WINAPI
VarBoolFromUI8(ULONG64 ullIn
, VARIANT_BOOL
*pBoolOut
)
5117 return _VarBoolFromUI8(ullIn
, pBoolOut
);
5123 /* Write a number from a UI8 and sign */
5124 static WCHAR
*VARIANT_WriteNumber(ULONG64 ulVal
, WCHAR
* szOut
)
5128 WCHAR ulNextDigit
= ulVal
% 10;
5130 *szOut
-- = '0' + ulNextDigit
;
5131 ulVal
= (ulVal
- ulNextDigit
) / 10;
5138 /* Create a (possibly localised) BSTR from a UI8 and sign */
5139 static BSTR
VARIANT_MakeBstr(LCID lcid
, DWORD dwFlags
, WCHAR
*szOut
)
5141 WCHAR szConverted
[256];
5143 if (dwFlags
& VAR_NEGATIVE
)
5146 if (dwFlags
& LOCALE_USE_NLS
)
5148 /* Format the number for the locale */
5149 szConverted
[0] = '\0';
5150 GetNumberFormatW(lcid
,
5151 dwFlags
& LOCALE_NOUSEROVERRIDE
,
5152 szOut
, NULL
, szConverted
, sizeof(szConverted
)/sizeof(WCHAR
));
5153 szOut
= szConverted
;
5155 return SysAllocStringByteLen((LPCSTR
)szOut
, strlenW(szOut
) * sizeof(WCHAR
));
5158 /* Create a (possibly localised) BSTR from a UI8 and sign */
5159 static HRESULT
VARIANT_BstrFromUInt(ULONG64 ulVal
, LCID lcid
, DWORD dwFlags
, BSTR
*pbstrOut
)
5161 WCHAR szBuff
[64], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5164 return E_INVALIDARG
;
5166 /* Create the basic number string */
5168 szOut
= VARIANT_WriteNumber(ulVal
, szOut
);
5170 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5171 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5172 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5175 /******************************************************************************
5176 * VarBstrFromUI1 (OLEAUT32.108)
5178 * Convert a VT_UI1 to a VT_BSTR.
5182 * lcid [I] LCID for the conversion
5183 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5184 * pbstrOut [O] Destination
5188 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5189 * E_OUTOFMEMORY, if memory allocation fails.
5191 HRESULT WINAPI
VarBstrFromUI1(BYTE bIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5193 return VARIANT_BstrFromUInt(bIn
, lcid
, dwFlags
, pbstrOut
);
5196 /******************************************************************************
5197 * VarBstrFromI2 (OLEAUT32.109)
5199 * Convert a VT_I2 to a VT_BSTR.
5203 * lcid [I] LCID for the conversion
5204 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5205 * pbstrOut [O] Destination
5209 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5210 * E_OUTOFMEMORY, if memory allocation fails.
5212 HRESULT WINAPI
VarBstrFromI2(short sIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5219 dwFlags
|= VAR_NEGATIVE
;
5221 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5224 /******************************************************************************
5225 * VarBstrFromI4 (OLEAUT32.110)
5227 * Convert a VT_I4 to a VT_BSTR.
5231 * lcid [I] LCID for the conversion
5232 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5233 * pbstrOut [O] Destination
5237 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5238 * E_OUTOFMEMORY, if memory allocation fails.
5240 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5247 dwFlags
|= VAR_NEGATIVE
;
5249 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5252 static HRESULT
VARIANT_BstrFromReal(DOUBLE dblIn
, LCID lcid
, ULONG dwFlags
,
5253 BSTR
* pbstrOut
, LPCWSTR lpszFormat
)
5258 return E_INVALIDARG
;
5260 sprintfW( buff
, lpszFormat
, dblIn
);
5261 TRACE("created string %s\n", debugstr_w(buff
));
5262 if (dwFlags
& LOCALE_USE_NLS
)
5266 /* Format the number for the locale */
5268 GetNumberFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5269 buff
, NULL
, numbuff
, sizeof(numbuff
) / sizeof(WCHAR
));
5270 TRACE("created NLS string %s\n", debugstr_w(numbuff
));
5271 *pbstrOut
= SysAllocString(numbuff
);
5274 *pbstrOut
= SysAllocString(buff
);
5275 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5278 /******************************************************************************
5279 * VarBstrFromR4 (OLEAUT32.111)
5281 * Convert a VT_R4 to a VT_BSTR.
5285 * lcid [I] LCID for the conversion
5286 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5287 * pbstrOut [O] Destination
5291 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5292 * E_OUTOFMEMORY, if memory allocation fails.
5294 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5296 return VARIANT_BstrFromReal(fltIn
, lcid
, dwFlags
, pbstrOut
, szFloatFormatW
);
5299 /******************************************************************************
5300 * VarBstrFromR8 (OLEAUT32.112)
5302 * Convert a VT_R8 to a VT_BSTR.
5306 * lcid [I] LCID for the conversion
5307 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5308 * pbstrOut [O] Destination
5312 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5313 * E_OUTOFMEMORY, if memory allocation fails.
5315 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5317 return VARIANT_BstrFromReal(dblIn
, lcid
, dwFlags
, pbstrOut
, szDoubleFormatW
);
5320 /******************************************************************************
5321 * VarBstrFromCy [OLEAUT32.113]
5323 * Convert a VT_CY to a VT_BSTR.
5327 * lcid [I] LCID for the conversion
5328 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5329 * pbstrOut [O] Destination
5333 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5334 * E_OUTOFMEMORY, if memory allocation fails.
5336 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
)
5342 return E_INVALIDARG
;
5344 VarR8FromCy(cyIn
, &dblVal
);
5345 sprintfW(buff
, szDoubleFormatW
, dblVal
);
5347 if (dwFlags
& LOCALE_USE_NLS
)
5351 /* Format the currency for the locale */
5353 GetCurrencyFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5354 buff
, NULL
, cybuff
, sizeof(cybuff
) / sizeof(WCHAR
));
5355 *pbstrOut
= SysAllocString(cybuff
);
5358 *pbstrOut
= SysAllocString(buff
);
5360 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5363 /******************************************************************************
5364 * VarBstrFromDate [OLEAUT32.114]
5366 * Convert a VT_DATE to a VT_BSTR.
5370 * lcid [I] LCID for the conversion
5371 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5372 * pbstrOut [O] Destination
5376 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5377 * E_OUTOFMEMORY, if memory allocation fails.
5379 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5382 DWORD dwFormatFlags
= dwFlags
& LOCALE_NOUSEROVERRIDE
;
5383 WCHAR date
[128], *time
;
5385 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
5387 if (!pbstrOut
|| !VariantTimeToSystemTime(dateIn
, &st
))
5388 return E_INVALIDARG
;
5392 if (dwFlags
& VAR_CALENDAR_THAI
)
5393 st
.wYear
+= 553; /* Use the Thai buddhist calendar year */
5394 else if (dwFlags
& (VAR_CALENDAR_HIJRI
|VAR_CALENDAR_GREGORIAN
))
5395 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5397 if (dwFlags
& LOCALE_USE_NLS
)
5398 dwFlags
&= ~(VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
);
5401 double whole
= dateIn
< 0 ? ceil(dateIn
) : floor(dateIn
);
5402 double partial
= dateIn
- whole
;
5405 dwFlags
|= VAR_TIMEVALUEONLY
;
5406 else if (partial
< 1e-12)
5407 dwFlags
|= VAR_DATEVALUEONLY
;
5410 if (dwFlags
& VAR_TIMEVALUEONLY
)
5413 if (!GetDateFormatW(lcid
, dwFormatFlags
|DATE_SHORTDATE
, &st
, NULL
, date
,
5414 sizeof(date
)/sizeof(WCHAR
)))
5415 return E_INVALIDARG
;
5417 if (!(dwFlags
& VAR_DATEVALUEONLY
))
5419 time
= date
+ strlenW(date
);
5422 if (!GetTimeFormatW(lcid
, dwFormatFlags
, &st
, NULL
, time
,
5423 sizeof(date
)/sizeof(WCHAR
)-(time
-date
)))
5424 return E_INVALIDARG
;
5427 *pbstrOut
= SysAllocString(date
);
5429 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5430 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5433 /******************************************************************************
5434 * VarBstrFromBool (OLEAUT32.116)
5436 * Convert a VT_BOOL to a VT_BSTR.
5440 * lcid [I] LCID for the conversion
5441 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5442 * pbstrOut [O] Destination
5446 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5447 * E_OUTOFMEMORY, if memory allocation fails.
5450 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5451 * localised text of "True" or "False". To convert a bool into a
5452 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5454 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5457 DWORD dwResId
= IDS_TRUE
;
5460 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
5463 return E_INVALIDARG
;
5465 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5466 * for variant formatting */
5467 switch (dwFlags
& (VAR_LOCALBOOL
|VAR_BOOLONOFF
|VAR_BOOLYESNO
))
5478 lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
),SORT_DEFAULT
);
5481 lcid
= ConvertDefaultLocale(lcid
);
5482 langId
= LANGIDFROMLCID(lcid
);
5483 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
5484 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5486 if (boolIn
== VARIANT_FALSE
)
5487 dwResId
++; /* Use negative form */
5489 VarBstrFromBool_GetLocalised
:
5490 if (VARIANT_GetLocalisedText(langId
, dwResId
, szBuff
))
5492 *pbstrOut
= SysAllocString(szBuff
);
5493 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5496 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
5498 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5499 goto VarBstrFromBool_GetLocalised
;
5502 /* Should never get here */
5503 WARN("Failed to load bool text!\n");
5504 return E_OUTOFMEMORY
;
5507 /******************************************************************************
5508 * VarBstrFromI1 (OLEAUT32.229)
5510 * Convert a VT_I1 to a VT_BSTR.
5514 * lcid [I] LCID for the conversion
5515 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5516 * pbstrOut [O] Destination
5520 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5521 * E_OUTOFMEMORY, if memory allocation fails.
5523 HRESULT WINAPI
VarBstrFromI1(signed char cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5530 dwFlags
|= VAR_NEGATIVE
;
5532 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5535 /******************************************************************************
5536 * VarBstrFromUI2 (OLEAUT32.230)
5538 * Convert a VT_UI2 to a VT_BSTR.
5542 * lcid [I] LCID for the conversion
5543 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5544 * pbstrOut [O] Destination
5548 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5549 * E_OUTOFMEMORY, if memory allocation fails.
5551 HRESULT WINAPI
VarBstrFromUI2(USHORT usIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5553 return VARIANT_BstrFromUInt(usIn
, lcid
, dwFlags
, pbstrOut
);
5556 /******************************************************************************
5557 * VarBstrFromUI4 (OLEAUT32.231)
5559 * Convert a VT_UI4 to a VT_BSTR.
5563 * lcid [I] LCID for the conversion
5564 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5565 * pbstrOut [O] Destination
5569 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5570 * E_OUTOFMEMORY, if memory allocation fails.
5572 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5574 return VARIANT_BstrFromUInt(ulIn
, lcid
, dwFlags
, pbstrOut
);
5577 /******************************************************************************
5578 * VarBstrFromDec (OLEAUT32.232)
5580 * Convert a VT_DECIMAL to a VT_BSTR.
5584 * lcid [I] LCID for the conversion
5585 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5586 * pbstrOut [O] Destination
5590 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5591 * E_OUTOFMEMORY, if memory allocation fails.
5593 HRESULT WINAPI
VarBstrFromDec(DECIMAL
* pDecIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5596 return E_INVALIDARG
;
5598 if (!DEC_SCALE(pDecIn
) && !DEC_HI32(pDecIn
))
5600 WCHAR szBuff
[256], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5602 /* Create the basic number string */
5604 szOut
= VARIANT_WriteNumber(DEC_LO64(pDecIn
), szOut
);
5605 if (DEC_SIGN(pDecIn
))
5606 dwFlags
|= VAR_NEGATIVE
;
5608 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5609 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5610 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5612 FIXME("semi-stub\n");
5613 return E_INVALIDARG
;
5616 /************************************************************************
5617 * VarBstrFromI8 (OLEAUT32.370)
5619 * Convert a VT_I8 to a VT_BSTR.
5623 * lcid [I] LCID for the conversion
5624 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5625 * pbstrOut [O] Destination
5629 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5630 * E_OUTOFMEMORY, if memory allocation fails.
5632 HRESULT WINAPI
VarBstrFromI8(LONG64 llIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5634 ULONG64 ul64
= llIn
;
5639 dwFlags
|= VAR_NEGATIVE
;
5641 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5644 /************************************************************************
5645 * VarBstrFromUI8 (OLEAUT32.371)
5647 * Convert a VT_UI8 to a VT_BSTR.
5651 * lcid [I] LCID for the conversion
5652 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5653 * pbstrOut [O] Destination
5657 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5658 * E_OUTOFMEMORY, if memory allocation fails.
5660 HRESULT WINAPI
VarBstrFromUI8(ULONG64 ullIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5662 return VARIANT_BstrFromUInt(ullIn
, lcid
, dwFlags
, pbstrOut
);
5665 /**********************************************************************
5666 * VarBstrCat (OLEAUT32.313)
5668 * Concatenate two BSTR values.
5671 * pbstrLeft [I] Source
5672 * pbstrRight [I] Value to concatenate
5673 * pbstrOut [O] Destination
5677 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5678 * E_OUTOFMEMORY, if memory allocation fails.
5680 HRESULT WINAPI
VarBstrCat(BSTR pbstrLeft
, BSTR pbstrRight
, BSTR
*pbstrOut
)
5685 return E_INVALIDARG
;
5687 len
= pbstrLeft
? strlenW(pbstrLeft
) : 0;
5689 len
+= strlenW(pbstrRight
);
5691 *pbstrOut
= SysAllocStringLen(NULL
, len
);
5693 return E_OUTOFMEMORY
;
5695 (*pbstrOut
)[0] = '\0';
5698 strcpyW(*pbstrOut
, pbstrLeft
);
5701 strcatW(*pbstrOut
, pbstrRight
);
5706 /**********************************************************************
5707 * VarBstrCmp (OLEAUT32.314)
5709 * Compare two BSTR values.
5712 * pbstrLeft [I] Source
5713 * pbstrRight [I] Value to compare
5714 * lcid [I] LCID for the comparison
5715 * dwFlags [I] Flags to pass directly to CompareStringW().
5718 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5719 * than, equal to or greater than pbstrRight respectively.
5720 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5721 * in which case VARCMP_EQ is returned.
5723 HRESULT WINAPI
VarBstrCmp(BSTR pbstrLeft
, BSTR pbstrRight
, LCID lcid
, DWORD dwFlags
)
5727 if (!pbstrRight
|| !*pbstrRight
)
5731 else if (!pbstrRight
)
5738 return CompareStringW(lcid
, dwFlags
, pbstrLeft
, -1, pbstrRight
, -1) - 1;
5745 /******************************************************************************
5746 * VarDateFromUI1 (OLEAUT32.88)
5748 * Convert a VT_UI1 to a VT_DATE.
5752 * pdateOut [O] Destination
5757 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
5759 return _VarDateFromUI1(bIn
, pdateOut
);
5762 /******************************************************************************
5763 * VarDateFromI2 (OLEAUT32.89)
5765 * Convert a VT_I2 to a VT_DATE.
5769 * pdateOut [O] Destination
5774 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
5776 return _VarDateFromI2(sIn
, pdateOut
);
5779 /******************************************************************************
5780 * VarDateFromI4 (OLEAUT32.90)
5782 * Convert a VT_I4 to a VT_DATE.
5786 * pdateOut [O] Destination
5791 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
5793 return _VarDateFromI4(lIn
, pdateOut
);
5796 /******************************************************************************
5797 * VarDateFromR4 (OLEAUT32.91)
5799 * Convert a VT_R4 to a VT_DATE.
5803 * pdateOut [O] Destination
5808 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
5810 return _VarDateFromR4(fltIn
, pdateOut
);
5813 /******************************************************************************
5814 * VarDateFromR8 (OLEAUT32.92)
5816 * Convert a VT_R8 to a VT_DATE.
5820 * pdateOut [O] Destination
5825 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
5827 return _VarDateFromR8(dblIn
, pdateOut
);
5830 /**********************************************************************
5831 * VarDateFromDisp (OLEAUT32.95)
5833 * Convert a VT_DISPATCH to a VT_DATE.
5836 * pdispIn [I] Source
5837 * lcid [I] LCID for conversion
5838 * pdateOut [O] Destination
5842 * Failure: E_INVALIDARG, if the source value is invalid
5843 * DISP_E_OVERFLOW, if the value will not fit in the destination
5844 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5846 HRESULT WINAPI
VarDateFromDisp(IDispatch
* pdispIn
, LCID lcid
, DATE
* pdateOut
)
5848 return _VarDateFromDisp(pdispIn
, lcid
, pdateOut
);
5851 /******************************************************************************
5852 * VarDateFromBool (OLEAUT32.96)
5854 * Convert a VT_BOOL to a VT_DATE.
5858 * pdateOut [O] Destination
5863 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
5865 return _VarDateFromBool(boolIn
, pdateOut
);
5868 /**********************************************************************
5869 * VarDateFromCy (OLEAUT32.93)
5871 * Convert a VT_CY to a VT_DATE.
5875 * pdateOut [O] Destination
5880 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
)
5882 return _VarDateFromCy(cyIn
, pdateOut
);
5885 /* Date string parsing */
5886 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
5887 #define DP_DATESEP 0x02 /* Date separator */
5888 #define DP_MONTH 0x04 /* Month name */
5889 #define DP_AM 0x08 /* AM */
5890 #define DP_PM 0x10 /* PM */
5892 typedef struct tagDATEPARSE
5894 DWORD dwCount
; /* Number of fields found so far (maximum 6) */
5895 DWORD dwParseFlags
; /* Global parse flags (DP_ Flags above) */
5896 DWORD dwFlags
[6]; /* Flags for each field */
5897 DWORD dwValues
[6]; /* Value of each field */
5900 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
5902 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5904 /* Determine if a day is valid in a given month of a given year */
5905 static BOOL
VARIANT_IsValidMonthDay(DWORD day
, DWORD month
, DWORD year
)
5907 static const BYTE days
[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
5909 if (day
&& month
&& month
< 13)
5911 if (day
<= days
[month
] || (month
== 2 && day
== 29 && IsLeapYear(year
)))
5917 /* Possible orders for 3 numbers making up a date */
5918 #define ORDER_MDY 0x01
5919 #define ORDER_YMD 0x02
5920 #define ORDER_YDM 0x04
5921 #define ORDER_DMY 0x08
5922 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
5924 /* Determine a date for a particular locale, from 3 numbers */
5925 static inline HRESULT
VARIANT_MakeDate(DATEPARSE
*dp
, DWORD iDate
,
5926 DWORD offset
, SYSTEMTIME
*st
)
5928 DWORD dwAllOrders
, dwTry
, dwCount
= 0, v1
, v2
, v3
;
5932 v1
= 30; /* Default to (Variant) 0 date part */
5935 goto VARIANT_MakeDate_OK
;
5938 v1
= dp
->dwValues
[offset
+ 0];
5939 v2
= dp
->dwValues
[offset
+ 1];
5940 if (dp
->dwCount
== 2)
5943 GetSystemTime(¤t
);
5947 v3
= dp
->dwValues
[offset
+ 2];
5949 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1
, v2
, v3
, iDate
, offset
);
5951 /* If one number must be a month (Because a month name was given), then only
5952 * consider orders with the month in that position.
5953 * If we took the current year as 'v3', then only allow a year in that position.
5955 if (dp
->dwFlags
[offset
+ 0] & DP_MONTH
)
5957 dwAllOrders
= ORDER_MDY
;
5959 else if (dp
->dwFlags
[offset
+ 1] & DP_MONTH
)
5961 dwAllOrders
= ORDER_DMY
;
5962 if (dp
->dwCount
> 2)
5963 dwAllOrders
|= ORDER_YMD
;
5965 else if (dp
->dwCount
> 2 && dp
->dwFlags
[offset
+ 2] & DP_MONTH
)
5967 dwAllOrders
= ORDER_YDM
;
5971 dwAllOrders
= ORDER_MDY
|ORDER_DMY
;
5972 if (dp
->dwCount
> 2)
5973 dwAllOrders
|= (ORDER_YMD
|ORDER_YDM
);
5976 VARIANT_MakeDate_Start
:
5977 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders
);
5985 /* First: Try the order given by iDate */
5988 case 0: dwTry
= dwAllOrders
& ORDER_MDY
; break;
5989 case 1: dwTry
= dwAllOrders
& ORDER_DMY
; break;
5990 default: dwTry
= dwAllOrders
& ORDER_YMD
; break;
5993 else if (dwCount
== 1)
5995 /* Second: Try all the orders compatible with iDate */
5998 case 0: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
5999 case 1: dwTry
= dwAllOrders
& ~(ORDER_MDY
|ORDER_YMD
|ORDER_MYD
); break;
6000 default: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
6005 /* Finally: Try any remaining orders */
6006 dwTry
= dwAllOrders
;
6009 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount
, dwTry
);
6015 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6017 if (dwTry
& ORDER_MDY
)
6019 if (VARIANT_IsValidMonthDay(v2
,v1
,v3
))
6022 goto VARIANT_MakeDate_OK
;
6024 dwAllOrders
&= ~ORDER_MDY
;
6026 if (dwTry
& ORDER_YMD
)
6028 if (VARIANT_IsValidMonthDay(v3
,v2
,v1
))
6031 goto VARIANT_MakeDate_OK
;
6033 dwAllOrders
&= ~ORDER_YMD
;
6035 if (dwTry
& ORDER_YDM
)
6037 if (VARIANT_IsValidMonthDay(v2
,v3
,v1
))
6041 goto VARIANT_MakeDate_OK
;
6043 dwAllOrders
&= ~ORDER_YDM
;
6045 if (dwTry
& ORDER_DMY
)
6047 if (VARIANT_IsValidMonthDay(v1
,v2
,v3
))
6048 goto VARIANT_MakeDate_OK
;
6049 dwAllOrders
&= ~ORDER_DMY
;
6051 if (dwTry
& ORDER_MYD
)
6053 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6054 if (VARIANT_IsValidMonthDay(v3
,v1
,v2
))
6058 goto VARIANT_MakeDate_OK
;
6060 dwAllOrders
&= ~ORDER_MYD
;
6064 if (dp
->dwCount
== 2)
6066 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6067 v3
= 1; /* 1st of the month */
6068 dwAllOrders
= ORDER_YMD
|ORDER_MYD
;
6069 dp
->dwCount
= 0; /* Don't return to this code path again */
6071 goto VARIANT_MakeDate_Start
;
6074 /* No valid dates were able to be constructed */
6075 return DISP_E_TYPEMISMATCH
;
6077 VARIANT_MakeDate_OK
:
6079 /* Check that the time part is ok */
6080 if (st
->wHour
> 23 || st
->wMinute
> 59 || st
->wSecond
> 59)
6081 return DISP_E_TYPEMISMATCH
;
6083 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6084 if (st
->wHour
< 12 && (dp
->dwParseFlags
& DP_PM
))
6086 else if (st
->wHour
== 12 && (dp
->dwParseFlags
& DP_AM
))
6088 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6092 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6093 * be retrieved from:
6094 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6095 * But Wine doesn't have/use that key as at the time of writing.
6097 st
->wYear
= v3
< 30 ? 2000 + v3
: v3
< 100 ? 1900 + v3
: v3
;
6098 TRACE("Returning date %ld/%ld/%d\n", v1
, v2
, st
->wYear
);
6102 /******************************************************************************
6103 * VarDateFromStr [OLEAUT32.94]
6105 * Convert a VT_BSTR to at VT_DATE.
6108 * strIn [I] String to convert
6109 * lcid [I] Locale identifier for the conversion
6110 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6111 * pdateOut [O] Destination for the converted value
6114 * Success: S_OK. pdateOut contains the converted value.
6115 * FAILURE: An HRESULT error code indicating the prolem.
6118 * Any date format that can be created using the date formats from lcid
6119 * (Either from kernel Nls functions, variant conversion or formatting) is a
6120 * valid input to this function. In addition, a few more esoteric formats are
6121 * also supported for compatibility with the native version. The date is
6122 * interpreted according to the date settings in the control panel, unless
6123 * the date is invalid in that format, in which the most compatible format
6124 * that produces a valid date will be used.
6126 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
6128 static const USHORT ParseDateTokens
[] =
6130 LOCALE_SMONTHNAME1
, LOCALE_SMONTHNAME2
, LOCALE_SMONTHNAME3
, LOCALE_SMONTHNAME4
,
6131 LOCALE_SMONTHNAME5
, LOCALE_SMONTHNAME6
, LOCALE_SMONTHNAME7
, LOCALE_SMONTHNAME8
,
6132 LOCALE_SMONTHNAME9
, LOCALE_SMONTHNAME10
, LOCALE_SMONTHNAME11
, LOCALE_SMONTHNAME12
,
6133 LOCALE_SMONTHNAME13
,
6134 LOCALE_SABBREVMONTHNAME1
, LOCALE_SABBREVMONTHNAME2
, LOCALE_SABBREVMONTHNAME3
,
6135 LOCALE_SABBREVMONTHNAME4
, LOCALE_SABBREVMONTHNAME5
, LOCALE_SABBREVMONTHNAME6
,
6136 LOCALE_SABBREVMONTHNAME7
, LOCALE_SABBREVMONTHNAME8
, LOCALE_SABBREVMONTHNAME9
,
6137 LOCALE_SABBREVMONTHNAME10
, LOCALE_SABBREVMONTHNAME11
, LOCALE_SABBREVMONTHNAME12
,
6138 LOCALE_SABBREVMONTHNAME13
,
6139 LOCALE_SDAYNAME1
, LOCALE_SDAYNAME2
, LOCALE_SDAYNAME3
, LOCALE_SDAYNAME4
,
6140 LOCALE_SDAYNAME5
, LOCALE_SDAYNAME6
, LOCALE_SDAYNAME7
,
6141 LOCALE_SABBREVDAYNAME1
, LOCALE_SABBREVDAYNAME2
, LOCALE_SABBREVDAYNAME3
,
6142 LOCALE_SABBREVDAYNAME4
, LOCALE_SABBREVDAYNAME5
, LOCALE_SABBREVDAYNAME6
,
6143 LOCALE_SABBREVDAYNAME7
,
6144 LOCALE_S1159
, LOCALE_S2359
6146 static const BYTE ParseDateMonths
[] =
6148 1,2,3,4,5,6,7,8,9,10,11,12,13,
6149 1,2,3,4,5,6,7,8,9,10,11,12,13
6152 BSTR tokens
[sizeof(ParseDateTokens
)/sizeof(ParseDateTokens
[0])];
6154 DWORD dwDateSeps
= 0, iDate
= 0;
6155 HRESULT hRet
= S_OK
;
6157 if ((dwFlags
& (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
)) ==
6158 (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
))
6159 return E_INVALIDARG
;
6162 return DISP_E_TYPEMISMATCH
;
6166 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn
), lcid
, dwFlags
, pdateOut
);
6168 memset(&dp
, 0, sizeof(dp
));
6170 GetLocaleInfoW(lcid
, LOCALE_IDATE
|LOCALE_RETURN_NUMBER
|(dwFlags
& LOCALE_NOUSEROVERRIDE
),
6171 (LPWSTR
)&iDate
, sizeof(iDate
)/sizeof(WCHAR
));
6172 TRACE("iDate is %ld\n", iDate
);
6174 /* Get the month/day/am/pm tokens for this locale */
6175 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6178 LCTYPE lctype
= ParseDateTokens
[i
] | (dwFlags
& LOCALE_NOUSEROVERRIDE
);
6180 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6181 * GetAltMonthNames(). We should really cache these strings too.
6184 GetLocaleInfoW(lcid
, lctype
, buff
, sizeof(buff
)/sizeof(WCHAR
));
6185 tokens
[i
] = SysAllocString(buff
);
6186 TRACE("token %d is %s\n", i
, debugstr_w(tokens
[i
]));
6189 /* Parse the string into our structure */
6195 if (isdigitW(*strIn
))
6197 dp
.dwValues
[dp
.dwCount
] = strtoulW(strIn
, &strIn
, 10);
6201 else if (isalpha(*strIn
))
6203 BOOL bFound
= FALSE
;
6205 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6207 DWORD dwLen
= strlenW(tokens
[i
]);
6208 if (dwLen
&& !strncmpiW(strIn
, tokens
[i
], dwLen
))
6212 dp
.dwValues
[dp
.dwCount
] = ParseDateMonths
[i
];
6213 dp
.dwFlags
[dp
.dwCount
] |= (DP_MONTH
|DP_DATESEP
);
6218 if (!dp
.dwCount
|| dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6219 hRet
= DISP_E_TYPEMISMATCH
;
6222 dp
.dwFlags
[dp
.dwCount
- 1] |= (i
== 40 ? DP_AM
: DP_PM
);
6223 dp
.dwParseFlags
|= (i
== 40 ? DP_AM
: DP_PM
);
6226 strIn
+= (dwLen
- 1);
6234 if ((*strIn
== 'a' || *strIn
== 'A' || *strIn
== 'p' || *strIn
== 'P') &&
6235 (dp
.dwCount
&& !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6237 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6238 if (*strIn
== 'a' || *strIn
== 'A')
6240 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_AM
;
6241 dp
.dwParseFlags
|= DP_AM
;
6245 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_PM
;
6246 dp
.dwParseFlags
|= DP_PM
;
6252 TRACE("No matching token for %s\n", debugstr_w(strIn
));
6253 hRet
= DISP_E_TYPEMISMATCH
;
6258 else if (*strIn
== ':' || *strIn
== '.')
6260 if (!dp
.dwCount
|| !strIn
[1])
6261 hRet
= DISP_E_TYPEMISMATCH
;
6263 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_TIMESEP
;
6265 else if (*strIn
== '-' || *strIn
== '/')
6268 if (dwDateSeps
> 2 || !dp
.dwCount
|| !strIn
[1])
6269 hRet
= DISP_E_TYPEMISMATCH
;
6271 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_DATESEP
;
6273 else if (*strIn
== ',' || isspaceW(*strIn
))
6275 if (*strIn
== ',' && !strIn
[1])
6276 hRet
= DISP_E_TYPEMISMATCH
;
6280 hRet
= DISP_E_TYPEMISMATCH
;
6285 if (!dp
.dwCount
|| dp
.dwCount
> 6 ||
6286 (dp
.dwCount
== 1 && !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6287 hRet
= DISP_E_TYPEMISMATCH
;
6289 if (SUCCEEDED(hRet
))
6292 DWORD dwOffset
= 0; /* Start of date fields in dp.dwValues */
6294 st
.wDayOfWeek
= st
.wHour
= st
.wMinute
= st
.wSecond
= st
.wMilliseconds
= 0;
6296 /* Figure out which numbers correspond to which fields.
6298 * This switch statement works based on the fact that native interprets any
6299 * fields that are not joined with a time separator ('.' or ':') as date
6300 * fields. Thus we construct a value from 0-32 where each set bit indicates
6301 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6302 * For valid permutations, we set dwOffset to point to the first date field
6303 * and shorten dp.dwCount by the number of time fields found. The real
6304 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6305 * each date number must represent in the context of iDate.
6307 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6309 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6311 case 0x1: /* TT TTDD TTDDD */
6312 if (dp
.dwCount
> 3 &&
6313 ((dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) ||
6314 (dp
.dwFlags
[4] & (DP_AM
|DP_PM
))))
6315 hRet
= DISP_E_TYPEMISMATCH
;
6316 else if (dp
.dwCount
!= 2 && dp
.dwCount
!= 4 && dp
.dwCount
!= 5)
6317 hRet
= DISP_E_TYPEMISMATCH
;
6318 st
.wHour
= dp
.dwValues
[0];
6319 st
.wMinute
= dp
.dwValues
[1];
6324 case 0x3: /* TTT TTTDD TTTDDD */
6325 if (dp
.dwCount
> 4 &&
6326 ((dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[4] & (DP_AM
|DP_PM
)) ||
6327 (dp
.dwFlags
[5] & (DP_AM
|DP_PM
))))
6328 hRet
= DISP_E_TYPEMISMATCH
;
6329 else if (dp
.dwCount
!= 3 && dp
.dwCount
!= 5 && dp
.dwCount
!= 6)
6330 hRet
= DISP_E_TYPEMISMATCH
;
6331 st
.wHour
= dp
.dwValues
[0];
6332 st
.wMinute
= dp
.dwValues
[1];
6333 st
.wSecond
= dp
.dwValues
[2];
6338 case 0x4: /* DDTT */
6339 if (dp
.dwCount
!= 4 ||
6340 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6341 hRet
= DISP_E_TYPEMISMATCH
;
6343 st
.wHour
= dp
.dwValues
[2];
6344 st
.wMinute
= dp
.dwValues
[3];
6348 case 0x0: /* T DD DDD TDDD TDDD */
6349 if (dp
.dwCount
== 1 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6351 st
.wHour
= dp
.dwValues
[0]; /* T */
6355 else if (dp
.dwCount
> 4 || (dp
.dwCount
< 3 && dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6357 hRet
= DISP_E_TYPEMISMATCH
;
6359 else if (dp
.dwCount
== 3)
6361 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDD */
6364 st
.wHour
= dp
.dwValues
[0];
6368 if (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) /* DDT */
6371 st
.wHour
= dp
.dwValues
[2];
6374 else if (dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6375 hRet
= DISP_E_TYPEMISMATCH
;
6377 else if (dp
.dwCount
== 4)
6380 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDDD */
6382 st
.wHour
= dp
.dwValues
[0];
6385 else if (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) /* DDDT */
6387 st
.wHour
= dp
.dwValues
[3];
6390 hRet
= DISP_E_TYPEMISMATCH
;
6393 /* .. fall through .. */
6395 case 0x8: /* DDDTT */
6396 if ((dp
.dwCount
== 2 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
))) ||
6397 (dp
.dwCount
== 5 && ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) ||
6398 (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))) ||
6399 dp
.dwCount
== 4 || dp
.dwCount
== 6)
6400 hRet
= DISP_E_TYPEMISMATCH
;
6401 st
.wHour
= dp
.dwValues
[3];
6402 st
.wMinute
= dp
.dwValues
[4];
6403 if (dp
.dwCount
== 5)
6407 case 0xC: /* DDTTT */
6408 if (dp
.dwCount
!= 5 ||
6409 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6410 hRet
= DISP_E_TYPEMISMATCH
;
6411 st
.wHour
= dp
.dwValues
[2];
6412 st
.wMinute
= dp
.dwValues
[3];
6413 st
.wSecond
= dp
.dwValues
[4];
6417 case 0x18: /* DDDTTT */
6418 if ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) ||
6419 (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))
6420 hRet
= DISP_E_TYPEMISMATCH
;
6421 st
.wHour
= dp
.dwValues
[3];
6422 st
.wMinute
= dp
.dwValues
[4];
6423 st
.wSecond
= dp
.dwValues
[5];
6428 hRet
= DISP_E_TYPEMISMATCH
;
6432 if (SUCCEEDED(hRet
))
6434 hRet
= VARIANT_MakeDate(&dp
, iDate
, dwOffset
, &st
);
6436 if (dwFlags
& VAR_TIMEVALUEONLY
)
6442 else if (dwFlags
& VAR_DATEVALUEONLY
)
6443 st
.wHour
= st
.wMinute
= st
.wSecond
= 0;
6445 /* Finally, convert the value to a VT_DATE */
6446 if (SUCCEEDED(hRet
))
6447 hRet
= SystemTimeToVariantTime(&st
, pdateOut
) ? S_OK
: DISP_E_TYPEMISMATCH
;
6451 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6452 SysFreeString(tokens
[i
]);
6456 /******************************************************************************
6457 * VarDateFromI1 (OLEAUT32.221)
6459 * Convert a VT_I1 to a VT_DATE.
6463 * pdateOut [O] Destination
6468 HRESULT WINAPI
VarDateFromI1(signed char cIn
, DATE
* pdateOut
)
6470 return _VarDateFromI1(cIn
, pdateOut
);
6473 /******************************************************************************
6474 * VarDateFromUI2 (OLEAUT32.222)
6476 * Convert a VT_UI2 to a VT_DATE.
6480 * pdateOut [O] Destination
6485 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
6487 return _VarDateFromUI2(uiIn
, pdateOut
);
6490 /******************************************************************************
6491 * VarDateFromUI4 (OLEAUT32.223)
6493 * Convert a VT_UI4 to a VT_DATE.
6497 * pdateOut [O] Destination
6502 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
6504 return _VarDateFromUI4(ulIn
, pdateOut
);
6507 /**********************************************************************
6508 * VarDateFromDec (OLEAUT32.224)
6510 * Convert a VT_DECIMAL to a VT_DATE.
6514 * pdateOut [O] Destination
6519 HRESULT WINAPI
VarDateFromDec(DECIMAL
*pdecIn
, DATE
* pdateOut
)
6521 return _VarDateFromDec(pdecIn
, pdateOut
);
6524 /******************************************************************************
6525 * VarDateFromI8 (OLEAUT32.364)
6527 * Convert a VT_I8 to a VT_DATE.
6531 * pdateOut [O] Destination
6535 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6537 HRESULT WINAPI
VarDateFromI8(LONG64 llIn
, DATE
* pdateOut
)
6539 return _VarDateFromI8(llIn
, pdateOut
);
6542 /******************************************************************************
6543 * VarDateFromUI8 (OLEAUT32.365)
6545 * Convert a VT_UI8 to a VT_DATE.
6549 * pdateOut [O] Destination
6553 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6555 HRESULT WINAPI
VarDateFromUI8(ULONG64 ullIn
, DATE
* pdateOut
)
6557 return _VarDateFromUI8(ullIn
, pdateOut
);