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
20 #define NONAMELESSUNION
21 #define NONAMELESSSTRUCT
22 #include "wine/debug.h"
23 #include "wine/unicode.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
33 extern HMODULE OLEAUT32_hModule
;
35 static const WCHAR szFloatFormatW
[] = { '%','.','7','G','\0' };
36 static const WCHAR szDoubleFormatW
[] = { '%','.','1','5','G','\0' };
38 /* Copy data from one variant to another. */
39 static inline void VARIANT_CopyData(const VARIANT
*srcVar
, VARTYPE vt
, void *pOut
)
44 case VT_UI1
: memcpy(pOut
, &V_UI1(srcVar
), sizeof(BYTE
)); break;
47 case VT_UI2
: memcpy(pOut
, &V_UI2(srcVar
), sizeof(SHORT
));
53 case VT_UI4
: memcpy(pOut
, &V_UI4(srcVar
), sizeof (LONG
));
59 case VT_UI8
: memcpy(pOut
, &V_UI8(srcVar
), sizeof (LONG64
));
61 case VT_INT_PTR
: memcpy(pOut
, &V_INT_PTR(srcVar
), sizeof (INT_PTR
)); break;
62 case VT_DECIMAL
: memcpy(pOut
, &V_DECIMAL(srcVar
), sizeof (DECIMAL
)); break;
64 FIXME("VT_ type %d unhandled, please report!\n", vt
);
69 /* Coerce VT_BSTR to a numeric type */
70 HRESULT
VARIANT_NumberFromBstr(OLECHAR
* pStrIn
, LCID lcid
, ULONG ulFlags
,
71 void* pOut
, VARTYPE vt
)
78 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
79 np
.cDig
= sizeof(rgb
) / sizeof(BYTE
);
80 np
.dwInFlags
= NUMPRS_STD
;
82 hRet
= VarParseNumFromStr(pStrIn
, lcid
, ulFlags
, &np
, rgb
);
86 /* 1 << vt gives us the VTBIT constant for the destination number type */
87 hRet
= VarNumFromParseNum(&np
, rgb
, 1 << vt
, &dstVar
);
89 VARIANT_CopyData(&dstVar
, vt
, pOut
);
94 /* Coerce VT_DISPATCH to another type */
95 HRESULT
VARIANT_FromDisp(IDispatch
* pdispIn
, LCID lcid
, void* pOut
, VARTYPE vt
)
97 static const DISPPARAMS emptyParams
= { NULL
, NULL
, 0, 0 };
98 VARIANTARG srcVar
, dstVar
;
102 return DISP_E_BADVARTYPE
;
104 /* Get the default 'value' property from the IDispatch */
105 hRet
= IDispatch_Invoke(pdispIn
, DISPID_VALUE
, &IID_NULL
, lcid
, DISPATCH_PROPERTYGET
,
106 (DISPPARAMS
*)&emptyParams
, &srcVar
, NULL
, NULL
);
110 /* Convert the property to the requested type */
111 V_VT(&dstVar
) = VT_EMPTY
;
112 hRet
= VariantChangeTypeEx(&dstVar
, &srcVar
, lcid
, 0, vt
);
113 VariantClear(&srcVar
);
117 VARIANT_CopyData(&dstVar
, vt
, pOut
);
118 VariantClear(&srcVar
);
122 hRet
= DISP_E_TYPEMISMATCH
;
129 /************************************************************************
130 * VarI1FromUI1 (OLEAUT32.244)
132 * Convert a VT_UI1 to a VT_I1.
136 * pcOut [O] Destination
140 * Failure: E_INVALIDARG, if the source value is invalid
141 * DISP_E_OVERFLOW, if the value will not fit in the destination
143 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, signed char* pcOut
)
145 return _VarI1FromUI1(bIn
, pcOut
);
148 /************************************************************************
149 * VarI1FromI2 (OLEAUT32.245)
151 * Convert a VT_I2 to a VT_I1.
155 * pcOut [O] Destination
159 * Failure: E_INVALIDARG, if the source value is invalid
160 * DISP_E_OVERFLOW, if the value will not fit in the destination
162 HRESULT WINAPI
VarI1FromI2(SHORT sIn
, signed char* pcOut
)
164 return _VarI1FromI2(sIn
, pcOut
);
167 /************************************************************************
168 * VarI1FromI4 (OLEAUT32.246)
170 * Convert a VT_I4 to a VT_I1.
174 * pcOut [O] Destination
178 * Failure: E_INVALIDARG, if the source value is invalid
179 * DISP_E_OVERFLOW, if the value will not fit in the destination
181 HRESULT WINAPI
VarI1FromI4(LONG iIn
, signed char* pcOut
)
183 return _VarI1FromI4(iIn
, pcOut
);
186 /************************************************************************
187 * VarI1FromR4 (OLEAUT32.247)
189 * Convert a VT_R4 to a VT_I1.
193 * pcOut [O] Destination
197 * Failure: E_INVALIDARG, if the source value is invalid
198 * DISP_E_OVERFLOW, if the value will not fit in the destination
200 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, signed char* pcOut
)
202 return _VarI1FromR4(fltIn
, pcOut
);
205 /************************************************************************
206 * VarI1FromR8 (OLEAUT32.248)
208 * Convert a VT_R8 to a VT_I1.
212 * pcOut [O] Destination
216 * Failure: E_INVALIDARG, if the source value is invalid
217 * DISP_E_OVERFLOW, if the value will not fit in the destination
220 * See VarI8FromR8() for details concerning rounding.
222 HRESULT WINAPI
VarI1FromR8(double dblIn
, signed char* pcOut
)
224 if (dblIn
< (double)I1_MIN
|| dblIn
> (double)I1_MAX
)
225 return DISP_E_OVERFLOW
;
226 OLEAUT32_DutchRound(CHAR
, dblIn
, *pcOut
);
230 /************************************************************************
231 * VarI1FromDate (OLEAUT32.249)
233 * Convert a VT_DATE to a VT_I1.
237 * pcOut [O] Destination
241 * Failure: E_INVALIDARG, if the source value is invalid
242 * DISP_E_OVERFLOW, if the value will not fit in the destination
244 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, signed char* pcOut
)
246 return _VarI1FromDate(dateIn
, pcOut
);
249 /************************************************************************
250 * VarI1FromCy (OLEAUT32.250)
252 * Convert a VT_CY to a VT_I1.
256 * pcOut [O] Destination
260 * Failure: E_INVALIDARG, if the source value is invalid
261 * DISP_E_OVERFLOW, if the value will not fit in the destination
263 HRESULT WINAPI
VarI1FromCy(CY cyIn
, signed char* pcOut
)
267 _VarI4FromCy(cyIn
, &i
);
268 return _VarI1FromI4(i
, pcOut
);
271 /************************************************************************
272 * VarI1FromStr (OLEAUT32.251)
274 * Convert a VT_BSTR to a VT_I1.
278 * lcid [I] LCID for the conversion
279 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
280 * pcOut [O] Destination
284 * Failure: E_INVALIDARG, if the source value is invalid
285 * DISP_E_OVERFLOW, if the value will not fit in the destination
286 * DISP_E_TYPEMISMATCH, if the type cannot be converted
288 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, signed char* pcOut
)
290 return _VarI1FromStr(strIn
, lcid
, dwFlags
, pcOut
);
293 /************************************************************************
294 * VarI1FromDisp (OLEAUT32.252)
296 * Convert a VT_DISPATCH to a VT_I1.
300 * lcid [I] LCID for conversion
301 * pcOut [O] Destination
305 * Failure: E_INVALIDARG, if the source value is invalid
306 * DISP_E_OVERFLOW, if the value will not fit in the destination
307 * DISP_E_TYPEMISMATCH, if the type cannot be converted
309 HRESULT WINAPI
VarI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, signed char* pcOut
)
311 return _VarI1FromDisp(pdispIn
, lcid
, pcOut
);
314 /************************************************************************
315 * VarI1FromBool (OLEAUT32.253)
317 * Convert a VT_BOOL to a VT_I1.
321 * pcOut [O] Destination
326 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, signed char* pcOut
)
328 return _VarI1FromBool(boolIn
, pcOut
);
331 /************************************************************************
332 * VarI1FromUI2 (OLEAUT32.254)
334 * Convert a VT_UI2 to a VT_I1.
338 * pcOut [O] Destination
342 * Failure: E_INVALIDARG, if the source value is invalid
343 * DISP_E_OVERFLOW, if the value will not fit in the destination
345 HRESULT WINAPI
VarI1FromUI2(USHORT usIn
, signed char* pcOut
)
347 return _VarI1FromUI2(usIn
, pcOut
);
350 /************************************************************************
351 * VarI1FromUI4 (OLEAUT32.255)
353 * Convert a VT_UI4 to a VT_I1.
357 * pcOut [O] Destination
361 * Failure: E_INVALIDARG, if the source value is invalid
362 * DISP_E_OVERFLOW, if the value will not fit in the destination
363 * DISP_E_TYPEMISMATCH, if the type cannot be converted
365 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, signed char* pcOut
)
367 return _VarI1FromUI4(ulIn
, pcOut
);
370 /************************************************************************
371 * VarI1FromDec (OLEAUT32.256)
373 * Convert a VT_DECIMAL to a VT_I1.
377 * pcOut [O] Destination
381 * Failure: E_INVALIDARG, if the source value is invalid
382 * DISP_E_OVERFLOW, if the value will not fit in the destination
384 HRESULT WINAPI
VarI1FromDec(DECIMAL
*pdecIn
, signed char* pcOut
)
389 hRet
= _VarI8FromDec(pdecIn
, &i64
);
392 hRet
= _VarI1FromI8(i64
, pcOut
);
396 /************************************************************************
397 * VarI1FromI8 (OLEAUT32.376)
399 * Convert a VT_I8 to a VT_I1.
403 * pcOut [O] Destination
407 * Failure: E_INVALIDARG, if the source value is invalid
408 * DISP_E_OVERFLOW, if the value will not fit in the destination
410 HRESULT WINAPI
VarI1FromI8(LONG64 llIn
, signed char* pcOut
)
412 return _VarI1FromI8(llIn
, pcOut
);
415 /************************************************************************
416 * VarI1FromUI8 (OLEAUT32.377)
418 * Convert a VT_UI8 to a VT_I1.
422 * pcOut [O] Destination
426 * Failure: E_INVALIDARG, if the source value is invalid
427 * DISP_E_OVERFLOW, if the value will not fit in the destination
429 HRESULT WINAPI
VarI1FromUI8(ULONG64 ullIn
, signed char* pcOut
)
431 return _VarI1FromUI8(ullIn
, pcOut
);
437 /************************************************************************
438 * VarUI1FromI2 (OLEAUT32.130)
440 * Convert a VT_I2 to a VT_UI1.
444 * pbOut [O] Destination
448 * Failure: E_INVALIDARG, if the source value is invalid
449 * DISP_E_OVERFLOW, if the value will not fit in the destination
451 HRESULT WINAPI
VarUI1FromI2(SHORT sIn
, BYTE
* pbOut
)
453 return _VarUI1FromI2(sIn
, pbOut
);
456 /************************************************************************
457 * VarUI1FromI4 (OLEAUT32.131)
459 * Convert a VT_I4 to a VT_UI1.
463 * pbOut [O] Destination
467 * Failure: E_INVALIDARG, if the source value is invalid
468 * DISP_E_OVERFLOW, if the value will not fit in the destination
470 HRESULT WINAPI
VarUI1FromI4(LONG iIn
, BYTE
* pbOut
)
472 return _VarUI1FromI4(iIn
, pbOut
);
475 /************************************************************************
476 * VarUI1FromR4 (OLEAUT32.132)
478 * Convert a VT_R4 to a VT_UI1.
482 * pbOut [O] Destination
486 * Failure: E_INVALIDARG, if the source value is invalid
487 * DISP_E_OVERFLOW, if the value will not fit in the destination
488 * DISP_E_TYPEMISMATCH, if the type cannot be converted
490 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
492 return _VarUI1FromR4(fltIn
, pbOut
);
495 /************************************************************************
496 * VarUI1FromR8 (OLEAUT32.133)
498 * Convert a VT_R8 to a VT_UI1.
502 * pbOut [O] Destination
506 * Failure: E_INVALIDARG, if the source value is invalid
507 * DISP_E_OVERFLOW, if the value will not fit in the destination
510 * See VarI8FromR8() for details concerning rounding.
512 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
514 if (dblIn
< -0.5 || dblIn
> (double)UI1_MAX
)
515 return DISP_E_OVERFLOW
;
516 OLEAUT32_DutchRound(BYTE
, dblIn
, *pbOut
);
520 /************************************************************************
521 * VarUI1FromCy (OLEAUT32.134)
523 * Convert a VT_CY to a VT_UI1.
527 * pbOut [O] Destination
531 * Failure: E_INVALIDARG, if the source value is invalid
532 * DISP_E_OVERFLOW, if the value will not fit in the destination
535 * Negative values >= -5000 will be converted to 0.
537 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
)
539 ULONG i
= UI1_MAX
+ 1;
541 _VarUI4FromCy(cyIn
, &i
);
542 return _VarUI1FromUI4(i
, pbOut
);
545 /************************************************************************
546 * VarUI1FromDate (OLEAUT32.135)
548 * Convert a VT_DATE to a VT_UI1.
552 * pbOut [O] Destination
556 * Failure: E_INVALIDARG, if the source value is invalid
557 * DISP_E_OVERFLOW, if the value will not fit in the destination
559 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
561 return _VarUI1FromDate(dateIn
, pbOut
);
564 /************************************************************************
565 * VarUI1FromStr (OLEAUT32.136)
567 * Convert a VT_BSTR to a VT_UI1.
571 * lcid [I] LCID for the conversion
572 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
573 * pbOut [O] Destination
577 * Failure: E_INVALIDARG, if the source value is invalid
578 * DISP_E_OVERFLOW, if the value will not fit in the destination
579 * DISP_E_TYPEMISMATCH, if the type cannot be converted
581 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
583 return _VarUI1FromStr(strIn
, lcid
, dwFlags
, pbOut
);
586 /************************************************************************
587 * VarUI1FromDisp (OLEAUT32.137)
589 * Convert a VT_DISPATCH to a VT_UI1.
593 * lcid [I] LCID for conversion
594 * pbOut [O] Destination
598 * Failure: E_INVALIDARG, if the source value is invalid
599 * DISP_E_OVERFLOW, if the value will not fit in the destination
600 * DISP_E_TYPEMISMATCH, if the type cannot be converted
602 HRESULT WINAPI
VarUI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, BYTE
* pbOut
)
604 return _VarUI1FromDisp(pdispIn
, lcid
, pbOut
);
607 /************************************************************************
608 * VarUI1FromBool (OLEAUT32.138)
610 * Convert a VT_BOOL to a VT_UI1.
614 * pbOut [O] Destination
619 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
621 return _VarUI1FromBool(boolIn
, pbOut
);
624 /************************************************************************
625 * VarUI1FromI1 (OLEAUT32.237)
627 * Convert a VT_I1 to a VT_UI1.
631 * pbOut [O] Destination
635 * Failure: E_INVALIDARG, if the source value is invalid
636 * DISP_E_OVERFLOW, if the value will not fit in the destination
638 HRESULT WINAPI
VarUI1FromI1(signed char cIn
, BYTE
* pbOut
)
640 return _VarUI1FromI1(cIn
, pbOut
);
643 /************************************************************************
644 * VarUI1FromUI2 (OLEAUT32.238)
646 * Convert a VT_UI2 to a VT_UI1.
650 * pbOut [O] Destination
654 * Failure: E_INVALIDARG, if the source value is invalid
655 * DISP_E_OVERFLOW, if the value will not fit in the destination
657 HRESULT WINAPI
VarUI1FromUI2(USHORT usIn
, BYTE
* pbOut
)
659 return _VarUI1FromUI2(usIn
, pbOut
);
662 /************************************************************************
663 * VarUI1FromUI4 (OLEAUT32.239)
665 * Convert a VT_UI4 to a VT_UI1.
669 * pbOut [O] Destination
673 * Failure: E_INVALIDARG, if the source value is invalid
674 * DISP_E_OVERFLOW, if the value will not fit in the destination
676 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
678 return _VarUI1FromUI4(ulIn
, pbOut
);
681 /************************************************************************
682 * VarUI1FromDec (OLEAUT32.240)
684 * Convert a VT_DECIMAL to a VT_UI1.
688 * pbOut [O] Destination
692 * Failure: E_INVALIDARG, if the source value is invalid
693 * DISP_E_OVERFLOW, if the value will not fit in the destination
695 HRESULT WINAPI
VarUI1FromDec(DECIMAL
*pdecIn
, BYTE
* pbOut
)
700 hRet
= _VarI8FromDec(pdecIn
, &i64
);
703 hRet
= _VarUI1FromI8(i64
, pbOut
);
707 /************************************************************************
708 * VarUI1FromI8 (OLEAUT32.372)
710 * Convert a VT_I8 to a VT_UI1.
714 * pbOut [O] Destination
718 * Failure: E_INVALIDARG, if the source value is invalid
719 * DISP_E_OVERFLOW, if the value will not fit in the destination
721 HRESULT WINAPI
VarUI1FromI8(LONG64 llIn
, BYTE
* pbOut
)
723 return _VarUI1FromI8(llIn
, pbOut
);
726 /************************************************************************
727 * VarUI1FromUI8 (OLEAUT32.373)
729 * Convert a VT_UI8 to a VT_UI1.
733 * pbOut [O] Destination
737 * Failure: E_INVALIDARG, if the source value is invalid
738 * DISP_E_OVERFLOW, if the value will not fit in the destination
740 HRESULT WINAPI
VarUI1FromUI8(ULONG64 ullIn
, BYTE
* pbOut
)
742 return _VarUI1FromUI8(ullIn
, pbOut
);
749 /************************************************************************
750 * VarI2FromUI1 (OLEAUT32.48)
752 * Convert a VT_UI2 to a VT_I2.
756 * psOut [O] Destination
761 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, SHORT
* psOut
)
763 return _VarI2FromUI1(bIn
, psOut
);
766 /************************************************************************
767 * VarI2FromI4 (OLEAUT32.49)
769 * Convert a VT_I4 to a VT_I2.
773 * psOut [O] Destination
777 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
779 HRESULT WINAPI
VarI2FromI4(LONG iIn
, SHORT
* psOut
)
781 return _VarI2FromI4(iIn
, psOut
);
784 /************************************************************************
785 * VarI2FromR4 (OLEAUT32.50)
787 * Convert a VT_R4 to a VT_I2.
791 * psOut [O] Destination
795 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
797 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, SHORT
* psOut
)
799 return _VarI2FromR4(fltIn
, psOut
);
802 /************************************************************************
803 * VarI2FromR8 (OLEAUT32.51)
805 * Convert a VT_R8 to a VT_I2.
809 * psOut [O] Destination
813 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
816 * See VarI8FromR8() for details concerning rounding.
818 HRESULT WINAPI
VarI2FromR8(double dblIn
, SHORT
* psOut
)
820 if (dblIn
< (double)I2_MIN
|| dblIn
> (double)I2_MAX
)
821 return DISP_E_OVERFLOW
;
822 OLEAUT32_DutchRound(SHORT
, dblIn
, *psOut
);
826 /************************************************************************
827 * VarI2FromCy (OLEAUT32.52)
829 * Convert a VT_CY to a VT_I2.
833 * psOut [O] Destination
837 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
839 HRESULT WINAPI
VarI2FromCy(CY cyIn
, SHORT
* psOut
)
843 _VarI4FromCy(cyIn
, &i
);
844 return _VarI2FromI4(i
, psOut
);
847 /************************************************************************
848 * VarI2FromDate (OLEAUT32.53)
850 * Convert a VT_DATE to a VT_I2.
854 * psOut [O] Destination
858 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
860 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, SHORT
* psOut
)
862 return _VarI2FromDate(dateIn
, psOut
);
865 /************************************************************************
866 * VarI2FromStr (OLEAUT32.54)
868 * Convert a VT_BSTR to a VT_I2.
872 * lcid [I] LCID for the conversion
873 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
874 * psOut [O] Destination
878 * Failure: E_INVALIDARG, if any parameter is invalid
879 * DISP_E_OVERFLOW, if the value will not fit in the destination
880 * DISP_E_TYPEMISMATCH, if the type cannot be converted
882 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, SHORT
* psOut
)
884 return _VarI2FromStr(strIn
, lcid
, dwFlags
, psOut
);
887 /************************************************************************
888 * VarI2FromDisp (OLEAUT32.55)
890 * Convert a VT_DISPATCH to a VT_I2.
894 * lcid [I] LCID for conversion
895 * psOut [O] Destination
899 * Failure: E_INVALIDARG, if pdispIn is invalid,
900 * DISP_E_OVERFLOW, if the value will not fit in the destination,
901 * DISP_E_TYPEMISMATCH, if the type cannot be converted
903 HRESULT WINAPI
VarI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, SHORT
* psOut
)
905 return _VarI2FromDisp(pdispIn
, lcid
, psOut
);
908 /************************************************************************
909 * VarI2FromBool (OLEAUT32.56)
911 * Convert a VT_BOOL to a VT_I2.
915 * psOut [O] Destination
920 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, SHORT
* psOut
)
922 return _VarI2FromBool(boolIn
, psOut
);
925 /************************************************************************
926 * VarI2FromI1 (OLEAUT32.205)
928 * Convert a VT_I1 to a VT_I2.
932 * psOut [O] Destination
937 HRESULT WINAPI
VarI2FromI1(signed char cIn
, SHORT
* psOut
)
939 return _VarI2FromI1(cIn
, psOut
);
942 /************************************************************************
943 * VarI2FromUI2 (OLEAUT32.206)
945 * Convert a VT_UI2 to a VT_I2.
949 * psOut [O] Destination
953 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
955 HRESULT WINAPI
VarI2FromUI2(USHORT usIn
, SHORT
* psOut
)
957 return _VarI2FromUI2(usIn
, psOut
);
960 /************************************************************************
961 * VarI2FromUI4 (OLEAUT32.207)
963 * Convert a VT_UI4 to a VT_I2.
967 * psOut [O] Destination
971 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
973 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, SHORT
* psOut
)
975 return _VarI2FromUI4(ulIn
, psOut
);
978 /************************************************************************
979 * VarI2FromDec (OLEAUT32.208)
981 * Convert a VT_DECIMAL to a VT_I2.
985 * psOut [O] Destination
989 * Failure: E_INVALIDARG, if the source value is invalid
990 * DISP_E_OVERFLOW, if the value will not fit in the destination
992 HRESULT WINAPI
VarI2FromDec(DECIMAL
*pdecIn
, SHORT
* psOut
)
997 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1000 hRet
= _VarI2FromI8(i64
, psOut
);
1004 /************************************************************************
1005 * VarI2FromI8 (OLEAUT32.346)
1007 * Convert a VT_I8 to a VT_I2.
1011 * psOut [O] Destination
1015 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1017 HRESULT WINAPI
VarI2FromI8(LONG64 llIn
, SHORT
* psOut
)
1019 return _VarI2FromI8(llIn
, psOut
);
1022 /************************************************************************
1023 * VarI2FromUI8 (OLEAUT32.347)
1025 * Convert a VT_UI8 to a VT_I2.
1029 * psOut [O] Destination
1033 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1035 HRESULT WINAPI
VarI2FromUI8(ULONG64 ullIn
, SHORT
* psOut
)
1037 return _VarI2FromUI8(ullIn
, psOut
);
1043 /************************************************************************
1044 * VarUI2FromUI1 (OLEAUT32.257)
1046 * Convert a VT_UI1 to a VT_UI2.
1050 * pusOut [O] Destination
1055 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* pusOut
)
1057 return _VarUI2FromUI1(bIn
, pusOut
);
1060 /************************************************************************
1061 * VarUI2FromI2 (OLEAUT32.258)
1063 * Convert a VT_I2 to a VT_UI2.
1067 * pusOut [O] Destination
1071 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1073 HRESULT WINAPI
VarUI2FromI2(SHORT sIn
, USHORT
* pusOut
)
1075 return _VarUI2FromI2(sIn
, pusOut
);
1078 /************************************************************************
1079 * VarUI2FromI4 (OLEAUT32.259)
1081 * Convert a VT_I4 to a VT_UI2.
1085 * pusOut [O] Destination
1089 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1091 HRESULT WINAPI
VarUI2FromI4(LONG iIn
, USHORT
* pusOut
)
1093 return _VarUI2FromI4(iIn
, pusOut
);
1096 /************************************************************************
1097 * VarUI2FromR4 (OLEAUT32.260)
1099 * Convert a VT_R4 to a VT_UI2.
1103 * pusOut [O] Destination
1107 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1109 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* pusOut
)
1111 return _VarUI2FromR4(fltIn
, pusOut
);
1114 /************************************************************************
1115 * VarUI2FromR8 (OLEAUT32.261)
1117 * Convert a VT_R8 to a VT_UI2.
1121 * pusOut [O] Destination
1125 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1128 * See VarI8FromR8() for details concerning rounding.
1130 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* pusOut
)
1132 if (dblIn
< -0.5 || dblIn
> (double)UI2_MAX
)
1133 return DISP_E_OVERFLOW
;
1134 OLEAUT32_DutchRound(USHORT
, dblIn
, *pusOut
);
1138 /************************************************************************
1139 * VarUI2FromDate (OLEAUT32.262)
1141 * Convert a VT_DATE to a VT_UI2.
1145 * pusOut [O] Destination
1149 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1151 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* pusOut
)
1153 return _VarUI2FromDate(dateIn
, pusOut
);
1156 /************************************************************************
1157 * VarUI2FromCy (OLEAUT32.263)
1159 * Convert a VT_CY to a VT_UI2.
1163 * pusOut [O] Destination
1167 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1170 * Negative values >= -5000 will be converted to 0.
1172 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
)
1174 ULONG i
= UI2_MAX
+ 1;
1176 _VarUI4FromCy(cyIn
, &i
);
1177 return _VarUI2FromUI4(i
, pusOut
);
1180 /************************************************************************
1181 * VarUI2FromStr (OLEAUT32.264)
1183 * Convert a VT_BSTR to a VT_UI2.
1187 * lcid [I] LCID for the conversion
1188 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1189 * pusOut [O] Destination
1193 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1194 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1196 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* pusOut
)
1198 return _VarUI2FromStr(strIn
, lcid
, dwFlags
, pusOut
);
1201 /************************************************************************
1202 * VarUI2FromDisp (OLEAUT32.265)
1204 * Convert a VT_DISPATCH to a VT_UI2.
1207 * pdispIn [I] Source
1208 * lcid [I] LCID for conversion
1209 * pusOut [O] Destination
1213 * Failure: E_INVALIDARG, if the source value is invalid
1214 * DISP_E_OVERFLOW, if the value will not fit in the destination
1215 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1217 HRESULT WINAPI
VarUI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, USHORT
* pusOut
)
1219 return _VarUI2FromDisp(pdispIn
, lcid
, pusOut
);
1222 /************************************************************************
1223 * VarUI2FromBool (OLEAUT32.266)
1225 * Convert a VT_BOOL to a VT_UI2.
1229 * pusOut [O] Destination
1234 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* pusOut
)
1236 return _VarUI2FromBool(boolIn
, pusOut
);
1239 /************************************************************************
1240 * VarUI2FromI1 (OLEAUT32.267)
1242 * Convert a VT_I1 to a VT_UI2.
1246 * pusOut [O] Destination
1250 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1252 HRESULT WINAPI
VarUI2FromI1(signed char cIn
, USHORT
* pusOut
)
1254 return _VarUI2FromI1(cIn
, pusOut
);
1257 /************************************************************************
1258 * VarUI2FromUI4 (OLEAUT32.268)
1260 * Convert a VT_UI4 to a VT_UI2.
1264 * pusOut [O] Destination
1268 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1270 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* pusOut
)
1272 return _VarUI2FromUI4(ulIn
, pusOut
);
1275 /************************************************************************
1276 * VarUI2FromDec (OLEAUT32.269)
1278 * Convert a VT_DECIMAL to a VT_UI2.
1282 * pusOut [O] Destination
1286 * Failure: E_INVALIDARG, if the source value is invalid
1287 * DISP_E_OVERFLOW, if the value will not fit in the destination
1289 HRESULT WINAPI
VarUI2FromDec(DECIMAL
*pdecIn
, USHORT
* pusOut
)
1294 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1296 if (SUCCEEDED(hRet
))
1297 hRet
= _VarUI2FromI8(i64
, pusOut
);
1301 /************************************************************************
1302 * VarUI2FromI8 (OLEAUT32.378)
1304 * Convert a VT_I8 to a VT_UI2.
1308 * pusOut [O] Destination
1312 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1314 HRESULT WINAPI
VarUI2FromI8(LONG64 llIn
, USHORT
* pusOut
)
1316 return _VarUI2FromI8(llIn
, pusOut
);
1319 /************************************************************************
1320 * VarUI2FromUI8 (OLEAUT32.379)
1322 * Convert a VT_UI8 to a VT_UI2.
1326 * pusOut [O] Destination
1330 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1332 HRESULT WINAPI
VarUI2FromUI8(ULONG64 ullIn
, USHORT
* pusOut
)
1334 return _VarUI2FromUI8(ullIn
, pusOut
);
1340 /************************************************************************
1341 * VarI4FromUI1 (OLEAUT32.58)
1343 * Convert a VT_UI1 to a VT_I4.
1347 * piOut [O] Destination
1352 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
*piOut
)
1354 return _VarI4FromUI1(bIn
, piOut
);
1357 /************************************************************************
1358 * VarI4FromI2 (OLEAUT32.59)
1360 * Convert a VT_I2 to a VT_I4.
1364 * piOut [O] Destination
1368 * Failure: E_INVALIDARG, if the source value is invalid
1369 * DISP_E_OVERFLOW, if the value will not fit in the destination
1371 HRESULT WINAPI
VarI4FromI2(SHORT sIn
, LONG
*piOut
)
1373 return _VarI4FromI2(sIn
, piOut
);
1376 /************************************************************************
1377 * VarI4FromR4 (OLEAUT32.60)
1379 * Convert a VT_R4 to a VT_I4.
1383 * piOut [O] Destination
1387 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1389 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
*piOut
)
1391 return _VarI4FromR4(fltIn
, piOut
);
1394 /************************************************************************
1395 * VarI4FromR8 (OLEAUT32.61)
1397 * Convert a VT_R8 to a VT_I4.
1401 * piOut [O] Destination
1405 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1408 * See VarI8FromR8() for details concerning rounding.
1410 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
*piOut
)
1412 if (dblIn
< (double)I4_MIN
|| dblIn
> (double)I4_MAX
)
1413 return DISP_E_OVERFLOW
;
1414 OLEAUT32_DutchRound(LONG
, dblIn
, *piOut
);
1418 /************************************************************************
1419 * VarI4FromCy (OLEAUT32.62)
1421 * Convert a VT_CY to a VT_I4.
1425 * piOut [O] Destination
1429 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1431 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
*piOut
)
1433 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1434 return _VarI4FromR8(d
, piOut
);
1437 /************************************************************************
1438 * VarI4FromDate (OLEAUT32.63)
1440 * Convert a VT_DATE to a VT_I4.
1444 * piOut [O] Destination
1448 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1450 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
*piOut
)
1452 return _VarI4FromDate(dateIn
, piOut
);
1455 /************************************************************************
1456 * VarI4FromStr (OLEAUT32.64)
1458 * Convert a VT_BSTR to a VT_I4.
1462 * lcid [I] LCID for the conversion
1463 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1464 * piOut [O] Destination
1468 * Failure: E_INVALIDARG, if any parameter is invalid
1469 * DISP_E_OVERFLOW, if the value will not fit in the destination
1470 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1472 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
*piOut
)
1474 return _VarI4FromStr(strIn
, lcid
, dwFlags
, piOut
);
1477 /************************************************************************
1478 * VarI4FromDisp (OLEAUT32.65)
1480 * Convert a VT_DISPATCH to a VT_I4.
1483 * pdispIn [I] Source
1484 * lcid [I] LCID for conversion
1485 * piOut [O] Destination
1489 * Failure: E_INVALIDARG, if the source value is invalid
1490 * DISP_E_OVERFLOW, if the value will not fit in the destination
1491 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1493 HRESULT WINAPI
VarI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG
*piOut
)
1495 return _VarI4FromDisp(pdispIn
, lcid
, piOut
);
1498 /************************************************************************
1499 * VarI4FromBool (OLEAUT32.66)
1501 * Convert a VT_BOOL to a VT_I4.
1505 * piOut [O] Destination
1510 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
*piOut
)
1512 return _VarI4FromBool(boolIn
, piOut
);
1515 /************************************************************************
1516 * VarI4FromI1 (OLEAUT32.209)
1518 * Convert a VT_I4 to a VT_I4.
1522 * piOut [O] Destination
1527 HRESULT WINAPI
VarI4FromI1(signed char cIn
, LONG
*piOut
)
1529 return _VarI4FromI1(cIn
, piOut
);
1532 /************************************************************************
1533 * VarI4FromUI2 (OLEAUT32.210)
1535 * Convert a VT_UI2 to a VT_I4.
1539 * piOut [O] Destination
1544 HRESULT WINAPI
VarI4FromUI2(USHORT usIn
, LONG
*piOut
)
1546 return _VarI4FromUI2(usIn
, piOut
);
1549 /************************************************************************
1550 * VarI4FromUI4 (OLEAUT32.211)
1552 * Convert a VT_UI4 to a VT_I4.
1556 * piOut [O] Destination
1560 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1562 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
*piOut
)
1564 return _VarI4FromUI4(ulIn
, piOut
);
1567 /************************************************************************
1568 * VarI4FromDec (OLEAUT32.212)
1570 * Convert a VT_DECIMAL to a VT_I4.
1574 * piOut [O] Destination
1578 * Failure: E_INVALIDARG, if pdecIn is invalid
1579 * DISP_E_OVERFLOW, if the value will not fit in the destination
1581 HRESULT WINAPI
VarI4FromDec(DECIMAL
*pdecIn
, LONG
*piOut
)
1586 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1588 if (SUCCEEDED(hRet
))
1589 hRet
= _VarI4FromI8(i64
, piOut
);
1593 /************************************************************************
1594 * VarI4FromI8 (OLEAUT32.348)
1596 * Convert a VT_I8 to a VT_I4.
1600 * piOut [O] Destination
1604 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1606 HRESULT WINAPI
VarI4FromI8(LONG64 llIn
, LONG
*piOut
)
1608 return _VarI4FromI8(llIn
, piOut
);
1611 /************************************************************************
1612 * VarI4FromUI8 (OLEAUT32.349)
1614 * Convert a VT_UI8 to a VT_I4.
1618 * piOut [O] Destination
1622 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1624 HRESULT WINAPI
VarI4FromUI8(ULONG64 ullIn
, LONG
*piOut
)
1626 return _VarI4FromUI8(ullIn
, piOut
);
1632 /************************************************************************
1633 * VarUI4FromUI1 (OLEAUT32.270)
1635 * Convert a VT_UI1 to a VT_UI4.
1639 * pulOut [O] Destination
1644 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
*pulOut
)
1646 return _VarUI4FromUI1(bIn
, pulOut
);
1649 /************************************************************************
1650 * VarUI4FromI2 (OLEAUT32.271)
1652 * Convert a VT_I2 to a VT_UI4.
1656 * pulOut [O] Destination
1660 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1662 HRESULT WINAPI
VarUI4FromI2(SHORT sIn
, ULONG
*pulOut
)
1664 return _VarUI4FromI2(sIn
, pulOut
);
1667 /************************************************************************
1668 * VarUI4FromI4 (OLEAUT32.272)
1670 * Convert a VT_I4 to a VT_UI4.
1674 * pulOut [O] Destination
1678 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1680 HRESULT WINAPI
VarUI4FromI4(LONG iIn
, ULONG
*pulOut
)
1682 return _VarUI4FromI4(iIn
, pulOut
);
1685 /************************************************************************
1686 * VarUI4FromR4 (OLEAUT32.273)
1688 * Convert a VT_R4 to a VT_UI4.
1692 * pulOut [O] Destination
1696 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1698 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
*pulOut
)
1700 return _VarUI4FromR4(fltIn
, pulOut
);
1703 /************************************************************************
1704 * VarUI4FromR8 (OLEAUT32.274)
1706 * Convert a VT_R8 to a VT_UI4.
1710 * pulOut [O] Destination
1714 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1717 * See VarI8FromR8() for details concerning rounding.
1719 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
*pulOut
)
1721 if (dblIn
< -0.5 || dblIn
> (double)UI4_MAX
)
1722 return DISP_E_OVERFLOW
;
1723 OLEAUT32_DutchRound(ULONG
, dblIn
, *pulOut
);
1727 /************************************************************************
1728 * VarUI4FromDate (OLEAUT32.275)
1730 * Convert a VT_DATE to a VT_UI4.
1734 * pulOut [O] Destination
1738 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1740 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
*pulOut
)
1742 return _VarUI4FromDate(dateIn
, pulOut
);
1745 /************************************************************************
1746 * VarUI4FromCy (OLEAUT32.276)
1748 * Convert a VT_CY to a VT_UI4.
1752 * pulOut [O] Destination
1756 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1758 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
*pulOut
)
1760 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1761 return _VarUI4FromR8(d
, pulOut
);
1765 /************************************************************************
1766 * VarUI4FromStr (OLEAUT32.277)
1768 * Convert a VT_BSTR to a VT_UI4.
1772 * lcid [I] LCID for the conversion
1773 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1774 * pulOut [O] Destination
1778 * Failure: E_INVALIDARG, if any parameter is invalid
1779 * DISP_E_OVERFLOW, if the value will not fit in the destination
1780 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1782 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
*pulOut
)
1784 return _VarUI4FromStr(strIn
, lcid
, dwFlags
, pulOut
);
1787 /************************************************************************
1788 * VarUI4FromDisp (OLEAUT32.278)
1790 * Convert a VT_DISPATCH to a VT_UI4.
1793 * pdispIn [I] Source
1794 * lcid [I] LCID for conversion
1795 * pulOut [O] Destination
1799 * Failure: E_INVALIDARG, if the source value is invalid
1800 * DISP_E_OVERFLOW, if the value will not fit in the destination
1801 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1803 HRESULT WINAPI
VarUI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG
*pulOut
)
1805 return _VarUI4FromDisp(pdispIn
, lcid
, pulOut
);
1808 /************************************************************************
1809 * VarUI4FromBool (OLEAUT32.279)
1811 * Convert a VT_BOOL to a VT_UI4.
1815 * pulOut [O] Destination
1820 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
*pulOut
)
1822 return _VarUI4FromBool(boolIn
, pulOut
);
1825 /************************************************************************
1826 * VarUI4FromI1 (OLEAUT32.280)
1828 * Convert a VT_I1 to a VT_UI4.
1832 * pulOut [O] Destination
1836 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1838 HRESULT WINAPI
VarUI4FromI1(signed char cIn
, ULONG
*pulOut
)
1840 return _VarUI4FromI1(cIn
, pulOut
);
1843 /************************************************************************
1844 * VarUI4FromUI2 (OLEAUT32.281)
1846 * Convert a VT_UI2 to a VT_UI4.
1850 * pulOut [O] Destination
1855 HRESULT WINAPI
VarUI4FromUI2(USHORT usIn
, ULONG
*pulOut
)
1857 return _VarUI4FromUI2(usIn
, pulOut
);
1860 /************************************************************************
1861 * VarUI4FromDec (OLEAUT32.282)
1863 * Convert a VT_DECIMAL to a VT_UI4.
1867 * pulOut [O] Destination
1871 * Failure: E_INVALIDARG, if pdecIn is invalid
1872 * DISP_E_OVERFLOW, if the value will not fit in the destination
1874 HRESULT WINAPI
VarUI4FromDec(DECIMAL
*pdecIn
, ULONG
*pulOut
)
1879 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1881 if (SUCCEEDED(hRet
))
1882 hRet
= _VarUI4FromI8(i64
, pulOut
);
1886 /************************************************************************
1887 * VarUI4FromI8 (OLEAUT32.425)
1889 * Convert a VT_I8 to a VT_UI4.
1893 * pulOut [O] Destination
1897 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1899 HRESULT WINAPI
VarUI4FromI8(LONG64 llIn
, ULONG
*pulOut
)
1901 return _VarUI4FromI8(llIn
, pulOut
);
1904 /************************************************************************
1905 * VarUI4FromUI8 (OLEAUT32.426)
1907 * Convert a VT_UI8 to a VT_UI4.
1911 * pulOut [O] Destination
1915 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1917 HRESULT WINAPI
VarUI4FromUI8(ULONG64 ullIn
, ULONG
*pulOut
)
1919 return _VarUI4FromUI8(ullIn
, pulOut
);
1925 /************************************************************************
1926 * VarI8FromUI1 (OLEAUT32.333)
1928 * Convert a VT_UI1 to a VT_I8.
1932 * pi64Out [O] Destination
1937 HRESULT WINAPI
VarI8FromUI1(BYTE bIn
, LONG64
* pi64Out
)
1939 return _VarI8FromUI1(bIn
, pi64Out
);
1943 /************************************************************************
1944 * VarI8FromI2 (OLEAUT32.334)
1946 * Convert a VT_I2 to a VT_I8.
1950 * pi64Out [O] Destination
1955 HRESULT WINAPI
VarI8FromI2(SHORT sIn
, LONG64
* pi64Out
)
1957 return _VarI8FromI2(sIn
, pi64Out
);
1960 /************************************************************************
1961 * VarI8FromR4 (OLEAUT32.335)
1963 * Convert a VT_R4 to a VT_I8.
1967 * pi64Out [O] Destination
1971 * Failure: E_INVALIDARG, if the source value is invalid
1972 * DISP_E_OVERFLOW, if the value will not fit in the destination
1974 HRESULT WINAPI
VarI8FromR4(FLOAT fltIn
, LONG64
* pi64Out
)
1976 return _VarI8FromR4(fltIn
, pi64Out
);
1979 /************************************************************************
1980 * VarI8FromR8 (OLEAUT32.336)
1982 * Convert a VT_R8 to a VT_I8.
1986 * pi64Out [O] Destination
1990 * Failure: E_INVALIDARG, if the source value is invalid
1991 * DISP_E_OVERFLOW, if the value will not fit in the destination
1994 * Only values that fit into 63 bits are accepted. Due to rounding issues,
1995 * very high or low values will not be accurately converted.
1997 * Numbers are rounded using Dutch rounding, as follows:
1999 *| Fractional Part Sign Direction Example
2000 *| --------------- ---- --------- -------
2001 *| < 0.5 + Down 0.4 -> 0.0
2002 *| < 0.5 - Up -0.4 -> 0.0
2003 *| > 0.5 + Up 0.6 -> 1.0
2004 *| < 0.5 - Up -0.6 -> -1.0
2005 *| = 0.5 + Up/Down Down if even, Up if odd
2006 *| = 0.5 - Up/Down Up if even, Down if odd
2008 * This system is often used in supermarkets.
2010 HRESULT WINAPI
VarI8FromR8(double dblIn
, LONG64
* pi64Out
)
2012 if ( dblIn
< -4611686018427387904.0 || dblIn
>= 4611686018427387904.0)
2013 return DISP_E_OVERFLOW
;
2014 OLEAUT32_DutchRound(LONG64
, dblIn
, *pi64Out
);
2019 /************************************************************************
2020 * VarI8FromCy (OLEAUT32.337)
2022 * Convert a VT_CY to a VT_I8.
2026 * pi64Out [O] Destination
2032 * All negative numbers are rounded down by 1, including those that are
2033 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2034 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2037 HRESULT WINAPI
VarI8FromCy(CY cyIn
, LONG64
* pi64Out
)
2039 *pi64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2042 (*pi64Out
)--; /* Mimic Win32 bug */
2045 cyIn
.int64
-= *pi64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2047 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pi64Out
& 0x1)))
2053 /************************************************************************
2054 * VarI8FromDate (OLEAUT32.338)
2056 * Convert a VT_DATE to a VT_I8.
2060 * pi64Out [O] Destination
2064 * Failure: E_INVALIDARG, if the source value is invalid
2065 * DISP_E_OVERFLOW, if the value will not fit in the destination
2066 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2068 HRESULT WINAPI
VarI8FromDate(DATE dateIn
, LONG64
* pi64Out
)
2070 return _VarI8FromDate(dateIn
, pi64Out
);
2073 /************************************************************************
2074 * VarI8FromStr (OLEAUT32.339)
2076 * Convert a VT_BSTR to a VT_I8.
2080 * lcid [I] LCID for the conversion
2081 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2082 * pi64Out [O] Destination
2086 * Failure: E_INVALIDARG, if the source value is invalid
2087 * DISP_E_OVERFLOW, if the value will not fit in the destination
2088 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2090 HRESULT WINAPI
VarI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG64
* pi64Out
)
2092 return _VarI8FromStr(strIn
, lcid
, dwFlags
, pi64Out
);
2095 /************************************************************************
2096 * VarI8FromDisp (OLEAUT32.340)
2098 * Convert a VT_DISPATCH to a VT_I8.
2101 * pdispIn [I] Source
2102 * lcid [I] LCID for conversion
2103 * pi64Out [O] Destination
2107 * Failure: E_INVALIDARG, if the source value is invalid
2108 * DISP_E_OVERFLOW, if the value will not fit in the destination
2109 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2111 HRESULT WINAPI
VarI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG64
* pi64Out
)
2113 return _VarI8FromDisp(pdispIn
, lcid
, pi64Out
);
2116 /************************************************************************
2117 * VarI8FromBool (OLEAUT32.341)
2119 * Convert a VT_BOOL to a VT_I8.
2123 * pi64Out [O] Destination
2128 HRESULT WINAPI
VarI8FromBool(VARIANT_BOOL boolIn
, LONG64
* pi64Out
)
2130 return _VarI8FromBool(boolIn
, pi64Out
);
2133 /************************************************************************
2134 * VarI8FromI1 (OLEAUT32.342)
2136 * Convert a VT_I1 to a VT_I8.
2140 * pi64Out [O] Destination
2145 HRESULT WINAPI
VarI8FromI1(signed char cIn
, LONG64
* pi64Out
)
2147 return _VarI8FromI1(cIn
, pi64Out
);
2150 /************************************************************************
2151 * VarI8FromUI2 (OLEAUT32.343)
2153 * Convert a VT_UI2 to a VT_I8.
2157 * pi64Out [O] Destination
2162 HRESULT WINAPI
VarI8FromUI2(USHORT usIn
, LONG64
* pi64Out
)
2164 return _VarI8FromUI2(usIn
, pi64Out
);
2167 /************************************************************************
2168 * VarI8FromUI4 (OLEAUT32.344)
2170 * Convert a VT_UI4 to a VT_I8.
2174 * pi64Out [O] Destination
2179 HRESULT WINAPI
VarI8FromUI4(ULONG ulIn
, LONG64
* pi64Out
)
2181 return _VarI8FromUI4(ulIn
, pi64Out
);
2184 /************************************************************************
2185 * VarI8FromDec (OLEAUT32.345)
2187 * Convert a VT_DECIMAL to a VT_I8.
2191 * pi64Out [O] Destination
2195 * Failure: E_INVALIDARG, if the source value is invalid
2196 * DISP_E_OVERFLOW, if the value will not fit in the destination
2198 HRESULT WINAPI
VarI8FromDec(DECIMAL
*pdecIn
, LONG64
* pi64Out
)
2200 if (!DEC_SCALE(pdecIn
))
2202 /* This decimal is just a 96 bit integer */
2203 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2204 return E_INVALIDARG
;
2206 if (DEC_HI32(pdecIn
) || DEC_MID32(pdecIn
) & 0x80000000)
2207 return DISP_E_OVERFLOW
;
2209 if (DEC_SIGN(pdecIn
))
2210 *pi64Out
= -DEC_LO64(pdecIn
);
2212 *pi64Out
= DEC_LO64(pdecIn
);
2217 /* Decimal contains a floating point number */
2221 hRet
= _VarR8FromDec(pdecIn
, &dbl
);
2222 if (SUCCEEDED(hRet
))
2223 hRet
= VarI8FromR8(dbl
, pi64Out
);
2228 /************************************************************************
2229 * VarI8FromUI8 (OLEAUT32.427)
2231 * Convert a VT_UI8 to a VT_I8.
2235 * pi64Out [O] Destination
2239 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2241 HRESULT WINAPI
VarI8FromUI8(ULONG64 ullIn
, LONG64
* pi64Out
)
2243 return _VarI8FromUI8(ullIn
, pi64Out
);
2249 /************************************************************************
2250 * VarUI8FromI8 (OLEAUT32.428)
2252 * Convert a VT_I8 to a VT_UI8.
2256 * pui64Out [O] Destination
2260 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2262 HRESULT WINAPI
VarUI8FromI8(LONG64 llIn
, ULONG64
* pui64Out
)
2264 return _VarUI8FromI8(llIn
, pui64Out
);
2267 /************************************************************************
2268 * VarUI8FromUI1 (OLEAUT32.429)
2270 * Convert a VT_UI1 to a VT_UI8.
2274 * pui64Out [O] Destination
2279 HRESULT WINAPI
VarUI8FromUI1(BYTE bIn
, ULONG64
* pui64Out
)
2281 return _VarUI8FromUI1(bIn
, pui64Out
);
2284 /************************************************************************
2285 * VarUI8FromI2 (OLEAUT32.430)
2287 * Convert a VT_I2 to a VT_UI8.
2291 * pui64Out [O] Destination
2296 HRESULT WINAPI
VarUI8FromI2(SHORT sIn
, ULONG64
* pui64Out
)
2298 return _VarUI8FromI2(sIn
, pui64Out
);
2301 /************************************************************************
2302 * VarUI8FromR4 (OLEAUT32.431)
2304 * Convert a VT_R4 to a VT_UI8.
2308 * pui64Out [O] Destination
2312 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2314 HRESULT WINAPI
VarUI8FromR4(FLOAT fltIn
, ULONG64
* pui64Out
)
2316 return _VarUI8FromR4(fltIn
, pui64Out
);
2319 /************************************************************************
2320 * VarUI8FromR8 (OLEAUT32.432)
2322 * Convert a VT_R8 to a VT_UI8.
2326 * pui64Out [O] Destination
2330 * Failure: E_INVALIDARG, if the source value is invalid
2331 * DISP_E_OVERFLOW, if the value will not fit in the destination
2334 * See VarI8FromR8() for details concerning rounding.
2336 HRESULT WINAPI
VarUI8FromR8(double dblIn
, ULONG64
* pui64Out
)
2338 if (dblIn
< -0.5 || dblIn
> 1.844674407370955e19
)
2339 return DISP_E_OVERFLOW
;
2340 OLEAUT32_DutchRound(ULONG64
, dblIn
, *pui64Out
);
2344 /************************************************************************
2345 * VarUI8FromCy (OLEAUT32.433)
2347 * Convert a VT_CY to a VT_UI8.
2351 * pui64Out [O] Destination
2355 * Failure: E_INVALIDARG, if the source value is invalid
2356 * DISP_E_OVERFLOW, if the value will not fit in the destination
2359 * Negative values >= -5000 will be converted to 0.
2361 HRESULT WINAPI
VarUI8FromCy(CY cyIn
, ULONG64
* pui64Out
)
2365 if (cyIn
.int64
< -CY_HALF
)
2366 return DISP_E_OVERFLOW
;
2371 *pui64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2373 cyIn
.int64
-= *pui64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2375 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pui64Out
& 0x1)))
2381 /************************************************************************
2382 * VarUI8FromDate (OLEAUT32.434)
2384 * Convert a VT_DATE to a VT_UI8.
2388 * pui64Out [O] Destination
2392 * Failure: E_INVALIDARG, if the source value is invalid
2393 * DISP_E_OVERFLOW, if the value will not fit in the destination
2394 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2396 HRESULT WINAPI
VarUI8FromDate(DATE dateIn
, ULONG64
* pui64Out
)
2398 return _VarUI8FromDate(dateIn
, pui64Out
);
2401 /************************************************************************
2402 * VarUI8FromStr (OLEAUT32.435)
2404 * Convert a VT_BSTR to a VT_UI8.
2408 * lcid [I] LCID for the conversion
2409 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2410 * pui64Out [O] Destination
2414 * Failure: E_INVALIDARG, if the source value is invalid
2415 * DISP_E_OVERFLOW, if the value will not fit in the destination
2416 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2418 HRESULT WINAPI
VarUI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG64
* pui64Out
)
2420 return _VarUI8FromStr(strIn
, lcid
, dwFlags
, pui64Out
);
2423 /************************************************************************
2424 * VarUI8FromDisp (OLEAUT32.436)
2426 * Convert a VT_DISPATCH to a VT_UI8.
2429 * pdispIn [I] Source
2430 * lcid [I] LCID for conversion
2431 * pui64Out [O] Destination
2435 * Failure: E_INVALIDARG, if the source value is invalid
2436 * DISP_E_OVERFLOW, if the value will not fit in the destination
2437 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2439 HRESULT WINAPI
VarUI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG64
* pui64Out
)
2441 return _VarUI8FromDisp(pdispIn
, lcid
, pui64Out
);
2444 /************************************************************************
2445 * VarUI8FromBool (OLEAUT32.437)
2447 * Convert a VT_BOOL to a VT_UI8.
2451 * pui64Out [O] Destination
2455 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2457 HRESULT WINAPI
VarUI8FromBool(VARIANT_BOOL boolIn
, ULONG64
* pui64Out
)
2459 return _VarUI8FromBool(boolIn
, pui64Out
);
2461 /************************************************************************
2462 * VarUI8FromI1 (OLEAUT32.438)
2464 * Convert a VT_I1 to a VT_UI8.
2468 * pui64Out [O] Destination
2472 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2474 HRESULT WINAPI
VarUI8FromI1(signed char cIn
, ULONG64
* pui64Out
)
2476 return _VarUI8FromI1(cIn
, pui64Out
);
2479 /************************************************************************
2480 * VarUI8FromUI2 (OLEAUT32.439)
2482 * Convert a VT_UI2 to a VT_UI8.
2486 * pui64Out [O] Destination
2491 HRESULT WINAPI
VarUI8FromUI2(USHORT usIn
, ULONG64
* pui64Out
)
2493 return _VarUI8FromUI2(usIn
, pui64Out
);
2496 /************************************************************************
2497 * VarUI8FromUI4 (OLEAUT32.440)
2499 * Convert a VT_UI4 to a VT_UI8.
2503 * pui64Out [O] Destination
2508 HRESULT WINAPI
VarUI8FromUI4(ULONG ulIn
, ULONG64
* pui64Out
)
2510 return _VarUI8FromUI4(ulIn
, pui64Out
);
2513 /************************************************************************
2514 * VarUI8FromDec (OLEAUT32.441)
2516 * Convert a VT_DECIMAL to a VT_UI8.
2520 * pui64Out [O] Destination
2524 * Failure: E_INVALIDARG, if the source value is invalid
2525 * DISP_E_OVERFLOW, if the value will not fit in the destination
2528 * Under native Win32, if the source value has a scale of 0, its sign is
2529 * ignored, i.e. this function takes the absolute value rather than fail
2530 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2531 * (use VarAbs() on pDecIn first if you really want this behaviour).
2533 HRESULT WINAPI
VarUI8FromDec(DECIMAL
*pdecIn
, ULONG64
* pui64Out
)
2535 if (!DEC_SCALE(pdecIn
))
2537 /* This decimal is just a 96 bit integer */
2538 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2539 return E_INVALIDARG
;
2541 if (DEC_HI32(pdecIn
))
2542 return DISP_E_OVERFLOW
;
2544 if (DEC_SIGN(pdecIn
))
2546 WARN("Sign would be ignored under Win32!\n");
2547 return DISP_E_OVERFLOW
;
2550 *pui64Out
= DEC_LO64(pdecIn
);
2555 /* Decimal contains a floating point number */
2559 hRet
= _VarR8FromDec(pdecIn
, &dbl
);
2560 if (SUCCEEDED(hRet
))
2561 hRet
= VarUI8FromR8(dbl
, pui64Out
);
2569 /************************************************************************
2570 * VarR4FromUI1 (OLEAUT32.68)
2572 * Convert a VT_UI1 to a VT_R4.
2576 * pFltOut [O] Destination
2581 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, float *pFltOut
)
2583 return _VarR4FromUI1(bIn
, pFltOut
);
2586 /************************************************************************
2587 * VarR4FromI2 (OLEAUT32.69)
2589 * Convert a VT_I2 to a VT_R4.
2593 * pFltOut [O] Destination
2598 HRESULT WINAPI
VarR4FromI2(SHORT sIn
, float *pFltOut
)
2600 return _VarR4FromI2(sIn
, pFltOut
);
2603 /************************************************************************
2604 * VarR4FromI4 (OLEAUT32.70)
2606 * Convert a VT_I4 to a VT_R4.
2610 * pFltOut [O] Destination
2615 HRESULT WINAPI
VarR4FromI4(LONG lIn
, float *pFltOut
)
2617 return _VarR4FromI4(lIn
, pFltOut
);
2620 /************************************************************************
2621 * VarR4FromR8 (OLEAUT32.71)
2623 * Convert a VT_R8 to a VT_R4.
2627 * pFltOut [O] Destination
2631 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2633 HRESULT WINAPI
VarR4FromR8(double dblIn
, float *pFltOut
)
2635 return _VarR4FromR8(dblIn
, pFltOut
);
2638 /************************************************************************
2639 * VarR4FromCy (OLEAUT32.72)
2641 * Convert a VT_CY to a VT_R4.
2645 * pFltOut [O] Destination
2650 HRESULT WINAPI
VarR4FromCy(CY cyIn
, float *pFltOut
)
2652 return _VarR4FromCy(cyIn
, pFltOut
);
2655 /************************************************************************
2656 * VarR4FromDate (OLEAUT32.73)
2658 * Convert a VT_DATE to a VT_R4.
2662 * pFltOut [O] Destination
2666 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2668 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, float *pFltOut
)
2670 return _VarR4FromDate(dateIn
, pFltOut
);
2673 /************************************************************************
2674 * VarR4FromStr (OLEAUT32.74)
2676 * Convert a VT_BSTR to a VT_R4.
2680 * lcid [I] LCID for the conversion
2681 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2682 * pFltOut [O] Destination
2686 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2687 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2689 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, float *pFltOut
)
2691 return _VarR4FromStr(strIn
, lcid
, dwFlags
, pFltOut
);
2694 /************************************************************************
2695 * VarR4FromDisp (OLEAUT32.75)
2697 * Convert a VT_DISPATCH to a VT_R4.
2700 * pdispIn [I] Source
2701 * lcid [I] LCID for conversion
2702 * pFltOut [O] Destination
2706 * Failure: E_INVALIDARG, if the source value is invalid
2707 * DISP_E_OVERFLOW, if the value will not fit in the destination
2708 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2710 HRESULT WINAPI
VarR4FromDisp(IDispatch
* pdispIn
, LCID lcid
, float *pFltOut
)
2712 return _VarR4FromDisp(pdispIn
, lcid
, pFltOut
);
2715 /************************************************************************
2716 * VarR4FromBool (OLEAUT32.76)
2718 * Convert a VT_BOOL to a VT_R4.
2722 * pFltOut [O] Destination
2727 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, float *pFltOut
)
2729 return _VarR4FromBool(boolIn
, pFltOut
);
2732 /************************************************************************
2733 * VarR4FromI1 (OLEAUT32.213)
2735 * Convert a VT_I1 to a VT_R4.
2739 * pFltOut [O] Destination
2743 * Failure: E_INVALIDARG, if the source value is invalid
2744 * DISP_E_OVERFLOW, if the value will not fit in the destination
2745 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2747 HRESULT WINAPI
VarR4FromI1(signed char cIn
, float *pFltOut
)
2749 return _VarR4FromI1(cIn
, pFltOut
);
2752 /************************************************************************
2753 * VarR4FromUI2 (OLEAUT32.214)
2755 * Convert a VT_UI2 to a VT_R4.
2759 * pFltOut [O] Destination
2763 * Failure: E_INVALIDARG, if the source value is invalid
2764 * DISP_E_OVERFLOW, if the value will not fit in the destination
2765 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2767 HRESULT WINAPI
VarR4FromUI2(USHORT usIn
, float *pFltOut
)
2769 return _VarR4FromUI2(usIn
, pFltOut
);
2772 /************************************************************************
2773 * VarR4FromUI4 (OLEAUT32.215)
2775 * Convert a VT_UI4 to a VT_R4.
2779 * pFltOut [O] Destination
2783 * Failure: E_INVALIDARG, if the source value is invalid
2784 * DISP_E_OVERFLOW, if the value will not fit in the destination
2785 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2787 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, float *pFltOut
)
2789 return _VarR4FromUI4(ulIn
, pFltOut
);
2792 /************************************************************************
2793 * VarR4FromDec (OLEAUT32.216)
2795 * Convert a VT_DECIMAL to a VT_R4.
2799 * pFltOut [O] Destination
2803 * Failure: E_INVALIDARG, if the source value is invalid.
2805 HRESULT WINAPI
VarR4FromDec(DECIMAL
* pDecIn
, float *pFltOut
)
2807 BYTE scale
= DEC_SCALE(pDecIn
);
2811 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
2812 return E_INVALIDARG
;
2817 if (DEC_SIGN(pDecIn
))
2820 if (DEC_HI32(pDecIn
))
2822 highPart
= (double)DEC_HI32(pDecIn
) / (double)divisor
;
2828 *pFltOut
= (double)DEC_LO64(pDecIn
) / (double)divisor
+ highPart
;
2833 /************************************************************************
2834 * VarR4FromI8 (OLEAUT32.360)
2836 * Convert a VT_I8 to a VT_R4.
2840 * pFltOut [O] Destination
2845 HRESULT WINAPI
VarR4FromI8(LONG64 llIn
, float *pFltOut
)
2847 return _VarR4FromI8(llIn
, pFltOut
);
2850 /************************************************************************
2851 * VarR4FromUI8 (OLEAUT32.361)
2853 * Convert a VT_UI8 to a VT_R4.
2857 * pFltOut [O] Destination
2862 HRESULT WINAPI
VarR4FromUI8(ULONG64 ullIn
, float *pFltOut
)
2864 return _VarR4FromUI8(ullIn
, pFltOut
);
2867 /************************************************************************
2868 * VarR4CmpR8 (OLEAUT32.316)
2870 * Compare a VT_R4 to a VT_R8.
2873 * fltLeft [I] Source
2874 * dblRight [I] Value to compare
2877 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
2878 * equal to or greater than dblRight respectively.
2880 HRESULT WINAPI
VarR4CmpR8(float fltLeft
, double dblRight
)
2882 if (fltLeft
< dblRight
)
2884 else if (fltLeft
> dblRight
)
2892 /************************************************************************
2893 * VarR8FromUI1 (OLEAUT32.78)
2895 * Convert a VT_UI1 to a VT_R8.
2899 * pDblOut [O] Destination
2904 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double *pDblOut
)
2906 return _VarR8FromUI1(bIn
, pDblOut
);
2909 /************************************************************************
2910 * VarR8FromI2 (OLEAUT32.79)
2912 * Convert a VT_I2 to a VT_R8.
2916 * pDblOut [O] Destination
2921 HRESULT WINAPI
VarR8FromI2(SHORT sIn
, double *pDblOut
)
2923 return _VarR8FromI2(sIn
, pDblOut
);
2926 /************************************************************************
2927 * VarR8FromI4 (OLEAUT32.80)
2929 * Convert a VT_I4 to a VT_R8.
2933 * pDblOut [O] Destination
2938 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double *pDblOut
)
2940 return _VarR8FromI4(lIn
, pDblOut
);
2943 /************************************************************************
2944 * VarR8FromR4 (OLEAUT32.81)
2946 * Convert a VT_R4 to a VT_R8.
2950 * pDblOut [O] Destination
2955 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double *pDblOut
)
2957 return _VarR8FromR4(fltIn
, pDblOut
);
2960 /************************************************************************
2961 * VarR8FromCy (OLEAUT32.82)
2963 * Convert a VT_CY to a VT_R8.
2967 * pDblOut [O] Destination
2972 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double *pDblOut
)
2974 return _VarR8FromCy(cyIn
, pDblOut
);
2977 /************************************************************************
2978 * VarR8FromDate (OLEAUT32.83)
2980 * Convert a VT_DATE to a VT_R8.
2984 * pDblOut [O] Destination
2989 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double *pDblOut
)
2991 return _VarR8FromDate(dateIn
, pDblOut
);
2994 /************************************************************************
2995 * VarR8FromStr (OLEAUT32.84)
2997 * Convert a VT_BSTR to a VT_R8.
3001 * lcid [I] LCID for the conversion
3002 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3003 * pDblOut [O] Destination
3007 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3008 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3010 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double *pDblOut
)
3012 return _VarR8FromStr(strIn
, lcid
, dwFlags
, pDblOut
);
3015 /************************************************************************
3016 * VarR8FromDisp (OLEAUT32.85)
3018 * Convert a VT_DISPATCH to a VT_R8.
3021 * pdispIn [I] Source
3022 * lcid [I] LCID for conversion
3023 * pDblOut [O] Destination
3027 * Failure: E_INVALIDARG, if the source value is invalid
3028 * DISP_E_OVERFLOW, if the value will not fit in the destination
3029 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3031 HRESULT WINAPI
VarR8FromDisp(IDispatch
* pdispIn
, LCID lcid
, double *pDblOut
)
3033 return _VarR8FromDisp(pdispIn
, lcid
, pDblOut
);
3036 /************************************************************************
3037 * VarR8FromBool (OLEAUT32.86)
3039 * Convert a VT_BOOL to a VT_R8.
3043 * pDblOut [O] Destination
3048 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double *pDblOut
)
3050 return _VarR8FromBool(boolIn
, pDblOut
);
3053 /************************************************************************
3054 * VarR8FromI1 (OLEAUT32.217)
3056 * Convert a VT_I1 to a VT_R8.
3060 * pDblOut [O] Destination
3064 * Failure: E_INVALIDARG, if the source value is invalid
3065 * DISP_E_OVERFLOW, if the value will not fit in the destination
3066 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3068 HRESULT WINAPI
VarR8FromI1(signed char cIn
, double *pDblOut
)
3070 return _VarR8FromI1(cIn
, pDblOut
);
3073 /************************************************************************
3074 * VarR8FromUI2 (OLEAUT32.218)
3076 * Convert a VT_UI2 to a VT_R8.
3080 * pDblOut [O] Destination
3084 * Failure: E_INVALIDARG, if the source value is invalid
3085 * DISP_E_OVERFLOW, if the value will not fit in the destination
3086 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3088 HRESULT WINAPI
VarR8FromUI2(USHORT usIn
, double *pDblOut
)
3090 return _VarR8FromUI2(usIn
, pDblOut
);
3093 /************************************************************************
3094 * VarR8FromUI4 (OLEAUT32.219)
3096 * Convert a VT_UI4 to a VT_R8.
3100 * pDblOut [O] Destination
3104 * Failure: E_INVALIDARG, if the source value is invalid
3105 * DISP_E_OVERFLOW, if the value will not fit in the destination
3106 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3108 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double *pDblOut
)
3110 return _VarR8FromUI4(ulIn
, pDblOut
);
3113 /************************************************************************
3114 * VarR8FromDec (OLEAUT32.220)
3116 * Convert a VT_DECIMAL to a VT_R8.
3120 * pDblOut [O] Destination
3124 * Failure: E_INVALIDARG, if the source value is invalid.
3126 HRESULT WINAPI
VarR8FromDec(DECIMAL
* pDecIn
, double *pDblOut
)
3128 BYTE scale
= DEC_SCALE(pDecIn
);
3129 double divisor
= 1.0, highPart
;
3131 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
3132 return E_INVALIDARG
;
3137 if (DEC_SIGN(pDecIn
))
3140 if (DEC_HI32(pDecIn
))
3142 highPart
= (double)DEC_HI32(pDecIn
) / divisor
;
3148 *pDblOut
= (double)DEC_LO64(pDecIn
) / divisor
+ highPart
;
3152 /************************************************************************
3153 * VarR8FromI8 (OLEAUT32.362)
3155 * Convert a VT_I8 to a VT_R8.
3159 * pDblOut [O] Destination
3164 HRESULT WINAPI
VarR8FromI8(LONG64 llIn
, double *pDblOut
)
3166 return _VarR8FromI8(llIn
, pDblOut
);
3169 /************************************************************************
3170 * VarR8FromUI8 (OLEAUT32.363)
3172 * Convert a VT_UI8 to a VT_R8.
3176 * pDblOut [O] Destination
3181 HRESULT WINAPI
VarR8FromUI8(ULONG64 ullIn
, double *pDblOut
)
3183 return _VarR8FromUI8(ullIn
, pDblOut
);
3186 /************************************************************************
3187 * VarR8Pow (OLEAUT32.315)
3189 * Raise a VT_R8 to a power.
3192 * dblLeft [I] Source
3193 * dblPow [I] Power to raise dblLeft by
3194 * pDblOut [O] Destination
3197 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3199 HRESULT WINAPI
VarR8Pow(double dblLeft
, double dblPow
, double *pDblOut
)
3201 *pDblOut
= pow(dblLeft
, dblPow
);
3205 /************************************************************************
3206 * VarR8Round (OLEAUT32.317)
3208 * Round a VT_R8 to a given number of decimal points.
3212 * nDig [I] Number of decimal points to round to
3213 * pDblOut [O] Destination for rounded number
3216 * Success: S_OK. pDblOut is rounded to nDig digits.
3217 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3220 * The native version of this function rounds using the internal
3221 * binary representation of the number. Wine uses the dutch rounding
3222 * convention, so therefore small differences can occur in the value returned.
3223 * MSDN says that you should use your own rounding function if you want
3224 * rounding to be predictable in your application.
3226 HRESULT WINAPI
VarR8Round(double dblIn
, int nDig
, double *pDblOut
)
3228 double scale
, whole
, fract
;
3231 return E_INVALIDARG
;
3233 scale
= pow(10.0, nDig
);
3236 whole
= dblIn
< 0 ? ceil(dblIn
) : floor(dblIn
);
3237 fract
= dblIn
- whole
;
3240 dblIn
= whole
+ 1.0;
3241 else if (fract
== 0.5)
3242 dblIn
= whole
+ fmod(whole
, 2.0);
3243 else if (fract
>= 0.0)
3245 else if (fract
== -0.5)
3246 dblIn
= whole
- fmod(whole
, 2.0);
3247 else if (fract
> -0.5)
3250 dblIn
= whole
- 1.0;
3252 *pDblOut
= dblIn
/ scale
;
3259 /* Powers of 10 from 0..4 D.P. */
3260 static const int CY_Divisors
[5] = { CY_MULTIPLIER
/10000, CY_MULTIPLIER
/1000,
3261 CY_MULTIPLIER
/100, CY_MULTIPLIER
/10, CY_MULTIPLIER
};
3263 /************************************************************************
3264 * VarCyFromUI1 (OLEAUT32.98)
3266 * Convert a VT_UI1 to a VT_CY.
3270 * pCyOut [O] Destination
3274 * Failure: E_INVALIDARG, if the source value is invalid
3275 * DISP_E_OVERFLOW, if the value will not fit in the destination
3276 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3278 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pCyOut
)
3280 return _VarCyFromUI1(bIn
, pCyOut
);
3283 /************************************************************************
3284 * VarCyFromI2 (OLEAUT32.99)
3286 * Convert a VT_I2 to a VT_CY.
3290 * pCyOut [O] Destination
3294 * Failure: E_INVALIDARG, if the source value is invalid
3295 * DISP_E_OVERFLOW, if the value will not fit in the destination
3296 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3298 HRESULT WINAPI
VarCyFromI2(SHORT sIn
, CY
* pCyOut
)
3300 return _VarCyFromI2(sIn
, pCyOut
);
3303 /************************************************************************
3304 * VarCyFromI4 (OLEAUT32.100)
3306 * Convert a VT_I4 to a VT_CY.
3310 * pCyOut [O] Destination
3314 * Failure: E_INVALIDARG, if the source value is invalid
3315 * DISP_E_OVERFLOW, if the value will not fit in the destination
3316 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3318 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pCyOut
)
3320 return _VarCyFromI4(lIn
, pCyOut
);
3323 /************************************************************************
3324 * VarCyFromR4 (OLEAUT32.101)
3326 * Convert a VT_R4 to a VT_CY.
3330 * pCyOut [O] Destination
3334 * Failure: E_INVALIDARG, if the source value is invalid
3335 * DISP_E_OVERFLOW, if the value will not fit in the destination
3336 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3338 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pCyOut
)
3340 return _VarCyFromR4(fltIn
, pCyOut
);
3343 /************************************************************************
3344 * VarCyFromR8 (OLEAUT32.102)
3346 * Convert a VT_R8 to a VT_CY.
3350 * pCyOut [O] Destination
3354 * Failure: E_INVALIDARG, if the source value is invalid
3355 * DISP_E_OVERFLOW, if the value will not fit in the destination
3356 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3358 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pCyOut
)
3360 #if defined(__GNUC__) && defined(__i386__)
3361 /* This code gives identical results to Win32 on Intel.
3362 * Here we use fp exceptions to catch overflows when storing the value.
3364 static const unsigned short r8_fpcontrol
= 0x137f;
3365 static const double r8_multiplier
= CY_MULTIPLIER_F
;
3366 unsigned short old_fpcontrol
, result_fpstatus
;
3368 /* Clear exceptions, save the old fp state and load the new state */
3369 __asm__
__volatile__( "fnclex" );
3370 __asm__
__volatile__( "fstcw %0" : "=m" (old_fpcontrol
) : );
3371 __asm__
__volatile__( "fldcw %0" : : "m" (r8_fpcontrol
) );
3372 /* Perform the conversion. */
3373 __asm__
__volatile__( "fldl %0" : : "m" (dblIn
) );
3374 __asm__
__volatile__( "fmull %0" : : "m" (r8_multiplier
) );
3375 __asm__
__volatile__( "fistpll %0" : : "m" (*pCyOut
) );
3376 /* Save the resulting fp state, load the old state and clear exceptions */
3377 __asm__
__volatile__( "fstsw %0" : "=m" (result_fpstatus
) : );
3378 __asm__
__volatile__( "fnclex" );
3379 __asm__
__volatile__( "fldcw %0" : : "m" (old_fpcontrol
) );
3381 if (result_fpstatus
& 0x9) /* Overflow | Invalid */
3382 return DISP_E_OVERFLOW
;
3385 /* This version produces slightly different results for boundary cases */
3386 if (dblIn
< -922337203685477.5807 || dblIn
>= 922337203685477.5807)
3387 return DISP_E_OVERFLOW
;
3388 dblIn
*= CY_MULTIPLIER_F
;
3389 OLEAUT32_DutchRound(LONG64
, dblIn
, pCyOut
->int64
);
3394 /************************************************************************
3395 * VarCyFromDate (OLEAUT32.103)
3397 * Convert a VT_DATE to a VT_CY.
3401 * pCyOut [O] Destination
3405 * Failure: E_INVALIDARG, if the source value is invalid
3406 * DISP_E_OVERFLOW, if the value will not fit in the destination
3407 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3409 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pCyOut
)
3411 return _VarCyFromDate(dateIn
, pCyOut
);
3414 /************************************************************************
3415 * VarCyFromStr (OLEAUT32.104)
3417 * Convert a VT_BSTR to a VT_CY.
3421 * lcid [I] LCID for the conversion
3422 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3423 * pCyOut [O] Destination
3427 * Failure: E_INVALIDARG, if the source value is invalid
3428 * DISP_E_OVERFLOW, if the value will not fit in the destination
3429 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3431 HRESULT WINAPI
VarCyFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CY
* pCyOut
)
3433 return _VarCyFromStr(strIn
, lcid
, dwFlags
, pCyOut
);
3436 /************************************************************************
3437 * VarCyFromDisp (OLEAUT32.105)
3439 * Convert a VT_DISPATCH to a VT_CY.
3442 * pdispIn [I] Source
3443 * lcid [I] LCID for conversion
3444 * pCyOut [O] Destination
3448 * Failure: E_INVALIDARG, if the source value is invalid
3449 * DISP_E_OVERFLOW, if the value will not fit in the destination
3450 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3452 HRESULT WINAPI
VarCyFromDisp(IDispatch
* pdispIn
, LCID lcid
, CY
* pCyOut
)
3454 return _VarCyFromDisp(pdispIn
, lcid
, pCyOut
);
3458 /************************************************************************
3459 * VarCyFromBool (OLEAUT32.106)
3461 * Convert a VT_BOOL to a VT_CY.
3465 * pCyOut [O] Destination
3469 * Failure: E_INVALIDARG, if the source value is invalid
3470 * DISP_E_OVERFLOW, if the value will not fit in the destination
3471 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3474 * While the sign of the boolean is stored in the currency, the value is
3475 * converted to either 0 or 1.
3477 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pCyOut
)
3479 return _VarCyFromBool(boolIn
, pCyOut
);
3482 /************************************************************************
3483 * VarCyFromI1 (OLEAUT32.225)
3485 * Convert a VT_I1 to a VT_CY.
3489 * pCyOut [O] Destination
3493 * Failure: E_INVALIDARG, if the source value is invalid
3494 * DISP_E_OVERFLOW, if the value will not fit in the destination
3495 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3497 HRESULT WINAPI
VarCyFromI1(signed char cIn
, CY
* pCyOut
)
3499 return _VarCyFromI1(cIn
, pCyOut
);
3502 /************************************************************************
3503 * VarCyFromUI2 (OLEAUT32.226)
3505 * Convert a VT_UI2 to a VT_CY.
3509 * pCyOut [O] Destination
3513 * Failure: E_INVALIDARG, if the source value is invalid
3514 * DISP_E_OVERFLOW, if the value will not fit in the destination
3515 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3517 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pCyOut
)
3519 return _VarCyFromUI2(usIn
, pCyOut
);
3522 /************************************************************************
3523 * VarCyFromUI4 (OLEAUT32.227)
3525 * Convert a VT_UI4 to a VT_CY.
3529 * pCyOut [O] Destination
3533 * Failure: E_INVALIDARG, if the source value is invalid
3534 * DISP_E_OVERFLOW, if the value will not fit in the destination
3535 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3537 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pCyOut
)
3539 return _VarCyFromUI4(ulIn
, pCyOut
);
3542 /************************************************************************
3543 * VarCyFromDec (OLEAUT32.228)
3545 * Convert a VT_DECIMAL to a VT_CY.
3549 * pCyOut [O] Destination
3553 * Failure: E_INVALIDARG, if the source value is invalid
3554 * DISP_E_OVERFLOW, if the value will not fit in the destination
3555 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3557 HRESULT WINAPI
VarCyFromDec(DECIMAL
* pdecIn
, CY
* pCyOut
)
3562 hRet
= VarDecRound(pdecIn
, 4, &rounded
);
3564 if (SUCCEEDED(hRet
))
3568 if (DEC_HI32(&rounded
))
3569 return DISP_E_OVERFLOW
;
3571 /* Note: Without the casts this promotes to int64 which loses precision */
3572 d
= (double)DEC_LO64(&rounded
) / (double)CY_Divisors
[DEC_SCALE(&rounded
)];
3573 if (DEC_SIGN(&rounded
))
3575 return _VarCyFromR8(d
, pCyOut
);
3580 /************************************************************************
3581 * VarCyFromI8 (OLEAUT32.366)
3583 * Convert a VT_I8 to a VT_CY.
3587 * pCyOut [O] Destination
3591 * Failure: E_INVALIDARG, if the source value is invalid
3592 * DISP_E_OVERFLOW, if the value will not fit in the destination
3593 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3595 HRESULT WINAPI
VarCyFromI8(LONG64 llIn
, CY
* pCyOut
)
3597 return _VarCyFromI8(llIn
, pCyOut
);
3600 /************************************************************************
3601 * VarCyFromUI8 (OLEAUT32.375)
3603 * Convert a VT_UI8 to a VT_CY.
3607 * pCyOut [O] Destination
3611 * Failure: E_INVALIDARG, if the source value is invalid
3612 * DISP_E_OVERFLOW, if the value will not fit in the destination
3613 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3615 HRESULT WINAPI
VarCyFromUI8(ULONG64 ullIn
, CY
* pCyOut
)
3617 return _VarCyFromUI8(ullIn
, pCyOut
);
3620 /************************************************************************
3621 * VarCyAdd (OLEAUT32.299)
3623 * Add one CY to another.
3627 * cyRight [I] Value to add
3628 * pCyOut [O] Destination
3632 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3634 HRESULT WINAPI
VarCyAdd(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3637 _VarR8FromCy(cyLeft
, &l
);
3638 _VarR8FromCy(cyRight
, &r
);
3640 return _VarCyFromR8(l
, pCyOut
);
3643 /************************************************************************
3644 * VarCyMul (OLEAUT32.303)
3646 * Multiply one CY by another.
3650 * cyRight [I] Value to multiply by
3651 * pCyOut [O] Destination
3655 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3657 HRESULT WINAPI
VarCyMul(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3660 _VarR8FromCy(cyLeft
, &l
);
3661 _VarR8FromCy(cyRight
, &r
);
3663 return _VarCyFromR8(l
, pCyOut
);
3666 /************************************************************************
3667 * VarCyMulI4 (OLEAUT32.304)
3669 * Multiply one CY by a VT_I4.
3673 * lRight [I] Value to multiply by
3674 * pCyOut [O] Destination
3678 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3680 HRESULT WINAPI
VarCyMulI4(const CY cyLeft
, LONG lRight
, CY
* pCyOut
)
3684 _VarR8FromCy(cyLeft
, &d
);
3686 return _VarCyFromR8(d
, pCyOut
);
3689 /************************************************************************
3690 * VarCySub (OLEAUT32.305)
3692 * Subtract one CY from another.
3696 * cyRight [I] Value to subtract
3697 * pCyOut [O] Destination
3701 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3703 HRESULT WINAPI
VarCySub(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3706 _VarR8FromCy(cyLeft
, &l
);
3707 _VarR8FromCy(cyRight
, &r
);
3709 return _VarCyFromR8(l
, pCyOut
);
3712 /************************************************************************
3713 * VarCyAbs (OLEAUT32.306)
3715 * Convert a VT_CY into its absolute value.
3719 * pCyOut [O] Destination
3722 * Success: S_OK. pCyOut contains the absolute value.
3723 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3725 HRESULT WINAPI
VarCyAbs(const CY cyIn
, CY
* pCyOut
)
3727 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3728 return DISP_E_OVERFLOW
;
3730 pCyOut
->int64
= cyIn
.int64
< 0 ? -cyIn
.int64
: cyIn
.int64
;
3734 /************************************************************************
3735 * VarCyFix (OLEAUT32.307)
3737 * Return the integer part of a VT_CY.
3741 * pCyOut [O] Destination
3745 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3748 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3749 * negative numbers away from 0, while this function rounds them towards zero.
3751 HRESULT WINAPI
VarCyFix(const CY cyIn
, CY
* pCyOut
)
3753 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3754 pCyOut
->int64
*= CY_MULTIPLIER
;
3758 /************************************************************************
3759 * VarCyInt (OLEAUT32.308)
3761 * Return the integer part of a VT_CY.
3765 * pCyOut [O] Destination
3769 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3772 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3773 * negative numbers towards 0, while this function rounds them away from zero.
3775 HRESULT WINAPI
VarCyInt(const CY cyIn
, CY
* pCyOut
)
3777 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3778 pCyOut
->int64
*= CY_MULTIPLIER
;
3780 if (cyIn
.int64
< 0 && cyIn
.int64
% CY_MULTIPLIER
!= 0)
3782 pCyOut
->int64
-= CY_MULTIPLIER
;
3787 /************************************************************************
3788 * VarCyNeg (OLEAUT32.309)
3790 * Change the sign of a VT_CY.
3794 * pCyOut [O] Destination
3798 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3800 HRESULT WINAPI
VarCyNeg(const CY cyIn
, CY
* pCyOut
)
3802 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3803 return DISP_E_OVERFLOW
;
3805 pCyOut
->int64
= -cyIn
.int64
;
3809 /************************************************************************
3810 * VarCyRound (OLEAUT32.310)
3812 * Change the precision of a VT_CY.
3816 * cDecimals [I] New number of decimals to keep
3817 * pCyOut [O] Destination
3821 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3823 HRESULT WINAPI
VarCyRound(const CY cyIn
, int cDecimals
, CY
* pCyOut
)
3826 return E_INVALIDARG
;
3830 /* Rounding to more precision than we have */
3836 double d
, div
= CY_Divisors
[cDecimals
];
3838 _VarR8FromCy(cyIn
, &d
);
3840 OLEAUT32_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3841 d
= (double)pCyOut
->int64
/ div
* CY_MULTIPLIER_F
;
3842 OLEAUT32_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3847 /************************************************************************
3848 * VarCyCmp (OLEAUT32.311)
3850 * Compare two VT_CY values.
3854 * cyRight [I] Value to compare
3857 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
3858 * compare is less, equal or greater than source respectively.
3859 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3861 HRESULT WINAPI
VarCyCmp(const CY cyLeft
, const CY cyRight
)
3866 /* Subtract right from left, and compare the result to 0 */
3867 hRet
= VarCySub(cyLeft
, cyRight
, &result
);
3869 if (SUCCEEDED(hRet
))
3871 if (result
.int64
< 0)
3872 hRet
= (HRESULT
)VARCMP_LT
;
3873 else if (result
.int64
> 0)
3874 hRet
= (HRESULT
)VARCMP_GT
;
3876 hRet
= (HRESULT
)VARCMP_EQ
;
3881 /************************************************************************
3882 * VarCyCmpR8 (OLEAUT32.312)
3884 * Compare a VT_CY to a double
3887 * cyLeft [I] Currency Source
3888 * dblRight [I] double to compare to cyLeft
3891 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
3892 * less than, equal to or greater than cyLeft respectively.
3893 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3895 HRESULT WINAPI
VarCyCmpR8(const CY cyLeft
, double dblRight
)
3900 hRet
= _VarCyFromR8(dblRight
, &cyRight
);
3902 if (SUCCEEDED(hRet
))
3903 hRet
= VarCyCmp(cyLeft
, cyRight
);
3908 /************************************************************************
3909 * VarCyMulI8 (OLEAUT32.329)
3911 * Multiply a VT_CY by a VT_I8.
3915 * llRight [I] Value to multiply by
3916 * pCyOut [O] Destination
3920 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3922 HRESULT WINAPI
VarCyMulI8(const CY cyLeft
, LONG64 llRight
, CY
* pCyOut
)
3926 _VarR8FromCy(cyLeft
, &d
);
3927 d
= d
* (double)llRight
;
3928 return _VarCyFromR8(d
, pCyOut
);
3934 /************************************************************************
3935 * VarDecFromUI1 (OLEAUT32.190)
3937 * Convert a VT_UI1 to a DECIMAL.
3941 * pDecOut [O] Destination
3946 HRESULT WINAPI
VarDecFromUI1(BYTE bIn
, DECIMAL
* pDecOut
)
3948 return _VarDecFromUI1(bIn
, pDecOut
);
3951 /************************************************************************
3952 * VarDecFromI2 (OLEAUT32.191)
3954 * Convert a VT_I2 to a DECIMAL.
3958 * pDecOut [O] Destination
3963 HRESULT WINAPI
VarDecFromI2(SHORT sIn
, DECIMAL
* pDecOut
)
3965 return _VarDecFromI2(sIn
, pDecOut
);
3968 /************************************************************************
3969 * VarDecFromI4 (OLEAUT32.192)
3971 * Convert a VT_I4 to a DECIMAL.
3975 * pDecOut [O] Destination
3980 HRESULT WINAPI
VarDecFromI4(LONG lIn
, DECIMAL
* pDecOut
)
3982 DEC_HI32(pDecOut
) = 0;
3983 DEC_MID32(pDecOut
) = 0;
3987 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
3988 DEC_LO32(pDecOut
) = -lIn
;
3992 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
3993 DEC_LO32(pDecOut
) = lIn
;
3998 /************************************************************************
3999 * VarDecFromR4 (OLEAUT32.193)
4001 * Convert a VT_R4 to a DECIMAL.
4005 * pDecOut [O] Destination
4010 HRESULT WINAPI
VarDecFromR4(FLOAT fltIn
, DECIMAL
* pDecOut
)
4014 sprintfW( buff
, szFloatFormatW
, fltIn
);
4015 return _VarDecFromStr(buff
, LOCALE_SYSTEM_DEFAULT
, 0, pDecOut
);
4018 /************************************************************************
4019 * VarDecFromR8 (OLEAUT32.194)
4021 * Convert a VT_R8 to a DECIMAL.
4025 * pDecOut [O] Destination
4030 HRESULT WINAPI
VarDecFromR8(double dblIn
, DECIMAL
* pDecOut
)
4034 sprintfW( buff
, szDoubleFormatW
, dblIn
);
4035 return _VarDecFromStr(buff
, LOCALE_USER_DEFAULT
, 0, pDecOut
);
4038 /************************************************************************
4039 * VarDecFromDate (OLEAUT32.195)
4041 * Convert a VT_DATE to a DECIMAL.
4045 * pDecOut [O] Destination
4050 HRESULT WINAPI
VarDecFromDate(DATE dateIn
, DECIMAL
* pDecOut
)
4052 return _VarDecFromDate(dateIn
, pDecOut
);
4055 /************************************************************************
4056 * VarDecFromCy (OLEAUT32.196)
4058 * Convert a VT_CY to a DECIMAL.
4062 * pDecOut [O] Destination
4067 HRESULT WINAPI
VarDecFromCy(CY cyIn
, DECIMAL
* pDecOut
)
4069 DEC_HI32(pDecOut
) = 0;
4071 /* Note: This assumes 2s complement integer representation */
4072 if (cyIn
.s
.Hi
& 0x80000000)
4074 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,4);
4075 DEC_LO64(pDecOut
) = -cyIn
.int64
;
4079 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,4);
4080 DEC_MID32(pDecOut
) = cyIn
.s
.Hi
;
4081 DEC_LO32(pDecOut
) = cyIn
.s
.Lo
;
4087 /************************************************************************
4088 * VarDecFromStr (OLEAUT32.197)
4090 * Convert a VT_BSTR to a DECIMAL.
4094 * lcid [I] LCID for the conversion
4095 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4096 * pDecOut [O] Destination
4100 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4102 HRESULT WINAPI
VarDecFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DECIMAL
* pDecOut
)
4104 return _VarDecFromStr(strIn
, lcid
, dwFlags
, pDecOut
);
4107 /************************************************************************
4108 * VarDecFromDisp (OLEAUT32.198)
4110 * Convert a VT_DISPATCH to a DECIMAL.
4113 * pdispIn [I] Source
4114 * lcid [I] LCID for conversion
4115 * pDecOut [O] Destination
4119 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4121 HRESULT WINAPI
VarDecFromDisp(IDispatch
* pdispIn
, LCID lcid
, DECIMAL
* pDecOut
)
4123 return _VarDecFromDisp(pdispIn
, lcid
, pDecOut
);
4126 /************************************************************************
4127 * VarDecFromBool (OLEAUT32.199)
4129 * Convert a VT_BOOL to a DECIMAL.
4133 * pDecOut [O] Destination
4139 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4141 HRESULT WINAPI
VarDecFromBool(VARIANT_BOOL bIn
, DECIMAL
* pDecOut
)
4143 DEC_HI32(pDecOut
) = 0;
4144 DEC_MID32(pDecOut
) = 0;
4147 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4148 DEC_LO32(pDecOut
) = 1;
4152 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4153 DEC_LO32(pDecOut
) = 0;
4158 /************************************************************************
4159 * VarDecFromI1 (OLEAUT32.241)
4161 * Convert a VT_I1 to a DECIMAL.
4165 * pDecOut [O] Destination
4170 HRESULT WINAPI
VarDecFromI1(signed char cIn
, DECIMAL
* pDecOut
)
4172 return _VarDecFromI1(cIn
, pDecOut
);
4175 /************************************************************************
4176 * VarDecFromUI2 (OLEAUT32.242)
4178 * Convert a VT_UI2 to a DECIMAL.
4182 * pDecOut [O] Destination
4187 HRESULT WINAPI
VarDecFromUI2(USHORT usIn
, DECIMAL
* pDecOut
)
4189 return _VarDecFromUI2(usIn
, pDecOut
);
4192 /************************************************************************
4193 * VarDecFromUI4 (OLEAUT32.243)
4195 * Convert a VT_UI4 to a DECIMAL.
4199 * pDecOut [O] Destination
4204 HRESULT WINAPI
VarDecFromUI4(ULONG ulIn
, DECIMAL
* pDecOut
)
4206 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4207 DEC_HI32(pDecOut
) = 0;
4208 DEC_MID32(pDecOut
) = 0;
4209 DEC_LO32(pDecOut
) = ulIn
;
4213 /************************************************************************
4214 * VarDecFromI8 (OLEAUT32.374)
4216 * Convert a VT_I8 to a DECIMAL.
4220 * pDecOut [O] Destination
4225 HRESULT WINAPI
VarDecFromI8(LONG64 llIn
, DECIMAL
* pDecOut
)
4227 PULARGE_INTEGER pLi
= (PULARGE_INTEGER
)&llIn
;
4229 DEC_HI32(pDecOut
) = 0;
4231 /* Note: This assumes 2s complement integer representation */
4232 if (pLi
->u
.HighPart
& 0x80000000)
4234 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4235 DEC_LO64(pDecOut
) = -pLi
->QuadPart
;
4239 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4240 DEC_MID32(pDecOut
) = pLi
->u
.HighPart
;
4241 DEC_LO32(pDecOut
) = pLi
->u
.LowPart
;
4246 /************************************************************************
4247 * VarDecFromUI8 (OLEAUT32.375)
4249 * Convert a VT_UI8 to a DECIMAL.
4253 * pDecOut [O] Destination
4258 HRESULT WINAPI
VarDecFromUI8(ULONG64 ullIn
, DECIMAL
* pDecOut
)
4260 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4261 DEC_HI32(pDecOut
) = 0;
4262 DEC_LO64(pDecOut
) = ullIn
;
4266 /* Make two DECIMALS the same scale; used by math functions below */
4267 static HRESULT
VARIANT_DecScale(const DECIMAL
** ppDecLeft
,
4268 const DECIMAL
** ppDecRight
,
4271 static DECIMAL scaleFactor
;
4274 HRESULT hRet
= S_OK
;
4276 if (DEC_SIGN(*ppDecLeft
) & ~DECIMAL_NEG
|| DEC_SIGN(*ppDecRight
) & ~DECIMAL_NEG
)
4277 return E_INVALIDARG
;
4279 DEC_LO32(&scaleFactor
) = 10;
4281 i
= scaleAmount
= DEC_SCALE(*ppDecLeft
) - DEC_SCALE(*ppDecRight
);
4284 return S_OK
; /* Same scale */
4286 if (scaleAmount
> 0)
4288 decTemp
= *(*ppDecRight
); /* Left is bigger - scale the right hand side */
4289 *ppDecRight
= pDecOut
;
4293 decTemp
= *(*ppDecLeft
); /* Right is bigger - scale the left hand side */
4294 *ppDecLeft
= pDecOut
;
4295 i
= scaleAmount
= -scaleAmount
;
4298 if (DEC_SCALE(&decTemp
) + scaleAmount
> DEC_MAX_SCALE
)
4299 return DISP_E_OVERFLOW
; /* Can't scale up */
4301 /* Multiply up the value to be scaled by the correct amount */
4302 while (SUCCEEDED(hRet
) && i
--)
4304 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4305 hRet
= VarDecMul(&decTemp
, &scaleFactor
, pDecOut
);
4308 DEC_SCALE(pDecOut
) += scaleAmount
; /* Set the new scale */
4312 /* Add two unsigned 32 bit values with overflow */
4313 static ULONG
VARIANT_Add(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4315 ULARGE_INTEGER ul64
;
4317 ul64
.QuadPart
= (ULONG64
)ulLeft
+ (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4318 *pulHigh
= ul64
.u
.HighPart
;
4319 return ul64
.u
.LowPart
;
4322 /* Subtract two unsigned 32 bit values with underflow */
4323 static ULONG
VARIANT_Sub(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4326 ULARGE_INTEGER ul64
;
4328 ul64
.QuadPart
= (LONG64
)ulLeft
- (ULONG64
)ulRight
;
4329 if (ulLeft
< ulRight
)
4332 if (ul64
.QuadPart
> (ULONG64
)*pulHigh
)
4333 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4336 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4340 ul64
.u
.HighPart
= -ul64
.u
.HighPart
;
4342 *pulHigh
= ul64
.u
.HighPart
;
4343 return ul64
.u
.LowPart
;
4346 /* Multiply two unsigned 32 bit values with overflow */
4347 static ULONG
VARIANT_Mul(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4349 ULARGE_INTEGER ul64
;
4351 ul64
.QuadPart
= (ULONG64
)ulLeft
* (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4352 *pulHigh
= ul64
.u
.HighPart
;
4353 return ul64
.u
.LowPart
;
4356 /* Compare two decimals that have the same scale */
4357 static inline int VARIANT_DecCmp(const DECIMAL
*pDecLeft
, const DECIMAL
*pDecRight
)
4359 if ( DEC_HI32(pDecLeft
) < DEC_HI32(pDecRight
) ||
4360 (DEC_HI32(pDecLeft
) <= DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) < DEC_LO64(pDecRight
)))
4362 else if (DEC_HI32(pDecLeft
) == DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) == DEC_LO64(pDecRight
))
4367 /************************************************************************
4368 * VarDecAdd (OLEAUT32.177)
4370 * Add one DECIMAL to another.
4373 * pDecLeft [I] Source
4374 * pDecRight [I] Value to add
4375 * pDecOut [O] Destination
4379 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4381 HRESULT WINAPI
VarDecAdd(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4386 hRet
= VARIANT_DecScale(&pDecLeft
, &pDecRight
, &scaled
);
4388 if (SUCCEEDED(hRet
))
4390 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4392 BYTE sign
= DECIMAL_POS
;
4394 /* Correct for the sign of the result */
4395 if (DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4397 /* -x + -y : Negative */
4399 goto VarDecAdd_AsPositive
;
4401 else if (DEC_SIGN(pDecLeft
) && !DEC_SIGN(pDecRight
))
4403 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4405 /* -x + y : Negative if x > y */
4409 VarDecAdd_AsNegative
:
4410 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4411 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4412 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4416 VarDecAdd_AsInvertedNegative
:
4417 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecRight
), DEC_LO32(pDecLeft
), &overflow
);
4418 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecRight
), DEC_MID32(pDecLeft
), &overflow
);
4419 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecRight
), DEC_HI32(pDecLeft
), &overflow
);
4422 else if (!DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4424 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4426 /* x + -y : Negative if x <= y */
4430 goto VarDecAdd_AsInvertedNegative
;
4432 goto VarDecAdd_AsNegative
;
4436 /* x + y : Positive */
4437 VarDecAdd_AsPositive
:
4438 DEC_LO32(pDecOut
) = VARIANT_Add(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4439 DEC_MID32(pDecOut
) = VARIANT_Add(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4440 DEC_HI32(pDecOut
) = VARIANT_Add(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4444 return DISP_E_OVERFLOW
; /* overflowed */
4446 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecLeft
);
4447 DEC_SIGN(pDecOut
) = sign
;
4452 /************************************************************************
4453 * VarDecDiv (OLEAUT32.178)
4455 * Divide one DECIMAL by another.
4458 * pDecLeft [I] Source
4459 * pDecRight [I] Value to divide by
4460 * pDecOut [O] Destination
4464 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4466 HRESULT WINAPI
VarDecDiv(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4468 FIXME("(%p,%p,%p)-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4469 return DISP_E_OVERFLOW
;
4472 /************************************************************************
4473 * VarDecMul (OLEAUT32.179)
4475 * Multiply one DECIMAL by another.
4478 * pDecLeft [I] Source
4479 * pDecRight [I] Value to multiply by
4480 * pDecOut [O] Destination
4484 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4486 HRESULT WINAPI
VarDecMul(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4488 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4490 if (!DEC_SCALE(pDecLeft
) || !DEC_SCALE(pDecRight
))
4492 /* At least one term is an integer */
4493 const DECIMAL
* pDecInteger
= DEC_SCALE(pDecLeft
) ? pDecRight
: pDecLeft
;
4494 const DECIMAL
* pDecOperand
= DEC_SCALE(pDecLeft
) ? pDecLeft
: pDecRight
;
4495 HRESULT hRet
= S_OK
;
4496 unsigned int multiplier
= DEC_LO32(pDecInteger
);
4499 if (DEC_HI32(pDecInteger
) || DEC_MID32(pDecInteger
))
4501 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4502 return DISP_E_OVERFLOW
;
4505 DEC_LO32(pDecOut
) = VARIANT_Mul(DEC_LO32(pDecOperand
), multiplier
, &overflow
);
4506 DEC_MID32(pDecOut
) = VARIANT_Mul(DEC_MID32(pDecOperand
), multiplier
, &overflow
);
4507 DEC_HI32(pDecOut
) = VARIANT_Mul(DEC_HI32(pDecOperand
), multiplier
, &overflow
);
4510 hRet
= DISP_E_OVERFLOW
;
4513 BYTE sign
= DECIMAL_POS
;
4515 if (DEC_SIGN(pDecLeft
) != DEC_SIGN(pDecRight
))
4516 sign
= DECIMAL_NEG
; /* pos * neg => negative */
4517 DEC_SIGN(pDecOut
) = sign
;
4518 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecOperand
);
4522 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4523 return DISP_E_OVERFLOW
;
4526 /************************************************************************
4527 * VarDecSub (OLEAUT32.181)
4529 * Subtract one DECIMAL from another.
4532 * pDecLeft [I] Source
4533 * pDecRight [I] DECIMAL to subtract from pDecLeft
4534 * pDecOut [O] Destination
4537 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4539 HRESULT WINAPI
VarDecSub(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4543 /* Implement as addition of the negative */
4544 VarDecNeg(pDecRight
, &decRight
);
4545 return VarDecAdd(pDecLeft
, &decRight
, pDecOut
);
4548 /************************************************************************
4549 * VarDecAbs (OLEAUT32.182)
4551 * Convert a DECIMAL into its absolute value.
4555 * pDecOut [O] Destination
4558 * S_OK. This function does not fail.
4560 HRESULT WINAPI
VarDecAbs(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4563 DEC_SIGN(pDecOut
) &= ~DECIMAL_NEG
;
4567 /************************************************************************
4568 * VarDecFix (OLEAUT32.187)
4570 * Return the integer portion of a DECIMAL.
4574 * pDecOut [O] Destination
4578 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4581 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4582 * negative numbers away from 0, while this function rounds them towards zero.
4584 HRESULT WINAPI
VarDecFix(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4586 if (DEC_SIGN(pDecOut
) & ~DECIMAL_NEG
)
4587 return E_INVALIDARG
;
4589 if (!DEC_SCALE(pDecIn
))
4591 *pDecOut
= *pDecIn
; /* Already an integer */
4595 FIXME("semi-stub!\n");
4596 return DISP_E_OVERFLOW
;
4599 /************************************************************************
4600 * VarDecInt (OLEAUT32.188)
4602 * Return the integer portion of a DECIMAL.
4606 * pDecOut [O] Destination
4610 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4613 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4614 * negative numbers towards 0, while this function rounds them away from zero.
4616 HRESULT WINAPI
VarDecInt(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4618 if (DEC_SIGN(pDecOut
) & ~DECIMAL_NEG
)
4619 return E_INVALIDARG
;
4621 if (!(DEC_SIGN(pDecOut
) & DECIMAL_NEG
) || !DEC_SCALE(pDecIn
))
4622 return VarDecFix(pDecIn
, pDecOut
); /* The same, if +ve or no fractionals */
4624 FIXME("semi-stub!\n");
4625 return DISP_E_OVERFLOW
;
4628 /************************************************************************
4629 * VarDecNeg (OLEAUT32.189)
4631 * Change the sign of a DECIMAL.
4635 * pDecOut [O] Destination
4638 * S_OK. This function does not fail.
4640 HRESULT WINAPI
VarDecNeg(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4643 DEC_SIGN(pDecOut
) ^= DECIMAL_NEG
;
4647 /************************************************************************
4648 * VarDecRound (OLEAUT32.203)
4650 * Change the precision of a DECIMAL.
4654 * cDecimals [I] New number of decimals to keep
4655 * pDecOut [O] Destination
4658 * Success: S_OK. pDecOut contains the rounded value.
4659 * Failure: E_INVALIDARG if any argument is invalid.
4661 HRESULT WINAPI
VarDecRound(const DECIMAL
* pDecIn
, int cDecimals
, DECIMAL
* pDecOut
)
4663 if (cDecimals
< 0 || (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
) || DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
)
4664 return E_INVALIDARG
;
4666 if (cDecimals
>= DEC_SCALE(pDecIn
))
4668 *pDecOut
= *pDecIn
; /* More precision than we have */
4672 FIXME("semi-stub!\n");
4674 return DISP_E_OVERFLOW
;
4677 /************************************************************************
4678 * VarDecCmp (OLEAUT32.204)
4680 * Compare two DECIMAL values.
4683 * pDecLeft [I] Source
4684 * pDecRight [I] Value to compare
4687 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4688 * is less than, equal to or greater than pDecRight respectively.
4689 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4691 HRESULT WINAPI
VarDecCmp(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
)
4696 /* Subtract right from left, and compare the result to 0 */
4697 hRet
= VarDecSub(pDecLeft
, pDecRight
, &result
);
4699 if (SUCCEEDED(hRet
))
4701 int non_zero
= DEC_HI32(&result
) | DEC_MID32(&result
) | DEC_LO32(&result
);
4703 if ((DEC_SIGN(&result
) & DECIMAL_NEG
) && non_zero
)
4704 hRet
= (HRESULT
)VARCMP_LT
;
4706 hRet
= (HRESULT
)VARCMP_GT
;
4708 hRet
= (HRESULT
)VARCMP_EQ
;
4714 /************************************************************************
4715 * VarDecCmpR8 (OLEAUT32.298)
4717 * Compare a DECIMAL to a double
4720 * pDecLeft [I] DECIMAL Source
4721 * dblRight [I] double to compare to pDecLeft
4724 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4725 * is less than, equal to or greater than pDecLeft respectively.
4726 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4728 HRESULT WINAPI
VarDecCmpR8(const DECIMAL
* pDecLeft
, double dblRight
)
4733 hRet
= VarDecFromR8(dblRight
, &decRight
);
4735 if (SUCCEEDED(hRet
))
4736 hRet
= VarDecCmp(pDecLeft
, &decRight
);
4744 /************************************************************************
4745 * VarBoolFromUI1 (OLEAUT32.118)
4747 * Convert a VT_UI1 to a VT_BOOL.
4751 * pBoolOut [O] Destination
4756 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
*pBoolOut
)
4758 return _VarBoolFromUI1(bIn
, pBoolOut
);
4761 /************************************************************************
4762 * VarBoolFromI2 (OLEAUT32.119)
4764 * Convert a VT_I2 to a VT_BOOL.
4768 * pBoolOut [O] Destination
4773 HRESULT WINAPI
VarBoolFromI2(SHORT sIn
, VARIANT_BOOL
*pBoolOut
)
4775 return _VarBoolFromI2(sIn
, pBoolOut
);
4778 /************************************************************************
4779 * VarBoolFromI4 (OLEAUT32.120)
4781 * Convert a VT_I4 to a VT_BOOL.
4785 * pBoolOut [O] Destination
4790 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
*pBoolOut
)
4792 return _VarBoolFromI4(lIn
, pBoolOut
);
4795 /************************************************************************
4796 * VarBoolFromR4 (OLEAUT32.121)
4798 * Convert a VT_R4 to a VT_BOOL.
4802 * pBoolOut [O] Destination
4807 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
*pBoolOut
)
4809 return _VarBoolFromR4(fltIn
, pBoolOut
);
4812 /************************************************************************
4813 * VarBoolFromR8 (OLEAUT32.122)
4815 * Convert a VT_R8 to a VT_BOOL.
4819 * pBoolOut [O] Destination
4824 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
*pBoolOut
)
4826 return _VarBoolFromR8(dblIn
, pBoolOut
);
4829 /************************************************************************
4830 * VarBoolFromDate (OLEAUT32.123)
4832 * Convert a VT_DATE to a VT_BOOL.
4836 * pBoolOut [O] Destination
4841 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
*pBoolOut
)
4843 return _VarBoolFromDate(dateIn
, pBoolOut
);
4846 /************************************************************************
4847 * VarBoolFromCy (OLEAUT32.124)
4849 * Convert a VT_CY to a VT_BOOL.
4853 * pBoolOut [O] Destination
4858 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
*pBoolOut
)
4860 return _VarBoolFromCy(cyIn
, pBoolOut
);
4863 static BOOL
VARIANT_GetLocalisedText(LANGID langId
, DWORD dwId
, WCHAR
*lpszDest
)
4867 hrsrc
= FindResourceExW( OLEAUT32_hModule
, (LPWSTR
)RT_STRING
,
4868 (LPCWSTR
)((dwId
>> 4) + 1), langId
);
4871 HGLOBAL hmem
= LoadResource( OLEAUT32_hModule
, hrsrc
);
4878 p
= LockResource( hmem
);
4879 for (i
= 0; i
< (dwId
& 0x0f); i
++) p
+= *p
+ 1;
4881 memcpy( lpszDest
, p
+ 1, *p
* sizeof(WCHAR
) );
4882 lpszDest
[*p
] = '\0';
4883 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest
), langId
);
4890 /************************************************************************
4891 * VarBoolFromStr (OLEAUT32.125)
4893 * Convert a VT_BSTR to a VT_BOOL.
4897 * lcid [I] LCID for the conversion
4898 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4899 * pBoolOut [O] Destination
4903 * Failure: E_INVALIDARG, if pBoolOut is invalid.
4904 * DISP_E_TYPEMISMATCH, if the type cannot be converted
4907 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
4908 * it may contain (in any case mapping) the text "true" or "false".
4909 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
4910 * localised text of "True" or "False" in the language specified by lcid.
4911 * - If none of these matches occur, the string is treated as a numeric string
4912 * and the boolean pBoolOut will be set according to whether the number is zero
4913 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
4914 * - If the text is not numeric and does not match any of the above, then
4915 * DISP_E_TYPEMISMATCH is returned.
4917 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
*pBoolOut
)
4919 /* Any VB/VBA programmers out there should recognise these strings... */
4920 static const WCHAR szFalse
[] = { '#','F','A','L','S','E','#','\0' };
4921 static const WCHAR szTrue
[] = { '#','T','R','U','E','#','\0' };
4923 LANGID langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4924 HRESULT hRes
= S_OK
;
4926 if (!strIn
|| !pBoolOut
)
4927 return DISP_E_TYPEMISMATCH
;
4929 /* Check if we should be comparing against localised text */
4930 if (dwFlags
& VAR_LOCALBOOL
)
4932 /* Convert our LCID into a usable value */
4933 lcid
= ConvertDefaultLocale(lcid
);
4935 langId
= LANGIDFROMLCID(lcid
);
4937 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
4938 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4940 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
4941 * I don't think this is needed unless any of the localised text strings
4942 * contain characters that can be so mapped. In the event that this is
4943 * true for a given language (possibly some Asian languages), then strIn
4944 * should be mapped here _only_ if langId is an Id for which this can occur.
4948 /* Note that if we are not comparing against localised strings, langId
4949 * will have its default value of LANG_ENGLISH. This allows us to mimic
4950 * the native behaviour of always checking against English strings even
4951 * after we've checked for localised ones.
4953 VarBoolFromStr_CheckLocalised
:
4954 if (VARIANT_GetLocalisedText(langId
, IDS_TRUE
, szBuff
))
4956 /* Compare against localised strings, ignoring case */
4957 if (!strcmpiW(strIn
, szBuff
))
4959 *pBoolOut
= VARIANT_TRUE
; /* Matched localised 'true' text */
4962 VARIANT_GetLocalisedText(langId
, IDS_FALSE
, szBuff
);
4963 if (!strcmpiW(strIn
, szBuff
))
4965 *pBoolOut
= VARIANT_FALSE
; /* Matched localised 'false' text */
4970 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
4972 /* We have checked the localised text, now check English */
4973 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4974 goto VarBoolFromStr_CheckLocalised
;
4977 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
4978 if (!strcmpW(strIn
, szFalse
))
4979 *pBoolOut
= VARIANT_FALSE
;
4980 else if (!strcmpW(strIn
, szTrue
))
4981 *pBoolOut
= VARIANT_TRUE
;
4986 /* If this string is a number, convert it as one */
4987 hRes
= _VarR8FromStr(strIn
, lcid
, dwFlags
, &d
);
4988 if (SUCCEEDED(hRes
))
4989 hRes
= _VarBoolFromR8(d
, pBoolOut
);
4994 /************************************************************************
4995 * VarBoolFromDisp (OLEAUT32.126)
4997 * Convert a VT_DISPATCH to a VT_BOOL.
5000 * pdispIn [I] Source
5001 * lcid [I] LCID for conversion
5002 * pBoolOut [O] Destination
5006 * Failure: E_INVALIDARG, if the source value is invalid
5007 * DISP_E_OVERFLOW, if the value will not fit in the destination
5008 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5010 HRESULT WINAPI
VarBoolFromDisp(IDispatch
* pdispIn
, LCID lcid
, VARIANT_BOOL
*pBoolOut
)
5012 return _VarBoolFromDisp(pdispIn
, lcid
, pBoolOut
);
5015 /************************************************************************
5016 * VarBoolFromI1 (OLEAUT32.233)
5018 * Convert a VT_I1 to a VT_BOOL.
5022 * pBoolOut [O] Destination
5027 HRESULT WINAPI
VarBoolFromI1(signed char cIn
, VARIANT_BOOL
*pBoolOut
)
5029 return _VarBoolFromI1(cIn
, pBoolOut
);
5032 /************************************************************************
5033 * VarBoolFromUI2 (OLEAUT32.234)
5035 * Convert a VT_UI2 to a VT_BOOL.
5039 * pBoolOut [O] Destination
5044 HRESULT WINAPI
VarBoolFromUI2(USHORT usIn
, VARIANT_BOOL
*pBoolOut
)
5046 return _VarBoolFromUI2(usIn
, pBoolOut
);
5049 /************************************************************************
5050 * VarBoolFromUI4 (OLEAUT32.235)
5052 * Convert a VT_UI4 to a VT_BOOL.
5056 * pBoolOut [O] Destination
5061 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
*pBoolOut
)
5063 return _VarBoolFromUI4(ulIn
, pBoolOut
);
5066 /************************************************************************
5067 * VarBoolFromDec (OLEAUT32.236)
5069 * Convert a VT_DECIMAL to a VT_BOOL.
5073 * pBoolOut [O] Destination
5077 * Failure: E_INVALIDARG, if pDecIn is invalid.
5079 HRESULT WINAPI
VarBoolFromDec(DECIMAL
* pDecIn
, VARIANT_BOOL
*pBoolOut
)
5081 if (DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
|| (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
))
5082 return E_INVALIDARG
;
5084 if (DEC_HI32(pDecIn
) || DEC_MID32(pDecIn
) || DEC_LO32(pDecIn
))
5085 *pBoolOut
= VARIANT_TRUE
;
5087 *pBoolOut
= VARIANT_FALSE
;
5091 /************************************************************************
5092 * VarBoolFromI8 (OLEAUT32.370)
5094 * Convert a VT_I8 to a VT_BOOL.
5098 * pBoolOut [O] Destination
5103 HRESULT WINAPI
VarBoolFromI8(LONG64 llIn
, VARIANT_BOOL
*pBoolOut
)
5105 return _VarBoolFromI8(llIn
, pBoolOut
);
5108 /************************************************************************
5109 * VarBoolFromUI8 (OLEAUT32.371)
5111 * Convert a VT_UI8 to a VT_BOOL.
5115 * pBoolOut [O] Destination
5120 HRESULT WINAPI
VarBoolFromUI8(ULONG64 ullIn
, VARIANT_BOOL
*pBoolOut
)
5122 return _VarBoolFromUI8(ullIn
, pBoolOut
);
5128 /* Write a number from a UI8 and sign */
5129 static WCHAR
*VARIANT_WriteNumber(ULONG64 ulVal
, WCHAR
* szOut
)
5133 WCHAR ulNextDigit
= ulVal
% 10;
5135 *szOut
-- = '0' + ulNextDigit
;
5136 ulVal
= (ulVal
- ulNextDigit
) / 10;
5143 /* Create a (possibly localised) BSTR from a UI8 and sign */
5144 static BSTR
VARIANT_MakeBstr(LCID lcid
, DWORD dwFlags
, WCHAR
*szOut
)
5146 WCHAR szConverted
[256];
5148 if (dwFlags
& VAR_NEGATIVE
)
5151 if (dwFlags
& LOCALE_USE_NLS
)
5153 /* Format the number for the locale */
5154 szConverted
[0] = '\0';
5155 GetNumberFormatW(lcid
,
5156 dwFlags
& LOCALE_NOUSEROVERRIDE
,
5157 szOut
, NULL
, szConverted
, sizeof(szConverted
)/sizeof(WCHAR
));
5158 szOut
= szConverted
;
5160 return SysAllocStringByteLen((LPCSTR
)szOut
, strlenW(szOut
) * sizeof(WCHAR
));
5163 /* Create a (possibly localised) BSTR from a UI8 and sign */
5164 static HRESULT
VARIANT_BstrFromUInt(ULONG64 ulVal
, LCID lcid
, DWORD dwFlags
, BSTR
*pbstrOut
)
5166 WCHAR szBuff
[64], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5169 return E_INVALIDARG
;
5171 /* Create the basic number string */
5173 szOut
= VARIANT_WriteNumber(ulVal
, szOut
);
5175 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5176 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5177 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5180 /******************************************************************************
5181 * VarBstrFromUI1 (OLEAUT32.108)
5183 * Convert a VT_UI1 to a VT_BSTR.
5187 * lcid [I] LCID for the conversion
5188 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5189 * pbstrOut [O] Destination
5193 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5194 * E_OUTOFMEMORY, if memory allocation fails.
5196 HRESULT WINAPI
VarBstrFromUI1(BYTE bIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5198 return VARIANT_BstrFromUInt(bIn
, lcid
, dwFlags
, pbstrOut
);
5201 /******************************************************************************
5202 * VarBstrFromI2 (OLEAUT32.109)
5204 * Convert a VT_I2 to a VT_BSTR.
5208 * lcid [I] LCID for the conversion
5209 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5210 * pbstrOut [O] Destination
5214 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5215 * E_OUTOFMEMORY, if memory allocation fails.
5217 HRESULT WINAPI
VarBstrFromI2(short sIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5224 dwFlags
|= VAR_NEGATIVE
;
5226 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5229 /******************************************************************************
5230 * VarBstrFromI4 (OLEAUT32.110)
5232 * Convert a VT_I4 to a VT_BSTR.
5236 * lcid [I] LCID for the conversion
5237 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5238 * pbstrOut [O] Destination
5242 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5243 * E_OUTOFMEMORY, if memory allocation fails.
5245 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5252 dwFlags
|= VAR_NEGATIVE
;
5254 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5257 static HRESULT
VARIANT_BstrFromReal(DOUBLE dblIn
, LCID lcid
, ULONG dwFlags
,
5258 BSTR
* pbstrOut
, LPCWSTR lpszFormat
)
5263 return E_INVALIDARG
;
5265 sprintfW( buff
, lpszFormat
, dblIn
);
5266 TRACE("created string %s\n", debugstr_w(buff
));
5267 if (dwFlags
& LOCALE_USE_NLS
)
5271 /* Format the number for the locale */
5273 GetNumberFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5274 buff
, NULL
, numbuff
, sizeof(numbuff
) / sizeof(WCHAR
));
5275 TRACE("created NLS string %s\n", debugstr_w(numbuff
));
5276 *pbstrOut
= SysAllocString(numbuff
);
5279 *pbstrOut
= SysAllocString(buff
);
5280 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5283 /******************************************************************************
5284 * VarBstrFromR4 (OLEAUT32.111)
5286 * Convert a VT_R4 to a VT_BSTR.
5290 * lcid [I] LCID for the conversion
5291 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5292 * pbstrOut [O] Destination
5296 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5297 * E_OUTOFMEMORY, if memory allocation fails.
5299 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5301 return VARIANT_BstrFromReal(fltIn
, lcid
, dwFlags
, pbstrOut
, szFloatFormatW
);
5304 /******************************************************************************
5305 * VarBstrFromR8 (OLEAUT32.112)
5307 * Convert a VT_R8 to a VT_BSTR.
5311 * lcid [I] LCID for the conversion
5312 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5313 * pbstrOut [O] Destination
5317 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5318 * E_OUTOFMEMORY, if memory allocation fails.
5320 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5322 return VARIANT_BstrFromReal(dblIn
, lcid
, dwFlags
, pbstrOut
, szDoubleFormatW
);
5325 /******************************************************************************
5326 * VarBstrFromCy [OLEAUT32.113]
5328 * Convert a VT_CY to a VT_BSTR.
5332 * lcid [I] LCID for the conversion
5333 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5334 * pbstrOut [O] Destination
5338 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5339 * E_OUTOFMEMORY, if memory allocation fails.
5341 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
)
5347 return E_INVALIDARG
;
5349 VarR8FromCy(cyIn
, &dblVal
);
5350 sprintfW(buff
, szDoubleFormatW
, dblVal
);
5352 if (dwFlags
& LOCALE_USE_NLS
)
5356 /* Format the currency for the locale */
5358 GetCurrencyFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5359 buff
, NULL
, cybuff
, sizeof(cybuff
) / sizeof(WCHAR
));
5360 *pbstrOut
= SysAllocString(cybuff
);
5363 *pbstrOut
= SysAllocString(buff
);
5365 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5368 /******************************************************************************
5369 * VarBstrFromDate [OLEAUT32.114]
5371 * Convert a VT_DATE to a VT_BSTR.
5375 * lcid [I] LCID for the conversion
5376 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5377 * pbstrOut [O] Destination
5381 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5382 * E_OUTOFMEMORY, if memory allocation fails.
5384 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5387 DWORD dwFormatFlags
= dwFlags
& LOCALE_NOUSEROVERRIDE
;
5388 WCHAR date
[128], *time
;
5390 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
5392 if (!pbstrOut
|| !VariantTimeToSystemTime(dateIn
, &st
))
5393 return E_INVALIDARG
;
5397 if (dwFlags
& VAR_CALENDAR_THAI
)
5398 st
.wYear
+= 553; /* Use the Thai buddhist calendar year */
5399 else if (dwFlags
& (VAR_CALENDAR_HIJRI
|VAR_CALENDAR_GREGORIAN
))
5400 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5402 if (dwFlags
& LOCALE_USE_NLS
)
5403 dwFlags
&= ~(VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
);
5406 double whole
= dateIn
< 0 ? ceil(dateIn
) : floor(dateIn
);
5407 double partial
= dateIn
- whole
;
5410 dwFlags
|= VAR_TIMEVALUEONLY
;
5411 else if (partial
< 1e-12)
5412 dwFlags
|= VAR_DATEVALUEONLY
;
5415 if (dwFlags
& VAR_TIMEVALUEONLY
)
5418 if (!GetDateFormatW(lcid
, dwFormatFlags
|DATE_SHORTDATE
, &st
, NULL
, date
,
5419 sizeof(date
)/sizeof(WCHAR
)))
5420 return E_INVALIDARG
;
5422 if (!(dwFlags
& VAR_DATEVALUEONLY
))
5424 time
= date
+ strlenW(date
);
5427 if (!GetTimeFormatW(lcid
, dwFormatFlags
, &st
, NULL
, time
,
5428 sizeof(date
)/sizeof(WCHAR
)-(time
-date
)))
5429 return E_INVALIDARG
;
5432 *pbstrOut
= SysAllocString(date
);
5434 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5435 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5438 /******************************************************************************
5439 * VarBstrFromBool (OLEAUT32.116)
5441 * Convert a VT_BOOL to a VT_BSTR.
5445 * lcid [I] LCID for the conversion
5446 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5447 * pbstrOut [O] Destination
5451 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5452 * E_OUTOFMEMORY, if memory allocation fails.
5455 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5456 * localised text of "True" or "False". To convert a bool into a
5457 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5459 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5462 DWORD dwResId
= IDS_TRUE
;
5465 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
5468 return E_INVALIDARG
;
5470 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5471 * for variant formatting */
5472 switch (dwFlags
& (VAR_LOCALBOOL
|VAR_BOOLONOFF
|VAR_BOOLYESNO
))
5483 lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
),SORT_DEFAULT
);
5486 lcid
= ConvertDefaultLocale(lcid
);
5487 langId
= LANGIDFROMLCID(lcid
);
5488 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
5489 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5491 if (boolIn
== VARIANT_FALSE
)
5492 dwResId
++; /* Use negative form */
5494 VarBstrFromBool_GetLocalised
:
5495 if (VARIANT_GetLocalisedText(langId
, dwResId
, szBuff
))
5497 *pbstrOut
= SysAllocString(szBuff
);
5498 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5501 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
5503 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5504 goto VarBstrFromBool_GetLocalised
;
5507 /* Should never get here */
5508 WARN("Failed to load bool text!\n");
5509 return E_OUTOFMEMORY
;
5512 /******************************************************************************
5513 * VarBstrFromI1 (OLEAUT32.229)
5515 * Convert a VT_I1 to a VT_BSTR.
5519 * lcid [I] LCID for the conversion
5520 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5521 * pbstrOut [O] Destination
5525 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5526 * E_OUTOFMEMORY, if memory allocation fails.
5528 HRESULT WINAPI
VarBstrFromI1(signed char cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5535 dwFlags
|= VAR_NEGATIVE
;
5537 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5540 /******************************************************************************
5541 * VarBstrFromUI2 (OLEAUT32.230)
5543 * Convert a VT_UI2 to a VT_BSTR.
5547 * lcid [I] LCID for the conversion
5548 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5549 * pbstrOut [O] Destination
5553 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5554 * E_OUTOFMEMORY, if memory allocation fails.
5556 HRESULT WINAPI
VarBstrFromUI2(USHORT usIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5558 return VARIANT_BstrFromUInt(usIn
, lcid
, dwFlags
, pbstrOut
);
5561 /******************************************************************************
5562 * VarBstrFromUI4 (OLEAUT32.231)
5564 * Convert a VT_UI4 to a VT_BSTR.
5568 * lcid [I] LCID for the conversion
5569 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5570 * pbstrOut [O] Destination
5574 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5575 * E_OUTOFMEMORY, if memory allocation fails.
5577 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5579 return VARIANT_BstrFromUInt(ulIn
, lcid
, dwFlags
, pbstrOut
);
5582 /******************************************************************************
5583 * VarBstrFromDec (OLEAUT32.232)
5585 * Convert a VT_DECIMAL to a VT_BSTR.
5589 * lcid [I] LCID for the conversion
5590 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5591 * pbstrOut [O] Destination
5595 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5596 * E_OUTOFMEMORY, if memory allocation fails.
5598 HRESULT WINAPI
VarBstrFromDec(DECIMAL
* pDecIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5601 return E_INVALIDARG
;
5603 if (!DEC_SCALE(pDecIn
) && !DEC_HI32(pDecIn
))
5605 WCHAR szBuff
[256], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5607 /* Create the basic number string */
5609 szOut
= VARIANT_WriteNumber(DEC_LO64(pDecIn
), szOut
);
5610 if (DEC_SIGN(pDecIn
))
5611 dwFlags
|= VAR_NEGATIVE
;
5613 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5614 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5615 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5617 FIXME("semi-stub\n");
5618 return E_INVALIDARG
;
5621 /************************************************************************
5622 * VarBstrFromI8 (OLEAUT32.370)
5624 * Convert a VT_I8 to a VT_BSTR.
5628 * lcid [I] LCID for the conversion
5629 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5630 * pbstrOut [O] Destination
5634 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5635 * E_OUTOFMEMORY, if memory allocation fails.
5637 HRESULT WINAPI
VarBstrFromI8(LONG64 llIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5639 ULONG64 ul64
= llIn
;
5644 dwFlags
|= VAR_NEGATIVE
;
5646 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5649 /************************************************************************
5650 * VarBstrFromUI8 (OLEAUT32.371)
5652 * Convert a VT_UI8 to a VT_BSTR.
5656 * lcid [I] LCID for the conversion
5657 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5658 * pbstrOut [O] Destination
5662 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5663 * E_OUTOFMEMORY, if memory allocation fails.
5665 HRESULT WINAPI
VarBstrFromUI8(ULONG64 ullIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5667 return VARIANT_BstrFromUInt(ullIn
, lcid
, dwFlags
, pbstrOut
);
5670 /**********************************************************************
5671 * VarBstrCat (OLEAUT32.313)
5673 * Concatenate two BSTR values.
5676 * pbstrLeft [I] Source
5677 * pbstrRight [I] Value to concatenate
5678 * pbstrOut [O] Destination
5682 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5683 * E_OUTOFMEMORY, if memory allocation fails.
5685 HRESULT WINAPI
VarBstrCat(BSTR pbstrLeft
, BSTR pbstrRight
, BSTR
*pbstrOut
)
5690 return E_INVALIDARG
;
5692 len
= pbstrLeft
? strlenW(pbstrLeft
) : 0;
5694 len
+= strlenW(pbstrRight
);
5696 *pbstrOut
= SysAllocStringLen(NULL
, len
);
5698 return E_OUTOFMEMORY
;
5700 (*pbstrOut
)[0] = '\0';
5703 strcpyW(*pbstrOut
, pbstrLeft
);
5706 strcatW(*pbstrOut
, pbstrRight
);
5711 /**********************************************************************
5712 * VarBstrCmp (OLEAUT32.314)
5714 * Compare two BSTR values.
5717 * pbstrLeft [I] Source
5718 * pbstrRight [I] Value to compare
5719 * lcid [I] LCID for the comparason
5720 * dwFlags [I] Flags to pass directly to CompareStringW().
5723 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5724 * than, equal to or greater than pbstrRight respectively.
5725 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5726 * in which case VARCMP_EQ is returned.
5728 HRESULT WINAPI
VarBstrCmp(BSTR pbstrLeft
, BSTR pbstrRight
, LCID lcid
, DWORD dwFlags
)
5732 if (!pbstrRight
|| !*pbstrRight
)
5736 else if (!pbstrRight
)
5743 return CompareStringW(lcid
, dwFlags
, pbstrLeft
, -1, pbstrRight
, -1) - 1;
5750 /******************************************************************************
5751 * VarDateFromUI1 (OLEAUT32.88)
5753 * Convert a VT_UI1 to a VT_DATE.
5757 * pdateOut [O] Destination
5762 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
5764 return _VarDateFromUI1(bIn
, pdateOut
);
5767 /******************************************************************************
5768 * VarDateFromI2 (OLEAUT32.89)
5770 * Convert a VT_I2 to a VT_DATE.
5774 * pdateOut [O] Destination
5779 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
5781 return _VarDateFromI2(sIn
, pdateOut
);
5784 /******************************************************************************
5785 * VarDateFromI4 (OLEAUT32.90)
5787 * Convert a VT_I4 to a VT_DATE.
5791 * pdateOut [O] Destination
5796 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
5798 return _VarDateFromI4(lIn
, pdateOut
);
5801 /******************************************************************************
5802 * VarDateFromR4 (OLEAUT32.91)
5804 * Convert a VT_R4 to a VT_DATE.
5808 * pdateOut [O] Destination
5813 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
5815 return _VarDateFromR4(fltIn
, pdateOut
);
5818 /******************************************************************************
5819 * VarDateFromR8 (OLEAUT32.92)
5821 * Convert a VT_R8 to a VT_DATE.
5825 * pdateOut [O] Destination
5830 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
5832 return _VarDateFromR8(dblIn
, pdateOut
);
5835 /**********************************************************************
5836 * VarDateFromDisp (OLEAUT32.95)
5838 * Convert a VT_DISPATCH to a VT_DATE.
5841 * pdispIn [I] Source
5842 * lcid [I] LCID for conversion
5843 * pdateOut [O] Destination
5847 * Failure: E_INVALIDARG, if the source value is invalid
5848 * DISP_E_OVERFLOW, if the value will not fit in the destination
5849 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5851 HRESULT WINAPI
VarDateFromDisp(IDispatch
* pdispIn
, LCID lcid
, DATE
* pdateOut
)
5853 return _VarDateFromDisp(pdispIn
, lcid
, pdateOut
);
5856 /******************************************************************************
5857 * VarDateFromBool (OLEAUT32.96)
5859 * Convert a VT_BOOL to a VT_DATE.
5863 * pdateOut [O] Destination
5868 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
5870 return _VarDateFromBool(boolIn
, pdateOut
);
5873 /**********************************************************************
5874 * VarDateFromCy (OLEAUT32.93)
5876 * Convert a VT_CY to a VT_DATE.
5880 * pdateOut [O] Destination
5885 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
)
5887 return _VarDateFromCy(cyIn
, pdateOut
);
5890 /* Date string parsing */
5891 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
5892 #define DP_DATESEP 0x02 /* Date separator */
5893 #define DP_MONTH 0x04 /* Month name */
5894 #define DP_AM 0x08 /* AM */
5895 #define DP_PM 0x10 /* PM */
5897 typedef struct tagDATEPARSE
5899 DWORD dwCount
; /* Number of fields found so far (maximum 6) */
5900 DWORD dwParseFlags
; /* Global parse flags (DP_ Flags above) */
5901 DWORD dwFlags
[6]; /* Flags for each field */
5902 DWORD dwValues
[6]; /* Value of each field */
5905 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
5907 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5909 /* Determine if a day is valid in a given month of a given year */
5910 static BOOL
VARIANT_IsValidMonthDay(DWORD day
, DWORD month
, DWORD year
)
5912 static const BYTE days
[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
5914 if (day
&& month
&& month
< 13)
5916 if (day
<= days
[month
] || (month
== 2 && day
== 29 && IsLeapYear(year
)))
5922 /* Possible orders for 3 numbers making up a date */
5923 #define ORDER_MDY 0x01
5924 #define ORDER_YMD 0x02
5925 #define ORDER_YDM 0x04
5926 #define ORDER_DMY 0x08
5927 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
5929 /* Determine a date for a particular locale, from 3 numbers */
5930 static inline HRESULT
VARIANT_MakeDate(DATEPARSE
*dp
, DWORD iDate
,
5931 DWORD offset
, SYSTEMTIME
*st
)
5933 DWORD dwAllOrders
, dwTry
, dwCount
= 0, v1
, v2
, v3
;
5937 v1
= 30; /* Default to (Variant) 0 date part */
5940 goto VARIANT_MakeDate_OK
;
5943 v1
= dp
->dwValues
[offset
+ 0];
5944 v2
= dp
->dwValues
[offset
+ 1];
5945 if (dp
->dwCount
== 2)
5948 GetSystemTime(¤t
);
5952 v3
= dp
->dwValues
[offset
+ 2];
5954 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1
, v2
, v3
, iDate
, offset
);
5956 /* If one number must be a month (Because a month name was given), then only
5957 * consider orders with the month in that position.
5958 * If we took the current year as 'v3', then only allow a year in that position.
5960 if (dp
->dwFlags
[offset
+ 0] & DP_MONTH
)
5962 dwAllOrders
= ORDER_MDY
;
5964 else if (dp
->dwFlags
[offset
+ 1] & DP_MONTH
)
5966 dwAllOrders
= ORDER_DMY
;
5967 if (dp
->dwCount
> 2)
5968 dwAllOrders
|= ORDER_YMD
;
5970 else if (dp
->dwCount
> 2 && dp
->dwFlags
[offset
+ 2] & DP_MONTH
)
5972 dwAllOrders
= ORDER_YDM
;
5976 dwAllOrders
= ORDER_MDY
|ORDER_DMY
;
5977 if (dp
->dwCount
> 2)
5978 dwAllOrders
|= (ORDER_YMD
|ORDER_YDM
);
5981 VARIANT_MakeDate_Start
:
5982 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders
);
5990 /* First: Try the order given by iDate */
5993 case 0: dwTry
= dwAllOrders
& ORDER_MDY
; break;
5994 case 1: dwTry
= dwAllOrders
& ORDER_DMY
; break;
5995 default: dwTry
= dwAllOrders
& ORDER_YMD
; break;
5998 else if (dwCount
== 1)
6000 /* Second: Try all the orders compatible with iDate */
6003 case 0: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
6004 case 1: dwTry
= dwAllOrders
& ~(ORDER_MDY
|ORDER_YMD
|ORDER_MYD
); break;
6005 default: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
6010 /* Finally: Try any remaining orders */
6011 dwTry
= dwAllOrders
;
6014 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount
, dwTry
);
6020 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6022 if (dwTry
& ORDER_MDY
)
6024 if (VARIANT_IsValidMonthDay(v2
,v1
,v3
))
6027 goto VARIANT_MakeDate_OK
;
6029 dwAllOrders
&= ~ORDER_MDY
;
6031 if (dwTry
& ORDER_YMD
)
6033 if (VARIANT_IsValidMonthDay(v3
,v2
,v1
))
6036 goto VARIANT_MakeDate_OK
;
6038 dwAllOrders
&= ~ORDER_YMD
;
6040 if (dwTry
& ORDER_YDM
)
6042 if (VARIANT_IsValidMonthDay(v2
,v3
,v1
))
6046 goto VARIANT_MakeDate_OK
;
6048 dwAllOrders
&= ~ORDER_YDM
;
6050 if (dwTry
& ORDER_DMY
)
6052 if (VARIANT_IsValidMonthDay(v1
,v2
,v3
))
6053 goto VARIANT_MakeDate_OK
;
6054 dwAllOrders
&= ~ORDER_DMY
;
6056 if (dwTry
& ORDER_MYD
)
6058 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6059 if (VARIANT_IsValidMonthDay(v3
,v1
,v2
))
6063 goto VARIANT_MakeDate_OK
;
6065 dwAllOrders
&= ~ORDER_MYD
;
6069 if (dp
->dwCount
== 2)
6071 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6072 v3
= 1; /* 1st of the month */
6073 dwAllOrders
= ORDER_YMD
|ORDER_MYD
;
6074 dp
->dwCount
= 0; /* Don't return to this code path again */
6076 goto VARIANT_MakeDate_Start
;
6079 /* No valid dates were able to be constructed */
6080 return DISP_E_TYPEMISMATCH
;
6082 VARIANT_MakeDate_OK
:
6084 /* Check that the time part is ok */
6085 if (st
->wHour
> 23 || st
->wMinute
> 59 || st
->wSecond
> 59)
6086 return DISP_E_TYPEMISMATCH
;
6088 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6089 if (st
->wHour
< 12 && (dp
->dwParseFlags
& DP_PM
))
6091 else if (st
->wHour
== 12 && (dp
->dwParseFlags
& DP_AM
))
6093 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6097 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6098 * be retrieved from:
6099 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6100 * But Wine doesn't have/use that key as at the time of writing.
6102 st
->wYear
= v3
< 30 ? 2000 + v3
: v3
< 100 ? 1900 + v3
: v3
;
6103 TRACE("Returning date %ld/%ld/%d\n", v1
, v2
, st
->wYear
);
6107 /******************************************************************************
6108 * VarDateFromStr [OLEAUT32.94]
6110 * Convert a VT_BSTR to at VT_DATE.
6113 * strIn [I] String to convert
6114 * lcid [I] Locale identifier for the conversion
6115 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6116 * pdateOut [O] Destination for the converted value
6119 * Success: S_OK. pdateOut contains the converted value.
6120 * FAILURE: An HRESULT error code indicating the prolem.
6123 * Any date format that can be created using the date formats from lcid
6124 * (Either from kernel Nls functions, variant conversion or formatting) is a
6125 * valid input to this function. In addition, a few more esoteric formats are
6126 * also supported for compatibility with the native version. The date is
6127 * interpreted according to the date settings in the control panel, unless
6128 * the date is invalid in that format, in which the most compatible format
6129 * that produces a valid date will be used.
6131 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
6133 static const USHORT ParseDateTokens
[] =
6135 LOCALE_SMONTHNAME1
, LOCALE_SMONTHNAME2
, LOCALE_SMONTHNAME3
, LOCALE_SMONTHNAME4
,
6136 LOCALE_SMONTHNAME5
, LOCALE_SMONTHNAME6
, LOCALE_SMONTHNAME7
, LOCALE_SMONTHNAME8
,
6137 LOCALE_SMONTHNAME9
, LOCALE_SMONTHNAME10
, LOCALE_SMONTHNAME11
, LOCALE_SMONTHNAME12
,
6138 LOCALE_SMONTHNAME13
,
6139 LOCALE_SABBREVMONTHNAME1
, LOCALE_SABBREVMONTHNAME2
, LOCALE_SABBREVMONTHNAME3
,
6140 LOCALE_SABBREVMONTHNAME4
, LOCALE_SABBREVMONTHNAME5
, LOCALE_SABBREVMONTHNAME6
,
6141 LOCALE_SABBREVMONTHNAME7
, LOCALE_SABBREVMONTHNAME8
, LOCALE_SABBREVMONTHNAME9
,
6142 LOCALE_SABBREVMONTHNAME10
, LOCALE_SABBREVMONTHNAME11
, LOCALE_SABBREVMONTHNAME12
,
6143 LOCALE_SABBREVMONTHNAME13
,
6144 LOCALE_SDAYNAME1
, LOCALE_SDAYNAME2
, LOCALE_SDAYNAME3
, LOCALE_SDAYNAME4
,
6145 LOCALE_SDAYNAME5
, LOCALE_SDAYNAME6
, LOCALE_SDAYNAME7
,
6146 LOCALE_SABBREVDAYNAME1
, LOCALE_SABBREVDAYNAME2
, LOCALE_SABBREVDAYNAME3
,
6147 LOCALE_SABBREVDAYNAME4
, LOCALE_SABBREVDAYNAME5
, LOCALE_SABBREVDAYNAME6
,
6148 LOCALE_SABBREVDAYNAME7
,
6149 LOCALE_S1159
, LOCALE_S2359
6151 static const BYTE ParseDateMonths
[] =
6153 1,2,3,4,5,6,7,8,9,10,11,12,13,
6154 1,2,3,4,5,6,7,8,9,10,11,12,13
6157 BSTR tokens
[sizeof(ParseDateTokens
)/sizeof(ParseDateTokens
[0])];
6159 DWORD dwDateSeps
= 0, iDate
= 0;
6160 HRESULT hRet
= S_OK
;
6162 if ((dwFlags
& (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
)) ==
6163 (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
))
6164 return E_INVALIDARG
;
6167 return DISP_E_TYPEMISMATCH
;
6171 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn
), lcid
, dwFlags
, pdateOut
);
6173 memset(&dp
, 0, sizeof(dp
));
6175 GetLocaleInfoW(lcid
, LOCALE_IDATE
|LOCALE_RETURN_NUMBER
|(dwFlags
& LOCALE_NOUSEROVERRIDE
),
6176 (LPWSTR
)&iDate
, sizeof(iDate
)/sizeof(WCHAR
));
6177 TRACE("iDate is %ld\n", iDate
);
6179 /* Get the month/day/am/pm tokens for this locale */
6180 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6183 LCTYPE lctype
= ParseDateTokens
[i
] | (dwFlags
& LOCALE_NOUSEROVERRIDE
);
6185 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6186 * GetAltMonthNames(). We should really cache these strings too.
6189 GetLocaleInfoW(lcid
, lctype
, buff
, sizeof(buff
)/sizeof(WCHAR
));
6190 tokens
[i
] = SysAllocString(buff
);
6191 TRACE("token %d is %s\n", i
, debugstr_w(tokens
[i
]));
6194 /* Parse the string into our structure */
6200 if (isdigitW(*strIn
))
6202 dp
.dwValues
[dp
.dwCount
] = strtoulW(strIn
, &strIn
, 10);
6206 else if (isalpha(*strIn
))
6208 BOOL bFound
= FALSE
;
6210 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6212 DWORD dwLen
= strlenW(tokens
[i
]);
6213 if (dwLen
&& !strncmpiW(strIn
, tokens
[i
], dwLen
))
6217 dp
.dwValues
[dp
.dwCount
] = ParseDateMonths
[i
];
6218 dp
.dwFlags
[dp
.dwCount
] |= (DP_MONTH
|DP_DATESEP
);
6223 if (!dp
.dwCount
|| dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6224 hRet
= DISP_E_TYPEMISMATCH
;
6227 dp
.dwFlags
[dp
.dwCount
- 1] |= (i
== 40 ? DP_AM
: DP_PM
);
6228 dp
.dwParseFlags
|= (i
== 40 ? DP_AM
: DP_PM
);
6231 strIn
+= (dwLen
- 1);
6239 if ((*strIn
== 'a' || *strIn
== 'A' || *strIn
== 'p' || *strIn
== 'P') &&
6240 (dp
.dwCount
&& !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6242 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6243 if (*strIn
== 'a' || *strIn
== 'A')
6245 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_AM
;
6246 dp
.dwParseFlags
|= DP_AM
;
6250 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_PM
;
6251 dp
.dwParseFlags
|= DP_PM
;
6257 TRACE("No matching token for %s\n", debugstr_w(strIn
));
6258 hRet
= DISP_E_TYPEMISMATCH
;
6263 else if (*strIn
== ':' || *strIn
== '.')
6265 if (!dp
.dwCount
|| !strIn
[1])
6266 hRet
= DISP_E_TYPEMISMATCH
;
6268 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_TIMESEP
;
6270 else if (*strIn
== '-' || *strIn
== '/')
6273 if (dwDateSeps
> 2 || !dp
.dwCount
|| !strIn
[1])
6274 hRet
= DISP_E_TYPEMISMATCH
;
6276 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_DATESEP
;
6278 else if (*strIn
== ',' || isspaceW(*strIn
))
6280 if (*strIn
== ',' && !strIn
[1])
6281 hRet
= DISP_E_TYPEMISMATCH
;
6285 hRet
= DISP_E_TYPEMISMATCH
;
6290 if (!dp
.dwCount
|| dp
.dwCount
> 6 ||
6291 (dp
.dwCount
== 1 && !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6292 hRet
= DISP_E_TYPEMISMATCH
;
6294 if (SUCCEEDED(hRet
))
6297 DWORD dwOffset
= 0; /* Start of date fields in dp.dwValues */
6299 st
.wDayOfWeek
= st
.wHour
= st
.wMinute
= st
.wSecond
= st
.wMilliseconds
= 0;
6301 /* Figure out which numbers correspond to which fields.
6303 * This switch statement works based on the fact that native interprets any
6304 * fields that are not joined with a time separator ('.' or ':') as date
6305 * fields. Thus we construct a value from 0-32 where each set bit indicates
6306 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6307 * For valid permutations, we set dwOffset to point to the first date field
6308 * and shorten dp.dwCount by the number of time fields found. The real
6309 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6310 * each date number must represent in the context of iDate.
6312 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6314 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6316 case 0x1: /* TT TTDD TTDDD */
6317 if (dp
.dwCount
> 3 &&
6318 ((dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) ||
6319 (dp
.dwFlags
[4] & (DP_AM
|DP_PM
))))
6320 hRet
= DISP_E_TYPEMISMATCH
;
6321 else if (dp
.dwCount
!= 2 && dp
.dwCount
!= 4 && dp
.dwCount
!= 5)
6322 hRet
= DISP_E_TYPEMISMATCH
;
6323 st
.wHour
= dp
.dwValues
[0];
6324 st
.wMinute
= dp
.dwValues
[1];
6329 case 0x3: /* TTT TTTDD TTTDDD */
6330 if (dp
.dwCount
> 4 &&
6331 ((dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[4] & (DP_AM
|DP_PM
)) ||
6332 (dp
.dwFlags
[5] & (DP_AM
|DP_PM
))))
6333 hRet
= DISP_E_TYPEMISMATCH
;
6334 else if (dp
.dwCount
!= 3 && dp
.dwCount
!= 5 && dp
.dwCount
!= 6)
6335 hRet
= DISP_E_TYPEMISMATCH
;
6336 st
.wHour
= dp
.dwValues
[0];
6337 st
.wMinute
= dp
.dwValues
[1];
6338 st
.wSecond
= dp
.dwValues
[2];
6343 case 0x4: /* DDTT */
6344 if (dp
.dwCount
!= 4 ||
6345 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6346 hRet
= DISP_E_TYPEMISMATCH
;
6348 st
.wHour
= dp
.dwValues
[2];
6349 st
.wMinute
= dp
.dwValues
[3];
6353 case 0x0: /* T DD DDD TDDD TDDD */
6354 if (dp
.dwCount
== 1 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6356 st
.wHour
= dp
.dwValues
[0]; /* T */
6360 else if (dp
.dwCount
> 4 || (dp
.dwCount
< 3 && dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6362 hRet
= DISP_E_TYPEMISMATCH
;
6364 else if (dp
.dwCount
== 3)
6366 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDD */
6369 st
.wHour
= dp
.dwValues
[0];
6373 if (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) /* DDT */
6376 st
.wHour
= dp
.dwValues
[2];
6379 else if (dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6380 hRet
= DISP_E_TYPEMISMATCH
;
6382 else if (dp
.dwCount
== 4)
6385 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDDD */
6387 st
.wHour
= dp
.dwValues
[0];
6390 else if (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) /* DDDT */
6392 st
.wHour
= dp
.dwValues
[3];
6395 hRet
= DISP_E_TYPEMISMATCH
;
6398 /* .. fall through .. */
6400 case 0x8: /* DDDTT */
6401 if ((dp
.dwCount
== 2 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
))) ||
6402 (dp
.dwCount
== 5 && ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) ||
6403 (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))) ||
6404 dp
.dwCount
== 4 || dp
.dwCount
== 6)
6405 hRet
= DISP_E_TYPEMISMATCH
;
6406 st
.wHour
= dp
.dwValues
[3];
6407 st
.wMinute
= dp
.dwValues
[4];
6408 if (dp
.dwCount
== 5)
6412 case 0xC: /* DDTTT */
6413 if (dp
.dwCount
!= 5 ||
6414 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6415 hRet
= DISP_E_TYPEMISMATCH
;
6416 st
.wHour
= dp
.dwValues
[2];
6417 st
.wMinute
= dp
.dwValues
[3];
6418 st
.wSecond
= dp
.dwValues
[4];
6422 case 0x18: /* DDDTTT */
6423 if ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) ||
6424 (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))
6425 hRet
= DISP_E_TYPEMISMATCH
;
6426 st
.wHour
= dp
.dwValues
[3];
6427 st
.wMinute
= dp
.dwValues
[4];
6428 st
.wSecond
= dp
.dwValues
[5];
6433 hRet
= DISP_E_TYPEMISMATCH
;
6437 if (SUCCEEDED(hRet
))
6439 hRet
= VARIANT_MakeDate(&dp
, iDate
, dwOffset
, &st
);
6441 if (dwFlags
& VAR_TIMEVALUEONLY
)
6447 else if (dwFlags
& VAR_DATEVALUEONLY
)
6448 st
.wHour
= st
.wMinute
= st
.wSecond
= 0;
6450 /* Finally, convert the value to a VT_DATE */
6451 if (SUCCEEDED(hRet
))
6452 hRet
= SystemTimeToVariantTime(&st
, pdateOut
) ? S_OK
: DISP_E_TYPEMISMATCH
;
6456 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6457 SysFreeString(tokens
[i
]);
6461 /******************************************************************************
6462 * VarDateFromI1 (OLEAUT32.221)
6464 * Convert a VT_I1 to a VT_DATE.
6468 * pdateOut [O] Destination
6473 HRESULT WINAPI
VarDateFromI1(signed char cIn
, DATE
* pdateOut
)
6475 return _VarDateFromI1(cIn
, pdateOut
);
6478 /******************************************************************************
6479 * VarDateFromUI2 (OLEAUT32.222)
6481 * Convert a VT_UI2 to a VT_DATE.
6485 * pdateOut [O] Destination
6490 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
6492 return _VarDateFromUI2(uiIn
, pdateOut
);
6495 /******************************************************************************
6496 * VarDateFromUI4 (OLEAUT32.223)
6498 * Convert a VT_UI4 to a VT_DATE.
6502 * pdateOut [O] Destination
6507 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
6509 return _VarDateFromUI4(ulIn
, pdateOut
);
6512 /**********************************************************************
6513 * VarDateFromDec (OLEAUT32.224)
6515 * Convert a VT_DECIMAL to a VT_DATE.
6519 * pdateOut [O] Destination
6524 HRESULT WINAPI
VarDateFromDec(DECIMAL
*pdecIn
, DATE
* pdateOut
)
6526 return _VarDateFromDec(pdecIn
, pdateOut
);
6529 /******************************************************************************
6530 * VarDateFromI8 (OLEAUT32.364)
6532 * Convert a VT_I8 to a VT_DATE.
6536 * pdateOut [O] Destination
6540 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6542 HRESULT WINAPI
VarDateFromI8(LONG64 llIn
, DATE
* pdateOut
)
6544 return _VarDateFromI8(llIn
, pdateOut
);
6547 /******************************************************************************
6548 * VarDateFromUI8 (OLEAUT32.365)
6550 * Convert a VT_UI8 to a VT_DATE.
6554 * pdateOut [O] Destination
6558 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6560 HRESULT WINAPI
VarDateFromUI8(ULONG64 ullIn
, DATE
* pdateOut
)
6562 return _VarDateFromUI8(ullIn
, pdateOut
);