2 * Low level variant functions
4 * Copyright 2003 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
25 #include "wine/debug.h"
26 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(variant);
35 extern HMODULE OLEAUT32_hModule;
37 static const WCHAR szFloatFormatW[] = { '%','.','7','G','\0' };
38 static const WCHAR szDoubleFormatW[] = { '%','.','1','5','G','\0' };
40 /* Copy data from one variant to another. */
41 static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
46 case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
49 case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
54 case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
59 case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
60 case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
61 case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
63 FIXME("VT_ type %d unhandled, please report!\n", vt);
68 /* Coerce VT_BSTR to a numeric type */
69 HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
70 void* pOut, VARTYPE vt)
77 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
78 np.cDig = sizeof(rgb) / sizeof(BYTE);
79 np.dwInFlags = NUMPRS_STD;
81 hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
85 /* 1 << vt gives us the VTBIT constant for the destination number type */
86 hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
88 VARIANT_CopyData(&dstVar, vt, pOut);
93 /* Coerce VT_DISPATCH to another type */
94 HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, VARTYPE vt)
96 static const DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
97 VARIANTARG srcVar, dstVar;
101 return DISP_E_BADVARTYPE;
103 /* Get the default 'value' property from the IDispatch */
104 hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
105 (DISPPARAMS*)&emptyParams, &srcVar, NULL, NULL);
109 /* Convert the property to the requested type */
110 V_VT(&dstVar) = VT_EMPTY;
111 hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, 0, vt);
112 VariantClear(&srcVar);
116 VARIANT_CopyData(&dstVar, vt, pOut);
117 VariantClear(&srcVar);
121 hRet = DISP_E_TYPEMISMATCH;
128 /************************************************************************
129 * VarI1FromUI1 (OLEAUT32.244)
131 * Convert a VT_UI1 to a VT_I1.
135 * pcOut [O] Destination
139 * Failure: E_INVALIDARG, if the source value is invalid
140 * DISP_E_OVERFLOW, if the value will not fit in the destination
142 HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
144 return _VarI1FromUI1(bIn, pcOut);
147 /************************************************************************
148 * VarI1FromI2 (OLEAUT32.245)
150 * Convert a VT_I2 to a VT_I1.
154 * pcOut [O] Destination
158 * Failure: E_INVALIDARG, if the source value is invalid
159 * DISP_E_OVERFLOW, if the value will not fit in the destination
161 HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
163 return _VarI1FromI2(sIn, pcOut);
166 /************************************************************************
167 * VarI1FromI4 (OLEAUT32.246)
169 * Convert a VT_I4 to a VT_I1.
173 * pcOut [O] Destination
177 * Failure: E_INVALIDARG, if the source value is invalid
178 * DISP_E_OVERFLOW, if the value will not fit in the destination
180 HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
182 return _VarI1FromI4(iIn, pcOut);
185 /************************************************************************
186 * VarI1FromR4 (OLEAUT32.247)
188 * Convert a VT_R4 to a VT_I1.
192 * pcOut [O] Destination
196 * Failure: E_INVALIDARG, if the source value is invalid
197 * DISP_E_OVERFLOW, if the value will not fit in the destination
199 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
201 return _VarI1FromR4(fltIn, pcOut);
204 /************************************************************************
205 * VarI1FromR8 (OLEAUT32.248)
207 * Convert a VT_R8 to a VT_I1.
211 * pcOut [O] Destination
215 * Failure: E_INVALIDARG, if the source value is invalid
216 * DISP_E_OVERFLOW, if the value will not fit in the destination
219 * See VarI8FromR8() for details concerning rounding.
221 HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
223 if (dblIn < (double)I1_MIN || dblIn > (double)I1_MAX)
224 return DISP_E_OVERFLOW;
225 OLEAUT32_DutchRound(CHAR, dblIn, *pcOut);
229 /************************************************************************
230 * VarI1FromDate (OLEAUT32.249)
232 * Convert a VT_DATE to a VT_I1.
236 * pcOut [O] Destination
240 * Failure: E_INVALIDARG, if the source value is invalid
241 * DISP_E_OVERFLOW, if the value will not fit in the destination
243 HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
245 return _VarI1FromDate(dateIn, pcOut);
248 /************************************************************************
249 * VarI1FromCy (OLEAUT32.250)
251 * Convert a VT_CY to a VT_I1.
255 * pcOut [O] Destination
259 * Failure: E_INVALIDARG, if the source value is invalid
260 * DISP_E_OVERFLOW, if the value will not fit in the destination
262 HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
266 _VarI4FromCy(cyIn, &i);
267 return _VarI1FromI4(i, pcOut);
270 /************************************************************************
271 * VarI1FromStr (OLEAUT32.251)
273 * Convert a VT_BSTR to a VT_I1.
277 * lcid [I] LCID for the conversion
278 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
279 * pcOut [O] Destination
283 * Failure: E_INVALIDARG, if the source value is invalid
284 * DISP_E_OVERFLOW, if the value will not fit in the destination
285 * DISP_E_TYPEMISMATCH, if the type cannot be converted
287 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
289 return _VarI1FromStr(strIn, lcid, dwFlags, pcOut);
292 /************************************************************************
293 * VarI1FromDisp (OLEAUT32.252)
295 * Convert a VT_DISPATCH to a VT_I1.
299 * lcid [I] LCID for conversion
300 * pcOut [O] Destination
304 * Failure: E_INVALIDARG, if the source value is invalid
305 * DISP_E_OVERFLOW, if the value will not fit in the destination
306 * DISP_E_TYPEMISMATCH, if the type cannot be converted
308 HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
310 return _VarI1FromDisp(pdispIn, lcid, pcOut);
313 /************************************************************************
314 * VarI1FromBool (OLEAUT32.253)
316 * Convert a VT_BOOL to a VT_I1.
320 * pcOut [O] Destination
325 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
327 return _VarI1FromBool(boolIn, pcOut);
330 /************************************************************************
331 * VarI1FromUI2 (OLEAUT32.254)
333 * Convert a VT_UI2 to a VT_I1.
337 * pcOut [O] Destination
341 * Failure: E_INVALIDARG, if the source value is invalid
342 * DISP_E_OVERFLOW, if the value will not fit in the destination
344 HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
346 return _VarI1FromUI2(usIn, pcOut);
349 /************************************************************************
350 * VarI1FromUI4 (OLEAUT32.255)
352 * Convert a VT_UI4 to a VT_I1.
356 * pcOut [O] Destination
360 * Failure: E_INVALIDARG, if the source value is invalid
361 * DISP_E_OVERFLOW, if the value will not fit in the destination
362 * DISP_E_TYPEMISMATCH, if the type cannot be converted
364 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
366 return _VarI1FromUI4(ulIn, pcOut);
369 /************************************************************************
370 * VarI1FromDec (OLEAUT32.256)
372 * Convert a VT_DECIMAL to a VT_I1.
376 * pcOut [O] Destination
380 * Failure: E_INVALIDARG, if the source value is invalid
381 * DISP_E_OVERFLOW, if the value will not fit in the destination
383 HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
388 hRet = _VarI8FromDec(pdecIn, &i64);
391 hRet = _VarI1FromI8(i64, pcOut);
395 /************************************************************************
396 * VarI1FromI8 (OLEAUT32.376)
398 * Convert a VT_I8 to a VT_I1.
402 * pcOut [O] Destination
406 * Failure: E_INVALIDARG, if the source value is invalid
407 * DISP_E_OVERFLOW, if the value will not fit in the destination
409 HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
411 return _VarI1FromI8(llIn, pcOut);
414 /************************************************************************
415 * VarI1FromUI8 (OLEAUT32.377)
417 * Convert a VT_UI8 to a VT_I1.
421 * pcOut [O] Destination
425 * Failure: E_INVALIDARG, if the source value is invalid
426 * DISP_E_OVERFLOW, if the value will not fit in the destination
428 HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
430 return _VarI1FromUI8(ullIn, pcOut);
436 /************************************************************************
437 * VarUI1FromI2 (OLEAUT32.130)
439 * Convert a VT_I2 to a VT_UI1.
443 * pbOut [O] Destination
447 * Failure: E_INVALIDARG, if the source value is invalid
448 * DISP_E_OVERFLOW, if the value will not fit in the destination
450 HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
452 return _VarUI1FromI2(sIn, pbOut);
455 /************************************************************************
456 * VarUI1FromI4 (OLEAUT32.131)
458 * Convert a VT_I4 to a VT_UI1.
462 * pbOut [O] Destination
466 * Failure: E_INVALIDARG, if the source value is invalid
467 * DISP_E_OVERFLOW, if the value will not fit in the destination
469 HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
471 return _VarUI1FromI4(iIn, pbOut);
474 /************************************************************************
475 * VarUI1FromR4 (OLEAUT32.132)
477 * Convert a VT_R4 to a VT_UI1.
481 * pbOut [O] Destination
485 * Failure: E_INVALIDARG, if the source value is invalid
486 * DISP_E_OVERFLOW, if the value will not fit in the destination
487 * DISP_E_TYPEMISMATCH, if the type cannot be converted
489 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
491 return _VarUI1FromR4(fltIn, pbOut);
494 /************************************************************************
495 * VarUI1FromR8 (OLEAUT32.133)
497 * Convert a VT_R8 to a VT_UI1.
501 * pbOut [O] Destination
505 * Failure: E_INVALIDARG, if the source value is invalid
506 * DISP_E_OVERFLOW, if the value will not fit in the destination
509 * See VarI8FromR8() for details concerning rounding.
511 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
513 if (dblIn < -0.5 || dblIn > (double)UI1_MAX)
514 return DISP_E_OVERFLOW;
515 OLEAUT32_DutchRound(BYTE, dblIn, *pbOut);
519 /************************************************************************
520 * VarUI1FromCy (OLEAUT32.134)
522 * Convert a VT_CY to a VT_UI1.
526 * pbOut [O] Destination
530 * Failure: E_INVALIDARG, if the source value is invalid
531 * DISP_E_OVERFLOW, if the value will not fit in the destination
534 * Negative values >= -5000 will be converted to 0.
536 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
538 ULONG i = UI1_MAX + 1;
540 _VarUI4FromCy(cyIn, &i);
541 return _VarUI1FromUI4(i, pbOut);
544 /************************************************************************
545 * VarUI1FromDate (OLEAUT32.135)
547 * Convert a VT_DATE to a VT_UI1.
551 * pbOut [O] Destination
555 * Failure: E_INVALIDARG, if the source value is invalid
556 * DISP_E_OVERFLOW, if the value will not fit in the destination
558 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
560 return _VarUI1FromDate(dateIn, pbOut);
563 /************************************************************************
564 * VarUI1FromStr (OLEAUT32.136)
566 * Convert a VT_BSTR to a VT_UI1.
570 * lcid [I] LCID for the conversion
571 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
572 * pbOut [O] Destination
576 * Failure: E_INVALIDARG, if the source value is invalid
577 * DISP_E_OVERFLOW, if the value will not fit in the destination
578 * DISP_E_TYPEMISMATCH, if the type cannot be converted
580 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
582 return _VarUI1FromStr(strIn, lcid, dwFlags, pbOut);
585 /************************************************************************
586 * VarUI1FromDisp (OLEAUT32.137)
588 * Convert a VT_DISPATCH to a VT_UI1.
592 * lcid [I] LCID for conversion
593 * pbOut [O] Destination
597 * Failure: E_INVALIDARG, if the source value is invalid
598 * DISP_E_OVERFLOW, if the value will not fit in the destination
599 * DISP_E_TYPEMISMATCH, if the type cannot be converted
601 HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
603 return _VarUI1FromDisp(pdispIn, lcid, pbOut);
606 /************************************************************************
607 * VarUI1FromBool (OLEAUT32.138)
609 * Convert a VT_BOOL to a VT_UI1.
613 * pbOut [O] Destination
618 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
620 return _VarUI1FromBool(boolIn, pbOut);
623 /************************************************************************
624 * VarUI1FromI1 (OLEAUT32.237)
626 * Convert a VT_I1 to a VT_UI1.
630 * pbOut [O] Destination
634 * Failure: E_INVALIDARG, if the source value is invalid
635 * DISP_E_OVERFLOW, if the value will not fit in the destination
637 HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
639 return _VarUI1FromI1(cIn, pbOut);
642 /************************************************************************
643 * VarUI1FromUI2 (OLEAUT32.238)
645 * Convert a VT_UI2 to a VT_UI1.
649 * pbOut [O] Destination
653 * Failure: E_INVALIDARG, if the source value is invalid
654 * DISP_E_OVERFLOW, if the value will not fit in the destination
656 HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
658 return _VarUI1FromUI2(usIn, pbOut);
661 /************************************************************************
662 * VarUI1FromUI4 (OLEAUT32.239)
664 * Convert a VT_UI4 to a VT_UI1.
668 * pbOut [O] Destination
672 * Failure: E_INVALIDARG, if the source value is invalid
673 * DISP_E_OVERFLOW, if the value will not fit in the destination
675 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
677 return _VarUI1FromUI4(ulIn, pbOut);
680 /************************************************************************
681 * VarUI1FromDec (OLEAUT32.240)
683 * Convert a VT_DECIMAL to a VT_UI1.
687 * pbOut [O] Destination
691 * Failure: E_INVALIDARG, if the source value is invalid
692 * DISP_E_OVERFLOW, if the value will not fit in the destination
694 HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
699 hRet = _VarI8FromDec(pdecIn, &i64);
702 hRet = _VarUI1FromI8(i64, pbOut);
706 /************************************************************************
707 * VarUI1FromI8 (OLEAUT32.372)
709 * Convert a VT_I8 to a VT_UI1.
713 * pbOut [O] Destination
717 * Failure: E_INVALIDARG, if the source value is invalid
718 * DISP_E_OVERFLOW, if the value will not fit in the destination
720 HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
722 return _VarUI1FromI8(llIn, pbOut);
725 /************************************************************************
726 * VarUI1FromUI8 (OLEAUT32.373)
728 * Convert a VT_UI8 to a VT_UI1.
732 * pbOut [O] Destination
736 * Failure: E_INVALIDARG, if the source value is invalid
737 * DISP_E_OVERFLOW, if the value will not fit in the destination
739 HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
741 return _VarUI1FromUI8(ullIn, pbOut);
748 /************************************************************************
749 * VarI2FromUI1 (OLEAUT32.48)
751 * Convert a VT_UI2 to a VT_I2.
755 * psOut [O] Destination
760 HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
762 return _VarI2FromUI1(bIn, psOut);
765 /************************************************************************
766 * VarI2FromI4 (OLEAUT32.49)
768 * Convert a VT_I4 to a VT_I2.
772 * psOut [O] Destination
776 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
778 HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
780 return _VarI2FromI4(iIn, psOut);
783 /************************************************************************
784 * VarI2FromR4 (OLEAUT32.50)
786 * Convert a VT_R4 to a VT_I2.
790 * psOut [O] Destination
794 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
796 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
798 return _VarI2FromR4(fltIn, psOut);
801 /************************************************************************
802 * VarI2FromR8 (OLEAUT32.51)
804 * Convert a VT_R8 to a VT_I2.
808 * psOut [O] Destination
812 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
815 * See VarI8FromR8() for details concerning rounding.
817 HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
819 if (dblIn < (double)I2_MIN || dblIn > (double)I2_MAX)
820 return DISP_E_OVERFLOW;
821 OLEAUT32_DutchRound(SHORT, dblIn, *psOut);
825 /************************************************************************
826 * VarI2FromCy (OLEAUT32.52)
828 * Convert a VT_CY to a VT_I2.
832 * psOut [O] Destination
836 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
838 HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
842 _VarI4FromCy(cyIn, &i);
843 return _VarI2FromI4(i, psOut);
846 /************************************************************************
847 * VarI2FromDate (OLEAUT32.53)
849 * Convert a VT_DATE to a VT_I2.
853 * psOut [O] Destination
857 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
859 HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
861 return _VarI2FromDate(dateIn, psOut);
864 /************************************************************************
865 * VarI2FromStr (OLEAUT32.54)
867 * Convert a VT_BSTR to a VT_I2.
871 * lcid [I] LCID for the conversion
872 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
873 * psOut [O] Destination
877 * Failure: E_INVALIDARG, if any parameter is invalid
878 * DISP_E_OVERFLOW, if the value will not fit in the destination
879 * DISP_E_TYPEMISMATCH, if the type cannot be converted
881 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
883 return _VarI2FromStr(strIn, lcid, dwFlags, psOut);
886 /************************************************************************
887 * VarI2FromDisp (OLEAUT32.55)
889 * Convert a VT_DISPATCH to a VT_I2.
893 * lcid [I] LCID for conversion
894 * psOut [O] Destination
898 * Failure: E_INVALIDARG, if pdispIn is invalid,
899 * DISP_E_OVERFLOW, if the value will not fit in the destination,
900 * DISP_E_TYPEMISMATCH, if the type cannot be converted
902 HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
904 return _VarI2FromDisp(pdispIn, lcid, psOut);
907 /************************************************************************
908 * VarI2FromBool (OLEAUT32.56)
910 * Convert a VT_BOOL to a VT_I2.
914 * psOut [O] Destination
919 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
921 return _VarI2FromBool(boolIn, psOut);
924 /************************************************************************
925 * VarI2FromI1 (OLEAUT32.205)
927 * Convert a VT_I1 to a VT_I2.
931 * psOut [O] Destination
936 HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
938 return _VarI2FromI1(cIn, psOut);
941 /************************************************************************
942 * VarI2FromUI2 (OLEAUT32.206)
944 * Convert a VT_UI2 to a VT_I2.
948 * psOut [O] Destination
952 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
954 HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
956 return _VarI2FromUI2(usIn, psOut);
959 /************************************************************************
960 * VarI2FromUI4 (OLEAUT32.207)
962 * Convert a VT_UI4 to a VT_I2.
966 * psOut [O] Destination
970 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
972 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
974 return _VarI2FromUI4(ulIn, psOut);
977 /************************************************************************
978 * VarI2FromDec (OLEAUT32.208)
980 * Convert a VT_DECIMAL to a VT_I2.
984 * psOut [O] Destination
988 * Failure: E_INVALIDARG, if the source value is invalid
989 * DISP_E_OVERFLOW, if the value will not fit in the destination
991 HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
996 hRet = _VarI8FromDec(pdecIn, &i64);
999 hRet = _VarI2FromI8(i64, psOut);
1003 /************************************************************************
1004 * VarI2FromI8 (OLEAUT32.346)
1006 * Convert a VT_I8 to a VT_I2.
1010 * psOut [O] Destination
1014 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1016 HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
1018 return _VarI2FromI8(llIn, psOut);
1021 /************************************************************************
1022 * VarI2FromUI8 (OLEAUT32.347)
1024 * Convert a VT_UI8 to a VT_I2.
1028 * psOut [O] Destination
1032 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1034 HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
1036 return _VarI2FromUI8(ullIn, psOut);
1042 /************************************************************************
1043 * VarUI2FromUI1 (OLEAUT32.257)
1045 * Convert a VT_UI1 to a VT_UI2.
1049 * pusOut [O] Destination
1054 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
1056 return _VarUI2FromUI1(bIn, pusOut);
1059 /************************************************************************
1060 * VarUI2FromI2 (OLEAUT32.258)
1062 * Convert a VT_I2 to a VT_UI2.
1066 * pusOut [O] Destination
1070 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1072 HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
1074 return _VarUI2FromI2(sIn, pusOut);
1077 /************************************************************************
1078 * VarUI2FromI4 (OLEAUT32.259)
1080 * Convert a VT_I4 to a VT_UI2.
1084 * pusOut [O] Destination
1088 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1090 HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
1092 return _VarUI2FromI4(iIn, pusOut);
1095 /************************************************************************
1096 * VarUI2FromR4 (OLEAUT32.260)
1098 * Convert a VT_R4 to a VT_UI2.
1102 * pusOut [O] Destination
1106 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1108 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
1110 return _VarUI2FromR4(fltIn, pusOut);
1113 /************************************************************************
1114 * VarUI2FromR8 (OLEAUT32.261)
1116 * Convert a VT_R8 to a VT_UI2.
1120 * pusOut [O] Destination
1124 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1127 * See VarI8FromR8() for details concerning rounding.
1129 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
1131 if (dblIn < -0.5 || dblIn > (double)UI2_MAX)
1132 return DISP_E_OVERFLOW;
1133 OLEAUT32_DutchRound(USHORT, dblIn, *pusOut);
1137 /************************************************************************
1138 * VarUI2FromDate (OLEAUT32.262)
1140 * Convert a VT_DATE to a VT_UI2.
1144 * pusOut [O] Destination
1148 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1150 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
1152 return _VarUI2FromDate(dateIn, pusOut);
1155 /************************************************************************
1156 * VarUI2FromCy (OLEAUT32.263)
1158 * Convert a VT_CY to a VT_UI2.
1162 * pusOut [O] Destination
1166 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1169 * Negative values >= -5000 will be converted to 0.
1171 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
1173 ULONG i = UI2_MAX + 1;
1175 _VarUI4FromCy(cyIn, &i);
1176 return _VarUI2FromUI4(i, pusOut);
1179 /************************************************************************
1180 * VarUI2FromStr (OLEAUT32.264)
1182 * Convert a VT_BSTR to a VT_UI2.
1186 * lcid [I] LCID for the conversion
1187 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1188 * pusOut [O] Destination
1192 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1193 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1195 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
1197 return _VarUI2FromStr(strIn, lcid, dwFlags, pusOut);
1200 /************************************************************************
1201 * VarUI2FromDisp (OLEAUT32.265)
1203 * Convert a VT_DISPATCH to a VT_UI2.
1206 * pdispIn [I] Source
1207 * lcid [I] LCID for conversion
1208 * pusOut [O] Destination
1212 * Failure: E_INVALIDARG, if the source value is invalid
1213 * DISP_E_OVERFLOW, if the value will not fit in the destination
1214 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1216 HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
1218 return _VarUI2FromDisp(pdispIn, lcid, pusOut);
1221 /************************************************************************
1222 * VarUI2FromBool (OLEAUT32.266)
1224 * Convert a VT_BOOL to a VT_UI2.
1228 * pusOut [O] Destination
1233 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
1235 return _VarUI2FromBool(boolIn, pusOut);
1238 /************************************************************************
1239 * VarUI2FromI1 (OLEAUT32.267)
1241 * Convert a VT_I1 to a VT_UI2.
1245 * pusOut [O] Destination
1249 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1251 HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
1253 return _VarUI2FromI1(cIn, pusOut);
1256 /************************************************************************
1257 * VarUI2FromUI4 (OLEAUT32.268)
1259 * Convert a VT_UI4 to a VT_UI2.
1263 * pusOut [O] Destination
1267 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1269 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
1271 return _VarUI2FromUI4(ulIn, pusOut);
1274 /************************************************************************
1275 * VarUI2FromDec (OLEAUT32.269)
1277 * Convert a VT_DECIMAL to a VT_UI2.
1281 * pusOut [O] Destination
1285 * Failure: E_INVALIDARG, if the source value is invalid
1286 * DISP_E_OVERFLOW, if the value will not fit in the destination
1288 HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
1293 hRet = _VarI8FromDec(pdecIn, &i64);
1295 if (SUCCEEDED(hRet))
1296 hRet = _VarUI2FromI8(i64, pusOut);
1300 /************************************************************************
1301 * VarUI2FromI8 (OLEAUT32.378)
1303 * Convert a VT_I8 to a VT_UI2.
1307 * pusOut [O] Destination
1311 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1313 HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
1315 return _VarUI2FromI8(llIn, pusOut);
1318 /************************************************************************
1319 * VarUI2FromUI8 (OLEAUT32.379)
1321 * Convert a VT_UI8 to a VT_UI2.
1325 * pusOut [O] Destination
1329 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1331 HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
1333 return _VarUI2FromUI8(ullIn, pusOut);
1339 /************************************************************************
1340 * VarI4FromUI1 (OLEAUT32.58)
1342 * Convert a VT_UI1 to a VT_I4.
1346 * piOut [O] Destination
1351 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
1353 return _VarI4FromUI1(bIn, piOut);
1356 /************************************************************************
1357 * VarI4FromI2 (OLEAUT32.59)
1359 * Convert a VT_I2 to a VT_I4.
1363 * piOut [O] Destination
1367 * Failure: E_INVALIDARG, if the source value is invalid
1368 * DISP_E_OVERFLOW, if the value will not fit in the destination
1370 HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
1372 return _VarI4FromI2(sIn, piOut);
1375 /************************************************************************
1376 * VarI4FromR4 (OLEAUT32.60)
1378 * Convert a VT_R4 to a VT_I4.
1382 * piOut [O] Destination
1386 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1388 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
1390 return _VarI4FromR4(fltIn, piOut);
1393 /************************************************************************
1394 * VarI4FromR8 (OLEAUT32.61)
1396 * Convert a VT_R8 to a VT_I4.
1400 * piOut [O] Destination
1404 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1407 * See VarI8FromR8() for details concerning rounding.
1409 HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
1411 if (dblIn < (double)I4_MIN || dblIn > (double)I4_MAX)
1412 return DISP_E_OVERFLOW;
1413 OLEAUT32_DutchRound(LONG, dblIn, *piOut);
1417 /************************************************************************
1418 * VarI4FromCy (OLEAUT32.62)
1420 * Convert a VT_CY to a VT_I4.
1424 * piOut [O] Destination
1428 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1430 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
1432 double d = cyIn.int64 / CY_MULTIPLIER_F;
1433 return _VarI4FromR8(d, piOut);
1436 /************************************************************************
1437 * VarI4FromDate (OLEAUT32.63)
1439 * Convert a VT_DATE to a VT_I4.
1443 * piOut [O] Destination
1447 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1449 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
1451 return _VarI4FromDate(dateIn, piOut);
1454 /************************************************************************
1455 * VarI4FromStr (OLEAUT32.64)
1457 * Convert a VT_BSTR to a VT_I4.
1461 * lcid [I] LCID for the conversion
1462 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1463 * piOut [O] Destination
1467 * Failure: E_INVALIDARG, if any parameter is invalid
1468 * DISP_E_OVERFLOW, if the value will not fit in the destination
1469 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1471 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
1473 return _VarI4FromStr(strIn, lcid, dwFlags, piOut);
1476 /************************************************************************
1477 * VarI4FromDisp (OLEAUT32.65)
1479 * Convert a VT_DISPATCH to a VT_I4.
1482 * pdispIn [I] Source
1483 * lcid [I] LCID for conversion
1484 * piOut [O] Destination
1488 * Failure: E_INVALIDARG, if the source value is invalid
1489 * DISP_E_OVERFLOW, if the value will not fit in the destination
1490 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1492 HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
1494 return _VarI4FromDisp(pdispIn, lcid, piOut);
1497 /************************************************************************
1498 * VarI4FromBool (OLEAUT32.66)
1500 * Convert a VT_BOOL to a VT_I4.
1504 * piOut [O] Destination
1509 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
1511 return _VarI4FromBool(boolIn, piOut);
1514 /************************************************************************
1515 * VarI4FromI1 (OLEAUT32.209)
1517 * Convert a VT_I4 to a VT_I4.
1521 * piOut [O] Destination
1526 HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
1528 return _VarI4FromI1(cIn, piOut);
1531 /************************************************************************
1532 * VarI4FromUI2 (OLEAUT32.210)
1534 * Convert a VT_UI2 to a VT_I4.
1538 * piOut [O] Destination
1543 HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
1545 return _VarI4FromUI2(usIn, piOut);
1548 /************************************************************************
1549 * VarI4FromUI4 (OLEAUT32.211)
1551 * Convert a VT_UI4 to a VT_I4.
1555 * piOut [O] Destination
1559 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1561 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
1563 return _VarI4FromUI4(ulIn, piOut);
1566 /************************************************************************
1567 * VarI4FromDec (OLEAUT32.212)
1569 * Convert a VT_DECIMAL to a VT_I4.
1573 * piOut [O] Destination
1577 * Failure: E_INVALIDARG, if pdecIn is invalid
1578 * DISP_E_OVERFLOW, if the value will not fit in the destination
1580 HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
1585 hRet = _VarI8FromDec(pdecIn, &i64);
1587 if (SUCCEEDED(hRet))
1588 hRet = _VarI4FromI8(i64, piOut);
1592 /************************************************************************
1593 * VarI4FromI8 (OLEAUT32.348)
1595 * Convert a VT_I8 to a VT_I4.
1599 * piOut [O] Destination
1603 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1605 HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
1607 return _VarI4FromI8(llIn, piOut);
1610 /************************************************************************
1611 * VarI4FromUI8 (OLEAUT32.349)
1613 * Convert a VT_UI8 to a VT_I4.
1617 * piOut [O] Destination
1621 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1623 HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
1625 return _VarI4FromUI8(ullIn, piOut);
1631 /************************************************************************
1632 * VarUI4FromUI1 (OLEAUT32.270)
1634 * Convert a VT_UI1 to a VT_UI4.
1638 * pulOut [O] Destination
1643 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
1645 return _VarUI4FromUI1(bIn, pulOut);
1648 /************************************************************************
1649 * VarUI4FromI2 (OLEAUT32.271)
1651 * Convert a VT_I2 to a VT_UI4.
1655 * pulOut [O] Destination
1659 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1661 HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
1663 return _VarUI4FromI2(sIn, pulOut);
1666 /************************************************************************
1667 * VarUI4FromI4 (OLEAUT32.272)
1669 * Convert a VT_I4 to a VT_UI4.
1673 * pulOut [O] Destination
1677 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1679 HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
1681 return _VarUI4FromI4(iIn, pulOut);
1684 /************************************************************************
1685 * VarUI4FromR4 (OLEAUT32.273)
1687 * Convert a VT_R4 to a VT_UI4.
1691 * pulOut [O] Destination
1695 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1697 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
1699 return _VarUI4FromR4(fltIn, pulOut);
1702 /************************************************************************
1703 * VarUI4FromR8 (OLEAUT32.274)
1705 * Convert a VT_R8 to a VT_UI4.
1709 * pulOut [O] Destination
1713 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1716 * See VarI8FromR8() for details concerning rounding.
1718 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
1720 if (dblIn < -0.5 || dblIn > (double)UI4_MAX)
1721 return DISP_E_OVERFLOW;
1722 OLEAUT32_DutchRound(ULONG, dblIn, *pulOut);
1726 /************************************************************************
1727 * VarUI4FromDate (OLEAUT32.275)
1729 * Convert a VT_DATE to a VT_UI4.
1733 * pulOut [O] Destination
1737 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1739 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
1741 return _VarUI4FromDate(dateIn, pulOut);
1744 /************************************************************************
1745 * VarUI4FromCy (OLEAUT32.276)
1747 * Convert a VT_CY to a VT_UI4.
1751 * pulOut [O] Destination
1755 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1757 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
1759 double d = cyIn.int64 / CY_MULTIPLIER_F;
1760 return _VarUI4FromR8(d, pulOut);
1763 /************************************************************************
1764 * VarUI4FromStr (OLEAUT32.277)
1766 * Convert a VT_BSTR to a VT_UI4.
1770 * lcid [I] LCID for the conversion
1771 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1772 * pulOut [O] Destination
1776 * Failure: E_INVALIDARG, if any parameter is invalid
1777 * DISP_E_OVERFLOW, if the value will not fit in the destination
1778 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1780 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
1782 return _VarUI4FromStr(strIn, lcid, dwFlags, pulOut);
1785 /************************************************************************
1786 * VarUI4FromDisp (OLEAUT32.278)
1788 * Convert a VT_DISPATCH to a VT_UI4.
1791 * pdispIn [I] Source
1792 * lcid [I] LCID for conversion
1793 * pulOut [O] Destination
1797 * Failure: E_INVALIDARG, if the source value is invalid
1798 * DISP_E_OVERFLOW, if the value will not fit in the destination
1799 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1801 HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
1803 return _VarUI4FromDisp(pdispIn, lcid, pulOut);
1806 /************************************************************************
1807 * VarUI4FromBool (OLEAUT32.279)
1809 * Convert a VT_BOOL to a VT_UI4.
1813 * pulOut [O] Destination
1818 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
1820 return _VarUI4FromBool(boolIn, pulOut);
1823 /************************************************************************
1824 * VarUI4FromI1 (OLEAUT32.280)
1826 * Convert a VT_I1 to a VT_UI4.
1830 * pulOut [O] Destination
1834 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1836 HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
1838 return _VarUI4FromI1(cIn, pulOut);
1841 /************************************************************************
1842 * VarUI4FromUI2 (OLEAUT32.281)
1844 * Convert a VT_UI2 to a VT_UI4.
1848 * pulOut [O] Destination
1853 HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
1855 return _VarUI4FromUI2(usIn, pulOut);
1858 /************************************************************************
1859 * VarUI4FromDec (OLEAUT32.282)
1861 * Convert a VT_DECIMAL to a VT_UI4.
1865 * pulOut [O] Destination
1869 * Failure: E_INVALIDARG, if pdecIn is invalid
1870 * DISP_E_OVERFLOW, if the value will not fit in the destination
1872 HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
1877 hRet = _VarI8FromDec(pdecIn, &i64);
1879 if (SUCCEEDED(hRet))
1880 hRet = _VarUI4FromI8(i64, pulOut);
1884 /************************************************************************
1885 * VarUI4FromI8 (OLEAUT32.425)
1887 * Convert a VT_I8 to a VT_UI4.
1891 * pulOut [O] Destination
1895 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1897 HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
1899 return _VarUI4FromI8(llIn, pulOut);
1902 /************************************************************************
1903 * VarUI4FromUI8 (OLEAUT32.426)
1905 * Convert a VT_UI8 to a VT_UI4.
1909 * pulOut [O] Destination
1913 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1915 HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
1917 return _VarUI4FromUI8(ullIn, pulOut);
1923 /************************************************************************
1924 * VarI8FromUI1 (OLEAUT32.333)
1926 * Convert a VT_UI1 to a VT_I8.
1930 * pi64Out [O] Destination
1935 HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
1937 return _VarI8FromUI1(bIn, pi64Out);
1941 /************************************************************************
1942 * VarI8FromI2 (OLEAUT32.334)
1944 * Convert a VT_I2 to a VT_I8.
1948 * pi64Out [O] Destination
1953 HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
1955 return _VarI8FromI2(sIn, pi64Out);
1958 /************************************************************************
1959 * VarI8FromR4 (OLEAUT32.335)
1961 * Convert a VT_R4 to a VT_I8.
1965 * pi64Out [O] Destination
1969 * Failure: E_INVALIDARG, if the source value is invalid
1970 * DISP_E_OVERFLOW, if the value will not fit in the destination
1972 HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
1974 return _VarI8FromR4(fltIn, pi64Out);
1977 /************************************************************************
1978 * VarI8FromR8 (OLEAUT32.336)
1980 * Convert a VT_R8 to a VT_I8.
1984 * pi64Out [O] Destination
1988 * Failure: E_INVALIDARG, if the source value is invalid
1989 * DISP_E_OVERFLOW, if the value will not fit in the destination
1992 * Only values that fit into 63 bits are accepted. Due to rounding issues,
1993 * very high or low values will not be accurately converted.
1995 * Numbers are rounded using Dutch rounding, as follows:
1997 *| Fractional Part Sign Direction Example
1998 *| --------------- ---- --------- -------
1999 *| < 0.5 + Down 0.4 -> 0.0
2000 *| < 0.5 - Up -0.4 -> 0.0
2001 *| > 0.5 + Up 0.6 -> 1.0
2002 *| < 0.5 - Up -0.6 -> -1.0
2003 *| = 0.5 + Up/Down Down if even, Up if odd
2004 *| = 0.5 - Up/Down Up if even, Down if odd
2006 * This system is often used in supermarkets.
2008 HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
2010 if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
2011 return DISP_E_OVERFLOW;
2012 OLEAUT32_DutchRound(LONG64, dblIn, *pi64Out);
2016 /************************************************************************
2017 * VarI8FromCy (OLEAUT32.337)
2019 * Convert a VT_CY to a VT_I8.
2023 * pi64Out [O] Destination
2029 * All negative numbers are rounded down by 1, including those that are
2030 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2031 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2034 HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
2036 *pi64Out = cyIn.int64 / CY_MULTIPLIER;
2039 (*pi64Out)--; /* Mimic Win32 bug */
2042 cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2044 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
2050 /************************************************************************
2051 * VarI8FromDate (OLEAUT32.338)
2053 * Convert a VT_DATE to a VT_I8.
2057 * pi64Out [O] Destination
2061 * Failure: E_INVALIDARG, if the source value is invalid
2062 * DISP_E_OVERFLOW, if the value will not fit in the destination
2063 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2065 HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
2067 return _VarI8FromDate(dateIn, pi64Out);
2070 /************************************************************************
2071 * VarI8FromStr (OLEAUT32.339)
2073 * Convert a VT_BSTR to a VT_I8.
2077 * lcid [I] LCID for the conversion
2078 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2079 * pi64Out [O] Destination
2083 * Failure: E_INVALIDARG, if the source value is invalid
2084 * DISP_E_OVERFLOW, if the value will not fit in the destination
2085 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2087 HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
2089 return _VarI8FromStr(strIn, lcid, dwFlags, pi64Out);
2092 /************************************************************************
2093 * VarI8FromDisp (OLEAUT32.340)
2095 * Convert a VT_DISPATCH to a VT_I8.
2098 * pdispIn [I] Source
2099 * lcid [I] LCID for conversion
2100 * pi64Out [O] Destination
2104 * Failure: E_INVALIDARG, if the source value is invalid
2105 * DISP_E_OVERFLOW, if the value will not fit in the destination
2106 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2108 HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
2110 return _VarI8FromDisp(pdispIn, lcid, pi64Out);
2113 /************************************************************************
2114 * VarI8FromBool (OLEAUT32.341)
2116 * Convert a VT_BOOL to a VT_I8.
2120 * pi64Out [O] Destination
2125 HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
2127 return _VarI8FromBool(boolIn, pi64Out);
2130 /************************************************************************
2131 * VarI8FromI1 (OLEAUT32.342)
2133 * Convert a VT_I1 to a VT_I8.
2137 * pi64Out [O] Destination
2142 HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
2144 return _VarI8FromI1(cIn, pi64Out);
2147 /************************************************************************
2148 * VarI8FromUI2 (OLEAUT32.343)
2150 * Convert a VT_UI2 to a VT_I8.
2154 * pi64Out [O] Destination
2159 HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
2161 return _VarI8FromUI2(usIn, pi64Out);
2164 /************************************************************************
2165 * VarI8FromUI4 (OLEAUT32.344)
2167 * Convert a VT_UI4 to a VT_I8.
2171 * pi64Out [O] Destination
2176 HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
2178 return _VarI8FromUI4(ulIn, pi64Out);
2181 /************************************************************************
2182 * VarI8FromDec (OLEAUT32.345)
2184 * Convert a VT_DECIMAL to a VT_I8.
2188 * pi64Out [O] Destination
2192 * Failure: E_INVALIDARG, if the source value is invalid
2193 * DISP_E_OVERFLOW, if the value will not fit in the destination
2195 HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
2197 if (!DEC_SCALE(pdecIn))
2199 /* This decimal is just a 96 bit integer */
2200 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2201 return E_INVALIDARG;
2203 if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
2204 return DISP_E_OVERFLOW;
2206 if (DEC_SIGN(pdecIn))
2207 *pi64Out = -DEC_LO64(pdecIn);
2209 *pi64Out = DEC_LO64(pdecIn);
2214 /* Decimal contains a floating point number */
2218 hRet = _VarR8FromDec(pdecIn, &dbl);
2219 if (SUCCEEDED(hRet))
2220 hRet = VarI8FromR8(dbl, pi64Out);
2225 /************************************************************************
2226 * VarI8FromUI8 (OLEAUT32.427)
2228 * Convert a VT_UI8 to a VT_I8.
2232 * pi64Out [O] Destination
2236 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2238 HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
2240 return _VarI8FromUI8(ullIn, pi64Out);
2246 /************************************************************************
2247 * VarUI8FromI8 (OLEAUT32.428)
2249 * Convert a VT_I8 to a VT_UI8.
2253 * pui64Out [O] Destination
2257 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2259 HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
2261 return _VarUI8FromI8(llIn, pui64Out);
2264 /************************************************************************
2265 * VarUI8FromUI1 (OLEAUT32.429)
2267 * Convert a VT_UI1 to a VT_UI8.
2271 * pui64Out [O] Destination
2276 HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
2278 return _VarUI8FromUI1(bIn, pui64Out);
2281 /************************************************************************
2282 * VarUI8FromI2 (OLEAUT32.430)
2284 * Convert a VT_I2 to a VT_UI8.
2288 * pui64Out [O] Destination
2293 HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
2295 return _VarUI8FromI2(sIn, pui64Out);
2298 /************************************************************************
2299 * VarUI8FromR4 (OLEAUT32.431)
2301 * Convert a VT_R4 to a VT_UI8.
2305 * pui64Out [O] Destination
2309 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2311 HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
2313 return _VarUI8FromR4(fltIn, pui64Out);
2316 /************************************************************************
2317 * VarUI8FromR8 (OLEAUT32.432)
2319 * Convert a VT_R8 to a VT_UI8.
2323 * pui64Out [O] Destination
2327 * Failure: E_INVALIDARG, if the source value is invalid
2328 * DISP_E_OVERFLOW, if the value will not fit in the destination
2331 * See VarI8FromR8() for details concerning rounding.
2333 HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
2335 if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
2336 return DISP_E_OVERFLOW;
2337 OLEAUT32_DutchRound(ULONG64, dblIn, *pui64Out);
2341 /************************************************************************
2342 * VarUI8FromCy (OLEAUT32.433)
2344 * Convert a VT_CY to a VT_UI8.
2348 * pui64Out [O] Destination
2352 * Failure: E_INVALIDARG, if the source value is invalid
2353 * DISP_E_OVERFLOW, if the value will not fit in the destination
2356 * Negative values >= -5000 will be converted to 0.
2358 HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
2362 if (cyIn.int64 < -CY_HALF)
2363 return DISP_E_OVERFLOW;
2368 *pui64Out = cyIn.int64 / CY_MULTIPLIER;
2370 cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2372 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
2378 /************************************************************************
2379 * VarUI8FromDate (OLEAUT32.434)
2381 * Convert a VT_DATE to a VT_UI8.
2385 * pui64Out [O] Destination
2389 * Failure: E_INVALIDARG, if the source value is invalid
2390 * DISP_E_OVERFLOW, if the value will not fit in the destination
2391 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2393 HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
2395 return _VarUI8FromDate(dateIn, pui64Out);
2398 /************************************************************************
2399 * VarUI8FromStr (OLEAUT32.435)
2401 * Convert a VT_BSTR to a VT_UI8.
2405 * lcid [I] LCID for the conversion
2406 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2407 * pui64Out [O] Destination
2411 * Failure: E_INVALIDARG, if the source value is invalid
2412 * DISP_E_OVERFLOW, if the value will not fit in the destination
2413 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2415 HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
2417 return _VarUI8FromStr(strIn, lcid, dwFlags, pui64Out);
2420 /************************************************************************
2421 * VarUI8FromDisp (OLEAUT32.436)
2423 * Convert a VT_DISPATCH to a VT_UI8.
2426 * pdispIn [I] Source
2427 * lcid [I] LCID for conversion
2428 * pui64Out [O] Destination
2432 * Failure: E_INVALIDARG, if the source value is invalid
2433 * DISP_E_OVERFLOW, if the value will not fit in the destination
2434 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2436 HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
2438 return _VarUI8FromDisp(pdispIn, lcid, pui64Out);
2441 /************************************************************************
2442 * VarUI8FromBool (OLEAUT32.437)
2444 * Convert a VT_BOOL to a VT_UI8.
2448 * pui64Out [O] Destination
2452 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2454 HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
2456 return _VarUI8FromBool(boolIn, pui64Out);
2458 /************************************************************************
2459 * VarUI8FromI1 (OLEAUT32.438)
2461 * Convert a VT_I1 to a VT_UI8.
2465 * pui64Out [O] Destination
2469 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2471 HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
2473 return _VarUI8FromI1(cIn, pui64Out);
2476 /************************************************************************
2477 * VarUI8FromUI2 (OLEAUT32.439)
2479 * Convert a VT_UI2 to a VT_UI8.
2483 * pui64Out [O] Destination
2488 HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
2490 return _VarUI8FromUI2(usIn, pui64Out);
2493 /************************************************************************
2494 * VarUI8FromUI4 (OLEAUT32.440)
2496 * Convert a VT_UI4 to a VT_UI8.
2500 * pui64Out [O] Destination
2505 HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
2507 return _VarUI8FromUI4(ulIn, pui64Out);
2510 /************************************************************************
2511 * VarUI8FromDec (OLEAUT32.441)
2513 * Convert a VT_DECIMAL to a VT_UI8.
2517 * pui64Out [O] Destination
2521 * Failure: E_INVALIDARG, if the source value is invalid
2522 * DISP_E_OVERFLOW, if the value will not fit in the destination
2525 * Under native Win32, if the source value has a scale of 0, its sign is
2526 * ignored, i.e. this function takes the absolute value rather than fail
2527 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2528 * (use VarAbs() on pDecIn first if you really want this behaviour).
2530 HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
2532 if (!DEC_SCALE(pdecIn))
2534 /* This decimal is just a 96 bit integer */
2535 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2536 return E_INVALIDARG;
2538 if (DEC_HI32(pdecIn))
2539 return DISP_E_OVERFLOW;
2541 if (DEC_SIGN(pdecIn))
2543 WARN("Sign would be ignored under Win32!\n");
2544 return DISP_E_OVERFLOW;
2547 *pui64Out = DEC_LO64(pdecIn);
2552 /* Decimal contains a floating point number */
2556 hRet = _VarR8FromDec(pdecIn, &dbl);
2557 if (SUCCEEDED(hRet))
2558 hRet = VarUI8FromR8(dbl, pui64Out);
2566 /************************************************************************
2567 * VarR4FromUI1 (OLEAUT32.68)
2569 * Convert a VT_UI1 to a VT_R4.
2573 * pFltOut [O] Destination
2578 HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
2580 return _VarR4FromUI1(bIn, pFltOut);
2583 /************************************************************************
2584 * VarR4FromI2 (OLEAUT32.69)
2586 * Convert a VT_I2 to a VT_R4.
2590 * pFltOut [O] Destination
2595 HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
2597 return _VarR4FromI2(sIn, pFltOut);
2600 /************************************************************************
2601 * VarR4FromI4 (OLEAUT32.70)
2603 * Convert a VT_I4 to a VT_R4.
2607 * pFltOut [O] Destination
2612 HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
2614 return _VarR4FromI4(lIn, pFltOut);
2617 /************************************************************************
2618 * VarR4FromR8 (OLEAUT32.71)
2620 * Convert a VT_R8 to a VT_R4.
2624 * pFltOut [O] Destination
2628 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2630 HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
2632 return _VarR4FromR8(dblIn, pFltOut);
2635 /************************************************************************
2636 * VarR4FromCy (OLEAUT32.72)
2638 * Convert a VT_CY to a VT_R4.
2642 * pFltOut [O] Destination
2647 HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
2649 return _VarR4FromCy(cyIn, pFltOut);
2652 /************************************************************************
2653 * VarR4FromDate (OLEAUT32.73)
2655 * Convert a VT_DATE to a VT_R4.
2659 * pFltOut [O] Destination
2663 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2665 HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
2667 return _VarR4FromDate(dateIn, pFltOut);
2670 /************************************************************************
2671 * VarR4FromStr (OLEAUT32.74)
2673 * Convert a VT_BSTR to a VT_R4.
2677 * lcid [I] LCID for the conversion
2678 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2679 * pFltOut [O] Destination
2683 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2684 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2686 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
2688 return _VarR4FromStr(strIn, lcid, dwFlags, pFltOut);
2691 /************************************************************************
2692 * VarR4FromDisp (OLEAUT32.75)
2694 * Convert a VT_DISPATCH to a VT_R4.
2697 * pdispIn [I] Source
2698 * lcid [I] LCID for conversion
2699 * pFltOut [O] Destination
2703 * Failure: E_INVALIDARG, if the source value is invalid
2704 * DISP_E_OVERFLOW, if the value will not fit in the destination
2705 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2707 HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
2709 return _VarR4FromDisp(pdispIn, lcid, pFltOut);
2712 /************************************************************************
2713 * VarR4FromBool (OLEAUT32.76)
2715 * Convert a VT_BOOL to a VT_R4.
2719 * pFltOut [O] Destination
2724 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
2726 return _VarR4FromBool(boolIn, pFltOut);
2729 /************************************************************************
2730 * VarR4FromI1 (OLEAUT32.213)
2732 * Convert a VT_I1 to a VT_R4.
2736 * pFltOut [O] Destination
2740 * Failure: E_INVALIDARG, if the source value is invalid
2741 * DISP_E_OVERFLOW, if the value will not fit in the destination
2742 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2744 HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
2746 return _VarR4FromI1(cIn, pFltOut);
2749 /************************************************************************
2750 * VarR4FromUI2 (OLEAUT32.214)
2752 * Convert a VT_UI2 to a VT_R4.
2756 * pFltOut [O] Destination
2760 * Failure: E_INVALIDARG, if the source value is invalid
2761 * DISP_E_OVERFLOW, if the value will not fit in the destination
2762 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2764 HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
2766 return _VarR4FromUI2(usIn, pFltOut);
2769 /************************************************************************
2770 * VarR4FromUI4 (OLEAUT32.215)
2772 * Convert a VT_UI4 to a VT_R4.
2776 * pFltOut [O] Destination
2780 * Failure: E_INVALIDARG, if the source value is invalid
2781 * DISP_E_OVERFLOW, if the value will not fit in the destination
2782 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2784 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
2786 return _VarR4FromUI4(ulIn, pFltOut);
2789 /************************************************************************
2790 * VarR4FromDec (OLEAUT32.216)
2792 * Convert a VT_DECIMAL to a VT_R4.
2796 * pFltOut [O] Destination
2800 * Failure: E_INVALIDARG, if the source value is invalid.
2802 HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
2804 BYTE scale = DEC_SCALE(pDecIn);
2808 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
2809 return E_INVALIDARG;
2814 if (DEC_SIGN(pDecIn))
2817 if (DEC_HI32(pDecIn))
2819 highPart = (double)DEC_HI32(pDecIn) / (double)divisor;
2825 *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
2829 /************************************************************************
2830 * VarR4FromI8 (OLEAUT32.360)
2832 * Convert a VT_I8 to a VT_R4.
2836 * pFltOut [O] Destination
2841 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2843 return _VarR4FromI8(llIn, pFltOut);
2846 /************************************************************************
2847 * VarR4FromUI8 (OLEAUT32.361)
2849 * Convert a VT_UI8 to a VT_R4.
2853 * pFltOut [O] Destination
2858 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
2860 return _VarR4FromUI8(ullIn, pFltOut);
2863 /************************************************************************
2864 * VarR4CmpR8 (OLEAUT32.316)
2866 * Compare a VT_R4 to a VT_R8.
2869 * fltLeft [I] Source
2870 * dblRight [I] Value to compare
2873 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
2874 * equal to or greater than dblRight respectively.
2876 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
2878 if (fltLeft < dblRight)
2880 else if (fltLeft > dblRight)
2888 /************************************************************************
2889 * VarR8FromUI1 (OLEAUT32.78)
2891 * Convert a VT_UI1 to a VT_R8.
2895 * pDblOut [O] Destination
2900 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
2902 return _VarR8FromUI1(bIn, pDblOut);
2905 /************************************************************************
2906 * VarR8FromI2 (OLEAUT32.79)
2908 * Convert a VT_I2 to a VT_R8.
2912 * pDblOut [O] Destination
2917 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
2919 return _VarR8FromI2(sIn, pDblOut);
2922 /************************************************************************
2923 * VarR8FromI4 (OLEAUT32.80)
2925 * Convert a VT_I4 to a VT_R8.
2929 * pDblOut [O] Destination
2934 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
2936 return _VarR8FromI4(lIn, pDblOut);
2939 /************************************************************************
2940 * VarR8FromR4 (OLEAUT32.81)
2942 * Convert a VT_R4 to a VT_R8.
2946 * pDblOut [O] Destination
2951 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
2953 return _VarR8FromR4(fltIn, pDblOut);
2956 /************************************************************************
2957 * VarR8FromCy (OLEAUT32.82)
2959 * Convert a VT_CY to a VT_R8.
2963 * pDblOut [O] Destination
2968 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
2970 return _VarR8FromCy(cyIn, pDblOut);
2973 /************************************************************************
2974 * VarR8FromDate (OLEAUT32.83)
2976 * Convert a VT_DATE to a VT_R8.
2980 * pDblOut [O] Destination
2985 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
2987 return _VarR8FromDate(dateIn, pDblOut);
2990 /************************************************************************
2991 * VarR8FromStr (OLEAUT32.84)
2993 * Convert a VT_BSTR to a VT_R8.
2997 * lcid [I] LCID for the conversion
2998 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2999 * pDblOut [O] Destination
3003 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3004 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3006 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3008 return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
3011 /************************************************************************
3012 * VarR8FromDisp (OLEAUT32.85)
3014 * Convert a VT_DISPATCH to a VT_R8.
3017 * pdispIn [I] Source
3018 * lcid [I] LCID for conversion
3019 * pDblOut [O] Destination
3023 * Failure: E_INVALIDARG, if the source value is invalid
3024 * DISP_E_OVERFLOW, if the value will not fit in the destination
3025 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3027 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3029 return _VarR8FromDisp(pdispIn, lcid, pDblOut);
3032 /************************************************************************
3033 * VarR8FromBool (OLEAUT32.86)
3035 * Convert a VT_BOOL to a VT_R8.
3039 * pDblOut [O] Destination
3044 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
3046 return _VarR8FromBool(boolIn, pDblOut);
3049 /************************************************************************
3050 * VarR8FromI1 (OLEAUT32.217)
3052 * Convert a VT_I1 to a VT_R8.
3056 * pDblOut [O] Destination
3060 * Failure: E_INVALIDARG, if the source value is invalid
3061 * DISP_E_OVERFLOW, if the value will not fit in the destination
3062 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3064 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3066 return _VarR8FromI1(cIn, pDblOut);
3069 /************************************************************************
3070 * VarR8FromUI2 (OLEAUT32.218)
3072 * Convert a VT_UI2 to a VT_R8.
3076 * pDblOut [O] Destination
3080 * Failure: E_INVALIDARG, if the source value is invalid
3081 * DISP_E_OVERFLOW, if the value will not fit in the destination
3082 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3084 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3086 return _VarR8FromUI2(usIn, pDblOut);
3089 /************************************************************************
3090 * VarR8FromUI4 (OLEAUT32.219)
3092 * Convert a VT_UI4 to a VT_R8.
3096 * pDblOut [O] Destination
3100 * Failure: E_INVALIDARG, if the source value is invalid
3101 * DISP_E_OVERFLOW, if the value will not fit in the destination
3102 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3104 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3106 return _VarR8FromUI4(ulIn, pDblOut);
3109 /************************************************************************
3110 * VarR8FromDec (OLEAUT32.220)
3112 * Convert a VT_DECIMAL to a VT_R8.
3116 * pDblOut [O] Destination
3120 * Failure: E_INVALIDARG, if the source value is invalid.
3122 HRESULT WINAPI VarR8FromDec(DECIMAL* pDecIn, double *pDblOut)
3124 BYTE scale = DEC_SCALE(pDecIn);
3125 double divisor = 1.0, highPart;
3127 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
3128 return E_INVALIDARG;
3133 if (DEC_SIGN(pDecIn))
3136 if (DEC_HI32(pDecIn))
3138 highPart = (double)DEC_HI32(pDecIn) / divisor;
3144 *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
3148 /************************************************************************
3149 * VarR8FromI8 (OLEAUT32.362)
3151 * Convert a VT_I8 to a VT_R8.
3155 * pDblOut [O] Destination
3160 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3162 return _VarR8FromI8(llIn, pDblOut);
3165 /************************************************************************
3166 * VarR8FromUI8 (OLEAUT32.363)
3168 * Convert a VT_UI8 to a VT_R8.
3172 * pDblOut [O] Destination
3177 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3179 return _VarR8FromUI8(ullIn, pDblOut);
3182 /************************************************************************
3183 * VarR8Pow (OLEAUT32.315)
3185 * Raise a VT_R8 to a power.
3188 * dblLeft [I] Source
3189 * dblPow [I] Power to raise dblLeft by
3190 * pDblOut [O] Destination
3193 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3195 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3197 *pDblOut = pow(dblLeft, dblPow);
3201 /************************************************************************
3202 * VarR8Round (OLEAUT32.317)
3204 * Round a VT_R8 to a given number of decimal points.
3208 * nDig [I] Number of decimal points to round to
3209 * pDblOut [O] Destination for rounded number
3212 * Success: S_OK. pDblOut is rounded to nDig digits.
3213 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3216 * The native version of this function rounds using the internal
3217 * binary representation of the number. Wine uses the dutch rounding
3218 * convention, so therefore small differences can occur in the value returned.
3219 * MSDN says that you should use your own rounding function if you want
3220 * rounding to be predictable in your application.
3222 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3224 double scale, whole, fract;
3227 return E_INVALIDARG;
3229 scale = pow(10.0, nDig);
3232 whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3233 fract = dblIn - whole;
3236 dblIn = whole + 1.0;
3237 else if (fract == 0.5)
3238 dblIn = whole + fmod(whole, 2.0);
3239 else if (fract >= 0.0)
3241 else if (fract == -0.5)
3242 dblIn = whole - fmod(whole, 2.0);
3243 else if (fract > -0.5)
3246 dblIn = whole - 1.0;
3248 *pDblOut = dblIn / scale;
3255 /* Powers of 10 from 0..4 D.P. */
3256 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3257 CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
3259 /************************************************************************
3260 * VarCyFromUI1 (OLEAUT32.98)
3262 * Convert a VT_UI1 to a VT_CY.
3266 * pCyOut [O] Destination
3270 * Failure: E_INVALIDARG, if the source value is invalid
3271 * DISP_E_OVERFLOW, if the value will not fit in the destination
3272 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3274 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
3276 return _VarCyFromUI1(bIn, pCyOut);
3279 /************************************************************************
3280 * VarCyFromI2 (OLEAUT32.99)
3282 * Convert a VT_I2 to a VT_CY.
3286 * pCyOut [O] Destination
3290 * Failure: E_INVALIDARG, if the source value is invalid
3291 * DISP_E_OVERFLOW, if the value will not fit in the destination
3292 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3294 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
3296 return _VarCyFromI2(sIn, pCyOut);
3299 /************************************************************************
3300 * VarCyFromI4 (OLEAUT32.100)
3302 * Convert a VT_I4 to a VT_CY.
3306 * pCyOut [O] Destination
3310 * Failure: E_INVALIDARG, if the source value is invalid
3311 * DISP_E_OVERFLOW, if the value will not fit in the destination
3312 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3314 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
3316 return _VarCyFromI4(lIn, pCyOut);
3319 /************************************************************************
3320 * VarCyFromR4 (OLEAUT32.101)
3322 * Convert a VT_R4 to a VT_CY.
3326 * pCyOut [O] Destination
3330 * Failure: E_INVALIDARG, if the source value is invalid
3331 * DISP_E_OVERFLOW, if the value will not fit in the destination
3332 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3334 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
3336 return _VarCyFromR4(fltIn, pCyOut);
3339 /************************************************************************
3340 * VarCyFromR8 (OLEAUT32.102)
3342 * Convert a VT_R8 to a VT_CY.
3346 * pCyOut [O] Destination
3350 * Failure: E_INVALIDARG, if the source value is invalid
3351 * DISP_E_OVERFLOW, if the value will not fit in the destination
3352 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3354 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3356 #if defined(__GNUC__) && defined(__i386__)
3357 /* This code gives identical results to Win32 on Intel.
3358 * Here we use fp exceptions to catch overflows when storing the value.
3360 static const unsigned short r8_fpcontrol = 0x137f;
3361 static const double r8_multiplier = CY_MULTIPLIER_F;
3362 unsigned short old_fpcontrol, result_fpstatus;
3364 /* Clear exceptions, save the old fp state and load the new state */
3365 __asm__ __volatile__( "fnclex" );
3366 __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
3367 __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
3368 /* Perform the conversion. */
3369 __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
3370 __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
3371 __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
3372 /* Save the resulting fp state, load the old state and clear exceptions */
3373 __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
3374 __asm__ __volatile__( "fnclex" );
3375 __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
3377 if (result_fpstatus & 0x9) /* Overflow | Invalid */
3378 return DISP_E_OVERFLOW;
3381 /* This version produces slightly different results for boundary cases */
3382 if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3383 return DISP_E_OVERFLOW;
3384 dblIn *= CY_MULTIPLIER_F;
3385 OLEAUT32_DutchRound(LONG64, dblIn, pCyOut->int64);
3390 /************************************************************************
3391 * VarCyFromDate (OLEAUT32.103)
3393 * Convert a VT_DATE to a VT_CY.
3397 * pCyOut [O] Destination
3401 * Failure: E_INVALIDARG, if the source value is invalid
3402 * DISP_E_OVERFLOW, if the value will not fit in the destination
3403 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3405 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
3407 return _VarCyFromDate(dateIn, pCyOut);
3410 /************************************************************************
3411 * VarCyFromStr (OLEAUT32.104)
3413 * Convert a VT_BSTR to a VT_CY.
3417 * lcid [I] LCID for the conversion
3418 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3419 * pCyOut [O] Destination
3423 * Failure: E_INVALIDARG, if the source value is invalid
3424 * DISP_E_OVERFLOW, if the value will not fit in the destination
3425 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3427 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
3429 return _VarCyFromStr(strIn, lcid, dwFlags, pCyOut);
3432 /************************************************************************
3433 * VarCyFromDisp (OLEAUT32.105)
3435 * Convert a VT_DISPATCH to a VT_CY.
3438 * pdispIn [I] Source
3439 * lcid [I] LCID for conversion
3440 * pCyOut [O] Destination
3444 * Failure: E_INVALIDARG, if the source value is invalid
3445 * DISP_E_OVERFLOW, if the value will not fit in the destination
3446 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3448 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
3450 return _VarCyFromDisp(pdispIn, lcid, pCyOut);
3453 /************************************************************************
3454 * VarCyFromBool (OLEAUT32.106)
3456 * Convert a VT_BOOL to a VT_CY.
3460 * pCyOut [O] Destination
3464 * Failure: E_INVALIDARG, if the source value is invalid
3465 * DISP_E_OVERFLOW, if the value will not fit in the destination
3466 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3469 * While the sign of the boolean is stored in the currency, the value is
3470 * converted to either 0 or 1.
3472 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
3474 return _VarCyFromBool(boolIn, pCyOut);
3477 /************************************************************************
3478 * VarCyFromI1 (OLEAUT32.225)
3480 * Convert a VT_I1 to a VT_CY.
3484 * pCyOut [O] Destination
3488 * Failure: E_INVALIDARG, if the source value is invalid
3489 * DISP_E_OVERFLOW, if the value will not fit in the destination
3490 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3492 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3494 return _VarCyFromI1(cIn, pCyOut);
3497 /************************************************************************
3498 * VarCyFromUI2 (OLEAUT32.226)
3500 * Convert a VT_UI2 to a VT_CY.
3504 * pCyOut [O] Destination
3508 * Failure: E_INVALIDARG, if the source value is invalid
3509 * DISP_E_OVERFLOW, if the value will not fit in the destination
3510 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3512 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
3514 return _VarCyFromUI2(usIn, pCyOut);
3517 /************************************************************************
3518 * VarCyFromUI4 (OLEAUT32.227)
3520 * Convert a VT_UI4 to a VT_CY.
3524 * pCyOut [O] Destination
3528 * Failure: E_INVALIDARG, if the source value is invalid
3529 * DISP_E_OVERFLOW, if the value will not fit in the destination
3530 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3532 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
3534 return _VarCyFromUI4(ulIn, pCyOut);
3537 /************************************************************************
3538 * VarCyFromDec (OLEAUT32.228)
3540 * Convert a VT_DECIMAL to a VT_CY.
3544 * pCyOut [O] Destination
3548 * Failure: E_INVALIDARG, if the source value is invalid
3549 * DISP_E_OVERFLOW, if the value will not fit in the destination
3550 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3552 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
3557 hRet = VarDecRound(pdecIn, 4, &rounded);
3559 if (SUCCEEDED(hRet))
3563 if (DEC_HI32(&rounded))
3564 return DISP_E_OVERFLOW;
3566 /* Note: Without the casts this promotes to int64 which loses precision */
3567 d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
3568 if (DEC_SIGN(&rounded))
3570 return _VarCyFromR8(d, pCyOut);
3575 /************************************************************************
3576 * VarCyFromI8 (OLEAUT32.366)
3578 * Convert a VT_I8 to a VT_CY.
3582 * pCyOut [O] Destination
3586 * Failure: E_INVALIDARG, if the source value is invalid
3587 * DISP_E_OVERFLOW, if the value will not fit in the destination
3588 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3590 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
3592 return _VarCyFromI8(llIn, pCyOut);
3595 /************************************************************************
3596 * VarCyFromUI8 (OLEAUT32.375)
3598 * Convert a VT_UI8 to a VT_CY.
3602 * pCyOut [O] Destination
3606 * Failure: E_INVALIDARG, if the source value is invalid
3607 * DISP_E_OVERFLOW, if the value will not fit in the destination
3608 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3610 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
3612 return _VarCyFromUI8(ullIn, pCyOut);
3615 /************************************************************************
3616 * VarCyAdd (OLEAUT32.299)
3618 * Add one CY to another.
3622 * cyRight [I] Value to add
3623 * pCyOut [O] Destination
3627 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3629 HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
3632 _VarR8FromCy(cyLeft, &l);
3633 _VarR8FromCy(cyRight, &r);
3635 return _VarCyFromR8(l, pCyOut);
3638 /************************************************************************
3639 * VarCyMul (OLEAUT32.303)
3641 * Multiply one CY by another.
3645 * cyRight [I] Value to multiply by
3646 * pCyOut [O] Destination
3650 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3652 HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
3655 _VarR8FromCy(cyLeft, &l);
3656 _VarR8FromCy(cyRight, &r);
3658 return _VarCyFromR8(l, pCyOut);
3661 /************************************************************************
3662 * VarCyMulI4 (OLEAUT32.304)
3664 * Multiply one CY by a VT_I4.
3668 * lRight [I] Value to multiply by
3669 * pCyOut [O] Destination
3673 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3675 HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
3679 _VarR8FromCy(cyLeft, &d);
3681 return _VarCyFromR8(d, pCyOut);
3684 /************************************************************************
3685 * VarCySub (OLEAUT32.305)
3687 * Subtract one CY from another.
3691 * cyRight [I] Value to subtract
3692 * pCyOut [O] Destination
3696 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3698 HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
3701 _VarR8FromCy(cyLeft, &l);
3702 _VarR8FromCy(cyRight, &r);
3704 return _VarCyFromR8(l, pCyOut);
3707 /************************************************************************
3708 * VarCyAbs (OLEAUT32.306)
3710 * Convert a VT_CY into its absolute value.
3714 * pCyOut [O] Destination
3717 * Success: S_OK. pCyOut contains the absolute value.
3718 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3720 HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
3722 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3723 return DISP_E_OVERFLOW;
3725 pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3729 /************************************************************************
3730 * VarCyFix (OLEAUT32.307)
3732 * Return the integer part of a VT_CY.
3736 * pCyOut [O] Destination
3740 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3743 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3744 * negative numbers away from 0, while this function rounds them towards zero.
3746 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
3748 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3749 pCyOut->int64 *= CY_MULTIPLIER;
3753 /************************************************************************
3754 * VarCyInt (OLEAUT32.308)
3756 * Return the integer part of a VT_CY.
3760 * pCyOut [O] Destination
3764 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3767 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3768 * negative numbers towards 0, while this function rounds them away from zero.
3770 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
3772 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3773 pCyOut->int64 *= CY_MULTIPLIER;
3775 if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3777 pCyOut->int64 -= CY_MULTIPLIER;
3782 /************************************************************************
3783 * VarCyNeg (OLEAUT32.309)
3785 * Change the sign of a VT_CY.
3789 * pCyOut [O] Destination
3793 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3795 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
3797 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3798 return DISP_E_OVERFLOW;
3800 pCyOut->int64 = -cyIn.int64;
3804 /************************************************************************
3805 * VarCyRound (OLEAUT32.310)
3807 * Change the precision of a VT_CY.
3811 * cDecimals [I] New number of decimals to keep
3812 * pCyOut [O] Destination
3816 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3818 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
3821 return E_INVALIDARG;
3825 /* Rounding to more precision than we have */
3831 double d, div = CY_Divisors[cDecimals];
3833 _VarR8FromCy(cyIn, &d);
3835 OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3836 d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3837 OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3842 /************************************************************************
3843 * VarCyCmp (OLEAUT32.311)
3845 * Compare two VT_CY values.
3849 * cyRight [I] Value to compare
3852 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
3853 * compare is less, equal or greater than source respectively.
3854 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
3856 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
3861 /* Subtract right from left, and compare the result to 0 */
3862 hRet = VarCySub(cyLeft, cyRight, &result);
3864 if (SUCCEEDED(hRet))
3866 if (result.int64 < 0)
3867 hRet = (HRESULT)VARCMP_LT;
3868 else if (result.int64 > 0)
3869 hRet = (HRESULT)VARCMP_GT;
3871 hRet = (HRESULT)VARCMP_EQ;
3876 /************************************************************************
3877 * VarCyCmpR8 (OLEAUT32.312)
3879 * Compare a VT_CY to a double
3882 * cyLeft [I] Currency Source
3883 * dblRight [I] double to compare to cyLeft
3886 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
3887 * less than, equal to or greater than cyLeft respectively.
3888 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
3890 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
3895 hRet = _VarCyFromR8(dblRight, &cyRight);
3897 if (SUCCEEDED(hRet))
3898 hRet = VarCyCmp(cyLeft, cyRight);
3903 /************************************************************************
3904 * VarCyMulI8 (OLEAUT32.329)
3906 * Multiply a VT_CY by a VT_I8.
3910 * llRight [I] Value to multiply by
3911 * pCyOut [O] Destination
3915 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3917 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
3921 _VarR8FromCy(cyLeft, &d);
3922 d = d * (double)llRight;
3923 return _VarCyFromR8(d, pCyOut);
3929 /************************************************************************
3930 * VarDecFromUI1 (OLEAUT32.190)
3932 * Convert a VT_UI1 to a DECIMAL.
3936 * pDecOut [O] Destination
3941 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
3943 return _VarDecFromUI1(bIn, pDecOut);
3946 /************************************************************************
3947 * VarDecFromI2 (OLEAUT32.191)
3949 * Convert a VT_I2 to a DECIMAL.
3953 * pDecOut [O] Destination
3958 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
3960 return _VarDecFromI2(sIn, pDecOut);
3963 /************************************************************************
3964 * VarDecFromI4 (OLEAUT32.192)
3966 * Convert a VT_I4 to a DECIMAL.
3970 * pDecOut [O] Destination
3975 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
3977 DEC_HI32(pDecOut) = 0;
3978 DEC_MID32(pDecOut) = 0;
3982 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
3983 DEC_LO32(pDecOut) = -lIn;
3987 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
3988 DEC_LO32(pDecOut) = lIn;
3993 /************************************************************************
3994 * VarDecFromR4 (OLEAUT32.193)
3996 * Convert a VT_R4 to a DECIMAL.
4000 * pDecOut [O] Destination
4005 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
4009 sprintfW( buff, szFloatFormatW, fltIn );
4010 return _VarDecFromStr(buff, LOCALE_SYSTEM_DEFAULT, 0, pDecOut);
4013 /************************************************************************
4014 * VarDecFromR8 (OLEAUT32.194)
4016 * Convert a VT_R8 to a DECIMAL.
4020 * pDecOut [O] Destination
4025 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4029 sprintfW( buff, szDoubleFormatW, dblIn );
4030 return _VarDecFromStr(buff, LOCALE_USER_DEFAULT, 0, pDecOut);
4033 /************************************************************************
4034 * VarDecFromDate (OLEAUT32.195)
4036 * Convert a VT_DATE to a DECIMAL.
4040 * pDecOut [O] Destination
4045 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
4047 return _VarDecFromDate(dateIn, pDecOut);
4050 /************************************************************************
4051 * VarDecFromCy (OLEAUT32.196)
4053 * Convert a VT_CY to a DECIMAL.
4057 * pDecOut [O] Destination
4062 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
4064 DEC_HI32(pDecOut) = 0;
4066 /* Note: This assumes 2s complement integer representation */
4067 if (cyIn.s.Hi & 0x80000000)
4069 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4070 DEC_LO64(pDecOut) = -cyIn.int64;
4074 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4075 DEC_MID32(pDecOut) = cyIn.s.Hi;
4076 DEC_LO32(pDecOut) = cyIn.s.Lo;
4081 /************************************************************************
4082 * VarDecFromStr (OLEAUT32.197)
4084 * Convert a VT_BSTR to a DECIMAL.
4088 * lcid [I] LCID for the conversion
4089 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4090 * pDecOut [O] Destination
4094 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4096 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
4098 return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
4101 /************************************************************************
4102 * VarDecFromDisp (OLEAUT32.198)
4104 * Convert a VT_DISPATCH to a DECIMAL.
4107 * pdispIn [I] Source
4108 * lcid [I] LCID for conversion
4109 * pDecOut [O] Destination
4113 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4115 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
4117 return _VarDecFromDisp(pdispIn, lcid, pDecOut);
4120 /************************************************************************
4121 * VarDecFromBool (OLEAUT32.199)
4123 * Convert a VT_BOOL to a DECIMAL.
4127 * pDecOut [O] Destination
4133 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4135 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
4137 DEC_HI32(pDecOut) = 0;
4138 DEC_MID32(pDecOut) = 0;
4141 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4142 DEC_LO32(pDecOut) = 1;
4146 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4147 DEC_LO32(pDecOut) = 0;
4152 /************************************************************************
4153 * VarDecFromI1 (OLEAUT32.241)
4155 * Convert a VT_I1 to a DECIMAL.
4159 * pDecOut [O] Destination
4164 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4166 return _VarDecFromI1(cIn, pDecOut);
4169 /************************************************************************
4170 * VarDecFromUI2 (OLEAUT32.242)
4172 * Convert a VT_UI2 to a DECIMAL.
4176 * pDecOut [O] Destination
4181 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
4183 return _VarDecFromUI2(usIn, pDecOut);
4186 /************************************************************************
4187 * VarDecFromUI4 (OLEAUT32.243)
4189 * Convert a VT_UI4 to a DECIMAL.
4193 * pDecOut [O] Destination
4198 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
4200 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4201 DEC_HI32(pDecOut) = 0;
4202 DEC_MID32(pDecOut) = 0;
4203 DEC_LO32(pDecOut) = ulIn;
4207 /************************************************************************
4208 * VarDecFromI8 (OLEAUT32.374)
4210 * Convert a VT_I8 to a DECIMAL.
4214 * pDecOut [O] Destination
4219 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
4221 PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4223 DEC_HI32(pDecOut) = 0;
4225 /* Note: This assumes 2s complement integer representation */
4226 if (pLi->u.HighPart & 0x80000000)
4228 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4229 DEC_LO64(pDecOut) = -pLi->QuadPart;
4233 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4234 DEC_MID32(pDecOut) = pLi->u.HighPart;
4235 DEC_LO32(pDecOut) = pLi->u.LowPart;
4240 /************************************************************************
4241 * VarDecFromUI8 (OLEAUT32.375)
4243 * Convert a VT_UI8 to a DECIMAL.
4247 * pDecOut [O] Destination
4252 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
4254 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4255 DEC_HI32(pDecOut) = 0;
4256 DEC_LO64(pDecOut) = ullIn;
4260 /* Make two DECIMALS the same scale; used by math functions below */
4261 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4262 const DECIMAL** ppDecRight,
4265 static DECIMAL scaleFactor;
4268 HRESULT hRet = S_OK;
4270 if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4271 return E_INVALIDARG;
4273 DEC_LO32(&scaleFactor) = 10;
4275 i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4278 return S_OK; /* Same scale */
4280 if (scaleAmount > 0)
4282 decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4283 *ppDecRight = pDecOut;
4287 decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4288 *ppDecLeft = pDecOut;
4289 i = scaleAmount = -scaleAmount;
4292 if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
4293 return DISP_E_OVERFLOW; /* Can't scale up */
4295 /* Multiply up the value to be scaled by the correct amount */
4296 while (SUCCEEDED(hRet) && i--)
4298 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4299 hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
4302 DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
4306 /* Add two unsigned 32 bit values with overflow */
4307 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4309 ULARGE_INTEGER ul64;
4311 ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4312 *pulHigh = ul64.u.HighPart;
4313 return ul64.u.LowPart;
4316 /* Subtract two unsigned 32 bit values with underflow */
4317 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4320 ULARGE_INTEGER ul64;
4322 ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4323 if (ulLeft < ulRight)
4326 if (ul64.QuadPart > (ULONG64)*pulHigh)
4327 ul64.QuadPart -= (ULONG64)*pulHigh;
4330 ul64.QuadPart -= (ULONG64)*pulHigh;
4334 ul64.u.HighPart = -ul64.u.HighPart ;
4336 *pulHigh = ul64.u.HighPart;
4337 return ul64.u.LowPart;
4340 /* Multiply two unsigned 32 bit values with overflow */
4341 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4343 ULARGE_INTEGER ul64;
4345 ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4346 *pulHigh = ul64.u.HighPart;
4347 return ul64.u.LowPart;
4350 /* Compare two decimals that have the same scale */
4351 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4353 if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4354 (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4356 else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4361 /************************************************************************
4362 * VarDecAdd (OLEAUT32.177)
4364 * Add one DECIMAL to another.
4367 * pDecLeft [I] Source
4368 * pDecRight [I] Value to add
4369 * pDecOut [O] Destination
4373 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4375 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4380 hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
4382 if (SUCCEEDED(hRet))
4384 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4386 BYTE sign = DECIMAL_POS;
4388 /* Correct for the sign of the result */
4389 if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4391 /* -x + -y : Negative */
4393 goto VarDecAdd_AsPositive;
4395 else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4397 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4399 /* -x + y : Negative if x > y */
4403 VarDecAdd_AsNegative:
4404 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4405 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4406 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4410 VarDecAdd_AsInvertedNegative:
4411 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecRight), DEC_LO32(pDecLeft), &overflow);
4412 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4413 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecRight), DEC_HI32(pDecLeft), &overflow);
4416 else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4418 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4420 /* x + -y : Negative if x <= y */
4424 goto VarDecAdd_AsInvertedNegative;
4426 goto VarDecAdd_AsNegative;
4430 /* x + y : Positive */
4431 VarDecAdd_AsPositive:
4432 DEC_LO32(pDecOut) = VARIANT_Add(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4433 DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4434 DEC_HI32(pDecOut) = VARIANT_Add(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4438 return DISP_E_OVERFLOW; /* overflowed */
4440 DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4441 DEC_SIGN(pDecOut) = sign;
4446 /************************************************************************
4447 * VarDecDiv (OLEAUT32.178)
4449 * Divide one DECIMAL by another.
4452 * pDecLeft [I] Source
4453 * pDecRight [I] Value to divide by
4454 * pDecOut [O] Destination
4458 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4460 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4462 FIXME("(%p,%p,%p)-stub!\n",pDecLeft,pDecRight,pDecOut);
4463 return DISP_E_OVERFLOW;
4466 /************************************************************************
4467 * VarDecMul (OLEAUT32.179)
4469 * Multiply one DECIMAL by another.
4472 * pDecLeft [I] Source
4473 * pDecRight [I] Value to multiply by
4474 * pDecOut [O] Destination
4478 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4480 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4482 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4484 if (!DEC_SCALE(pDecLeft) || !DEC_SCALE(pDecRight))
4486 /* At least one term is an integer */
4487 const DECIMAL* pDecInteger = DEC_SCALE(pDecLeft) ? pDecRight : pDecLeft;
4488 const DECIMAL* pDecOperand = DEC_SCALE(pDecLeft) ? pDecLeft : pDecRight;
4489 HRESULT hRet = S_OK;
4490 unsigned int multiplier = DEC_LO32(pDecInteger);
4493 if (DEC_HI32(pDecInteger) || DEC_MID32(pDecInteger))
4495 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4496 return DISP_E_OVERFLOW;
4499 DEC_LO32(pDecOut) = VARIANT_Mul(DEC_LO32(pDecOperand), multiplier, &overflow);
4500 DEC_MID32(pDecOut) = VARIANT_Mul(DEC_MID32(pDecOperand), multiplier, &overflow);
4501 DEC_HI32(pDecOut) = VARIANT_Mul(DEC_HI32(pDecOperand), multiplier, &overflow);
4504 hRet = DISP_E_OVERFLOW;
4507 BYTE sign = DECIMAL_POS;
4509 if (DEC_SIGN(pDecLeft) != DEC_SIGN(pDecRight))
4510 sign = DECIMAL_NEG; /* pos * neg => negative */
4511 DEC_SIGN(pDecOut) = sign;
4512 DEC_SCALE(pDecOut) = DEC_SCALE(pDecOperand);
4516 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4517 return DISP_E_OVERFLOW;
4520 /************************************************************************
4521 * VarDecSub (OLEAUT32.181)
4523 * Subtract one DECIMAL from another.
4526 * pDecLeft [I] Source
4527 * pDecRight [I] DECIMAL to subtract from pDecLeft
4528 * pDecOut [O] Destination
4531 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4533 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4537 /* Implement as addition of the negative */
4538 VarDecNeg(pDecRight, &decRight);
4539 return VarDecAdd(pDecLeft, &decRight, pDecOut);
4542 /************************************************************************
4543 * VarDecAbs (OLEAUT32.182)
4545 * Convert a DECIMAL into its absolute value.
4549 * pDecOut [O] Destination
4552 * S_OK. This function does not fail.
4554 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4557 DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
4561 /************************************************************************
4562 * VarDecFix (OLEAUT32.187)
4564 * Return the integer portion of a DECIMAL.
4568 * pDecOut [O] Destination
4572 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4575 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4576 * negative numbers away from 0, while this function rounds them towards zero.
4578 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4580 if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
4581 return E_INVALIDARG;
4583 if (!DEC_SCALE(pDecIn))
4585 *pDecOut = *pDecIn; /* Already an integer */
4589 FIXME("semi-stub!\n");
4590 return DISP_E_OVERFLOW;
4593 /************************************************************************
4594 * VarDecInt (OLEAUT32.188)
4596 * Return the integer portion of a DECIMAL.
4600 * pDecOut [O] Destination
4604 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4607 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4608 * negative numbers towards 0, while this function rounds them away from zero.
4610 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4612 if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
4613 return E_INVALIDARG;
4615 if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
4616 return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
4618 FIXME("semi-stub!\n");
4619 return DISP_E_OVERFLOW;
4622 /************************************************************************
4623 * VarDecNeg (OLEAUT32.189)
4625 * Change the sign of a DECIMAL.
4629 * pDecOut [O] Destination
4632 * S_OK. This function does not fail.
4634 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4637 DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
4641 /************************************************************************
4642 * VarDecRound (OLEAUT32.203)
4644 * Change the precision of a DECIMAL.
4648 * cDecimals [I] New number of decimals to keep
4649 * pDecOut [O] Destination
4652 * Success: S_OK. pDecOut contains the rounded value.
4653 * Failure: E_INVALIDARG if any argument is invalid.
4655 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
4657 if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
4658 return E_INVALIDARG;
4660 if (cDecimals >= DEC_SCALE(pDecIn))
4662 *pDecOut = *pDecIn; /* More precision than we have */
4666 FIXME("semi-stub!\n");
4668 return DISP_E_OVERFLOW;
4671 /************************************************************************
4672 * VarDecCmp (OLEAUT32.204)
4674 * Compare two DECIMAL values.
4677 * pDecLeft [I] Source
4678 * pDecRight [I] Value to compare
4681 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4682 * is less than, equal to or greater than pDecRight respectively.
4683 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4685 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
4690 /* Subtract right from left, and compare the result to 0 */
4691 hRet = VarDecSub(pDecLeft, pDecRight, &result);
4693 if (SUCCEEDED(hRet))
4695 int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
4697 if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
4698 hRet = (HRESULT)VARCMP_LT;
4700 hRet = (HRESULT)VARCMP_GT;
4702 hRet = (HRESULT)VARCMP_EQ;
4707 /************************************************************************
4708 * VarDecCmpR8 (OLEAUT32.298)
4710 * Compare a DECIMAL to a double
4713 * pDecLeft [I] DECIMAL Source
4714 * dblRight [I] double to compare to pDecLeft
4717 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4718 * is less than, equal to or greater than pDecLeft respectively.
4719 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4721 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
4726 hRet = VarDecFromR8(dblRight, &decRight);
4728 if (SUCCEEDED(hRet))
4729 hRet = VarDecCmp(pDecLeft, &decRight);
4737 /************************************************************************
4738 * VarBoolFromUI1 (OLEAUT32.118)
4740 * Convert a VT_UI1 to a VT_BOOL.
4744 * pBoolOut [O] Destination
4749 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
4751 return _VarBoolFromUI1(bIn, pBoolOut);
4754 /************************************************************************
4755 * VarBoolFromI2 (OLEAUT32.119)
4757 * Convert a VT_I2 to a VT_BOOL.
4761 * pBoolOut [O] Destination
4766 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
4768 return _VarBoolFromI2(sIn, pBoolOut);
4771 /************************************************************************
4772 * VarBoolFromI4 (OLEAUT32.120)
4774 * Convert a VT_I4 to a VT_BOOL.
4778 * pBoolOut [O] Destination
4783 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
4785 return _VarBoolFromI4(lIn, pBoolOut);
4788 /************************************************************************
4789 * VarBoolFromR4 (OLEAUT32.121)
4791 * Convert a VT_R4 to a VT_BOOL.
4795 * pBoolOut [O] Destination
4800 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
4802 return _VarBoolFromR4(fltIn, pBoolOut);
4805 /************************************************************************
4806 * VarBoolFromR8 (OLEAUT32.122)
4808 * Convert a VT_R8 to a VT_BOOL.
4812 * pBoolOut [O] Destination
4817 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
4819 return _VarBoolFromR8(dblIn, pBoolOut);
4822 /************************************************************************
4823 * VarBoolFromDate (OLEAUT32.123)
4825 * Convert a VT_DATE to a VT_BOOL.
4829 * pBoolOut [O] Destination
4834 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
4836 return _VarBoolFromDate(dateIn, pBoolOut);
4839 /************************************************************************
4840 * VarBoolFromCy (OLEAUT32.124)
4842 * Convert a VT_CY to a VT_BOOL.
4846 * pBoolOut [O] Destination
4851 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
4853 return _VarBoolFromCy(cyIn, pBoolOut);
4856 static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
4860 hrsrc = FindResourceExW( OLEAUT32_hModule, (LPWSTR)RT_STRING,
4861 (LPCWSTR)((dwId >> 4) + 1), langId );
4864 HGLOBAL hmem = LoadResource( OLEAUT32_hModule, hrsrc );
4871 p = LockResource( hmem );
4872 for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
4874 memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
4875 lpszDest[*p] = '\0';
4876 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
4883 /************************************************************************
4884 * VarBoolFromStr (OLEAUT32.125)
4886 * Convert a VT_BSTR to a VT_BOOL.
4890 * lcid [I] LCID for the conversion
4891 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4892 * pBoolOut [O] Destination
4896 * Failure: E_INVALIDARG, if pBoolOut is invalid.
4897 * DISP_E_TYPEMISMATCH, if the type cannot be converted
4900 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
4901 * it may contain (in any case mapping) the text "true" or "false".
4902 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
4903 * localised text of "True" or "False" in the language specified by lcid.
4904 * - If none of these matches occur, the string is treated as a numeric string
4905 * and the boolean pBoolOut will be set according to whether the number is zero
4906 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
4907 * - If the text is not numeric and does not match any of the above, then
4908 * DISP_E_TYPEMISMATCH is returned.
4910 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
4912 /* Any VB/VBA programmers out there should recognise these strings... */
4913 static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
4914 static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
4916 LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4917 HRESULT hRes = S_OK;
4919 if (!strIn || !pBoolOut)
4920 return DISP_E_TYPEMISMATCH;
4922 /* Check if we should be comparing against localised text */
4923 if (dwFlags & VAR_LOCALBOOL)
4925 /* Convert our LCID into a usable value */
4926 lcid = ConvertDefaultLocale(lcid);
4928 langId = LANGIDFROMLCID(lcid);
4930 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
4931 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4933 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
4934 * I don't think this is needed unless any of the localised text strings
4935 * contain characters that can be so mapped. In the event that this is
4936 * true for a given language (possibly some Asian languages), then strIn
4937 * should be mapped here _only_ if langId is an Id for which this can occur.
4941 /* Note that if we are not comparing against localised strings, langId
4942 * will have its default value of LANG_ENGLISH. This allows us to mimic
4943 * the native behaviour of always checking against English strings even
4944 * after we've checked for localised ones.
4946 VarBoolFromStr_CheckLocalised:
4947 if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
4949 /* Compare against localised strings, ignoring case */
4950 if (!strcmpiW(strIn, szBuff))
4952 *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
4955 VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
4956 if (!strcmpiW(strIn, szBuff))
4958 *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
4963 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
4965 /* We have checked the localised text, now check English */
4966 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4967 goto VarBoolFromStr_CheckLocalised;
4970 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
4971 if (!strcmpW(strIn, szFalse))
4972 *pBoolOut = VARIANT_FALSE;
4973 else if (!strcmpW(strIn, szTrue))
4974 *pBoolOut = VARIANT_TRUE;
4979 /* If this string is a number, convert it as one */
4980 hRes = _VarR8FromStr(strIn, lcid, dwFlags, &d);
4981 if (SUCCEEDED(hRes))
4982 hRes = _VarBoolFromR8(d, pBoolOut);
4987 /************************************************************************
4988 * VarBoolFromDisp (OLEAUT32.126)
4990 * Convert a VT_DISPATCH to a VT_BOOL.
4993 * pdispIn [I] Source
4994 * lcid [I] LCID for conversion
4995 * pBoolOut [O] Destination
4999 * Failure: E_INVALIDARG, if the source value is invalid
5000 * DISP_E_OVERFLOW, if the value will not fit in the destination
5001 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5003 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
5005 return _VarBoolFromDisp(pdispIn, lcid, pBoolOut);
5008 /************************************************************************
5009 * VarBoolFromI1 (OLEAUT32.233)
5011 * Convert a VT_I1 to a VT_BOOL.
5015 * pBoolOut [O] Destination
5020 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
5022 return _VarBoolFromI1(cIn, pBoolOut);
5025 /************************************************************************
5026 * VarBoolFromUI2 (OLEAUT32.234)
5028 * Convert a VT_UI2 to a VT_BOOL.
5032 * pBoolOut [O] Destination
5037 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
5039 return _VarBoolFromUI2(usIn, pBoolOut);
5042 /************************************************************************
5043 * VarBoolFromUI4 (OLEAUT32.235)
5045 * Convert a VT_UI4 to a VT_BOOL.
5049 * pBoolOut [O] Destination
5054 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
5056 return _VarBoolFromUI4(ulIn, pBoolOut);
5059 /************************************************************************
5060 * VarBoolFromDec (OLEAUT32.236)
5062 * Convert a VT_DECIMAL to a VT_BOOL.
5066 * pBoolOut [O] Destination
5070 * Failure: E_INVALIDARG, if pDecIn is invalid.
5072 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
5074 if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
5075 return E_INVALIDARG;
5077 if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
5078 *pBoolOut = VARIANT_TRUE;
5080 *pBoolOut = VARIANT_FALSE;
5084 /************************************************************************
5085 * VarBoolFromI8 (OLEAUT32.370)
5087 * Convert a VT_I8 to a VT_BOOL.
5091 * pBoolOut [O] Destination
5096 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
5098 return _VarBoolFromI8(llIn, pBoolOut);
5101 /************************************************************************
5102 * VarBoolFromUI8 (OLEAUT32.371)
5104 * Convert a VT_UI8 to a VT_BOOL.
5108 * pBoolOut [O] Destination
5113 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
5115 return _VarBoolFromUI8(ullIn, pBoolOut);
5121 /* Write a number from a UI8 and sign */
5122 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
5126 WCHAR ulNextDigit = ulVal % 10;
5128 *szOut-- = '0' + ulNextDigit;
5129 ulVal = (ulVal - ulNextDigit) / 10;
5136 /* Create a (possibly localised) BSTR from a UI8 and sign */
5137 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
5139 WCHAR szConverted[256];
5141 if (dwFlags & VAR_NEGATIVE)
5144 if (dwFlags & LOCALE_USE_NLS)
5146 /* Format the number for the locale */
5147 szConverted[0] = '\0';
5148 GetNumberFormatW(lcid,
5149 dwFlags & LOCALE_NOUSEROVERRIDE,
5150 szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
5151 szOut = szConverted;
5153 return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
5156 /* Create a (possibly localised) BSTR from a UI8 and sign */
5157 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
5159 WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5162 return E_INVALIDARG;
5164 /* Create the basic number string */
5166 szOut = VARIANT_WriteNumber(ulVal, szOut);
5168 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5169 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5170 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5173 /******************************************************************************
5174 * VarBstrFromUI1 (OLEAUT32.108)
5176 * Convert a VT_UI1 to a VT_BSTR.
5180 * lcid [I] LCID for the conversion
5181 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5182 * pbstrOut [O] Destination
5186 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5187 * E_OUTOFMEMORY, if memory allocation fails.
5189 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5191 return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
5194 /******************************************************************************
5195 * VarBstrFromI2 (OLEAUT32.109)
5197 * Convert a VT_I2 to a VT_BSTR.
5201 * lcid [I] LCID for the conversion
5202 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5203 * pbstrOut [O] Destination
5207 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5208 * E_OUTOFMEMORY, if memory allocation fails.
5210 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5217 dwFlags |= VAR_NEGATIVE;
5219 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5222 /******************************************************************************
5223 * VarBstrFromI4 (OLEAUT32.110)
5225 * Convert a VT_I4 to a VT_BSTR.
5229 * lcid [I] LCID for the conversion
5230 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5231 * pbstrOut [O] Destination
5235 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5236 * E_OUTOFMEMORY, if memory allocation fails.
5238 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5245 dwFlags |= VAR_NEGATIVE;
5247 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5250 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
5251 BSTR* pbstrOut, LPCWSTR lpszFormat)
5256 return E_INVALIDARG;
5258 sprintfW( buff, lpszFormat, dblIn );
5259 TRACE("created string %s\n", debugstr_w(buff));
5260 if (dwFlags & LOCALE_USE_NLS)
5264 /* Format the number for the locale */
5266 GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5267 buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
5268 TRACE("created NLS string %s\n", debugstr_w(numbuff));
5269 *pbstrOut = SysAllocString(numbuff);
5272 *pbstrOut = SysAllocString(buff);
5273 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5276 /******************************************************************************
5277 * VarBstrFromR4 (OLEAUT32.111)
5279 * Convert a VT_R4 to a VT_BSTR.
5283 * lcid [I] LCID for the conversion
5284 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5285 * pbstrOut [O] Destination
5289 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5290 * E_OUTOFMEMORY, if memory allocation fails.
5292 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5294 return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
5297 /******************************************************************************
5298 * VarBstrFromR8 (OLEAUT32.112)
5300 * Convert a VT_R8 to a VT_BSTR.
5304 * lcid [I] LCID for the conversion
5305 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5306 * pbstrOut [O] Destination
5310 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5311 * E_OUTOFMEMORY, if memory allocation fails.
5313 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5315 return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
5318 /******************************************************************************
5319 * VarBstrFromCy [OLEAUT32.113]
5321 * Convert a VT_CY to a VT_BSTR.
5325 * lcid [I] LCID for the conversion
5326 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5327 * pbstrOut [O] Destination
5331 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5332 * E_OUTOFMEMORY, if memory allocation fails.
5334 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
5340 return E_INVALIDARG;
5342 VarR8FromCy(cyIn, &dblVal);
5343 sprintfW(buff, szDoubleFormatW, dblVal);
5345 if (dwFlags & LOCALE_USE_NLS)
5349 /* Format the currency for the locale */
5351 GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5352 buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
5353 *pbstrOut = SysAllocString(cybuff);
5356 *pbstrOut = SysAllocString(buff);
5358 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5361 /******************************************************************************
5362 * VarBstrFromDate [OLEAUT32.114]
5364 * Convert a VT_DATE to a VT_BSTR.
5368 * lcid [I] LCID for the conversion
5369 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5370 * pbstrOut [O] Destination
5374 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5375 * E_OUTOFMEMORY, if memory allocation fails.
5377 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5380 DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
5381 WCHAR date[128], *time;
5383 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
5385 if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
5386 return E_INVALIDARG;
5390 if (dwFlags & VAR_CALENDAR_THAI)
5391 st.wYear += 553; /* Use the Thai buddhist calendar year */
5392 else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
5393 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5395 if (dwFlags & LOCALE_USE_NLS)
5396 dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
5399 double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
5400 double partial = dateIn - whole;
5403 dwFlags |= VAR_TIMEVALUEONLY;
5404 else if (partial < 1e-12)
5405 dwFlags |= VAR_DATEVALUEONLY;
5408 if (dwFlags & VAR_TIMEVALUEONLY)
5411 if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
5412 sizeof(date)/sizeof(WCHAR)))
5413 return E_INVALIDARG;
5415 if (!(dwFlags & VAR_DATEVALUEONLY))
5417 time = date + strlenW(date);
5420 if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
5421 sizeof(date)/sizeof(WCHAR)-(time-date)))
5422 return E_INVALIDARG;
5425 *pbstrOut = SysAllocString(date);
5427 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5428 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5431 /******************************************************************************
5432 * VarBstrFromBool (OLEAUT32.116)
5434 * Convert a VT_BOOL to a VT_BSTR.
5438 * lcid [I] LCID for the conversion
5439 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5440 * pbstrOut [O] Destination
5444 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5445 * E_OUTOFMEMORY, if memory allocation fails.
5448 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5449 * localised text of "True" or "False". To convert a bool into a
5450 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5452 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5455 DWORD dwResId = IDS_TRUE;
5458 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn, lcid, dwFlags, pbstrOut);
5461 return E_INVALIDARG;
5463 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5464 * for variant formatting */
5465 switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
5476 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
5479 lcid = ConvertDefaultLocale(lcid);
5480 langId = LANGIDFROMLCID(lcid);
5481 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
5482 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5484 if (boolIn == VARIANT_FALSE)
5485 dwResId++; /* Use negative form */
5487 VarBstrFromBool_GetLocalised:
5488 if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
5490 *pbstrOut = SysAllocString(szBuff);
5491 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5494 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5496 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5497 goto VarBstrFromBool_GetLocalised;
5500 /* Should never get here */
5501 WARN("Failed to load bool text!\n");
5502 return E_OUTOFMEMORY;
5505 /******************************************************************************
5506 * VarBstrFromI1 (OLEAUT32.229)
5508 * Convert a VT_I1 to a VT_BSTR.
5512 * lcid [I] LCID for the conversion
5513 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5514 * pbstrOut [O] Destination
5518 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5519 * E_OUTOFMEMORY, if memory allocation fails.
5521 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5528 dwFlags |= VAR_NEGATIVE;
5530 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5533 /******************************************************************************
5534 * VarBstrFromUI2 (OLEAUT32.230)
5536 * Convert a VT_UI2 to a VT_BSTR.
5540 * lcid [I] LCID for the conversion
5541 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5542 * pbstrOut [O] Destination
5546 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5547 * E_OUTOFMEMORY, if memory allocation fails.
5549 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5551 return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
5554 /******************************************************************************
5555 * VarBstrFromUI4 (OLEAUT32.231)
5557 * Convert a VT_UI4 to a VT_BSTR.
5561 * lcid [I] LCID for the conversion
5562 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5563 * pbstrOut [O] Destination
5567 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5568 * E_OUTOFMEMORY, if memory allocation fails.
5570 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5572 return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
5575 /******************************************************************************
5576 * VarBstrFromDec (OLEAUT32.232)
5578 * Convert a VT_DECIMAL to a VT_BSTR.
5582 * lcid [I] LCID for the conversion
5583 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5584 * pbstrOut [O] Destination
5588 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5589 * E_OUTOFMEMORY, if memory allocation fails.
5591 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5594 return E_INVALIDARG;
5596 if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
5598 WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5600 /* Create the basic number string */
5602 szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
5603 if (DEC_SIGN(pDecIn))
5604 dwFlags |= VAR_NEGATIVE;
5606 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5607 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5608 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5610 FIXME("semi-stub\n");
5611 return E_INVALIDARG;
5614 /************************************************************************
5615 * VarBstrFromI8 (OLEAUT32.370)
5617 * Convert a VT_I8 to a VT_BSTR.
5621 * lcid [I] LCID for the conversion
5622 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5623 * pbstrOut [O] Destination
5627 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5628 * E_OUTOFMEMORY, if memory allocation fails.
5630 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5632 ULONG64 ul64 = llIn;
5637 dwFlags |= VAR_NEGATIVE;
5639 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5642 /************************************************************************
5643 * VarBstrFromUI8 (OLEAUT32.371)
5645 * Convert a VT_UI8 to a VT_BSTR.
5649 * lcid [I] LCID for the conversion
5650 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5651 * pbstrOut [O] Destination
5655 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5656 * E_OUTOFMEMORY, if memory allocation fails.
5658 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5660 return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
5663 /**********************************************************************
5664 * VarBstrCat (OLEAUT32.313)
5666 * Concatenate two BSTR values.
5669 * pbstrLeft [I] Source
5670 * pbstrRight [I] Value to concatenate
5671 * pbstrOut [O] Destination
5675 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5676 * E_OUTOFMEMORY, if memory allocation fails.
5678 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
5683 return E_INVALIDARG;
5685 len = pbstrLeft ? strlenW(pbstrLeft) : 0;
5687 len += strlenW(pbstrRight);
5689 *pbstrOut = SysAllocStringLen(NULL, len);
5691 return E_OUTOFMEMORY;
5693 (*pbstrOut)[0] = '\0';
5696 strcpyW(*pbstrOut, pbstrLeft);
5699 strcatW(*pbstrOut, pbstrRight);
5704 /**********************************************************************
5705 * VarBstrCmp (OLEAUT32.314)
5707 * Compare two BSTR values.
5710 * pbstrLeft [I] Source
5711 * pbstrRight [I] Value to compare
5712 * lcid [I] LCID for the comparison
5713 * dwFlags [I] Flags to pass directly to CompareStringW().
5716 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5717 * than, equal to or greater than pbstrRight respectively.
5718 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5719 * in which case VARCMP_EQ is returned.
5721 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
5725 if (!pbstrRight || !*pbstrRight)
5729 else if (!pbstrRight)
5736 return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
5743 /******************************************************************************
5744 * VarDateFromUI1 (OLEAUT32.88)
5746 * Convert a VT_UI1 to a VT_DATE.
5750 * pdateOut [O] Destination
5755 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
5757 return _VarDateFromUI1(bIn, pdateOut);
5760 /******************************************************************************
5761 * VarDateFromI2 (OLEAUT32.89)
5763 * Convert a VT_I2 to a VT_DATE.
5767 * pdateOut [O] Destination
5772 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
5774 return _VarDateFromI2(sIn, pdateOut);
5777 /******************************************************************************
5778 * VarDateFromI4 (OLEAUT32.90)
5780 * Convert a VT_I4 to a VT_DATE.
5784 * pdateOut [O] Destination
5789 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
5791 return _VarDateFromI4(lIn, pdateOut);
5794 /******************************************************************************
5795 * VarDateFromR4 (OLEAUT32.91)
5797 * Convert a VT_R4 to a VT_DATE.
5801 * pdateOut [O] Destination
5806 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
5808 return _VarDateFromR4(fltIn, pdateOut);
5811 /******************************************************************************
5812 * VarDateFromR8 (OLEAUT32.92)
5814 * Convert a VT_R8 to a VT_DATE.
5818 * pdateOut [O] Destination
5823 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
5825 return _VarDateFromR8(dblIn, pdateOut);
5828 /**********************************************************************
5829 * VarDateFromDisp (OLEAUT32.95)
5831 * Convert a VT_DISPATCH to a VT_DATE.
5834 * pdispIn [I] Source
5835 * lcid [I] LCID for conversion
5836 * pdateOut [O] Destination
5840 * Failure: E_INVALIDARG, if the source value is invalid
5841 * DISP_E_OVERFLOW, if the value will not fit in the destination
5842 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5844 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
5846 return _VarDateFromDisp(pdispIn, lcid, pdateOut);
5849 /******************************************************************************
5850 * VarDateFromBool (OLEAUT32.96)
5852 * Convert a VT_BOOL to a VT_DATE.
5856 * pdateOut [O] Destination
5861 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
5863 return _VarDateFromBool(boolIn, pdateOut);
5866 /**********************************************************************
5867 * VarDateFromCy (OLEAUT32.93)
5869 * Convert a VT_CY to a VT_DATE.
5873 * pdateOut [O] Destination
5878 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
5880 return _VarDateFromCy(cyIn, pdateOut);
5883 /* Date string parsing */
5884 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
5885 #define DP_DATESEP 0x02 /* Date separator */
5886 #define DP_MONTH 0x04 /* Month name */
5887 #define DP_AM 0x08 /* AM */
5888 #define DP_PM 0x10 /* PM */
5890 typedef struct tagDATEPARSE
5892 DWORD dwCount; /* Number of fields found so far (maximum 6) */
5893 DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
5894 DWORD dwFlags[6]; /* Flags for each field */
5895 DWORD dwValues[6]; /* Value of each field */
5898 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
5900 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5902 /* Determine if a day is valid in a given month of a given year */
5903 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
5905 static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
5907 if (day && month && month < 13)
5909 if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
5915 /* Possible orders for 3 numbers making up a date */
5916 #define ORDER_MDY 0x01
5917 #define ORDER_YMD 0x02
5918 #define ORDER_YDM 0x04
5919 #define ORDER_DMY 0x08
5920 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
5922 /* Determine a date for a particular locale, from 3 numbers */
5923 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
5924 DWORD offset, SYSTEMTIME *st)
5926 DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
5930 v1 = 30; /* Default to (Variant) 0 date part */
5933 goto VARIANT_MakeDate_OK;
5936 v1 = dp->dwValues[offset + 0];
5937 v2 = dp->dwValues[offset + 1];
5938 if (dp->dwCount == 2)
5941 GetSystemTime(¤t);
5945 v3 = dp->dwValues[offset + 2];
5947 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
5949 /* If one number must be a month (Because a month name was given), then only
5950 * consider orders with the month in that position.
5951 * If we took the current year as 'v3', then only allow a year in that position.
5953 if (dp->dwFlags[offset + 0] & DP_MONTH)
5955 dwAllOrders = ORDER_MDY;
5957 else if (dp->dwFlags[offset + 1] & DP_MONTH)
5959 dwAllOrders = ORDER_DMY;
5960 if (dp->dwCount > 2)
5961 dwAllOrders |= ORDER_YMD;
5963 else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
5965 dwAllOrders = ORDER_YDM;
5969 dwAllOrders = ORDER_MDY|ORDER_DMY;
5970 if (dp->dwCount > 2)
5971 dwAllOrders |= (ORDER_YMD|ORDER_YDM);
5974 VARIANT_MakeDate_Start:
5975 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
5983 /* First: Try the order given by iDate */
5986 case 0: dwTry = dwAllOrders & ORDER_MDY; break;
5987 case 1: dwTry = dwAllOrders & ORDER_DMY; break;
5988 default: dwTry = dwAllOrders & ORDER_YMD; break;
5991 else if (dwCount == 1)
5993 /* Second: Try all the orders compatible with iDate */
5996 case 0: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
5997 case 1: dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
5998 default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
6003 /* Finally: Try any remaining orders */
6004 dwTry = dwAllOrders;
6007 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
6013 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6015 if (dwTry & ORDER_MDY)
6017 if (VARIANT_IsValidMonthDay(v2,v1,v3))
6020 goto VARIANT_MakeDate_OK;
6022 dwAllOrders &= ~ORDER_MDY;
6024 if (dwTry & ORDER_YMD)
6026 if (VARIANT_IsValidMonthDay(v3,v2,v1))
6029 goto VARIANT_MakeDate_OK;
6031 dwAllOrders &= ~ORDER_YMD;
6033 if (dwTry & ORDER_YDM)
6035 if (VARIANT_IsValidMonthDay(v2,v3,v1))
6039 goto VARIANT_MakeDate_OK;
6041 dwAllOrders &= ~ORDER_YDM;
6043 if (dwTry & ORDER_DMY)
6045 if (VARIANT_IsValidMonthDay(v1,v2,v3))
6046 goto VARIANT_MakeDate_OK;
6047 dwAllOrders &= ~ORDER_DMY;
6049 if (dwTry & ORDER_MYD)
6051 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6052 if (VARIANT_IsValidMonthDay(v3,v1,v2))
6056 goto VARIANT_MakeDate_OK;
6058 dwAllOrders &= ~ORDER_MYD;
6062 if (dp->dwCount == 2)
6064 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6065 v3 = 1; /* 1st of the month */
6066 dwAllOrders = ORDER_YMD|ORDER_MYD;
6067 dp->dwCount = 0; /* Don't return to this code path again */
6069 goto VARIANT_MakeDate_Start;
6072 /* No valid dates were able to be constructed */
6073 return DISP_E_TYPEMISMATCH;
6075 VARIANT_MakeDate_OK:
6077 /* Check that the time part is ok */
6078 if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
6079 return DISP_E_TYPEMISMATCH;
6081 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6082 if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
6084 else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
6086 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6090 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6091 * be retrieved from:
6092 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6093 * But Wine doesn't have/use that key as at the time of writing.
6095 st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
6096 TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
6100 /******************************************************************************
6101 * VarDateFromStr [OLEAUT32.94]
6103 * Convert a VT_BSTR to at VT_DATE.
6106 * strIn [I] String to convert
6107 * lcid [I] Locale identifier for the conversion
6108 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6109 * pdateOut [O] Destination for the converted value
6112 * Success: S_OK. pdateOut contains the converted value.
6113 * FAILURE: An HRESULT error code indicating the prolem.
6116 * Any date format that can be created using the date formats from lcid
6117 * (Either from kernel Nls functions, variant conversion or formatting) is a
6118 * valid input to this function. In addition, a few more esoteric formats are
6119 * also supported for compatibility with the native version. The date is
6120 * interpreted according to the date settings in the control panel, unless
6121 * the date is invalid in that format, in which the most compatible format
6122 * that produces a valid date will be used.
6124 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
6126 static const USHORT ParseDateTokens[] =
6128 LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
6129 LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
6130 LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
6131 LOCALE_SMONTHNAME13,
6132 LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
6133 LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
6134 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
6135 LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
6136 LOCALE_SABBREVMONTHNAME13,
6137 LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
6138 LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
6139 LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
6140 LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
6141 LOCALE_SABBREVDAYNAME7,
6142 LOCALE_S1159, LOCALE_S2359
6144 static const BYTE ParseDateMonths[] =
6146 1,2,3,4,5,6,7,8,9,10,11,12,13,
6147 1,2,3,4,5,6,7,8,9,10,11,12,13
6150 BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
6152 DWORD dwDateSeps = 0, iDate = 0;
6153 HRESULT hRet = S_OK;
6155 if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
6156 (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
6157 return E_INVALIDARG;
6160 return DISP_E_TYPEMISMATCH;
6164 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
6166 memset(&dp, 0, sizeof(dp));
6168 GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
6169 (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
6170 TRACE("iDate is %ld\n", iDate);
6172 /* Get the month/day/am/pm tokens for this locale */
6173 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6176 LCTYPE lctype = ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
6178 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6179 * GetAltMonthNames(). We should really cache these strings too.
6182 GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
6183 tokens[i] = SysAllocString(buff);
6184 TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
6187 /* Parse the string into our structure */
6193 if (isdigitW(*strIn))
6195 dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
6199 else if (isalpha(*strIn))
6201 BOOL bFound = FALSE;
6203 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6205 DWORD dwLen = strlenW(tokens[i]);
6206 if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
6210 dp.dwValues[dp.dwCount] = ParseDateMonths[i];
6211 dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
6216 if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
6217 hRet = DISP_E_TYPEMISMATCH;
6220 dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
6221 dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
6224 strIn += (dwLen - 1);
6232 if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
6233 (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6235 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6236 if (*strIn == 'a' || *strIn == 'A')
6238 dp.dwFlags[dp.dwCount - 1] |= DP_AM;
6239 dp.dwParseFlags |= DP_AM;
6243 dp.dwFlags[dp.dwCount - 1] |= DP_PM;
6244 dp.dwParseFlags |= DP_PM;
6250 TRACE("No matching token for %s\n", debugstr_w(strIn));
6251 hRet = DISP_E_TYPEMISMATCH;
6256 else if (*strIn == ':' || *strIn == '.')
6258 if (!dp.dwCount || !strIn[1])
6259 hRet = DISP_E_TYPEMISMATCH;
6261 dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
6263 else if (*strIn == '-' || *strIn == '/')
6266 if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
6267 hRet = DISP_E_TYPEMISMATCH;
6269 dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
6271 else if (*strIn == ',' || isspaceW(*strIn))
6273 if (*strIn == ',' && !strIn[1])
6274 hRet = DISP_E_TYPEMISMATCH;
6278 hRet = DISP_E_TYPEMISMATCH;
6283 if (!dp.dwCount || dp.dwCount > 6 ||
6284 (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6285 hRet = DISP_E_TYPEMISMATCH;
6287 if (SUCCEEDED(hRet))
6290 DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
6292 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
6294 /* Figure out which numbers correspond to which fields.
6296 * This switch statement works based on the fact that native interprets any
6297 * fields that are not joined with a time separator ('.' or ':') as date
6298 * fields. Thus we construct a value from 0-32 where each set bit indicates
6299 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6300 * For valid permutations, we set dwOffset to point to the first date field
6301 * and shorten dp.dwCount by the number of time fields found. The real
6302 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6303 * each date number must represent in the context of iDate.
6305 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6307 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6309 case 0x1: /* TT TTDD TTDDD */
6310 if (dp.dwCount > 3 &&
6311 ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
6312 (dp.dwFlags[4] & (DP_AM|DP_PM))))
6313 hRet = DISP_E_TYPEMISMATCH;
6314 else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
6315 hRet = DISP_E_TYPEMISMATCH;
6316 st.wHour = dp.dwValues[0];
6317 st.wMinute = dp.dwValues[1];
6322 case 0x3: /* TTT TTTDD TTTDDD */
6323 if (dp.dwCount > 4 &&
6324 ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
6325 (dp.dwFlags[5] & (DP_AM|DP_PM))))
6326 hRet = DISP_E_TYPEMISMATCH;
6327 else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
6328 hRet = DISP_E_TYPEMISMATCH;
6329 st.wHour = dp.dwValues[0];
6330 st.wMinute = dp.dwValues[1];
6331 st.wSecond = dp.dwValues[2];
6336 case 0x4: /* DDTT */
6337 if (dp.dwCount != 4 ||
6338 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6339 hRet = DISP_E_TYPEMISMATCH;
6341 st.wHour = dp.dwValues[2];
6342 st.wMinute = dp.dwValues[3];
6346 case 0x0: /* T DD DDD TDDD TDDD */
6347 if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
6349 st.wHour = dp.dwValues[0]; /* T */
6353 else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
6355 hRet = DISP_E_TYPEMISMATCH;
6357 else if (dp.dwCount == 3)
6359 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
6362 st.wHour = dp.dwValues[0];
6366 if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
6369 st.wHour = dp.dwValues[2];
6372 else if (dp.dwParseFlags & (DP_AM|DP_PM))
6373 hRet = DISP_E_TYPEMISMATCH;
6375 else if (dp.dwCount == 4)
6378 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
6380 st.wHour = dp.dwValues[0];
6383 else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
6385 st.wHour = dp.dwValues[3];
6388 hRet = DISP_E_TYPEMISMATCH;
6391 /* .. fall through .. */
6393 case 0x8: /* DDDTT */
6394 if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
6395 (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
6396 (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
6397 dp.dwCount == 4 || dp.dwCount == 6)
6398 hRet = DISP_E_TYPEMISMATCH;
6399 st.wHour = dp.dwValues[3];
6400 st.wMinute = dp.dwValues[4];
6401 if (dp.dwCount == 5)
6405 case 0xC: /* DDTTT */
6406 if (dp.dwCount != 5 ||
6407 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6408 hRet = DISP_E_TYPEMISMATCH;
6409 st.wHour = dp.dwValues[2];
6410 st.wMinute = dp.dwValues[3];
6411 st.wSecond = dp.dwValues[4];
6415 case 0x18: /* DDDTTT */
6416 if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
6417 (dp.dwFlags[2] & (DP_AM|DP_PM)))
6418 hRet = DISP_E_TYPEMISMATCH;
6419 st.wHour = dp.dwValues[3];
6420 st.wMinute = dp.dwValues[4];
6421 st.wSecond = dp.dwValues[5];
6426 hRet = DISP_E_TYPEMISMATCH;
6430 if (SUCCEEDED(hRet))
6432 hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
6434 if (dwFlags & VAR_TIMEVALUEONLY)
6440 else if (dwFlags & VAR_DATEVALUEONLY)
6441 st.wHour = st.wMinute = st.wSecond = 0;
6443 /* Finally, convert the value to a VT_DATE */
6444 if (SUCCEEDED(hRet))
6445 hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
6449 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6450 SysFreeString(tokens[i]);
6454 /******************************************************************************
6455 * VarDateFromI1 (OLEAUT32.221)
6457 * Convert a VT_I1 to a VT_DATE.
6461 * pdateOut [O] Destination
6466 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
6468 return _VarDateFromI1(cIn, pdateOut);
6471 /******************************************************************************
6472 * VarDateFromUI2 (OLEAUT32.222)
6474 * Convert a VT_UI2 to a VT_DATE.
6478 * pdateOut [O] Destination
6483 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
6485 return _VarDateFromUI2(uiIn, pdateOut);
6488 /******************************************************************************
6489 * VarDateFromUI4 (OLEAUT32.223)
6491 * Convert a VT_UI4 to a VT_DATE.
6495 * pdateOut [O] Destination
6500 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
6502 return _VarDateFromUI4(ulIn, pdateOut);
6505 /**********************************************************************
6506 * VarDateFromDec (OLEAUT32.224)
6508 * Convert a VT_DECIMAL to a VT_DATE.
6512 * pdateOut [O] Destination
6517 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
6519 return _VarDateFromDec(pdecIn, pdateOut);
6522 /******************************************************************************
6523 * VarDateFromI8 (OLEAUT32.364)
6525 * Convert a VT_I8 to a VT_DATE.
6529 * pdateOut [O] Destination
6533 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6535 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
6537 return _VarDateFromI8(llIn, pdateOut);
6540 /******************************************************************************
6541 * VarDateFromUI8 (OLEAUT32.365)
6543 * Convert a VT_UI8 to a VT_DATE.
6547 * pdateOut [O] Destination
6551 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6553 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
6555 return _VarDateFromUI8(ullIn, pdateOut);