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 #ifdef __REACTOS__ /*FIXME*/
34 /* problems with decVal member of VARIANT union in MinGW headers */
36 #define V_DECIMAL(X) (X->__VARIANT_NAME_1.decVal)
40 extern HMODULE OLEAUT32_hModule
;
42 static const WCHAR szFloatFormatW
[] = { '%','.','7','G','\0' };
43 static const WCHAR szDoubleFormatW
[] = { '%','.','1','5','G','\0' };
45 /* Copy data from one variant to another. */
46 static inline void VARIANT_CopyData(const VARIANT
*srcVar
, VARTYPE vt
, void *pOut
)
51 case VT_UI1
: memcpy(pOut
, &V_UI1(srcVar
), sizeof(BYTE
)); break;
54 #ifndef __REACTOS__ /*FIXME*/
55 case VT_UI2
: memcpy(pOut
, &V_UI2(srcVar
), sizeof(SHORT
));
62 #ifndef __REACTOS__ /*FIXME*/
63 case VT_UI4
: memcpy(pOut
, &V_UI4(srcVar
), sizeof (LONG
));
70 #ifndef __REACTOS__ /*FIXME*/
71 case VT_UI8
: memcpy(pOut
, &V_UI8(srcVar
), sizeof (LONG64
));
74 case VT_INT_PTR
: memcpy(pOut
, &V_INT_PTR(srcVar
), sizeof (INT_PTR
)); break;
75 case VT_DECIMAL
: memcpy(pOut
, &V_DECIMAL(srcVar
), sizeof (DECIMAL
)); break;
77 FIXME("VT_ type %d unhandled, please report!\n", vt
);
82 /* Coerce VT_BSTR to a numeric type */
83 HRESULT
VARIANT_NumberFromBstr(OLECHAR
* pStrIn
, LCID lcid
, ULONG ulFlags
,
84 void* pOut
, VARTYPE vt
)
91 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
92 np
.cDig
= sizeof(rgb
) / sizeof(BYTE
);
93 np
.dwInFlags
= NUMPRS_STD
;
95 hRet
= VarParseNumFromStr(pStrIn
, lcid
, ulFlags
, &np
, rgb
);
99 /* 1 << vt gives us the VTBIT constant for the destination number type */
100 hRet
= VarNumFromParseNum(&np
, rgb
, 1 << vt
, &dstVar
);
102 VARIANT_CopyData(&dstVar
, vt
, pOut
);
107 /* Coerce VT_DISPATCH to another type */
108 HRESULT
VARIANT_FromDisp(IDispatch
* pdispIn
, LCID lcid
, void* pOut
, VARTYPE vt
)
110 static const DISPPARAMS emptyParams
= { NULL
, NULL
, 0, 0 };
111 VARIANTARG srcVar
, dstVar
;
115 return DISP_E_BADVARTYPE
;
117 /* Get the default 'value' property from the IDispatch */
118 hRet
= IDispatch_Invoke(pdispIn
, DISPID_VALUE
, &IID_NULL
, lcid
, DISPATCH_PROPERTYGET
,
119 (DISPPARAMS
*)&emptyParams
, &srcVar
, NULL
, NULL
);
123 /* Convert the property to the requested type */
124 V_VT(&dstVar
) = VT_EMPTY
;
125 hRet
= VariantChangeTypeEx(&dstVar
, &srcVar
, lcid
, 0, vt
);
126 VariantClear(&srcVar
);
130 VARIANT_CopyData(&dstVar
, vt
, pOut
);
131 VariantClear(&srcVar
);
135 hRet
= DISP_E_TYPEMISMATCH
;
142 /************************************************************************
143 * VarI1FromUI1 (OLEAUT32.244)
145 * Convert a VT_UI1 to a VT_I1.
149 * pcOut [O] Destination
153 * Failure: E_INVALIDARG, if the source value is invalid
154 * DISP_E_OVERFLOW, if the value will not fit in the destination
156 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, signed char* pcOut
)
158 return _VarI1FromUI1(bIn
, pcOut
);
161 /************************************************************************
162 * VarI1FromI2 (OLEAUT32.245)
164 * Convert a VT_I2 to a VT_I1.
168 * pcOut [O] Destination
172 * Failure: E_INVALIDARG, if the source value is invalid
173 * DISP_E_OVERFLOW, if the value will not fit in the destination
175 HRESULT WINAPI
VarI1FromI2(SHORT sIn
, signed char* pcOut
)
177 return _VarI1FromI2(sIn
, pcOut
);
180 /************************************************************************
181 * VarI1FromI4 (OLEAUT32.246)
183 * Convert a VT_I4 to a VT_I1.
187 * pcOut [O] Destination
191 * Failure: E_INVALIDARG, if the source value is invalid
192 * DISP_E_OVERFLOW, if the value will not fit in the destination
194 HRESULT WINAPI
VarI1FromI4(LONG iIn
, signed char* pcOut
)
196 return _VarI1FromI4(iIn
, pcOut
);
199 /************************************************************************
200 * VarI1FromR4 (OLEAUT32.247)
202 * Convert a VT_R4 to a VT_I1.
206 * pcOut [O] Destination
210 * Failure: E_INVALIDARG, if the source value is invalid
211 * DISP_E_OVERFLOW, if the value will not fit in the destination
213 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, signed char* pcOut
)
215 return _VarI1FromR4(fltIn
, pcOut
);
218 /************************************************************************
219 * VarI1FromR8 (OLEAUT32.248)
221 * Convert a VT_R8 to a VT_I1.
225 * pcOut [O] Destination
229 * Failure: E_INVALIDARG, if the source value is invalid
230 * DISP_E_OVERFLOW, if the value will not fit in the destination
233 * See VarI8FromR8() for details concerning rounding.
235 HRESULT WINAPI
VarI1FromR8(double dblIn
, signed char* pcOut
)
237 if (dblIn
< (double)I1_MIN
|| dblIn
> (double)I1_MAX
)
238 return DISP_E_OVERFLOW
;
239 OLEAUT32_DutchRound(CHAR
, dblIn
, *pcOut
);
243 /************************************************************************
244 * VarI1FromDate (OLEAUT32.249)
246 * Convert a VT_DATE to a VT_I1.
250 * pcOut [O] Destination
254 * Failure: E_INVALIDARG, if the source value is invalid
255 * DISP_E_OVERFLOW, if the value will not fit in the destination
257 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, signed char* pcOut
)
259 return _VarI1FromDate(dateIn
, pcOut
);
262 /************************************************************************
263 * VarI1FromCy (OLEAUT32.250)
265 * Convert a VT_CY to a VT_I1.
269 * pcOut [O] Destination
273 * Failure: E_INVALIDARG, if the source value is invalid
274 * DISP_E_OVERFLOW, if the value will not fit in the destination
276 HRESULT WINAPI
VarI1FromCy(CY cyIn
, signed char* pcOut
)
280 _VarI4FromCy(cyIn
, &i
);
281 return _VarI1FromI4(i
, pcOut
);
284 /************************************************************************
285 * VarI1FromStr (OLEAUT32.251)
287 * Convert a VT_BSTR to a VT_I1.
291 * lcid [I] LCID for the conversion
292 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
293 * pcOut [O] Destination
297 * Failure: E_INVALIDARG, if the source value is invalid
298 * DISP_E_OVERFLOW, if the value will not fit in the destination
299 * DISP_E_TYPEMISMATCH, if the type cannot be converted
301 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, signed char* pcOut
)
303 return _VarI1FromStr(strIn
, lcid
, dwFlags
, pcOut
);
306 /************************************************************************
307 * VarI1FromDisp (OLEAUT32.252)
309 * Convert a VT_DISPATCH to a VT_I1.
313 * lcid [I] LCID for conversion
314 * pcOut [O] Destination
318 * Failure: E_INVALIDARG, if the source value is invalid
319 * DISP_E_OVERFLOW, if the value will not fit in the destination
320 * DISP_E_TYPEMISMATCH, if the type cannot be converted
322 HRESULT WINAPI
VarI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, signed char* pcOut
)
324 return _VarI1FromDisp(pdispIn
, lcid
, pcOut
);
327 /************************************************************************
328 * VarI1FromBool (OLEAUT32.253)
330 * Convert a VT_BOOL to a VT_I1.
334 * pcOut [O] Destination
339 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, signed char* pcOut
)
341 return _VarI1FromBool(boolIn
, pcOut
);
344 /************************************************************************
345 * VarI1FromUI2 (OLEAUT32.254)
347 * Convert a VT_UI2 to a VT_I1.
351 * pcOut [O] Destination
355 * Failure: E_INVALIDARG, if the source value is invalid
356 * DISP_E_OVERFLOW, if the value will not fit in the destination
358 HRESULT WINAPI
VarI1FromUI2(USHORT usIn
, signed char* pcOut
)
360 return _VarI1FromUI2(usIn
, pcOut
);
363 /************************************************************************
364 * VarI1FromUI4 (OLEAUT32.255)
366 * Convert a VT_UI4 to a VT_I1.
370 * pcOut [O] Destination
374 * Failure: E_INVALIDARG, if the source value is invalid
375 * DISP_E_OVERFLOW, if the value will not fit in the destination
376 * DISP_E_TYPEMISMATCH, if the type cannot be converted
378 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, signed char* pcOut
)
380 return _VarI1FromUI4(ulIn
, pcOut
);
383 /************************************************************************
384 * VarI1FromDec (OLEAUT32.256)
386 * Convert a VT_DECIMAL to a VT_I1.
390 * pcOut [O] Destination
394 * Failure: E_INVALIDARG, if the source value is invalid
395 * DISP_E_OVERFLOW, if the value will not fit in the destination
397 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
398 HRESULT WINAPI
VarI1FromDec(DECIMAL
*pdecIn
, signed char* pcOut
)
403 hRet
= _VarI8FromDec(pdecIn
, &i64
);
406 hRet
= _VarI1FromI8(i64
, pcOut
);
411 /************************************************************************
412 * VarI1FromI8 (OLEAUT32.376)
414 * Convert a VT_I8 to a VT_I1.
418 * pcOut [O] Destination
422 * Failure: E_INVALIDARG, if the source value is invalid
423 * DISP_E_OVERFLOW, if the value will not fit in the destination
425 HRESULT WINAPI
VarI1FromI8(LONG64 llIn
, signed char* pcOut
)
427 return _VarI1FromI8(llIn
, pcOut
);
430 /************************************************************************
431 * VarI1FromUI8 (OLEAUT32.377)
433 * Convert a VT_UI8 to a VT_I1.
437 * pcOut [O] Destination
441 * Failure: E_INVALIDARG, if the source value is invalid
442 * DISP_E_OVERFLOW, if the value will not fit in the destination
444 HRESULT WINAPI
VarI1FromUI8(ULONG64 ullIn
, signed char* pcOut
)
446 return _VarI1FromUI8(ullIn
, pcOut
);
452 /************************************************************************
453 * VarUI1FromI2 (OLEAUT32.130)
455 * Convert a VT_I2 to a VT_UI1.
459 * pbOut [O] Destination
463 * Failure: E_INVALIDARG, if the source value is invalid
464 * DISP_E_OVERFLOW, if the value will not fit in the destination
466 HRESULT WINAPI
VarUI1FromI2(SHORT sIn
, BYTE
* pbOut
)
468 return _VarUI1FromI2(sIn
, pbOut
);
471 /************************************************************************
472 * VarUI1FromI4 (OLEAUT32.131)
474 * Convert a VT_I4 to a VT_UI1.
478 * pbOut [O] Destination
482 * Failure: E_INVALIDARG, if the source value is invalid
483 * DISP_E_OVERFLOW, if the value will not fit in the destination
485 HRESULT WINAPI
VarUI1FromI4(LONG iIn
, BYTE
* pbOut
)
487 return _VarUI1FromI4(iIn
, pbOut
);
490 /************************************************************************
491 * VarUI1FromR4 (OLEAUT32.132)
493 * Convert a VT_R4 to a VT_UI1.
497 * pbOut [O] Destination
501 * Failure: E_INVALIDARG, if the source value is invalid
502 * DISP_E_OVERFLOW, if the value will not fit in the destination
503 * DISP_E_TYPEMISMATCH, if the type cannot be converted
505 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
507 return _VarUI1FromR4(fltIn
, pbOut
);
510 /************************************************************************
511 * VarUI1FromR8 (OLEAUT32.133)
513 * Convert a VT_R8 to a VT_UI1.
517 * pbOut [O] Destination
521 * Failure: E_INVALIDARG, if the source value is invalid
522 * DISP_E_OVERFLOW, if the value will not fit in the destination
525 * See VarI8FromR8() for details concerning rounding.
527 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
529 if (dblIn
< -0.5 || dblIn
> (double)UI1_MAX
)
530 return DISP_E_OVERFLOW
;
531 OLEAUT32_DutchRound(BYTE
, dblIn
, *pbOut
);
535 /************************************************************************
536 * VarUI1FromCy (OLEAUT32.134)
538 * Convert a VT_CY to a VT_UI1.
542 * pbOut [O] Destination
546 * Failure: E_INVALIDARG, if the source value is invalid
547 * DISP_E_OVERFLOW, if the value will not fit in the destination
550 * Negative values >= -5000 will be converted to 0.
552 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
)
554 ULONG i
= UI1_MAX
+ 1;
556 _VarUI4FromCy(cyIn
, &i
);
557 return _VarUI1FromUI4(i
, pbOut
);
560 /************************************************************************
561 * VarUI1FromDate (OLEAUT32.135)
563 * Convert a VT_DATE to a VT_UI1.
567 * pbOut [O] Destination
571 * Failure: E_INVALIDARG, if the source value is invalid
572 * DISP_E_OVERFLOW, if the value will not fit in the destination
574 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
576 return _VarUI1FromDate(dateIn
, pbOut
);
579 /************************************************************************
580 * VarUI1FromStr (OLEAUT32.136)
582 * Convert a VT_BSTR to a VT_UI1.
586 * lcid [I] LCID for the conversion
587 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
588 * pbOut [O] Destination
592 * Failure: E_INVALIDARG, if the source value is invalid
593 * DISP_E_OVERFLOW, if the value will not fit in the destination
594 * DISP_E_TYPEMISMATCH, if the type cannot be converted
596 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
598 return _VarUI1FromStr(strIn
, lcid
, dwFlags
, pbOut
);
601 /************************************************************************
602 * VarUI1FromDisp (OLEAUT32.137)
604 * Convert a VT_DISPATCH to a VT_UI1.
608 * lcid [I] LCID for conversion
609 * pbOut [O] Destination
613 * Failure: E_INVALIDARG, if the source value is invalid
614 * DISP_E_OVERFLOW, if the value will not fit in the destination
615 * DISP_E_TYPEMISMATCH, if the type cannot be converted
617 HRESULT WINAPI
VarUI1FromDisp(IDispatch
* pdispIn
, LCID lcid
, BYTE
* pbOut
)
619 return _VarUI1FromDisp(pdispIn
, lcid
, pbOut
);
622 /************************************************************************
623 * VarUI1FromBool (OLEAUT32.138)
625 * Convert a VT_BOOL to a VT_UI1.
629 * pbOut [O] Destination
634 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
636 return _VarUI1FromBool(boolIn
, pbOut
);
639 /************************************************************************
640 * VarUI1FromI1 (OLEAUT32.237)
642 * Convert a VT_I1 to a VT_UI1.
646 * pbOut [O] Destination
650 * Failure: E_INVALIDARG, if the source value is invalid
651 * DISP_E_OVERFLOW, if the value will not fit in the destination
653 HRESULT WINAPI
VarUI1FromI1(signed char cIn
, BYTE
* pbOut
)
655 return _VarUI1FromI1(cIn
, pbOut
);
658 /************************************************************************
659 * VarUI1FromUI2 (OLEAUT32.238)
661 * Convert a VT_UI2 to a VT_UI1.
665 * pbOut [O] Destination
669 * Failure: E_INVALIDARG, if the source value is invalid
670 * DISP_E_OVERFLOW, if the value will not fit in the destination
672 HRESULT WINAPI
VarUI1FromUI2(USHORT usIn
, BYTE
* pbOut
)
674 return _VarUI1FromUI2(usIn
, pbOut
);
677 /************************************************************************
678 * VarUI1FromUI4 (OLEAUT32.239)
680 * Convert a VT_UI4 to a VT_UI1.
684 * pbOut [O] Destination
688 * Failure: E_INVALIDARG, if the source value is invalid
689 * DISP_E_OVERFLOW, if the value will not fit in the destination
691 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
693 return _VarUI1FromUI4(ulIn
, pbOut
);
696 /************************************************************************
697 * VarUI1FromDec (OLEAUT32.240)
699 * Convert a VT_DECIMAL to a VT_UI1.
703 * pbOut [O] Destination
707 * Failure: E_INVALIDARG, if the source value is invalid
708 * DISP_E_OVERFLOW, if the value will not fit in the destination
710 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
711 HRESULT WINAPI
VarUI1FromDec(DECIMAL
*pdecIn
, BYTE
* pbOut
)
716 hRet
= _VarI8FromDec(pdecIn
, &i64
);
719 hRet
= _VarUI1FromI8(i64
, pbOut
);
724 /************************************************************************
725 * VarUI1FromI8 (OLEAUT32.372)
727 * Convert a VT_I8 to a VT_UI1.
731 * pbOut [O] Destination
735 * Failure: E_INVALIDARG, if the source value is invalid
736 * DISP_E_OVERFLOW, if the value will not fit in the destination
738 HRESULT WINAPI
VarUI1FromI8(LONG64 llIn
, BYTE
* pbOut
)
740 return _VarUI1FromI8(llIn
, pbOut
);
743 /************************************************************************
744 * VarUI1FromUI8 (OLEAUT32.373)
746 * Convert a VT_UI8 to a VT_UI1.
750 * pbOut [O] Destination
754 * Failure: E_INVALIDARG, if the source value is invalid
755 * DISP_E_OVERFLOW, if the value will not fit in the destination
757 HRESULT WINAPI
VarUI1FromUI8(ULONG64 ullIn
, BYTE
* pbOut
)
759 return _VarUI1FromUI8(ullIn
, pbOut
);
766 /************************************************************************
767 * VarI2FromUI1 (OLEAUT32.48)
769 * Convert a VT_UI2 to a VT_I2.
773 * psOut [O] Destination
778 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, SHORT
* psOut
)
780 return _VarI2FromUI1(bIn
, psOut
);
783 /************************************************************************
784 * VarI2FromI4 (OLEAUT32.49)
786 * Convert a VT_I4 to a VT_I2.
790 * psOut [O] Destination
794 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
796 HRESULT WINAPI
VarI2FromI4(LONG iIn
, SHORT
* psOut
)
798 return _VarI2FromI4(iIn
, psOut
);
801 /************************************************************************
802 * VarI2FromR4 (OLEAUT32.50)
804 * Convert a VT_R4 to a VT_I2.
808 * psOut [O] Destination
812 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
814 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, SHORT
* psOut
)
816 return _VarI2FromR4(fltIn
, psOut
);
819 /************************************************************************
820 * VarI2FromR8 (OLEAUT32.51)
822 * Convert a VT_R8 to a VT_I2.
826 * psOut [O] Destination
830 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
833 * See VarI8FromR8() for details concerning rounding.
835 HRESULT WINAPI
VarI2FromR8(double dblIn
, SHORT
* psOut
)
837 if (dblIn
< (double)I2_MIN
|| dblIn
> (double)I2_MAX
)
838 return DISP_E_OVERFLOW
;
839 OLEAUT32_DutchRound(SHORT
, dblIn
, *psOut
);
843 /************************************************************************
844 * VarI2FromCy (OLEAUT32.52)
846 * Convert a VT_CY to a VT_I2.
850 * psOut [O] Destination
854 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
856 HRESULT WINAPI
VarI2FromCy(CY cyIn
, SHORT
* psOut
)
860 _VarI4FromCy(cyIn
, &i
);
861 return _VarI2FromI4(i
, psOut
);
864 /************************************************************************
865 * VarI2FromDate (OLEAUT32.53)
867 * Convert a VT_DATE to a VT_I2.
871 * psOut [O] Destination
875 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
877 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, SHORT
* psOut
)
879 return _VarI2FromDate(dateIn
, psOut
);
882 /************************************************************************
883 * VarI2FromStr (OLEAUT32.54)
885 * Convert a VT_BSTR to a VT_I2.
889 * lcid [I] LCID for the conversion
890 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
891 * psOut [O] Destination
895 * Failure: E_INVALIDARG, if any parameter is invalid
896 * DISP_E_OVERFLOW, if the value will not fit in the destination
897 * DISP_E_TYPEMISMATCH, if the type cannot be converted
899 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, SHORT
* psOut
)
901 return _VarI2FromStr(strIn
, lcid
, dwFlags
, psOut
);
904 /************************************************************************
905 * VarI2FromDisp (OLEAUT32.55)
907 * Convert a VT_DISPATCH to a VT_I2.
911 * lcid [I] LCID for conversion
912 * psOut [O] Destination
916 * Failure: E_INVALIDARG, if pdispIn is invalid,
917 * DISP_E_OVERFLOW, if the value will not fit in the destination,
918 * DISP_E_TYPEMISMATCH, if the type cannot be converted
920 HRESULT WINAPI
VarI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, SHORT
* psOut
)
922 return _VarI2FromDisp(pdispIn
, lcid
, psOut
);
925 /************************************************************************
926 * VarI2FromBool (OLEAUT32.56)
928 * Convert a VT_BOOL to a VT_I2.
932 * psOut [O] Destination
937 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, SHORT
* psOut
)
939 return _VarI2FromBool(boolIn
, psOut
);
942 /************************************************************************
943 * VarI2FromI1 (OLEAUT32.205)
945 * Convert a VT_I1 to a VT_I2.
949 * psOut [O] Destination
954 HRESULT WINAPI
VarI2FromI1(signed char cIn
, SHORT
* psOut
)
956 return _VarI2FromI1(cIn
, psOut
);
959 /************************************************************************
960 * VarI2FromUI2 (OLEAUT32.206)
962 * Convert a VT_UI2 to a VT_I2.
966 * psOut [O] Destination
970 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
972 HRESULT WINAPI
VarI2FromUI2(USHORT usIn
, SHORT
* psOut
)
974 return _VarI2FromUI2(usIn
, psOut
);
977 /************************************************************************
978 * VarI2FromUI4 (OLEAUT32.207)
980 * Convert a VT_UI4 to a VT_I2.
984 * psOut [O] Destination
988 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
990 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, SHORT
* psOut
)
992 return _VarI2FromUI4(ulIn
, psOut
);
995 /************************************************************************
996 * VarI2FromDec (OLEAUT32.208)
998 * Convert a VT_DECIMAL to a VT_I2.
1002 * psOut [O] Destination
1006 * Failure: E_INVALIDARG, if the source value is invalid
1007 * DISP_E_OVERFLOW, if the value will not fit in the destination
1009 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
1010 HRESULT WINAPI
VarI2FromDec(DECIMAL
*pdecIn
, SHORT
* psOut
)
1015 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1017 if (SUCCEEDED(hRet
))
1018 hRet
= _VarI2FromI8(i64
, psOut
);
1023 /************************************************************************
1024 * VarI2FromI8 (OLEAUT32.346)
1026 * Convert a VT_I8 to a VT_I2.
1030 * psOut [O] Destination
1034 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1036 HRESULT WINAPI
VarI2FromI8(LONG64 llIn
, SHORT
* psOut
)
1038 return _VarI2FromI8(llIn
, psOut
);
1041 /************************************************************************
1042 * VarI2FromUI8 (OLEAUT32.347)
1044 * Convert a VT_UI8 to a VT_I2.
1048 * psOut [O] Destination
1052 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1054 HRESULT WINAPI
VarI2FromUI8(ULONG64 ullIn
, SHORT
* psOut
)
1056 return _VarI2FromUI8(ullIn
, psOut
);
1062 /************************************************************************
1063 * VarUI2FromUI1 (OLEAUT32.257)
1065 * Convert a VT_UI1 to a VT_UI2.
1069 * pusOut [O] Destination
1074 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* pusOut
)
1076 return _VarUI2FromUI1(bIn
, pusOut
);
1079 /************************************************************************
1080 * VarUI2FromI2 (OLEAUT32.258)
1082 * Convert a VT_I2 to a VT_UI2.
1086 * pusOut [O] Destination
1090 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1092 HRESULT WINAPI
VarUI2FromI2(SHORT sIn
, USHORT
* pusOut
)
1094 return _VarUI2FromI2(sIn
, pusOut
);
1097 /************************************************************************
1098 * VarUI2FromI4 (OLEAUT32.259)
1100 * Convert a VT_I4 to a VT_UI2.
1104 * pusOut [O] Destination
1108 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1110 HRESULT WINAPI
VarUI2FromI4(LONG iIn
, USHORT
* pusOut
)
1112 return _VarUI2FromI4(iIn
, pusOut
);
1115 /************************************************************************
1116 * VarUI2FromR4 (OLEAUT32.260)
1118 * Convert a VT_R4 to a VT_UI2.
1122 * pusOut [O] Destination
1126 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1128 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* pusOut
)
1130 return _VarUI2FromR4(fltIn
, pusOut
);
1133 /************************************************************************
1134 * VarUI2FromR8 (OLEAUT32.261)
1136 * Convert a VT_R8 to a VT_UI2.
1140 * pusOut [O] Destination
1144 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1147 * See VarI8FromR8() for details concerning rounding.
1149 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* pusOut
)
1151 if (dblIn
< -0.5 || dblIn
> (double)UI2_MAX
)
1152 return DISP_E_OVERFLOW
;
1153 OLEAUT32_DutchRound(USHORT
, dblIn
, *pusOut
);
1157 /************************************************************************
1158 * VarUI2FromDate (OLEAUT32.262)
1160 * Convert a VT_DATE to a VT_UI2.
1164 * pusOut [O] Destination
1168 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1170 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* pusOut
)
1172 return _VarUI2FromDate(dateIn
, pusOut
);
1175 /************************************************************************
1176 * VarUI2FromCy (OLEAUT32.263)
1178 * Convert a VT_CY to a VT_UI2.
1182 * pusOut [O] Destination
1186 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1189 * Negative values >= -5000 will be converted to 0.
1191 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
)
1193 ULONG i
= UI2_MAX
+ 1;
1195 _VarUI4FromCy(cyIn
, &i
);
1196 return _VarUI2FromUI4(i
, pusOut
);
1199 /************************************************************************
1200 * VarUI2FromStr (OLEAUT32.264)
1202 * Convert a VT_BSTR to a VT_UI2.
1206 * lcid [I] LCID for the conversion
1207 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1208 * pusOut [O] Destination
1212 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1213 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1215 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* pusOut
)
1217 return _VarUI2FromStr(strIn
, lcid
, dwFlags
, pusOut
);
1220 /************************************************************************
1221 * VarUI2FromDisp (OLEAUT32.265)
1223 * Convert a VT_DISPATCH to a VT_UI2.
1226 * pdispIn [I] Source
1227 * lcid [I] LCID for conversion
1228 * pusOut [O] Destination
1232 * Failure: E_INVALIDARG, if the source value is invalid
1233 * DISP_E_OVERFLOW, if the value will not fit in the destination
1234 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1236 HRESULT WINAPI
VarUI2FromDisp(IDispatch
* pdispIn
, LCID lcid
, USHORT
* pusOut
)
1238 return _VarUI2FromDisp(pdispIn
, lcid
, pusOut
);
1241 /************************************************************************
1242 * VarUI2FromBool (OLEAUT32.266)
1244 * Convert a VT_BOOL to a VT_UI2.
1248 * pusOut [O] Destination
1253 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* pusOut
)
1255 return _VarUI2FromBool(boolIn
, pusOut
);
1258 /************************************************************************
1259 * VarUI2FromI1 (OLEAUT32.267)
1261 * Convert a VT_I1 to a VT_UI2.
1265 * pusOut [O] Destination
1269 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1271 HRESULT WINAPI
VarUI2FromI1(signed char cIn
, USHORT
* pusOut
)
1273 return _VarUI2FromI1(cIn
, pusOut
);
1276 /************************************************************************
1277 * VarUI2FromUI4 (OLEAUT32.268)
1279 * Convert a VT_UI4 to a VT_UI2.
1283 * pusOut [O] Destination
1287 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1289 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* pusOut
)
1291 return _VarUI2FromUI4(ulIn
, pusOut
);
1294 /************************************************************************
1295 * VarUI2FromDec (OLEAUT32.269)
1297 * Convert a VT_DECIMAL to a VT_UI2.
1301 * pusOut [O] Destination
1305 * Failure: E_INVALIDARG, if the source value is invalid
1306 * DISP_E_OVERFLOW, if the value will not fit in the destination
1308 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
1309 HRESULT WINAPI
VarUI2FromDec(DECIMAL
*pdecIn
, USHORT
* pusOut
)
1314 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1316 if (SUCCEEDED(hRet
))
1317 hRet
= _VarUI2FromI8(i64
, pusOut
);
1322 /************************************************************************
1323 * VarUI2FromI8 (OLEAUT32.378)
1325 * Convert a VT_I8 to a VT_UI2.
1329 * pusOut [O] Destination
1333 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1335 HRESULT WINAPI
VarUI2FromI8(LONG64 llIn
, USHORT
* pusOut
)
1337 return _VarUI2FromI8(llIn
, pusOut
);
1340 /************************************************************************
1341 * VarUI2FromUI8 (OLEAUT32.379)
1343 * Convert a VT_UI8 to a VT_UI2.
1347 * pusOut [O] Destination
1351 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1353 HRESULT WINAPI
VarUI2FromUI8(ULONG64 ullIn
, USHORT
* pusOut
)
1355 return _VarUI2FromUI8(ullIn
, pusOut
);
1361 /************************************************************************
1362 * VarI4FromUI1 (OLEAUT32.58)
1364 * Convert a VT_UI1 to a VT_I4.
1368 * piOut [O] Destination
1373 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
*piOut
)
1375 return _VarI4FromUI1(bIn
, piOut
);
1378 /************************************************************************
1379 * VarI4FromI2 (OLEAUT32.59)
1381 * Convert a VT_I2 to a VT_I4.
1385 * piOut [O] Destination
1389 * Failure: E_INVALIDARG, if the source value is invalid
1390 * DISP_E_OVERFLOW, if the value will not fit in the destination
1392 HRESULT WINAPI
VarI4FromI2(SHORT sIn
, LONG
*piOut
)
1394 return _VarI4FromI2(sIn
, piOut
);
1397 /************************************************************************
1398 * VarI4FromR4 (OLEAUT32.60)
1400 * Convert a VT_R4 to a VT_I4.
1404 * piOut [O] Destination
1408 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1410 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
*piOut
)
1412 return _VarI4FromR4(fltIn
, piOut
);
1415 /************************************************************************
1416 * VarI4FromR8 (OLEAUT32.61)
1418 * Convert a VT_R8 to a VT_I4.
1422 * piOut [O] Destination
1426 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1429 * See VarI8FromR8() for details concerning rounding.
1431 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
*piOut
)
1433 if (dblIn
< (double)I4_MIN
|| dblIn
> (double)I4_MAX
)
1434 return DISP_E_OVERFLOW
;
1435 OLEAUT32_DutchRound(LONG
, dblIn
, *piOut
);
1439 /************************************************************************
1440 * VarI4FromCy (OLEAUT32.62)
1442 * Convert a VT_CY to a VT_I4.
1446 * piOut [O] Destination
1450 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1452 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
*piOut
)
1454 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1455 return _VarI4FromR8(d
, piOut
);
1458 /************************************************************************
1459 * VarI4FromDate (OLEAUT32.63)
1461 * Convert a VT_DATE to a VT_I4.
1465 * piOut [O] Destination
1469 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1471 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
*piOut
)
1473 return _VarI4FromDate(dateIn
, piOut
);
1476 /************************************************************************
1477 * VarI4FromStr (OLEAUT32.64)
1479 * Convert a VT_BSTR to a VT_I4.
1483 * lcid [I] LCID for the conversion
1484 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1485 * piOut [O] Destination
1489 * Failure: E_INVALIDARG, if any parameter is invalid
1490 * DISP_E_OVERFLOW, if the value will not fit in the destination
1491 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1493 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
*piOut
)
1495 return _VarI4FromStr(strIn
, lcid
, dwFlags
, piOut
);
1498 /************************************************************************
1499 * VarI4FromDisp (OLEAUT32.65)
1501 * Convert a VT_DISPATCH to a VT_I4.
1504 * pdispIn [I] Source
1505 * lcid [I] LCID for conversion
1506 * piOut [O] Destination
1510 * Failure: E_INVALIDARG, if the source value is invalid
1511 * DISP_E_OVERFLOW, if the value will not fit in the destination
1512 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1514 HRESULT WINAPI
VarI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG
*piOut
)
1516 return _VarI4FromDisp(pdispIn
, lcid
, piOut
);
1519 /************************************************************************
1520 * VarI4FromBool (OLEAUT32.66)
1522 * Convert a VT_BOOL to a VT_I4.
1526 * piOut [O] Destination
1531 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
*piOut
)
1533 return _VarI4FromBool(boolIn
, piOut
);
1536 /************************************************************************
1537 * VarI4FromI1 (OLEAUT32.209)
1539 * Convert a VT_I4 to a VT_I4.
1543 * piOut [O] Destination
1548 HRESULT WINAPI
VarI4FromI1(signed char cIn
, LONG
*piOut
)
1550 return _VarI4FromI1(cIn
, piOut
);
1553 /************************************************************************
1554 * VarI4FromUI2 (OLEAUT32.210)
1556 * Convert a VT_UI2 to a VT_I4.
1560 * piOut [O] Destination
1565 HRESULT WINAPI
VarI4FromUI2(USHORT usIn
, LONG
*piOut
)
1567 return _VarI4FromUI2(usIn
, piOut
);
1570 /************************************************************************
1571 * VarI4FromUI4 (OLEAUT32.211)
1573 * Convert a VT_UI4 to a VT_I4.
1577 * piOut [O] Destination
1581 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1583 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
*piOut
)
1585 return _VarI4FromUI4(ulIn
, piOut
);
1588 /************************************************************************
1589 * VarI4FromDec (OLEAUT32.212)
1591 * Convert a VT_DECIMAL to a VT_I4.
1595 * piOut [O] Destination
1599 * Failure: E_INVALIDARG, if pdecIn is invalid
1600 * DISP_E_OVERFLOW, if the value will not fit in the destination
1602 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
1603 HRESULT WINAPI
VarI4FromDec(DECIMAL
*pdecIn
, LONG
*piOut
)
1608 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1610 if (SUCCEEDED(hRet
))
1611 hRet
= _VarI4FromI8(i64
, piOut
);
1616 /************************************************************************
1617 * VarI4FromI8 (OLEAUT32.348)
1619 * Convert a VT_I8 to a VT_I4.
1623 * piOut [O] Destination
1627 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1629 HRESULT WINAPI
VarI4FromI8(LONG64 llIn
, LONG
*piOut
)
1631 return _VarI4FromI8(llIn
, piOut
);
1634 /************************************************************************
1635 * VarI4FromUI8 (OLEAUT32.349)
1637 * Convert a VT_UI8 to a VT_I4.
1641 * piOut [O] Destination
1645 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1647 HRESULT WINAPI
VarI4FromUI8(ULONG64 ullIn
, LONG
*piOut
)
1649 return _VarI4FromUI8(ullIn
, piOut
);
1655 /************************************************************************
1656 * VarUI4FromUI1 (OLEAUT32.270)
1658 * Convert a VT_UI1 to a VT_UI4.
1662 * pulOut [O] Destination
1667 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
*pulOut
)
1669 return _VarUI4FromUI1(bIn
, pulOut
);
1672 /************************************************************************
1673 * VarUI4FromI2 (OLEAUT32.271)
1675 * Convert a VT_I2 to a VT_UI4.
1679 * pulOut [O] Destination
1683 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1685 HRESULT WINAPI
VarUI4FromI2(SHORT sIn
, ULONG
*pulOut
)
1687 return _VarUI4FromI2(sIn
, pulOut
);
1690 /************************************************************************
1691 * VarUI4FromI4 (OLEAUT32.272)
1693 * Convert a VT_I4 to a VT_UI4.
1697 * pulOut [O] Destination
1701 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1703 HRESULT WINAPI
VarUI4FromI4(LONG iIn
, ULONG
*pulOut
)
1705 return _VarUI4FromI4(iIn
, pulOut
);
1708 /************************************************************************
1709 * VarUI4FromR4 (OLEAUT32.273)
1711 * Convert a VT_R4 to a VT_UI4.
1715 * pulOut [O] Destination
1719 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1721 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
*pulOut
)
1723 return _VarUI4FromR4(fltIn
, pulOut
);
1726 /************************************************************************
1727 * VarUI4FromR8 (OLEAUT32.274)
1729 * Convert a VT_R8 to a VT_UI4.
1733 * pulOut [O] Destination
1737 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1740 * See VarI8FromR8() for details concerning rounding.
1742 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
*pulOut
)
1744 if (dblIn
< -0.5 || dblIn
> (double)UI4_MAX
)
1745 return DISP_E_OVERFLOW
;
1746 OLEAUT32_DutchRound(ULONG
, dblIn
, *pulOut
);
1750 /************************************************************************
1751 * VarUI4FromDate (OLEAUT32.275)
1753 * Convert a VT_DATE to a VT_UI4.
1757 * pulOut [O] Destination
1761 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1763 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
*pulOut
)
1765 return _VarUI4FromDate(dateIn
, pulOut
);
1768 /************************************************************************
1769 * VarUI4FromCy (OLEAUT32.276)
1771 * Convert a VT_CY to a VT_UI4.
1775 * pulOut [O] Destination
1779 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1781 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
*pulOut
)
1783 double d
= cyIn
.int64
/ CY_MULTIPLIER_F
;
1784 return _VarUI4FromR8(d
, pulOut
);
1788 /************************************************************************
1789 * VarUI4FromStr (OLEAUT32.277)
1791 * Convert a VT_BSTR to a VT_UI4.
1795 * lcid [I] LCID for the conversion
1796 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1797 * pulOut [O] Destination
1801 * Failure: E_INVALIDARG, if any parameter is invalid
1802 * DISP_E_OVERFLOW, if the value will not fit in the destination
1803 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1805 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
*pulOut
)
1807 return _VarUI4FromStr(strIn
, lcid
, dwFlags
, pulOut
);
1810 /************************************************************************
1811 * VarUI4FromDisp (OLEAUT32.278)
1813 * Convert a VT_DISPATCH to a VT_UI4.
1816 * pdispIn [I] Source
1817 * lcid [I] LCID for conversion
1818 * pulOut [O] Destination
1822 * Failure: E_INVALIDARG, if the source value is invalid
1823 * DISP_E_OVERFLOW, if the value will not fit in the destination
1824 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1826 HRESULT WINAPI
VarUI4FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG
*pulOut
)
1828 return _VarUI4FromDisp(pdispIn
, lcid
, pulOut
);
1831 /************************************************************************
1832 * VarUI4FromBool (OLEAUT32.279)
1834 * Convert a VT_BOOL to a VT_UI4.
1838 * pulOut [O] Destination
1843 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
*pulOut
)
1845 return _VarUI4FromBool(boolIn
, pulOut
);
1848 /************************************************************************
1849 * VarUI4FromI1 (OLEAUT32.280)
1851 * Convert a VT_I1 to a VT_UI4.
1855 * pulOut [O] Destination
1859 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1861 HRESULT WINAPI
VarUI4FromI1(signed char cIn
, ULONG
*pulOut
)
1863 return _VarUI4FromI1(cIn
, pulOut
);
1866 /************************************************************************
1867 * VarUI4FromUI2 (OLEAUT32.281)
1869 * Convert a VT_UI2 to a VT_UI4.
1873 * pulOut [O] Destination
1878 HRESULT WINAPI
VarUI4FromUI2(USHORT usIn
, ULONG
*pulOut
)
1880 return _VarUI4FromUI2(usIn
, pulOut
);
1883 /************************************************************************
1884 * VarUI4FromDec (OLEAUT32.282)
1886 * Convert a VT_DECIMAL to a VT_UI4.
1890 * pulOut [O] Destination
1894 * Failure: E_INVALIDARG, if pdecIn is invalid
1895 * DISP_E_OVERFLOW, if the value will not fit in the destination
1897 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
1898 HRESULT WINAPI
VarUI4FromDec(DECIMAL
*pdecIn
, ULONG
*pulOut
)
1903 hRet
= _VarI8FromDec(pdecIn
, &i64
);
1905 if (SUCCEEDED(hRet
))
1906 hRet
= _VarUI4FromI8(i64
, pulOut
);
1911 /************************************************************************
1912 * VarUI4FromI8 (OLEAUT32.425)
1914 * Convert a VT_I8 to a VT_UI4.
1918 * pulOut [O] Destination
1922 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1924 HRESULT WINAPI
VarUI4FromI8(LONG64 llIn
, ULONG
*pulOut
)
1926 return _VarUI4FromI8(llIn
, pulOut
);
1929 /************************************************************************
1930 * VarUI4FromUI8 (OLEAUT32.426)
1932 * Convert a VT_UI8 to a VT_UI4.
1936 * pulOut [O] Destination
1940 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1942 HRESULT WINAPI
VarUI4FromUI8(ULONG64 ullIn
, ULONG
*pulOut
)
1944 return _VarUI4FromUI8(ullIn
, pulOut
);
1950 /************************************************************************
1951 * VarI8FromUI1 (OLEAUT32.333)
1953 * Convert a VT_UI1 to a VT_I8.
1957 * pi64Out [O] Destination
1962 HRESULT WINAPI
VarI8FromUI1(BYTE bIn
, LONG64
* pi64Out
)
1964 return _VarI8FromUI1(bIn
, pi64Out
);
1968 /************************************************************************
1969 * VarI8FromI2 (OLEAUT32.334)
1971 * Convert a VT_I2 to a VT_I8.
1975 * pi64Out [O] Destination
1980 HRESULT WINAPI
VarI8FromI2(SHORT sIn
, LONG64
* pi64Out
)
1982 return _VarI8FromI2(sIn
, pi64Out
);
1985 /************************************************************************
1986 * VarI8FromR4 (OLEAUT32.335)
1988 * Convert a VT_R4 to a VT_I8.
1992 * pi64Out [O] Destination
1996 * Failure: E_INVALIDARG, if the source value is invalid
1997 * DISP_E_OVERFLOW, if the value will not fit in the destination
1999 HRESULT WINAPI
VarI8FromR4(FLOAT fltIn
, LONG64
* pi64Out
)
2001 return _VarI8FromR4(fltIn
, pi64Out
);
2004 /************************************************************************
2005 * VarI8FromR8 (OLEAUT32.336)
2007 * Convert a VT_R8 to a VT_I8.
2011 * pi64Out [O] Destination
2015 * Failure: E_INVALIDARG, if the source value is invalid
2016 * DISP_E_OVERFLOW, if the value will not fit in the destination
2019 * Only values that fit into 63 bits are accepted. Due to rounding issues,
2020 * very high or low values will not be accurately converted.
2022 * Numbers are rounded using Dutch rounding, as follows:
2024 *| Fractional Part Sign Direction Example
2025 *| --------------- ---- --------- -------
2026 *| < 0.5 + Down 0.4 -> 0.0
2027 *| < 0.5 - Up -0.4 -> 0.0
2028 *| > 0.5 + Up 0.6 -> 1.0
2029 *| < 0.5 - Up -0.6 -> -1.0
2030 *| = 0.5 + Up/Down Down if even, Up if odd
2031 *| = 0.5 - Up/Down Up if even, Down if odd
2033 * This system is often used in supermarkets.
2035 HRESULT WINAPI
VarI8FromR8(double dblIn
, LONG64
* pi64Out
)
2037 if ( dblIn
< -4611686018427387904.0 || dblIn
>= 4611686018427387904.0)
2038 return DISP_E_OVERFLOW
;
2039 OLEAUT32_DutchRound(LONG64
, dblIn
, *pi64Out
);
2044 /************************************************************************
2045 * VarI8FromCy (OLEAUT32.337)
2047 * Convert a VT_CY to a VT_I8.
2051 * pi64Out [O] Destination
2057 * All negative numbers are rounded down by 1, including those that are
2058 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2059 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2062 HRESULT WINAPI
VarI8FromCy(CY cyIn
, LONG64
* pi64Out
)
2064 *pi64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2067 (*pi64Out
)--; /* Mimic Win32 bug */
2070 cyIn
.int64
-= *pi64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2072 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pi64Out
& 0x1)))
2078 /************************************************************************
2079 * VarI8FromDate (OLEAUT32.338)
2081 * Convert a VT_DATE to a VT_I8.
2085 * pi64Out [O] Destination
2089 * Failure: E_INVALIDARG, if the source value is invalid
2090 * DISP_E_OVERFLOW, if the value will not fit in the destination
2091 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2093 HRESULT WINAPI
VarI8FromDate(DATE dateIn
, LONG64
* pi64Out
)
2095 return _VarI8FromDate(dateIn
, pi64Out
);
2098 /************************************************************************
2099 * VarI8FromStr (OLEAUT32.339)
2101 * Convert a VT_BSTR to a VT_I8.
2105 * lcid [I] LCID for the conversion
2106 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2107 * pi64Out [O] Destination
2111 * Failure: E_INVALIDARG, if the source value is invalid
2112 * DISP_E_OVERFLOW, if the value will not fit in the destination
2113 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2115 HRESULT WINAPI
VarI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG64
* pi64Out
)
2117 return _VarI8FromStr(strIn
, lcid
, dwFlags
, pi64Out
);
2120 /************************************************************************
2121 * VarI8FromDisp (OLEAUT32.340)
2123 * Convert a VT_DISPATCH to a VT_I8.
2126 * pdispIn [I] Source
2127 * lcid [I] LCID for conversion
2128 * pi64Out [O] Destination
2132 * Failure: E_INVALIDARG, if the source value is invalid
2133 * DISP_E_OVERFLOW, if the value will not fit in the destination
2134 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2136 HRESULT WINAPI
VarI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, LONG64
* pi64Out
)
2138 return _VarI8FromDisp(pdispIn
, lcid
, pi64Out
);
2141 /************************************************************************
2142 * VarI8FromBool (OLEAUT32.341)
2144 * Convert a VT_BOOL to a VT_I8.
2148 * pi64Out [O] Destination
2153 HRESULT WINAPI
VarI8FromBool(VARIANT_BOOL boolIn
, LONG64
* pi64Out
)
2155 return _VarI8FromBool(boolIn
, pi64Out
);
2158 /************************************************************************
2159 * VarI8FromI1 (OLEAUT32.342)
2161 * Convert a VT_I1 to a VT_I8.
2165 * pi64Out [O] Destination
2170 HRESULT WINAPI
VarI8FromI1(signed char cIn
, LONG64
* pi64Out
)
2172 return _VarI8FromI1(cIn
, pi64Out
);
2175 /************************************************************************
2176 * VarI8FromUI2 (OLEAUT32.343)
2178 * Convert a VT_UI2 to a VT_I8.
2182 * pi64Out [O] Destination
2187 HRESULT WINAPI
VarI8FromUI2(USHORT usIn
, LONG64
* pi64Out
)
2189 return _VarI8FromUI2(usIn
, pi64Out
);
2192 /************************************************************************
2193 * VarI8FromUI4 (OLEAUT32.344)
2195 * Convert a VT_UI4 to a VT_I8.
2199 * pi64Out [O] Destination
2204 HRESULT WINAPI
VarI8FromUI4(ULONG ulIn
, LONG64
* pi64Out
)
2206 return _VarI8FromUI4(ulIn
, pi64Out
);
2209 /************************************************************************
2210 * VarI8FromDec (OLEAUT32.345)
2212 * Convert a VT_DECIMAL to a VT_I8.
2216 * pi64Out [O] Destination
2220 * Failure: E_INVALIDARG, if the source value is invalid
2221 * DISP_E_OVERFLOW, if the value will not fit in the destination
2223 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
2224 HRESULT WINAPI
VarI8FromDec(DECIMAL
*pdecIn
, LONG64
* pi64Out
)
2226 if (!DEC_SCALE(pdecIn
))
2228 /* This decimal is just a 96 bit integer */
2229 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2230 return E_INVALIDARG
;
2232 if (DEC_HI32(pdecIn
) || DEC_MID32(pdecIn
) & 0x80000000)
2233 return DISP_E_OVERFLOW
;
2235 if (DEC_SIGN(pdecIn
))
2236 *pi64Out
= -DEC_LO64(pdecIn
);
2238 *pi64Out
= DEC_LO64(pdecIn
);
2243 /* Decimal contains a floating point number */
2247 hRet
= _VarR8FromDec(pdecIn
, &dbl
);
2248 if (SUCCEEDED(hRet
))
2249 hRet
= VarI8FromR8(dbl
, pi64Out
);
2255 /************************************************************************
2256 * VarI8FromUI8 (OLEAUT32.427)
2258 * Convert a VT_UI8 to a VT_I8.
2262 * pi64Out [O] Destination
2266 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2268 HRESULT WINAPI
VarI8FromUI8(ULONG64 ullIn
, LONG64
* pi64Out
)
2270 return _VarI8FromUI8(ullIn
, pi64Out
);
2276 /************************************************************************
2277 * VarUI8FromI8 (OLEAUT32.428)
2279 * Convert a VT_I8 to a VT_UI8.
2283 * pui64Out [O] Destination
2287 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2289 HRESULT WINAPI
VarUI8FromI8(LONG64 llIn
, ULONG64
* pui64Out
)
2291 return _VarUI8FromI8(llIn
, pui64Out
);
2294 /************************************************************************
2295 * VarUI8FromUI1 (OLEAUT32.429)
2297 * Convert a VT_UI1 to a VT_UI8.
2301 * pui64Out [O] Destination
2306 HRESULT WINAPI
VarUI8FromUI1(BYTE bIn
, ULONG64
* pui64Out
)
2308 return _VarUI8FromUI1(bIn
, pui64Out
);
2311 /************************************************************************
2312 * VarUI8FromI2 (OLEAUT32.430)
2314 * Convert a VT_I2 to a VT_UI8.
2318 * pui64Out [O] Destination
2323 HRESULT WINAPI
VarUI8FromI2(SHORT sIn
, ULONG64
* pui64Out
)
2325 return _VarUI8FromI2(sIn
, pui64Out
);
2328 /************************************************************************
2329 * VarUI8FromR4 (OLEAUT32.431)
2331 * Convert a VT_R4 to a VT_UI8.
2335 * pui64Out [O] Destination
2339 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2341 HRESULT WINAPI
VarUI8FromR4(FLOAT fltIn
, ULONG64
* pui64Out
)
2343 return _VarUI8FromR4(fltIn
, pui64Out
);
2346 /************************************************************************
2347 * VarUI8FromR8 (OLEAUT32.432)
2349 * Convert a VT_R8 to a VT_UI8.
2353 * pui64Out [O] Destination
2357 * Failure: E_INVALIDARG, if the source value is invalid
2358 * DISP_E_OVERFLOW, if the value will not fit in the destination
2361 * See VarI8FromR8() for details concerning rounding.
2363 HRESULT WINAPI
VarUI8FromR8(double dblIn
, ULONG64
* pui64Out
)
2365 if (dblIn
< -0.5 || dblIn
> 1.844674407370955e19
)
2366 return DISP_E_OVERFLOW
;
2367 OLEAUT32_DutchRound(ULONG64
, dblIn
, *pui64Out
);
2371 /************************************************************************
2372 * VarUI8FromCy (OLEAUT32.433)
2374 * Convert a VT_CY to a VT_UI8.
2378 * pui64Out [O] Destination
2382 * Failure: E_INVALIDARG, if the source value is invalid
2383 * DISP_E_OVERFLOW, if the value will not fit in the destination
2386 * Negative values >= -5000 will be converted to 0.
2388 HRESULT WINAPI
VarUI8FromCy(CY cyIn
, ULONG64
* pui64Out
)
2392 if (cyIn
.int64
< -CY_HALF
)
2393 return DISP_E_OVERFLOW
;
2398 *pui64Out
= cyIn
.int64
/ CY_MULTIPLIER
;
2400 cyIn
.int64
-= *pui64Out
* CY_MULTIPLIER
; /* cyIn.s.Lo now holds fractional remainder */
2402 if (cyIn
.s
.Lo
> CY_HALF
|| (cyIn
.s
.Lo
== CY_HALF
&& (*pui64Out
& 0x1)))
2408 /************************************************************************
2409 * VarUI8FromDate (OLEAUT32.434)
2411 * Convert a VT_DATE to a VT_UI8.
2415 * pui64Out [O] Destination
2419 * Failure: E_INVALIDARG, if the source value is invalid
2420 * DISP_E_OVERFLOW, if the value will not fit in the destination
2421 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2423 HRESULT WINAPI
VarUI8FromDate(DATE dateIn
, ULONG64
* pui64Out
)
2425 return _VarUI8FromDate(dateIn
, pui64Out
);
2428 /************************************************************************
2429 * VarUI8FromStr (OLEAUT32.435)
2431 * Convert a VT_BSTR to a VT_UI8.
2435 * lcid [I] LCID for the conversion
2436 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2437 * pui64Out [O] Destination
2441 * Failure: E_INVALIDARG, if the source value is invalid
2442 * DISP_E_OVERFLOW, if the value will not fit in the destination
2443 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2445 HRESULT WINAPI
VarUI8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG64
* pui64Out
)
2447 return _VarUI8FromStr(strIn
, lcid
, dwFlags
, pui64Out
);
2450 /************************************************************************
2451 * VarUI8FromDisp (OLEAUT32.436)
2453 * Convert a VT_DISPATCH to a VT_UI8.
2456 * pdispIn [I] Source
2457 * lcid [I] LCID for conversion
2458 * pui64Out [O] Destination
2462 * Failure: E_INVALIDARG, if the source value is invalid
2463 * DISP_E_OVERFLOW, if the value will not fit in the destination
2464 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2466 HRESULT WINAPI
VarUI8FromDisp(IDispatch
* pdispIn
, LCID lcid
, ULONG64
* pui64Out
)
2468 return _VarUI8FromDisp(pdispIn
, lcid
, pui64Out
);
2471 /************************************************************************
2472 * VarUI8FromBool (OLEAUT32.437)
2474 * Convert a VT_BOOL to a VT_UI8.
2478 * pui64Out [O] Destination
2482 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2484 HRESULT WINAPI
VarUI8FromBool(VARIANT_BOOL boolIn
, ULONG64
* pui64Out
)
2486 return _VarUI8FromBool(boolIn
, pui64Out
);
2488 /************************************************************************
2489 * VarUI8FromI1 (OLEAUT32.438)
2491 * Convert a VT_I1 to a VT_UI8.
2495 * pui64Out [O] Destination
2499 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2501 HRESULT WINAPI
VarUI8FromI1(signed char cIn
, ULONG64
* pui64Out
)
2503 return _VarUI8FromI1(cIn
, pui64Out
);
2506 /************************************************************************
2507 * VarUI8FromUI2 (OLEAUT32.439)
2509 * Convert a VT_UI2 to a VT_UI8.
2513 * pui64Out [O] Destination
2518 HRESULT WINAPI
VarUI8FromUI2(USHORT usIn
, ULONG64
* pui64Out
)
2520 return _VarUI8FromUI2(usIn
, pui64Out
);
2523 /************************************************************************
2524 * VarUI8FromUI4 (OLEAUT32.440)
2526 * Convert a VT_UI4 to a VT_UI8.
2530 * pui64Out [O] Destination
2535 HRESULT WINAPI
VarUI8FromUI4(ULONG ulIn
, ULONG64
* pui64Out
)
2537 return _VarUI8FromUI4(ulIn
, pui64Out
);
2540 /************************************************************************
2541 * VarUI8FromDec (OLEAUT32.441)
2543 * Convert a VT_DECIMAL to a VT_UI8.
2547 * pui64Out [O] Destination
2551 * Failure: E_INVALIDARG, if the source value is invalid
2552 * DISP_E_OVERFLOW, if the value will not fit in the destination
2555 * Under native Win32, if the source value has a scale of 0, its sign is
2556 * ignored, i.e. this function takes the absolute value rather than fail
2557 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2558 * (use VarAbs() on pDecIn first if you really want this behaviour).
2560 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
2561 HRESULT WINAPI
VarUI8FromDec(DECIMAL
*pdecIn
, ULONG64
* pui64Out
)
2563 if (!DEC_SCALE(pdecIn
))
2565 /* This decimal is just a 96 bit integer */
2566 if (DEC_SIGN(pdecIn
) & ~DECIMAL_NEG
)
2567 return E_INVALIDARG
;
2569 if (DEC_HI32(pdecIn
))
2570 return DISP_E_OVERFLOW
;
2572 if (DEC_SIGN(pdecIn
))
2574 WARN("Sign would be ignored under Win32!\n");
2575 return DISP_E_OVERFLOW
;
2578 *pui64Out
= DEC_LO64(pdecIn
);
2583 /* Decimal contains a floating point number */
2587 hRet
= _VarR8FromDec(pdecIn
, &dbl
);
2588 if (SUCCEEDED(hRet
))
2589 hRet
= VarUI8FromR8(dbl
, pui64Out
);
2598 /************************************************************************
2599 * VarR4FromUI1 (OLEAUT32.68)
2601 * Convert a VT_UI1 to a VT_R4.
2605 * pFltOut [O] Destination
2610 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, float *pFltOut
)
2612 return _VarR4FromUI1(bIn
, pFltOut
);
2615 /************************************************************************
2616 * VarR4FromI2 (OLEAUT32.69)
2618 * Convert a VT_I2 to a VT_R4.
2622 * pFltOut [O] Destination
2627 HRESULT WINAPI
VarR4FromI2(SHORT sIn
, float *pFltOut
)
2629 return _VarR4FromI2(sIn
, pFltOut
);
2632 /************************************************************************
2633 * VarR4FromI4 (OLEAUT32.70)
2635 * Convert a VT_I4 to a VT_R4.
2639 * pFltOut [O] Destination
2644 HRESULT WINAPI
VarR4FromI4(LONG lIn
, float *pFltOut
)
2646 return _VarR4FromI4(lIn
, pFltOut
);
2649 /************************************************************************
2650 * VarR4FromR8 (OLEAUT32.71)
2652 * Convert a VT_R8 to a VT_R4.
2656 * pFltOut [O] Destination
2660 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2662 HRESULT WINAPI
VarR4FromR8(double dblIn
, float *pFltOut
)
2664 return _VarR4FromR8(dblIn
, pFltOut
);
2667 /************************************************************************
2668 * VarR4FromCy (OLEAUT32.72)
2670 * Convert a VT_CY to a VT_R4.
2674 * pFltOut [O] Destination
2679 HRESULT WINAPI
VarR4FromCy(CY cyIn
, float *pFltOut
)
2681 return _VarR4FromCy(cyIn
, pFltOut
);
2684 /************************************************************************
2685 * VarR4FromDate (OLEAUT32.73)
2687 * Convert a VT_DATE to a VT_R4.
2691 * pFltOut [O] Destination
2695 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2697 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, float *pFltOut
)
2699 return _VarR4FromDate(dateIn
, pFltOut
);
2702 /************************************************************************
2703 * VarR4FromStr (OLEAUT32.74)
2705 * Convert a VT_BSTR to a VT_R4.
2709 * lcid [I] LCID for the conversion
2710 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2711 * pFltOut [O] Destination
2715 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2716 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2718 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, float *pFltOut
)
2720 return _VarR4FromStr(strIn
, lcid
, dwFlags
, pFltOut
);
2723 /************************************************************************
2724 * VarR4FromDisp (OLEAUT32.75)
2726 * Convert a VT_DISPATCH to a VT_R4.
2729 * pdispIn [I] Source
2730 * lcid [I] LCID for conversion
2731 * pFltOut [O] Destination
2735 * Failure: E_INVALIDARG, if the source value is invalid
2736 * DISP_E_OVERFLOW, if the value will not fit in the destination
2737 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2739 HRESULT WINAPI
VarR4FromDisp(IDispatch
* pdispIn
, LCID lcid
, float *pFltOut
)
2741 return _VarR4FromDisp(pdispIn
, lcid
, pFltOut
);
2744 /************************************************************************
2745 * VarR4FromBool (OLEAUT32.76)
2747 * Convert a VT_BOOL to a VT_R4.
2751 * pFltOut [O] Destination
2756 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, float *pFltOut
)
2758 return _VarR4FromBool(boolIn
, pFltOut
);
2761 /************************************************************************
2762 * VarR4FromI1 (OLEAUT32.213)
2764 * Convert a VT_I1 to a VT_R4.
2768 * pFltOut [O] Destination
2772 * Failure: E_INVALIDARG, if the source value is invalid
2773 * DISP_E_OVERFLOW, if the value will not fit in the destination
2774 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2776 HRESULT WINAPI
VarR4FromI1(signed char cIn
, float *pFltOut
)
2778 return _VarR4FromI1(cIn
, pFltOut
);
2781 /************************************************************************
2782 * VarR4FromUI2 (OLEAUT32.214)
2784 * Convert a VT_UI2 to a VT_R4.
2788 * pFltOut [O] Destination
2792 * Failure: E_INVALIDARG, if the source value is invalid
2793 * DISP_E_OVERFLOW, if the value will not fit in the destination
2794 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2796 HRESULT WINAPI
VarR4FromUI2(USHORT usIn
, float *pFltOut
)
2798 return _VarR4FromUI2(usIn
, pFltOut
);
2801 /************************************************************************
2802 * VarR4FromUI4 (OLEAUT32.215)
2804 * Convert a VT_UI4 to a VT_R4.
2808 * pFltOut [O] Destination
2812 * Failure: E_INVALIDARG, if the source value is invalid
2813 * DISP_E_OVERFLOW, if the value will not fit in the destination
2814 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2816 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, float *pFltOut
)
2818 return _VarR4FromUI4(ulIn
, pFltOut
);
2821 /************************************************************************
2822 * VarR4FromDec (OLEAUT32.216)
2824 * Convert a VT_DECIMAL to a VT_R4.
2828 * pFltOut [O] Destination
2832 * Failure: E_INVALIDARG, if the source value is invalid.
2834 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
2835 HRESULT WINAPI
VarR4FromDec(DECIMAL
* pDecIn
, float *pFltOut
)
2837 BYTE scale
= DEC_SCALE(pDecIn
);
2841 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
2842 return E_INVALIDARG
;
2847 if (DEC_SIGN(pDecIn
))
2850 if (DEC_HI32(pDecIn
))
2852 highPart
= (double)DEC_HI32(pDecIn
) / (double)divisor
;
2858 *pFltOut
= (double)DEC_LO64(pDecIn
) / (double)divisor
+ highPart
;
2864 /************************************************************************
2865 * VarR4FromI8 (OLEAUT32.360)
2867 * Convert a VT_I8 to a VT_R4.
2871 * pFltOut [O] Destination
2876 HRESULT WINAPI
VarR4FromI8(LONG64 llIn
, float *pFltOut
)
2878 return _VarR4FromI8(llIn
, pFltOut
);
2881 /************************************************************************
2882 * VarR4FromUI8 (OLEAUT32.361)
2884 * Convert a VT_UI8 to a VT_R4.
2888 * pFltOut [O] Destination
2893 HRESULT WINAPI
VarR4FromUI8(ULONG64 ullIn
, float *pFltOut
)
2895 return _VarR4FromUI8(ullIn
, pFltOut
);
2898 /************************************************************************
2899 * VarR4CmpR8 (OLEAUT32.316)
2901 * Compare a VT_R4 to a VT_R8.
2904 * fltLeft [I] Source
2905 * dblRight [I] Value to compare
2908 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
2909 * equal to or greater than dblRight respectively.
2911 HRESULT WINAPI
VarR4CmpR8(float fltLeft
, double dblRight
)
2913 if (fltLeft
< dblRight
)
2915 else if (fltLeft
> dblRight
)
2923 /************************************************************************
2924 * VarR8FromUI1 (OLEAUT32.78)
2926 * Convert a VT_UI1 to a VT_R8.
2930 * pDblOut [O] Destination
2935 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double *pDblOut
)
2937 return _VarR8FromUI1(bIn
, pDblOut
);
2940 /************************************************************************
2941 * VarR8FromI2 (OLEAUT32.79)
2943 * Convert a VT_I2 to a VT_R8.
2947 * pDblOut [O] Destination
2952 HRESULT WINAPI
VarR8FromI2(SHORT sIn
, double *pDblOut
)
2954 return _VarR8FromI2(sIn
, pDblOut
);
2957 /************************************************************************
2958 * VarR8FromI4 (OLEAUT32.80)
2960 * Convert a VT_I4 to a VT_R8.
2964 * pDblOut [O] Destination
2969 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double *pDblOut
)
2971 return _VarR8FromI4(lIn
, pDblOut
);
2974 /************************************************************************
2975 * VarR8FromR4 (OLEAUT32.81)
2977 * Convert a VT_R4 to a VT_R8.
2981 * pDblOut [O] Destination
2986 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double *pDblOut
)
2988 return _VarR8FromR4(fltIn
, pDblOut
);
2991 /************************************************************************
2992 * VarR8FromCy (OLEAUT32.82)
2994 * Convert a VT_CY to a VT_R8.
2998 * pDblOut [O] Destination
3003 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double *pDblOut
)
3005 return _VarR8FromCy(cyIn
, pDblOut
);
3008 /************************************************************************
3009 * VarR8FromDate (OLEAUT32.83)
3011 * Convert a VT_DATE to a VT_R8.
3015 * pDblOut [O] Destination
3020 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double *pDblOut
)
3022 return _VarR8FromDate(dateIn
, pDblOut
);
3025 /************************************************************************
3026 * VarR8FromStr (OLEAUT32.84)
3028 * Convert a VT_BSTR to a VT_R8.
3032 * lcid [I] LCID for the conversion
3033 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3034 * pDblOut [O] Destination
3038 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3039 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3041 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double *pDblOut
)
3043 return _VarR8FromStr(strIn
, lcid
, dwFlags
, pDblOut
);
3046 /************************************************************************
3047 * VarR8FromDisp (OLEAUT32.85)
3049 * Convert a VT_DISPATCH to a VT_R8.
3052 * pdispIn [I] Source
3053 * lcid [I] LCID for conversion
3054 * pDblOut [O] Destination
3058 * Failure: E_INVALIDARG, if the source value is invalid
3059 * DISP_E_OVERFLOW, if the value will not fit in the destination
3060 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3062 HRESULT WINAPI
VarR8FromDisp(IDispatch
* pdispIn
, LCID lcid
, double *pDblOut
)
3064 return _VarR8FromDisp(pdispIn
, lcid
, pDblOut
);
3067 /************************************************************************
3068 * VarR8FromBool (OLEAUT32.86)
3070 * Convert a VT_BOOL to a VT_R8.
3074 * pDblOut [O] Destination
3079 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double *pDblOut
)
3081 return _VarR8FromBool(boolIn
, pDblOut
);
3084 /************************************************************************
3085 * VarR8FromI1 (OLEAUT32.217)
3087 * Convert a VT_I1 to a VT_R8.
3091 * pDblOut [O] Destination
3095 * Failure: E_INVALIDARG, if the source value is invalid
3096 * DISP_E_OVERFLOW, if the value will not fit in the destination
3097 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3099 HRESULT WINAPI
VarR8FromI1(signed char cIn
, double *pDblOut
)
3101 return _VarR8FromI1(cIn
, pDblOut
);
3104 /************************************************************************
3105 * VarR8FromUI2 (OLEAUT32.218)
3107 * Convert a VT_UI2 to a VT_R8.
3111 * pDblOut [O] Destination
3115 * Failure: E_INVALIDARG, if the source value is invalid
3116 * DISP_E_OVERFLOW, if the value will not fit in the destination
3117 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3119 HRESULT WINAPI
VarR8FromUI2(USHORT usIn
, double *pDblOut
)
3121 return _VarR8FromUI2(usIn
, pDblOut
);
3124 /************************************************************************
3125 * VarR8FromUI4 (OLEAUT32.219)
3127 * Convert a VT_UI4 to a VT_R8.
3131 * pDblOut [O] Destination
3135 * Failure: E_INVALIDARG, if the source value is invalid
3136 * DISP_E_OVERFLOW, if the value will not fit in the destination
3137 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3139 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double *pDblOut
)
3141 return _VarR8FromUI4(ulIn
, pDblOut
);
3144 /************************************************************************
3145 * VarR8FromDec (OLEAUT32.220)
3147 * Convert a VT_DECIMAL to a VT_R8.
3151 * pDblOut [O] Destination
3155 * Failure: E_INVALIDARG, if the source value is invalid.
3157 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
3158 HRESULT WINAPI
VarR8FromDec(DECIMAL
* pDecIn
, double *pDblOut
)
3160 BYTE scale
= DEC_SCALE(pDecIn
);
3161 double divisor
= 1.0, highPart
;
3163 if (scale
> DEC_MAX_SCALE
|| DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
)
3164 return E_INVALIDARG
;
3169 if (DEC_SIGN(pDecIn
))
3172 if (DEC_HI32(pDecIn
))
3174 highPart
= (double)DEC_HI32(pDecIn
) / divisor
;
3180 *pDblOut
= (double)DEC_LO64(pDecIn
) / divisor
+ highPart
;
3185 /************************************************************************
3186 * VarR8FromI8 (OLEAUT32.362)
3188 * Convert a VT_I8 to a VT_R8.
3192 * pDblOut [O] Destination
3197 HRESULT WINAPI
VarR8FromI8(LONG64 llIn
, double *pDblOut
)
3199 return _VarR8FromI8(llIn
, pDblOut
);
3202 /************************************************************************
3203 * VarR8FromUI8 (OLEAUT32.363)
3205 * Convert a VT_UI8 to a VT_R8.
3209 * pDblOut [O] Destination
3214 HRESULT WINAPI
VarR8FromUI8(ULONG64 ullIn
, double *pDblOut
)
3216 return _VarR8FromUI8(ullIn
, pDblOut
);
3219 /************************************************************************
3220 * VarR8Pow (OLEAUT32.315)
3222 * Raise a VT_R8 to a power.
3225 * dblLeft [I] Source
3226 * dblPow [I] Power to raise dblLeft by
3227 * pDblOut [O] Destination
3230 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3232 HRESULT WINAPI
VarR8Pow(double dblLeft
, double dblPow
, double *pDblOut
)
3234 *pDblOut
= pow(dblLeft
, dblPow
);
3238 /************************************************************************
3239 * VarR8Round (OLEAUT32.317)
3241 * Round a VT_R8 to a given number of decimal points.
3245 * nDig [I] Number of decimal points to round to
3246 * pDblOut [O] Destination for rounded number
3249 * Success: S_OK. pDblOut is rounded to nDig digits.
3250 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3253 * The native version of this function rounds using the internal
3254 * binary representation of the number. Wine uses the dutch rounding
3255 * convention, so therefore small differences can occur in the value returned.
3256 * MSDN says that you should use your own rounding function if you want
3257 * rounding to be predictable in your application.
3259 HRESULT WINAPI
VarR8Round(double dblIn
, int nDig
, double *pDblOut
)
3261 double scale
, whole
, fract
;
3264 return E_INVALIDARG
;
3266 scale
= pow(10.0, nDig
);
3269 whole
= dblIn
< 0 ? ceil(dblIn
) : floor(dblIn
);
3270 fract
= dblIn
- whole
;
3273 dblIn
= whole
+ 1.0;
3274 else if (fract
== 0.5)
3275 dblIn
= whole
+ fmod(whole
, 2.0);
3276 else if (fract
>= 0.0)
3278 else if (fract
== -0.5)
3279 dblIn
= whole
- fmod(whole
, 2.0);
3280 else if (fract
> -0.5)
3283 dblIn
= whole
- 1.0;
3285 *pDblOut
= dblIn
/ scale
;
3292 /* Powers of 10 from 0..4 D.P. */
3293 static const int CY_Divisors
[5] = { CY_MULTIPLIER
/10000, CY_MULTIPLIER
/1000,
3294 CY_MULTIPLIER
/100, CY_MULTIPLIER
/10, CY_MULTIPLIER
};
3296 /************************************************************************
3297 * VarCyFromUI1 (OLEAUT32.98)
3299 * Convert a VT_UI1 to a VT_CY.
3303 * pCyOut [O] Destination
3307 * Failure: E_INVALIDARG, if the source value is invalid
3308 * DISP_E_OVERFLOW, if the value will not fit in the destination
3309 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3311 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pCyOut
)
3313 return _VarCyFromUI1(bIn
, pCyOut
);
3316 /************************************************************************
3317 * VarCyFromI2 (OLEAUT32.99)
3319 * Convert a VT_I2 to a VT_CY.
3323 * pCyOut [O] Destination
3327 * Failure: E_INVALIDARG, if the source value is invalid
3328 * DISP_E_OVERFLOW, if the value will not fit in the destination
3329 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3331 HRESULT WINAPI
VarCyFromI2(SHORT sIn
, CY
* pCyOut
)
3333 return _VarCyFromI2(sIn
, pCyOut
);
3336 /************************************************************************
3337 * VarCyFromI4 (OLEAUT32.100)
3339 * Convert a VT_I4 to a VT_CY.
3343 * pCyOut [O] Destination
3347 * Failure: E_INVALIDARG, if the source value is invalid
3348 * DISP_E_OVERFLOW, if the value will not fit in the destination
3349 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3351 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pCyOut
)
3353 return _VarCyFromI4(lIn
, pCyOut
);
3356 /************************************************************************
3357 * VarCyFromR4 (OLEAUT32.101)
3359 * Convert a VT_R4 to a VT_CY.
3363 * pCyOut [O] Destination
3367 * Failure: E_INVALIDARG, if the source value is invalid
3368 * DISP_E_OVERFLOW, if the value will not fit in the destination
3369 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3371 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pCyOut
)
3373 return _VarCyFromR4(fltIn
, pCyOut
);
3376 /************************************************************************
3377 * VarCyFromR8 (OLEAUT32.102)
3379 * Convert a VT_R8 to a VT_CY.
3383 * pCyOut [O] Destination
3387 * Failure: E_INVALIDARG, if the source value is invalid
3388 * DISP_E_OVERFLOW, if the value will not fit in the destination
3389 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3391 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pCyOut
)
3393 #if defined(__GNUC__) && defined(__i386__)
3394 /* This code gives identical results to Win32 on Intel.
3395 * Here we use fp exceptions to catch overflows when storing the value.
3397 static const unsigned short r8_fpcontrol
= 0x137f;
3398 static const double r8_multiplier
= CY_MULTIPLIER_F
;
3399 unsigned short old_fpcontrol
, result_fpstatus
;
3401 /* Clear exceptions, save the old fp state and load the new state */
3402 __asm__
__volatile__( "fnclex" );
3403 __asm__
__volatile__( "fstcw %0" : "=m" (old_fpcontrol
) : );
3404 __asm__
__volatile__( "fldcw %0" : : "m" (r8_fpcontrol
) );
3405 /* Perform the conversion. */
3406 __asm__
__volatile__( "fldl %0" : : "m" (dblIn
) );
3407 __asm__
__volatile__( "fmull %0" : : "m" (r8_multiplier
) );
3408 __asm__
__volatile__( "fistpll %0" : : "m" (*pCyOut
) );
3409 /* Save the resulting fp state, load the old state and clear exceptions */
3410 __asm__
__volatile__( "fstsw %0" : "=m" (result_fpstatus
) : );
3411 __asm__
__volatile__( "fnclex" );
3412 __asm__
__volatile__( "fldcw %0" : : "m" (old_fpcontrol
) );
3414 if (result_fpstatus
& 0x9) /* Overflow | Invalid */
3415 return DISP_E_OVERFLOW
;
3418 /* This version produces slightly different results for boundary cases */
3419 if (dblIn
< -922337203685477.5807 || dblIn
>= 922337203685477.5807)
3420 return DISP_E_OVERFLOW
;
3421 dblIn
*= CY_MULTIPLIER_F
;
3422 OLEAUT32_DutchRound(LONG64
, dblIn
, pCyOut
->int64
);
3427 /************************************************************************
3428 * VarCyFromDate (OLEAUT32.103)
3430 * Convert a VT_DATE to a VT_CY.
3434 * pCyOut [O] Destination
3438 * Failure: E_INVALIDARG, if the source value is invalid
3439 * DISP_E_OVERFLOW, if the value will not fit in the destination
3440 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3442 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pCyOut
)
3444 return _VarCyFromDate(dateIn
, pCyOut
);
3447 /************************************************************************
3448 * VarCyFromStr (OLEAUT32.104)
3450 * Convert a VT_BSTR to a VT_CY.
3454 * lcid [I] LCID for the conversion
3455 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3456 * pCyOut [O] Destination
3460 * Failure: E_INVALIDARG, if the source value is invalid
3461 * DISP_E_OVERFLOW, if the value will not fit in the destination
3462 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3464 HRESULT WINAPI
VarCyFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CY
* pCyOut
)
3466 return _VarCyFromStr(strIn
, lcid
, dwFlags
, pCyOut
);
3469 /************************************************************************
3470 * VarCyFromDisp (OLEAUT32.105)
3472 * Convert a VT_DISPATCH to a VT_CY.
3475 * pdispIn [I] Source
3476 * lcid [I] LCID for conversion
3477 * pCyOut [O] Destination
3481 * Failure: E_INVALIDARG, if the source value is invalid
3482 * DISP_E_OVERFLOW, if the value will not fit in the destination
3483 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3485 HRESULT WINAPI
VarCyFromDisp(IDispatch
* pdispIn
, LCID lcid
, CY
* pCyOut
)
3487 return _VarCyFromDisp(pdispIn
, lcid
, pCyOut
);
3491 /************************************************************************
3492 * VarCyFromBool (OLEAUT32.106)
3494 * Convert a VT_BOOL to a VT_CY.
3498 * pCyOut [O] Destination
3502 * Failure: E_INVALIDARG, if the source value is invalid
3503 * DISP_E_OVERFLOW, if the value will not fit in the destination
3504 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3507 * While the sign of the boolean is stored in the currency, the value is
3508 * converted to either 0 or 1.
3510 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pCyOut
)
3512 return _VarCyFromBool(boolIn
, pCyOut
);
3515 /************************************************************************
3516 * VarCyFromI1 (OLEAUT32.225)
3518 * Convert a VT_I1 to a VT_CY.
3522 * pCyOut [O] Destination
3526 * Failure: E_INVALIDARG, if the source value is invalid
3527 * DISP_E_OVERFLOW, if the value will not fit in the destination
3528 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3530 HRESULT WINAPI
VarCyFromI1(signed char cIn
, CY
* pCyOut
)
3532 return _VarCyFromI1(cIn
, pCyOut
);
3535 /************************************************************************
3536 * VarCyFromUI2 (OLEAUT32.226)
3538 * Convert a VT_UI2 to a VT_CY.
3542 * pCyOut [O] Destination
3546 * Failure: E_INVALIDARG, if the source value is invalid
3547 * DISP_E_OVERFLOW, if the value will not fit in the destination
3548 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3550 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pCyOut
)
3552 return _VarCyFromUI2(usIn
, pCyOut
);
3555 /************************************************************************
3556 * VarCyFromUI4 (OLEAUT32.227)
3558 * Convert a VT_UI4 to a VT_CY.
3562 * pCyOut [O] Destination
3566 * Failure: E_INVALIDARG, if the source value is invalid
3567 * DISP_E_OVERFLOW, if the value will not fit in the destination
3568 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3570 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pCyOut
)
3572 return _VarCyFromUI4(ulIn
, pCyOut
);
3575 /************************************************************************
3576 * VarCyFromDec (OLEAUT32.228)
3578 * Convert a VT_DECIMAL to a VT_CY.
3582 * pCyOut [O] Destination
3586 * Failure: E_INVALIDARG, if the source value is invalid
3587 * DISP_E_OVERFLOW, if the value will not fit in the destination
3588 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3590 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
3591 HRESULT WINAPI
VarCyFromDec(DECIMAL
* pdecIn
, CY
* pCyOut
)
3596 hRet
= VarDecRound(pdecIn
, 4, &rounded
);
3598 if (SUCCEEDED(hRet
))
3602 if (DEC_HI32(&rounded
))
3603 return DISP_E_OVERFLOW
;
3605 /* Note: Without the casts this promotes to int64 which loses precision */
3606 d
= (double)DEC_LO64(&rounded
) / (double)CY_Divisors
[DEC_SCALE(&rounded
)];
3607 if (DEC_SIGN(&rounded
))
3609 return _VarCyFromR8(d
, pCyOut
);
3615 /************************************************************************
3616 * VarCyFromI8 (OLEAUT32.366)
3618 * Convert a VT_I8 to a VT_CY.
3622 * pCyOut [O] Destination
3626 * Failure: E_INVALIDARG, if the source value is invalid
3627 * DISP_E_OVERFLOW, if the value will not fit in the destination
3628 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3630 HRESULT WINAPI
VarCyFromI8(LONG64 llIn
, CY
* pCyOut
)
3632 return _VarCyFromI8(llIn
, pCyOut
);
3635 /************************************************************************
3636 * VarCyFromUI8 (OLEAUT32.375)
3638 * Convert a VT_UI8 to a VT_CY.
3642 * pCyOut [O] Destination
3646 * Failure: E_INVALIDARG, if the source value is invalid
3647 * DISP_E_OVERFLOW, if the value will not fit in the destination
3648 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3650 HRESULT WINAPI
VarCyFromUI8(ULONG64 ullIn
, CY
* pCyOut
)
3652 return _VarCyFromUI8(ullIn
, pCyOut
);
3655 /************************************************************************
3656 * VarCyAdd (OLEAUT32.299)
3658 * Add one CY to another.
3662 * cyRight [I] Value to add
3663 * pCyOut [O] Destination
3667 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3669 HRESULT WINAPI
VarCyAdd(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3672 _VarR8FromCy(cyLeft
, &l
);
3673 _VarR8FromCy(cyRight
, &r
);
3675 return _VarCyFromR8(l
, pCyOut
);
3678 /************************************************************************
3679 * VarCyMul (OLEAUT32.303)
3681 * Multiply one CY by another.
3685 * cyRight [I] Value to multiply by
3686 * pCyOut [O] Destination
3690 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3692 HRESULT WINAPI
VarCyMul(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3695 _VarR8FromCy(cyLeft
, &l
);
3696 _VarR8FromCy(cyRight
, &r
);
3698 return _VarCyFromR8(l
, pCyOut
);
3701 /************************************************************************
3702 * VarCyMulI4 (OLEAUT32.304)
3704 * Multiply one CY by a VT_I4.
3708 * lRight [I] Value to multiply by
3709 * pCyOut [O] Destination
3713 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3715 HRESULT WINAPI
VarCyMulI4(const CY cyLeft
, LONG lRight
, CY
* pCyOut
)
3719 _VarR8FromCy(cyLeft
, &d
);
3721 return _VarCyFromR8(d
, pCyOut
);
3724 /************************************************************************
3725 * VarCySub (OLEAUT32.305)
3727 * Subtract one CY from another.
3731 * cyRight [I] Value to subtract
3732 * pCyOut [O] Destination
3736 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3738 HRESULT WINAPI
VarCySub(const CY cyLeft
, const CY cyRight
, CY
* pCyOut
)
3741 _VarR8FromCy(cyLeft
, &l
);
3742 _VarR8FromCy(cyRight
, &r
);
3744 return _VarCyFromR8(l
, pCyOut
);
3747 /************************************************************************
3748 * VarCyAbs (OLEAUT32.306)
3750 * Convert a VT_CY into its absolute value.
3754 * pCyOut [O] Destination
3757 * Success: S_OK. pCyOut contains the absolute value.
3758 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3760 HRESULT WINAPI
VarCyAbs(const CY cyIn
, CY
* pCyOut
)
3762 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3763 return DISP_E_OVERFLOW
;
3765 pCyOut
->int64
= cyIn
.int64
< 0 ? -cyIn
.int64
: cyIn
.int64
;
3769 /************************************************************************
3770 * VarCyFix (OLEAUT32.307)
3772 * Return the integer part of a VT_CY.
3776 * pCyOut [O] Destination
3780 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3783 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3784 * negative numbers away from 0, while this function rounds them towards zero.
3786 HRESULT WINAPI
VarCyFix(const CY cyIn
, CY
* pCyOut
)
3788 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3789 pCyOut
->int64
*= CY_MULTIPLIER
;
3793 /************************************************************************
3794 * VarCyInt (OLEAUT32.308)
3796 * Return the integer part of a VT_CY.
3800 * pCyOut [O] Destination
3804 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3807 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3808 * negative numbers towards 0, while this function rounds them away from zero.
3810 HRESULT WINAPI
VarCyInt(const CY cyIn
, CY
* pCyOut
)
3812 pCyOut
->int64
= cyIn
.int64
/ CY_MULTIPLIER
;
3813 pCyOut
->int64
*= CY_MULTIPLIER
;
3815 if (cyIn
.int64
< 0 && cyIn
.int64
% CY_MULTIPLIER
!= 0)
3817 pCyOut
->int64
-= CY_MULTIPLIER
;
3822 /************************************************************************
3823 * VarCyNeg (OLEAUT32.309)
3825 * Change the sign of a VT_CY.
3829 * pCyOut [O] Destination
3833 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3835 HRESULT WINAPI
VarCyNeg(const CY cyIn
, CY
* pCyOut
)
3837 if (cyIn
.s
.Hi
== (int)0x80000000 && !cyIn
.s
.Lo
)
3838 return DISP_E_OVERFLOW
;
3840 pCyOut
->int64
= -cyIn
.int64
;
3844 /************************************************************************
3845 * VarCyRound (OLEAUT32.310)
3847 * Change the precision of a VT_CY.
3851 * cDecimals [I] New number of decimals to keep
3852 * pCyOut [O] Destination
3856 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3858 HRESULT WINAPI
VarCyRound(const CY cyIn
, int cDecimals
, CY
* pCyOut
)
3861 return E_INVALIDARG
;
3865 /* Rounding to more precision than we have */
3871 double d
, div
= CY_Divisors
[cDecimals
];
3873 _VarR8FromCy(cyIn
, &d
);
3875 OLEAUT32_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3876 d
= (double)pCyOut
->int64
/ div
* CY_MULTIPLIER_F
;
3877 OLEAUT32_DutchRound(LONGLONG
, d
, pCyOut
->int64
)
3882 /************************************************************************
3883 * VarCyCmp (OLEAUT32.311)
3885 * Compare two VT_CY values.
3889 * cyRight [I] Value to compare
3892 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
3893 * compare is less, equal or greater than source respectively.
3894 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3896 HRESULT WINAPI
VarCyCmp(const CY cyLeft
, const CY cyRight
)
3901 /* Subtract right from left, and compare the result to 0 */
3902 hRet
= VarCySub(cyLeft
, cyRight
, &result
);
3904 if (SUCCEEDED(hRet
))
3906 if (result
.int64
< 0)
3907 hRet
= (HRESULT
)VARCMP_LT
;
3908 else if (result
.int64
> 0)
3909 hRet
= (HRESULT
)VARCMP_GT
;
3911 hRet
= (HRESULT
)VARCMP_EQ
;
3916 /************************************************************************
3917 * VarCyCmpR8 (OLEAUT32.312)
3919 * Compare a VT_CY to a double
3922 * cyLeft [I] Currency Source
3923 * dblRight [I] double to compare to cyLeft
3926 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
3927 * less than, equal to or greater than cyLeft respectively.
3928 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3930 HRESULT WINAPI
VarCyCmpR8(const CY cyLeft
, double dblRight
)
3935 hRet
= _VarCyFromR8(dblRight
, &cyRight
);
3937 if (SUCCEEDED(hRet
))
3938 hRet
= VarCyCmp(cyLeft
, cyRight
);
3943 /************************************************************************
3944 * VarCyMulI8 (OLEAUT32.329)
3946 * Multiply a VT_CY by a VT_I8.
3950 * llRight [I] Value to multiply by
3951 * pCyOut [O] Destination
3955 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3957 HRESULT WINAPI
VarCyMulI8(const CY cyLeft
, LONG64 llRight
, CY
* pCyOut
)
3961 _VarR8FromCy(cyLeft
, &d
);
3962 d
= d
* (double)llRight
;
3963 return _VarCyFromR8(d
, pCyOut
);
3969 /************************************************************************
3970 * VarDecFromUI1 (OLEAUT32.190)
3972 * Convert a VT_UI1 to a DECIMAL.
3976 * pDecOut [O] Destination
3981 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
3982 HRESULT WINAPI
VarDecFromUI1(BYTE bIn
, DECIMAL
* pDecOut
)
3984 return _VarDecFromUI1(bIn
, pDecOut
);
3987 /************************************************************************
3988 * VarDecFromI2 (OLEAUT32.191)
3990 * Convert a VT_I2 to a DECIMAL.
3994 * pDecOut [O] Destination
3999 HRESULT WINAPI
VarDecFromI2(SHORT sIn
, DECIMAL
* pDecOut
)
4001 return _VarDecFromI2(sIn
, pDecOut
);
4005 /************************************************************************
4006 * VarDecFromI4 (OLEAUT32.192)
4008 * Convert a VT_I4 to a DECIMAL.
4012 * pDecOut [O] Destination
4017 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
4018 HRESULT WINAPI
VarDecFromI4(LONG lIn
, DECIMAL
* pDecOut
)
4020 DEC_HI32(pDecOut
) = 0;
4021 DEC_MID32(pDecOut
) = 0;
4025 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4026 DEC_LO32(pDecOut
) = -lIn
;
4030 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4031 DEC_LO32(pDecOut
) = lIn
;
4037 /************************************************************************
4038 * VarDecFromR4 (OLEAUT32.193)
4040 * Convert a VT_R4 to a DECIMAL.
4044 * pDecOut [O] Destination
4049 HRESULT WINAPI
VarDecFromR4(FLOAT fltIn
, DECIMAL
* pDecOut
)
4053 sprintfW( buff
, szFloatFormatW
, fltIn
);
4054 return _VarDecFromStr(buff
, LOCALE_SYSTEM_DEFAULT
, 0, pDecOut
);
4057 /************************************************************************
4058 * VarDecFromR8 (OLEAUT32.194)
4060 * Convert a VT_R8 to a DECIMAL.
4064 * pDecOut [O] Destination
4069 HRESULT WINAPI
VarDecFromR8(double dblIn
, DECIMAL
* pDecOut
)
4073 sprintfW( buff
, szDoubleFormatW
, dblIn
);
4074 return _VarDecFromStr(buff
, LOCALE_USER_DEFAULT
, 0, pDecOut
);
4077 /************************************************************************
4078 * VarDecFromDate (OLEAUT32.195)
4080 * Convert a VT_DATE to a DECIMAL.
4084 * pDecOut [O] Destination
4089 HRESULT WINAPI
VarDecFromDate(DATE dateIn
, DECIMAL
* pDecOut
)
4091 return _VarDecFromDate(dateIn
, pDecOut
);
4094 /************************************************************************
4095 * VarDecFromCy (OLEAUT32.196)
4097 * Convert a VT_CY to a DECIMAL.
4101 * pDecOut [O] Destination
4106 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4107 HRESULT WINAPI
VarDecFromCy(CY cyIn
, DECIMAL
* pDecOut
)
4109 DEC_HI32(pDecOut
) = 0;
4111 /* Note: This assumes 2s complement integer representation */
4112 if (cyIn
.s
.Hi
& 0x80000000)
4114 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,4);
4115 DEC_LO64(pDecOut
) = -cyIn
.int64
;
4119 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,4);
4120 DEC_MID32(pDecOut
) = cyIn
.s
.Hi
;
4121 DEC_LO32(pDecOut
) = cyIn
.s
.Lo
;
4128 /************************************************************************
4129 * VarDecFromStr (OLEAUT32.197)
4131 * Convert a VT_BSTR to a DECIMAL.
4135 * lcid [I] LCID for the conversion
4136 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4137 * pDecOut [O] Destination
4141 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4143 HRESULT WINAPI
VarDecFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DECIMAL
* pDecOut
)
4145 return _VarDecFromStr(strIn
, lcid
, dwFlags
, pDecOut
);
4148 /************************************************************************
4149 * VarDecFromDisp (OLEAUT32.198)
4151 * Convert a VT_DISPATCH to a DECIMAL.
4154 * pdispIn [I] Source
4155 * lcid [I] LCID for conversion
4156 * pDecOut [O] Destination
4160 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4162 HRESULT WINAPI
VarDecFromDisp(IDispatch
* pdispIn
, LCID lcid
, DECIMAL
* pDecOut
)
4164 return _VarDecFromDisp(pdispIn
, lcid
, pDecOut
);
4167 /************************************************************************
4168 * VarDecFromBool (OLEAUT32.199)
4170 * Convert a VT_BOOL to a DECIMAL.
4174 * pDecOut [O] Destination
4180 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4182 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
4183 HRESULT WINAPI
VarDecFromBool(VARIANT_BOOL bIn
, DECIMAL
* pDecOut
)
4185 DEC_HI32(pDecOut
) = 0;
4186 DEC_MID32(pDecOut
) = 0;
4189 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4190 DEC_LO32(pDecOut
) = 1;
4194 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4195 DEC_LO32(pDecOut
) = 0;
4200 /************************************************************************
4201 * VarDecFromI1 (OLEAUT32.241)
4203 * Convert a VT_I1 to a DECIMAL.
4207 * pDecOut [O] Destination
4212 HRESULT WINAPI
VarDecFromI1(signed char cIn
, DECIMAL
* pDecOut
)
4214 return _VarDecFromI1(cIn
, pDecOut
);
4217 /************************************************************************
4218 * VarDecFromUI2 (OLEAUT32.242)
4220 * Convert a VT_UI2 to a DECIMAL.
4224 * pDecOut [O] Destination
4229 HRESULT WINAPI
VarDecFromUI2(USHORT usIn
, DECIMAL
* pDecOut
)
4231 return _VarDecFromUI2(usIn
, pDecOut
);
4235 /************************************************************************
4236 * VarDecFromUI4 (OLEAUT32.243)
4238 * Convert a VT_UI4 to a DECIMAL.
4242 * pDecOut [O] Destination
4247 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
4248 HRESULT WINAPI
VarDecFromUI4(ULONG ulIn
, DECIMAL
* pDecOut
)
4250 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4251 DEC_HI32(pDecOut
) = 0;
4252 DEC_MID32(pDecOut
) = 0;
4253 DEC_LO32(pDecOut
) = ulIn
;
4258 /************************************************************************
4259 * VarDecFromI8 (OLEAUT32.374)
4261 * Convert a VT_I8 to a DECIMAL.
4265 * pDecOut [O] Destination
4270 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4271 HRESULT WINAPI
VarDecFromI8(LONG64 llIn
, DECIMAL
* pDecOut
)
4273 PULARGE_INTEGER pLi
= (PULARGE_INTEGER
)&llIn
;
4275 DEC_HI32(pDecOut
) = 0;
4277 /* Note: This assumes 2s complement integer representation */
4278 if (pLi
->u
.HighPart
& 0x80000000)
4280 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_NEG
,0);
4281 DEC_LO64(pDecOut
) = -pLi
->QuadPart
;
4285 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4286 DEC_MID32(pDecOut
) = pLi
->u
.HighPart
;
4287 DEC_LO32(pDecOut
) = pLi
->u
.LowPart
;
4293 /************************************************************************
4294 * VarDecFromUI8 (OLEAUT32.375)
4296 * Convert a VT_UI8 to a DECIMAL.
4300 * pDecOut [O] Destination
4305 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4306 HRESULT WINAPI
VarDecFromUI8(ULONG64 ullIn
, DECIMAL
* pDecOut
)
4308 DEC_SIGNSCALE(pDecOut
) = SIGNSCALE(DECIMAL_POS
,0);
4309 DEC_HI32(pDecOut
) = 0;
4310 DEC_LO64(pDecOut
) = ullIn
;
4315 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4316 /* Make two DECIMALS the same scale; used by math functions below */
4317 static HRESULT
VARIANT_DecScale(const DECIMAL
** ppDecLeft
,
4318 const DECIMAL
** ppDecRight
,
4321 static DECIMAL scaleFactor
;
4324 HRESULT hRet
= S_OK
;
4326 if (DEC_SIGN(*ppDecLeft
) & ~DECIMAL_NEG
|| DEC_SIGN(*ppDecRight
) & ~DECIMAL_NEG
)
4327 return E_INVALIDARG
;
4329 DEC_LO32(&scaleFactor
) = 10;
4331 i
= scaleAmount
= DEC_SCALE(*ppDecLeft
) - DEC_SCALE(*ppDecRight
);
4334 return S_OK
; /* Same scale */
4336 if (scaleAmount
> 0)
4338 decTemp
= *(*ppDecRight
); /* Left is bigger - scale the right hand side */
4339 *ppDecRight
= pDecOut
;
4343 decTemp
= *(*ppDecLeft
); /* Right is bigger - scale the left hand side */
4344 *ppDecLeft
= pDecOut
;
4345 i
= scaleAmount
= -scaleAmount
;
4348 if (DEC_SCALE(&decTemp
) + scaleAmount
> DEC_MAX_SCALE
)
4349 return DISP_E_OVERFLOW
; /* Can't scale up */
4351 /* Multiply up the value to be scaled by the correct amount */
4352 while (SUCCEEDED(hRet
) && i
--)
4354 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4355 hRet
= VarDecMul(&decTemp
, &scaleFactor
, pDecOut
);
4358 DEC_SCALE(pDecOut
) += scaleAmount
; /* Set the new scale */
4363 /* Add two unsigned 32 bit values with overflow */
4364 static ULONG
VARIANT_Add(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4366 ULARGE_INTEGER ul64
;
4368 ul64
.QuadPart
= (ULONG64
)ulLeft
+ (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4369 *pulHigh
= ul64
.u
.HighPart
;
4370 return ul64
.u
.LowPart
;
4373 /* Subtract two unsigned 32 bit values with underflow */
4374 static ULONG
VARIANT_Sub(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4377 ULARGE_INTEGER ul64
;
4379 ul64
.QuadPart
= (LONG64
)ulLeft
- (ULONG64
)ulRight
;
4380 if (ulLeft
< ulRight
)
4383 if (ul64
.QuadPart
> (ULONG64
)*pulHigh
)
4384 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4387 ul64
.QuadPart
-= (ULONG64
)*pulHigh
;
4391 ul64
.u
.HighPart
= -ul64
.u
.HighPart
;
4393 *pulHigh
= ul64
.u
.HighPart
;
4394 return ul64
.u
.LowPart
;
4397 /* Multiply two unsigned 32 bit values with overflow */
4398 static ULONG
VARIANT_Mul(ULONG ulLeft
, ULONG ulRight
, ULONG
* pulHigh
)
4400 ULARGE_INTEGER ul64
;
4402 ul64
.QuadPart
= (ULONG64
)ulLeft
* (ULONG64
)ulRight
+ (ULONG64
)*pulHigh
;
4403 *pulHigh
= ul64
.u
.HighPart
;
4404 return ul64
.u
.LowPart
;
4407 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4408 /* Compare two decimals that have the same scale */
4409 static inline int VARIANT_DecCmp(const DECIMAL
*pDecLeft
, const DECIMAL
*pDecRight
)
4411 if ( DEC_HI32(pDecLeft
) < DEC_HI32(pDecRight
) ||
4412 (DEC_HI32(pDecLeft
) <= DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) < DEC_LO64(pDecRight
)))
4414 else if (DEC_HI32(pDecLeft
) == DEC_HI32(pDecRight
) && DEC_LO64(pDecLeft
) == DEC_LO64(pDecRight
))
4420 /************************************************************************
4421 * VarDecAdd (OLEAUT32.177)
4423 * Add one DECIMAL to another.
4426 * pDecLeft [I] Source
4427 * pDecRight [I] Value to add
4428 * pDecOut [O] Destination
4432 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4434 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4435 HRESULT WINAPI
VarDecAdd(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4440 hRet
= VARIANT_DecScale(&pDecLeft
, &pDecRight
, &scaled
);
4442 if (SUCCEEDED(hRet
))
4444 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4446 BYTE sign
= DECIMAL_POS
;
4448 /* Correct for the sign of the result */
4449 if (DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4451 /* -x + -y : Negative */
4453 goto VarDecAdd_AsPositive
;
4455 else if (DEC_SIGN(pDecLeft
) && !DEC_SIGN(pDecRight
))
4457 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4459 /* -x + y : Negative if x > y */
4463 VarDecAdd_AsNegative
:
4464 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4465 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4466 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4470 VarDecAdd_AsInvertedNegative
:
4471 DEC_LO32(pDecOut
) = VARIANT_Sub(DEC_LO32(pDecRight
), DEC_LO32(pDecLeft
), &overflow
);
4472 DEC_MID32(pDecOut
) = VARIANT_Sub(DEC_MID32(pDecRight
), DEC_MID32(pDecLeft
), &overflow
);
4473 DEC_HI32(pDecOut
) = VARIANT_Sub(DEC_HI32(pDecRight
), DEC_HI32(pDecLeft
), &overflow
);
4476 else if (!DEC_SIGN(pDecLeft
) && DEC_SIGN(pDecRight
))
4478 int cmp
= VARIANT_DecCmp(pDecLeft
, pDecRight
);
4480 /* x + -y : Negative if x <= y */
4484 goto VarDecAdd_AsInvertedNegative
;
4486 goto VarDecAdd_AsNegative
;
4490 /* x + y : Positive */
4491 VarDecAdd_AsPositive
:
4492 DEC_LO32(pDecOut
) = VARIANT_Add(DEC_LO32(pDecLeft
), DEC_LO32(pDecRight
), &overflow
);
4493 DEC_MID32(pDecOut
) = VARIANT_Add(DEC_MID32(pDecLeft
), DEC_MID32(pDecRight
), &overflow
);
4494 DEC_HI32(pDecOut
) = VARIANT_Add(DEC_HI32(pDecLeft
), DEC_HI32(pDecRight
), &overflow
);
4498 return DISP_E_OVERFLOW
; /* overflowed */
4500 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecLeft
);
4501 DEC_SIGN(pDecOut
) = sign
;
4507 /************************************************************************
4508 * VarDecDiv (OLEAUT32.178)
4510 * Divide one DECIMAL by another.
4513 * pDecLeft [I] Source
4514 * pDecRight [I] Value to divide by
4515 * pDecOut [O] Destination
4519 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4521 HRESULT WINAPI
VarDecDiv(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4523 FIXME("(%p,%p,%p)-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4524 return DISP_E_OVERFLOW
;
4527 /************************************************************************
4528 * VarDecMul (OLEAUT32.179)
4530 * Multiply one DECIMAL by another.
4533 * pDecLeft [I] Source
4534 * pDecRight [I] Value to multiply by
4535 * pDecOut [O] Destination
4539 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4541 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4542 HRESULT WINAPI
VarDecMul(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4544 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4546 if (!DEC_SCALE(pDecLeft
) || !DEC_SCALE(pDecRight
))
4548 /* At least one term is an integer */
4549 const DECIMAL
* pDecInteger
= DEC_SCALE(pDecLeft
) ? pDecRight
: pDecLeft
;
4550 const DECIMAL
* pDecOperand
= DEC_SCALE(pDecLeft
) ? pDecLeft
: pDecRight
;
4551 HRESULT hRet
= S_OK
;
4552 unsigned int multiplier
= DEC_LO32(pDecInteger
);
4555 if (DEC_HI32(pDecInteger
) || DEC_MID32(pDecInteger
))
4557 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4558 return DISP_E_OVERFLOW
;
4561 DEC_LO32(pDecOut
) = VARIANT_Mul(DEC_LO32(pDecOperand
), multiplier
, &overflow
);
4562 DEC_MID32(pDecOut
) = VARIANT_Mul(DEC_MID32(pDecOperand
), multiplier
, &overflow
);
4563 DEC_HI32(pDecOut
) = VARIANT_Mul(DEC_HI32(pDecOperand
), multiplier
, &overflow
);
4566 hRet
= DISP_E_OVERFLOW
;
4569 BYTE sign
= DECIMAL_POS
;
4571 if (DEC_SIGN(pDecLeft
) != DEC_SIGN(pDecRight
))
4572 sign
= DECIMAL_NEG
; /* pos * neg => negative */
4573 DEC_SIGN(pDecOut
) = sign
;
4574 DEC_SCALE(pDecOut
) = DEC_SCALE(pDecOperand
);
4578 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft
,pDecRight
,pDecOut
);
4579 return DISP_E_OVERFLOW
;
4582 /************************************************************************
4583 * VarDecSub (OLEAUT32.181)
4585 * Subtract one DECIMAL from another.
4588 * pDecLeft [I] Source
4589 * pDecRight [I] DECIMAL to subtract from pDecLeft
4590 * pDecOut [O] Destination
4593 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4595 HRESULT WINAPI
VarDecSub(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
, DECIMAL
* pDecOut
)
4599 /* Implement as addition of the negative */
4600 VarDecNeg(pDecRight
, &decRight
);
4601 return VarDecAdd(pDecLeft
, &decRight
, pDecOut
);
4605 /************************************************************************
4606 * VarDecAbs (OLEAUT32.182)
4608 * Convert a DECIMAL into its absolute value.
4612 * pDecOut [O] Destination
4615 * S_OK. This function does not fail.
4617 HRESULT WINAPI
VarDecAbs(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4620 DEC_SIGN(pDecOut
) &= ~DECIMAL_NEG
;
4624 /************************************************************************
4625 * VarDecFix (OLEAUT32.187)
4627 * Return the integer portion of a DECIMAL.
4631 * pDecOut [O] Destination
4635 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4638 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4639 * negative numbers away from 0, while this function rounds them towards zero.
4641 HRESULT WINAPI
VarDecFix(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4643 if (DEC_SIGN(pDecOut
) & ~DECIMAL_NEG
)
4644 return E_INVALIDARG
;
4646 if (!DEC_SCALE(pDecIn
))
4648 *pDecOut
= *pDecIn
; /* Already an integer */
4652 FIXME("semi-stub!\n");
4653 return DISP_E_OVERFLOW
;
4656 /************************************************************************
4657 * VarDecInt (OLEAUT32.188)
4659 * Return the integer portion of a DECIMAL.
4663 * pDecOut [O] Destination
4667 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4670 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4671 * negative numbers towards 0, while this function rounds them away from zero.
4673 HRESULT WINAPI
VarDecInt(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4675 if (DEC_SIGN(pDecOut
) & ~DECIMAL_NEG
)
4676 return E_INVALIDARG
;
4678 if (!(DEC_SIGN(pDecOut
) & DECIMAL_NEG
) || !DEC_SCALE(pDecIn
))
4679 return VarDecFix(pDecIn
, pDecOut
); /* The same, if +ve or no fractionals */
4681 FIXME("semi-stub!\n");
4682 return DISP_E_OVERFLOW
;
4685 /************************************************************************
4686 * VarDecNeg (OLEAUT32.189)
4688 * Change the sign of a DECIMAL.
4692 * pDecOut [O] Destination
4695 * S_OK. This function does not fail.
4697 HRESULT WINAPI
VarDecNeg(const DECIMAL
* pDecIn
, DECIMAL
* pDecOut
)
4700 DEC_SIGN(pDecOut
) ^= DECIMAL_NEG
;
4704 /************************************************************************
4705 * VarDecRound (OLEAUT32.203)
4707 * Change the precision of a DECIMAL.
4711 * cDecimals [I] New number of decimals to keep
4712 * pDecOut [O] Destination
4715 * Success: S_OK. pDecOut contains the rounded value.
4716 * Failure: E_INVALIDARG if any argument is invalid.
4718 HRESULT WINAPI
VarDecRound(const DECIMAL
* pDecIn
, int cDecimals
, DECIMAL
* pDecOut
)
4720 if (cDecimals
< 0 || (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
) || DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
)
4721 return E_INVALIDARG
;
4723 if (cDecimals
>= DEC_SCALE(pDecIn
))
4725 *pDecOut
= *pDecIn
; /* More precision than we have */
4729 FIXME("semi-stub!\n");
4731 return DISP_E_OVERFLOW
;
4734 /************************************************************************
4735 * VarDecCmp (OLEAUT32.204)
4737 * Compare two DECIMAL values.
4740 * pDecLeft [I] Source
4741 * pDecRight [I] Value to compare
4744 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4745 * is less than, equal to or greater than pDecRight respectively.
4746 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4748 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4749 HRESULT WINAPI
VarDecCmp(const DECIMAL
* pDecLeft
, const DECIMAL
* pDecRight
)
4754 /* Subtract right from left, and compare the result to 0 */
4755 hRet
= VarDecSub(pDecLeft
, pDecRight
, &result
);
4757 if (SUCCEEDED(hRet
))
4759 int non_zero
= DEC_HI32(&result
) | DEC_MID32(&result
) | DEC_LO32(&result
);
4761 if ((DEC_SIGN(&result
) & DECIMAL_NEG
) && non_zero
)
4762 hRet
= (HRESULT
)VARCMP_LT
;
4764 hRet
= (HRESULT
)VARCMP_GT
;
4766 hRet
= (HRESULT
)VARCMP_EQ
;
4772 /************************************************************************
4773 * VarDecCmpR8 (OLEAUT32.298)
4775 * Compare a DECIMAL to a double
4778 * pDecLeft [I] DECIMAL Source
4779 * dblRight [I] double to compare to pDecLeft
4782 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4783 * is less than, equal to or greater than pDecLeft respectively.
4784 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4786 HRESULT WINAPI
VarDecCmpR8(const DECIMAL
* pDecLeft
, double dblRight
)
4791 hRet
= VarDecFromR8(dblRight
, &decRight
);
4793 if (SUCCEEDED(hRet
))
4794 hRet
= VarDecCmp(pDecLeft
, &decRight
);
4803 /************************************************************************
4804 * VarBoolFromUI1 (OLEAUT32.118)
4806 * Convert a VT_UI1 to a VT_BOOL.
4810 * pBoolOut [O] Destination
4815 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
*pBoolOut
)
4817 return _VarBoolFromUI1(bIn
, pBoolOut
);
4820 /************************************************************************
4821 * VarBoolFromI2 (OLEAUT32.119)
4823 * Convert a VT_I2 to a VT_BOOL.
4827 * pBoolOut [O] Destination
4832 HRESULT WINAPI
VarBoolFromI2(SHORT sIn
, VARIANT_BOOL
*pBoolOut
)
4834 return _VarBoolFromI2(sIn
, pBoolOut
);
4837 /************************************************************************
4838 * VarBoolFromI4 (OLEAUT32.120)
4840 * Convert a VT_I4 to a VT_BOOL.
4844 * pBoolOut [O] Destination
4849 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
*pBoolOut
)
4851 return _VarBoolFromI4(lIn
, pBoolOut
);
4854 /************************************************************************
4855 * VarBoolFromR4 (OLEAUT32.121)
4857 * Convert a VT_R4 to a VT_BOOL.
4861 * pBoolOut [O] Destination
4866 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
*pBoolOut
)
4868 return _VarBoolFromR4(fltIn
, pBoolOut
);
4871 /************************************************************************
4872 * VarBoolFromR8 (OLEAUT32.122)
4874 * Convert a VT_R8 to a VT_BOOL.
4878 * pBoolOut [O] Destination
4883 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
*pBoolOut
)
4885 return _VarBoolFromR8(dblIn
, pBoolOut
);
4888 /************************************************************************
4889 * VarBoolFromDate (OLEAUT32.123)
4891 * Convert a VT_DATE to a VT_BOOL.
4895 * pBoolOut [O] Destination
4900 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
*pBoolOut
)
4902 return _VarBoolFromDate(dateIn
, pBoolOut
);
4905 /************************************************************************
4906 * VarBoolFromCy (OLEAUT32.124)
4908 * Convert a VT_CY to a VT_BOOL.
4912 * pBoolOut [O] Destination
4917 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
*pBoolOut
)
4919 return _VarBoolFromCy(cyIn
, pBoolOut
);
4922 static BOOL
VARIANT_GetLocalisedText(LANGID langId
, DWORD dwId
, WCHAR
*lpszDest
)
4926 hrsrc
= FindResourceExW( OLEAUT32_hModule
, (LPWSTR
)RT_STRING
,
4927 (LPCWSTR
)((dwId
>> 4) + 1), langId
);
4930 HGLOBAL hmem
= LoadResource( OLEAUT32_hModule
, hrsrc
);
4937 p
= LockResource( hmem
);
4938 for (i
= 0; i
< (dwId
& 0x0f); i
++) p
+= *p
+ 1;
4940 memcpy( lpszDest
, p
+ 1, *p
* sizeof(WCHAR
) );
4941 lpszDest
[*p
] = '\0';
4942 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest
), langId
);
4949 /************************************************************************
4950 * VarBoolFromStr (OLEAUT32.125)
4952 * Convert a VT_BSTR to a VT_BOOL.
4956 * lcid [I] LCID for the conversion
4957 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4958 * pBoolOut [O] Destination
4962 * Failure: E_INVALIDARG, if pBoolOut is invalid.
4963 * DISP_E_TYPEMISMATCH, if the type cannot be converted
4966 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
4967 * it may contain (in any case mapping) the text "true" or "false".
4968 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
4969 * localised text of "True" or "False" in the language specified by lcid.
4970 * - If none of these matches occur, the string is treated as a numeric string
4971 * and the boolean pBoolOut will be set according to whether the number is zero
4972 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
4973 * - If the text is not numeric and does not match any of the above, then
4974 * DISP_E_TYPEMISMATCH is returned.
4976 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
*pBoolOut
)
4978 /* Any VB/VBA programmers out there should recognise these strings... */
4979 static const WCHAR szFalse
[] = { '#','F','A','L','S','E','#','\0' };
4980 static const WCHAR szTrue
[] = { '#','T','R','U','E','#','\0' };
4982 LANGID langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4983 HRESULT hRes
= S_OK
;
4985 if (!strIn
|| !pBoolOut
)
4986 return DISP_E_TYPEMISMATCH
;
4988 /* Check if we should be comparing against localised text */
4989 if (dwFlags
& VAR_LOCALBOOL
)
4991 /* Convert our LCID into a usable value */
4992 lcid
= ConvertDefaultLocale(lcid
);
4994 langId
= LANGIDFROMLCID(lcid
);
4996 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
4997 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
4999 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
5000 * I don't think this is needed unless any of the localised text strings
5001 * contain characters that can be so mapped. In the event that this is
5002 * true for a given language (possibly some Asian languages), then strIn
5003 * should be mapped here _only_ if langId is an Id for which this can occur.
5007 /* Note that if we are not comparing against localised strings, langId
5008 * will have its default value of LANG_ENGLISH. This allows us to mimic
5009 * the native behaviour of always checking against English strings even
5010 * after we've checked for localised ones.
5012 VarBoolFromStr_CheckLocalised
:
5013 if (VARIANT_GetLocalisedText(langId
, IDS_TRUE
, szBuff
))
5015 /* Compare against localised strings, ignoring case */
5016 if (!strcmpiW(strIn
, szBuff
))
5018 *pBoolOut
= VARIANT_TRUE
; /* Matched localised 'true' text */
5021 VARIANT_GetLocalisedText(langId
, IDS_FALSE
, szBuff
);
5022 if (!strcmpiW(strIn
, szBuff
))
5024 *pBoolOut
= VARIANT_FALSE
; /* Matched localised 'false' text */
5029 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
5031 /* We have checked the localised text, now check English */
5032 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5033 goto VarBoolFromStr_CheckLocalised
;
5036 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
5037 if (!strcmpW(strIn
, szFalse
))
5038 *pBoolOut
= VARIANT_FALSE
;
5039 else if (!strcmpW(strIn
, szTrue
))
5040 *pBoolOut
= VARIANT_TRUE
;
5045 /* If this string is a number, convert it as one */
5046 hRes
= _VarR8FromStr(strIn
, lcid
, dwFlags
, &d
);
5047 if (SUCCEEDED(hRes
))
5048 hRes
= _VarBoolFromR8(d
, pBoolOut
);
5053 /************************************************************************
5054 * VarBoolFromDisp (OLEAUT32.126)
5056 * Convert a VT_DISPATCH to a VT_BOOL.
5059 * pdispIn [I] Source
5060 * lcid [I] LCID for conversion
5061 * pBoolOut [O] Destination
5065 * Failure: E_INVALIDARG, if the source value is invalid
5066 * DISP_E_OVERFLOW, if the value will not fit in the destination
5067 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5069 HRESULT WINAPI
VarBoolFromDisp(IDispatch
* pdispIn
, LCID lcid
, VARIANT_BOOL
*pBoolOut
)
5071 return _VarBoolFromDisp(pdispIn
, lcid
, pBoolOut
);
5074 /************************************************************************
5075 * VarBoolFromI1 (OLEAUT32.233)
5077 * Convert a VT_I1 to a VT_BOOL.
5081 * pBoolOut [O] Destination
5086 HRESULT WINAPI
VarBoolFromI1(signed char cIn
, VARIANT_BOOL
*pBoolOut
)
5088 return _VarBoolFromI1(cIn
, pBoolOut
);
5091 /************************************************************************
5092 * VarBoolFromUI2 (OLEAUT32.234)
5094 * Convert a VT_UI2 to a VT_BOOL.
5098 * pBoolOut [O] Destination
5103 HRESULT WINAPI
VarBoolFromUI2(USHORT usIn
, VARIANT_BOOL
*pBoolOut
)
5105 return _VarBoolFromUI2(usIn
, pBoolOut
);
5108 /************************************************************************
5109 * VarBoolFromUI4 (OLEAUT32.235)
5111 * Convert a VT_UI4 to a VT_BOOL.
5115 * pBoolOut [O] Destination
5120 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
*pBoolOut
)
5122 return _VarBoolFromUI4(ulIn
, pBoolOut
);
5125 /************************************************************************
5126 * VarBoolFromDec (OLEAUT32.236)
5128 * Convert a VT_DECIMAL to a VT_BOOL.
5132 * pBoolOut [O] Destination
5136 * Failure: E_INVALIDARG, if pDecIn is invalid.
5138 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
5139 HRESULT WINAPI
VarBoolFromDec(DECIMAL
* pDecIn
, VARIANT_BOOL
*pBoolOut
)
5141 if (DEC_SCALE(pDecIn
) > DEC_MAX_SCALE
|| (DEC_SIGN(pDecIn
) & ~DECIMAL_NEG
))
5142 return E_INVALIDARG
;
5144 if (DEC_HI32(pDecIn
) || DEC_MID32(pDecIn
) || DEC_LO32(pDecIn
))
5145 *pBoolOut
= VARIANT_TRUE
;
5147 *pBoolOut
= VARIANT_FALSE
;
5152 /************************************************************************
5153 * VarBoolFromI8 (OLEAUT32.370)
5155 * Convert a VT_I8 to a VT_BOOL.
5159 * pBoolOut [O] Destination
5164 HRESULT WINAPI
VarBoolFromI8(LONG64 llIn
, VARIANT_BOOL
*pBoolOut
)
5166 return _VarBoolFromI8(llIn
, pBoolOut
);
5169 /************************************************************************
5170 * VarBoolFromUI8 (OLEAUT32.371)
5172 * Convert a VT_UI8 to a VT_BOOL.
5176 * pBoolOut [O] Destination
5181 HRESULT WINAPI
VarBoolFromUI8(ULONG64 ullIn
, VARIANT_BOOL
*pBoolOut
)
5183 return _VarBoolFromUI8(ullIn
, pBoolOut
);
5189 /* Write a number from a UI8 and sign */
5190 static WCHAR
*VARIANT_WriteNumber(ULONG64 ulVal
, WCHAR
* szOut
)
5194 WCHAR ulNextDigit
= ulVal
% 10;
5196 *szOut
-- = '0' + ulNextDigit
;
5197 ulVal
= (ulVal
- ulNextDigit
) / 10;
5204 /* Create a (possibly localised) BSTR from a UI8 and sign */
5205 static BSTR
VARIANT_MakeBstr(LCID lcid
, DWORD dwFlags
, WCHAR
*szOut
)
5207 WCHAR szConverted
[256];
5209 if (dwFlags
& VAR_NEGATIVE
)
5212 if (dwFlags
& LOCALE_USE_NLS
)
5214 /* Format the number for the locale */
5215 szConverted
[0] = '\0';
5216 GetNumberFormatW(lcid
,
5217 dwFlags
& LOCALE_NOUSEROVERRIDE
,
5218 szOut
, NULL
, szConverted
, sizeof(szConverted
)/sizeof(WCHAR
));
5219 szOut
= szConverted
;
5221 return SysAllocStringByteLen((LPCSTR
)szOut
, strlenW(szOut
) * sizeof(WCHAR
));
5224 /* Create a (possibly localised) BSTR from a UI8 and sign */
5225 static HRESULT
VARIANT_BstrFromUInt(ULONG64 ulVal
, LCID lcid
, DWORD dwFlags
, BSTR
*pbstrOut
)
5227 WCHAR szBuff
[64], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5230 return E_INVALIDARG
;
5232 /* Create the basic number string */
5234 szOut
= VARIANT_WriteNumber(ulVal
, szOut
);
5236 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5237 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5238 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5241 /******************************************************************************
5242 * VarBstrFromUI1 (OLEAUT32.108)
5244 * Convert a VT_UI1 to a VT_BSTR.
5248 * lcid [I] LCID for the conversion
5249 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5250 * pbstrOut [O] Destination
5254 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5255 * E_OUTOFMEMORY, if memory allocation fails.
5257 HRESULT WINAPI
VarBstrFromUI1(BYTE bIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5259 return VARIANT_BstrFromUInt(bIn
, lcid
, dwFlags
, pbstrOut
);
5262 /******************************************************************************
5263 * VarBstrFromI2 (OLEAUT32.109)
5265 * Convert a VT_I2 to a VT_BSTR.
5269 * lcid [I] LCID for the conversion
5270 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5271 * pbstrOut [O] Destination
5275 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5276 * E_OUTOFMEMORY, if memory allocation fails.
5278 HRESULT WINAPI
VarBstrFromI2(short sIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5285 dwFlags
|= VAR_NEGATIVE
;
5287 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5290 /******************************************************************************
5291 * VarBstrFromI4 (OLEAUT32.110)
5293 * Convert a VT_I4 to a VT_BSTR.
5297 * lcid [I] LCID for the conversion
5298 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5299 * pbstrOut [O] Destination
5303 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5304 * E_OUTOFMEMORY, if memory allocation fails.
5306 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5313 dwFlags
|= VAR_NEGATIVE
;
5315 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5318 static HRESULT
VARIANT_BstrFromReal(DOUBLE dblIn
, LCID lcid
, ULONG dwFlags
,
5319 BSTR
* pbstrOut
, LPCWSTR lpszFormat
)
5324 return E_INVALIDARG
;
5326 sprintfW( buff
, lpszFormat
, dblIn
);
5327 TRACE("created string %s\n", debugstr_w(buff
));
5328 if (dwFlags
& LOCALE_USE_NLS
)
5332 /* Format the number for the locale */
5334 GetNumberFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5335 buff
, NULL
, numbuff
, sizeof(numbuff
) / sizeof(WCHAR
));
5336 TRACE("created NLS string %s\n", debugstr_w(numbuff
));
5337 *pbstrOut
= SysAllocString(numbuff
);
5340 *pbstrOut
= SysAllocString(buff
);
5341 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5344 /******************************************************************************
5345 * VarBstrFromR4 (OLEAUT32.111)
5347 * Convert a VT_R4 to a VT_BSTR.
5351 * lcid [I] LCID for the conversion
5352 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5353 * pbstrOut [O] Destination
5357 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5358 * E_OUTOFMEMORY, if memory allocation fails.
5360 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5362 return VARIANT_BstrFromReal(fltIn
, lcid
, dwFlags
, pbstrOut
, szFloatFormatW
);
5365 /******************************************************************************
5366 * VarBstrFromR8 (OLEAUT32.112)
5368 * Convert a VT_R8 to a VT_BSTR.
5372 * lcid [I] LCID for the conversion
5373 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5374 * pbstrOut [O] Destination
5378 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5379 * E_OUTOFMEMORY, if memory allocation fails.
5381 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5383 return VARIANT_BstrFromReal(dblIn
, lcid
, dwFlags
, pbstrOut
, szDoubleFormatW
);
5386 /******************************************************************************
5387 * VarBstrFromCy [OLEAUT32.113]
5389 * Convert a VT_CY to a VT_BSTR.
5393 * lcid [I] LCID for the conversion
5394 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5395 * pbstrOut [O] Destination
5399 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5400 * E_OUTOFMEMORY, if memory allocation fails.
5402 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
)
5408 return E_INVALIDARG
;
5410 VarR8FromCy(cyIn
, &dblVal
);
5411 sprintfW(buff
, szDoubleFormatW
, dblVal
);
5413 if (dwFlags
& LOCALE_USE_NLS
)
5417 /* Format the currency for the locale */
5419 GetCurrencyFormatW(lcid
, dwFlags
& LOCALE_NOUSEROVERRIDE
,
5420 buff
, NULL
, cybuff
, sizeof(cybuff
) / sizeof(WCHAR
));
5421 *pbstrOut
= SysAllocString(cybuff
);
5424 *pbstrOut
= SysAllocString(buff
);
5426 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5429 /******************************************************************************
5430 * VarBstrFromDate [OLEAUT32.114]
5432 * Convert a VT_DATE to a VT_BSTR.
5436 * lcid [I] LCID for the conversion
5437 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5438 * pbstrOut [O] Destination
5442 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5443 * E_OUTOFMEMORY, if memory allocation fails.
5445 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5448 DWORD dwFormatFlags
= dwFlags
& LOCALE_NOUSEROVERRIDE
;
5449 WCHAR date
[128], *time
;
5451 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
5453 #ifndef __REACTOS__ /*FIXME: no VariantTimeToSystemTime() yet */
5454 if (!pbstrOut
|| !VariantTimeToSystemTime(dateIn
, &st
))
5458 return E_INVALIDARG
;
5462 if (dwFlags
& VAR_CALENDAR_THAI
)
5463 st
.wYear
+= 553; /* Use the Thai buddhist calendar year */
5464 else if (dwFlags
& (VAR_CALENDAR_HIJRI
|VAR_CALENDAR_GREGORIAN
))
5465 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5467 if (dwFlags
& LOCALE_USE_NLS
)
5468 dwFlags
&= ~(VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
);
5471 double whole
= dateIn
< 0 ? ceil(dateIn
) : floor(dateIn
);
5472 double partial
= dateIn
- whole
;
5475 dwFlags
|= VAR_TIMEVALUEONLY
;
5476 else if (partial
< 1e-12)
5477 dwFlags
|= VAR_DATEVALUEONLY
;
5480 if (dwFlags
& VAR_TIMEVALUEONLY
)
5483 if (!GetDateFormatW(lcid
, dwFormatFlags
|DATE_SHORTDATE
, &st
, NULL
, date
,
5484 sizeof(date
)/sizeof(WCHAR
)))
5485 return E_INVALIDARG
;
5487 if (!(dwFlags
& VAR_DATEVALUEONLY
))
5489 time
= date
+ strlenW(date
);
5492 if (!GetTimeFormatW(lcid
, dwFormatFlags
, &st
, NULL
, time
,
5493 sizeof(date
)/sizeof(WCHAR
)-(time
-date
)))
5494 return E_INVALIDARG
;
5497 *pbstrOut
= SysAllocString(date
);
5499 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5500 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5503 /******************************************************************************
5504 * VarBstrFromBool (OLEAUT32.116)
5506 * Convert a VT_BOOL to a VT_BSTR.
5510 * lcid [I] LCID for the conversion
5511 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5512 * pbstrOut [O] Destination
5516 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5517 * E_OUTOFMEMORY, if memory allocation fails.
5520 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5521 * localised text of "True" or "False". To convert a bool into a
5522 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5524 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5527 DWORD dwResId
= IDS_TRUE
;
5530 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
5533 return E_INVALIDARG
;
5535 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5536 * for variant formatting */
5537 switch (dwFlags
& (VAR_LOCALBOOL
|VAR_BOOLONOFF
|VAR_BOOLYESNO
))
5548 lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
),SORT_DEFAULT
);
5551 lcid
= ConvertDefaultLocale(lcid
);
5552 langId
= LANGIDFROMLCID(lcid
);
5553 if (PRIMARYLANGID(langId
) == LANG_NEUTRAL
)
5554 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5556 if (boolIn
== VARIANT_FALSE
)
5557 dwResId
++; /* Use negative form */
5559 VarBstrFromBool_GetLocalised
:
5560 if (VARIANT_GetLocalisedText(langId
, dwResId
, szBuff
))
5562 *pbstrOut
= SysAllocString(szBuff
);
5563 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5566 if (langId
!= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
))
5568 langId
= MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
);
5569 goto VarBstrFromBool_GetLocalised
;
5572 /* Should never get here */
5573 WARN("Failed to load bool text!\n");
5574 return E_OUTOFMEMORY
;
5577 /******************************************************************************
5578 * VarBstrFromI1 (OLEAUT32.229)
5580 * Convert a VT_I1 to a VT_BSTR.
5584 * lcid [I] LCID for the conversion
5585 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5586 * pbstrOut [O] Destination
5590 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5591 * E_OUTOFMEMORY, if memory allocation fails.
5593 HRESULT WINAPI
VarBstrFromI1(signed char cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5600 dwFlags
|= VAR_NEGATIVE
;
5602 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5605 /******************************************************************************
5606 * VarBstrFromUI2 (OLEAUT32.230)
5608 * Convert a VT_UI2 to a VT_BSTR.
5612 * lcid [I] LCID for the conversion
5613 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5614 * pbstrOut [O] Destination
5618 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5619 * E_OUTOFMEMORY, if memory allocation fails.
5621 HRESULT WINAPI
VarBstrFromUI2(USHORT usIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5623 return VARIANT_BstrFromUInt(usIn
, lcid
, dwFlags
, pbstrOut
);
5626 /******************************************************************************
5627 * VarBstrFromUI4 (OLEAUT32.231)
5629 * Convert a VT_UI4 to a VT_BSTR.
5633 * lcid [I] LCID for the conversion
5634 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5635 * pbstrOut [O] Destination
5639 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5640 * E_OUTOFMEMORY, if memory allocation fails.
5642 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5644 return VARIANT_BstrFromUInt(ulIn
, lcid
, dwFlags
, pbstrOut
);
5647 /******************************************************************************
5648 * VarBstrFromDec (OLEAUT32.232)
5650 * Convert a VT_DECIMAL to a VT_BSTR.
5654 * lcid [I] LCID for the conversion
5655 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5656 * pbstrOut [O] Destination
5660 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5661 * E_OUTOFMEMORY, if memory allocation fails.
5663 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
5664 HRESULT WINAPI
VarBstrFromDec(DECIMAL
* pDecIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5667 return E_INVALIDARG
;
5669 if (!DEC_SCALE(pDecIn
) && !DEC_HI32(pDecIn
))
5671 WCHAR szBuff
[256], *szOut
= szBuff
+ sizeof(szBuff
)/sizeof(WCHAR
) - 1;
5673 /* Create the basic number string */
5675 szOut
= VARIANT_WriteNumber(DEC_LO64(pDecIn
), szOut
);
5676 if (DEC_SIGN(pDecIn
))
5677 dwFlags
|= VAR_NEGATIVE
;
5679 *pbstrOut
= VARIANT_MakeBstr(lcid
, dwFlags
, szOut
);
5680 TRACE("returning %s\n", debugstr_w(*pbstrOut
));
5681 return *pbstrOut
? S_OK
: E_OUTOFMEMORY
;
5683 FIXME("semi-stub\n");
5684 return E_INVALIDARG
;
5688 /************************************************************************
5689 * VarBstrFromI8 (OLEAUT32.370)
5691 * Convert a VT_I8 to a VT_BSTR.
5695 * lcid [I] LCID for the conversion
5696 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5697 * pbstrOut [O] Destination
5701 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5702 * E_OUTOFMEMORY, if memory allocation fails.
5704 HRESULT WINAPI
VarBstrFromI8(LONG64 llIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5706 ULONG64 ul64
= llIn
;
5711 dwFlags
|= VAR_NEGATIVE
;
5713 return VARIANT_BstrFromUInt(ul64
, lcid
, dwFlags
, pbstrOut
);
5716 /************************************************************************
5717 * VarBstrFromUI8 (OLEAUT32.371)
5719 * Convert a VT_UI8 to a VT_BSTR.
5723 * lcid [I] LCID for the conversion
5724 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5725 * pbstrOut [O] Destination
5729 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5730 * E_OUTOFMEMORY, if memory allocation fails.
5732 HRESULT WINAPI
VarBstrFromUI8(ULONG64 ullIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
5734 return VARIANT_BstrFromUInt(ullIn
, lcid
, dwFlags
, pbstrOut
);
5737 /**********************************************************************
5738 * VarBstrCat (OLEAUT32.313)
5740 * Concatenate two BSTR values.
5743 * pbstrLeft [I] Source
5744 * pbstrRight [I] Value to concatenate
5745 * pbstrOut [O] Destination
5749 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5750 * E_OUTOFMEMORY, if memory allocation fails.
5752 HRESULT WINAPI
VarBstrCat(BSTR pbstrLeft
, BSTR pbstrRight
, BSTR
*pbstrOut
)
5757 return E_INVALIDARG
;
5759 len
= pbstrLeft
? strlenW(pbstrLeft
) : 0;
5761 len
+= strlenW(pbstrRight
);
5763 *pbstrOut
= SysAllocStringLen(NULL
, len
);
5765 return E_OUTOFMEMORY
;
5767 (*pbstrOut
)[0] = '\0';
5770 strcpyW(*pbstrOut
, pbstrLeft
);
5773 strcatW(*pbstrOut
, pbstrRight
);
5778 /**********************************************************************
5779 * VarBstrCmp (OLEAUT32.314)
5781 * Compare two BSTR values.
5784 * pbstrLeft [I] Source
5785 * pbstrRight [I] Value to compare
5786 * lcid [I] LCID for the comparason
5787 * dwFlags [I] Flags to pass directly to CompareStringW().
5790 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5791 * than, equal to or greater than pbstrRight respectively.
5792 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5793 * in which case VARCMP_EQ is returned.
5795 HRESULT WINAPI
VarBstrCmp(BSTR pbstrLeft
, BSTR pbstrRight
, LCID lcid
, DWORD dwFlags
)
5799 if (!pbstrRight
|| !*pbstrRight
)
5803 else if (!pbstrRight
)
5810 return CompareStringW(lcid
, dwFlags
, pbstrLeft
, -1, pbstrRight
, -1) - 1;
5817 /******************************************************************************
5818 * VarDateFromUI1 (OLEAUT32.88)
5820 * Convert a VT_UI1 to a VT_DATE.
5824 * pdateOut [O] Destination
5829 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
5831 return _VarDateFromUI1(bIn
, pdateOut
);
5834 /******************************************************************************
5835 * VarDateFromI2 (OLEAUT32.89)
5837 * Convert a VT_I2 to a VT_DATE.
5841 * pdateOut [O] Destination
5846 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
5848 return _VarDateFromI2(sIn
, pdateOut
);
5851 /******************************************************************************
5852 * VarDateFromI4 (OLEAUT32.90)
5854 * Convert a VT_I4 to a VT_DATE.
5858 * pdateOut [O] Destination
5863 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
5865 return _VarDateFromI4(lIn
, pdateOut
);
5868 /******************************************************************************
5869 * VarDateFromR4 (OLEAUT32.91)
5871 * Convert a VT_R4 to a VT_DATE.
5875 * pdateOut [O] Destination
5880 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
5882 return _VarDateFromR4(fltIn
, pdateOut
);
5885 /******************************************************************************
5886 * VarDateFromR8 (OLEAUT32.92)
5888 * Convert a VT_R8 to a VT_DATE.
5892 * pdateOut [O] Destination
5897 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
5899 return _VarDateFromR8(dblIn
, pdateOut
);
5902 /**********************************************************************
5903 * VarDateFromDisp (OLEAUT32.95)
5905 * Convert a VT_DISPATCH to a VT_DATE.
5908 * pdispIn [I] Source
5909 * lcid [I] LCID for conversion
5910 * pdateOut [O] Destination
5914 * Failure: E_INVALIDARG, if the source value is invalid
5915 * DISP_E_OVERFLOW, if the value will not fit in the destination
5916 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5918 HRESULT WINAPI
VarDateFromDisp(IDispatch
* pdispIn
, LCID lcid
, DATE
* pdateOut
)
5920 return _VarDateFromDisp(pdispIn
, lcid
, pdateOut
);
5923 /******************************************************************************
5924 * VarDateFromBool (OLEAUT32.96)
5926 * Convert a VT_BOOL to a VT_DATE.
5930 * pdateOut [O] Destination
5935 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
5937 return _VarDateFromBool(boolIn
, pdateOut
);
5940 /**********************************************************************
5941 * VarDateFromCy (OLEAUT32.93)
5943 * Convert a VT_CY to a VT_DATE.
5947 * pdateOut [O] Destination
5952 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
)
5954 return _VarDateFromCy(cyIn
, pdateOut
);
5957 /* Date string parsing */
5958 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
5959 #define DP_DATESEP 0x02 /* Date separator */
5960 #define DP_MONTH 0x04 /* Month name */
5961 #define DP_AM 0x08 /* AM */
5962 #define DP_PM 0x10 /* PM */
5964 typedef struct tagDATEPARSE
5966 DWORD dwCount
; /* Number of fields found so far (maximum 6) */
5967 DWORD dwParseFlags
; /* Global parse flags (DP_ Flags above) */
5968 DWORD dwFlags
[6]; /* Flags for each field */
5969 DWORD dwValues
[6]; /* Value of each field */
5972 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
5974 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5976 /* Determine if a day is valid in a given month of a given year */
5977 static BOOL
VARIANT_IsValidMonthDay(DWORD day
, DWORD month
, DWORD year
)
5979 static const BYTE days
[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
5981 if (day
&& month
&& month
< 13)
5983 if (day
<= days
[month
] || (month
== 2 && day
== 29 && IsLeapYear(year
)))
5989 /* Possible orders for 3 numbers making up a date */
5990 #define ORDER_MDY 0x01
5991 #define ORDER_YMD 0x02
5992 #define ORDER_YDM 0x04
5993 #define ORDER_DMY 0x08
5994 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
5996 /* Determine a date for a particular locale, from 3 numbers */
5997 static inline HRESULT
VARIANT_MakeDate(DATEPARSE
*dp
, DWORD iDate
,
5998 DWORD offset
, SYSTEMTIME
*st
)
6000 DWORD dwAllOrders
, dwTry
, dwCount
= 0, v1
, v2
, v3
;
6004 v1
= 30; /* Default to (Variant) 0 date part */
6007 goto VARIANT_MakeDate_OK
;
6010 v1
= dp
->dwValues
[offset
+ 0];
6011 v2
= dp
->dwValues
[offset
+ 1];
6012 if (dp
->dwCount
== 2)
6015 GetSystemTime(¤t
);
6019 v3
= dp
->dwValues
[offset
+ 2];
6021 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1
, v2
, v3
, iDate
, offset
);
6023 /* If one number must be a month (Because a month name was given), then only
6024 * consider orders with the month in that position.
6025 * If we took the current year as 'v3', then only allow a year in that position.
6027 if (dp
->dwFlags
[offset
+ 0] & DP_MONTH
)
6029 dwAllOrders
= ORDER_MDY
;
6031 else if (dp
->dwFlags
[offset
+ 1] & DP_MONTH
)
6033 dwAllOrders
= ORDER_DMY
;
6034 if (dp
->dwCount
> 2)
6035 dwAllOrders
|= ORDER_YMD
;
6037 else if (dp
->dwCount
> 2 && dp
->dwFlags
[offset
+ 2] & DP_MONTH
)
6039 dwAllOrders
= ORDER_YDM
;
6043 dwAllOrders
= ORDER_MDY
|ORDER_DMY
;
6044 if (dp
->dwCount
> 2)
6045 dwAllOrders
|= (ORDER_YMD
|ORDER_YDM
);
6048 VARIANT_MakeDate_Start
:
6049 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders
);
6057 /* First: Try the order given by iDate */
6060 case 0: dwTry
= dwAllOrders
& ORDER_MDY
; break;
6061 case 1: dwTry
= dwAllOrders
& ORDER_DMY
; break;
6062 default: dwTry
= dwAllOrders
& ORDER_YMD
; break;
6065 else if (dwCount
== 1)
6067 /* Second: Try all the orders compatible with iDate */
6070 case 0: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
6071 case 1: dwTry
= dwAllOrders
& ~(ORDER_MDY
|ORDER_YMD
|ORDER_MYD
); break;
6072 default: dwTry
= dwAllOrders
& ~(ORDER_DMY
|ORDER_YDM
); break;
6077 /* Finally: Try any remaining orders */
6078 dwTry
= dwAllOrders
;
6081 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount
, dwTry
);
6087 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6089 if (dwTry
& ORDER_MDY
)
6091 if (VARIANT_IsValidMonthDay(v2
,v1
,v3
))
6094 goto VARIANT_MakeDate_OK
;
6096 dwAllOrders
&= ~ORDER_MDY
;
6098 if (dwTry
& ORDER_YMD
)
6100 if (VARIANT_IsValidMonthDay(v3
,v2
,v1
))
6103 goto VARIANT_MakeDate_OK
;
6105 dwAllOrders
&= ~ORDER_YMD
;
6107 if (dwTry
& ORDER_YDM
)
6109 if (VARIANT_IsValidMonthDay(v2
,v3
,v1
))
6113 goto VARIANT_MakeDate_OK
;
6115 dwAllOrders
&= ~ORDER_YDM
;
6117 if (dwTry
& ORDER_DMY
)
6119 if (VARIANT_IsValidMonthDay(v1
,v2
,v3
))
6120 goto VARIANT_MakeDate_OK
;
6121 dwAllOrders
&= ~ORDER_DMY
;
6123 if (dwTry
& ORDER_MYD
)
6125 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6126 if (VARIANT_IsValidMonthDay(v3
,v1
,v2
))
6130 goto VARIANT_MakeDate_OK
;
6132 dwAllOrders
&= ~ORDER_MYD
;
6136 if (dp
->dwCount
== 2)
6138 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6139 v3
= 1; /* 1st of the month */
6140 dwAllOrders
= ORDER_YMD
|ORDER_MYD
;
6141 dp
->dwCount
= 0; /* Don't return to this code path again */
6143 goto VARIANT_MakeDate_Start
;
6146 /* No valid dates were able to be constructed */
6147 return DISP_E_TYPEMISMATCH
;
6149 VARIANT_MakeDate_OK
:
6151 /* Check that the time part is ok */
6152 if (st
->wHour
> 23 || st
->wMinute
> 59 || st
->wSecond
> 59)
6153 return DISP_E_TYPEMISMATCH
;
6155 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6156 if (st
->wHour
< 12 && (dp
->dwParseFlags
& DP_PM
))
6158 else if (st
->wHour
== 12 && (dp
->dwParseFlags
& DP_AM
))
6160 TRACE("Time %d %d %d\n", st
->wHour
, st
->wMinute
, st
->wSecond
);
6164 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6165 * be retrieved from:
6166 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6167 * But Wine doesn't have/use that key as at the time of writing.
6169 st
->wYear
= v3
< 30 ? 2000 + v3
: v3
< 100 ? 1900 + v3
: v3
;
6170 TRACE("Returning date %ld/%ld/%d\n", v1
, v2
, st
->wYear
);
6174 /******************************************************************************
6175 * VarDateFromStr [OLEAUT32.94]
6177 * Convert a VT_BSTR to at VT_DATE.
6180 * strIn [I] String to convert
6181 * lcid [I] Locale identifier for the conversion
6182 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6183 * pdateOut [O] Destination for the converted value
6186 * Success: S_OK. pdateOut contains the converted value.
6187 * FAILURE: An HRESULT error code indicating the prolem.
6190 * Any date format that can be created using the date formats from lcid
6191 * (Either from kernel Nls functions, variant conversion or formatting) is a
6192 * valid input to this function. In addition, a few more esoteric formats are
6193 * also supported for compatibility with the native version. The date is
6194 * interpreted according to the date settings in the control panel, unless
6195 * the date is invalid in that format, in which the most compatible format
6196 * that produces a valid date will be used.
6198 #ifndef __REACTOS__ /*FIXME: no SystemTimeToVariantTime() yet */
6199 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
6201 static const USHORT ParseDateTokens
[] =
6203 LOCALE_SMONTHNAME1
, LOCALE_SMONTHNAME2
, LOCALE_SMONTHNAME3
, LOCALE_SMONTHNAME4
,
6204 LOCALE_SMONTHNAME5
, LOCALE_SMONTHNAME6
, LOCALE_SMONTHNAME7
, LOCALE_SMONTHNAME8
,
6205 LOCALE_SMONTHNAME9
, LOCALE_SMONTHNAME10
, LOCALE_SMONTHNAME11
, LOCALE_SMONTHNAME12
,
6206 LOCALE_SMONTHNAME13
,
6207 LOCALE_SABBREVMONTHNAME1
, LOCALE_SABBREVMONTHNAME2
, LOCALE_SABBREVMONTHNAME3
,
6208 LOCALE_SABBREVMONTHNAME4
, LOCALE_SABBREVMONTHNAME5
, LOCALE_SABBREVMONTHNAME6
,
6209 LOCALE_SABBREVMONTHNAME7
, LOCALE_SABBREVMONTHNAME8
, LOCALE_SABBREVMONTHNAME9
,
6210 LOCALE_SABBREVMONTHNAME10
, LOCALE_SABBREVMONTHNAME11
, LOCALE_SABBREVMONTHNAME12
,
6211 LOCALE_SABBREVMONTHNAME13
,
6212 LOCALE_SDAYNAME1
, LOCALE_SDAYNAME2
, LOCALE_SDAYNAME3
, LOCALE_SDAYNAME4
,
6213 LOCALE_SDAYNAME5
, LOCALE_SDAYNAME6
, LOCALE_SDAYNAME7
,
6214 LOCALE_SABBREVDAYNAME1
, LOCALE_SABBREVDAYNAME2
, LOCALE_SABBREVDAYNAME3
,
6215 LOCALE_SABBREVDAYNAME4
, LOCALE_SABBREVDAYNAME5
, LOCALE_SABBREVDAYNAME6
,
6216 LOCALE_SABBREVDAYNAME7
,
6217 LOCALE_S1159
, LOCALE_S2359
6219 static const BYTE ParseDateMonths
[] =
6221 1,2,3,4,5,6,7,8,9,10,11,12,13,
6222 1,2,3,4,5,6,7,8,9,10,11,12,13
6225 BSTR tokens
[sizeof(ParseDateTokens
)/sizeof(ParseDateTokens
[0])];
6227 DWORD dwDateSeps
= 0, iDate
= 0;
6228 HRESULT hRet
= S_OK
;
6230 if ((dwFlags
& (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
)) ==
6231 (VAR_TIMEVALUEONLY
|VAR_DATEVALUEONLY
))
6232 return E_INVALIDARG
;
6235 return DISP_E_TYPEMISMATCH
;
6239 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn
), lcid
, dwFlags
, pdateOut
);
6241 memset(&dp
, 0, sizeof(dp
));
6243 GetLocaleInfoW(lcid
, LOCALE_IDATE
|LOCALE_RETURN_NUMBER
|(dwFlags
& LOCALE_NOUSEROVERRIDE
),
6244 (LPWSTR
)&iDate
, sizeof(iDate
)/sizeof(WCHAR
));
6245 TRACE("iDate is %ld\n", iDate
);
6247 /* Get the month/day/am/pm tokens for this locale */
6248 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6251 LCTYPE lctype
= ParseDateTokens
[i
] | (dwFlags
& LOCALE_NOUSEROVERRIDE
);
6253 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6254 * GetAltMonthNames(). We should really cache these strings too.
6257 GetLocaleInfoW(lcid
, lctype
, buff
, sizeof(buff
)/sizeof(WCHAR
));
6258 tokens
[i
] = SysAllocString(buff
);
6259 TRACE("token %d is %s\n", i
, debugstr_w(tokens
[i
]));
6262 /* Parse the string into our structure */
6268 if (isdigitW(*strIn
))
6270 dp
.dwValues
[dp
.dwCount
] = strtoulW(strIn
, &strIn
, 10);
6274 else if (isalpha(*strIn
))
6276 BOOL bFound
= FALSE
;
6278 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6280 DWORD dwLen
= strlenW(tokens
[i
]);
6281 if (dwLen
&& !strncmpiW(strIn
, tokens
[i
], dwLen
))
6285 dp
.dwValues
[dp
.dwCount
] = ParseDateMonths
[i
];
6286 dp
.dwFlags
[dp
.dwCount
] |= (DP_MONTH
|DP_DATESEP
);
6291 if (!dp
.dwCount
|| dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6292 hRet
= DISP_E_TYPEMISMATCH
;
6295 dp
.dwFlags
[dp
.dwCount
- 1] |= (i
== 40 ? DP_AM
: DP_PM
);
6296 dp
.dwParseFlags
|= (i
== 40 ? DP_AM
: DP_PM
);
6299 strIn
+= (dwLen
- 1);
6307 if ((*strIn
== 'a' || *strIn
== 'A' || *strIn
== 'p' || *strIn
== 'P') &&
6308 (dp
.dwCount
&& !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6310 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6311 if (*strIn
== 'a' || *strIn
== 'A')
6313 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_AM
;
6314 dp
.dwParseFlags
|= DP_AM
;
6318 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_PM
;
6319 dp
.dwParseFlags
|= DP_PM
;
6325 TRACE("No matching token for %s\n", debugstr_w(strIn
));
6326 hRet
= DISP_E_TYPEMISMATCH
;
6331 else if (*strIn
== ':' || *strIn
== '.')
6333 if (!dp
.dwCount
|| !strIn
[1])
6334 hRet
= DISP_E_TYPEMISMATCH
;
6336 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_TIMESEP
;
6338 else if (*strIn
== '-' || *strIn
== '/')
6341 if (dwDateSeps
> 2 || !dp
.dwCount
|| !strIn
[1])
6342 hRet
= DISP_E_TYPEMISMATCH
;
6344 dp
.dwFlags
[dp
.dwCount
- 1] |= DP_DATESEP
;
6346 else if (*strIn
== ',' || isspaceW(*strIn
))
6348 if (*strIn
== ',' && !strIn
[1])
6349 hRet
= DISP_E_TYPEMISMATCH
;
6353 hRet
= DISP_E_TYPEMISMATCH
;
6358 if (!dp
.dwCount
|| dp
.dwCount
> 6 ||
6359 (dp
.dwCount
== 1 && !(dp
.dwParseFlags
& (DP_AM
|DP_PM
))))
6360 hRet
= DISP_E_TYPEMISMATCH
;
6362 if (SUCCEEDED(hRet
))
6365 DWORD dwOffset
= 0; /* Start of date fields in dp.dwValues */
6367 st
.wDayOfWeek
= st
.wHour
= st
.wMinute
= st
.wSecond
= st
.wMilliseconds
= 0;
6369 /* Figure out which numbers correspond to which fields.
6371 * This switch statement works based on the fact that native interprets any
6372 * fields that are not joined with a time separator ('.' or ':') as date
6373 * fields. Thus we construct a value from 0-32 where each set bit indicates
6374 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6375 * For valid permutations, we set dwOffset to point to the first date field
6376 * and shorten dp.dwCount by the number of time fields found. The real
6377 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6378 * each date number must represent in the context of iDate.
6380 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6382 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6384 case 0x1: /* TT TTDD TTDDD */
6385 if (dp
.dwCount
> 3 &&
6386 ((dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) ||
6387 (dp
.dwFlags
[4] & (DP_AM
|DP_PM
))))
6388 hRet
= DISP_E_TYPEMISMATCH
;
6389 else if (dp
.dwCount
!= 2 && dp
.dwCount
!= 4 && dp
.dwCount
!= 5)
6390 hRet
= DISP_E_TYPEMISMATCH
;
6391 st
.wHour
= dp
.dwValues
[0];
6392 st
.wMinute
= dp
.dwValues
[1];
6397 case 0x3: /* TTT TTTDD TTTDDD */
6398 if (dp
.dwCount
> 4 &&
6399 ((dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[4] & (DP_AM
|DP_PM
)) ||
6400 (dp
.dwFlags
[5] & (DP_AM
|DP_PM
))))
6401 hRet
= DISP_E_TYPEMISMATCH
;
6402 else if (dp
.dwCount
!= 3 && dp
.dwCount
!= 5 && dp
.dwCount
!= 6)
6403 hRet
= DISP_E_TYPEMISMATCH
;
6404 st
.wHour
= dp
.dwValues
[0];
6405 st
.wMinute
= dp
.dwValues
[1];
6406 st
.wSecond
= dp
.dwValues
[2];
6411 case 0x4: /* DDTT */
6412 if (dp
.dwCount
!= 4 ||
6413 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6414 hRet
= DISP_E_TYPEMISMATCH
;
6416 st
.wHour
= dp
.dwValues
[2];
6417 st
.wMinute
= dp
.dwValues
[3];
6421 case 0x0: /* T DD DDD TDDD TDDD */
6422 if (dp
.dwCount
== 1 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6424 st
.wHour
= dp
.dwValues
[0]; /* T */
6428 else if (dp
.dwCount
> 4 || (dp
.dwCount
< 3 && dp
.dwParseFlags
& (DP_AM
|DP_PM
)))
6430 hRet
= DISP_E_TYPEMISMATCH
;
6432 else if (dp
.dwCount
== 3)
6434 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDD */
6437 st
.wHour
= dp
.dwValues
[0];
6441 if (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)) /* DDT */
6444 st
.wHour
= dp
.dwValues
[2];
6447 else if (dp
.dwParseFlags
& (DP_AM
|DP_PM
))
6448 hRet
= DISP_E_TYPEMISMATCH
;
6450 else if (dp
.dwCount
== 4)
6453 if (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) /* TDDD */
6455 st
.wHour
= dp
.dwValues
[0];
6458 else if (dp
.dwFlags
[3] & (DP_AM
|DP_PM
)) /* DDDT */
6460 st
.wHour
= dp
.dwValues
[3];
6463 hRet
= DISP_E_TYPEMISMATCH
;
6466 /* .. fall through .. */
6468 case 0x8: /* DDDTT */
6469 if ((dp
.dwCount
== 2 && (dp
.dwParseFlags
& (DP_AM
|DP_PM
))) ||
6470 (dp
.dwCount
== 5 && ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) ||
6471 (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))) ||
6472 dp
.dwCount
== 4 || dp
.dwCount
== 6)
6473 hRet
= DISP_E_TYPEMISMATCH
;
6474 st
.wHour
= dp
.dwValues
[3];
6475 st
.wMinute
= dp
.dwValues
[4];
6476 if (dp
.dwCount
== 5)
6480 case 0xC: /* DDTTT */
6481 if (dp
.dwCount
!= 5 ||
6482 (dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)))
6483 hRet
= DISP_E_TYPEMISMATCH
;
6484 st
.wHour
= dp
.dwValues
[2];
6485 st
.wMinute
= dp
.dwValues
[3];
6486 st
.wSecond
= dp
.dwValues
[4];
6490 case 0x18: /* DDDTTT */
6491 if ((dp
.dwFlags
[0] & (DP_AM
|DP_PM
)) || (dp
.dwFlags
[1] & (DP_AM
|DP_PM
)) ||
6492 (dp
.dwFlags
[2] & (DP_AM
|DP_PM
)))
6493 hRet
= DISP_E_TYPEMISMATCH
;
6494 st
.wHour
= dp
.dwValues
[3];
6495 st
.wMinute
= dp
.dwValues
[4];
6496 st
.wSecond
= dp
.dwValues
[5];
6501 hRet
= DISP_E_TYPEMISMATCH
;
6505 if (SUCCEEDED(hRet
))
6507 hRet
= VARIANT_MakeDate(&dp
, iDate
, dwOffset
, &st
);
6509 if (dwFlags
& VAR_TIMEVALUEONLY
)
6515 else if (dwFlags
& VAR_DATEVALUEONLY
)
6516 st
.wHour
= st
.wMinute
= st
.wSecond
= 0;
6518 /* Finally, convert the value to a VT_DATE */
6519 if (SUCCEEDED(hRet
))
6520 hRet
= SystemTimeToVariantTime(&st
, pdateOut
) ? S_OK
: DISP_E_TYPEMISMATCH
;
6524 for (i
= 0; i
< sizeof(tokens
)/sizeof(tokens
[0]); i
++)
6525 SysFreeString(tokens
[i
]);
6530 /******************************************************************************
6531 * VarDateFromI1 (OLEAUT32.221)
6533 * Convert a VT_I1 to a VT_DATE.
6537 * pdateOut [O] Destination
6542 HRESULT WINAPI
VarDateFromI1(signed char cIn
, DATE
* pdateOut
)
6544 return _VarDateFromI1(cIn
, pdateOut
);
6547 /******************************************************************************
6548 * VarDateFromUI2 (OLEAUT32.222)
6550 * Convert a VT_UI2 to a VT_DATE.
6554 * pdateOut [O] Destination
6559 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
6561 return _VarDateFromUI2(uiIn
, pdateOut
);
6564 /******************************************************************************
6565 * VarDateFromUI4 (OLEAUT32.223)
6567 * Convert a VT_UI4 to a VT_DATE.
6571 * pdateOut [O] Destination
6576 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
6578 return _VarDateFromUI4(ulIn
, pdateOut
);
6581 /**********************************************************************
6582 * VarDateFromDec (OLEAUT32.224)
6584 * Convert a VT_DECIMAL to a VT_DATE.
6588 * pdateOut [O] Destination
6593 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
6594 HRESULT WINAPI
VarDateFromDec(DECIMAL
*pdecIn
, DATE
* pdateOut
)
6596 return _VarDateFromDec(pdecIn
, pdateOut
);
6600 /******************************************************************************
6601 * VarDateFromI8 (OLEAUT32.364)
6603 * Convert a VT_I8 to a VT_DATE.
6607 * pdateOut [O] Destination
6611 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6613 HRESULT WINAPI
VarDateFromI8(LONG64 llIn
, DATE
* pdateOut
)
6615 return _VarDateFromI8(llIn
, pdateOut
);
6618 /******************************************************************************
6619 * VarDateFromUI8 (OLEAUT32.365)
6621 * Convert a VT_UI8 to a VT_DATE.
6625 * pdateOut [O] Destination
6629 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6631 HRESULT WINAPI
VarDateFromUI8(ULONG64 ullIn
, DATE
* pdateOut
)
6633 return _VarDateFromUI8(ullIn
, pdateOut
);