- more Extensions work (begin to detect ATI extensions)
[wine/wine-kai.git] / dlls / oleaut32 / vartype.c
blob8d3c4e3fca74cdc91a38df18ad969dc7180808ae
1 /*
2 * Low level variant functions
4 * Copyright 2003 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #define NONAMELESSUNION
21 #define NONAMELESSSTRUCT
22 #include "wine/debug.h"
23 #include "wine/unicode.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "winnt.h"
27 #include "variant.h"
28 #include "resource.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(ole);
32 extern HMODULE OLEAUT32_hModule;
34 static const WCHAR szFloatFormatW[] = { '%','.','7','G','\0' };
35 static const WCHAR szDoubleFormatW[] = { '%','.','1','5','G','\0' };
37 /* Copy data from one variant to another. */
38 static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
40 switch (vt)
42 case VT_I1:
43 case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
44 case VT_BOOL:
45 case VT_I2:
46 case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
47 case VT_R4:
48 case VT_INT:
49 case VT_I4:
50 case VT_UINT:
51 case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
52 case VT_R8:
53 case VT_DATE:
54 case VT_CY:
55 case VT_I8:
56 case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
57 case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
58 case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
59 default:
60 FIXME("VT_ type %d unhandled, please report!\n", vt);
65 /* Coerce VT_BSTR to a numeric type */
66 HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
67 void* pOut, VARTYPE vt)
69 VARIANTARG dstVar;
70 HRESULT hRet;
71 NUMPARSE np;
72 BYTE rgb[1024];
74 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
75 np.cDig = sizeof(rgb) / sizeof(BYTE);
76 np.dwInFlags = NUMPRS_STD;
78 hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
80 if (SUCCEEDED(hRet))
82 /* 1 << vt gives us the VTBIT constant for the destination number type */
83 hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
84 if (SUCCEEDED(hRet))
85 VARIANT_CopyData(&dstVar, vt, pOut);
87 return hRet;
90 /* Coerce VT_DISPATCH to another type */
91 HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, VARTYPE vt)
93 static const DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
94 VARIANTARG srcVar, dstVar;
95 HRESULT hRet;
97 if (!pdispIn)
98 return DISP_E_BADVARTYPE;
100 /* Get the default 'value' property from the IDispatch */
101 hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
102 (DISPPARAMS*)&emptyParams, &srcVar, NULL, NULL);
104 if (SUCCEEDED(hRet))
106 /* Convert the property to the requested type */
107 V_VT(&dstVar) = VT_EMPTY;
108 hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, 0, vt);
109 VariantClear(&srcVar);
111 if (SUCCEEDED(hRet))
113 VARIANT_CopyData(&dstVar, vt, pOut);
114 VariantClear(&srcVar);
117 else
118 hRet = DISP_E_TYPEMISMATCH;
119 return hRet;
122 /* I1
125 /************************************************************************
126 * VarI1FromUI1 (OLEAUT32.244)
128 * Convert a VT_UI1 to a VT_I1.
130 * PARAMS
131 * bIn [I] Source
132 * pcOut [O] Destination
134 * RETURNS
135 * Success: S_OK.
136 * Failure: E_INVALIDARG, if the source value is invalid
137 * DISP_E_OVERFLOW, if the value will not fit in the destination
139 HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
141 return _VarI1FromUI1(bIn, pcOut);
144 /************************************************************************
145 * VarI1FromI2 (OLEAUT32.245)
147 * Convert a VT_I2 to a VT_I1.
149 * PARAMS
150 * sIn [I] Source
151 * pcOut [O] Destination
153 * RETURNS
154 * Success: S_OK.
155 * Failure: E_INVALIDARG, if the source value is invalid
156 * DISP_E_OVERFLOW, if the value will not fit in the destination
158 HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
160 return _VarI1FromI2(sIn, pcOut);
163 /************************************************************************
164 * VarI1FromI4 (OLEAUT32.246)
166 * Convert a VT_I4 to a VT_I1.
168 * PARAMS
169 * iIn [I] Source
170 * pcOut [O] Destination
172 * RETURNS
173 * Success: S_OK.
174 * Failure: E_INVALIDARG, if the source value is invalid
175 * DISP_E_OVERFLOW, if the value will not fit in the destination
177 HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
179 return _VarI1FromI4(iIn, pcOut);
182 /************************************************************************
183 * VarI1FromR4 (OLEAUT32.247)
185 * Convert a VT_R4 to a VT_I1.
187 * PARAMS
188 * fltIn [I] Source
189 * pcOut [O] Destination
191 * RETURNS
192 * Success: S_OK.
193 * Failure: E_INVALIDARG, if the source value is invalid
194 * DISP_E_OVERFLOW, if the value will not fit in the destination
196 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
198 return _VarI1FromR4(fltIn, pcOut);
201 /************************************************************************
202 * VarI1FromR8 (OLEAUT32.248)
204 * Convert a VT_R8 to a VT_I1.
206 * PARAMS
207 * dblIn [I] Source
208 * pcOut [O] Destination
210 * RETURNS
211 * Success: S_OK.
212 * Failure: E_INVALIDARG, if the source value is invalid
213 * DISP_E_OVERFLOW, if the value will not fit in the destination
215 * NOTES
216 * See VarI8FromR8() for details concerning rounding.
218 HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
220 if (dblIn < (double)I1_MIN || dblIn > (double)I1_MAX)
221 return DISP_E_OVERFLOW;
222 OLEAUT32_DutchRound(CHAR, dblIn, *pcOut);
223 return S_OK;
226 /************************************************************************
227 * VarI1FromDate (OLEAUT32.249)
229 * Convert a VT_DATE to a VT_I1.
231 * PARAMS
232 * dateIn [I] Source
233 * pcOut [O] Destination
235 * RETURNS
236 * Success: S_OK.
237 * Failure: E_INVALIDARG, if the source value is invalid
238 * DISP_E_OVERFLOW, if the value will not fit in the destination
240 HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
242 return _VarI1FromDate(dateIn, pcOut);
245 /************************************************************************
246 * VarI1FromCy (OLEAUT32.250)
248 * Convert a VT_CY to a VT_I1.
250 * PARAMS
251 * cyIn [I] Source
252 * pcOut [O] Destination
254 * RETURNS
255 * Success: S_OK.
256 * Failure: E_INVALIDARG, if the source value is invalid
257 * DISP_E_OVERFLOW, if the value will not fit in the destination
259 HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
261 LONG i = I1_MAX + 1;
263 _VarI4FromCy(cyIn, &i);
264 return _VarI1FromI4(i, pcOut);
267 /************************************************************************
268 * VarI1FromStr (OLEAUT32.251)
270 * Convert a VT_BSTR to a VT_I1.
272 * PARAMS
273 * strIn [I] Source
274 * lcid [I] LCID for the conversion
275 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
276 * pcOut [O] Destination
278 * RETURNS
279 * Success: S_OK.
280 * Failure: E_INVALIDARG, if the source value is invalid
281 * DISP_E_OVERFLOW, if the value will not fit in the destination
282 * DISP_E_TYPEMISMATCH, if the type cannot be converted
284 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
286 return _VarI1FromStr(strIn, lcid, dwFlags, pcOut);
289 /************************************************************************
290 * VarI1FromDisp (OLEAUT32.252)
292 * Convert a VT_DISPATCH to a VT_I1.
294 * PARAMS
295 * pdispIn [I] Source
296 * lcid [I] LCID for conversion
297 * pcOut [O] Destination
299 * RETURNS
300 * Success: S_OK.
301 * Failure: E_INVALIDARG, if the source value is invalid
302 * DISP_E_OVERFLOW, if the value will not fit in the destination
303 * DISP_E_TYPEMISMATCH, if the type cannot be converted
305 HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
307 return _VarI1FromDisp(pdispIn, lcid, pcOut);
310 /************************************************************************
311 * VarI1FromBool (OLEAUT32.253)
313 * Convert a VT_BOOL to a VT_I1.
315 * PARAMS
316 * boolIn [I] Source
317 * pcOut [O] Destination
319 * RETURNS
320 * S_OK.
322 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
324 return _VarI1FromBool(boolIn, pcOut);
327 /************************************************************************
328 * VarI1FromUI2 (OLEAUT32.254)
330 * Convert a VT_UI2 to a VT_I1.
332 * PARAMS
333 * usIn [I] Source
334 * pcOut [O] Destination
336 * RETURNS
337 * Success: S_OK.
338 * Failure: E_INVALIDARG, if the source value is invalid
339 * DISP_E_OVERFLOW, if the value will not fit in the destination
341 HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
343 return _VarI1FromUI2(usIn, pcOut);
346 /************************************************************************
347 * VarI1FromUI4 (OLEAUT32.255)
349 * Convert a VT_UI4 to a VT_I1.
351 * PARAMS
352 * ulIn [I] Source
353 * pcOut [O] Destination
355 * RETURNS
356 * Success: S_OK.
357 * Failure: E_INVALIDARG, if the source value is invalid
358 * DISP_E_OVERFLOW, if the value will not fit in the destination
359 * DISP_E_TYPEMISMATCH, if the type cannot be converted
361 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
363 return _VarI1FromUI4(ulIn, pcOut);
366 /************************************************************************
367 * VarI1FromDec (OLEAUT32.256)
369 * Convert a VT_DECIMAL to a VT_I1.
371 * PARAMS
372 * pDecIn [I] Source
373 * pcOut [O] Destination
375 * RETURNS
376 * Success: S_OK.
377 * Failure: E_INVALIDARG, if the source value is invalid
378 * DISP_E_OVERFLOW, if the value will not fit in the destination
380 HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
382 LONG64 i64;
383 HRESULT hRet;
385 hRet = _VarI8FromDec(pdecIn, &i64);
387 if (SUCCEEDED(hRet))
388 hRet = _VarI1FromI8(i64, pcOut);
389 return hRet;
392 /************************************************************************
393 * VarI1FromI8 (OLEAUT32.376)
395 * Convert a VT_I8 to a VT_I1.
397 * PARAMS
398 * llIn [I] Source
399 * pcOut [O] Destination
401 * RETURNS
402 * Success: S_OK.
403 * Failure: E_INVALIDARG, if the source value is invalid
404 * DISP_E_OVERFLOW, if the value will not fit in the destination
406 HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
408 return _VarI1FromI8(llIn, pcOut);
411 /************************************************************************
412 * VarI1FromUI8 (OLEAUT32.377)
414 * Convert a VT_UI8 to a VT_I1.
416 * PARAMS
417 * ullIn [I] Source
418 * pcOut [O] Destination
420 * RETURNS
421 * Success: S_OK.
422 * Failure: E_INVALIDARG, if the source value is invalid
423 * DISP_E_OVERFLOW, if the value will not fit in the destination
425 HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
427 return _VarI1FromUI8(ullIn, pcOut);
430 /* UI1
433 /************************************************************************
434 * VarUI1FromI2 (OLEAUT32.130)
436 * Convert a VT_I2 to a VT_UI1.
438 * PARAMS
439 * sIn [I] Source
440 * pbOut [O] Destination
442 * RETURNS
443 * Success: S_OK.
444 * Failure: E_INVALIDARG, if the source value is invalid
445 * DISP_E_OVERFLOW, if the value will not fit in the destination
447 HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
449 return _VarUI1FromI2(sIn, pbOut);
452 /************************************************************************
453 * VarUI1FromI4 (OLEAUT32.131)
455 * Convert a VT_I4 to a VT_UI1.
457 * PARAMS
458 * iIn [I] Source
459 * pbOut [O] Destination
461 * RETURNS
462 * Success: S_OK.
463 * Failure: E_INVALIDARG, if the source value is invalid
464 * DISP_E_OVERFLOW, if the value will not fit in the destination
466 HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
468 return _VarUI1FromI4(iIn, pbOut);
471 /************************************************************************
472 * VarUI1FromR4 (OLEAUT32.132)
474 * Convert a VT_R4 to a VT_UI1.
476 * PARAMS
477 * fltIn [I] Source
478 * pbOut [O] Destination
480 * RETURNS
481 * Success: S_OK.
482 * Failure: E_INVALIDARG, if the source value is invalid
483 * DISP_E_OVERFLOW, if the value will not fit in the destination
484 * DISP_E_TYPEMISMATCH, if the type cannot be converted
486 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
488 return _VarUI1FromR4(fltIn, pbOut);
491 /************************************************************************
492 * VarUI1FromR8 (OLEAUT32.133)
494 * Convert a VT_R8 to a VT_UI1.
496 * PARAMS
497 * dblIn [I] Source
498 * pbOut [O] Destination
500 * RETURNS
501 * Success: S_OK.
502 * Failure: E_INVALIDARG, if the source value is invalid
503 * DISP_E_OVERFLOW, if the value will not fit in the destination
505 * NOTES
506 * See VarI8FromR8() for details concerning rounding.
508 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
510 if (dblIn < -0.5 || dblIn > (double)UI1_MAX)
511 return DISP_E_OVERFLOW;
512 OLEAUT32_DutchRound(BYTE, dblIn, *pbOut);
513 return S_OK;
516 /************************************************************************
517 * VarUI1FromCy (OLEAUT32.134)
519 * Convert a VT_CY to a VT_UI1.
521 * PARAMS
522 * cyIn [I] Source
523 * pbOut [O] Destination
525 * RETURNS
526 * Success: S_OK.
527 * Failure: E_INVALIDARG, if the source value is invalid
528 * DISP_E_OVERFLOW, if the value will not fit in the destination
530 * NOTES
531 * Negative values >= -5000 will be converted to 0.
533 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
535 ULONG i = UI1_MAX + 1;
537 _VarUI4FromCy(cyIn, &i);
538 return _VarUI1FromUI4(i, pbOut);
541 /************************************************************************
542 * VarUI1FromDate (OLEAUT32.135)
544 * Convert a VT_DATE to a VT_UI1.
546 * PARAMS
547 * dateIn [I] Source
548 * pbOut [O] Destination
550 * RETURNS
551 * Success: S_OK.
552 * Failure: E_INVALIDARG, if the source value is invalid
553 * DISP_E_OVERFLOW, if the value will not fit in the destination
555 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
557 return _VarUI1FromDate(dateIn, pbOut);
560 /************************************************************************
561 * VarUI1FromStr (OLEAUT32.136)
563 * Convert a VT_BSTR to a VT_UI1.
565 * PARAMS
566 * strIn [I] Source
567 * lcid [I] LCID for the conversion
568 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
569 * pbOut [O] Destination
571 * RETURNS
572 * Success: S_OK.
573 * Failure: E_INVALIDARG, if the source value is invalid
574 * DISP_E_OVERFLOW, if the value will not fit in the destination
575 * DISP_E_TYPEMISMATCH, if the type cannot be converted
577 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
579 return _VarUI1FromStr(strIn, lcid, dwFlags, pbOut);
582 /************************************************************************
583 * VarUI1FromDisp (OLEAUT32.137)
585 * Convert a VT_DISPATCH to a VT_UI1.
587 * PARAMS
588 * pdispIn [I] Source
589 * lcid [I] LCID for conversion
590 * pbOut [O] Destination
592 * RETURNS
593 * Success: S_OK.
594 * Failure: E_INVALIDARG, if the source value is invalid
595 * DISP_E_OVERFLOW, if the value will not fit in the destination
596 * DISP_E_TYPEMISMATCH, if the type cannot be converted
598 HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
600 return _VarUI1FromDisp(pdispIn, lcid, pbOut);
603 /************************************************************************
604 * VarUI1FromBool (OLEAUT32.138)
606 * Convert a VT_BOOL to a VT_UI1.
608 * PARAMS
609 * boolIn [I] Source
610 * pbOut [O] Destination
612 * RETURNS
613 * S_OK.
615 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
617 return _VarUI1FromBool(boolIn, pbOut);
620 /************************************************************************
621 * VarUI1FromI1 (OLEAUT32.237)
623 * Convert a VT_I1 to a VT_UI1.
625 * PARAMS
626 * cIn [I] Source
627 * pbOut [O] Destination
629 * RETURNS
630 * Success: S_OK.
631 * Failure: E_INVALIDARG, if the source value is invalid
632 * DISP_E_OVERFLOW, if the value will not fit in the destination
634 HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
636 return _VarUI1FromI1(cIn, pbOut);
639 /************************************************************************
640 * VarUI1FromUI2 (OLEAUT32.238)
642 * Convert a VT_UI2 to a VT_UI1.
644 * PARAMS
645 * usIn [I] Source
646 * pbOut [O] Destination
648 * RETURNS
649 * Success: S_OK.
650 * Failure: E_INVALIDARG, if the source value is invalid
651 * DISP_E_OVERFLOW, if the value will not fit in the destination
653 HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
655 return _VarUI1FromUI2(usIn, pbOut);
658 /************************************************************************
659 * VarUI1FromUI4 (OLEAUT32.239)
661 * Convert a VT_UI4 to a VT_UI1.
663 * PARAMS
664 * ulIn [I] Source
665 * pbOut [O] Destination
667 * RETURNS
668 * Success: S_OK.
669 * Failure: E_INVALIDARG, if the source value is invalid
670 * DISP_E_OVERFLOW, if the value will not fit in the destination
672 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
674 return _VarUI1FromUI4(ulIn, pbOut);
677 /************************************************************************
678 * VarUI1FromDec (OLEAUT32.240)
680 * Convert a VT_DECIMAL to a VT_UI1.
682 * PARAMS
683 * pDecIn [I] Source
684 * pbOut [O] Destination
686 * RETURNS
687 * Success: S_OK.
688 * Failure: E_INVALIDARG, if the source value is invalid
689 * DISP_E_OVERFLOW, if the value will not fit in the destination
691 HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
693 LONG64 i64;
694 HRESULT hRet;
696 hRet = _VarI8FromDec(pdecIn, &i64);
698 if (SUCCEEDED(hRet))
699 hRet = _VarUI1FromI8(i64, pbOut);
700 return hRet;
703 /************************************************************************
704 * VarUI1FromI8 (OLEAUT32.372)
706 * Convert a VT_I8 to a VT_UI1.
708 * PARAMS
709 * llIn [I] Source
710 * pbOut [O] Destination
712 * RETURNS
713 * Success: S_OK.
714 * Failure: E_INVALIDARG, if the source value is invalid
715 * DISP_E_OVERFLOW, if the value will not fit in the destination
717 HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
719 return _VarUI1FromI8(llIn, pbOut);
722 /************************************************************************
723 * VarUI1FromUI8 (OLEAUT32.373)
725 * Convert a VT_UI8 to a VT_UI1.
727 * PARAMS
728 * ullIn [I] Source
729 * pbOut [O] Destination
731 * RETURNS
732 * Success: S_OK.
733 * Failure: E_INVALIDARG, if the source value is invalid
734 * DISP_E_OVERFLOW, if the value will not fit in the destination
736 HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
738 return _VarUI1FromUI8(ullIn, pbOut);
742 /* I2
745 /************************************************************************
746 * VarI2FromUI1 (OLEAUT32.48)
748 * Convert a VT_UI2 to a VT_I2.
750 * PARAMS
751 * bIn [I] Source
752 * psOut [O] Destination
754 * RETURNS
755 * S_OK.
757 HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
759 return _VarI2FromUI1(bIn, psOut);
762 /************************************************************************
763 * VarI2FromI4 (OLEAUT32.49)
765 * Convert a VT_I4 to a VT_I2.
767 * PARAMS
768 * iIn [I] Source
769 * psOut [O] Destination
771 * RETURNS
772 * Success: S_OK.
773 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
775 HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
777 return _VarI2FromI4(iIn, psOut);
780 /************************************************************************
781 * VarI2FromR4 (OLEAUT32.50)
783 * Convert a VT_R4 to a VT_I2.
785 * PARAMS
786 * fltIn [I] Source
787 * psOut [O] Destination
789 * RETURNS
790 * Success: S_OK.
791 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
793 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
795 return _VarI2FromR4(fltIn, psOut);
798 /************************************************************************
799 * VarI2FromR8 (OLEAUT32.51)
801 * Convert a VT_R8 to a VT_I2.
803 * PARAMS
804 * dblIn [I] Source
805 * psOut [O] Destination
807 * RETURNS
808 * Success: S_OK.
809 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
811 * NOTES
812 * See VarI8FromR8() for details concerning rounding.
814 HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
816 if (dblIn < (double)I2_MIN || dblIn > (double)I2_MAX)
817 return DISP_E_OVERFLOW;
818 OLEAUT32_DutchRound(SHORT, dblIn, *psOut);
819 return S_OK;
822 /************************************************************************
823 * VarI2FromCy (OLEAUT32.52)
825 * Convert a VT_CY to a VT_I2.
827 * PARAMS
828 * cyIn [I] Source
829 * psOut [O] Destination
831 * RETURNS
832 * Success: S_OK.
833 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
835 HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
837 LONG i = I2_MAX + 1;
839 _VarI4FromCy(cyIn, &i);
840 return _VarI2FromI4(i, psOut);
843 /************************************************************************
844 * VarI2FromDate (OLEAUT32.53)
846 * Convert a VT_DATE to a VT_I2.
848 * PARAMS
849 * dateIn [I] Source
850 * psOut [O] Destination
852 * RETURNS
853 * Success: S_OK.
854 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
856 HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
858 return _VarI2FromDate(dateIn, psOut);
861 /************************************************************************
862 * VarI2FromStr (OLEAUT32.54)
864 * Convert a VT_BSTR to a VT_I2.
866 * PARAMS
867 * strIn [I] Source
868 * lcid [I] LCID for the conversion
869 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
870 * psOut [O] Destination
872 * RETURNS
873 * Success: S_OK.
874 * Failure: E_INVALIDARG, if any parameter is invalid
875 * DISP_E_OVERFLOW, if the value will not fit in the destination
876 * DISP_E_TYPEMISMATCH, if the type cannot be converted
878 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
880 return _VarI2FromStr(strIn, lcid, dwFlags, psOut);
883 /************************************************************************
884 * VarI2FromDisp (OLEAUT32.55)
886 * Convert a VT_DISPATCH to a VT_I2.
888 * PARAMS
889 * pdispIn [I] Source
890 * lcid [I] LCID for conversion
891 * psOut [O] Destination
893 * RETURNS
894 * Success: S_OK.
895 * Failure: E_INVALIDARG, if pdispIn is invalid,
896 * DISP_E_OVERFLOW, if the value will not fit in the destination,
897 * DISP_E_TYPEMISMATCH, if the type cannot be converted
899 HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
901 return _VarI2FromDisp(pdispIn, lcid, psOut);
904 /************************************************************************
905 * VarI2FromBool (OLEAUT32.56)
907 * Convert a VT_BOOL to a VT_I2.
909 * PARAMS
910 * boolIn [I] Source
911 * psOut [O] Destination
913 * RETURNS
914 * S_OK.
916 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
918 return _VarI2FromBool(boolIn, psOut);
921 /************************************************************************
922 * VarI2FromI1 (OLEAUT32.205)
924 * Convert a VT_I1 to a VT_I2.
926 * PARAMS
927 * cIn [I] Source
928 * psOut [O] Destination
930 * RETURNS
931 * S_OK.
933 HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
935 return _VarI2FromI1(cIn, psOut);
938 /************************************************************************
939 * VarI2FromUI2 (OLEAUT32.206)
941 * Convert a VT_UI2 to a VT_I2.
943 * PARAMS
944 * usIn [I] Source
945 * psOut [O] Destination
947 * RETURNS
948 * Success: S_OK.
949 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
951 HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
953 return _VarI2FromUI2(usIn, psOut);
956 /************************************************************************
957 * VarI2FromUI4 (OLEAUT32.207)
959 * Convert a VT_UI4 to a VT_I2.
961 * PARAMS
962 * ulIn [I] Source
963 * psOut [O] Destination
965 * RETURNS
966 * Success: S_OK.
967 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
969 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
971 return _VarI2FromUI4(ulIn, psOut);
974 /************************************************************************
975 * VarI2FromDec (OLEAUT32.208)
977 * Convert a VT_DECIMAL to a VT_I2.
979 * PARAMS
980 * pDecIn [I] Source
981 * psOut [O] Destination
983 * RETURNS
984 * Success: S_OK.
985 * Failure: E_INVALIDARG, if the source value is invalid
986 * DISP_E_OVERFLOW, if the value will not fit in the destination
988 HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
990 LONG64 i64;
991 HRESULT hRet;
993 hRet = _VarI8FromDec(pdecIn, &i64);
995 if (SUCCEEDED(hRet))
996 hRet = _VarI2FromI8(i64, psOut);
997 return hRet;
1000 /************************************************************************
1001 * VarI2FromI8 (OLEAUT32.346)
1003 * Convert a VT_I8 to a VT_I2.
1005 * PARAMS
1006 * llIn [I] Source
1007 * psOut [O] Destination
1009 * RETURNS
1010 * Success: S_OK.
1011 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1013 HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
1015 return _VarI2FromI8(llIn, psOut);
1018 /************************************************************************
1019 * VarI2FromUI8 (OLEAUT32.347)
1021 * Convert a VT_UI8 to a VT_I2.
1023 * PARAMS
1024 * ullIn [I] Source
1025 * psOut [O] Destination
1027 * RETURNS
1028 * Success: S_OK.
1029 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1031 HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
1033 return _VarI2FromUI8(ullIn, psOut);
1036 /* UI2
1039 /************************************************************************
1040 * VarUI2FromUI1 (OLEAUT32.257)
1042 * Convert a VT_UI1 to a VT_UI2.
1044 * PARAMS
1045 * bIn [I] Source
1046 * pusOut [O] Destination
1048 * RETURNS
1049 * S_OK.
1051 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
1053 return _VarUI2FromUI1(bIn, pusOut);
1056 /************************************************************************
1057 * VarUI2FromI2 (OLEAUT32.258)
1059 * Convert a VT_I2 to a VT_UI2.
1061 * PARAMS
1062 * sIn [I] Source
1063 * pusOut [O] Destination
1065 * RETURNS
1066 * Success: S_OK.
1067 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1069 HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
1071 return _VarUI2FromI2(sIn, pusOut);
1074 /************************************************************************
1075 * VarUI2FromI4 (OLEAUT32.259)
1077 * Convert a VT_I4 to a VT_UI2.
1079 * PARAMS
1080 * iIn [I] Source
1081 * pusOut [O] Destination
1083 * RETURNS
1084 * Success: S_OK.
1085 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1087 HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
1089 return _VarUI2FromI4(iIn, pusOut);
1092 /************************************************************************
1093 * VarUI2FromR4 (OLEAUT32.260)
1095 * Convert a VT_R4 to a VT_UI2.
1097 * PARAMS
1098 * fltIn [I] Source
1099 * pusOut [O] Destination
1101 * RETURNS
1102 * Success: S_OK.
1103 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1105 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
1107 return _VarUI2FromR4(fltIn, pusOut);
1110 /************************************************************************
1111 * VarUI2FromR8 (OLEAUT32.261)
1113 * Convert a VT_R8 to a VT_UI2.
1115 * PARAMS
1116 * dblIn [I] Source
1117 * pusOut [O] Destination
1119 * RETURNS
1120 * Success: S_OK.
1121 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1123 * NOTES
1124 * See VarI8FromR8() for details concerning rounding.
1126 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
1128 if (dblIn < -0.5 || dblIn > (double)UI2_MAX)
1129 return DISP_E_OVERFLOW;
1130 OLEAUT32_DutchRound(USHORT, dblIn, *pusOut);
1131 return S_OK;
1134 /************************************************************************
1135 * VarUI2FromDate (OLEAUT32.262)
1137 * Convert a VT_DATE to a VT_UI2.
1139 * PARAMS
1140 * dateIn [I] Source
1141 * pusOut [O] Destination
1143 * RETURNS
1144 * Success: S_OK.
1145 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1147 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
1149 return _VarUI2FromDate(dateIn, pusOut);
1152 /************************************************************************
1153 * VarUI2FromCy (OLEAUT32.263)
1155 * Convert a VT_CY to a VT_UI2.
1157 * PARAMS
1158 * cyIn [I] Source
1159 * pusOut [O] Destination
1161 * RETURNS
1162 * Success: S_OK.
1163 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1165 * NOTES
1166 * Negative values >= -5000 will be converted to 0.
1168 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
1170 ULONG i = UI2_MAX + 1;
1172 _VarUI4FromCy(cyIn, &i);
1173 return _VarUI2FromUI4(i, pusOut);
1176 /************************************************************************
1177 * VarUI2FromStr (OLEAUT32.264)
1179 * Convert a VT_BSTR to a VT_UI2.
1181 * PARAMS
1182 * strIn [I] Source
1183 * lcid [I] LCID for the conversion
1184 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1185 * pusOut [O] Destination
1187 * RETURNS
1188 * Success: S_OK.
1189 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1190 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1192 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
1194 return _VarUI2FromStr(strIn, lcid, dwFlags, pusOut);
1197 /************************************************************************
1198 * VarUI2FromDisp (OLEAUT32.265)
1200 * Convert a VT_DISPATCH to a VT_UI2.
1202 * PARAMS
1203 * pdispIn [I] Source
1204 * lcid [I] LCID for conversion
1205 * pusOut [O] Destination
1207 * RETURNS
1208 * Success: S_OK.
1209 * Failure: E_INVALIDARG, if the source value is invalid
1210 * DISP_E_OVERFLOW, if the value will not fit in the destination
1211 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1213 HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
1215 return _VarUI2FromDisp(pdispIn, lcid, pusOut);
1218 /************************************************************************
1219 * VarUI2FromBool (OLEAUT32.266)
1221 * Convert a VT_BOOL to a VT_UI2.
1223 * PARAMS
1224 * boolIn [I] Source
1225 * pusOut [O] Destination
1227 * RETURNS
1228 * S_OK.
1230 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
1232 return _VarUI2FromBool(boolIn, pusOut);
1235 /************************************************************************
1236 * VarUI2FromI1 (OLEAUT32.267)
1238 * Convert a VT_I1 to a VT_UI2.
1240 * PARAMS
1241 * cIn [I] Source
1242 * pusOut [O] Destination
1244 * RETURNS
1245 * Success: S_OK.
1246 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1248 HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
1250 return _VarUI2FromI1(cIn, pusOut);
1253 /************************************************************************
1254 * VarUI2FromUI4 (OLEAUT32.268)
1256 * Convert a VT_UI4 to a VT_UI2.
1258 * PARAMS
1259 * ulIn [I] Source
1260 * pusOut [O] Destination
1262 * RETURNS
1263 * Success: S_OK.
1264 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1266 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
1268 return _VarUI2FromUI4(ulIn, pusOut);
1271 /************************************************************************
1272 * VarUI2FromDec (OLEAUT32.269)
1274 * Convert a VT_DECIMAL to a VT_UI2.
1276 * PARAMS
1277 * pDecIn [I] Source
1278 * pusOut [O] Destination
1280 * RETURNS
1281 * Success: S_OK.
1282 * Failure: E_INVALIDARG, if the source value is invalid
1283 * DISP_E_OVERFLOW, if the value will not fit in the destination
1285 HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
1287 LONG64 i64;
1288 HRESULT hRet;
1290 hRet = _VarI8FromDec(pdecIn, &i64);
1292 if (SUCCEEDED(hRet))
1293 hRet = _VarUI2FromI8(i64, pusOut);
1294 return hRet;
1297 /************************************************************************
1298 * VarUI2FromI8 (OLEAUT32.378)
1300 * Convert a VT_I8 to a VT_UI2.
1302 * PARAMS
1303 * llIn [I] Source
1304 * pusOut [O] Destination
1306 * RETURNS
1307 * Success: S_OK.
1308 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1310 HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
1312 return _VarUI2FromI8(llIn, pusOut);
1315 /************************************************************************
1316 * VarUI2FromUI8 (OLEAUT32.379)
1318 * Convert a VT_UI8 to a VT_UI2.
1320 * PARAMS
1321 * ullIn [I] Source
1322 * pusOut [O] Destination
1324 * RETURNS
1325 * Success: S_OK.
1326 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1328 HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
1330 return _VarUI2FromUI8(ullIn, pusOut);
1333 /* I4
1336 /************************************************************************
1337 * VarI4FromUI1 (OLEAUT32.58)
1339 * Convert a VT_UI1 to a VT_I4.
1341 * PARAMS
1342 * bIn [I] Source
1343 * piOut [O] Destination
1345 * RETURNS
1346 * S_OK.
1348 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
1350 return _VarI4FromUI1(bIn, piOut);
1353 /************************************************************************
1354 * VarI4FromI2 (OLEAUT32.59)
1356 * Convert a VT_I2 to a VT_I4.
1358 * PARAMS
1359 * iIn [I] Source
1360 * piOut [O] Destination
1362 * RETURNS
1363 * Success: S_OK.
1364 * Failure: E_INVALIDARG, if the source value is invalid
1365 * DISP_E_OVERFLOW, if the value will not fit in the destination
1367 HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
1369 return _VarI4FromI2(sIn, piOut);
1372 /************************************************************************
1373 * VarI4FromR4 (OLEAUT32.60)
1375 * Convert a VT_R4 to a VT_I4.
1377 * PARAMS
1378 * fltIn [I] Source
1379 * piOut [O] Destination
1381 * RETURNS
1382 * Success: S_OK.
1383 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1385 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
1387 return _VarI4FromR4(fltIn, piOut);
1390 /************************************************************************
1391 * VarI4FromR8 (OLEAUT32.61)
1393 * Convert a VT_R8 to a VT_I4.
1395 * PARAMS
1396 * dblIn [I] Source
1397 * piOut [O] Destination
1399 * RETURNS
1400 * Success: S_OK.
1401 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1403 * NOTES
1404 * See VarI8FromR8() for details concerning rounding.
1406 HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
1408 if (dblIn < (double)I4_MIN || dblIn > (double)I4_MAX)
1409 return DISP_E_OVERFLOW;
1410 OLEAUT32_DutchRound(LONG, dblIn, *piOut);
1411 return S_OK;
1414 /************************************************************************
1415 * VarI4FromCy (OLEAUT32.62)
1417 * Convert a VT_CY to a VT_I4.
1419 * PARAMS
1420 * cyIn [I] Source
1421 * piOut [O] Destination
1423 * RETURNS
1424 * Success: S_OK.
1425 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1427 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
1429 double d = cyIn.int64 / CY_MULTIPLIER_F;
1430 return _VarI4FromR8(d, piOut);
1433 /************************************************************************
1434 * VarI4FromDate (OLEAUT32.63)
1436 * Convert a VT_DATE to a VT_I4.
1438 * PARAMS
1439 * dateIn [I] Source
1440 * piOut [O] Destination
1442 * RETURNS
1443 * Success: S_OK.
1444 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1446 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
1448 return _VarI4FromDate(dateIn, piOut);
1451 /************************************************************************
1452 * VarI4FromStr (OLEAUT32.64)
1454 * Convert a VT_BSTR to a VT_I4.
1456 * PARAMS
1457 * strIn [I] Source
1458 * lcid [I] LCID for the conversion
1459 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1460 * piOut [O] Destination
1462 * RETURNS
1463 * Success: S_OK.
1464 * Failure: E_INVALIDARG, if any parameter is invalid
1465 * DISP_E_OVERFLOW, if the value will not fit in the destination
1466 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1468 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
1470 return _VarI4FromStr(strIn, lcid, dwFlags, piOut);
1473 /************************************************************************
1474 * VarI4FromDisp (OLEAUT32.65)
1476 * Convert a VT_DISPATCH to a VT_I4.
1478 * PARAMS
1479 * pdispIn [I] Source
1480 * lcid [I] LCID for conversion
1481 * piOut [O] Destination
1483 * RETURNS
1484 * Success: S_OK.
1485 * Failure: E_INVALIDARG, if the source value is invalid
1486 * DISP_E_OVERFLOW, if the value will not fit in the destination
1487 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1489 HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
1491 return _VarI4FromDisp(pdispIn, lcid, piOut);
1494 /************************************************************************
1495 * VarI4FromBool (OLEAUT32.66)
1497 * Convert a VT_BOOL to a VT_I4.
1499 * PARAMS
1500 * boolIn [I] Source
1501 * piOut [O] Destination
1503 * RETURNS
1504 * S_OK.
1506 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
1508 return _VarI4FromBool(boolIn, piOut);
1511 /************************************************************************
1512 * VarI4FromI1 (OLEAUT32.209)
1514 * Convert a VT_I4 to a VT_I4.
1516 * PARAMS
1517 * cIn [I] Source
1518 * piOut [O] Destination
1520 * RETURNS
1521 * S_OK.
1523 HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
1525 return _VarI4FromI1(cIn, piOut);
1528 /************************************************************************
1529 * VarI4FromUI2 (OLEAUT32.210)
1531 * Convert a VT_UI2 to a VT_I4.
1533 * PARAMS
1534 * usIn [I] Source
1535 * piOut [O] Destination
1537 * RETURNS
1538 * S_OK.
1540 HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
1542 return _VarI4FromUI2(usIn, piOut);
1545 /************************************************************************
1546 * VarI4FromUI4 (OLEAUT32.211)
1548 * Convert a VT_UI4 to a VT_I4.
1550 * PARAMS
1551 * ulIn [I] Source
1552 * piOut [O] Destination
1554 * RETURNS
1555 * Success: S_OK.
1556 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1558 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
1560 return _VarI4FromUI4(ulIn, piOut);
1563 /************************************************************************
1564 * VarI4FromDec (OLEAUT32.212)
1566 * Convert a VT_DECIMAL to a VT_I4.
1568 * PARAMS
1569 * pDecIn [I] Source
1570 * piOut [O] Destination
1572 * RETURNS
1573 * Success: S_OK.
1574 * Failure: E_INVALIDARG, if pdecIn is invalid
1575 * DISP_E_OVERFLOW, if the value will not fit in the destination
1577 HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
1579 LONG64 i64;
1580 HRESULT hRet;
1582 hRet = _VarI8FromDec(pdecIn, &i64);
1584 if (SUCCEEDED(hRet))
1585 hRet = _VarI4FromI8(i64, piOut);
1586 return hRet;
1589 /************************************************************************
1590 * VarI4FromI8 (OLEAUT32.348)
1592 * Convert a VT_I8 to a VT_I4.
1594 * PARAMS
1595 * llIn [I] Source
1596 * piOut [O] Destination
1598 * RETURNS
1599 * Success: S_OK.
1600 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1602 HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
1604 return _VarI4FromI8(llIn, piOut);
1607 /************************************************************************
1608 * VarI4FromUI8 (OLEAUT32.349)
1610 * Convert a VT_UI8 to a VT_I4.
1612 * PARAMS
1613 * ullIn [I] Source
1614 * piOut [O] Destination
1616 * RETURNS
1617 * Success: S_OK.
1618 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1620 HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
1622 return _VarI4FromUI8(ullIn, piOut);
1625 /* UI4
1628 /************************************************************************
1629 * VarUI4FromUI1 (OLEAUT32.270)
1631 * Convert a VT_UI1 to a VT_UI4.
1633 * PARAMS
1634 * bIn [I] Source
1635 * pulOut [O] Destination
1637 * RETURNS
1638 * S_OK.
1640 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
1642 return _VarUI4FromUI1(bIn, pulOut);
1645 /************************************************************************
1646 * VarUI4FromI2 (OLEAUT32.271)
1648 * Convert a VT_I2 to a VT_UI4.
1650 * PARAMS
1651 * sIn [I] Source
1652 * pulOut [O] Destination
1654 * RETURNS
1655 * Success: S_OK.
1656 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1658 HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
1660 return _VarUI4FromI2(sIn, pulOut);
1663 /************************************************************************
1664 * VarUI4FromI4 (OLEAUT32.272)
1666 * Convert a VT_I4 to a VT_UI4.
1668 * PARAMS
1669 * iIn [I] Source
1670 * pulOut [O] Destination
1672 * RETURNS
1673 * Success: S_OK.
1674 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1676 HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
1678 return _VarUI4FromI4(iIn, pulOut);
1681 /************************************************************************
1682 * VarUI4FromR4 (OLEAUT32.273)
1684 * Convert a VT_R4 to a VT_UI4.
1686 * PARAMS
1687 * fltIn [I] Source
1688 * pulOut [O] Destination
1690 * RETURNS
1691 * Success: S_OK.
1692 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1694 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
1696 return _VarUI4FromR4(fltIn, pulOut);
1699 /************************************************************************
1700 * VarUI4FromR8 (OLEAUT32.274)
1702 * Convert a VT_R8 to a VT_UI4.
1704 * PARAMS
1705 * dblIn [I] Source
1706 * pulOut [O] Destination
1708 * RETURNS
1709 * Success: S_OK.
1710 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1712 * NOTES
1713 * See VarI8FromR8() for details concerning rounding.
1715 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
1717 if (dblIn < -0.5 || dblIn > (double)UI4_MAX)
1718 return DISP_E_OVERFLOW;
1719 OLEAUT32_DutchRound(ULONG, dblIn, *pulOut);
1720 return S_OK;
1723 /************************************************************************
1724 * VarUI4FromDate (OLEAUT32.275)
1726 * Convert a VT_DATE to a VT_UI4.
1728 * PARAMS
1729 * dateIn [I] Source
1730 * pulOut [O] Destination
1732 * RETURNS
1733 * Success: S_OK.
1734 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1736 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
1738 return _VarUI4FromDate(dateIn, pulOut);
1741 /************************************************************************
1742 * VarUI4FromCy (OLEAUT32.276)
1744 * Convert a VT_CY to a VT_UI4.
1746 * PARAMS
1747 * cyIn [I] Source
1748 * pulOut [O] Destination
1750 * RETURNS
1751 * Success: S_OK.
1752 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1754 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
1756 double d = cyIn.int64 / CY_MULTIPLIER_F;
1757 return _VarUI4FromR8(d, pulOut);
1760 /************************************************************************
1761 * VarUI4FromStr (OLEAUT32.277)
1763 * Convert a VT_BSTR to a VT_UI4.
1765 * PARAMS
1766 * strIn [I] Source
1767 * lcid [I] LCID for the conversion
1768 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1769 * pulOut [O] Destination
1771 * RETURNS
1772 * Success: S_OK.
1773 * Failure: E_INVALIDARG, if any parameter is invalid
1774 * DISP_E_OVERFLOW, if the value will not fit in the destination
1775 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1777 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
1779 return _VarUI4FromStr(strIn, lcid, dwFlags, pulOut);
1782 /************************************************************************
1783 * VarUI4FromDisp (OLEAUT32.278)
1785 * Convert a VT_DISPATCH to a VT_UI4.
1787 * PARAMS
1788 * pdispIn [I] Source
1789 * lcid [I] LCID for conversion
1790 * pulOut [O] Destination
1792 * RETURNS
1793 * Success: S_OK.
1794 * Failure: E_INVALIDARG, if the source value is invalid
1795 * DISP_E_OVERFLOW, if the value will not fit in the destination
1796 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1798 HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
1800 return _VarUI4FromDisp(pdispIn, lcid, pulOut);
1803 /************************************************************************
1804 * VarUI4FromBool (OLEAUT32.279)
1806 * Convert a VT_BOOL to a VT_UI4.
1808 * PARAMS
1809 * boolIn [I] Source
1810 * pulOut [O] Destination
1812 * RETURNS
1813 * S_OK.
1815 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
1817 return _VarUI4FromBool(boolIn, pulOut);
1820 /************************************************************************
1821 * VarUI4FromI1 (OLEAUT32.280)
1823 * Convert a VT_I1 to a VT_UI4.
1825 * PARAMS
1826 * cIn [I] Source
1827 * pulOut [O] Destination
1829 * RETURNS
1830 * Success: S_OK.
1831 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1833 HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
1835 return _VarUI4FromI1(cIn, pulOut);
1838 /************************************************************************
1839 * VarUI4FromUI2 (OLEAUT32.281)
1841 * Convert a VT_UI2 to a VT_UI4.
1843 * PARAMS
1844 * usIn [I] Source
1845 * pulOut [O] Destination
1847 * RETURNS
1848 * S_OK.
1850 HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
1852 return _VarUI4FromUI2(usIn, pulOut);
1855 /************************************************************************
1856 * VarUI4FromDec (OLEAUT32.282)
1858 * Convert a VT_DECIMAL to a VT_UI4.
1860 * PARAMS
1861 * pDecIn [I] Source
1862 * pulOut [O] Destination
1864 * RETURNS
1865 * Success: S_OK.
1866 * Failure: E_INVALIDARG, if pdecIn is invalid
1867 * DISP_E_OVERFLOW, if the value will not fit in the destination
1869 HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
1871 LONG64 i64;
1872 HRESULT hRet;
1874 hRet = _VarI8FromDec(pdecIn, &i64);
1876 if (SUCCEEDED(hRet))
1877 hRet = _VarUI4FromI8(i64, pulOut);
1878 return hRet;
1881 /************************************************************************
1882 * VarUI4FromI8 (OLEAUT32.425)
1884 * Convert a VT_I8 to a VT_UI4.
1886 * PARAMS
1887 * llIn [I] Source
1888 * pulOut [O] Destination
1890 * RETURNS
1891 * Success: S_OK.
1892 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1894 HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
1896 return _VarUI4FromI8(llIn, pulOut);
1899 /************************************************************************
1900 * VarUI4FromUI8 (OLEAUT32.426)
1902 * Convert a VT_UI8 to a VT_UI4.
1904 * PARAMS
1905 * ullIn [I] Source
1906 * pulOut [O] Destination
1908 * RETURNS
1909 * Success: S_OK.
1910 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1912 HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
1914 return _VarUI4FromUI8(ullIn, pulOut);
1917 /* I8
1920 /************************************************************************
1921 * VarI8FromUI1 (OLEAUT32.333)
1923 * Convert a VT_UI1 to a VT_I8.
1925 * PARAMS
1926 * bIn [I] Source
1927 * pi64Out [O] Destination
1929 * RETURNS
1930 * S_OK.
1932 HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
1934 return _VarI8FromUI1(bIn, pi64Out);
1938 /************************************************************************
1939 * VarI8FromI2 (OLEAUT32.334)
1941 * Convert a VT_I2 to a VT_I8.
1943 * PARAMS
1944 * sIn [I] Source
1945 * pi64Out [O] Destination
1947 * RETURNS
1948 * S_OK.
1950 HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
1952 return _VarI8FromI2(sIn, pi64Out);
1955 /************************************************************************
1956 * VarI8FromR4 (OLEAUT32.335)
1958 * Convert a VT_R4 to a VT_I8.
1960 * PARAMS
1961 * fltIn [I] Source
1962 * pi64Out [O] Destination
1964 * RETURNS
1965 * Success: S_OK.
1966 * Failure: E_INVALIDARG, if the source value is invalid
1967 * DISP_E_OVERFLOW, if the value will not fit in the destination
1969 HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
1971 return _VarI8FromR4(fltIn, pi64Out);
1974 /************************************************************************
1975 * VarI8FromR8 (OLEAUT32.336)
1977 * Convert a VT_R8 to a VT_I8.
1979 * PARAMS
1980 * dblIn [I] Source
1981 * pi64Out [O] Destination
1983 * RETURNS
1984 * Success: S_OK.
1985 * Failure: E_INVALIDARG, if the source value is invalid
1986 * DISP_E_OVERFLOW, if the value will not fit in the destination
1988 * NOTES
1989 * Only values that fit into 63 bits are accepted. Due to rounding issues,
1990 * very high or low values will not be accurately converted.
1992 * Numbers are rounded using Dutch rounding, as follows:
1994 *| Fractional Part Sign Direction Example
1995 *| --------------- ---- --------- -------
1996 *| < 0.5 + Down 0.4 -> 0.0
1997 *| < 0.5 - Up -0.4 -> 0.0
1998 *| > 0.5 + Up 0.6 -> 1.0
1999 *| < 0.5 - Up -0.6 -> -1.0
2000 *| = 0.5 + Up/Down Down if even, Up if odd
2001 *| = 0.5 - Up/Down Up if even, Down if odd
2003 * This system is often used in supermarkets.
2005 HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
2007 if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
2008 return DISP_E_OVERFLOW;
2009 OLEAUT32_DutchRound(LONG64, dblIn, *pi64Out);
2010 return S_OK;
2013 /************************************************************************
2014 * VarI8FromCy (OLEAUT32.337)
2016 * Convert a VT_CY to a VT_I8.
2018 * PARAMS
2019 * cyIn [I] Source
2020 * pi64Out [O] Destination
2022 * RETURNS
2023 * S_OK.
2025 * NOTES
2026 * All negative numbers are rounded down by 1, including those that are
2027 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2028 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2029 * for details.
2031 HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
2033 *pi64Out = cyIn.int64 / CY_MULTIPLIER;
2035 if (cyIn.int64 < 0)
2036 (*pi64Out)--; /* Mimic Win32 bug */
2037 else
2039 cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2041 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
2042 (*pi64Out)++;
2044 return S_OK;
2047 /************************************************************************
2048 * VarI8FromDate (OLEAUT32.338)
2050 * Convert a VT_DATE to a VT_I8.
2052 * PARAMS
2053 * dateIn [I] Source
2054 * pi64Out [O] Destination
2056 * RETURNS
2057 * Success: S_OK.
2058 * Failure: E_INVALIDARG, if the source value is invalid
2059 * DISP_E_OVERFLOW, if the value will not fit in the destination
2060 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2062 HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
2064 return _VarI8FromDate(dateIn, pi64Out);
2067 /************************************************************************
2068 * VarI8FromStr (OLEAUT32.339)
2070 * Convert a VT_BSTR to a VT_I8.
2072 * PARAMS
2073 * strIn [I] Source
2074 * lcid [I] LCID for the conversion
2075 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2076 * pi64Out [O] Destination
2078 * RETURNS
2079 * Success: S_OK.
2080 * Failure: E_INVALIDARG, if the source value is invalid
2081 * DISP_E_OVERFLOW, if the value will not fit in the destination
2082 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2084 HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
2086 return _VarI8FromStr(strIn, lcid, dwFlags, pi64Out);
2089 /************************************************************************
2090 * VarI8FromDisp (OLEAUT32.340)
2092 * Convert a VT_DISPATCH to a VT_I8.
2094 * PARAMS
2095 * pdispIn [I] Source
2096 * lcid [I] LCID for conversion
2097 * pi64Out [O] Destination
2099 * RETURNS
2100 * Success: S_OK.
2101 * Failure: E_INVALIDARG, if the source value is invalid
2102 * DISP_E_OVERFLOW, if the value will not fit in the destination
2103 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2105 HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
2107 return _VarI8FromDisp(pdispIn, lcid, pi64Out);
2110 /************************************************************************
2111 * VarI8FromBool (OLEAUT32.341)
2113 * Convert a VT_BOOL to a VT_I8.
2115 * PARAMS
2116 * boolIn [I] Source
2117 * pi64Out [O] Destination
2119 * RETURNS
2120 * S_OK.
2122 HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
2124 return _VarI8FromBool(boolIn, pi64Out);
2127 /************************************************************************
2128 * VarI8FromI1 (OLEAUT32.342)
2130 * Convert a VT_I1 to a VT_I8.
2132 * PARAMS
2133 * cIn [I] Source
2134 * pi64Out [O] Destination
2136 * RETURNS
2137 * S_OK.
2139 HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
2141 return _VarI8FromI1(cIn, pi64Out);
2144 /************************************************************************
2145 * VarI8FromUI2 (OLEAUT32.343)
2147 * Convert a VT_UI2 to a VT_I8.
2149 * PARAMS
2150 * usIn [I] Source
2151 * pi64Out [O] Destination
2153 * RETURNS
2154 * S_OK.
2156 HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
2158 return _VarI8FromUI2(usIn, pi64Out);
2161 /************************************************************************
2162 * VarI8FromUI4 (OLEAUT32.344)
2164 * Convert a VT_UI4 to a VT_I8.
2166 * PARAMS
2167 * ulIn [I] Source
2168 * pi64Out [O] Destination
2170 * RETURNS
2171 * S_OK.
2173 HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
2175 return _VarI8FromUI4(ulIn, pi64Out);
2178 /************************************************************************
2179 * VarI8FromDec (OLEAUT32.345)
2181 * Convert a VT_DECIMAL to a VT_I8.
2183 * PARAMS
2184 * pDecIn [I] Source
2185 * pi64Out [O] Destination
2187 * RETURNS
2188 * Success: S_OK.
2189 * Failure: E_INVALIDARG, if the source value is invalid
2190 * DISP_E_OVERFLOW, if the value will not fit in the destination
2192 HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
2194 if (!DEC_SCALE(pdecIn))
2196 /* This decimal is just a 96 bit integer */
2197 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2198 return E_INVALIDARG;
2200 if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
2201 return DISP_E_OVERFLOW;
2203 if (DEC_SIGN(pdecIn))
2204 *pi64Out = -DEC_LO64(pdecIn);
2205 else
2206 *pi64Out = DEC_LO64(pdecIn);
2207 return S_OK;
2209 else
2211 /* Decimal contains a floating point number */
2212 HRESULT hRet;
2213 double dbl;
2215 hRet = _VarR8FromDec(pdecIn, &dbl);
2216 if (SUCCEEDED(hRet))
2217 hRet = VarI8FromR8(dbl, pi64Out);
2218 return hRet;
2222 /************************************************************************
2223 * VarI8FromUI8 (OLEAUT32.427)
2225 * Convert a VT_UI8 to a VT_I8.
2227 * PARAMS
2228 * ullIn [I] Source
2229 * pi64Out [O] Destination
2231 * RETURNS
2232 * Success: S_OK.
2233 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2235 HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
2237 return _VarI8FromUI8(ullIn, pi64Out);
2240 /* UI8
2243 /************************************************************************
2244 * VarUI8FromI8 (OLEAUT32.428)
2246 * Convert a VT_I8 to a VT_UI8.
2248 * PARAMS
2249 * ulIn [I] Source
2250 * pui64Out [O] Destination
2252 * RETURNS
2253 * Success: S_OK.
2254 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2256 HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
2258 return _VarUI8FromI8(llIn, pui64Out);
2261 /************************************************************************
2262 * VarUI8FromUI1 (OLEAUT32.429)
2264 * Convert a VT_UI1 to a VT_UI8.
2266 * PARAMS
2267 * bIn [I] Source
2268 * pui64Out [O] Destination
2270 * RETURNS
2271 * S_OK.
2273 HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
2275 return _VarUI8FromUI1(bIn, pui64Out);
2278 /************************************************************************
2279 * VarUI8FromI2 (OLEAUT32.430)
2281 * Convert a VT_I2 to a VT_UI8.
2283 * PARAMS
2284 * sIn [I] Source
2285 * pui64Out [O] Destination
2287 * RETURNS
2288 * S_OK.
2290 HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
2292 return _VarUI8FromI2(sIn, pui64Out);
2295 /************************************************************************
2296 * VarUI8FromR4 (OLEAUT32.431)
2298 * Convert a VT_R4 to a VT_UI8.
2300 * PARAMS
2301 * fltIn [I] Source
2302 * pui64Out [O] Destination
2304 * RETURNS
2305 * Success: S_OK.
2306 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2308 HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
2310 return _VarUI8FromR4(fltIn, pui64Out);
2313 /************************************************************************
2314 * VarUI8FromR8 (OLEAUT32.432)
2316 * Convert a VT_R8 to a VT_UI8.
2318 * PARAMS
2319 * dblIn [I] Source
2320 * pui64Out [O] Destination
2322 * RETURNS
2323 * Success: S_OK.
2324 * Failure: E_INVALIDARG, if the source value is invalid
2325 * DISP_E_OVERFLOW, if the value will not fit in the destination
2327 * NOTES
2328 * See VarI8FromR8() for details concerning rounding.
2330 HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
2332 if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
2333 return DISP_E_OVERFLOW;
2334 OLEAUT32_DutchRound(ULONG64, dblIn, *pui64Out);
2335 return S_OK;
2338 /************************************************************************
2339 * VarUI8FromCy (OLEAUT32.433)
2341 * Convert a VT_CY to a VT_UI8.
2343 * PARAMS
2344 * cyIn [I] Source
2345 * pui64Out [O] Destination
2347 * RETURNS
2348 * Success: S_OK.
2349 * Failure: E_INVALIDARG, if the source value is invalid
2350 * DISP_E_OVERFLOW, if the value will not fit in the destination
2352 * NOTES
2353 * Negative values >= -5000 will be converted to 0.
2355 HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
2357 if (cyIn.int64 < 0)
2359 if (cyIn.int64 < -CY_HALF)
2360 return DISP_E_OVERFLOW;
2361 *pui64Out = 0;
2363 else
2365 *pui64Out = cyIn.int64 / CY_MULTIPLIER;
2367 cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2369 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
2370 (*pui64Out)++;
2372 return S_OK;
2375 /************************************************************************
2376 * VarUI8FromDate (OLEAUT32.434)
2378 * Convert a VT_DATE to a VT_UI8.
2380 * PARAMS
2381 * dateIn [I] Source
2382 * pui64Out [O] Destination
2384 * RETURNS
2385 * Success: S_OK.
2386 * Failure: E_INVALIDARG, if the source value is invalid
2387 * DISP_E_OVERFLOW, if the value will not fit in the destination
2388 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2390 HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
2392 return _VarUI8FromDate(dateIn, pui64Out);
2395 /************************************************************************
2396 * VarUI8FromStr (OLEAUT32.435)
2398 * Convert a VT_BSTR to a VT_UI8.
2400 * PARAMS
2401 * strIn [I] Source
2402 * lcid [I] LCID for the conversion
2403 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2404 * pui64Out [O] Destination
2406 * RETURNS
2407 * Success: S_OK.
2408 * Failure: E_INVALIDARG, if the source value is invalid
2409 * DISP_E_OVERFLOW, if the value will not fit in the destination
2410 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2412 HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
2414 return _VarUI8FromStr(strIn, lcid, dwFlags, pui64Out);
2417 /************************************************************************
2418 * VarUI8FromDisp (OLEAUT32.436)
2420 * Convert a VT_DISPATCH to a VT_UI8.
2422 * PARAMS
2423 * pdispIn [I] Source
2424 * lcid [I] LCID for conversion
2425 * pui64Out [O] Destination
2427 * RETURNS
2428 * Success: S_OK.
2429 * Failure: E_INVALIDARG, if the source value is invalid
2430 * DISP_E_OVERFLOW, if the value will not fit in the destination
2431 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2433 HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
2435 return _VarUI8FromDisp(pdispIn, lcid, pui64Out);
2438 /************************************************************************
2439 * VarUI8FromBool (OLEAUT32.437)
2441 * Convert a VT_BOOL to a VT_UI8.
2443 * PARAMS
2444 * boolIn [I] Source
2445 * pui64Out [O] Destination
2447 * RETURNS
2448 * Success: S_OK.
2449 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2451 HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
2453 return _VarUI8FromBool(boolIn, pui64Out);
2455 /************************************************************************
2456 * VarUI8FromI1 (OLEAUT32.438)
2458 * Convert a VT_I1 to a VT_UI8.
2460 * PARAMS
2461 * cIn [I] Source
2462 * pui64Out [O] Destination
2464 * RETURNS
2465 * Success: S_OK.
2466 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2468 HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
2470 return _VarUI8FromI1(cIn, pui64Out);
2473 /************************************************************************
2474 * VarUI8FromUI2 (OLEAUT32.439)
2476 * Convert a VT_UI2 to a VT_UI8.
2478 * PARAMS
2479 * usIn [I] Source
2480 * pui64Out [O] Destination
2482 * RETURNS
2483 * S_OK.
2485 HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
2487 return _VarUI8FromUI2(usIn, pui64Out);
2490 /************************************************************************
2491 * VarUI8FromUI4 (OLEAUT32.440)
2493 * Convert a VT_UI4 to a VT_UI8.
2495 * PARAMS
2496 * ulIn [I] Source
2497 * pui64Out [O] Destination
2499 * RETURNS
2500 * S_OK.
2502 HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
2504 return _VarUI8FromUI4(ulIn, pui64Out);
2507 /************************************************************************
2508 * VarUI8FromDec (OLEAUT32.441)
2510 * Convert a VT_DECIMAL to a VT_UI8.
2512 * PARAMS
2513 * pDecIn [I] Source
2514 * pui64Out [O] Destination
2516 * RETURNS
2517 * Success: S_OK.
2518 * Failure: E_INVALIDARG, if the source value is invalid
2519 * DISP_E_OVERFLOW, if the value will not fit in the destination
2521 * NOTES
2522 * Under native Win32, if the source value has a scale of 0, its sign is
2523 * ignored, i.e. this function takes the absolute value rather than fail
2524 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2525 * (use VarAbs() on pDecIn first if you really want this behaviour).
2527 HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
2529 if (!DEC_SCALE(pdecIn))
2531 /* This decimal is just a 96 bit integer */
2532 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2533 return E_INVALIDARG;
2535 if (DEC_HI32(pdecIn))
2536 return DISP_E_OVERFLOW;
2538 if (DEC_SIGN(pdecIn))
2540 WARN("Sign would be ignored under Win32!\n");
2541 return DISP_E_OVERFLOW;
2544 *pui64Out = DEC_LO64(pdecIn);
2545 return S_OK;
2547 else
2549 /* Decimal contains a floating point number */
2550 HRESULT hRet;
2551 double dbl;
2553 hRet = _VarR8FromDec(pdecIn, &dbl);
2554 if (SUCCEEDED(hRet))
2555 hRet = VarUI8FromR8(dbl, pui64Out);
2556 return hRet;
2560 /* R4
2563 /************************************************************************
2564 * VarR4FromUI1 (OLEAUT32.68)
2566 * Convert a VT_UI1 to a VT_R4.
2568 * PARAMS
2569 * bIn [I] Source
2570 * pFltOut [O] Destination
2572 * RETURNS
2573 * S_OK.
2575 HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
2577 return _VarR4FromUI1(bIn, pFltOut);
2580 /************************************************************************
2581 * VarR4FromI2 (OLEAUT32.69)
2583 * Convert a VT_I2 to a VT_R4.
2585 * PARAMS
2586 * sIn [I] Source
2587 * pFltOut [O] Destination
2589 * RETURNS
2590 * S_OK.
2592 HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
2594 return _VarR4FromI2(sIn, pFltOut);
2597 /************************************************************************
2598 * VarR4FromI4 (OLEAUT32.70)
2600 * Convert a VT_I4 to a VT_R4.
2602 * PARAMS
2603 * sIn [I] Source
2604 * pFltOut [O] Destination
2606 * RETURNS
2607 * S_OK.
2609 HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
2611 return _VarR4FromI4(lIn, pFltOut);
2614 /************************************************************************
2615 * VarR4FromR8 (OLEAUT32.71)
2617 * Convert a VT_R8 to a VT_R4.
2619 * PARAMS
2620 * dblIn [I] Source
2621 * pFltOut [O] Destination
2623 * RETURNS
2624 * Success: S_OK.
2625 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2627 HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
2629 return _VarR4FromR8(dblIn, pFltOut);
2632 /************************************************************************
2633 * VarR4FromCy (OLEAUT32.72)
2635 * Convert a VT_CY to a VT_R4.
2637 * PARAMS
2638 * cyIn [I] Source
2639 * pFltOut [O] Destination
2641 * RETURNS
2642 * S_OK.
2644 HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
2646 return _VarR4FromCy(cyIn, pFltOut);
2649 /************************************************************************
2650 * VarR4FromDate (OLEAUT32.73)
2652 * Convert a VT_DATE to a VT_R4.
2654 * PARAMS
2655 * dateIn [I] Source
2656 * pFltOut [O] Destination
2658 * RETURNS
2659 * Success: S_OK.
2660 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2662 HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
2664 return _VarR4FromDate(dateIn, pFltOut);
2667 /************************************************************************
2668 * VarR4FromStr (OLEAUT32.74)
2670 * Convert a VT_BSTR to a VT_R4.
2672 * PARAMS
2673 * strIn [I] Source
2674 * lcid [I] LCID for the conversion
2675 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2676 * pFltOut [O] Destination
2678 * RETURNS
2679 * Success: S_OK.
2680 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2681 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2683 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
2685 return _VarR4FromStr(strIn, lcid, dwFlags, pFltOut);
2688 /************************************************************************
2689 * VarR4FromDisp (OLEAUT32.75)
2691 * Convert a VT_DISPATCH to a VT_R4.
2693 * PARAMS
2694 * pdispIn [I] Source
2695 * lcid [I] LCID for conversion
2696 * pFltOut [O] Destination
2698 * RETURNS
2699 * Success: S_OK.
2700 * Failure: E_INVALIDARG, if the source value is invalid
2701 * DISP_E_OVERFLOW, if the value will not fit in the destination
2702 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2704 HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
2706 return _VarR4FromDisp(pdispIn, lcid, pFltOut);
2709 /************************************************************************
2710 * VarR4FromBool (OLEAUT32.76)
2712 * Convert a VT_BOOL to a VT_R4.
2714 * PARAMS
2715 * boolIn [I] Source
2716 * pFltOut [O] Destination
2718 * RETURNS
2719 * S_OK.
2721 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
2723 return _VarR4FromBool(boolIn, pFltOut);
2726 /************************************************************************
2727 * VarR4FromI1 (OLEAUT32.213)
2729 * Convert a VT_I1 to a VT_R4.
2731 * PARAMS
2732 * cIn [I] Source
2733 * pFltOut [O] Destination
2735 * RETURNS
2736 * Success: S_OK.
2737 * Failure: E_INVALIDARG, if the source value is invalid
2738 * DISP_E_OVERFLOW, if the value will not fit in the destination
2739 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2741 HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
2743 return _VarR4FromI1(cIn, pFltOut);
2746 /************************************************************************
2747 * VarR4FromUI2 (OLEAUT32.214)
2749 * Convert a VT_UI2 to a VT_R4.
2751 * PARAMS
2752 * usIn [I] Source
2753 * pFltOut [O] Destination
2755 * RETURNS
2756 * Success: S_OK.
2757 * Failure: E_INVALIDARG, if the source value is invalid
2758 * DISP_E_OVERFLOW, if the value will not fit in the destination
2759 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2761 HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
2763 return _VarR4FromUI2(usIn, pFltOut);
2766 /************************************************************************
2767 * VarR4FromUI4 (OLEAUT32.215)
2769 * Convert a VT_UI4 to a VT_R4.
2771 * PARAMS
2772 * ulIn [I] Source
2773 * pFltOut [O] Destination
2775 * RETURNS
2776 * Success: S_OK.
2777 * Failure: E_INVALIDARG, if the source value is invalid
2778 * DISP_E_OVERFLOW, if the value will not fit in the destination
2779 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2781 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
2783 return _VarR4FromUI4(ulIn, pFltOut);
2786 /************************************************************************
2787 * VarR4FromDec (OLEAUT32.216)
2789 * Convert a VT_DECIMAL to a VT_R4.
2791 * PARAMS
2792 * pDecIn [I] Source
2793 * pFltOut [O] Destination
2795 * RETURNS
2796 * Success: S_OK.
2797 * Failure: E_INVALIDARG, if the source value is invalid.
2799 HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
2801 BYTE scale = DEC_SCALE(pDecIn);
2802 int divisor = 1;
2803 double highPart;
2805 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
2806 return E_INVALIDARG;
2808 while (scale--)
2809 divisor *= 10;
2811 if (DEC_SIGN(pDecIn))
2812 divisor = -divisor;
2814 if (DEC_HI32(pDecIn))
2816 highPart = (double)DEC_HI32(pDecIn) / (double)divisor;
2817 highPart *= 1.0e64;
2819 else
2820 highPart = 0.0;
2822 *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
2823 return S_OK;
2826 /************************************************************************
2827 * VarR4FromI8 (OLEAUT32.360)
2829 * Convert a VT_I8 to a VT_R4.
2831 * PARAMS
2832 * ullIn [I] Source
2833 * pFltOut [O] Destination
2835 * RETURNS
2836 * S_OK.
2838 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2840 return _VarR4FromI8(llIn, pFltOut);
2843 /************************************************************************
2844 * VarR4FromUI8 (OLEAUT32.361)
2846 * Convert a VT_UI8 to a VT_R4.
2848 * PARAMS
2849 * ullIn [I] Source
2850 * pFltOut [O] Destination
2852 * RETURNS
2853 * S_OK.
2855 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
2857 return _VarR4FromUI8(ullIn, pFltOut);
2860 /************************************************************************
2861 * VarR4CmpR8 (OLEAUT32.316)
2863 * Compare a VT_R4 to a VT_R8.
2865 * PARAMS
2866 * fltLeft [I] Source
2867 * dblRight [I] Value to compare
2869 * RETURNS
2870 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
2871 * equal to or greater than dblRight respectively.
2873 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
2875 if (fltLeft < dblRight)
2876 return VARCMP_LT;
2877 else if (fltLeft > dblRight)
2878 return VARCMP_GT;
2879 return VARCMP_EQ;
2882 /* R8
2885 /************************************************************************
2886 * VarR8FromUI1 (OLEAUT32.78)
2888 * Convert a VT_UI1 to a VT_R8.
2890 * PARAMS
2891 * bIn [I] Source
2892 * pDblOut [O] Destination
2894 * RETURNS
2895 * S_OK.
2897 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
2899 return _VarR8FromUI1(bIn, pDblOut);
2902 /************************************************************************
2903 * VarR8FromI2 (OLEAUT32.79)
2905 * Convert a VT_I2 to a VT_R8.
2907 * PARAMS
2908 * sIn [I] Source
2909 * pDblOut [O] Destination
2911 * RETURNS
2912 * S_OK.
2914 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
2916 return _VarR8FromI2(sIn, pDblOut);
2919 /************************************************************************
2920 * VarR8FromI4 (OLEAUT32.80)
2922 * Convert a VT_I4 to a VT_R8.
2924 * PARAMS
2925 * sIn [I] Source
2926 * pDblOut [O] Destination
2928 * RETURNS
2929 * S_OK.
2931 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
2933 return _VarR8FromI4(lIn, pDblOut);
2936 /************************************************************************
2937 * VarR8FromR4 (OLEAUT32.81)
2939 * Convert a VT_R4 to a VT_R8.
2941 * PARAMS
2942 * fltIn [I] Source
2943 * pDblOut [O] Destination
2945 * RETURNS
2946 * S_OK.
2948 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
2950 return _VarR8FromR4(fltIn, pDblOut);
2953 /************************************************************************
2954 * VarR8FromCy (OLEAUT32.82)
2956 * Convert a VT_CY to a VT_R8.
2958 * PARAMS
2959 * cyIn [I] Source
2960 * pDblOut [O] Destination
2962 * RETURNS
2963 * S_OK.
2965 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
2967 return _VarR8FromCy(cyIn, pDblOut);
2970 /************************************************************************
2971 * VarR8FromDate (OLEAUT32.83)
2973 * Convert a VT_DATE to a VT_R8.
2975 * PARAMS
2976 * dateIn [I] Source
2977 * pDblOut [O] Destination
2979 * RETURNS
2980 * S_OK.
2982 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
2984 return _VarR8FromDate(dateIn, pDblOut);
2987 /************************************************************************
2988 * VarR8FromStr (OLEAUT32.84)
2990 * Convert a VT_BSTR to a VT_R8.
2992 * PARAMS
2993 * strIn [I] Source
2994 * lcid [I] LCID for the conversion
2995 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2996 * pDblOut [O] Destination
2998 * RETURNS
2999 * Success: S_OK.
3000 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3001 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3003 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3005 return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
3008 /************************************************************************
3009 * VarR8FromDisp (OLEAUT32.85)
3011 * Convert a VT_DISPATCH to a VT_R8.
3013 * PARAMS
3014 * pdispIn [I] Source
3015 * lcid [I] LCID for conversion
3016 * pDblOut [O] Destination
3018 * RETURNS
3019 * Success: S_OK.
3020 * Failure: E_INVALIDARG, if the source value is invalid
3021 * DISP_E_OVERFLOW, if the value will not fit in the destination
3022 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3024 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3026 return _VarR8FromDisp(pdispIn, lcid, pDblOut);
3029 /************************************************************************
3030 * VarR8FromBool (OLEAUT32.86)
3032 * Convert a VT_BOOL to a VT_R8.
3034 * PARAMS
3035 * boolIn [I] Source
3036 * pDblOut [O] Destination
3038 * RETURNS
3039 * S_OK.
3041 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
3043 return _VarR8FromBool(boolIn, pDblOut);
3046 /************************************************************************
3047 * VarR8FromI1 (OLEAUT32.217)
3049 * Convert a VT_I1 to a VT_R8.
3051 * PARAMS
3052 * cIn [I] Source
3053 * pDblOut [O] Destination
3055 * RETURNS
3056 * Success: S_OK.
3057 * Failure: E_INVALIDARG, if the source value is invalid
3058 * DISP_E_OVERFLOW, if the value will not fit in the destination
3059 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3061 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3063 return _VarR8FromI1(cIn, pDblOut);
3066 /************************************************************************
3067 * VarR8FromUI2 (OLEAUT32.218)
3069 * Convert a VT_UI2 to a VT_R8.
3071 * PARAMS
3072 * usIn [I] Source
3073 * pDblOut [O] Destination
3075 * RETURNS
3076 * Success: S_OK.
3077 * Failure: E_INVALIDARG, if the source value is invalid
3078 * DISP_E_OVERFLOW, if the value will not fit in the destination
3079 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3081 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3083 return _VarR8FromUI2(usIn, pDblOut);
3086 /************************************************************************
3087 * VarR8FromUI4 (OLEAUT32.219)
3089 * Convert a VT_UI4 to a VT_R8.
3091 * PARAMS
3092 * ulIn [I] Source
3093 * pDblOut [O] Destination
3095 * RETURNS
3096 * Success: S_OK.
3097 * Failure: E_INVALIDARG, if the source value is invalid
3098 * DISP_E_OVERFLOW, if the value will not fit in the destination
3099 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3101 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3103 return _VarR8FromUI4(ulIn, pDblOut);
3106 /************************************************************************
3107 * VarR8FromDec (OLEAUT32.220)
3109 * Convert a VT_DECIMAL to a VT_R8.
3111 * PARAMS
3112 * pDecIn [I] Source
3113 * pDblOut [O] Destination
3115 * RETURNS
3116 * Success: S_OK.
3117 * Failure: E_INVALIDARG, if the source value is invalid.
3119 HRESULT WINAPI VarR8FromDec(DECIMAL* pDecIn, double *pDblOut)
3121 BYTE scale = DEC_SCALE(pDecIn);
3122 double divisor = 1.0, highPart;
3124 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
3125 return E_INVALIDARG;
3127 while (scale--)
3128 divisor *= 10;
3130 if (DEC_SIGN(pDecIn))
3131 divisor = -divisor;
3133 if (DEC_HI32(pDecIn))
3135 highPart = (double)DEC_HI32(pDecIn) / divisor;
3136 highPart *= 1.0e64;
3138 else
3139 highPart = 0.0;
3141 *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
3142 return S_OK;
3145 /************************************************************************
3146 * VarR8FromI8 (OLEAUT32.362)
3148 * Convert a VT_I8 to a VT_R8.
3150 * PARAMS
3151 * ullIn [I] Source
3152 * pDblOut [O] Destination
3154 * RETURNS
3155 * S_OK.
3157 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3159 return _VarR8FromI8(llIn, pDblOut);
3162 /************************************************************************
3163 * VarR8FromUI8 (OLEAUT32.363)
3165 * Convert a VT_UI8 to a VT_R8.
3167 * PARAMS
3168 * ullIn [I] Source
3169 * pDblOut [O] Destination
3171 * RETURNS
3172 * S_OK.
3174 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3176 return _VarR8FromUI8(ullIn, pDblOut);
3179 /************************************************************************
3180 * VarR8Pow (OLEAUT32.315)
3182 * Raise a VT_R8 to a power.
3184 * PARAMS
3185 * dblLeft [I] Source
3186 * dblPow [I] Power to raise dblLeft by
3187 * pDblOut [O] Destination
3189 * RETURNS
3190 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3192 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3194 *pDblOut = pow(dblLeft, dblPow);
3195 return S_OK;
3198 /************************************************************************
3199 * VarR8Round (OLEAUT32.317)
3201 * Round a VT_R8 to a given number of decimal points.
3203 * PARAMS
3204 * dblIn [I] Source
3205 * nDig [I] Number of decimal points to round to
3206 * pDblOut [O] Destination for rounded number
3208 * RETURNS
3209 * Success: S_OK. pDblOut is rounded to nDig digits.
3210 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3212 * NOTES
3213 * The native version of this function rounds using the internal
3214 * binary representation of the number. Wine uses the dutch rounding
3215 * convention, so therefore small differences can occur in the value returned.
3216 * MSDN says that you should use your own rounding function if you want
3217 * rounding to be predictable in your application.
3219 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3221 double scale, whole, fract;
3223 if (nDig < 0)
3224 return E_INVALIDARG;
3226 scale = pow(10.0, nDig);
3228 dblIn *= scale;
3229 whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3230 fract = dblIn - whole;
3232 if (fract > 0.5)
3233 dblIn = whole + 1.0;
3234 else if (fract == 0.5)
3235 dblIn = whole + fmod(whole, 2.0);
3236 else if (fract >= 0.0)
3237 dblIn = whole;
3238 else if (fract == -0.5)
3239 dblIn = whole - fmod(whole, 2.0);
3240 else if (fract > -0.5)
3241 dblIn = whole;
3242 else
3243 dblIn = whole - 1.0;
3245 *pDblOut = dblIn / scale;
3246 return S_OK;
3249 /* CY
3252 /* Powers of 10 from 0..4 D.P. */
3253 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3254 CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
3256 /************************************************************************
3257 * VarCyFromUI1 (OLEAUT32.98)
3259 * Convert a VT_UI1 to a VT_CY.
3261 * PARAMS
3262 * bIn [I] Source
3263 * pCyOut [O] Destination
3265 * RETURNS
3266 * Success: S_OK.
3267 * Failure: E_INVALIDARG, if the source value is invalid
3268 * DISP_E_OVERFLOW, if the value will not fit in the destination
3269 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3271 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
3273 return _VarCyFromUI1(bIn, pCyOut);
3276 /************************************************************************
3277 * VarCyFromI2 (OLEAUT32.99)
3279 * Convert a VT_I2 to a VT_CY.
3281 * PARAMS
3282 * sIn [I] Source
3283 * pCyOut [O] Destination
3285 * RETURNS
3286 * Success: S_OK.
3287 * Failure: E_INVALIDARG, if the source value is invalid
3288 * DISP_E_OVERFLOW, if the value will not fit in the destination
3289 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3291 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
3293 return _VarCyFromI2(sIn, pCyOut);
3296 /************************************************************************
3297 * VarCyFromI4 (OLEAUT32.100)
3299 * Convert a VT_I4 to a VT_CY.
3301 * PARAMS
3302 * sIn [I] Source
3303 * pCyOut [O] Destination
3305 * RETURNS
3306 * Success: S_OK.
3307 * Failure: E_INVALIDARG, if the source value is invalid
3308 * DISP_E_OVERFLOW, if the value will not fit in the destination
3309 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3311 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
3313 return _VarCyFromI4(lIn, pCyOut);
3316 /************************************************************************
3317 * VarCyFromR4 (OLEAUT32.101)
3319 * Convert a VT_R4 to a VT_CY.
3321 * PARAMS
3322 * fltIn [I] Source
3323 * pCyOut [O] Destination
3325 * RETURNS
3326 * Success: S_OK.
3327 * Failure: E_INVALIDARG, if the source value is invalid
3328 * DISP_E_OVERFLOW, if the value will not fit in the destination
3329 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3331 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
3333 return _VarCyFromR4(fltIn, pCyOut);
3336 /************************************************************************
3337 * VarCyFromR8 (OLEAUT32.102)
3339 * Convert a VT_R8 to a VT_CY.
3341 * PARAMS
3342 * dblIn [I] Source
3343 * pCyOut [O] Destination
3345 * RETURNS
3346 * Success: S_OK.
3347 * Failure: E_INVALIDARG, if the source value is invalid
3348 * DISP_E_OVERFLOW, if the value will not fit in the destination
3349 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3351 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3353 #if defined(__GNUC__) && defined(__i386__)
3354 /* This code gives identical results to Win32 on Intel.
3355 * Here we use fp exceptions to catch overflows when storing the value.
3357 static const unsigned short r8_fpcontrol = 0x137f;
3358 static const double r8_multiplier = CY_MULTIPLIER_F;
3359 unsigned short old_fpcontrol, result_fpstatus;
3361 /* Clear exceptions, save the old fp state and load the new state */
3362 __asm__ __volatile__( "fnclex" );
3363 __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
3364 __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
3365 /* Perform the conversion. */
3366 __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
3367 __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
3368 __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
3369 /* Save the resulting fp state, load the old state and clear exceptions */
3370 __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
3371 __asm__ __volatile__( "fnclex" );
3372 __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
3374 if (result_fpstatus & 0x9) /* Overflow | Invalid */
3375 return DISP_E_OVERFLOW;
3376 return S_OK;
3377 #else
3378 /* This version produces slightly different results for boundary cases */
3379 if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3380 return DISP_E_OVERFLOW;
3381 dblIn *= CY_MULTIPLIER_F;
3382 OLEAUT32_DutchRound(LONG64, dblIn, pCyOut->int64);
3383 #endif
3384 return S_OK;
3387 /************************************************************************
3388 * VarCyFromDate (OLEAUT32.103)
3390 * Convert a VT_DATE to a VT_CY.
3392 * PARAMS
3393 * dateIn [I] Source
3394 * pCyOut [O] Destination
3396 * RETURNS
3397 * Success: S_OK.
3398 * Failure: E_INVALIDARG, if the source value is invalid
3399 * DISP_E_OVERFLOW, if the value will not fit in the destination
3400 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3402 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
3404 return _VarCyFromDate(dateIn, pCyOut);
3407 /************************************************************************
3408 * VarCyFromStr (OLEAUT32.104)
3410 * Convert a VT_BSTR to a VT_CY.
3412 * PARAMS
3413 * strIn [I] Source
3414 * lcid [I] LCID for the conversion
3415 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3416 * pCyOut [O] Destination
3418 * RETURNS
3419 * Success: S_OK.
3420 * Failure: E_INVALIDARG, if the source value is invalid
3421 * DISP_E_OVERFLOW, if the value will not fit in the destination
3422 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3424 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
3426 return _VarCyFromStr(strIn, lcid, dwFlags, pCyOut);
3429 /************************************************************************
3430 * VarCyFromDisp (OLEAUT32.105)
3432 * Convert a VT_DISPATCH to a VT_CY.
3434 * PARAMS
3435 * pdispIn [I] Source
3436 * lcid [I] LCID for conversion
3437 * pCyOut [O] Destination
3439 * RETURNS
3440 * Success: S_OK.
3441 * Failure: E_INVALIDARG, if the source value is invalid
3442 * DISP_E_OVERFLOW, if the value will not fit in the destination
3443 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3445 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
3447 return _VarCyFromDisp(pdispIn, lcid, pCyOut);
3450 /************************************************************************
3451 * VarCyFromBool (OLEAUT32.106)
3453 * Convert a VT_BOOL to a VT_CY.
3455 * PARAMS
3456 * boolIn [I] Source
3457 * pCyOut [O] Destination
3459 * RETURNS
3460 * Success: S_OK.
3461 * Failure: E_INVALIDARG, if the source value is invalid
3462 * DISP_E_OVERFLOW, if the value will not fit in the destination
3463 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3465 * NOTES
3466 * While the sign of the boolean is stored in the currency, the value is
3467 * converted to either 0 or 1.
3469 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
3471 return _VarCyFromBool(boolIn, pCyOut);
3474 /************************************************************************
3475 * VarCyFromI1 (OLEAUT32.225)
3477 * Convert a VT_I1 to a VT_CY.
3479 * PARAMS
3480 * cIn [I] Source
3481 * pCyOut [O] Destination
3483 * RETURNS
3484 * Success: S_OK.
3485 * Failure: E_INVALIDARG, if the source value is invalid
3486 * DISP_E_OVERFLOW, if the value will not fit in the destination
3487 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3489 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3491 return _VarCyFromI1(cIn, pCyOut);
3494 /************************************************************************
3495 * VarCyFromUI2 (OLEAUT32.226)
3497 * Convert a VT_UI2 to a VT_CY.
3499 * PARAMS
3500 * usIn [I] Source
3501 * pCyOut [O] Destination
3503 * RETURNS
3504 * Success: S_OK.
3505 * Failure: E_INVALIDARG, if the source value is invalid
3506 * DISP_E_OVERFLOW, if the value will not fit in the destination
3507 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3509 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
3511 return _VarCyFromUI2(usIn, pCyOut);
3514 /************************************************************************
3515 * VarCyFromUI4 (OLEAUT32.227)
3517 * Convert a VT_UI4 to a VT_CY.
3519 * PARAMS
3520 * ulIn [I] Source
3521 * pCyOut [O] Destination
3523 * RETURNS
3524 * Success: S_OK.
3525 * Failure: E_INVALIDARG, if the source value is invalid
3526 * DISP_E_OVERFLOW, if the value will not fit in the destination
3527 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3529 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
3531 return _VarCyFromUI4(ulIn, pCyOut);
3534 /************************************************************************
3535 * VarCyFromDec (OLEAUT32.228)
3537 * Convert a VT_DECIMAL to a VT_CY.
3539 * PARAMS
3540 * pdecIn [I] Source
3541 * pCyOut [O] Destination
3543 * RETURNS
3544 * Success: S_OK.
3545 * Failure: E_INVALIDARG, if the source value is invalid
3546 * DISP_E_OVERFLOW, if the value will not fit in the destination
3547 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3549 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
3551 DECIMAL rounded;
3552 HRESULT hRet;
3554 hRet = VarDecRound(pdecIn, 4, &rounded);
3556 if (SUCCEEDED(hRet))
3558 double d;
3560 if (DEC_HI32(&rounded))
3561 return DISP_E_OVERFLOW;
3563 /* Note: Without the casts this promotes to int64 which loses precision */
3564 d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
3565 if (DEC_SIGN(&rounded))
3566 d = -d;
3567 return _VarCyFromR8(d, pCyOut);
3569 return hRet;
3572 /************************************************************************
3573 * VarCyFromI8 (OLEAUT32.366)
3575 * Convert a VT_I8 to a VT_CY.
3577 * PARAMS
3578 * ullIn [I] Source
3579 * pCyOut [O] Destination
3581 * RETURNS
3582 * Success: S_OK.
3583 * Failure: E_INVALIDARG, if the source value is invalid
3584 * DISP_E_OVERFLOW, if the value will not fit in the destination
3585 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3587 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
3589 return _VarCyFromI8(llIn, pCyOut);
3592 /************************************************************************
3593 * VarCyFromUI8 (OLEAUT32.375)
3595 * Convert a VT_UI8 to a VT_CY.
3597 * PARAMS
3598 * ullIn [I] Source
3599 * pCyOut [O] Destination
3601 * RETURNS
3602 * Success: S_OK.
3603 * Failure: E_INVALIDARG, if the source value is invalid
3604 * DISP_E_OVERFLOW, if the value will not fit in the destination
3605 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3607 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
3609 return _VarCyFromUI8(ullIn, pCyOut);
3612 /************************************************************************
3613 * VarCyAdd (OLEAUT32.299)
3615 * Add one CY to another.
3617 * PARAMS
3618 * cyLeft [I] Source
3619 * cyRight [I] Value to add
3620 * pCyOut [O] Destination
3622 * RETURNS
3623 * Success: S_OK.
3624 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3626 HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
3628 double l,r;
3629 _VarR8FromCy(cyLeft, &l);
3630 _VarR8FromCy(cyRight, &r);
3631 l = l + r;
3632 return _VarCyFromR8(l, pCyOut);
3635 /************************************************************************
3636 * VarCyMul (OLEAUT32.303)
3638 * Multiply one CY by another.
3640 * PARAMS
3641 * cyLeft [I] Source
3642 * cyRight [I] Value to multiply by
3643 * pCyOut [O] Destination
3645 * RETURNS
3646 * Success: S_OK.
3647 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3649 HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
3651 double l,r;
3652 _VarR8FromCy(cyLeft, &l);
3653 _VarR8FromCy(cyRight, &r);
3654 l = l * r;
3655 return _VarCyFromR8(l, pCyOut);
3658 /************************************************************************
3659 * VarCyMulI4 (OLEAUT32.304)
3661 * Multiply one CY by a VT_I4.
3663 * PARAMS
3664 * cyLeft [I] Source
3665 * lRight [I] Value to multiply by
3666 * pCyOut [O] Destination
3668 * RETURNS
3669 * Success: S_OK.
3670 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3672 HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
3674 double d;
3676 _VarR8FromCy(cyLeft, &d);
3677 d = d * lRight;
3678 return _VarCyFromR8(d, pCyOut);
3681 /************************************************************************
3682 * VarCySub (OLEAUT32.305)
3684 * Subtract one CY from another.
3686 * PARAMS
3687 * cyLeft [I] Source
3688 * cyRight [I] Value to subtract
3689 * pCyOut [O] Destination
3691 * RETURNS
3692 * Success: S_OK.
3693 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3695 HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
3697 double l,r;
3698 _VarR8FromCy(cyLeft, &l);
3699 _VarR8FromCy(cyRight, &r);
3700 l = l - r;
3701 return _VarCyFromR8(l, pCyOut);
3704 /************************************************************************
3705 * VarCyAbs (OLEAUT32.306)
3707 * Convert a VT_CY into its absolute value.
3709 * PARAMS
3710 * cyIn [I] Source
3711 * pCyOut [O] Destination
3713 * RETURNS
3714 * Success: S_OK. pCyOut contains the absolute value.
3715 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3717 HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
3719 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3720 return DISP_E_OVERFLOW;
3722 pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3723 return S_OK;
3726 /************************************************************************
3727 * VarCyFix (OLEAUT32.307)
3729 * Return the integer part of a VT_CY.
3731 * PARAMS
3732 * cyIn [I] Source
3733 * pCyOut [O] Destination
3735 * RETURNS
3736 * Success: S_OK.
3737 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3739 * NOTES
3740 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3741 * negative numbers away from 0, while this function rounds them towards zero.
3743 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
3745 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3746 pCyOut->int64 *= CY_MULTIPLIER;
3747 return S_OK;
3750 /************************************************************************
3751 * VarCyInt (OLEAUT32.308)
3753 * Return the integer part of a VT_CY.
3755 * PARAMS
3756 * cyIn [I] Source
3757 * pCyOut [O] Destination
3759 * RETURNS
3760 * Success: S_OK.
3761 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3763 * NOTES
3764 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3765 * negative numbers towards 0, while this function rounds them away from zero.
3767 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
3769 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3770 pCyOut->int64 *= CY_MULTIPLIER;
3772 if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3774 pCyOut->int64 -= CY_MULTIPLIER;
3776 return S_OK;
3779 /************************************************************************
3780 * VarCyNeg (OLEAUT32.309)
3782 * Change the sign of a VT_CY.
3784 * PARAMS
3785 * cyIn [I] Source
3786 * pCyOut [O] Destination
3788 * RETURNS
3789 * Success: S_OK.
3790 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3792 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
3794 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3795 return DISP_E_OVERFLOW;
3797 pCyOut->int64 = -cyIn.int64;
3798 return S_OK;
3801 /************************************************************************
3802 * VarCyRound (OLEAUT32.310)
3804 * Change the precision of a VT_CY.
3806 * PARAMS
3807 * cyIn [I] Source
3808 * cDecimals [I] New number of decimals to keep
3809 * pCyOut [O] Destination
3811 * RETURNS
3812 * Success: S_OK.
3813 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3815 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
3817 if (cDecimals < 0)
3818 return E_INVALIDARG;
3820 if (cDecimals > 3)
3822 /* Rounding to more precision than we have */
3823 *pCyOut = cyIn;
3824 return S_OK;
3826 else
3828 double d, div = CY_Divisors[cDecimals];
3830 _VarR8FromCy(cyIn, &d);
3831 d = d * div;
3832 OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3833 d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3834 OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3835 return S_OK;
3839 /************************************************************************
3840 * VarCyCmp (OLEAUT32.311)
3842 * Compare two VT_CY values.
3844 * PARAMS
3845 * cyLeft [I] Source
3846 * cyRight [I] Value to compare
3848 * RETURNS
3849 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
3850 * compare is less, equal or greater than source respectively.
3851 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
3853 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
3855 HRESULT hRet;
3856 CY result;
3858 /* Subtract right from left, and compare the result to 0 */
3859 hRet = VarCySub(cyLeft, cyRight, &result);
3861 if (SUCCEEDED(hRet))
3863 if (result.int64 < 0)
3864 hRet = (HRESULT)VARCMP_LT;
3865 else if (result.int64 > 0)
3866 hRet = (HRESULT)VARCMP_GT;
3867 else
3868 hRet = (HRESULT)VARCMP_EQ;
3870 return hRet;
3873 /************************************************************************
3874 * VarCyCmpR8 (OLEAUT32.312)
3876 * Compare a VT_CY to a double
3878 * PARAMS
3879 * cyLeft [I] Currency Source
3880 * dblRight [I] double to compare to cyLeft
3882 * RETURNS
3883 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
3884 * less than, equal to or greater than cyLeft respectively.
3885 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
3887 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
3889 HRESULT hRet;
3890 CY cyRight;
3892 hRet = _VarCyFromR8(dblRight, &cyRight);
3894 if (SUCCEEDED(hRet))
3895 hRet = VarCyCmp(cyLeft, cyRight);
3897 return hRet;
3900 /************************************************************************
3901 * VarCyMulI8 (OLEAUT32.329)
3903 * Multiply a VT_CY by a VT_I8.
3905 * PARAMS
3906 * cyLeft [I] Source
3907 * llRight [I] Value to multiply by
3908 * pCyOut [O] Destination
3910 * RETURNS
3911 * Success: S_OK.
3912 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3914 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
3916 double d;
3918 _VarR8FromCy(cyLeft, &d);
3919 d = d * (double)llRight;
3920 return _VarCyFromR8(d, pCyOut);
3923 /* DECIMAL
3926 /************************************************************************
3927 * VarDecFromUI1 (OLEAUT32.190)
3929 * Convert a VT_UI1 to a DECIMAL.
3931 * PARAMS
3932 * bIn [I] Source
3933 * pDecOut [O] Destination
3935 * RETURNS
3936 * S_OK.
3938 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
3940 return _VarDecFromUI1(bIn, pDecOut);
3943 /************************************************************************
3944 * VarDecFromI2 (OLEAUT32.191)
3946 * Convert a VT_I2 to a DECIMAL.
3948 * PARAMS
3949 * sIn [I] Source
3950 * pDecOut [O] Destination
3952 * RETURNS
3953 * S_OK.
3955 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
3957 return _VarDecFromI2(sIn, pDecOut);
3960 /************************************************************************
3961 * VarDecFromI4 (OLEAUT32.192)
3963 * Convert a VT_I4 to a DECIMAL.
3965 * PARAMS
3966 * sIn [I] Source
3967 * pDecOut [O] Destination
3969 * RETURNS
3970 * S_OK.
3972 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
3974 DEC_HI32(pDecOut) = 0;
3975 DEC_MID32(pDecOut) = 0;
3977 if (lIn < 0)
3979 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
3980 DEC_LO32(pDecOut) = -lIn;
3982 else
3984 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
3985 DEC_LO32(pDecOut) = lIn;
3987 return S_OK;
3990 /************************************************************************
3991 * VarDecFromR4 (OLEAUT32.193)
3993 * Convert a VT_R4 to a DECIMAL.
3995 * PARAMS
3996 * fltIn [I] Source
3997 * pDecOut [O] Destination
3999 * RETURNS
4000 * S_OK.
4002 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
4004 WCHAR buff[256];
4006 sprintfW( buff, szFloatFormatW, fltIn );
4007 return _VarDecFromStr(buff, LOCALE_SYSTEM_DEFAULT, 0, pDecOut);
4010 /************************************************************************
4011 * VarDecFromR8 (OLEAUT32.194)
4013 * Convert a VT_R8 to a DECIMAL.
4015 * PARAMS
4016 * dblIn [I] Source
4017 * pDecOut [O] Destination
4019 * RETURNS
4020 * S_OK.
4022 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4024 WCHAR buff[256];
4026 sprintfW( buff, szDoubleFormatW, dblIn );
4027 return _VarDecFromStr(buff, LOCALE_USER_DEFAULT, 0, pDecOut);
4030 /************************************************************************
4031 * VarDecFromDate (OLEAUT32.195)
4033 * Convert a VT_DATE to a DECIMAL.
4035 * PARAMS
4036 * dateIn [I] Source
4037 * pDecOut [O] Destination
4039 * RETURNS
4040 * S_OK.
4042 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
4044 return _VarDecFromDate(dateIn, pDecOut);
4047 /************************************************************************
4048 * VarDecFromCy (OLEAUT32.196)
4050 * Convert a VT_CY to a DECIMAL.
4052 * PARAMS
4053 * cyIn [I] Source
4054 * pDecOut [O] Destination
4056 * RETURNS
4057 * S_OK.
4059 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
4061 DEC_HI32(pDecOut) = 0;
4063 /* Note: This assumes 2s complement integer representation */
4064 if (cyIn.s.Hi & 0x80000000)
4066 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4067 DEC_LO64(pDecOut) = -cyIn.int64;
4069 else
4071 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4072 DEC_MID32(pDecOut) = cyIn.s.Hi;
4073 DEC_LO32(pDecOut) = cyIn.s.Lo;
4075 return S_OK;
4078 /************************************************************************
4079 * VarDecFromStr (OLEAUT32.197)
4081 * Convert a VT_BSTR to a DECIMAL.
4083 * PARAMS
4084 * strIn [I] Source
4085 * lcid [I] LCID for the conversion
4086 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4087 * pDecOut [O] Destination
4089 * RETURNS
4090 * Success: S_OK.
4091 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4093 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
4095 return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
4098 /************************************************************************
4099 * VarDecFromDisp (OLEAUT32.198)
4101 * Convert a VT_DISPATCH to a DECIMAL.
4103 * PARAMS
4104 * pdispIn [I] Source
4105 * lcid [I] LCID for conversion
4106 * pDecOut [O] Destination
4108 * RETURNS
4109 * Success: S_OK.
4110 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4112 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
4114 return _VarDecFromDisp(pdispIn, lcid, pDecOut);
4117 /************************************************************************
4118 * VarDecFromBool (OLEAUT32.199)
4120 * Convert a VT_BOOL to a DECIMAL.
4122 * PARAMS
4123 * bIn [I] Source
4124 * pDecOut [O] Destination
4126 * RETURNS
4127 * S_OK.
4129 * NOTES
4130 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4132 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
4134 DEC_HI32(pDecOut) = 0;
4135 DEC_MID32(pDecOut) = 0;
4136 if (bIn)
4138 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4139 DEC_LO32(pDecOut) = 1;
4141 else
4143 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4144 DEC_LO32(pDecOut) = 0;
4146 return S_OK;
4149 /************************************************************************
4150 * VarDecFromI1 (OLEAUT32.241)
4152 * Convert a VT_I1 to a DECIMAL.
4154 * PARAMS
4155 * cIn [I] Source
4156 * pDecOut [O] Destination
4158 * RETURNS
4159 * S_OK.
4161 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4163 return _VarDecFromI1(cIn, pDecOut);
4166 /************************************************************************
4167 * VarDecFromUI2 (OLEAUT32.242)
4169 * Convert a VT_UI2 to a DECIMAL.
4171 * PARAMS
4172 * usIn [I] Source
4173 * pDecOut [O] Destination
4175 * RETURNS
4176 * S_OK.
4178 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
4180 return _VarDecFromUI2(usIn, pDecOut);
4183 /************************************************************************
4184 * VarDecFromUI4 (OLEAUT32.243)
4186 * Convert a VT_UI4 to a DECIMAL.
4188 * PARAMS
4189 * ulIn [I] Source
4190 * pDecOut [O] Destination
4192 * RETURNS
4193 * S_OK.
4195 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
4197 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4198 DEC_HI32(pDecOut) = 0;
4199 DEC_MID32(pDecOut) = 0;
4200 DEC_LO32(pDecOut) = ulIn;
4201 return S_OK;
4204 /************************************************************************
4205 * VarDecFromI8 (OLEAUT32.374)
4207 * Convert a VT_I8 to a DECIMAL.
4209 * PARAMS
4210 * llIn [I] Source
4211 * pDecOut [O] Destination
4213 * RETURNS
4214 * S_OK.
4216 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
4218 PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4220 DEC_HI32(pDecOut) = 0;
4222 /* Note: This assumes 2s complement integer representation */
4223 if (pLi->u.HighPart & 0x80000000)
4225 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4226 DEC_LO64(pDecOut) = -pLi->QuadPart;
4228 else
4230 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4231 DEC_MID32(pDecOut) = pLi->u.HighPart;
4232 DEC_LO32(pDecOut) = pLi->u.LowPart;
4234 return S_OK;
4237 /************************************************************************
4238 * VarDecFromUI8 (OLEAUT32.375)
4240 * Convert a VT_UI8 to a DECIMAL.
4242 * PARAMS
4243 * ullIn [I] Source
4244 * pDecOut [O] Destination
4246 * RETURNS
4247 * S_OK.
4249 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
4251 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4252 DEC_HI32(pDecOut) = 0;
4253 DEC_LO64(pDecOut) = ullIn;
4254 return S_OK;
4257 /* Make two DECIMALS the same scale; used by math functions below */
4258 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4259 const DECIMAL** ppDecRight,
4260 DECIMAL* pDecOut)
4262 static DECIMAL scaleFactor;
4263 DECIMAL decTemp;
4264 int scaleAmount, i;
4265 HRESULT hRet = S_OK;
4267 if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4268 return E_INVALIDARG;
4270 DEC_LO32(&scaleFactor) = 10;
4272 i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4274 if (!scaleAmount)
4275 return S_OK; /* Same scale */
4277 if (scaleAmount > 0)
4279 decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4280 *ppDecRight = pDecOut;
4282 else
4284 decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4285 *ppDecLeft = pDecOut;
4286 i = scaleAmount = -scaleAmount;
4289 if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
4290 return DISP_E_OVERFLOW; /* Can't scale up */
4292 /* Multiply up the value to be scaled by the correct amount */
4293 while (SUCCEEDED(hRet) && i--)
4295 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4296 hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
4297 decTemp = *pDecOut;
4299 DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
4300 return hRet;
4303 /* Add two unsigned 32 bit values with overflow */
4304 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4306 ULARGE_INTEGER ul64;
4308 ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4309 *pulHigh = ul64.u.HighPart;
4310 return ul64.u.LowPart;
4313 /* Subtract two unsigned 32 bit values with underflow */
4314 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4316 int invert = 0;
4317 ULARGE_INTEGER ul64;
4319 ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4320 if (ulLeft < ulRight)
4321 invert = 1;
4323 if (ul64.QuadPart > (ULONG64)*pulHigh)
4324 ul64.QuadPart -= (ULONG64)*pulHigh;
4325 else
4327 ul64.QuadPart -= (ULONG64)*pulHigh;
4328 invert = 1;
4330 if (invert)
4331 ul64.u.HighPart = -ul64.u.HighPart ;
4333 *pulHigh = ul64.u.HighPart;
4334 return ul64.u.LowPart;
4337 /* Multiply two unsigned 32 bit values with overflow */
4338 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4340 ULARGE_INTEGER ul64;
4342 ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4343 *pulHigh = ul64.u.HighPart;
4344 return ul64.u.LowPart;
4347 /* Compare two decimals that have the same scale */
4348 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4350 if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4351 (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4352 return -1;
4353 else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4354 return 0;
4355 return 1;
4358 /************************************************************************
4359 * VarDecAdd (OLEAUT32.177)
4361 * Add one DECIMAL to another.
4363 * PARAMS
4364 * pDecLeft [I] Source
4365 * pDecRight [I] Value to add
4366 * pDecOut [O] Destination
4368 * RETURNS
4369 * Success: S_OK.
4370 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4372 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4374 HRESULT hRet;
4375 DECIMAL scaled;
4377 hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
4379 if (SUCCEEDED(hRet))
4381 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4382 ULONG overflow = 0;
4383 BYTE sign = DECIMAL_POS;
4385 /* Correct for the sign of the result */
4386 if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4388 /* -x + -y : Negative */
4389 sign = DECIMAL_NEG;
4390 goto VarDecAdd_AsPositive;
4392 else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4394 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4396 /* -x + y : Negative if x > y */
4397 if (cmp > 0)
4399 sign = DECIMAL_NEG;
4400 VarDecAdd_AsNegative:
4401 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4402 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4403 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4405 else
4407 VarDecAdd_AsInvertedNegative:
4408 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecRight), DEC_LO32(pDecLeft), &overflow);
4409 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4410 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecRight), DEC_HI32(pDecLeft), &overflow);
4413 else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4415 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4417 /* x + -y : Negative if x <= y */
4418 if (cmp <= 0)
4420 sign = DECIMAL_NEG;
4421 goto VarDecAdd_AsInvertedNegative;
4423 goto VarDecAdd_AsNegative;
4425 else
4427 /* x + y : Positive */
4428 VarDecAdd_AsPositive:
4429 DEC_LO32(pDecOut) = VARIANT_Add(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4430 DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4431 DEC_HI32(pDecOut) = VARIANT_Add(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4434 if (overflow)
4435 return DISP_E_OVERFLOW; /* overflowed */
4437 DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4438 DEC_SIGN(pDecOut) = sign;
4440 return hRet;
4443 /************************************************************************
4444 * VarDecDiv (OLEAUT32.178)
4446 * Divide one DECIMAL by another.
4448 * PARAMS
4449 * pDecLeft [I] Source
4450 * pDecRight [I] Value to divide by
4451 * pDecOut [O] Destination
4453 * RETURNS
4454 * Success: S_OK.
4455 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4457 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4459 FIXME("(%p,%p,%p)-stub!\n",pDecLeft,pDecRight,pDecOut);
4460 return DISP_E_OVERFLOW;
4463 /************************************************************************
4464 * VarDecMul (OLEAUT32.179)
4466 * Multiply one DECIMAL by another.
4468 * PARAMS
4469 * pDecLeft [I] Source
4470 * pDecRight [I] Value to multiply by
4471 * pDecOut [O] Destination
4473 * RETURNS
4474 * Success: S_OK.
4475 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4477 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4479 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4481 if (!DEC_SCALE(pDecLeft) || !DEC_SCALE(pDecRight))
4483 /* At least one term is an integer */
4484 const DECIMAL* pDecInteger = DEC_SCALE(pDecLeft) ? pDecRight : pDecLeft;
4485 const DECIMAL* pDecOperand = DEC_SCALE(pDecLeft) ? pDecLeft : pDecRight;
4486 HRESULT hRet = S_OK;
4487 unsigned int multiplier = DEC_LO32(pDecInteger);
4488 ULONG overflow = 0;
4490 if (DEC_HI32(pDecInteger) || DEC_MID32(pDecInteger))
4492 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4493 return DISP_E_OVERFLOW;
4496 DEC_LO32(pDecOut) = VARIANT_Mul(DEC_LO32(pDecOperand), multiplier, &overflow);
4497 DEC_MID32(pDecOut) = VARIANT_Mul(DEC_MID32(pDecOperand), multiplier, &overflow);
4498 DEC_HI32(pDecOut) = VARIANT_Mul(DEC_HI32(pDecOperand), multiplier, &overflow);
4500 if (overflow)
4501 hRet = DISP_E_OVERFLOW;
4502 else
4504 BYTE sign = DECIMAL_POS;
4506 if (DEC_SIGN(pDecLeft) != DEC_SIGN(pDecRight))
4507 sign = DECIMAL_NEG; /* pos * neg => negative */
4508 DEC_SIGN(pDecOut) = sign;
4509 DEC_SCALE(pDecOut) = DEC_SCALE(pDecOperand);
4511 return hRet;
4513 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4514 return DISP_E_OVERFLOW;
4517 /************************************************************************
4518 * VarDecSub (OLEAUT32.181)
4520 * Subtract one DECIMAL from another.
4522 * PARAMS
4523 * pDecLeft [I] Source
4524 * pDecRight [I] DECIMAL to subtract from pDecLeft
4525 * pDecOut [O] Destination
4527 * RETURNS
4528 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4530 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4532 DECIMAL decRight;
4534 /* Implement as addition of the negative */
4535 VarDecNeg(pDecRight, &decRight);
4536 return VarDecAdd(pDecLeft, &decRight, pDecOut);
4539 /************************************************************************
4540 * VarDecAbs (OLEAUT32.182)
4542 * Convert a DECIMAL into its absolute value.
4544 * PARAMS
4545 * pDecIn [I] Source
4546 * pDecOut [O] Destination
4548 * RETURNS
4549 * S_OK. This function does not fail.
4551 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4553 *pDecOut = *pDecIn;
4554 DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
4555 return S_OK;
4558 /************************************************************************
4559 * VarDecFix (OLEAUT32.187)
4561 * Return the integer portion of a DECIMAL.
4563 * PARAMS
4564 * pDecIn [I] Source
4565 * pDecOut [O] Destination
4567 * RETURNS
4568 * Success: S_OK.
4569 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4571 * NOTES
4572 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4573 * negative numbers away from 0, while this function rounds them towards zero.
4575 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4577 if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
4578 return E_INVALIDARG;
4580 if (!DEC_SCALE(pDecIn))
4582 *pDecOut = *pDecIn; /* Already an integer */
4583 return S_OK;
4586 FIXME("semi-stub!\n");
4587 return DISP_E_OVERFLOW;
4590 /************************************************************************
4591 * VarDecInt (OLEAUT32.188)
4593 * Return the integer portion of a DECIMAL.
4595 * PARAMS
4596 * pDecIn [I] Source
4597 * pDecOut [O] Destination
4599 * RETURNS
4600 * Success: S_OK.
4601 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4603 * NOTES
4604 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4605 * negative numbers towards 0, while this function rounds them away from zero.
4607 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4609 if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
4610 return E_INVALIDARG;
4612 if (!(DEC_SIGN(pDecOut) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
4613 return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
4615 FIXME("semi-stub!\n");
4616 return DISP_E_OVERFLOW;
4619 /************************************************************************
4620 * VarDecNeg (OLEAUT32.189)
4622 * Change the sign of a DECIMAL.
4624 * PARAMS
4625 * pDecIn [I] Source
4626 * pDecOut [O] Destination
4628 * RETURNS
4629 * S_OK. This function does not fail.
4631 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4633 *pDecOut = *pDecIn;
4634 DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
4635 return S_OK;
4638 /************************************************************************
4639 * VarDecRound (OLEAUT32.203)
4641 * Change the precision of a DECIMAL.
4643 * PARAMS
4644 * pDecIn [I] Source
4645 * cDecimals [I] New number of decimals to keep
4646 * pDecOut [O] Destination
4648 * RETURNS
4649 * Success: S_OK. pDecOut contains the rounded value.
4650 * Failure: E_INVALIDARG if any argument is invalid.
4652 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
4654 if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
4655 return E_INVALIDARG;
4657 if (cDecimals >= DEC_SCALE(pDecIn))
4659 *pDecOut = *pDecIn; /* More precision than we have */
4660 return S_OK;
4663 FIXME("semi-stub!\n");
4665 return DISP_E_OVERFLOW;
4668 /************************************************************************
4669 * VarDecCmp (OLEAUT32.204)
4671 * Compare two DECIMAL values.
4673 * PARAMS
4674 * pDecLeft [I] Source
4675 * pDecRight [I] Value to compare
4677 * RETURNS
4678 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4679 * is less than, equal to or greater than pDecRight respectively.
4680 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4682 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
4684 HRESULT hRet;
4685 DECIMAL result;
4687 /* Subtract right from left, and compare the result to 0 */
4688 hRet = VarDecSub(pDecLeft, pDecRight, &result);
4690 if (SUCCEEDED(hRet))
4692 int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
4694 if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
4695 hRet = (HRESULT)VARCMP_LT;
4696 else if (non_zero)
4697 hRet = (HRESULT)VARCMP_GT;
4698 else
4699 hRet = (HRESULT)VARCMP_EQ;
4701 return hRet;
4704 /************************************************************************
4705 * VarDecCmpR8 (OLEAUT32.298)
4707 * Compare a DECIMAL to a double
4709 * PARAMS
4710 * pDecLeft [I] DECIMAL Source
4711 * dblRight [I] double to compare to pDecLeft
4713 * RETURNS
4714 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4715 * is less than, equal to or greater than pDecLeft respectively.
4716 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4718 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
4720 HRESULT hRet;
4721 DECIMAL decRight;
4723 hRet = VarDecFromR8(dblRight, &decRight);
4725 if (SUCCEEDED(hRet))
4726 hRet = VarDecCmp(pDecLeft, &decRight);
4728 return hRet;
4731 /* BOOL
4734 /************************************************************************
4735 * VarBoolFromUI1 (OLEAUT32.118)
4737 * Convert a VT_UI1 to a VT_BOOL.
4739 * PARAMS
4740 * bIn [I] Source
4741 * pBoolOut [O] Destination
4743 * RETURNS
4744 * S_OK.
4746 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
4748 return _VarBoolFromUI1(bIn, pBoolOut);
4751 /************************************************************************
4752 * VarBoolFromI2 (OLEAUT32.119)
4754 * Convert a VT_I2 to a VT_BOOL.
4756 * PARAMS
4757 * sIn [I] Source
4758 * pBoolOut [O] Destination
4760 * RETURNS
4761 * S_OK.
4763 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
4765 return _VarBoolFromI2(sIn, pBoolOut);
4768 /************************************************************************
4769 * VarBoolFromI4 (OLEAUT32.120)
4771 * Convert a VT_I4 to a VT_BOOL.
4773 * PARAMS
4774 * sIn [I] Source
4775 * pBoolOut [O] Destination
4777 * RETURNS
4778 * S_OK.
4780 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
4782 return _VarBoolFromI4(lIn, pBoolOut);
4785 /************************************************************************
4786 * VarBoolFromR4 (OLEAUT32.121)
4788 * Convert a VT_R4 to a VT_BOOL.
4790 * PARAMS
4791 * fltIn [I] Source
4792 * pBoolOut [O] Destination
4794 * RETURNS
4795 * S_OK.
4797 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
4799 return _VarBoolFromR4(fltIn, pBoolOut);
4802 /************************************************************************
4803 * VarBoolFromR8 (OLEAUT32.122)
4805 * Convert a VT_R8 to a VT_BOOL.
4807 * PARAMS
4808 * dblIn [I] Source
4809 * pBoolOut [O] Destination
4811 * RETURNS
4812 * S_OK.
4814 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
4816 return _VarBoolFromR8(dblIn, pBoolOut);
4819 /************************************************************************
4820 * VarBoolFromDate (OLEAUT32.123)
4822 * Convert a VT_DATE to a VT_BOOL.
4824 * PARAMS
4825 * dateIn [I] Source
4826 * pBoolOut [O] Destination
4828 * RETURNS
4829 * S_OK.
4831 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
4833 return _VarBoolFromDate(dateIn, pBoolOut);
4836 /************************************************************************
4837 * VarBoolFromCy (OLEAUT32.124)
4839 * Convert a VT_CY to a VT_BOOL.
4841 * PARAMS
4842 * cyIn [I] Source
4843 * pBoolOut [O] Destination
4845 * RETURNS
4846 * S_OK.
4848 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
4850 return _VarBoolFromCy(cyIn, pBoolOut);
4853 static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
4855 HRSRC hrsrc;
4857 hrsrc = FindResourceExW( OLEAUT32_hModule, (LPWSTR)RT_STRING,
4858 (LPCWSTR)((dwId >> 4) + 1), langId );
4859 if (hrsrc)
4861 HGLOBAL hmem = LoadResource( OLEAUT32_hModule, hrsrc );
4863 if (hmem)
4865 const WCHAR *p;
4866 unsigned int i;
4868 p = LockResource( hmem );
4869 for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
4871 memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
4872 lpszDest[*p] = '\0';
4873 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
4874 return TRUE;
4877 return FALSE;
4880 /************************************************************************
4881 * VarBoolFromStr (OLEAUT32.125)
4883 * Convert a VT_BSTR to a VT_BOOL.
4885 * PARAMS
4886 * strIn [I] Source
4887 * lcid [I] LCID for the conversion
4888 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4889 * pBoolOut [O] Destination
4891 * RETURNS
4892 * Success: S_OK.
4893 * Failure: E_INVALIDARG, if pBoolOut is invalid.
4894 * DISP_E_TYPEMISMATCH, if the type cannot be converted
4896 * NOTES
4897 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
4898 * it may contain (in any case mapping) the text "true" or "false".
4899 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
4900 * localised text of "True" or "False" in the language specified by lcid.
4901 * - If none of these matches occur, the string is treated as a numeric string
4902 * and the boolean pBoolOut will be set according to whether the number is zero
4903 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
4904 * - If the text is not numeric and does not match any of the above, then
4905 * DISP_E_TYPEMISMATCH is returned.
4907 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
4909 /* Any VB/VBA programmers out there should recognise these strings... */
4910 static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
4911 static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
4912 WCHAR szBuff[64];
4913 LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4914 HRESULT hRes = S_OK;
4916 if (!strIn || !pBoolOut)
4917 return DISP_E_TYPEMISMATCH;
4919 /* Check if we should be comparing against localised text */
4920 if (dwFlags & VAR_LOCALBOOL)
4922 /* Convert our LCID into a usable value */
4923 lcid = ConvertDefaultLocale(lcid);
4925 langId = LANGIDFROMLCID(lcid);
4927 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
4928 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4930 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
4931 * I don't think this is needed unless any of the localised text strings
4932 * contain characters that can be so mapped. In the event that this is
4933 * true for a given language (possibly some Asian languages), then strIn
4934 * should be mapped here _only_ if langId is an Id for which this can occur.
4938 /* Note that if we are not comparing against localised strings, langId
4939 * will have its default value of LANG_ENGLISH. This allows us to mimic
4940 * the native behaviour of always checking against English strings even
4941 * after we've checked for localised ones.
4943 VarBoolFromStr_CheckLocalised:
4944 if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
4946 /* Compare against localised strings, ignoring case */
4947 if (!strcmpiW(strIn, szBuff))
4949 *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
4950 return hRes;
4952 VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
4953 if (!strcmpiW(strIn, szBuff))
4955 *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
4956 return hRes;
4960 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
4962 /* We have checked the localised text, now check English */
4963 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4964 goto VarBoolFromStr_CheckLocalised;
4967 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
4968 if (!strcmpW(strIn, szFalse))
4969 *pBoolOut = VARIANT_FALSE;
4970 else if (!strcmpW(strIn, szTrue))
4971 *pBoolOut = VARIANT_TRUE;
4972 else
4974 double d;
4976 /* If this string is a number, convert it as one */
4977 hRes = _VarR8FromStr(strIn, lcid, dwFlags, &d);
4978 if (SUCCEEDED(hRes))
4979 hRes = _VarBoolFromR8(d, pBoolOut);
4981 return hRes;
4984 /************************************************************************
4985 * VarBoolFromDisp (OLEAUT32.126)
4987 * Convert a VT_DISPATCH to a VT_BOOL.
4989 * PARAMS
4990 * pdispIn [I] Source
4991 * lcid [I] LCID for conversion
4992 * pBoolOut [O] Destination
4994 * RETURNS
4995 * Success: S_OK.
4996 * Failure: E_INVALIDARG, if the source value is invalid
4997 * DISP_E_OVERFLOW, if the value will not fit in the destination
4998 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5000 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
5002 return _VarBoolFromDisp(pdispIn, lcid, pBoolOut);
5005 /************************************************************************
5006 * VarBoolFromI1 (OLEAUT32.233)
5008 * Convert a VT_I1 to a VT_BOOL.
5010 * PARAMS
5011 * cIn [I] Source
5012 * pBoolOut [O] Destination
5014 * RETURNS
5015 * S_OK.
5017 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
5019 return _VarBoolFromI1(cIn, pBoolOut);
5022 /************************************************************************
5023 * VarBoolFromUI2 (OLEAUT32.234)
5025 * Convert a VT_UI2 to a VT_BOOL.
5027 * PARAMS
5028 * usIn [I] Source
5029 * pBoolOut [O] Destination
5031 * RETURNS
5032 * S_OK.
5034 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
5036 return _VarBoolFromUI2(usIn, pBoolOut);
5039 /************************************************************************
5040 * VarBoolFromUI4 (OLEAUT32.235)
5042 * Convert a VT_UI4 to a VT_BOOL.
5044 * PARAMS
5045 * ulIn [I] Source
5046 * pBoolOut [O] Destination
5048 * RETURNS
5049 * S_OK.
5051 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
5053 return _VarBoolFromUI4(ulIn, pBoolOut);
5056 /************************************************************************
5057 * VarBoolFromDec (OLEAUT32.236)
5059 * Convert a VT_DECIMAL to a VT_BOOL.
5061 * PARAMS
5062 * pDecIn [I] Source
5063 * pBoolOut [O] Destination
5065 * RETURNS
5066 * Success: S_OK.
5067 * Failure: E_INVALIDARG, if pDecIn is invalid.
5069 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
5071 if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
5072 return E_INVALIDARG;
5074 if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
5075 *pBoolOut = VARIANT_TRUE;
5076 else
5077 *pBoolOut = VARIANT_FALSE;
5078 return S_OK;
5081 /************************************************************************
5082 * VarBoolFromI8 (OLEAUT32.370)
5084 * Convert a VT_I8 to a VT_BOOL.
5086 * PARAMS
5087 * ullIn [I] Source
5088 * pBoolOut [O] Destination
5090 * RETURNS
5091 * S_OK.
5093 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
5095 return _VarBoolFromI8(llIn, pBoolOut);
5098 /************************************************************************
5099 * VarBoolFromUI8 (OLEAUT32.371)
5101 * Convert a VT_UI8 to a VT_BOOL.
5103 * PARAMS
5104 * ullIn [I] Source
5105 * pBoolOut [O] Destination
5107 * RETURNS
5108 * S_OK.
5110 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
5112 return _VarBoolFromUI8(ullIn, pBoolOut);
5115 /* BSTR
5118 /* Write a number from a UI8 and sign */
5119 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
5123 WCHAR ulNextDigit = ulVal % 10;
5125 *szOut-- = '0' + ulNextDigit;
5126 ulVal = (ulVal - ulNextDigit) / 10;
5127 } while (ulVal);
5129 szOut++;
5130 return szOut;
5133 /* Create a (possibly localised) BSTR from a UI8 and sign */
5134 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
5136 WCHAR szConverted[256];
5138 if (dwFlags & VAR_NEGATIVE)
5139 *--szOut = '-';
5141 if (dwFlags & LOCALE_USE_NLS)
5143 /* Format the number for the locale */
5144 szConverted[0] = '\0';
5145 GetNumberFormatW(lcid,
5146 dwFlags & LOCALE_NOUSEROVERRIDE,
5147 szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
5148 szOut = szConverted;
5150 return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
5153 /* Create a (possibly localised) BSTR from a UI8 and sign */
5154 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
5156 WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5158 if (!pbstrOut)
5159 return E_INVALIDARG;
5161 /* Create the basic number string */
5162 *szOut-- = '\0';
5163 szOut = VARIANT_WriteNumber(ulVal, szOut);
5165 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5166 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5167 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5170 /******************************************************************************
5171 * VarBstrFromUI1 (OLEAUT32.108)
5173 * Convert a VT_UI1 to a VT_BSTR.
5175 * PARAMS
5176 * bIn [I] Source
5177 * lcid [I] LCID for the conversion
5178 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5179 * pbstrOut [O] Destination
5181 * RETURNS
5182 * Success: S_OK.
5183 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5184 * E_OUTOFMEMORY, if memory allocation fails.
5186 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5188 return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
5191 /******************************************************************************
5192 * VarBstrFromI2 (OLEAUT32.109)
5194 * Convert a VT_I2 to a VT_BSTR.
5196 * PARAMS
5197 * sIn [I] Source
5198 * lcid [I] LCID for the conversion
5199 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5200 * pbstrOut [O] Destination
5202 * RETURNS
5203 * Success: S_OK.
5204 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5205 * E_OUTOFMEMORY, if memory allocation fails.
5207 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5209 ULONG64 ul64 = sIn;
5211 if (sIn < 0)
5213 ul64 = -sIn;
5214 dwFlags |= VAR_NEGATIVE;
5216 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5219 /******************************************************************************
5220 * VarBstrFromI4 (OLEAUT32.110)
5222 * Convert a VT_I4 to a VT_BSTR.
5224 * PARAMS
5225 * lIn [I] Source
5226 * lcid [I] LCID for the conversion
5227 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5228 * pbstrOut [O] Destination
5230 * RETURNS
5231 * Success: S_OK.
5232 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5233 * E_OUTOFMEMORY, if memory allocation fails.
5235 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5237 ULONG64 ul64 = lIn;
5239 if (lIn < 0)
5241 ul64 = (ULONG)-lIn;
5242 dwFlags |= VAR_NEGATIVE;
5244 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5247 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
5248 BSTR* pbstrOut, LPCWSTR lpszFormat)
5250 WCHAR buff[256];
5252 if (!pbstrOut)
5253 return E_INVALIDARG;
5255 sprintfW( buff, lpszFormat, dblIn );
5256 TRACE("created string %s\n", debugstr_w(buff));
5257 if (dwFlags & LOCALE_USE_NLS)
5259 WCHAR numbuff[256];
5261 /* Format the number for the locale */
5262 numbuff[0] = '\0';
5263 GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5264 buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
5265 TRACE("created NLS string %s\n", debugstr_w(numbuff));
5266 *pbstrOut = SysAllocString(numbuff);
5268 else
5269 *pbstrOut = SysAllocString(buff);
5270 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5273 /******************************************************************************
5274 * VarBstrFromR4 (OLEAUT32.111)
5276 * Convert a VT_R4 to a VT_BSTR.
5278 * PARAMS
5279 * fltIn [I] Source
5280 * lcid [I] LCID for the conversion
5281 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5282 * pbstrOut [O] Destination
5284 * RETURNS
5285 * Success: S_OK.
5286 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5287 * E_OUTOFMEMORY, if memory allocation fails.
5289 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5291 return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
5294 /******************************************************************************
5295 * VarBstrFromR8 (OLEAUT32.112)
5297 * Convert a VT_R8 to a VT_BSTR.
5299 * PARAMS
5300 * dblIn [I] Source
5301 * lcid [I] LCID for the conversion
5302 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5303 * pbstrOut [O] Destination
5305 * RETURNS
5306 * Success: S_OK.
5307 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5308 * E_OUTOFMEMORY, if memory allocation fails.
5310 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5312 return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
5315 /******************************************************************************
5316 * VarBstrFromCy [OLEAUT32.113]
5318 * Convert a VT_CY to a VT_BSTR.
5320 * PARAMS
5321 * cyIn [I] Source
5322 * lcid [I] LCID for the conversion
5323 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5324 * pbstrOut [O] Destination
5326 * RETURNS
5327 * Success: S_OK.
5328 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5329 * E_OUTOFMEMORY, if memory allocation fails.
5331 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
5333 WCHAR buff[256];
5334 double dblVal;
5336 if (!pbstrOut)
5337 return E_INVALIDARG;
5339 VarR8FromCy(cyIn, &dblVal);
5340 sprintfW(buff, szDoubleFormatW, dblVal);
5342 if (dwFlags & LOCALE_USE_NLS)
5344 WCHAR cybuff[256];
5346 /* Format the currency for the locale */
5347 cybuff[0] = '\0';
5348 GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5349 buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
5350 *pbstrOut = SysAllocString(cybuff);
5352 else
5353 *pbstrOut = SysAllocString(buff);
5355 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5358 /******************************************************************************
5359 * VarBstrFromDate [OLEAUT32.114]
5361 * Convert a VT_DATE to a VT_BSTR.
5363 * PARAMS
5364 * dateIn [I] Source
5365 * lcid [I] LCID for the conversion
5366 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5367 * pbstrOut [O] Destination
5369 * RETURNS
5370 * Success: S_OK.
5371 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5372 * E_OUTOFMEMORY, if memory allocation fails.
5374 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5376 SYSTEMTIME st;
5377 DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
5378 WCHAR date[128], *time;
5380 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
5382 if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
5383 return E_INVALIDARG;
5385 *pbstrOut = NULL;
5387 if (dwFlags & VAR_CALENDAR_THAI)
5388 st.wYear += 553; /* Use the Thai buddhist calendar year */
5389 else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
5390 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5392 if (dwFlags & LOCALE_USE_NLS)
5393 dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
5394 else
5396 double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
5397 double partial = dateIn - whole;
5399 if (whole == 0.0)
5400 dwFlags |= VAR_TIMEVALUEONLY;
5401 else if (partial < 1e-12)
5402 dwFlags |= VAR_DATEVALUEONLY;
5405 if (dwFlags & VAR_TIMEVALUEONLY)
5406 date[0] = '\0';
5407 else
5408 if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
5409 sizeof(date)/sizeof(WCHAR)))
5410 return E_INVALIDARG;
5412 if (!(dwFlags & VAR_DATEVALUEONLY))
5414 time = date + strlenW(date);
5415 if (time != date)
5416 *time++ = ' ';
5417 if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
5418 sizeof(date)/sizeof(WCHAR)-(time-date)))
5419 return E_INVALIDARG;
5422 *pbstrOut = SysAllocString(date);
5423 if (*pbstrOut)
5424 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5425 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5428 /******************************************************************************
5429 * VarBstrFromBool (OLEAUT32.116)
5431 * Convert a VT_BOOL to a VT_BSTR.
5433 * PARAMS
5434 * boolIn [I] Source
5435 * lcid [I] LCID for the conversion
5436 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5437 * pbstrOut [O] Destination
5439 * RETURNS
5440 * Success: S_OK.
5441 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5442 * E_OUTOFMEMORY, if memory allocation fails.
5444 * NOTES
5445 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5446 * localised text of "True" or "False". To convert a bool into a
5447 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5449 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5451 WCHAR szBuff[64];
5452 DWORD dwResId = IDS_TRUE;
5453 LANGID langId;
5455 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn, lcid, dwFlags, pbstrOut);
5457 if (!pbstrOut)
5458 return E_INVALIDARG;
5460 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5461 * for variant formatting */
5462 switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
5464 case VAR_BOOLONOFF:
5465 dwResId = IDS_ON;
5466 break;
5467 case VAR_BOOLYESNO:
5468 dwResId = IDS_YES;
5469 break;
5470 case VAR_LOCALBOOL:
5471 break;
5472 default:
5473 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
5476 lcid = ConvertDefaultLocale(lcid);
5477 langId = LANGIDFROMLCID(lcid);
5478 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
5479 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5481 if (boolIn == VARIANT_FALSE)
5482 dwResId++; /* Use negative form */
5484 VarBstrFromBool_GetLocalised:
5485 if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
5487 *pbstrOut = SysAllocString(szBuff);
5488 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5491 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5493 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5494 goto VarBstrFromBool_GetLocalised;
5497 /* Should never get here */
5498 WARN("Failed to load bool text!\n");
5499 return E_OUTOFMEMORY;
5502 /******************************************************************************
5503 * VarBstrFromI1 (OLEAUT32.229)
5505 * Convert a VT_I1 to a VT_BSTR.
5507 * PARAMS
5508 * cIn [I] Source
5509 * lcid [I] LCID for the conversion
5510 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5511 * pbstrOut [O] Destination
5513 * RETURNS
5514 * Success: S_OK.
5515 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5516 * E_OUTOFMEMORY, if memory allocation fails.
5518 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5520 ULONG64 ul64 = cIn;
5522 if (cIn < 0)
5524 ul64 = -cIn;
5525 dwFlags |= VAR_NEGATIVE;
5527 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5530 /******************************************************************************
5531 * VarBstrFromUI2 (OLEAUT32.230)
5533 * Convert a VT_UI2 to a VT_BSTR.
5535 * PARAMS
5536 * usIn [I] Source
5537 * lcid [I] LCID for the conversion
5538 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5539 * pbstrOut [O] Destination
5541 * RETURNS
5542 * Success: S_OK.
5543 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5544 * E_OUTOFMEMORY, if memory allocation fails.
5546 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5548 return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
5551 /******************************************************************************
5552 * VarBstrFromUI4 (OLEAUT32.231)
5554 * Convert a VT_UI4 to a VT_BSTR.
5556 * PARAMS
5557 * ulIn [I] Source
5558 * lcid [I] LCID for the conversion
5559 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5560 * pbstrOut [O] Destination
5562 * RETURNS
5563 * Success: S_OK.
5564 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5565 * E_OUTOFMEMORY, if memory allocation fails.
5567 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5569 return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
5572 /******************************************************************************
5573 * VarBstrFromDec (OLEAUT32.232)
5575 * Convert a VT_DECIMAL to a VT_BSTR.
5577 * PARAMS
5578 * pDecIn [I] Source
5579 * lcid [I] LCID for the conversion
5580 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5581 * pbstrOut [O] Destination
5583 * RETURNS
5584 * Success: S_OK.
5585 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5586 * E_OUTOFMEMORY, if memory allocation fails.
5588 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5590 if (!pbstrOut)
5591 return E_INVALIDARG;
5593 if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
5595 WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5597 /* Create the basic number string */
5598 *szOut-- = '\0';
5599 szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
5600 if (DEC_SIGN(pDecIn))
5601 dwFlags |= VAR_NEGATIVE;
5603 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5604 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5605 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5607 FIXME("semi-stub\n");
5608 return E_INVALIDARG;
5611 /************************************************************************
5612 * VarBstrFromI8 (OLEAUT32.370)
5614 * Convert a VT_I8 to a VT_BSTR.
5616 * PARAMS
5617 * llIn [I] Source
5618 * lcid [I] LCID for the conversion
5619 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5620 * pbstrOut [O] Destination
5622 * RETURNS
5623 * Success: S_OK.
5624 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5625 * E_OUTOFMEMORY, if memory allocation fails.
5627 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5629 ULONG64 ul64 = llIn;
5631 if (llIn < 0)
5633 ul64 = -llIn;
5634 dwFlags |= VAR_NEGATIVE;
5636 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5639 /************************************************************************
5640 * VarBstrFromUI8 (OLEAUT32.371)
5642 * Convert a VT_UI8 to a VT_BSTR.
5644 * PARAMS
5645 * ullIn [I] Source
5646 * lcid [I] LCID for the conversion
5647 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5648 * pbstrOut [O] Destination
5650 * RETURNS
5651 * Success: S_OK.
5652 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5653 * E_OUTOFMEMORY, if memory allocation fails.
5655 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5657 return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
5660 /**********************************************************************
5661 * VarBstrCat (OLEAUT32.313)
5663 * Concatenate two BSTR values.
5665 * PARAMS
5666 * pbstrLeft [I] Source
5667 * pbstrRight [I] Value to concatenate
5668 * pbstrOut [O] Destination
5670 * RETURNS
5671 * Success: S_OK.
5672 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5673 * E_OUTOFMEMORY, if memory allocation fails.
5675 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
5677 unsigned int len;
5679 if (!pbstrOut)
5680 return E_INVALIDARG;
5682 len = pbstrLeft ? strlenW(pbstrLeft) : 0;
5683 if (pbstrRight)
5684 len += strlenW(pbstrRight);
5686 *pbstrOut = SysAllocStringLen(NULL, len);
5687 if (!*pbstrOut)
5688 return E_OUTOFMEMORY;
5690 (*pbstrOut)[0] = '\0';
5692 if (pbstrLeft)
5693 strcpyW(*pbstrOut, pbstrLeft);
5695 if (pbstrRight)
5696 strcatW(*pbstrOut, pbstrRight);
5698 return S_OK;
5701 /**********************************************************************
5702 * VarBstrCmp (OLEAUT32.314)
5704 * Compare two BSTR values.
5706 * PARAMS
5707 * pbstrLeft [I] Source
5708 * pbstrRight [I] Value to compare
5709 * lcid [I] LCID for the comparison
5710 * dwFlags [I] Flags to pass directly to CompareStringW().
5712 * RETURNS
5713 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5714 * than, equal to or greater than pbstrRight respectively.
5715 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5716 * in which case VARCMP_EQ is returned.
5718 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
5720 if (!pbstrLeft)
5722 if (!pbstrRight || !*pbstrRight)
5723 return VARCMP_EQ;
5724 return VARCMP_NULL;
5726 else if (!pbstrRight)
5728 if (!*pbstrLeft)
5729 return VARCMP_EQ;
5730 return VARCMP_NULL;
5733 return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
5737 * DATE
5740 /******************************************************************************
5741 * VarDateFromUI1 (OLEAUT32.88)
5743 * Convert a VT_UI1 to a VT_DATE.
5745 * PARAMS
5746 * bIn [I] Source
5747 * pdateOut [O] Destination
5749 * RETURNS
5750 * S_OK.
5752 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
5754 return _VarDateFromUI1(bIn, pdateOut);
5757 /******************************************************************************
5758 * VarDateFromI2 (OLEAUT32.89)
5760 * Convert a VT_I2 to a VT_DATE.
5762 * PARAMS
5763 * sIn [I] Source
5764 * pdateOut [O] Destination
5766 * RETURNS
5767 * S_OK.
5769 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
5771 return _VarDateFromI2(sIn, pdateOut);
5774 /******************************************************************************
5775 * VarDateFromI4 (OLEAUT32.90)
5777 * Convert a VT_I4 to a VT_DATE.
5779 * PARAMS
5780 * lIn [I] Source
5781 * pdateOut [O] Destination
5783 * RETURNS
5784 * S_OK.
5786 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
5788 return _VarDateFromI4(lIn, pdateOut);
5791 /******************************************************************************
5792 * VarDateFromR4 (OLEAUT32.91)
5794 * Convert a VT_R4 to a VT_DATE.
5796 * PARAMS
5797 * fltIn [I] Source
5798 * pdateOut [O] Destination
5800 * RETURNS
5801 * S_OK.
5803 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
5805 return _VarDateFromR4(fltIn, pdateOut);
5808 /******************************************************************************
5809 * VarDateFromR8 (OLEAUT32.92)
5811 * Convert a VT_R8 to a VT_DATE.
5813 * PARAMS
5814 * dblIn [I] Source
5815 * pdateOut [O] Destination
5817 * RETURNS
5818 * S_OK.
5820 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
5822 return _VarDateFromR8(dblIn, pdateOut);
5825 /**********************************************************************
5826 * VarDateFromDisp (OLEAUT32.95)
5828 * Convert a VT_DISPATCH to a VT_DATE.
5830 * PARAMS
5831 * pdispIn [I] Source
5832 * lcid [I] LCID for conversion
5833 * pdateOut [O] Destination
5835 * RETURNS
5836 * Success: S_OK.
5837 * Failure: E_INVALIDARG, if the source value is invalid
5838 * DISP_E_OVERFLOW, if the value will not fit in the destination
5839 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5841 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
5843 return _VarDateFromDisp(pdispIn, lcid, pdateOut);
5846 /******************************************************************************
5847 * VarDateFromBool (OLEAUT32.96)
5849 * Convert a VT_BOOL to a VT_DATE.
5851 * PARAMS
5852 * boolIn [I] Source
5853 * pdateOut [O] Destination
5855 * RETURNS
5856 * S_OK.
5858 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
5860 return _VarDateFromBool(boolIn, pdateOut);
5863 /**********************************************************************
5864 * VarDateFromCy (OLEAUT32.93)
5866 * Convert a VT_CY to a VT_DATE.
5868 * PARAMS
5869 * lIn [I] Source
5870 * pdateOut [O] Destination
5872 * RETURNS
5873 * S_OK.
5875 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
5877 return _VarDateFromCy(cyIn, pdateOut);
5880 /* Date string parsing */
5881 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
5882 #define DP_DATESEP 0x02 /* Date separator */
5883 #define DP_MONTH 0x04 /* Month name */
5884 #define DP_AM 0x08 /* AM */
5885 #define DP_PM 0x10 /* PM */
5887 typedef struct tagDATEPARSE
5889 DWORD dwCount; /* Number of fields found so far (maximum 6) */
5890 DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
5891 DWORD dwFlags[6]; /* Flags for each field */
5892 DWORD dwValues[6]; /* Value of each field */
5893 } DATEPARSE;
5895 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
5897 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5899 /* Determine if a day is valid in a given month of a given year */
5900 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
5902 static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
5904 if (day && month && month < 13)
5906 if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
5907 return TRUE;
5909 return FALSE;
5912 /* Possible orders for 3 numbers making up a date */
5913 #define ORDER_MDY 0x01
5914 #define ORDER_YMD 0x02
5915 #define ORDER_YDM 0x04
5916 #define ORDER_DMY 0x08
5917 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
5919 /* Determine a date for a particular locale, from 3 numbers */
5920 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
5921 DWORD offset, SYSTEMTIME *st)
5923 DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
5925 if (!dp->dwCount)
5927 v1 = 30; /* Default to (Variant) 0 date part */
5928 v2 = 12;
5929 v3 = 1899;
5930 goto VARIANT_MakeDate_OK;
5933 v1 = dp->dwValues[offset + 0];
5934 v2 = dp->dwValues[offset + 1];
5935 if (dp->dwCount == 2)
5937 SYSTEMTIME current;
5938 GetSystemTime(&current);
5939 v3 = current.wYear;
5941 else
5942 v3 = dp->dwValues[offset + 2];
5944 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
5946 /* If one number must be a month (Because a month name was given), then only
5947 * consider orders with the month in that position.
5948 * If we took the current year as 'v3', then only allow a year in that position.
5950 if (dp->dwFlags[offset + 0] & DP_MONTH)
5952 dwAllOrders = ORDER_MDY;
5954 else if (dp->dwFlags[offset + 1] & DP_MONTH)
5956 dwAllOrders = ORDER_DMY;
5957 if (dp->dwCount > 2)
5958 dwAllOrders |= ORDER_YMD;
5960 else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
5962 dwAllOrders = ORDER_YDM;
5964 else
5966 dwAllOrders = ORDER_MDY|ORDER_DMY;
5967 if (dp->dwCount > 2)
5968 dwAllOrders |= (ORDER_YMD|ORDER_YDM);
5971 VARIANT_MakeDate_Start:
5972 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
5974 while (dwAllOrders)
5976 DWORD dwTemp;
5978 if (dwCount == 0)
5980 /* First: Try the order given by iDate */
5981 switch (iDate)
5983 case 0: dwTry = dwAllOrders & ORDER_MDY; break;
5984 case 1: dwTry = dwAllOrders & ORDER_DMY; break;
5985 default: dwTry = dwAllOrders & ORDER_YMD; break;
5988 else if (dwCount == 1)
5990 /* Second: Try all the orders compatible with iDate */
5991 switch (iDate)
5993 case 0: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
5994 case 1: dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
5995 default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
5998 else
6000 /* Finally: Try any remaining orders */
6001 dwTry = dwAllOrders;
6004 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
6006 dwCount++;
6007 if (!dwTry)
6008 continue;
6010 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6012 if (dwTry & ORDER_MDY)
6014 if (VARIANT_IsValidMonthDay(v2,v1,v3))
6016 DATE_SWAP(v1,v2);
6017 goto VARIANT_MakeDate_OK;
6019 dwAllOrders &= ~ORDER_MDY;
6021 if (dwTry & ORDER_YMD)
6023 if (VARIANT_IsValidMonthDay(v3,v2,v1))
6025 DATE_SWAP(v1,v3);
6026 goto VARIANT_MakeDate_OK;
6028 dwAllOrders &= ~ORDER_YMD;
6030 if (dwTry & ORDER_YDM)
6032 if (VARIANT_IsValidMonthDay(v2,v3,v1))
6034 DATE_SWAP(v1,v2);
6035 DATE_SWAP(v2,v3);
6036 goto VARIANT_MakeDate_OK;
6038 dwAllOrders &= ~ORDER_YDM;
6040 if (dwTry & ORDER_DMY)
6042 if (VARIANT_IsValidMonthDay(v1,v2,v3))
6043 goto VARIANT_MakeDate_OK;
6044 dwAllOrders &= ~ORDER_DMY;
6046 if (dwTry & ORDER_MYD)
6048 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6049 if (VARIANT_IsValidMonthDay(v3,v1,v2))
6051 DATE_SWAP(v1,v3);
6052 DATE_SWAP(v2,v3);
6053 goto VARIANT_MakeDate_OK;
6055 dwAllOrders &= ~ORDER_MYD;
6059 if (dp->dwCount == 2)
6061 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6062 v3 = 1; /* 1st of the month */
6063 dwAllOrders = ORDER_YMD|ORDER_MYD;
6064 dp->dwCount = 0; /* Don't return to this code path again */
6065 dwCount = 0;
6066 goto VARIANT_MakeDate_Start;
6069 /* No valid dates were able to be constructed */
6070 return DISP_E_TYPEMISMATCH;
6072 VARIANT_MakeDate_OK:
6074 /* Check that the time part is ok */
6075 if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
6076 return DISP_E_TYPEMISMATCH;
6078 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6079 if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
6080 st->wHour += 12;
6081 else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
6082 st->wHour = 0;
6083 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6085 st->wDay = v1;
6086 st->wMonth = v2;
6087 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6088 * be retrieved from:
6089 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6090 * But Wine doesn't have/use that key as at the time of writing.
6092 st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
6093 TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
6094 return S_OK;
6097 /******************************************************************************
6098 * VarDateFromStr [OLEAUT32.94]
6100 * Convert a VT_BSTR to at VT_DATE.
6102 * PARAMS
6103 * strIn [I] String to convert
6104 * lcid [I] Locale identifier for the conversion
6105 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6106 * pdateOut [O] Destination for the converted value
6108 * RETURNS
6109 * Success: S_OK. pdateOut contains the converted value.
6110 * FAILURE: An HRESULT error code indicating the prolem.
6112 * NOTES
6113 * Any date format that can be created using the date formats from lcid
6114 * (Either from kernel Nls functions, variant conversion or formatting) is a
6115 * valid input to this function. In addition, a few more esoteric formats are
6116 * also supported for compatibility with the native version. The date is
6117 * interpreted according to the date settings in the control panel, unless
6118 * the date is invalid in that format, in which the most compatible format
6119 * that produces a valid date will be used.
6121 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
6123 static const USHORT ParseDateTokens[] =
6125 LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
6126 LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
6127 LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
6128 LOCALE_SMONTHNAME13,
6129 LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
6130 LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
6131 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
6132 LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
6133 LOCALE_SABBREVMONTHNAME13,
6134 LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
6135 LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
6136 LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
6137 LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
6138 LOCALE_SABBREVDAYNAME7,
6139 LOCALE_S1159, LOCALE_S2359
6141 static const BYTE ParseDateMonths[] =
6143 1,2,3,4,5,6,7,8,9,10,11,12,13,
6144 1,2,3,4,5,6,7,8,9,10,11,12,13
6146 size_t i;
6147 BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
6148 DATEPARSE dp;
6149 DWORD dwDateSeps = 0, iDate = 0;
6150 HRESULT hRet = S_OK;
6152 if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
6153 (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
6154 return E_INVALIDARG;
6156 if (!strIn)
6157 return DISP_E_TYPEMISMATCH;
6159 *pdateOut = 0.0;
6161 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
6163 memset(&dp, 0, sizeof(dp));
6165 GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
6166 (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
6167 TRACE("iDate is %ld\n", iDate);
6169 /* Get the month/day/am/pm tokens for this locale */
6170 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6172 WCHAR buff[128];
6173 LCTYPE lctype = ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
6175 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6176 * GetAltMonthNames(). We should really cache these strings too.
6178 buff[0] = '\0';
6179 GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
6180 tokens[i] = SysAllocString(buff);
6181 TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
6184 /* Parse the string into our structure */
6185 while (*strIn)
6187 if (dp.dwCount > 6)
6188 break;
6190 if (isdigitW(*strIn))
6192 dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
6193 dp.dwCount++;
6194 strIn--;
6196 else if (isalpha(*strIn))
6198 BOOL bFound = FALSE;
6200 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6202 DWORD dwLen = strlenW(tokens[i]);
6203 if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
6205 if (i <= 25)
6207 dp.dwValues[dp.dwCount] = ParseDateMonths[i];
6208 dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
6209 dp.dwCount++;
6211 else if (i > 39)
6213 if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
6214 hRet = DISP_E_TYPEMISMATCH;
6215 else
6217 dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
6218 dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
6221 strIn += (dwLen - 1);
6222 bFound = TRUE;
6223 break;
6227 if (!bFound)
6229 if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
6230 (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6232 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6233 if (*strIn == 'a' || *strIn == 'A')
6235 dp.dwFlags[dp.dwCount - 1] |= DP_AM;
6236 dp.dwParseFlags |= DP_AM;
6238 else
6240 dp.dwFlags[dp.dwCount - 1] |= DP_PM;
6241 dp.dwParseFlags |= DP_PM;
6243 strIn++;
6245 else
6247 TRACE("No matching token for %s\n", debugstr_w(strIn));
6248 hRet = DISP_E_TYPEMISMATCH;
6249 break;
6253 else if (*strIn == ':' || *strIn == '.')
6255 if (!dp.dwCount || !strIn[1])
6256 hRet = DISP_E_TYPEMISMATCH;
6257 else
6258 dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
6260 else if (*strIn == '-' || *strIn == '/')
6262 dwDateSeps++;
6263 if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
6264 hRet = DISP_E_TYPEMISMATCH;
6265 else
6266 dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
6268 else if (*strIn == ',' || isspaceW(*strIn))
6270 if (*strIn == ',' && !strIn[1])
6271 hRet = DISP_E_TYPEMISMATCH;
6273 else
6275 hRet = DISP_E_TYPEMISMATCH;
6277 strIn++;
6280 if (!dp.dwCount || dp.dwCount > 6 ||
6281 (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6282 hRet = DISP_E_TYPEMISMATCH;
6284 if (SUCCEEDED(hRet))
6286 SYSTEMTIME st;
6287 DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
6289 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
6291 /* Figure out which numbers correspond to which fields.
6293 * This switch statement works based on the fact that native interprets any
6294 * fields that are not joined with a time separator ('.' or ':') as date
6295 * fields. Thus we construct a value from 0-32 where each set bit indicates
6296 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6297 * For valid permutations, we set dwOffset to point to the first date field
6298 * and shorten dp.dwCount by the number of time fields found. The real
6299 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6300 * each date number must represent in the context of iDate.
6302 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6304 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6306 case 0x1: /* TT TTDD TTDDD */
6307 if (dp.dwCount > 3 &&
6308 ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
6309 (dp.dwFlags[4] & (DP_AM|DP_PM))))
6310 hRet = DISP_E_TYPEMISMATCH;
6311 else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
6312 hRet = DISP_E_TYPEMISMATCH;
6313 st.wHour = dp.dwValues[0];
6314 st.wMinute = dp.dwValues[1];
6315 dp.dwCount -= 2;
6316 dwOffset = 2;
6317 break;
6319 case 0x3: /* TTT TTTDD TTTDDD */
6320 if (dp.dwCount > 4 &&
6321 ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
6322 (dp.dwFlags[5] & (DP_AM|DP_PM))))
6323 hRet = DISP_E_TYPEMISMATCH;
6324 else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
6325 hRet = DISP_E_TYPEMISMATCH;
6326 st.wHour = dp.dwValues[0];
6327 st.wMinute = dp.dwValues[1];
6328 st.wSecond = dp.dwValues[2];
6329 dwOffset = 3;
6330 dp.dwCount -= 3;
6331 break;
6333 case 0x4: /* DDTT */
6334 if (dp.dwCount != 4 ||
6335 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6336 hRet = DISP_E_TYPEMISMATCH;
6338 st.wHour = dp.dwValues[2];
6339 st.wMinute = dp.dwValues[3];
6340 dp.dwCount -= 2;
6341 break;
6343 case 0x0: /* T DD DDD TDDD TDDD */
6344 if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
6346 st.wHour = dp.dwValues[0]; /* T */
6347 dp.dwCount = 0;
6348 break;
6350 else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
6352 hRet = DISP_E_TYPEMISMATCH;
6354 else if (dp.dwCount == 3)
6356 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
6358 dp.dwCount = 2;
6359 st.wHour = dp.dwValues[0];
6360 dwOffset = 1;
6361 break;
6363 if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
6365 dp.dwCount = 2;
6366 st.wHour = dp.dwValues[2];
6367 break;
6369 else if (dp.dwParseFlags & (DP_AM|DP_PM))
6370 hRet = DISP_E_TYPEMISMATCH;
6372 else if (dp.dwCount == 4)
6374 dp.dwCount = 3;
6375 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
6377 st.wHour = dp.dwValues[0];
6378 dwOffset = 1;
6380 else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
6382 st.wHour = dp.dwValues[3];
6384 else
6385 hRet = DISP_E_TYPEMISMATCH;
6386 break;
6388 /* .. fall through .. */
6390 case 0x8: /* DDDTT */
6391 if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
6392 (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
6393 (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
6394 dp.dwCount == 4 || dp.dwCount == 6)
6395 hRet = DISP_E_TYPEMISMATCH;
6396 st.wHour = dp.dwValues[3];
6397 st.wMinute = dp.dwValues[4];
6398 if (dp.dwCount == 5)
6399 dp.dwCount -= 2;
6400 break;
6402 case 0xC: /* DDTTT */
6403 if (dp.dwCount != 5 ||
6404 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6405 hRet = DISP_E_TYPEMISMATCH;
6406 st.wHour = dp.dwValues[2];
6407 st.wMinute = dp.dwValues[3];
6408 st.wSecond = dp.dwValues[4];
6409 dp.dwCount -= 3;
6410 break;
6412 case 0x18: /* DDDTTT */
6413 if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
6414 (dp.dwFlags[2] & (DP_AM|DP_PM)))
6415 hRet = DISP_E_TYPEMISMATCH;
6416 st.wHour = dp.dwValues[3];
6417 st.wMinute = dp.dwValues[4];
6418 st.wSecond = dp.dwValues[5];
6419 dp.dwCount -= 3;
6420 break;
6422 default:
6423 hRet = DISP_E_TYPEMISMATCH;
6424 break;
6427 if (SUCCEEDED(hRet))
6429 hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
6431 if (dwFlags & VAR_TIMEVALUEONLY)
6433 st.wYear = 1899;
6434 st.wMonth = 12;
6435 st.wDay = 30;
6437 else if (dwFlags & VAR_DATEVALUEONLY)
6438 st.wHour = st.wMinute = st.wSecond = 0;
6440 /* Finally, convert the value to a VT_DATE */
6441 if (SUCCEEDED(hRet))
6442 hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
6446 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6447 SysFreeString(tokens[i]);
6448 return hRet;
6451 /******************************************************************************
6452 * VarDateFromI1 (OLEAUT32.221)
6454 * Convert a VT_I1 to a VT_DATE.
6456 * PARAMS
6457 * cIn [I] Source
6458 * pdateOut [O] Destination
6460 * RETURNS
6461 * S_OK.
6463 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
6465 return _VarDateFromI1(cIn, pdateOut);
6468 /******************************************************************************
6469 * VarDateFromUI2 (OLEAUT32.222)
6471 * Convert a VT_UI2 to a VT_DATE.
6473 * PARAMS
6474 * uiIn [I] Source
6475 * pdateOut [O] Destination
6477 * RETURNS
6478 * S_OK.
6480 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
6482 return _VarDateFromUI2(uiIn, pdateOut);
6485 /******************************************************************************
6486 * VarDateFromUI4 (OLEAUT32.223)
6488 * Convert a VT_UI4 to a VT_DATE.
6490 * PARAMS
6491 * ulIn [I] Source
6492 * pdateOut [O] Destination
6494 * RETURNS
6495 * S_OK.
6497 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
6499 return _VarDateFromUI4(ulIn, pdateOut);
6502 /**********************************************************************
6503 * VarDateFromDec (OLEAUT32.224)
6505 * Convert a VT_DECIMAL to a VT_DATE.
6507 * PARAMS
6508 * pdecIn [I] Source
6509 * pdateOut [O] Destination
6511 * RETURNS
6512 * S_OK.
6514 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
6516 return _VarDateFromDec(pdecIn, pdateOut);
6519 /******************************************************************************
6520 * VarDateFromI8 (OLEAUT32.364)
6522 * Convert a VT_I8 to a VT_DATE.
6524 * PARAMS
6525 * llIn [I] Source
6526 * pdateOut [O] Destination
6528 * RETURNS
6529 * Success: S_OK.
6530 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6532 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
6534 return _VarDateFromI8(llIn, pdateOut);
6537 /******************************************************************************
6538 * VarDateFromUI8 (OLEAUT32.365)
6540 * Convert a VT_UI8 to a VT_DATE.
6542 * PARAMS
6543 * ullIn [I] Source
6544 * pdateOut [O] Destination
6546 * RETURNS
6547 * Success: S_OK.
6548 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6550 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
6552 return _VarDateFromUI8(ullIn, pdateOut);