Remove tempfile used to download Mozilla ActiveX control once it's not
[wine/testsucceed.git] / dlls / oleaut32 / vartype.c
blobec54eb3020d2aa1ae61071767986d1371822f932
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
21 #define COBJMACROS
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
25 #include "wine/debug.h"
26 #include "wine/unicode.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnt.h"
30 #include "variant.h"
31 #include "resource.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(variant);
35 extern HMODULE OLEAUT32_hModule;
37 #define CY_MULTIPLIER 10000 /* 4 dp of precision */
38 #define CY_MULTIPLIER_F 10000.0
39 #define CY_HALF (CY_MULTIPLIER/2) /* 0.5 */
40 #define CY_HALF_F (CY_MULTIPLIER_F/2.0)
42 static const WCHAR szFloatFormatW[] = { '%','.','7','G','\0' };
43 static const WCHAR szDoubleFormatW[] = { '%','.','1','5','G','\0' };
45 /* Copy data from one variant to another. */
46 static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
48 switch (vt)
50 case VT_I1:
51 case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
52 case VT_BOOL:
53 case VT_I2:
54 case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
55 case VT_R4:
56 case VT_INT:
57 case VT_I4:
58 case VT_UINT:
59 case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
60 case VT_R8:
61 case VT_DATE:
62 case VT_CY:
63 case VT_I8:
64 case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
65 case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
66 case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
67 default:
68 FIXME("VT_ type %d unhandled, please report!\n", vt);
72 /* Macro to inline conversion from a float or double to any integer type,
73 * rounding according to the 'dutch' convention.
75 #define VARIANT_DutchRound(typ, value, res) do { \
76 double whole = value < 0 ? ceil(value) : floor(value); \
77 double fract = value - whole; \
78 if (fract > 0.5) res = (typ)whole + (typ)1; \
79 else if (fract == 0.5) { typ is_odd = (typ)whole & 1; res = whole + is_odd; } \
80 else if (fract >= 0.0) res = (typ)whole; \
81 else if (fract == -0.5) { typ is_odd = (typ)whole & 1; res = whole - is_odd; } \
82 else if (fract > -0.5) res = (typ)whole; \
83 else res = (typ)whole - (typ)1; \
84 } while(0);
87 /* Coerce VT_BSTR to a numeric type */
88 static HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
89 void* pOut, VARTYPE vt)
91 VARIANTARG dstVar;
92 HRESULT hRet;
93 NUMPARSE np;
94 BYTE rgb[1024];
96 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
97 np.cDig = sizeof(rgb) / sizeof(BYTE);
98 np.dwInFlags = NUMPRS_STD;
100 hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
102 if (SUCCEEDED(hRet))
104 /* 1 << vt gives us the VTBIT constant for the destination number type */
105 hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
106 if (SUCCEEDED(hRet))
107 VARIANT_CopyData(&dstVar, vt, pOut);
109 return hRet;
112 /* Coerce VT_DISPATCH to another type */
113 static HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, VARTYPE vt)
115 static const DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
116 VARIANTARG srcVar, dstVar;
117 HRESULT hRet;
119 if (!pdispIn)
120 return DISP_E_BADVARTYPE;
122 /* Get the default 'value' property from the IDispatch */
123 hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
124 (DISPPARAMS*)&emptyParams, &srcVar, NULL, NULL);
126 if (SUCCEEDED(hRet))
128 /* Convert the property to the requested type */
129 V_VT(&dstVar) = VT_EMPTY;
130 hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, 0, vt);
131 VariantClear(&srcVar);
133 if (SUCCEEDED(hRet))
135 VARIANT_CopyData(&dstVar, vt, pOut);
136 VariantClear(&srcVar);
139 else
140 hRet = DISP_E_TYPEMISMATCH;
141 return hRet;
144 /* Inline return type */
145 #define RETTYP inline static HRESULT
148 /* Simple compiler cast from one type to another */
149 #define SIMPLE(dest, src, func) RETTYP _##func(src in, dest* out) { \
150 *out = in; return S_OK; }
152 /* Compiler cast where input cannot be negative */
153 #define NEGTST(dest, src, func) RETTYP _##func(src in, dest* out) { \
154 if (in < (src)0) return DISP_E_OVERFLOW; *out = in; return S_OK; }
156 /* Compiler cast where input cannot be > some number */
157 #define POSTST(dest, src, func, tst) RETTYP _##func(src in, dest* out) { \
158 if (in > (dest)tst) return DISP_E_OVERFLOW; *out = in; return S_OK; }
160 /* Compiler cast where input cannot be < some number or >= some other number */
161 #define BOTHTST(dest, src, func, lo, hi) RETTYP _##func(src in, dest* out) { \
162 if (in < (dest)lo || in > hi) return DISP_E_OVERFLOW; *out = in; return S_OK; }
164 /* I1 */
165 POSTST(signed char, BYTE, VarI1FromUI1, I1_MAX);
166 BOTHTST(signed char, SHORT, VarI1FromI2, I1_MIN, I1_MAX);
167 BOTHTST(signed char, LONG, VarI1FromI4, I1_MIN, I1_MAX);
168 SIMPLE(signed char, VARIANT_BOOL, VarI1FromBool);
169 POSTST(signed char, USHORT, VarI1FromUI2, I1_MAX);
170 POSTST(signed char, ULONG, VarI1FromUI4, I1_MAX);
171 BOTHTST(signed char, LONG64, VarI1FromI8, I1_MIN, I1_MAX);
172 POSTST(signed char, ULONG64, VarI1FromUI8, I1_MAX);
174 /* UI1 */
175 BOTHTST(BYTE, SHORT, VarUI1FromI2, UI1_MIN, UI1_MAX);
176 SIMPLE(BYTE, VARIANT_BOOL, VarUI1FromBool);
177 NEGTST(BYTE, signed char, VarUI1FromI1);
178 POSTST(BYTE, USHORT, VarUI1FromUI2, UI1_MAX);
179 BOTHTST(BYTE, LONG, VarUI1FromI4, UI1_MIN, UI1_MAX);
180 POSTST(BYTE, ULONG, VarUI1FromUI4, UI1_MAX);
181 BOTHTST(BYTE, LONG64, VarUI1FromI8, UI1_MIN, UI1_MAX);
182 POSTST(BYTE, ULONG64, VarUI1FromUI8, UI1_MAX);
184 /* I2 */
185 SIMPLE(SHORT, BYTE, VarI2FromUI1);
186 BOTHTST(SHORT, LONG, VarI2FromI4, I2_MIN, I2_MAX);
187 SIMPLE(SHORT, VARIANT_BOOL, VarI2FromBool);
188 SIMPLE(SHORT, signed char, VarI2FromI1);
189 POSTST(SHORT, USHORT, VarI2FromUI2, I2_MAX);
190 POSTST(SHORT, ULONG, VarI2FromUI4, I2_MAX);
191 BOTHTST(SHORT, LONG64, VarI2FromI8, I2_MIN, I2_MAX);
192 POSTST(SHORT, ULONG64, VarI2FromUI8, I2_MAX);
194 /* UI2 */
195 SIMPLE(USHORT, BYTE, VarUI2FromUI1);
196 NEGTST(USHORT, SHORT, VarUI2FromI2);
197 BOTHTST(USHORT, LONG, VarUI2FromI4, UI2_MIN, UI2_MAX);
198 SIMPLE(USHORT, VARIANT_BOOL, VarUI2FromBool);
199 NEGTST(USHORT, signed char, VarUI2FromI1);
200 POSTST(USHORT, ULONG, VarUI2FromUI4, UI2_MAX);
201 BOTHTST(USHORT, LONG64, VarUI2FromI8, UI2_MIN, UI2_MAX);
202 POSTST(USHORT, ULONG64, VarUI2FromUI8, UI2_MAX);
204 /* I4 */
205 SIMPLE(LONG, BYTE, VarI4FromUI1);
206 SIMPLE(LONG, SHORT, VarI4FromI2);
207 SIMPLE(LONG, VARIANT_BOOL, VarI4FromBool);
208 SIMPLE(LONG, signed char, VarI4FromI1);
209 SIMPLE(LONG, USHORT, VarI4FromUI2);
210 POSTST(LONG, ULONG, VarI4FromUI4, I4_MAX);
211 BOTHTST(LONG, LONG64, VarI4FromI8, I4_MIN, I4_MAX);
212 POSTST(LONG, ULONG64, VarI4FromUI8, I4_MAX);
214 /* UI4 */
215 SIMPLE(ULONG, BYTE, VarUI4FromUI1);
216 NEGTST(ULONG, SHORT, VarUI4FromI2);
217 NEGTST(ULONG, LONG, VarUI4FromI4);
218 SIMPLE(ULONG, VARIANT_BOOL, VarUI4FromBool);
219 NEGTST(ULONG, signed char, VarUI4FromI1);
220 SIMPLE(ULONG, USHORT, VarUI4FromUI2);
221 BOTHTST(ULONG, LONG64, VarUI4FromI8, UI4_MIN, UI4_MAX);
222 POSTST(ULONG, ULONG64, VarUI4FromUI8, UI4_MAX);
224 /* I8 */
225 SIMPLE(LONG64, BYTE, VarI8FromUI1);
226 SIMPLE(LONG64, SHORT, VarI8FromI2);
227 SIMPLE(LONG64, signed char, VarI8FromI1);
228 SIMPLE(LONG64, USHORT, VarI8FromUI2);
229 SIMPLE(LONG64, LONG, VarI8FromI4);
230 SIMPLE(LONG64, ULONG, VarI8FromUI4);
231 POSTST(LONG64, ULONG64, VarI8FromUI8, I8_MAX);
233 /* UI8 */
234 SIMPLE(ULONG64, BYTE, VarUI8FromUI1);
235 NEGTST(ULONG64, SHORT, VarUI8FromI2);
236 NEGTST(ULONG64, signed char, VarUI8FromI1);
237 SIMPLE(ULONG64, USHORT, VarUI8FromUI2);
238 NEGTST(ULONG64, LONG, VarUI8FromI4);
239 SIMPLE(ULONG64, ULONG, VarUI8FromUI4);
240 NEGTST(ULONG64, LONG64, VarUI8FromI8);
242 /* R4 (float) */
243 SIMPLE(float, BYTE, VarR4FromUI1);
244 SIMPLE(float, SHORT, VarR4FromI2);
245 SIMPLE(float, signed char, VarR4FromI1);
246 SIMPLE(float, USHORT, VarR4FromUI2);
247 SIMPLE(float, LONG, VarR4FromI4);
248 SIMPLE(float, ULONG, VarR4FromUI4);
249 SIMPLE(float, LONG64, VarR4FromI8);
250 SIMPLE(float, ULONG64, VarR4FromUI8);
252 /* R8 (double) */
253 SIMPLE(double, BYTE, VarR8FromUI1);
254 SIMPLE(double, SHORT, VarR8FromI2);
255 SIMPLE(double, float, VarR8FromR4);
256 RETTYP _VarR8FromCy(CY i, double* o) { *o = (double)i.int64 / CY_MULTIPLIER_F; return S_OK; }
257 SIMPLE(double, DATE, VarR8FromDate);
258 SIMPLE(double, signed char, VarR8FromI1);
259 SIMPLE(double, USHORT, VarR8FromUI2);
260 SIMPLE(double, LONG, VarR8FromI4);
261 SIMPLE(double, ULONG, VarR8FromUI4);
262 SIMPLE(double, LONG64, VarR8FromI8);
263 SIMPLE(double, ULONG64, VarR8FromUI8);
266 /* I1
269 /************************************************************************
270 * VarI1FromUI1 (OLEAUT32.244)
272 * Convert a VT_UI1 to a VT_I1.
274 * PARAMS
275 * bIn [I] Source
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
283 HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
285 return _VarI1FromUI1(bIn, pcOut);
288 /************************************************************************
289 * VarI1FromI2 (OLEAUT32.245)
291 * Convert a VT_I2 to a VT_I1.
293 * PARAMS
294 * sIn [I] Source
295 * pcOut [O] Destination
297 * RETURNS
298 * Success: S_OK.
299 * Failure: E_INVALIDARG, if the source value is invalid
300 * DISP_E_OVERFLOW, if the value will not fit in the destination
302 HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
304 return _VarI1FromI2(sIn, pcOut);
307 /************************************************************************
308 * VarI1FromI4 (OLEAUT32.246)
310 * Convert a VT_I4 to a VT_I1.
312 * PARAMS
313 * iIn [I] Source
314 * pcOut [O] Destination
316 * RETURNS
317 * Success: S_OK.
318 * Failure: E_INVALIDARG, if the source value is invalid
319 * DISP_E_OVERFLOW, if the value will not fit in the destination
321 HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
323 return _VarI1FromI4(iIn, pcOut);
326 /************************************************************************
327 * VarI1FromR4 (OLEAUT32.247)
329 * Convert a VT_R4 to a VT_I1.
331 * PARAMS
332 * fltIn [I] Source
333 * pcOut [O] Destination
335 * RETURNS
336 * Success: S_OK.
337 * Failure: E_INVALIDARG, if the source value is invalid
338 * DISP_E_OVERFLOW, if the value will not fit in the destination
340 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
342 return VarI1FromR8(fltIn, pcOut);
345 /************************************************************************
346 * VarI1FromR8 (OLEAUT32.248)
348 * Convert a VT_R8 to a VT_I1.
350 * PARAMS
351 * dblIn [I] Source
352 * pcOut [O] Destination
354 * RETURNS
355 * Success: S_OK.
356 * Failure: E_INVALIDARG, if the source value is invalid
357 * DISP_E_OVERFLOW, if the value will not fit in the destination
359 * NOTES
360 * See VarI8FromR8() for details concerning rounding.
362 HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
364 if (dblIn < (double)I1_MIN || dblIn > (double)I1_MAX)
365 return DISP_E_OVERFLOW;
366 VARIANT_DutchRound(CHAR, dblIn, *pcOut);
367 return S_OK;
370 /************************************************************************
371 * VarI1FromDate (OLEAUT32.249)
373 * Convert a VT_DATE to a VT_I1.
375 * PARAMS
376 * dateIn [I] Source
377 * pcOut [O] Destination
379 * RETURNS
380 * Success: S_OK.
381 * Failure: E_INVALIDARG, if the source value is invalid
382 * DISP_E_OVERFLOW, if the value will not fit in the destination
384 HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
386 return VarI1FromR8(dateIn, pcOut);
389 /************************************************************************
390 * VarI1FromCy (OLEAUT32.250)
392 * Convert a VT_CY to a VT_I1.
394 * PARAMS
395 * cyIn [I] Source
396 * pcOut [O] Destination
398 * RETURNS
399 * Success: S_OK.
400 * Failure: E_INVALIDARG, if the source value is invalid
401 * DISP_E_OVERFLOW, if the value will not fit in the destination
403 HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
405 LONG i = I1_MAX + 1;
407 VarI4FromCy(cyIn, &i);
408 return _VarI1FromI4(i, pcOut);
411 /************************************************************************
412 * VarI1FromStr (OLEAUT32.251)
414 * Convert a VT_BSTR to a VT_I1.
416 * PARAMS
417 * strIn [I] Source
418 * lcid [I] LCID for the conversion
419 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
420 * pcOut [O] Destination
422 * RETURNS
423 * Success: S_OK.
424 * Failure: E_INVALIDARG, if the source value is invalid
425 * DISP_E_OVERFLOW, if the value will not fit in the destination
426 * DISP_E_TYPEMISMATCH, if the type cannot be converted
428 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
430 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pcOut, VT_I1);
433 /************************************************************************
434 * VarI1FromDisp (OLEAUT32.252)
436 * Convert a VT_DISPATCH to a VT_I1.
438 * PARAMS
439 * pdispIn [I] Source
440 * lcid [I] LCID for conversion
441 * pcOut [O] Destination
443 * RETURNS
444 * Success: S_OK.
445 * Failure: E_INVALIDARG, if the source value is invalid
446 * DISP_E_OVERFLOW, if the value will not fit in the destination
447 * DISP_E_TYPEMISMATCH, if the type cannot be converted
449 HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
451 return VARIANT_FromDisp(pdispIn, lcid, pcOut, VT_I1);
454 /************************************************************************
455 * VarI1FromBool (OLEAUT32.253)
457 * Convert a VT_BOOL to a VT_I1.
459 * PARAMS
460 * boolIn [I] Source
461 * pcOut [O] Destination
463 * RETURNS
464 * S_OK.
466 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
468 return _VarI1FromBool(boolIn, pcOut);
471 /************************************************************************
472 * VarI1FromUI2 (OLEAUT32.254)
474 * Convert a VT_UI2 to a VT_I1.
476 * PARAMS
477 * usIn [I] Source
478 * pcOut [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
485 HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
487 return _VarI1FromUI2(usIn, pcOut);
490 /************************************************************************
491 * VarI1FromUI4 (OLEAUT32.255)
493 * Convert a VT_UI4 to a VT_I1.
495 * PARAMS
496 * ulIn [I] Source
497 * pcOut [O] Destination
499 * RETURNS
500 * Success: S_OK.
501 * Failure: E_INVALIDARG, if the source value is invalid
502 * DISP_E_OVERFLOW, if the value will not fit in the destination
503 * DISP_E_TYPEMISMATCH, if the type cannot be converted
505 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
507 return _VarI1FromUI4(ulIn, pcOut);
510 /************************************************************************
511 * VarI1FromDec (OLEAUT32.256)
513 * Convert a VT_DECIMAL to a VT_I1.
515 * PARAMS
516 * pDecIn [I] Source
517 * pcOut [O] Destination
519 * RETURNS
520 * Success: S_OK.
521 * Failure: E_INVALIDARG, if the source value is invalid
522 * DISP_E_OVERFLOW, if the value will not fit in the destination
524 HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
526 LONG64 i64;
527 HRESULT hRet;
529 hRet = VarI8FromDec(pdecIn, &i64);
531 if (SUCCEEDED(hRet))
532 hRet = _VarI1FromI8(i64, pcOut);
533 return hRet;
536 /************************************************************************
537 * VarI1FromI8 (OLEAUT32.376)
539 * Convert a VT_I8 to a VT_I1.
541 * PARAMS
542 * llIn [I] Source
543 * pcOut [O] Destination
545 * RETURNS
546 * Success: S_OK.
547 * Failure: E_INVALIDARG, if the source value is invalid
548 * DISP_E_OVERFLOW, if the value will not fit in the destination
550 HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
552 return _VarI1FromI8(llIn, pcOut);
555 /************************************************************************
556 * VarI1FromUI8 (OLEAUT32.377)
558 * Convert a VT_UI8 to a VT_I1.
560 * PARAMS
561 * ullIn [I] Source
562 * pcOut [O] Destination
564 * RETURNS
565 * Success: S_OK.
566 * Failure: E_INVALIDARG, if the source value is invalid
567 * DISP_E_OVERFLOW, if the value will not fit in the destination
569 HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
571 return _VarI1FromUI8(ullIn, pcOut);
574 /* UI1
577 /************************************************************************
578 * VarUI1FromI2 (OLEAUT32.130)
580 * Convert a VT_I2 to a VT_UI1.
582 * PARAMS
583 * sIn [I] Source
584 * pbOut [O] Destination
586 * RETURNS
587 * Success: S_OK.
588 * Failure: E_INVALIDARG, if the source value is invalid
589 * DISP_E_OVERFLOW, if the value will not fit in the destination
591 HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
593 return _VarUI1FromI2(sIn, pbOut);
596 /************************************************************************
597 * VarUI1FromI4 (OLEAUT32.131)
599 * Convert a VT_I4 to a VT_UI1.
601 * PARAMS
602 * iIn [I] Source
603 * pbOut [O] Destination
605 * RETURNS
606 * Success: S_OK.
607 * Failure: E_INVALIDARG, if the source value is invalid
608 * DISP_E_OVERFLOW, if the value will not fit in the destination
610 HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
612 return _VarUI1FromI4(iIn, pbOut);
615 /************************************************************************
616 * VarUI1FromR4 (OLEAUT32.132)
618 * Convert a VT_R4 to a VT_UI1.
620 * PARAMS
621 * fltIn [I] Source
622 * pbOut [O] Destination
624 * RETURNS
625 * Success: S_OK.
626 * Failure: E_INVALIDARG, if the source value is invalid
627 * DISP_E_OVERFLOW, if the value will not fit in the destination
628 * DISP_E_TYPEMISMATCH, if the type cannot be converted
630 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
632 return VarUI1FromR8(fltIn, pbOut);
635 /************************************************************************
636 * VarUI1FromR8 (OLEAUT32.133)
638 * Convert a VT_R8 to a VT_UI1.
640 * PARAMS
641 * dblIn [I] Source
642 * pbOut [O] Destination
644 * RETURNS
645 * Success: S_OK.
646 * Failure: E_INVALIDARG, if the source value is invalid
647 * DISP_E_OVERFLOW, if the value will not fit in the destination
649 * NOTES
650 * See VarI8FromR8() for details concerning rounding.
652 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
654 if (dblIn < -0.5 || dblIn > (double)UI1_MAX)
655 return DISP_E_OVERFLOW;
656 VARIANT_DutchRound(BYTE, dblIn, *pbOut);
657 return S_OK;
660 /************************************************************************
661 * VarUI1FromCy (OLEAUT32.134)
663 * Convert a VT_CY to a VT_UI1.
665 * PARAMS
666 * cyIn [I] Source
667 * pbOut [O] Destination
669 * RETURNS
670 * Success: S_OK.
671 * Failure: E_INVALIDARG, if the source value is invalid
672 * DISP_E_OVERFLOW, if the value will not fit in the destination
674 * NOTES
675 * Negative values >= -5000 will be converted to 0.
677 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
679 ULONG i = UI1_MAX + 1;
681 VarUI4FromCy(cyIn, &i);
682 return _VarUI1FromUI4(i, pbOut);
685 /************************************************************************
686 * VarUI1FromDate (OLEAUT32.135)
688 * Convert a VT_DATE to a VT_UI1.
690 * PARAMS
691 * dateIn [I] Source
692 * pbOut [O] Destination
694 * RETURNS
695 * Success: S_OK.
696 * Failure: E_INVALIDARG, if the source value is invalid
697 * DISP_E_OVERFLOW, if the value will not fit in the destination
699 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
701 return VarUI1FromR8(dateIn, pbOut);
704 /************************************************************************
705 * VarUI1FromStr (OLEAUT32.136)
707 * Convert a VT_BSTR to a VT_UI1.
709 * PARAMS
710 * strIn [I] Source
711 * lcid [I] LCID for the conversion
712 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
713 * pbOut [O] Destination
715 * RETURNS
716 * Success: S_OK.
717 * Failure: E_INVALIDARG, if the source value is invalid
718 * DISP_E_OVERFLOW, if the value will not fit in the destination
719 * DISP_E_TYPEMISMATCH, if the type cannot be converted
721 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
723 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pbOut, VT_UI1);
726 /************************************************************************
727 * VarUI1FromDisp (OLEAUT32.137)
729 * Convert a VT_DISPATCH to a VT_UI1.
731 * PARAMS
732 * pdispIn [I] Source
733 * lcid [I] LCID for conversion
734 * pbOut [O] Destination
736 * RETURNS
737 * Success: S_OK.
738 * Failure: E_INVALIDARG, if the source value is invalid
739 * DISP_E_OVERFLOW, if the value will not fit in the destination
740 * DISP_E_TYPEMISMATCH, if the type cannot be converted
742 HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
744 return VARIANT_FromDisp(pdispIn, lcid, pbOut, VT_UI1);
747 /************************************************************************
748 * VarUI1FromBool (OLEAUT32.138)
750 * Convert a VT_BOOL to a VT_UI1.
752 * PARAMS
753 * boolIn [I] Source
754 * pbOut [O] Destination
756 * RETURNS
757 * S_OK.
759 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
761 return _VarUI1FromBool(boolIn, pbOut);
764 /************************************************************************
765 * VarUI1FromI1 (OLEAUT32.237)
767 * Convert a VT_I1 to a VT_UI1.
769 * PARAMS
770 * cIn [I] Source
771 * pbOut [O] Destination
773 * RETURNS
774 * Success: S_OK.
775 * Failure: E_INVALIDARG, if the source value is invalid
776 * DISP_E_OVERFLOW, if the value will not fit in the destination
778 HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
780 return _VarUI1FromI1(cIn, pbOut);
783 /************************************************************************
784 * VarUI1FromUI2 (OLEAUT32.238)
786 * Convert a VT_UI2 to a VT_UI1.
788 * PARAMS
789 * usIn [I] Source
790 * pbOut [O] Destination
792 * RETURNS
793 * Success: S_OK.
794 * Failure: E_INVALIDARG, if the source value is invalid
795 * DISP_E_OVERFLOW, if the value will not fit in the destination
797 HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
799 return _VarUI1FromUI2(usIn, pbOut);
802 /************************************************************************
803 * VarUI1FromUI4 (OLEAUT32.239)
805 * Convert a VT_UI4 to a VT_UI1.
807 * PARAMS
808 * ulIn [I] Source
809 * pbOut [O] Destination
811 * RETURNS
812 * Success: S_OK.
813 * Failure: E_INVALIDARG, if the source value is invalid
814 * DISP_E_OVERFLOW, if the value will not fit in the destination
816 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
818 return _VarUI1FromUI4(ulIn, pbOut);
821 /************************************************************************
822 * VarUI1FromDec (OLEAUT32.240)
824 * Convert a VT_DECIMAL to a VT_UI1.
826 * PARAMS
827 * pDecIn [I] Source
828 * pbOut [O] Destination
830 * RETURNS
831 * Success: S_OK.
832 * Failure: E_INVALIDARG, if the source value is invalid
833 * DISP_E_OVERFLOW, if the value will not fit in the destination
835 HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
837 LONG64 i64;
838 HRESULT hRet;
840 hRet = VarI8FromDec(pdecIn, &i64);
842 if (SUCCEEDED(hRet))
843 hRet = _VarUI1FromI8(i64, pbOut);
844 return hRet;
847 /************************************************************************
848 * VarUI1FromI8 (OLEAUT32.372)
850 * Convert a VT_I8 to a VT_UI1.
852 * PARAMS
853 * llIn [I] Source
854 * pbOut [O] Destination
856 * RETURNS
857 * Success: S_OK.
858 * Failure: E_INVALIDARG, if the source value is invalid
859 * DISP_E_OVERFLOW, if the value will not fit in the destination
861 HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
863 return _VarUI1FromI8(llIn, pbOut);
866 /************************************************************************
867 * VarUI1FromUI8 (OLEAUT32.373)
869 * Convert a VT_UI8 to a VT_UI1.
871 * PARAMS
872 * ullIn [I] Source
873 * pbOut [O] Destination
875 * RETURNS
876 * Success: S_OK.
877 * Failure: E_INVALIDARG, if the source value is invalid
878 * DISP_E_OVERFLOW, if the value will not fit in the destination
880 HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
882 return _VarUI1FromUI8(ullIn, pbOut);
886 /* I2
889 /************************************************************************
890 * VarI2FromUI1 (OLEAUT32.48)
892 * Convert a VT_UI2 to a VT_I2.
894 * PARAMS
895 * bIn [I] Source
896 * psOut [O] Destination
898 * RETURNS
899 * S_OK.
901 HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
903 return _VarI2FromUI1(bIn, psOut);
906 /************************************************************************
907 * VarI2FromI4 (OLEAUT32.49)
909 * Convert a VT_I4 to a VT_I2.
911 * PARAMS
912 * iIn [I] Source
913 * psOut [O] Destination
915 * RETURNS
916 * Success: S_OK.
917 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
919 HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
921 return _VarI2FromI4(iIn, psOut);
924 /************************************************************************
925 * VarI2FromR4 (OLEAUT32.50)
927 * Convert a VT_R4 to a VT_I2.
929 * PARAMS
930 * fltIn [I] Source
931 * psOut [O] Destination
933 * RETURNS
934 * Success: S_OK.
935 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
937 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
939 return VarI2FromR8(fltIn, psOut);
942 /************************************************************************
943 * VarI2FromR8 (OLEAUT32.51)
945 * Convert a VT_R8 to a VT_I2.
947 * PARAMS
948 * dblIn [I] Source
949 * psOut [O] Destination
951 * RETURNS
952 * Success: S_OK.
953 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
955 * NOTES
956 * See VarI8FromR8() for details concerning rounding.
958 HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
960 if (dblIn < (double)I2_MIN || dblIn > (double)I2_MAX)
961 return DISP_E_OVERFLOW;
962 VARIANT_DutchRound(SHORT, dblIn, *psOut);
963 return S_OK;
966 /************************************************************************
967 * VarI2FromCy (OLEAUT32.52)
969 * Convert a VT_CY to a VT_I2.
971 * PARAMS
972 * cyIn [I] Source
973 * psOut [O] Destination
975 * RETURNS
976 * Success: S_OK.
977 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
979 HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
981 LONG i = I2_MAX + 1;
983 VarI4FromCy(cyIn, &i);
984 return _VarI2FromI4(i, psOut);
987 /************************************************************************
988 * VarI2FromDate (OLEAUT32.53)
990 * Convert a VT_DATE to a VT_I2.
992 * PARAMS
993 * dateIn [I] Source
994 * psOut [O] Destination
996 * RETURNS
997 * Success: S_OK.
998 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1000 HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
1002 return VarI2FromR8(dateIn, psOut);
1005 /************************************************************************
1006 * VarI2FromStr (OLEAUT32.54)
1008 * Convert a VT_BSTR to a VT_I2.
1010 * PARAMS
1011 * strIn [I] Source
1012 * lcid [I] LCID for the conversion
1013 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1014 * psOut [O] Destination
1016 * RETURNS
1017 * Success: S_OK.
1018 * Failure: E_INVALIDARG, if any parameter is invalid
1019 * DISP_E_OVERFLOW, if the value will not fit in the destination
1020 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1022 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
1024 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, psOut, VT_I2);
1027 /************************************************************************
1028 * VarI2FromDisp (OLEAUT32.55)
1030 * Convert a VT_DISPATCH to a VT_I2.
1032 * PARAMS
1033 * pdispIn [I] Source
1034 * lcid [I] LCID for conversion
1035 * psOut [O] Destination
1037 * RETURNS
1038 * Success: S_OK.
1039 * Failure: E_INVALIDARG, if pdispIn is invalid,
1040 * DISP_E_OVERFLOW, if the value will not fit in the destination,
1041 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1043 HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
1045 return VARIANT_FromDisp(pdispIn, lcid, psOut, VT_I2);
1048 /************************************************************************
1049 * VarI2FromBool (OLEAUT32.56)
1051 * Convert a VT_BOOL to a VT_I2.
1053 * PARAMS
1054 * boolIn [I] Source
1055 * psOut [O] Destination
1057 * RETURNS
1058 * S_OK.
1060 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
1062 return _VarI2FromBool(boolIn, psOut);
1065 /************************************************************************
1066 * VarI2FromI1 (OLEAUT32.205)
1068 * Convert a VT_I1 to a VT_I2.
1070 * PARAMS
1071 * cIn [I] Source
1072 * psOut [O] Destination
1074 * RETURNS
1075 * S_OK.
1077 HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
1079 return _VarI2FromI1(cIn, psOut);
1082 /************************************************************************
1083 * VarI2FromUI2 (OLEAUT32.206)
1085 * Convert a VT_UI2 to a VT_I2.
1087 * PARAMS
1088 * usIn [I] Source
1089 * psOut [O] Destination
1091 * RETURNS
1092 * Success: S_OK.
1093 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1095 HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
1097 return _VarI2FromUI2(usIn, psOut);
1100 /************************************************************************
1101 * VarI2FromUI4 (OLEAUT32.207)
1103 * Convert a VT_UI4 to a VT_I2.
1105 * PARAMS
1106 * ulIn [I] Source
1107 * psOut [O] Destination
1109 * RETURNS
1110 * Success: S_OK.
1111 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1113 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
1115 return _VarI2FromUI4(ulIn, psOut);
1118 /************************************************************************
1119 * VarI2FromDec (OLEAUT32.208)
1121 * Convert a VT_DECIMAL to a VT_I2.
1123 * PARAMS
1124 * pDecIn [I] Source
1125 * psOut [O] Destination
1127 * RETURNS
1128 * Success: S_OK.
1129 * Failure: E_INVALIDARG, if the source value is invalid
1130 * DISP_E_OVERFLOW, if the value will not fit in the destination
1132 HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
1134 LONG64 i64;
1135 HRESULT hRet;
1137 hRet = VarI8FromDec(pdecIn, &i64);
1139 if (SUCCEEDED(hRet))
1140 hRet = _VarI2FromI8(i64, psOut);
1141 return hRet;
1144 /************************************************************************
1145 * VarI2FromI8 (OLEAUT32.346)
1147 * Convert a VT_I8 to a VT_I2.
1149 * PARAMS
1150 * llIn [I] Source
1151 * psOut [O] Destination
1153 * RETURNS
1154 * Success: S_OK.
1155 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1157 HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
1159 return _VarI2FromI8(llIn, psOut);
1162 /************************************************************************
1163 * VarI2FromUI8 (OLEAUT32.347)
1165 * Convert a VT_UI8 to a VT_I2.
1167 * PARAMS
1168 * ullIn [I] Source
1169 * psOut [O] Destination
1171 * RETURNS
1172 * Success: S_OK.
1173 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1175 HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
1177 return _VarI2FromUI8(ullIn, psOut);
1180 /* UI2
1183 /************************************************************************
1184 * VarUI2FromUI1 (OLEAUT32.257)
1186 * Convert a VT_UI1 to a VT_UI2.
1188 * PARAMS
1189 * bIn [I] Source
1190 * pusOut [O] Destination
1192 * RETURNS
1193 * S_OK.
1195 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
1197 return _VarUI2FromUI1(bIn, pusOut);
1200 /************************************************************************
1201 * VarUI2FromI2 (OLEAUT32.258)
1203 * Convert a VT_I2 to a VT_UI2.
1205 * PARAMS
1206 * sIn [I] Source
1207 * pusOut [O] Destination
1209 * RETURNS
1210 * Success: S_OK.
1211 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1213 HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
1215 return _VarUI2FromI2(sIn, pusOut);
1218 /************************************************************************
1219 * VarUI2FromI4 (OLEAUT32.259)
1221 * Convert a VT_I4 to a VT_UI2.
1223 * PARAMS
1224 * iIn [I] Source
1225 * pusOut [O] Destination
1227 * RETURNS
1228 * Success: S_OK.
1229 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1231 HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
1233 return _VarUI2FromI4(iIn, pusOut);
1236 /************************************************************************
1237 * VarUI2FromR4 (OLEAUT32.260)
1239 * Convert a VT_R4 to a VT_UI2.
1241 * PARAMS
1242 * fltIn [I] Source
1243 * pusOut [O] Destination
1245 * RETURNS
1246 * Success: S_OK.
1247 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1249 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
1251 return VarUI2FromR8(fltIn, pusOut);
1254 /************************************************************************
1255 * VarUI2FromR8 (OLEAUT32.261)
1257 * Convert a VT_R8 to a VT_UI2.
1259 * PARAMS
1260 * dblIn [I] Source
1261 * pusOut [O] Destination
1263 * RETURNS
1264 * Success: S_OK.
1265 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1267 * NOTES
1268 * See VarI8FromR8() for details concerning rounding.
1270 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
1272 if (dblIn < -0.5 || dblIn > (double)UI2_MAX)
1273 return DISP_E_OVERFLOW;
1274 VARIANT_DutchRound(USHORT, dblIn, *pusOut);
1275 return S_OK;
1278 /************************************************************************
1279 * VarUI2FromDate (OLEAUT32.262)
1281 * Convert a VT_DATE to a VT_UI2.
1283 * PARAMS
1284 * dateIn [I] Source
1285 * pusOut [O] Destination
1287 * RETURNS
1288 * Success: S_OK.
1289 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1291 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
1293 return VarUI2FromR8(dateIn, pusOut);
1296 /************************************************************************
1297 * VarUI2FromCy (OLEAUT32.263)
1299 * Convert a VT_CY to a VT_UI2.
1301 * PARAMS
1302 * cyIn [I] Source
1303 * pusOut [O] Destination
1305 * RETURNS
1306 * Success: S_OK.
1307 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1309 * NOTES
1310 * Negative values >= -5000 will be converted to 0.
1312 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
1314 ULONG i = UI2_MAX + 1;
1316 VarUI4FromCy(cyIn, &i);
1317 return _VarUI2FromUI4(i, pusOut);
1320 /************************************************************************
1321 * VarUI2FromStr (OLEAUT32.264)
1323 * Convert a VT_BSTR to a VT_UI2.
1325 * PARAMS
1326 * strIn [I] Source
1327 * lcid [I] LCID for the conversion
1328 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1329 * pusOut [O] Destination
1331 * RETURNS
1332 * Success: S_OK.
1333 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1334 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1336 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
1338 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pusOut, VT_UI2);
1341 /************************************************************************
1342 * VarUI2FromDisp (OLEAUT32.265)
1344 * Convert a VT_DISPATCH to a VT_UI2.
1346 * PARAMS
1347 * pdispIn [I] Source
1348 * lcid [I] LCID for conversion
1349 * pusOut [O] Destination
1351 * RETURNS
1352 * Success: S_OK.
1353 * Failure: E_INVALIDARG, if the source value is invalid
1354 * DISP_E_OVERFLOW, if the value will not fit in the destination
1355 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1357 HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
1359 return VARIANT_FromDisp(pdispIn, lcid, pusOut, VT_UI2);
1362 /************************************************************************
1363 * VarUI2FromBool (OLEAUT32.266)
1365 * Convert a VT_BOOL to a VT_UI2.
1367 * PARAMS
1368 * boolIn [I] Source
1369 * pusOut [O] Destination
1371 * RETURNS
1372 * S_OK.
1374 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
1376 return _VarUI2FromBool(boolIn, pusOut);
1379 /************************************************************************
1380 * VarUI2FromI1 (OLEAUT32.267)
1382 * Convert a VT_I1 to a VT_UI2.
1384 * PARAMS
1385 * cIn [I] Source
1386 * pusOut [O] Destination
1388 * RETURNS
1389 * Success: S_OK.
1390 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1392 HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
1394 return _VarUI2FromI1(cIn, pusOut);
1397 /************************************************************************
1398 * VarUI2FromUI4 (OLEAUT32.268)
1400 * Convert a VT_UI4 to a VT_UI2.
1402 * PARAMS
1403 * ulIn [I] Source
1404 * pusOut [O] Destination
1406 * RETURNS
1407 * Success: S_OK.
1408 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1410 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
1412 return _VarUI2FromUI4(ulIn, pusOut);
1415 /************************************************************************
1416 * VarUI2FromDec (OLEAUT32.269)
1418 * Convert a VT_DECIMAL to a VT_UI2.
1420 * PARAMS
1421 * pDecIn [I] Source
1422 * pusOut [O] Destination
1424 * RETURNS
1425 * Success: S_OK.
1426 * Failure: E_INVALIDARG, if the source value is invalid
1427 * DISP_E_OVERFLOW, if the value will not fit in the destination
1429 HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
1431 LONG64 i64;
1432 HRESULT hRet;
1434 hRet = VarI8FromDec(pdecIn, &i64);
1436 if (SUCCEEDED(hRet))
1437 hRet = _VarUI2FromI8(i64, pusOut);
1438 return hRet;
1441 /************************************************************************
1442 * VarUI2FromI8 (OLEAUT32.378)
1444 * Convert a VT_I8 to a VT_UI2.
1446 * PARAMS
1447 * llIn [I] Source
1448 * pusOut [O] Destination
1450 * RETURNS
1451 * Success: S_OK.
1452 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1454 HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
1456 return _VarUI2FromI8(llIn, pusOut);
1459 /************************************************************************
1460 * VarUI2FromUI8 (OLEAUT32.379)
1462 * Convert a VT_UI8 to a VT_UI2.
1464 * PARAMS
1465 * ullIn [I] Source
1466 * pusOut [O] Destination
1468 * RETURNS
1469 * Success: S_OK.
1470 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1472 HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
1474 return _VarUI2FromUI8(ullIn, pusOut);
1477 /* I4
1480 /************************************************************************
1481 * VarI4FromUI1 (OLEAUT32.58)
1483 * Convert a VT_UI1 to a VT_I4.
1485 * PARAMS
1486 * bIn [I] Source
1487 * piOut [O] Destination
1489 * RETURNS
1490 * S_OK.
1492 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
1494 return _VarI4FromUI1(bIn, piOut);
1497 /************************************************************************
1498 * VarI4FromI2 (OLEAUT32.59)
1500 * Convert a VT_I2 to a VT_I4.
1502 * PARAMS
1503 * sIn [I] Source
1504 * piOut [O] Destination
1506 * RETURNS
1507 * Success: S_OK.
1508 * Failure: E_INVALIDARG, if the source value is invalid
1509 * DISP_E_OVERFLOW, if the value will not fit in the destination
1511 HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
1513 return _VarI4FromI2(sIn, piOut);
1516 /************************************************************************
1517 * VarI4FromR4 (OLEAUT32.60)
1519 * Convert a VT_R4 to a VT_I4.
1521 * PARAMS
1522 * fltIn [I] Source
1523 * piOut [O] Destination
1525 * RETURNS
1526 * Success: S_OK.
1527 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1529 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
1531 return VarI4FromR8(fltIn, piOut);
1534 /************************************************************************
1535 * VarI4FromR8 (OLEAUT32.61)
1537 * Convert a VT_R8 to a VT_I4.
1539 * PARAMS
1540 * dblIn [I] Source
1541 * piOut [O] Destination
1543 * RETURNS
1544 * Success: S_OK.
1545 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1547 * NOTES
1548 * See VarI8FromR8() for details concerning rounding.
1550 HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
1552 if (dblIn < (double)I4_MIN || dblIn > (double)I4_MAX)
1553 return DISP_E_OVERFLOW;
1554 VARIANT_DutchRound(LONG, dblIn, *piOut);
1555 return S_OK;
1558 /************************************************************************
1559 * VarI4FromCy (OLEAUT32.62)
1561 * Convert a VT_CY to a VT_I4.
1563 * PARAMS
1564 * cyIn [I] Source
1565 * piOut [O] Destination
1567 * RETURNS
1568 * Success: S_OK.
1569 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1571 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
1573 double d = cyIn.int64 / CY_MULTIPLIER_F;
1574 return VarI4FromR8(d, piOut);
1577 /************************************************************************
1578 * VarI4FromDate (OLEAUT32.63)
1580 * Convert a VT_DATE to a VT_I4.
1582 * PARAMS
1583 * dateIn [I] Source
1584 * piOut [O] Destination
1586 * RETURNS
1587 * Success: S_OK.
1588 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1590 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
1592 return VarI4FromR8(dateIn, piOut);
1595 /************************************************************************
1596 * VarI4FromStr (OLEAUT32.64)
1598 * Convert a VT_BSTR to a VT_I4.
1600 * PARAMS
1601 * strIn [I] Source
1602 * lcid [I] LCID for the conversion
1603 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1604 * piOut [O] Destination
1606 * RETURNS
1607 * Success: S_OK.
1608 * Failure: E_INVALIDARG, if any parameter is invalid
1609 * DISP_E_OVERFLOW, if the value will not fit in the destination
1610 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1612 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
1614 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, piOut, VT_I4);
1617 /************************************************************************
1618 * VarI4FromDisp (OLEAUT32.65)
1620 * Convert a VT_DISPATCH to a VT_I4.
1622 * PARAMS
1623 * pdispIn [I] Source
1624 * lcid [I] LCID for conversion
1625 * piOut [O] Destination
1627 * RETURNS
1628 * Success: S_OK.
1629 * Failure: E_INVALIDARG, if the source value is invalid
1630 * DISP_E_OVERFLOW, if the value will not fit in the destination
1631 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1633 HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
1635 return VARIANT_FromDisp(pdispIn, lcid, piOut, VT_I4);
1638 /************************************************************************
1639 * VarI4FromBool (OLEAUT32.66)
1641 * Convert a VT_BOOL to a VT_I4.
1643 * PARAMS
1644 * boolIn [I] Source
1645 * piOut [O] Destination
1647 * RETURNS
1648 * S_OK.
1650 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
1652 return _VarI4FromBool(boolIn, piOut);
1655 /************************************************************************
1656 * VarI4FromI1 (OLEAUT32.209)
1658 * Convert a VT_I4 to a VT_I4.
1660 * PARAMS
1661 * cIn [I] Source
1662 * piOut [O] Destination
1664 * RETURNS
1665 * S_OK.
1667 HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
1669 return _VarI4FromI1(cIn, piOut);
1672 /************************************************************************
1673 * VarI4FromUI2 (OLEAUT32.210)
1675 * Convert a VT_UI2 to a VT_I4.
1677 * PARAMS
1678 * usIn [I] Source
1679 * piOut [O] Destination
1681 * RETURNS
1682 * S_OK.
1684 HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
1686 return _VarI4FromUI2(usIn, piOut);
1689 /************************************************************************
1690 * VarI4FromUI4 (OLEAUT32.211)
1692 * Convert a VT_UI4 to a VT_I4.
1694 * PARAMS
1695 * ulIn [I] Source
1696 * piOut [O] Destination
1698 * RETURNS
1699 * Success: S_OK.
1700 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1702 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
1704 return _VarI4FromUI4(ulIn, piOut);
1707 /************************************************************************
1708 * VarI4FromDec (OLEAUT32.212)
1710 * Convert a VT_DECIMAL to a VT_I4.
1712 * PARAMS
1713 * pDecIn [I] Source
1714 * piOut [O] Destination
1716 * RETURNS
1717 * Success: S_OK.
1718 * Failure: E_INVALIDARG, if pdecIn is invalid
1719 * DISP_E_OVERFLOW, if the value will not fit in the destination
1721 HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
1723 LONG64 i64;
1724 HRESULT hRet;
1726 hRet = VarI8FromDec(pdecIn, &i64);
1728 if (SUCCEEDED(hRet))
1729 hRet = _VarI4FromI8(i64, piOut);
1730 return hRet;
1733 /************************************************************************
1734 * VarI4FromI8 (OLEAUT32.348)
1736 * Convert a VT_I8 to a VT_I4.
1738 * PARAMS
1739 * llIn [I] Source
1740 * piOut [O] Destination
1742 * RETURNS
1743 * Success: S_OK.
1744 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1746 HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
1748 return _VarI4FromI8(llIn, piOut);
1751 /************************************************************************
1752 * VarI4FromUI8 (OLEAUT32.349)
1754 * Convert a VT_UI8 to a VT_I4.
1756 * PARAMS
1757 * ullIn [I] Source
1758 * piOut [O] Destination
1760 * RETURNS
1761 * Success: S_OK.
1762 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1764 HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
1766 return _VarI4FromUI8(ullIn, piOut);
1769 /* UI4
1772 /************************************************************************
1773 * VarUI4FromUI1 (OLEAUT32.270)
1775 * Convert a VT_UI1 to a VT_UI4.
1777 * PARAMS
1778 * bIn [I] Source
1779 * pulOut [O] Destination
1781 * RETURNS
1782 * S_OK.
1784 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
1786 return _VarUI4FromUI1(bIn, pulOut);
1789 /************************************************************************
1790 * VarUI4FromI2 (OLEAUT32.271)
1792 * Convert a VT_I2 to a VT_UI4.
1794 * PARAMS
1795 * sIn [I] Source
1796 * pulOut [O] Destination
1798 * RETURNS
1799 * Success: S_OK.
1800 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1802 HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
1804 return _VarUI4FromI2(sIn, pulOut);
1807 /************************************************************************
1808 * VarUI4FromI4 (OLEAUT32.272)
1810 * Convert a VT_I4 to a VT_UI4.
1812 * PARAMS
1813 * iIn [I] Source
1814 * pulOut [O] Destination
1816 * RETURNS
1817 * Success: S_OK.
1818 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1820 HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
1822 return _VarUI4FromI4(iIn, pulOut);
1825 /************************************************************************
1826 * VarUI4FromR4 (OLEAUT32.273)
1828 * Convert a VT_R4 to a VT_UI4.
1830 * PARAMS
1831 * fltIn [I] Source
1832 * pulOut [O] Destination
1834 * RETURNS
1835 * Success: S_OK.
1836 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1838 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
1840 return VarUI4FromR8(fltIn, pulOut);
1843 /************************************************************************
1844 * VarUI4FromR8 (OLEAUT32.274)
1846 * Convert a VT_R8 to a VT_UI4.
1848 * PARAMS
1849 * dblIn [I] Source
1850 * pulOut [O] Destination
1852 * RETURNS
1853 * Success: S_OK.
1854 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1856 * NOTES
1857 * See VarI8FromR8() for details concerning rounding.
1859 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
1861 if (dblIn < -0.5 || dblIn > (double)UI4_MAX)
1862 return DISP_E_OVERFLOW;
1863 VARIANT_DutchRound(ULONG, dblIn, *pulOut);
1864 return S_OK;
1867 /************************************************************************
1868 * VarUI4FromDate (OLEAUT32.275)
1870 * Convert a VT_DATE to a VT_UI4.
1872 * PARAMS
1873 * dateIn [I] Source
1874 * pulOut [O] Destination
1876 * RETURNS
1877 * Success: S_OK.
1878 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1880 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
1882 return VarUI4FromR8(dateIn, pulOut);
1885 /************************************************************************
1886 * VarUI4FromCy (OLEAUT32.276)
1888 * Convert a VT_CY to a VT_UI4.
1890 * PARAMS
1891 * cyIn [I] Source
1892 * pulOut [O] Destination
1894 * RETURNS
1895 * Success: S_OK.
1896 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1898 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
1900 double d = cyIn.int64 / CY_MULTIPLIER_F;
1901 return VarUI4FromR8(d, pulOut);
1904 /************************************************************************
1905 * VarUI4FromStr (OLEAUT32.277)
1907 * Convert a VT_BSTR to a VT_UI4.
1909 * PARAMS
1910 * strIn [I] Source
1911 * lcid [I] LCID for the conversion
1912 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1913 * pulOut [O] Destination
1915 * RETURNS
1916 * Success: S_OK.
1917 * Failure: E_INVALIDARG, if any parameter is invalid
1918 * DISP_E_OVERFLOW, if the value will not fit in the destination
1919 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1921 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
1923 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pulOut, VT_UI4);
1926 /************************************************************************
1927 * VarUI4FromDisp (OLEAUT32.278)
1929 * Convert a VT_DISPATCH to a VT_UI4.
1931 * PARAMS
1932 * pdispIn [I] Source
1933 * lcid [I] LCID for conversion
1934 * pulOut [O] Destination
1936 * RETURNS
1937 * Success: S_OK.
1938 * Failure: E_INVALIDARG, if the source value is invalid
1939 * DISP_E_OVERFLOW, if the value will not fit in the destination
1940 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1942 HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
1944 return VARIANT_FromDisp(pdispIn, lcid, pulOut, VT_UI4);
1947 /************************************************************************
1948 * VarUI4FromBool (OLEAUT32.279)
1950 * Convert a VT_BOOL to a VT_UI4.
1952 * PARAMS
1953 * boolIn [I] Source
1954 * pulOut [O] Destination
1956 * RETURNS
1957 * S_OK.
1959 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
1961 return _VarUI4FromBool(boolIn, pulOut);
1964 /************************************************************************
1965 * VarUI4FromI1 (OLEAUT32.280)
1967 * Convert a VT_I1 to a VT_UI4.
1969 * PARAMS
1970 * cIn [I] Source
1971 * pulOut [O] Destination
1973 * RETURNS
1974 * Success: S_OK.
1975 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1977 HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
1979 return _VarUI4FromI1(cIn, pulOut);
1982 /************************************************************************
1983 * VarUI4FromUI2 (OLEAUT32.281)
1985 * Convert a VT_UI2 to a VT_UI4.
1987 * PARAMS
1988 * usIn [I] Source
1989 * pulOut [O] Destination
1991 * RETURNS
1992 * S_OK.
1994 HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
1996 return _VarUI4FromUI2(usIn, pulOut);
1999 /************************************************************************
2000 * VarUI4FromDec (OLEAUT32.282)
2002 * Convert a VT_DECIMAL to a VT_UI4.
2004 * PARAMS
2005 * pDecIn [I] Source
2006 * pulOut [O] Destination
2008 * RETURNS
2009 * Success: S_OK.
2010 * Failure: E_INVALIDARG, if pdecIn is invalid
2011 * DISP_E_OVERFLOW, if the value will not fit in the destination
2013 HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
2015 LONG64 i64;
2016 HRESULT hRet;
2018 hRet = VarI8FromDec(pdecIn, &i64);
2020 if (SUCCEEDED(hRet))
2021 hRet = _VarUI4FromI8(i64, pulOut);
2022 return hRet;
2025 /************************************************************************
2026 * VarUI4FromI8 (OLEAUT32.425)
2028 * Convert a VT_I8 to a VT_UI4.
2030 * PARAMS
2031 * llIn [I] Source
2032 * pulOut [O] Destination
2034 * RETURNS
2035 * Success: S_OK.
2036 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2038 HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
2040 return _VarUI4FromI8(llIn, pulOut);
2043 /************************************************************************
2044 * VarUI4FromUI8 (OLEAUT32.426)
2046 * Convert a VT_UI8 to a VT_UI4.
2048 * PARAMS
2049 * ullIn [I] Source
2050 * pulOut [O] Destination
2052 * RETURNS
2053 * Success: S_OK.
2054 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2056 HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
2058 return _VarUI4FromUI8(ullIn, pulOut);
2061 /* I8
2064 /************************************************************************
2065 * VarI8FromUI1 (OLEAUT32.333)
2067 * Convert a VT_UI1 to a VT_I8.
2069 * PARAMS
2070 * bIn [I] Source
2071 * pi64Out [O] Destination
2073 * RETURNS
2074 * S_OK.
2076 HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
2078 return _VarI8FromUI1(bIn, pi64Out);
2082 /************************************************************************
2083 * VarI8FromI2 (OLEAUT32.334)
2085 * Convert a VT_I2 to a VT_I8.
2087 * PARAMS
2088 * sIn [I] Source
2089 * pi64Out [O] Destination
2091 * RETURNS
2092 * S_OK.
2094 HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
2096 return _VarI8FromI2(sIn, pi64Out);
2099 /************************************************************************
2100 * VarI8FromR4 (OLEAUT32.335)
2102 * Convert a VT_R4 to a VT_I8.
2104 * PARAMS
2105 * fltIn [I] Source
2106 * pi64Out [O] Destination
2108 * RETURNS
2109 * Success: S_OK.
2110 * Failure: E_INVALIDARG, if the source value is invalid
2111 * DISP_E_OVERFLOW, if the value will not fit in the destination
2113 HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
2115 return VarI8FromR8(fltIn, pi64Out);
2118 /************************************************************************
2119 * VarI8FromR8 (OLEAUT32.336)
2121 * Convert a VT_R8 to a VT_I8.
2123 * PARAMS
2124 * dblIn [I] Source
2125 * pi64Out [O] Destination
2127 * RETURNS
2128 * Success: S_OK.
2129 * Failure: E_INVALIDARG, if the source value is invalid
2130 * DISP_E_OVERFLOW, if the value will not fit in the destination
2132 * NOTES
2133 * Only values that fit into 63 bits are accepted. Due to rounding issues,
2134 * very high or low values will not be accurately converted.
2136 * Numbers are rounded using Dutch rounding, as follows:
2138 *| Fractional Part Sign Direction Example
2139 *| --------------- ---- --------- -------
2140 *| < 0.5 + Down 0.4 -> 0.0
2141 *| < 0.5 - Up -0.4 -> 0.0
2142 *| > 0.5 + Up 0.6 -> 1.0
2143 *| < 0.5 - Up -0.6 -> -1.0
2144 *| = 0.5 + Up/Down Down if even, Up if odd
2145 *| = 0.5 - Up/Down Up if even, Down if odd
2147 * This system is often used in supermarkets.
2149 HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
2151 if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
2152 return DISP_E_OVERFLOW;
2153 VARIANT_DutchRound(LONG64, dblIn, *pi64Out);
2154 return S_OK;
2157 /************************************************************************
2158 * VarI8FromCy (OLEAUT32.337)
2160 * Convert a VT_CY to a VT_I8.
2162 * PARAMS
2163 * cyIn [I] Source
2164 * pi64Out [O] Destination
2166 * RETURNS
2167 * S_OK.
2169 * NOTES
2170 * All negative numbers are rounded down by 1, including those that are
2171 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2172 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2173 * for details.
2175 HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
2177 *pi64Out = cyIn.int64 / CY_MULTIPLIER;
2179 if (cyIn.int64 < 0)
2180 (*pi64Out)--; /* Mimic Win32 bug */
2181 else
2183 cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2185 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
2186 (*pi64Out)++;
2188 return S_OK;
2191 /************************************************************************
2192 * VarI8FromDate (OLEAUT32.338)
2194 * Convert a VT_DATE to a VT_I8.
2196 * PARAMS
2197 * dateIn [I] Source
2198 * pi64Out [O] Destination
2200 * RETURNS
2201 * Success: S_OK.
2202 * Failure: E_INVALIDARG, if the source value is invalid
2203 * DISP_E_OVERFLOW, if the value will not fit in the destination
2204 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2206 HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
2208 return VarI8FromR8(dateIn, pi64Out);
2211 /************************************************************************
2212 * VarI8FromStr (OLEAUT32.339)
2214 * Convert a VT_BSTR to a VT_I8.
2216 * PARAMS
2217 * strIn [I] Source
2218 * lcid [I] LCID for the conversion
2219 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2220 * pi64Out [O] Destination
2222 * RETURNS
2223 * Success: S_OK.
2224 * Failure: E_INVALIDARG, if the source value is invalid
2225 * DISP_E_OVERFLOW, if the value will not fit in the destination
2226 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2228 HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
2230 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pi64Out, VT_I8);
2233 /************************************************************************
2234 * VarI8FromDisp (OLEAUT32.340)
2236 * Convert a VT_DISPATCH to a VT_I8.
2238 * PARAMS
2239 * pdispIn [I] Source
2240 * lcid [I] LCID for conversion
2241 * pi64Out [O] Destination
2243 * RETURNS
2244 * Success: S_OK.
2245 * Failure: E_INVALIDARG, if the source value is invalid
2246 * DISP_E_OVERFLOW, if the value will not fit in the destination
2247 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2249 HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
2251 return VARIANT_FromDisp(pdispIn, lcid, pi64Out, VT_I8);
2254 /************************************************************************
2255 * VarI8FromBool (OLEAUT32.341)
2257 * Convert a VT_BOOL to a VT_I8.
2259 * PARAMS
2260 * boolIn [I] Source
2261 * pi64Out [O] Destination
2263 * RETURNS
2264 * S_OK.
2266 HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
2268 return VarI8FromI2(boolIn, pi64Out);
2271 /************************************************************************
2272 * VarI8FromI1 (OLEAUT32.342)
2274 * Convert a VT_I1 to a VT_I8.
2276 * PARAMS
2277 * cIn [I] Source
2278 * pi64Out [O] Destination
2280 * RETURNS
2281 * S_OK.
2283 HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
2285 return _VarI8FromI1(cIn, pi64Out);
2288 /************************************************************************
2289 * VarI8FromUI2 (OLEAUT32.343)
2291 * Convert a VT_UI2 to a VT_I8.
2293 * PARAMS
2294 * usIn [I] Source
2295 * pi64Out [O] Destination
2297 * RETURNS
2298 * S_OK.
2300 HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
2302 return _VarI8FromUI2(usIn, pi64Out);
2305 /************************************************************************
2306 * VarI8FromUI4 (OLEAUT32.344)
2308 * Convert a VT_UI4 to a VT_I8.
2310 * PARAMS
2311 * ulIn [I] Source
2312 * pi64Out [O] Destination
2314 * RETURNS
2315 * S_OK.
2317 HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
2319 return _VarI8FromUI4(ulIn, pi64Out);
2322 /************************************************************************
2323 * VarI8FromDec (OLEAUT32.345)
2325 * Convert a VT_DECIMAL to a VT_I8.
2327 * PARAMS
2328 * pDecIn [I] Source
2329 * pi64Out [O] Destination
2331 * RETURNS
2332 * Success: S_OK.
2333 * Failure: E_INVALIDARG, if the source value is invalid
2334 * DISP_E_OVERFLOW, if the value will not fit in the destination
2336 HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
2338 if (!DEC_SCALE(pdecIn))
2340 /* This decimal is just a 96 bit integer */
2341 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2342 return E_INVALIDARG;
2344 if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
2345 return DISP_E_OVERFLOW;
2347 if (DEC_SIGN(pdecIn))
2348 *pi64Out = -DEC_LO64(pdecIn);
2349 else
2350 *pi64Out = DEC_LO64(pdecIn);
2351 return S_OK;
2353 else
2355 /* Decimal contains a floating point number */
2356 HRESULT hRet;
2357 double dbl;
2359 hRet = VarR8FromDec(pdecIn, &dbl);
2360 if (SUCCEEDED(hRet))
2361 hRet = VarI8FromR8(dbl, pi64Out);
2362 return hRet;
2366 /************************************************************************
2367 * VarI8FromUI8 (OLEAUT32.427)
2369 * Convert a VT_UI8 to a VT_I8.
2371 * PARAMS
2372 * ullIn [I] Source
2373 * pi64Out [O] Destination
2375 * RETURNS
2376 * Success: S_OK.
2377 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2379 HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
2381 return _VarI8FromUI8(ullIn, pi64Out);
2384 /* UI8
2387 /************************************************************************
2388 * VarUI8FromI8 (OLEAUT32.428)
2390 * Convert a VT_I8 to a VT_UI8.
2392 * PARAMS
2393 * ulIn [I] Source
2394 * pui64Out [O] Destination
2396 * RETURNS
2397 * Success: S_OK.
2398 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2400 HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
2402 return _VarUI8FromI8(llIn, pui64Out);
2405 /************************************************************************
2406 * VarUI8FromUI1 (OLEAUT32.429)
2408 * Convert a VT_UI1 to a VT_UI8.
2410 * PARAMS
2411 * bIn [I] Source
2412 * pui64Out [O] Destination
2414 * RETURNS
2415 * S_OK.
2417 HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
2419 return _VarUI8FromUI1(bIn, pui64Out);
2422 /************************************************************************
2423 * VarUI8FromI2 (OLEAUT32.430)
2425 * Convert a VT_I2 to a VT_UI8.
2427 * PARAMS
2428 * sIn [I] Source
2429 * pui64Out [O] Destination
2431 * RETURNS
2432 * S_OK.
2434 HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
2436 return _VarUI8FromI2(sIn, pui64Out);
2439 /************************************************************************
2440 * VarUI8FromR4 (OLEAUT32.431)
2442 * Convert a VT_R4 to a VT_UI8.
2444 * PARAMS
2445 * fltIn [I] Source
2446 * pui64Out [O] Destination
2448 * RETURNS
2449 * Success: S_OK.
2450 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2452 HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
2454 return VarUI8FromR8(fltIn, pui64Out);
2457 /************************************************************************
2458 * VarUI8FromR8 (OLEAUT32.432)
2460 * Convert a VT_R8 to a VT_UI8.
2462 * PARAMS
2463 * dblIn [I] Source
2464 * pui64Out [O] Destination
2466 * RETURNS
2467 * Success: S_OK.
2468 * Failure: E_INVALIDARG, if the source value is invalid
2469 * DISP_E_OVERFLOW, if the value will not fit in the destination
2471 * NOTES
2472 * See VarI8FromR8() for details concerning rounding.
2474 HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
2476 if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
2477 return DISP_E_OVERFLOW;
2478 VARIANT_DutchRound(ULONG64, dblIn, *pui64Out);
2479 return S_OK;
2482 /************************************************************************
2483 * VarUI8FromCy (OLEAUT32.433)
2485 * Convert a VT_CY to a VT_UI8.
2487 * PARAMS
2488 * cyIn [I] Source
2489 * pui64Out [O] Destination
2491 * RETURNS
2492 * Success: S_OK.
2493 * Failure: E_INVALIDARG, if the source value is invalid
2494 * DISP_E_OVERFLOW, if the value will not fit in the destination
2496 * NOTES
2497 * Negative values >= -5000 will be converted to 0.
2499 HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
2501 if (cyIn.int64 < 0)
2503 if (cyIn.int64 < -CY_HALF)
2504 return DISP_E_OVERFLOW;
2505 *pui64Out = 0;
2507 else
2509 *pui64Out = cyIn.int64 / CY_MULTIPLIER;
2511 cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2513 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
2514 (*pui64Out)++;
2516 return S_OK;
2519 /************************************************************************
2520 * VarUI8FromDate (OLEAUT32.434)
2522 * Convert a VT_DATE to a VT_UI8.
2524 * PARAMS
2525 * dateIn [I] Source
2526 * pui64Out [O] Destination
2528 * RETURNS
2529 * Success: S_OK.
2530 * Failure: E_INVALIDARG, if the source value is invalid
2531 * DISP_E_OVERFLOW, if the value will not fit in the destination
2532 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2534 HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
2536 return VarUI8FromR8(dateIn, pui64Out);
2539 /************************************************************************
2540 * VarUI8FromStr (OLEAUT32.435)
2542 * Convert a VT_BSTR to a VT_UI8.
2544 * PARAMS
2545 * strIn [I] Source
2546 * lcid [I] LCID for the conversion
2547 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2548 * pui64Out [O] Destination
2550 * RETURNS
2551 * Success: S_OK.
2552 * Failure: E_INVALIDARG, if the source value is invalid
2553 * DISP_E_OVERFLOW, if the value will not fit in the destination
2554 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2556 HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
2558 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pui64Out, VT_UI8);
2561 /************************************************************************
2562 * VarUI8FromDisp (OLEAUT32.436)
2564 * Convert a VT_DISPATCH to a VT_UI8.
2566 * PARAMS
2567 * pdispIn [I] Source
2568 * lcid [I] LCID for conversion
2569 * pui64Out [O] Destination
2571 * RETURNS
2572 * Success: S_OK.
2573 * Failure: E_INVALIDARG, if the source value is invalid
2574 * DISP_E_OVERFLOW, if the value will not fit in the destination
2575 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2577 HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
2579 return VARIANT_FromDisp(pdispIn, lcid, pui64Out, VT_UI8);
2582 /************************************************************************
2583 * VarUI8FromBool (OLEAUT32.437)
2585 * Convert a VT_BOOL to a VT_UI8.
2587 * PARAMS
2588 * boolIn [I] Source
2589 * pui64Out [O] Destination
2591 * RETURNS
2592 * Success: S_OK.
2593 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2595 HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
2597 return VarI8FromI2(boolIn, (LONG64 *)pui64Out);
2599 /************************************************************************
2600 * VarUI8FromI1 (OLEAUT32.438)
2602 * Convert a VT_I1 to a VT_UI8.
2604 * PARAMS
2605 * cIn [I] Source
2606 * pui64Out [O] Destination
2608 * RETURNS
2609 * Success: S_OK.
2610 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2612 HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
2614 return _VarUI8FromI1(cIn, pui64Out);
2617 /************************************************************************
2618 * VarUI8FromUI2 (OLEAUT32.439)
2620 * Convert a VT_UI2 to a VT_UI8.
2622 * PARAMS
2623 * usIn [I] Source
2624 * pui64Out [O] Destination
2626 * RETURNS
2627 * S_OK.
2629 HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
2631 return _VarUI8FromUI2(usIn, pui64Out);
2634 /************************************************************************
2635 * VarUI8FromUI4 (OLEAUT32.440)
2637 * Convert a VT_UI4 to a VT_UI8.
2639 * PARAMS
2640 * ulIn [I] Source
2641 * pui64Out [O] Destination
2643 * RETURNS
2644 * S_OK.
2646 HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
2648 return _VarUI8FromUI4(ulIn, pui64Out);
2651 /************************************************************************
2652 * VarUI8FromDec (OLEAUT32.441)
2654 * Convert a VT_DECIMAL to a VT_UI8.
2656 * PARAMS
2657 * pDecIn [I] Source
2658 * pui64Out [O] Destination
2660 * RETURNS
2661 * Success: S_OK.
2662 * Failure: E_INVALIDARG, if the source value is invalid
2663 * DISP_E_OVERFLOW, if the value will not fit in the destination
2665 * NOTES
2666 * Under native Win32, if the source value has a scale of 0, its sign is
2667 * ignored, i.e. this function takes the absolute value rather than fail
2668 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2669 * (use VarAbs() on pDecIn first if you really want this behaviour).
2671 HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
2673 if (!DEC_SCALE(pdecIn))
2675 /* This decimal is just a 96 bit integer */
2676 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2677 return E_INVALIDARG;
2679 if (DEC_HI32(pdecIn))
2680 return DISP_E_OVERFLOW;
2682 if (DEC_SIGN(pdecIn))
2684 WARN("Sign would be ignored under Win32!\n");
2685 return DISP_E_OVERFLOW;
2688 *pui64Out = DEC_LO64(pdecIn);
2689 return S_OK;
2691 else
2693 /* Decimal contains a floating point number */
2694 HRESULT hRet;
2695 double dbl;
2697 hRet = VarR8FromDec(pdecIn, &dbl);
2698 if (SUCCEEDED(hRet))
2699 hRet = VarUI8FromR8(dbl, pui64Out);
2700 return hRet;
2704 /* R4
2707 /************************************************************************
2708 * VarR4FromUI1 (OLEAUT32.68)
2710 * Convert a VT_UI1 to a VT_R4.
2712 * PARAMS
2713 * bIn [I] Source
2714 * pFltOut [O] Destination
2716 * RETURNS
2717 * S_OK.
2719 HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
2721 return _VarR4FromUI1(bIn, pFltOut);
2724 /************************************************************************
2725 * VarR4FromI2 (OLEAUT32.69)
2727 * Convert a VT_I2 to a VT_R4.
2729 * PARAMS
2730 * sIn [I] Source
2731 * pFltOut [O] Destination
2733 * RETURNS
2734 * S_OK.
2736 HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
2738 return _VarR4FromI2(sIn, pFltOut);
2741 /************************************************************************
2742 * VarR4FromI4 (OLEAUT32.70)
2744 * Convert a VT_I4 to a VT_R4.
2746 * PARAMS
2747 * sIn [I] Source
2748 * pFltOut [O] Destination
2750 * RETURNS
2751 * S_OK.
2753 HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
2755 return _VarR4FromI4(lIn, pFltOut);
2758 /************************************************************************
2759 * VarR4FromR8 (OLEAUT32.71)
2761 * Convert a VT_R8 to a VT_R4.
2763 * PARAMS
2764 * dblIn [I] Source
2765 * pFltOut [O] Destination
2767 * RETURNS
2768 * Success: S_OK.
2769 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2771 HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
2773 double d = dblIn < 0.0 ? -dblIn : dblIn;
2774 if (d > R4_MAX) return DISP_E_OVERFLOW;
2775 *pFltOut = dblIn;
2776 return S_OK;
2779 /************************************************************************
2780 * VarR4FromCy (OLEAUT32.72)
2782 * Convert a VT_CY to a VT_R4.
2784 * PARAMS
2785 * cyIn [I] Source
2786 * pFltOut [O] Destination
2788 * RETURNS
2789 * S_OK.
2791 HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
2793 *pFltOut = (double)cyIn.int64 / CY_MULTIPLIER_F;
2794 return S_OK;
2797 /************************************************************************
2798 * VarR4FromDate (OLEAUT32.73)
2800 * Convert a VT_DATE to a VT_R4.
2802 * PARAMS
2803 * dateIn [I] Source
2804 * pFltOut [O] Destination
2806 * RETURNS
2807 * Success: S_OK.
2808 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2810 HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
2812 return VarR4FromR8(dateIn, pFltOut);
2815 /************************************************************************
2816 * VarR4FromStr (OLEAUT32.74)
2818 * Convert a VT_BSTR to a VT_R4.
2820 * PARAMS
2821 * strIn [I] Source
2822 * lcid [I] LCID for the conversion
2823 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2824 * pFltOut [O] Destination
2826 * RETURNS
2827 * Success: S_OK.
2828 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2829 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2831 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
2833 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pFltOut, VT_R4);
2836 /************************************************************************
2837 * VarR4FromDisp (OLEAUT32.75)
2839 * Convert a VT_DISPATCH to a VT_R4.
2841 * PARAMS
2842 * pdispIn [I] Source
2843 * lcid [I] LCID for conversion
2844 * pFltOut [O] Destination
2846 * RETURNS
2847 * Success: S_OK.
2848 * Failure: E_INVALIDARG, if the source value is invalid
2849 * DISP_E_OVERFLOW, if the value will not fit in the destination
2850 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2852 HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
2854 return VARIANT_FromDisp(pdispIn, lcid, pFltOut, VT_R4);
2857 /************************************************************************
2858 * VarR4FromBool (OLEAUT32.76)
2860 * Convert a VT_BOOL to a VT_R4.
2862 * PARAMS
2863 * boolIn [I] Source
2864 * pFltOut [O] Destination
2866 * RETURNS
2867 * S_OK.
2869 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
2871 return VarR4FromI2(boolIn, pFltOut);
2874 /************************************************************************
2875 * VarR4FromI1 (OLEAUT32.213)
2877 * Convert a VT_I1 to a VT_R4.
2879 * PARAMS
2880 * cIn [I] Source
2881 * pFltOut [O] Destination
2883 * RETURNS
2884 * Success: S_OK.
2885 * Failure: E_INVALIDARG, if the source value is invalid
2886 * DISP_E_OVERFLOW, if the value will not fit in the destination
2887 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2889 HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
2891 return _VarR4FromI1(cIn, pFltOut);
2894 /************************************************************************
2895 * VarR4FromUI2 (OLEAUT32.214)
2897 * Convert a VT_UI2 to a VT_R4.
2899 * PARAMS
2900 * usIn [I] Source
2901 * pFltOut [O] Destination
2903 * RETURNS
2904 * Success: S_OK.
2905 * Failure: E_INVALIDARG, if the source value is invalid
2906 * DISP_E_OVERFLOW, if the value will not fit in the destination
2907 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2909 HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
2911 return _VarR4FromUI2(usIn, pFltOut);
2914 /************************************************************************
2915 * VarR4FromUI4 (OLEAUT32.215)
2917 * Convert a VT_UI4 to a VT_R4.
2919 * PARAMS
2920 * ulIn [I] Source
2921 * pFltOut [O] Destination
2923 * RETURNS
2924 * Success: S_OK.
2925 * Failure: E_INVALIDARG, if the source value is invalid
2926 * DISP_E_OVERFLOW, if the value will not fit in the destination
2927 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2929 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
2931 return _VarR4FromUI4(ulIn, pFltOut);
2934 /************************************************************************
2935 * VarR4FromDec (OLEAUT32.216)
2937 * Convert a VT_DECIMAL to a VT_R4.
2939 * PARAMS
2940 * pDecIn [I] Source
2941 * pFltOut [O] Destination
2943 * RETURNS
2944 * Success: S_OK.
2945 * Failure: E_INVALIDARG, if the source value is invalid.
2947 HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
2949 BYTE scale = DEC_SCALE(pDecIn);
2950 int divisor = 1;
2951 double highPart;
2953 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
2954 return E_INVALIDARG;
2956 while (scale--)
2957 divisor *= 10;
2959 if (DEC_SIGN(pDecIn))
2960 divisor = -divisor;
2962 if (DEC_HI32(pDecIn))
2964 highPart = (double)DEC_HI32(pDecIn) / (double)divisor;
2965 highPart *= 4294967296.0F;
2966 highPart *= 4294967296.0F;
2968 else
2969 highPart = 0.0;
2971 *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
2972 return S_OK;
2975 /************************************************************************
2976 * VarR4FromI8 (OLEAUT32.360)
2978 * Convert a VT_I8 to a VT_R4.
2980 * PARAMS
2981 * ullIn [I] Source
2982 * pFltOut [O] Destination
2984 * RETURNS
2985 * S_OK.
2987 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2989 return _VarR4FromI8(llIn, pFltOut);
2992 /************************************************************************
2993 * VarR4FromUI8 (OLEAUT32.361)
2995 * Convert a VT_UI8 to a VT_R4.
2997 * PARAMS
2998 * ullIn [I] Source
2999 * pFltOut [O] Destination
3001 * RETURNS
3002 * S_OK.
3004 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
3006 return _VarR4FromUI8(ullIn, pFltOut);
3009 /************************************************************************
3010 * VarR4CmpR8 (OLEAUT32.316)
3012 * Compare a VT_R4 to a VT_R8.
3014 * PARAMS
3015 * fltLeft [I] Source
3016 * dblRight [I] Value to compare
3018 * RETURNS
3019 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
3020 * equal to or greater than dblRight respectively.
3022 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
3024 if (fltLeft < dblRight)
3025 return VARCMP_LT;
3026 else if (fltLeft > dblRight)
3027 return VARCMP_GT;
3028 return VARCMP_EQ;
3031 /* R8
3034 /************************************************************************
3035 * VarR8FromUI1 (OLEAUT32.78)
3037 * Convert a VT_UI1 to a VT_R8.
3039 * PARAMS
3040 * bIn [I] Source
3041 * pDblOut [O] Destination
3043 * RETURNS
3044 * S_OK.
3046 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
3048 return _VarR8FromUI1(bIn, pDblOut);
3051 /************************************************************************
3052 * VarR8FromI2 (OLEAUT32.79)
3054 * Convert a VT_I2 to a VT_R8.
3056 * PARAMS
3057 * sIn [I] Source
3058 * pDblOut [O] Destination
3060 * RETURNS
3061 * S_OK.
3063 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
3065 return _VarR8FromI2(sIn, pDblOut);
3068 /************************************************************************
3069 * VarR8FromI4 (OLEAUT32.80)
3071 * Convert a VT_I4 to a VT_R8.
3073 * PARAMS
3074 * sIn [I] Source
3075 * pDblOut [O] Destination
3077 * RETURNS
3078 * S_OK.
3080 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
3082 return _VarR8FromI4(lIn, pDblOut);
3085 /************************************************************************
3086 * VarR8FromR4 (OLEAUT32.81)
3088 * Convert a VT_R4 to a VT_R8.
3090 * PARAMS
3091 * fltIn [I] Source
3092 * pDblOut [O] Destination
3094 * RETURNS
3095 * S_OK.
3097 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
3099 return _VarR8FromR4(fltIn, pDblOut);
3102 /************************************************************************
3103 * VarR8FromCy (OLEAUT32.82)
3105 * Convert a VT_CY to a VT_R8.
3107 * PARAMS
3108 * cyIn [I] Source
3109 * pDblOut [O] Destination
3111 * RETURNS
3112 * S_OK.
3114 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
3116 return _VarR8FromCy(cyIn, pDblOut);
3119 /************************************************************************
3120 * VarR8FromDate (OLEAUT32.83)
3122 * Convert a VT_DATE to a VT_R8.
3124 * PARAMS
3125 * dateIn [I] Source
3126 * pDblOut [O] Destination
3128 * RETURNS
3129 * S_OK.
3131 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
3133 return _VarR8FromDate(dateIn, pDblOut);
3136 /************************************************************************
3137 * VarR8FromStr (OLEAUT32.84)
3139 * Convert a VT_BSTR to a VT_R8.
3141 * PARAMS
3142 * strIn [I] Source
3143 * lcid [I] LCID for the conversion
3144 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3145 * pDblOut [O] Destination
3147 * RETURNS
3148 * Success: S_OK.
3149 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3150 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3152 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3154 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDblOut, VT_R8);
3157 /************************************************************************
3158 * VarR8FromDisp (OLEAUT32.85)
3160 * Convert a VT_DISPATCH to a VT_R8.
3162 * PARAMS
3163 * pdispIn [I] Source
3164 * lcid [I] LCID for conversion
3165 * pDblOut [O] Destination
3167 * RETURNS
3168 * Success: S_OK.
3169 * Failure: E_INVALIDARG, if the source value is invalid
3170 * DISP_E_OVERFLOW, if the value will not fit in the destination
3171 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3173 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3175 return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8);
3178 /************************************************************************
3179 * VarR8FromBool (OLEAUT32.86)
3181 * Convert a VT_BOOL to a VT_R8.
3183 * PARAMS
3184 * boolIn [I] Source
3185 * pDblOut [O] Destination
3187 * RETURNS
3188 * S_OK.
3190 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
3192 return VarR8FromI2(boolIn, pDblOut);
3195 /************************************************************************
3196 * VarR8FromI1 (OLEAUT32.217)
3198 * Convert a VT_I1 to a VT_R8.
3200 * PARAMS
3201 * cIn [I] Source
3202 * pDblOut [O] Destination
3204 * RETURNS
3205 * Success: S_OK.
3206 * Failure: E_INVALIDARG, if the source value is invalid
3207 * DISP_E_OVERFLOW, if the value will not fit in the destination
3208 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3210 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3212 return _VarR8FromI1(cIn, pDblOut);
3215 /************************************************************************
3216 * VarR8FromUI2 (OLEAUT32.218)
3218 * Convert a VT_UI2 to a VT_R8.
3220 * PARAMS
3221 * usIn [I] Source
3222 * pDblOut [O] Destination
3224 * RETURNS
3225 * Success: S_OK.
3226 * Failure: E_INVALIDARG, if the source value is invalid
3227 * DISP_E_OVERFLOW, if the value will not fit in the destination
3228 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3230 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3232 return _VarR8FromUI2(usIn, pDblOut);
3235 /************************************************************************
3236 * VarR8FromUI4 (OLEAUT32.219)
3238 * Convert a VT_UI4 to a VT_R8.
3240 * PARAMS
3241 * ulIn [I] Source
3242 * pDblOut [O] Destination
3244 * RETURNS
3245 * Success: S_OK.
3246 * Failure: E_INVALIDARG, if the source value is invalid
3247 * DISP_E_OVERFLOW, if the value will not fit in the destination
3248 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3250 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3252 return _VarR8FromUI4(ulIn, pDblOut);
3255 /************************************************************************
3256 * VarR8FromDec (OLEAUT32.220)
3258 * Convert a VT_DECIMAL to a VT_R8.
3260 * PARAMS
3261 * pDecIn [I] Source
3262 * pDblOut [O] Destination
3264 * RETURNS
3265 * Success: S_OK.
3266 * Failure: E_INVALIDARG, if the source value is invalid.
3268 HRESULT WINAPI VarR8FromDec(DECIMAL* pDecIn, double *pDblOut)
3270 BYTE scale = DEC_SCALE(pDecIn);
3271 double divisor = 1.0, highPart;
3273 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
3274 return E_INVALIDARG;
3276 while (scale--)
3277 divisor *= 10;
3279 if (DEC_SIGN(pDecIn))
3280 divisor = -divisor;
3282 if (DEC_HI32(pDecIn))
3284 highPart = (double)DEC_HI32(pDecIn) / divisor;
3285 highPart *= 4294967296.0F;
3286 highPart *= 4294967296.0F;
3288 else
3289 highPart = 0.0;
3291 *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
3292 return S_OK;
3295 /************************************************************************
3296 * VarR8FromI8 (OLEAUT32.362)
3298 * Convert a VT_I8 to a VT_R8.
3300 * PARAMS
3301 * ullIn [I] Source
3302 * pDblOut [O] Destination
3304 * RETURNS
3305 * S_OK.
3307 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3309 return _VarR8FromI8(llIn, pDblOut);
3312 /************************************************************************
3313 * VarR8FromUI8 (OLEAUT32.363)
3315 * Convert a VT_UI8 to a VT_R8.
3317 * PARAMS
3318 * ullIn [I] Source
3319 * pDblOut [O] Destination
3321 * RETURNS
3322 * S_OK.
3324 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3326 return _VarR8FromUI8(ullIn, pDblOut);
3329 /************************************************************************
3330 * VarR8Pow (OLEAUT32.315)
3332 * Raise a VT_R8 to a power.
3334 * PARAMS
3335 * dblLeft [I] Source
3336 * dblPow [I] Power to raise dblLeft by
3337 * pDblOut [O] Destination
3339 * RETURNS
3340 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3342 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3344 *pDblOut = pow(dblLeft, dblPow);
3345 return S_OK;
3348 /************************************************************************
3349 * VarR8Round (OLEAUT32.317)
3351 * Round a VT_R8 to a given number of decimal points.
3353 * PARAMS
3354 * dblIn [I] Source
3355 * nDig [I] Number of decimal points to round to
3356 * pDblOut [O] Destination for rounded number
3358 * RETURNS
3359 * Success: S_OK. pDblOut is rounded to nDig digits.
3360 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3362 * NOTES
3363 * The native version of this function rounds using the internal
3364 * binary representation of the number. Wine uses the dutch rounding
3365 * convention, so therefore small differences can occur in the value returned.
3366 * MSDN says that you should use your own rounding function if you want
3367 * rounding to be predictable in your application.
3369 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3371 double scale, whole, fract;
3373 if (nDig < 0)
3374 return E_INVALIDARG;
3376 scale = pow(10.0, nDig);
3378 dblIn *= scale;
3379 whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3380 fract = dblIn - whole;
3382 if (fract > 0.5)
3383 dblIn = whole + 1.0;
3384 else if (fract == 0.5)
3385 dblIn = whole + fmod(whole, 2.0);
3386 else if (fract >= 0.0)
3387 dblIn = whole;
3388 else if (fract == -0.5)
3389 dblIn = whole - fmod(whole, 2.0);
3390 else if (fract > -0.5)
3391 dblIn = whole;
3392 else
3393 dblIn = whole - 1.0;
3395 *pDblOut = dblIn / scale;
3396 return S_OK;
3399 /* CY
3402 /* Powers of 10 from 0..4 D.P. */
3403 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3404 CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
3406 /************************************************************************
3407 * VarCyFromUI1 (OLEAUT32.98)
3409 * Convert a VT_UI1 to a VT_CY.
3411 * PARAMS
3412 * bIn [I] Source
3413 * pCyOut [O] Destination
3415 * RETURNS
3416 * Success: S_OK.
3417 * Failure: E_INVALIDARG, if the source value is invalid
3418 * DISP_E_OVERFLOW, if the value will not fit in the destination
3419 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3421 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
3423 return VarCyFromR8(bIn, pCyOut);
3426 /************************************************************************
3427 * VarCyFromI2 (OLEAUT32.99)
3429 * Convert a VT_I2 to a VT_CY.
3431 * PARAMS
3432 * sIn [I] Source
3433 * pCyOut [O] Destination
3435 * RETURNS
3436 * Success: S_OK.
3437 * Failure: E_INVALIDARG, if the source value is invalid
3438 * DISP_E_OVERFLOW, if the value will not fit in the destination
3439 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3441 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
3443 return VarCyFromR8(sIn, pCyOut);
3446 /************************************************************************
3447 * VarCyFromI4 (OLEAUT32.100)
3449 * Convert a VT_I4 to a VT_CY.
3451 * PARAMS
3452 * sIn [I] Source
3453 * pCyOut [O] Destination
3455 * RETURNS
3456 * Success: S_OK.
3457 * Failure: E_INVALIDARG, if the source value is invalid
3458 * DISP_E_OVERFLOW, if the value will not fit in the destination
3459 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3461 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
3463 return VarCyFromR8(lIn, pCyOut);
3466 /************************************************************************
3467 * VarCyFromR4 (OLEAUT32.101)
3469 * Convert a VT_R4 to a VT_CY.
3471 * PARAMS
3472 * fltIn [I] Source
3473 * pCyOut [O] Destination
3475 * RETURNS
3476 * Success: S_OK.
3477 * Failure: E_INVALIDARG, if the source value is invalid
3478 * DISP_E_OVERFLOW, if the value will not fit in the destination
3479 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3481 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
3483 return VarCyFromR8(fltIn, pCyOut);
3486 /************************************************************************
3487 * VarCyFromR8 (OLEAUT32.102)
3489 * Convert a VT_R8 to a VT_CY.
3491 * PARAMS
3492 * dblIn [I] Source
3493 * pCyOut [O] Destination
3495 * RETURNS
3496 * Success: S_OK.
3497 * Failure: E_INVALIDARG, if the source value is invalid
3498 * DISP_E_OVERFLOW, if the value will not fit in the destination
3499 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3501 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3503 #if defined(__GNUC__) && defined(__i386__)
3504 /* This code gives identical results to Win32 on Intel.
3505 * Here we use fp exceptions to catch overflows when storing the value.
3507 static const unsigned short r8_fpcontrol = 0x137f;
3508 static const double r8_multiplier = CY_MULTIPLIER_F;
3509 unsigned short old_fpcontrol, result_fpstatus;
3511 /* Clear exceptions, save the old fp state and load the new state */
3512 __asm__ __volatile__( "fnclex" );
3513 __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
3514 __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
3515 /* Perform the conversion. */
3516 __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
3517 __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
3518 __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
3519 /* Save the resulting fp state, load the old state and clear exceptions */
3520 __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
3521 __asm__ __volatile__( "fnclex" );
3522 __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
3524 if (result_fpstatus & 0x9) /* Overflow | Invalid */
3525 return DISP_E_OVERFLOW;
3526 return S_OK;
3527 #else
3528 /* This version produces slightly different results for boundary cases */
3529 if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3530 return DISP_E_OVERFLOW;
3531 dblIn *= CY_MULTIPLIER_F;
3532 VARIANT_DutchRound(LONG64, dblIn, pCyOut->int64);
3533 #endif
3534 return S_OK;
3537 /************************************************************************
3538 * VarCyFromDate (OLEAUT32.103)
3540 * Convert a VT_DATE to a VT_CY.
3542 * PARAMS
3543 * dateIn [I] Source
3544 * pCyOut [O] Destination
3546 * RETURNS
3547 * Success: S_OK.
3548 * Failure: E_INVALIDARG, if the source value is invalid
3549 * DISP_E_OVERFLOW, if the value will not fit in the destination
3550 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3552 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
3554 return VarCyFromR8(dateIn, pCyOut);
3557 /************************************************************************
3558 * VarCyFromStr (OLEAUT32.104)
3560 * Convert a VT_BSTR to a VT_CY.
3562 * PARAMS
3563 * strIn [I] Source
3564 * lcid [I] LCID for the conversion
3565 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3566 * pCyOut [O] Destination
3568 * RETURNS
3569 * Success: S_OK.
3570 * Failure: E_INVALIDARG, if the source value is invalid
3571 * DISP_E_OVERFLOW, if the value will not fit in the destination
3572 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3574 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
3576 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pCyOut, VT_CY);
3579 /************************************************************************
3580 * VarCyFromDisp (OLEAUT32.105)
3582 * Convert a VT_DISPATCH to a VT_CY.
3584 * PARAMS
3585 * pdispIn [I] Source
3586 * lcid [I] LCID for conversion
3587 * pCyOut [O] Destination
3589 * RETURNS
3590 * Success: S_OK.
3591 * Failure: E_INVALIDARG, if the source value is invalid
3592 * DISP_E_OVERFLOW, if the value will not fit in the destination
3593 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3595 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
3597 return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY);
3600 /************************************************************************
3601 * VarCyFromBool (OLEAUT32.106)
3603 * Convert a VT_BOOL to a VT_CY.
3605 * PARAMS
3606 * boolIn [I] Source
3607 * pCyOut [O] Destination
3609 * RETURNS
3610 * Success: S_OK.
3611 * Failure: E_INVALIDARG, if the source value is invalid
3612 * DISP_E_OVERFLOW, if the value will not fit in the destination
3613 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3615 * NOTES
3616 * While the sign of the boolean is stored in the currency, the value is
3617 * converted to either 0 or 1.
3619 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
3621 return VarCyFromR8(boolIn, pCyOut);
3624 /************************************************************************
3625 * VarCyFromI1 (OLEAUT32.225)
3627 * Convert a VT_I1 to a VT_CY.
3629 * PARAMS
3630 * cIn [I] Source
3631 * pCyOut [O] Destination
3633 * RETURNS
3634 * Success: S_OK.
3635 * Failure: E_INVALIDARG, if the source value is invalid
3636 * DISP_E_OVERFLOW, if the value will not fit in the destination
3637 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3639 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3641 return VarCyFromR8(cIn, pCyOut);
3644 /************************************************************************
3645 * VarCyFromUI2 (OLEAUT32.226)
3647 * Convert a VT_UI2 to a VT_CY.
3649 * PARAMS
3650 * usIn [I] Source
3651 * pCyOut [O] Destination
3653 * RETURNS
3654 * Success: S_OK.
3655 * Failure: E_INVALIDARG, if the source value is invalid
3656 * DISP_E_OVERFLOW, if the value will not fit in the destination
3657 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3659 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
3661 return VarCyFromR8(usIn, pCyOut);
3664 /************************************************************************
3665 * VarCyFromUI4 (OLEAUT32.227)
3667 * Convert a VT_UI4 to a VT_CY.
3669 * PARAMS
3670 * ulIn [I] Source
3671 * pCyOut [O] Destination
3673 * RETURNS
3674 * Success: S_OK.
3675 * Failure: E_INVALIDARG, if the source value is invalid
3676 * DISP_E_OVERFLOW, if the value will not fit in the destination
3677 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3679 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
3681 return VarCyFromR8(ulIn, pCyOut);
3684 /************************************************************************
3685 * VarCyFromDec (OLEAUT32.228)
3687 * Convert a VT_DECIMAL to a VT_CY.
3689 * PARAMS
3690 * pdecIn [I] Source
3691 * pCyOut [O] Destination
3693 * RETURNS
3694 * Success: S_OK.
3695 * Failure: E_INVALIDARG, if the source value is invalid
3696 * DISP_E_OVERFLOW, if the value will not fit in the destination
3697 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3699 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
3701 DECIMAL rounded;
3702 HRESULT hRet;
3704 hRet = VarDecRound(pdecIn, 4, &rounded);
3706 if (SUCCEEDED(hRet))
3708 double d;
3710 if (DEC_HI32(&rounded))
3711 return DISP_E_OVERFLOW;
3713 /* Note: Without the casts this promotes to int64 which loses precision */
3714 d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
3715 if (DEC_SIGN(&rounded))
3716 d = -d;
3717 return VarCyFromR8(d, pCyOut);
3719 return hRet;
3722 /************************************************************************
3723 * VarCyFromI8 (OLEAUT32.366)
3725 * Convert a VT_I8 to a VT_CY.
3727 * PARAMS
3728 * ullIn [I] Source
3729 * pCyOut [O] Destination
3731 * RETURNS
3732 * Success: S_OK.
3733 * Failure: E_INVALIDARG, if the source value is invalid
3734 * DISP_E_OVERFLOW, if the value will not fit in the destination
3735 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3737 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
3739 if (llIn <= (I8_MIN/CY_MULTIPLIER) || llIn >= (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
3740 pCyOut->int64 = llIn * CY_MULTIPLIER;
3741 return S_OK;
3744 /************************************************************************
3745 * VarCyFromUI8 (OLEAUT32.375)
3747 * Convert a VT_UI8 to a VT_CY.
3749 * PARAMS
3750 * ullIn [I] Source
3751 * pCyOut [O] Destination
3753 * RETURNS
3754 * Success: S_OK.
3755 * Failure: E_INVALIDARG, if the source value is invalid
3756 * DISP_E_OVERFLOW, if the value will not fit in the destination
3757 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3759 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
3761 return VarCyFromR8(ullIn, pCyOut);
3764 /************************************************************************
3765 * VarCyAdd (OLEAUT32.299)
3767 * Add one CY to another.
3769 * PARAMS
3770 * cyLeft [I] Source
3771 * cyRight [I] Value to add
3772 * pCyOut [O] Destination
3774 * RETURNS
3775 * Success: S_OK.
3776 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3778 HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
3780 double l,r;
3781 _VarR8FromCy(cyLeft, &l);
3782 _VarR8FromCy(cyRight, &r);
3783 l = l + r;
3784 return VarCyFromR8(l, pCyOut);
3787 /************************************************************************
3788 * VarCyMul (OLEAUT32.303)
3790 * Multiply one CY by another.
3792 * PARAMS
3793 * cyLeft [I] Source
3794 * cyRight [I] Value to multiply by
3795 * pCyOut [O] Destination
3797 * RETURNS
3798 * Success: S_OK.
3799 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3801 HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
3803 double l,r;
3804 _VarR8FromCy(cyLeft, &l);
3805 _VarR8FromCy(cyRight, &r);
3806 l = l * r;
3807 return VarCyFromR8(l, pCyOut);
3810 /************************************************************************
3811 * VarCyMulI4 (OLEAUT32.304)
3813 * Multiply one CY by a VT_I4.
3815 * PARAMS
3816 * cyLeft [I] Source
3817 * lRight [I] Value to multiply by
3818 * pCyOut [O] Destination
3820 * RETURNS
3821 * Success: S_OK.
3822 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3824 HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
3826 double d;
3828 _VarR8FromCy(cyLeft, &d);
3829 d = d * lRight;
3830 return VarCyFromR8(d, pCyOut);
3833 /************************************************************************
3834 * VarCySub (OLEAUT32.305)
3836 * Subtract one CY from another.
3838 * PARAMS
3839 * cyLeft [I] Source
3840 * cyRight [I] Value to subtract
3841 * pCyOut [O] Destination
3843 * RETURNS
3844 * Success: S_OK.
3845 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3847 HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
3849 double l,r;
3850 _VarR8FromCy(cyLeft, &l);
3851 _VarR8FromCy(cyRight, &r);
3852 l = l - r;
3853 return VarCyFromR8(l, pCyOut);
3856 /************************************************************************
3857 * VarCyAbs (OLEAUT32.306)
3859 * Convert a VT_CY into its absolute value.
3861 * PARAMS
3862 * cyIn [I] Source
3863 * pCyOut [O] Destination
3865 * RETURNS
3866 * Success: S_OK. pCyOut contains the absolute value.
3867 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3869 HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
3871 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3872 return DISP_E_OVERFLOW;
3874 pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3875 return S_OK;
3878 /************************************************************************
3879 * VarCyFix (OLEAUT32.307)
3881 * Return the integer part of a VT_CY.
3883 * PARAMS
3884 * cyIn [I] Source
3885 * pCyOut [O] Destination
3887 * RETURNS
3888 * Success: S_OK.
3889 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3891 * NOTES
3892 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3893 * negative numbers away from 0, while this function rounds them towards zero.
3895 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
3897 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3898 pCyOut->int64 *= CY_MULTIPLIER;
3899 return S_OK;
3902 /************************************************************************
3903 * VarCyInt (OLEAUT32.308)
3905 * Return the integer part of a VT_CY.
3907 * PARAMS
3908 * cyIn [I] Source
3909 * pCyOut [O] Destination
3911 * RETURNS
3912 * Success: S_OK.
3913 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3915 * NOTES
3916 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3917 * negative numbers towards 0, while this function rounds them away from zero.
3919 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
3921 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3922 pCyOut->int64 *= CY_MULTIPLIER;
3924 if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3926 pCyOut->int64 -= CY_MULTIPLIER;
3928 return S_OK;
3931 /************************************************************************
3932 * VarCyNeg (OLEAUT32.309)
3934 * Change the sign of a VT_CY.
3936 * PARAMS
3937 * cyIn [I] Source
3938 * pCyOut [O] Destination
3940 * RETURNS
3941 * Success: S_OK.
3942 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3944 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
3946 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3947 return DISP_E_OVERFLOW;
3949 pCyOut->int64 = -cyIn.int64;
3950 return S_OK;
3953 /************************************************************************
3954 * VarCyRound (OLEAUT32.310)
3956 * Change the precision of a VT_CY.
3958 * PARAMS
3959 * cyIn [I] Source
3960 * cDecimals [I] New number of decimals to keep
3961 * pCyOut [O] Destination
3963 * RETURNS
3964 * Success: S_OK.
3965 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3967 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
3969 if (cDecimals < 0)
3970 return E_INVALIDARG;
3972 if (cDecimals > 3)
3974 /* Rounding to more precision than we have */
3975 *pCyOut = cyIn;
3976 return S_OK;
3978 else
3980 double d, div = CY_Divisors[cDecimals];
3982 _VarR8FromCy(cyIn, &d);
3983 d = d * div;
3984 VARIANT_DutchRound(LONGLONG, d, pCyOut->int64)
3985 d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3986 VARIANT_DutchRound(LONGLONG, d, pCyOut->int64)
3987 return S_OK;
3991 /************************************************************************
3992 * VarCyCmp (OLEAUT32.311)
3994 * Compare two VT_CY values.
3996 * PARAMS
3997 * cyLeft [I] Source
3998 * cyRight [I] Value to compare
4000 * RETURNS
4001 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
4002 * compare is less, equal or greater than source respectively.
4003 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4005 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
4007 HRESULT hRet;
4008 CY result;
4010 /* Subtract right from left, and compare the result to 0 */
4011 hRet = VarCySub(cyLeft, cyRight, &result);
4013 if (SUCCEEDED(hRet))
4015 if (result.int64 < 0)
4016 hRet = (HRESULT)VARCMP_LT;
4017 else if (result.int64 > 0)
4018 hRet = (HRESULT)VARCMP_GT;
4019 else
4020 hRet = (HRESULT)VARCMP_EQ;
4022 return hRet;
4025 /************************************************************************
4026 * VarCyCmpR8 (OLEAUT32.312)
4028 * Compare a VT_CY to a double
4030 * PARAMS
4031 * cyLeft [I] Currency Source
4032 * dblRight [I] double to compare to cyLeft
4034 * RETURNS
4035 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
4036 * less than, equal to or greater than cyLeft respectively.
4037 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4039 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
4041 HRESULT hRet;
4042 CY cyRight;
4044 hRet = VarCyFromR8(dblRight, &cyRight);
4046 if (SUCCEEDED(hRet))
4047 hRet = VarCyCmp(cyLeft, cyRight);
4049 return hRet;
4052 /************************************************************************
4053 * VarCyMulI8 (OLEAUT32.329)
4055 * Multiply a VT_CY by a VT_I8.
4057 * PARAMS
4058 * cyLeft [I] Source
4059 * llRight [I] Value to multiply by
4060 * pCyOut [O] Destination
4062 * RETURNS
4063 * Success: S_OK.
4064 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4066 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
4068 double d;
4070 _VarR8FromCy(cyLeft, &d);
4071 d = d * (double)llRight;
4072 return VarCyFromR8(d, pCyOut);
4075 /* DECIMAL
4078 /************************************************************************
4079 * VarDecFromUI1 (OLEAUT32.190)
4081 * Convert a VT_UI1 to a DECIMAL.
4083 * PARAMS
4084 * bIn [I] Source
4085 * pDecOut [O] Destination
4087 * RETURNS
4088 * S_OK.
4090 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
4092 return VarDecFromUI4(bIn, pDecOut);
4095 /************************************************************************
4096 * VarDecFromI2 (OLEAUT32.191)
4098 * Convert a VT_I2 to a DECIMAL.
4100 * PARAMS
4101 * sIn [I] Source
4102 * pDecOut [O] Destination
4104 * RETURNS
4105 * S_OK.
4107 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
4109 return VarDecFromI4(sIn, pDecOut);
4112 /************************************************************************
4113 * VarDecFromI4 (OLEAUT32.192)
4115 * Convert a VT_I4 to a DECIMAL.
4117 * PARAMS
4118 * sIn [I] Source
4119 * pDecOut [O] Destination
4121 * RETURNS
4122 * S_OK.
4124 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
4126 DEC_HI32(pDecOut) = 0;
4127 DEC_MID32(pDecOut) = 0;
4129 if (lIn < 0)
4131 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4132 DEC_LO32(pDecOut) = -lIn;
4134 else
4136 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4137 DEC_LO32(pDecOut) = lIn;
4139 return S_OK;
4142 #define LOCALE_EN_US (MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT))
4144 /************************************************************************
4145 * VarDecFromR4 (OLEAUT32.193)
4147 * Convert a VT_R4 to a DECIMAL.
4149 * PARAMS
4150 * fltIn [I] Source
4151 * pDecOut [O] Destination
4153 * RETURNS
4154 * S_OK.
4156 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
4158 WCHAR buff[256];
4160 sprintfW( buff, szFloatFormatW, fltIn );
4161 return VarDecFromStr(buff, LOCALE_EN_US, 0, pDecOut);
4164 /************************************************************************
4165 * VarDecFromR8 (OLEAUT32.194)
4167 * Convert a VT_R8 to a DECIMAL.
4169 * PARAMS
4170 * dblIn [I] Source
4171 * pDecOut [O] Destination
4173 * RETURNS
4174 * S_OK.
4176 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4178 WCHAR buff[256];
4180 sprintfW( buff, szDoubleFormatW, dblIn );
4181 return VarDecFromStr(buff, LOCALE_EN_US, 0, pDecOut);
4184 /************************************************************************
4185 * VarDecFromDate (OLEAUT32.195)
4187 * Convert a VT_DATE to a DECIMAL.
4189 * PARAMS
4190 * dateIn [I] Source
4191 * pDecOut [O] Destination
4193 * RETURNS
4194 * S_OK.
4196 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
4198 return VarDecFromR8(dateIn, pDecOut);
4201 /************************************************************************
4202 * VarDecFromCy (OLEAUT32.196)
4204 * Convert a VT_CY to a DECIMAL.
4206 * PARAMS
4207 * cyIn [I] Source
4208 * pDecOut [O] Destination
4210 * RETURNS
4211 * S_OK.
4213 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
4215 DEC_HI32(pDecOut) = 0;
4217 /* Note: This assumes 2s complement integer representation */
4218 if (cyIn.s.Hi & 0x80000000)
4220 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4221 DEC_LO64(pDecOut) = -cyIn.int64;
4223 else
4225 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4226 DEC_MID32(pDecOut) = cyIn.s.Hi;
4227 DEC_LO32(pDecOut) = cyIn.s.Lo;
4229 return S_OK;
4232 /************************************************************************
4233 * VarDecFromStr (OLEAUT32.197)
4235 * Convert a VT_BSTR to a DECIMAL.
4237 * PARAMS
4238 * strIn [I] Source
4239 * lcid [I] LCID for the conversion
4240 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4241 * pDecOut [O] Destination
4243 * RETURNS
4244 * Success: S_OK.
4245 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4247 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
4249 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDecOut, VT_DECIMAL);
4252 /************************************************************************
4253 * VarDecFromDisp (OLEAUT32.198)
4255 * Convert a VT_DISPATCH to a DECIMAL.
4257 * PARAMS
4258 * pdispIn [I] Source
4259 * lcid [I] LCID for conversion
4260 * pDecOut [O] Destination
4262 * RETURNS
4263 * Success: S_OK.
4264 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4266 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
4268 return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL);
4271 /************************************************************************
4272 * VarDecFromBool (OLEAUT32.199)
4274 * Convert a VT_BOOL to a DECIMAL.
4276 * PARAMS
4277 * bIn [I] Source
4278 * pDecOut [O] Destination
4280 * RETURNS
4281 * S_OK.
4283 * NOTES
4284 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4286 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
4288 DEC_HI32(pDecOut) = 0;
4289 DEC_MID32(pDecOut) = 0;
4290 if (bIn)
4292 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4293 DEC_LO32(pDecOut) = 1;
4295 else
4297 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4298 DEC_LO32(pDecOut) = 0;
4300 return S_OK;
4303 /************************************************************************
4304 * VarDecFromI1 (OLEAUT32.241)
4306 * Convert a VT_I1 to a DECIMAL.
4308 * PARAMS
4309 * cIn [I] Source
4310 * pDecOut [O] Destination
4312 * RETURNS
4313 * S_OK.
4315 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4317 return VarDecFromI4(cIn, pDecOut);
4320 /************************************************************************
4321 * VarDecFromUI2 (OLEAUT32.242)
4323 * Convert a VT_UI2 to a DECIMAL.
4325 * PARAMS
4326 * usIn [I] Source
4327 * pDecOut [O] Destination
4329 * RETURNS
4330 * S_OK.
4332 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
4334 return VarDecFromUI4(usIn, pDecOut);
4337 /************************************************************************
4338 * VarDecFromUI4 (OLEAUT32.243)
4340 * Convert a VT_UI4 to a DECIMAL.
4342 * PARAMS
4343 * ulIn [I] Source
4344 * pDecOut [O] Destination
4346 * RETURNS
4347 * S_OK.
4349 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
4351 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4352 DEC_HI32(pDecOut) = 0;
4353 DEC_MID32(pDecOut) = 0;
4354 DEC_LO32(pDecOut) = ulIn;
4355 return S_OK;
4358 /************************************************************************
4359 * VarDecFromI8 (OLEAUT32.374)
4361 * Convert a VT_I8 to a DECIMAL.
4363 * PARAMS
4364 * llIn [I] Source
4365 * pDecOut [O] Destination
4367 * RETURNS
4368 * S_OK.
4370 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
4372 PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4374 DEC_HI32(pDecOut) = 0;
4376 /* Note: This assumes 2s complement integer representation */
4377 if (pLi->u.HighPart & 0x80000000)
4379 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4380 DEC_LO64(pDecOut) = -pLi->QuadPart;
4382 else
4384 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4385 DEC_MID32(pDecOut) = pLi->u.HighPart;
4386 DEC_LO32(pDecOut) = pLi->u.LowPart;
4388 return S_OK;
4391 /************************************************************************
4392 * VarDecFromUI8 (OLEAUT32.375)
4394 * Convert a VT_UI8 to a DECIMAL.
4396 * PARAMS
4397 * ullIn [I] Source
4398 * pDecOut [O] Destination
4400 * RETURNS
4401 * S_OK.
4403 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
4405 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4406 DEC_HI32(pDecOut) = 0;
4407 DEC_LO64(pDecOut) = ullIn;
4408 return S_OK;
4411 /* Make two DECIMALS the same scale; used by math functions below */
4412 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4413 const DECIMAL** ppDecRight,
4414 DECIMAL* pDecOut)
4416 static DECIMAL scaleFactor;
4417 DECIMAL decTemp;
4418 int scaleAmount, i;
4419 HRESULT hRet = S_OK;
4421 if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4422 return E_INVALIDARG;
4424 DEC_LO32(&scaleFactor) = 10;
4426 i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4428 if (!scaleAmount)
4429 return S_OK; /* Same scale */
4431 if (scaleAmount > 0)
4433 decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4434 *ppDecRight = pDecOut;
4436 else
4438 decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4439 *ppDecLeft = pDecOut;
4440 i = scaleAmount = -scaleAmount;
4443 if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
4444 return DISP_E_OVERFLOW; /* Can't scale up */
4446 /* Multiply up the value to be scaled by the correct amount */
4447 while (SUCCEEDED(hRet) && i--)
4449 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4450 hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
4451 decTemp = *pDecOut;
4453 DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
4454 return hRet;
4457 /* Add two unsigned 32 bit values with overflow */
4458 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4460 ULARGE_INTEGER ul64;
4462 ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4463 *pulHigh = ul64.u.HighPart;
4464 return ul64.u.LowPart;
4467 /* Subtract two unsigned 32 bit values with underflow */
4468 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4470 int invert = 0;
4471 ULARGE_INTEGER ul64;
4473 ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4474 if (ulLeft < ulRight)
4475 invert = 1;
4477 if (ul64.QuadPart > (ULONG64)*pulHigh)
4478 ul64.QuadPart -= (ULONG64)*pulHigh;
4479 else
4481 ul64.QuadPart -= (ULONG64)*pulHigh;
4482 invert = 1;
4484 if (invert)
4485 ul64.u.HighPart = -ul64.u.HighPart ;
4487 *pulHigh = ul64.u.HighPart;
4488 return ul64.u.LowPart;
4491 /* Multiply two unsigned 32 bit values with overflow */
4492 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4494 ULARGE_INTEGER ul64;
4496 ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4497 *pulHigh = ul64.u.HighPart;
4498 return ul64.u.LowPart;
4501 /* Compare two decimals that have the same scale */
4502 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4504 if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4505 (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4506 return -1;
4507 else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4508 return 0;
4509 return 1;
4512 /************************************************************************
4513 * VarDecAdd (OLEAUT32.177)
4515 * Add one DECIMAL to another.
4517 * PARAMS
4518 * pDecLeft [I] Source
4519 * pDecRight [I] Value to add
4520 * pDecOut [O] Destination
4522 * RETURNS
4523 * Success: S_OK.
4524 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4526 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4528 HRESULT hRet;
4529 DECIMAL scaled;
4531 hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
4533 if (SUCCEEDED(hRet))
4535 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4536 ULONG overflow = 0;
4537 BYTE sign = DECIMAL_POS;
4539 /* Correct for the sign of the result */
4540 if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4542 /* -x + -y : Negative */
4543 sign = DECIMAL_NEG;
4544 goto VarDecAdd_AsPositive;
4546 else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4548 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4550 /* -x + y : Negative if x > y */
4551 if (cmp > 0)
4553 sign = DECIMAL_NEG;
4554 VarDecAdd_AsNegative:
4555 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4556 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4557 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4559 else
4561 VarDecAdd_AsInvertedNegative:
4562 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecRight), DEC_LO32(pDecLeft), &overflow);
4563 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4564 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecRight), DEC_HI32(pDecLeft), &overflow);
4567 else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4569 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4571 /* x + -y : Negative if x <= y */
4572 if (cmp <= 0)
4574 sign = DECIMAL_NEG;
4575 goto VarDecAdd_AsInvertedNegative;
4577 goto VarDecAdd_AsNegative;
4579 else
4581 /* x + y : Positive */
4582 VarDecAdd_AsPositive:
4583 DEC_LO32(pDecOut) = VARIANT_Add(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4584 DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4585 DEC_HI32(pDecOut) = VARIANT_Add(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4588 if (overflow)
4589 return DISP_E_OVERFLOW; /* overflowed */
4591 DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4592 DEC_SIGN(pDecOut) = sign;
4594 return hRet;
4597 /************************************************************************
4598 * VarDecDiv (OLEAUT32.178)
4600 * Divide one DECIMAL by another.
4602 * PARAMS
4603 * pDecLeft [I] Source
4604 * pDecRight [I] Value to divide by
4605 * pDecOut [O] Destination
4607 * RETURNS
4608 * Success: S_OK.
4609 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4611 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4613 FIXME("(%p,%p,%p)-stub!\n",pDecLeft,pDecRight,pDecOut);
4614 return DISP_E_OVERFLOW;
4617 /************************************************************************
4618 * VarDecMul (OLEAUT32.179)
4620 * Multiply one DECIMAL by another.
4622 * PARAMS
4623 * pDecLeft [I] Source
4624 * pDecRight [I] Value to multiply by
4625 * pDecOut [O] Destination
4627 * RETURNS
4628 * Success: S_OK.
4629 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4631 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4633 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4635 if (!DEC_SCALE(pDecLeft) || !DEC_SCALE(pDecRight))
4637 /* At least one term is an integer */
4638 const DECIMAL* pDecInteger = DEC_SCALE(pDecLeft) ? pDecRight : pDecLeft;
4639 const DECIMAL* pDecOperand = DEC_SCALE(pDecLeft) ? pDecLeft : pDecRight;
4640 HRESULT hRet = S_OK;
4641 unsigned int multiplier = DEC_LO32(pDecInteger);
4642 ULONG overflow = 0;
4644 if (DEC_HI32(pDecInteger) || DEC_MID32(pDecInteger))
4646 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4647 return DISP_E_OVERFLOW;
4650 DEC_LO32(pDecOut) = VARIANT_Mul(DEC_LO32(pDecOperand), multiplier, &overflow);
4651 DEC_MID32(pDecOut) = VARIANT_Mul(DEC_MID32(pDecOperand), multiplier, &overflow);
4652 DEC_HI32(pDecOut) = VARIANT_Mul(DEC_HI32(pDecOperand), multiplier, &overflow);
4654 if (overflow)
4655 hRet = DISP_E_OVERFLOW;
4656 else
4658 BYTE sign = DECIMAL_POS;
4660 if (DEC_SIGN(pDecLeft) != DEC_SIGN(pDecRight))
4661 sign = DECIMAL_NEG; /* pos * neg => negative */
4662 DEC_SIGN(pDecOut) = sign;
4663 DEC_SCALE(pDecOut) = DEC_SCALE(pDecOperand);
4665 return hRet;
4667 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4668 return DISP_E_OVERFLOW;
4671 /************************************************************************
4672 * VarDecSub (OLEAUT32.181)
4674 * Subtract one DECIMAL from another.
4676 * PARAMS
4677 * pDecLeft [I] Source
4678 * pDecRight [I] DECIMAL to subtract from pDecLeft
4679 * pDecOut [O] Destination
4681 * RETURNS
4682 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4684 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4686 DECIMAL decRight;
4688 /* Implement as addition of the negative */
4689 VarDecNeg(pDecRight, &decRight);
4690 return VarDecAdd(pDecLeft, &decRight, pDecOut);
4693 /************************************************************************
4694 * VarDecAbs (OLEAUT32.182)
4696 * Convert a DECIMAL into its absolute value.
4698 * PARAMS
4699 * pDecIn [I] Source
4700 * pDecOut [O] Destination
4702 * RETURNS
4703 * S_OK. This function does not fail.
4705 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4707 *pDecOut = *pDecIn;
4708 DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
4709 return S_OK;
4712 /************************************************************************
4713 * VarDecFix (OLEAUT32.187)
4715 * Return the integer portion of a DECIMAL.
4717 * PARAMS
4718 * pDecIn [I] Source
4719 * pDecOut [O] Destination
4721 * RETURNS
4722 * Success: S_OK.
4723 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4725 * NOTES
4726 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4727 * negative numbers away from 0, while this function rounds them towards zero.
4729 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4731 if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
4732 return E_INVALIDARG;
4734 if (!DEC_SCALE(pDecIn))
4736 *pDecOut = *pDecIn; /* Already an integer */
4737 return S_OK;
4740 FIXME("semi-stub!\n");
4741 return DISP_E_OVERFLOW;
4744 /************************************************************************
4745 * VarDecInt (OLEAUT32.188)
4747 * Return the integer portion of a DECIMAL.
4749 * PARAMS
4750 * pDecIn [I] Source
4751 * pDecOut [O] Destination
4753 * RETURNS
4754 * Success: S_OK.
4755 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4757 * NOTES
4758 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4759 * negative numbers towards 0, while this function rounds them away from zero.
4761 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4763 if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
4764 return E_INVALIDARG;
4766 if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
4767 return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
4769 FIXME("semi-stub!\n");
4770 return DISP_E_OVERFLOW;
4773 /************************************************************************
4774 * VarDecNeg (OLEAUT32.189)
4776 * Change the sign of a DECIMAL.
4778 * PARAMS
4779 * pDecIn [I] Source
4780 * pDecOut [O] Destination
4782 * RETURNS
4783 * S_OK. This function does not fail.
4785 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4787 *pDecOut = *pDecIn;
4788 DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
4789 return S_OK;
4792 /************************************************************************
4793 * VarDecRound (OLEAUT32.203)
4795 * Change the precision of a DECIMAL.
4797 * PARAMS
4798 * pDecIn [I] Source
4799 * cDecimals [I] New number of decimals to keep
4800 * pDecOut [O] Destination
4802 * RETURNS
4803 * Success: S_OK. pDecOut contains the rounded value.
4804 * Failure: E_INVALIDARG if any argument is invalid.
4806 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
4808 if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
4809 return E_INVALIDARG;
4811 if (cDecimals >= DEC_SCALE(pDecIn))
4813 *pDecOut = *pDecIn; /* More precision than we have */
4814 return S_OK;
4817 FIXME("semi-stub!\n");
4819 return DISP_E_OVERFLOW;
4822 /************************************************************************
4823 * VarDecCmp (OLEAUT32.204)
4825 * Compare two DECIMAL values.
4827 * PARAMS
4828 * pDecLeft [I] Source
4829 * pDecRight [I] Value to compare
4831 * RETURNS
4832 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4833 * is less than, equal to or greater than pDecRight respectively.
4834 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4836 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
4838 HRESULT hRet;
4839 DECIMAL result;
4841 /* Subtract right from left, and compare the result to 0 */
4842 hRet = VarDecSub(pDecLeft, pDecRight, &result);
4844 if (SUCCEEDED(hRet))
4846 int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
4848 if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
4849 hRet = (HRESULT)VARCMP_LT;
4850 else if (non_zero)
4851 hRet = (HRESULT)VARCMP_GT;
4852 else
4853 hRet = (HRESULT)VARCMP_EQ;
4855 return hRet;
4858 /************************************************************************
4859 * VarDecCmpR8 (OLEAUT32.298)
4861 * Compare a DECIMAL to a double
4863 * PARAMS
4864 * pDecLeft [I] DECIMAL Source
4865 * dblRight [I] double to compare to pDecLeft
4867 * RETURNS
4868 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4869 * is less than, equal to or greater than pDecLeft respectively.
4870 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4872 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
4874 HRESULT hRet;
4875 DECIMAL decRight;
4877 hRet = VarDecFromR8(dblRight, &decRight);
4879 if (SUCCEEDED(hRet))
4880 hRet = VarDecCmp(pDecLeft, &decRight);
4882 return hRet;
4885 /* BOOL
4888 /************************************************************************
4889 * VarBoolFromUI1 (OLEAUT32.118)
4891 * Convert a VT_UI1 to a VT_BOOL.
4893 * PARAMS
4894 * bIn [I] Source
4895 * pBoolOut [O] Destination
4897 * RETURNS
4898 * S_OK.
4900 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
4902 *pBoolOut = bIn ? VARIANT_TRUE : VARIANT_FALSE;
4903 return S_OK;
4906 /************************************************************************
4907 * VarBoolFromI2 (OLEAUT32.119)
4909 * Convert a VT_I2 to a VT_BOOL.
4911 * PARAMS
4912 * sIn [I] Source
4913 * pBoolOut [O] Destination
4915 * RETURNS
4916 * S_OK.
4918 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
4920 *pBoolOut = sIn ? VARIANT_TRUE : VARIANT_FALSE;
4921 return S_OK;
4924 /************************************************************************
4925 * VarBoolFromI4 (OLEAUT32.120)
4927 * Convert a VT_I4 to a VT_BOOL.
4929 * PARAMS
4930 * sIn [I] Source
4931 * pBoolOut [O] Destination
4933 * RETURNS
4934 * S_OK.
4936 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
4938 *pBoolOut = lIn ? VARIANT_TRUE : VARIANT_FALSE;
4939 return S_OK;
4942 /************************************************************************
4943 * VarBoolFromR4 (OLEAUT32.121)
4945 * Convert a VT_R4 to a VT_BOOL.
4947 * PARAMS
4948 * fltIn [I] Source
4949 * pBoolOut [O] Destination
4951 * RETURNS
4952 * S_OK.
4954 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
4956 *pBoolOut = fltIn ? VARIANT_TRUE : VARIANT_FALSE;
4957 return S_OK;
4960 /************************************************************************
4961 * VarBoolFromR8 (OLEAUT32.122)
4963 * Convert a VT_R8 to a VT_BOOL.
4965 * PARAMS
4966 * dblIn [I] Source
4967 * pBoolOut [O] Destination
4969 * RETURNS
4970 * S_OK.
4972 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
4974 *pBoolOut = dblIn ? VARIANT_TRUE : VARIANT_FALSE;
4975 return S_OK;
4978 /************************************************************************
4979 * VarBoolFromDate (OLEAUT32.123)
4981 * Convert a VT_DATE to a VT_BOOL.
4983 * PARAMS
4984 * dateIn [I] Source
4985 * pBoolOut [O] Destination
4987 * RETURNS
4988 * S_OK.
4990 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
4992 *pBoolOut = dateIn ? VARIANT_TRUE : VARIANT_FALSE;
4993 return S_OK;
4996 /************************************************************************
4997 * VarBoolFromCy (OLEAUT32.124)
4999 * Convert a VT_CY to a VT_BOOL.
5001 * PARAMS
5002 * cyIn [I] Source
5003 * pBoolOut [O] Destination
5005 * RETURNS
5006 * S_OK.
5008 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
5010 *pBoolOut = cyIn.int64 ? VARIANT_TRUE : VARIANT_FALSE;
5011 return S_OK;
5014 static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
5016 HRSRC hrsrc;
5018 hrsrc = FindResourceExW( OLEAUT32_hModule, (LPWSTR)RT_STRING,
5019 MAKEINTRESOURCEW((dwId >> 4) + 1), langId );
5020 if (hrsrc)
5022 HGLOBAL hmem = LoadResource( OLEAUT32_hModule, hrsrc );
5024 if (hmem)
5026 const WCHAR *p;
5027 unsigned int i;
5029 p = LockResource( hmem );
5030 for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
5032 memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
5033 lpszDest[*p] = '\0';
5034 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
5035 return TRUE;
5038 return FALSE;
5041 /************************************************************************
5042 * VarBoolFromStr (OLEAUT32.125)
5044 * Convert a VT_BSTR to a VT_BOOL.
5046 * PARAMS
5047 * strIn [I] Source
5048 * lcid [I] LCID for the conversion
5049 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5050 * pBoolOut [O] Destination
5052 * RETURNS
5053 * Success: S_OK.
5054 * Failure: E_INVALIDARG, if pBoolOut is invalid.
5055 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5057 * NOTES
5058 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
5059 * it may contain (in any case mapping) the text "true" or "false".
5060 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
5061 * localised text of "True" or "False" in the language specified by lcid.
5062 * - If none of these matches occur, the string is treated as a numeric string
5063 * and the boolean pBoolOut will be set according to whether the number is zero
5064 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
5065 * - If the text is not numeric and does not match any of the above, then
5066 * DISP_E_TYPEMISMATCH is returned.
5068 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
5070 /* Any VB/VBA programmers out there should recognise these strings... */
5071 static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
5072 static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
5073 WCHAR szBuff[64];
5074 LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5075 HRESULT hRes = S_OK;
5077 if (!strIn || !pBoolOut)
5078 return DISP_E_TYPEMISMATCH;
5080 /* Check if we should be comparing against localised text */
5081 if (dwFlags & VAR_LOCALBOOL)
5083 /* Convert our LCID into a usable value */
5084 lcid = ConvertDefaultLocale(lcid);
5086 langId = LANGIDFROMLCID(lcid);
5088 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
5089 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5091 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
5092 * I don't think this is needed unless any of the localised text strings
5093 * contain characters that can be so mapped. In the event that this is
5094 * true for a given language (possibly some Asian languages), then strIn
5095 * should be mapped here _only_ if langId is an Id for which this can occur.
5099 /* Note that if we are not comparing against localised strings, langId
5100 * will have its default value of LANG_ENGLISH. This allows us to mimic
5101 * the native behaviour of always checking against English strings even
5102 * after we've checked for localised ones.
5104 VarBoolFromStr_CheckLocalised:
5105 if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
5107 /* Compare against localised strings, ignoring case */
5108 if (!strcmpiW(strIn, szBuff))
5110 *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
5111 return hRes;
5113 VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
5114 if (!strcmpiW(strIn, szBuff))
5116 *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
5117 return hRes;
5121 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5123 /* We have checked the localised text, now check English */
5124 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5125 goto VarBoolFromStr_CheckLocalised;
5128 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
5129 if (!strcmpW(strIn, szFalse))
5130 *pBoolOut = VARIANT_FALSE;
5131 else if (!strcmpW(strIn, szTrue))
5132 *pBoolOut = VARIANT_TRUE;
5133 else
5135 double d;
5137 /* If this string is a number, convert it as one */
5138 hRes = VarR8FromStr(strIn, lcid, dwFlags, &d);
5139 if (SUCCEEDED(hRes)) *pBoolOut = d ? VARIANT_TRUE : VARIANT_FALSE;
5141 return hRes;
5144 /************************************************************************
5145 * VarBoolFromDisp (OLEAUT32.126)
5147 * Convert a VT_DISPATCH to a VT_BOOL.
5149 * PARAMS
5150 * pdispIn [I] Source
5151 * lcid [I] LCID for conversion
5152 * pBoolOut [O] Destination
5154 * RETURNS
5155 * Success: S_OK.
5156 * Failure: E_INVALIDARG, if the source value is invalid
5157 * DISP_E_OVERFLOW, if the value will not fit in the destination
5158 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5160 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
5162 return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL);
5165 /************************************************************************
5166 * VarBoolFromI1 (OLEAUT32.233)
5168 * Convert a VT_I1 to a VT_BOOL.
5170 * PARAMS
5171 * cIn [I] Source
5172 * pBoolOut [O] Destination
5174 * RETURNS
5175 * S_OK.
5177 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
5179 *pBoolOut = cIn ? VARIANT_TRUE : VARIANT_FALSE;
5180 return S_OK;
5183 /************************************************************************
5184 * VarBoolFromUI2 (OLEAUT32.234)
5186 * Convert a VT_UI2 to a VT_BOOL.
5188 * PARAMS
5189 * usIn [I] Source
5190 * pBoolOut [O] Destination
5192 * RETURNS
5193 * S_OK.
5195 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
5197 *pBoolOut = usIn ? VARIANT_TRUE : VARIANT_FALSE;
5198 return S_OK;
5201 /************************************************************************
5202 * VarBoolFromUI4 (OLEAUT32.235)
5204 * Convert a VT_UI4 to a VT_BOOL.
5206 * PARAMS
5207 * ulIn [I] Source
5208 * pBoolOut [O] Destination
5210 * RETURNS
5211 * S_OK.
5213 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
5215 *pBoolOut = ulIn ? VARIANT_TRUE : VARIANT_FALSE;
5216 return S_OK;
5219 /************************************************************************
5220 * VarBoolFromDec (OLEAUT32.236)
5222 * Convert a VT_DECIMAL to a VT_BOOL.
5224 * PARAMS
5225 * pDecIn [I] Source
5226 * pBoolOut [O] Destination
5228 * RETURNS
5229 * Success: S_OK.
5230 * Failure: E_INVALIDARG, if pDecIn is invalid.
5232 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
5234 if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
5235 return E_INVALIDARG;
5237 if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
5238 *pBoolOut = VARIANT_TRUE;
5239 else
5240 *pBoolOut = VARIANT_FALSE;
5241 return S_OK;
5244 /************************************************************************
5245 * VarBoolFromI8 (OLEAUT32.370)
5247 * Convert a VT_I8 to a VT_BOOL.
5249 * PARAMS
5250 * ullIn [I] Source
5251 * pBoolOut [O] Destination
5253 * RETURNS
5254 * S_OK.
5256 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
5258 *pBoolOut = llIn ? VARIANT_TRUE : VARIANT_FALSE;
5259 return S_OK;
5262 /************************************************************************
5263 * VarBoolFromUI8 (OLEAUT32.371)
5265 * Convert a VT_UI8 to a VT_BOOL.
5267 * PARAMS
5268 * ullIn [I] Source
5269 * pBoolOut [O] Destination
5271 * RETURNS
5272 * S_OK.
5274 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
5276 *pBoolOut = ullIn ? VARIANT_TRUE : VARIANT_FALSE;
5277 return S_OK;
5280 /* BSTR
5283 /* Write a number from a UI8 and sign */
5284 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
5288 WCHAR ulNextDigit = ulVal % 10;
5290 *szOut-- = '0' + ulNextDigit;
5291 ulVal = (ulVal - ulNextDigit) / 10;
5292 } while (ulVal);
5294 szOut++;
5295 return szOut;
5298 /* Create a (possibly localised) BSTR from a UI8 and sign */
5299 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
5301 WCHAR szConverted[256];
5303 if (dwFlags & VAR_NEGATIVE)
5304 *--szOut = '-';
5306 if (dwFlags & LOCALE_USE_NLS)
5308 /* Format the number for the locale */
5309 szConverted[0] = '\0';
5310 GetNumberFormatW(lcid,
5311 dwFlags & LOCALE_NOUSEROVERRIDE,
5312 szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
5313 szOut = szConverted;
5315 return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
5318 /* Create a (possibly localised) BSTR from a UI8 and sign */
5319 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
5321 WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5323 if (!pbstrOut)
5324 return E_INVALIDARG;
5326 /* Create the basic number string */
5327 *szOut-- = '\0';
5328 szOut = VARIANT_WriteNumber(ulVal, szOut);
5330 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5331 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5332 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5335 /******************************************************************************
5336 * VarBstrFromUI1 (OLEAUT32.108)
5338 * Convert a VT_UI1 to a VT_BSTR.
5340 * PARAMS
5341 * bIn [I] Source
5342 * lcid [I] LCID for the conversion
5343 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5344 * pbstrOut [O] Destination
5346 * RETURNS
5347 * Success: S_OK.
5348 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5349 * E_OUTOFMEMORY, if memory allocation fails.
5351 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5353 return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
5356 /******************************************************************************
5357 * VarBstrFromI2 (OLEAUT32.109)
5359 * Convert a VT_I2 to a VT_BSTR.
5361 * PARAMS
5362 * sIn [I] Source
5363 * lcid [I] LCID for the conversion
5364 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5365 * pbstrOut [O] Destination
5367 * RETURNS
5368 * Success: S_OK.
5369 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5370 * E_OUTOFMEMORY, if memory allocation fails.
5372 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5374 ULONG64 ul64 = sIn;
5376 if (sIn < 0)
5378 ul64 = -sIn;
5379 dwFlags |= VAR_NEGATIVE;
5381 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5384 /******************************************************************************
5385 * VarBstrFromI4 (OLEAUT32.110)
5387 * Convert a VT_I4 to a VT_BSTR.
5389 * PARAMS
5390 * lIn [I] Source
5391 * lcid [I] LCID for the conversion
5392 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5393 * pbstrOut [O] Destination
5395 * RETURNS
5396 * Success: S_OK.
5397 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5398 * E_OUTOFMEMORY, if memory allocation fails.
5400 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5402 ULONG64 ul64 = lIn;
5404 if (lIn < 0)
5406 ul64 = (ULONG)-lIn;
5407 dwFlags |= VAR_NEGATIVE;
5409 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5412 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
5413 BSTR* pbstrOut, LPCWSTR lpszFormat)
5415 WCHAR buff[256];
5417 if (!pbstrOut)
5418 return E_INVALIDARG;
5420 sprintfW( buff, lpszFormat, dblIn );
5422 /* Negative zeroes are disallowed (some applications depend on this).
5423 If buff starts with a minus, and then nothing follows but zeroes
5424 and/or a period, it is a negative zero and is replaced with a
5425 canonical zero. This duplicates native oleaut32 behavior.
5427 if (buff[0] == '-')
5429 const WCHAR szAccept[] = {'0', '.', '\0'};
5430 if (strlenW(buff + 1) == strspnW(buff + 1, szAccept))
5431 { buff[0] = '0'; buff[1] = '\0'; }
5434 TRACE("created string %s\n", debugstr_w(buff));
5435 if (dwFlags & LOCALE_USE_NLS)
5437 WCHAR numbuff[256];
5439 /* Format the number for the locale */
5440 numbuff[0] = '\0';
5441 GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5442 buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
5443 TRACE("created NLS string %s\n", debugstr_w(numbuff));
5444 *pbstrOut = SysAllocString(numbuff);
5446 else
5448 WCHAR lpDecimalSep[16];
5450 /* Native oleaut32 uses the locale-specific decimal separator even in the
5451 absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin
5452 American locales will see "one thousand and one tenth" as "1000,1"
5453 instead of "1000.1" (notice the comma). The following code checks for
5454 the need to replace the decimal separator, and if so, will prepare an
5455 appropriate NUMBERFMTW structure to do the job via GetNumberFormatW().
5457 GetLocaleInfoW(lcid, LOCALE_SDECIMAL, lpDecimalSep, sizeof(lpDecimalSep) / sizeof(WCHAR));
5458 if (lpDecimalSep[0] == '.' && lpDecimalSep[1] == '\0')
5460 /* locale is compatible with English - return original string */
5461 *pbstrOut = SysAllocString(buff);
5463 else
5465 WCHAR *p;
5466 WCHAR numbuff[256];
5467 WCHAR empty[1] = {'\0'};
5468 NUMBERFMTW minFormat;
5470 minFormat.NumDigits = 0;
5471 minFormat.LeadingZero = 0;
5472 minFormat.Grouping = 0;
5473 minFormat.lpDecimalSep = lpDecimalSep;
5474 minFormat.lpThousandSep = empty;
5475 minFormat.NegativeOrder = 1; /* NLS_NEG_LEFT */
5477 /* count number of decimal digits in string */
5478 p = strchrW( buff, '.' );
5479 if (p) minFormat.NumDigits = strlenW(p + 1);
5481 numbuff[0] = '\0';
5482 if (!GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5483 buff, &minFormat, numbuff, sizeof(numbuff) / sizeof(WCHAR)))
5485 WARN("GetNumberFormatW() failed, returning raw number string instead\n");
5486 *pbstrOut = SysAllocString(buff);
5488 else
5490 TRACE("created minimal NLS string %s\n", debugstr_w(numbuff));
5491 *pbstrOut = SysAllocString(numbuff);
5495 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5498 /******************************************************************************
5499 * VarBstrFromR4 (OLEAUT32.111)
5501 * Convert a VT_R4 to a VT_BSTR.
5503 * PARAMS
5504 * fltIn [I] Source
5505 * lcid [I] LCID for the conversion
5506 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5507 * pbstrOut [O] Destination
5509 * RETURNS
5510 * Success: S_OK.
5511 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5512 * E_OUTOFMEMORY, if memory allocation fails.
5514 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5516 return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
5519 /******************************************************************************
5520 * VarBstrFromR8 (OLEAUT32.112)
5522 * Convert a VT_R8 to a VT_BSTR.
5524 * PARAMS
5525 * dblIn [I] Source
5526 * lcid [I] LCID for the conversion
5527 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5528 * pbstrOut [O] Destination
5530 * RETURNS
5531 * Success: S_OK.
5532 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5533 * E_OUTOFMEMORY, if memory allocation fails.
5535 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5537 return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
5540 /******************************************************************************
5541 * VarBstrFromCy [OLEAUT32.113]
5543 * Convert a VT_CY to a VT_BSTR.
5545 * PARAMS
5546 * cyIn [I] Source
5547 * lcid [I] LCID for the conversion
5548 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5549 * pbstrOut [O] Destination
5551 * RETURNS
5552 * Success: S_OK.
5553 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5554 * E_OUTOFMEMORY, if memory allocation fails.
5556 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
5558 WCHAR buff[256];
5559 double dblVal;
5561 if (!pbstrOut)
5562 return E_INVALIDARG;
5564 VarR8FromCy(cyIn, &dblVal);
5565 sprintfW(buff, szDoubleFormatW, dblVal);
5567 if (dwFlags & LOCALE_USE_NLS)
5569 WCHAR cybuff[256];
5571 /* Format the currency for the locale */
5572 cybuff[0] = '\0';
5573 GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5574 buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
5575 *pbstrOut = SysAllocString(cybuff);
5577 else
5578 *pbstrOut = SysAllocString(buff);
5580 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5583 /******************************************************************************
5584 * VarBstrFromDate [OLEAUT32.114]
5586 * Convert a VT_DATE to a VT_BSTR.
5588 * PARAMS
5589 * dateIn [I] Source
5590 * lcid [I] LCID for the conversion
5591 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5592 * pbstrOut [O] Destination
5594 * RETURNS
5595 * Success: S_OK.
5596 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5597 * E_OUTOFMEMORY, if memory allocation fails.
5599 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5601 SYSTEMTIME st;
5602 DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
5603 WCHAR date[128], *time;
5605 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
5607 if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
5608 return E_INVALIDARG;
5610 *pbstrOut = NULL;
5612 if (dwFlags & VAR_CALENDAR_THAI)
5613 st.wYear += 553; /* Use the Thai buddhist calendar year */
5614 else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
5615 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5617 if (dwFlags & LOCALE_USE_NLS)
5618 dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
5619 else
5621 double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
5622 double partial = dateIn - whole;
5624 if (whole == 0.0)
5625 dwFlags |= VAR_TIMEVALUEONLY;
5626 else if (partial < 1e-12)
5627 dwFlags |= VAR_DATEVALUEONLY;
5630 if (dwFlags & VAR_TIMEVALUEONLY)
5631 date[0] = '\0';
5632 else
5633 if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
5634 sizeof(date)/sizeof(WCHAR)))
5635 return E_INVALIDARG;
5637 if (!(dwFlags & VAR_DATEVALUEONLY))
5639 time = date + strlenW(date);
5640 if (time != date)
5641 *time++ = ' ';
5642 if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
5643 sizeof(date)/sizeof(WCHAR)-(time-date)))
5644 return E_INVALIDARG;
5647 *pbstrOut = SysAllocString(date);
5648 if (*pbstrOut)
5649 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5650 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5653 /******************************************************************************
5654 * VarBstrFromBool (OLEAUT32.116)
5656 * Convert a VT_BOOL to a VT_BSTR.
5658 * PARAMS
5659 * boolIn [I] Source
5660 * lcid [I] LCID for the conversion
5661 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5662 * pbstrOut [O] Destination
5664 * RETURNS
5665 * Success: S_OK.
5666 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5667 * E_OUTOFMEMORY, if memory allocation fails.
5669 * NOTES
5670 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5671 * localised text of "True" or "False". To convert a bool into a
5672 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5674 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5676 WCHAR szBuff[64];
5677 DWORD dwResId = IDS_TRUE;
5678 LANGID langId;
5680 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn, lcid, dwFlags, pbstrOut);
5682 if (!pbstrOut)
5683 return E_INVALIDARG;
5685 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5686 * for variant formatting */
5687 switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
5689 case VAR_BOOLONOFF:
5690 dwResId = IDS_ON;
5691 break;
5692 case VAR_BOOLYESNO:
5693 dwResId = IDS_YES;
5694 break;
5695 case VAR_LOCALBOOL:
5696 break;
5697 default:
5698 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
5701 lcid = ConvertDefaultLocale(lcid);
5702 langId = LANGIDFROMLCID(lcid);
5703 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
5704 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5706 if (boolIn == VARIANT_FALSE)
5707 dwResId++; /* Use negative form */
5709 VarBstrFromBool_GetLocalised:
5710 if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
5712 *pbstrOut = SysAllocString(szBuff);
5713 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5716 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5718 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5719 goto VarBstrFromBool_GetLocalised;
5722 /* Should never get here */
5723 WARN("Failed to load bool text!\n");
5724 return E_OUTOFMEMORY;
5727 /******************************************************************************
5728 * VarBstrFromI1 (OLEAUT32.229)
5730 * Convert a VT_I1 to a VT_BSTR.
5732 * PARAMS
5733 * cIn [I] Source
5734 * lcid [I] LCID for the conversion
5735 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5736 * pbstrOut [O] Destination
5738 * RETURNS
5739 * Success: S_OK.
5740 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5741 * E_OUTOFMEMORY, if memory allocation fails.
5743 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5745 ULONG64 ul64 = cIn;
5747 if (cIn < 0)
5749 ul64 = -cIn;
5750 dwFlags |= VAR_NEGATIVE;
5752 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5755 /******************************************************************************
5756 * VarBstrFromUI2 (OLEAUT32.230)
5758 * Convert a VT_UI2 to a VT_BSTR.
5760 * PARAMS
5761 * usIn [I] Source
5762 * lcid [I] LCID for the conversion
5763 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5764 * pbstrOut [O] Destination
5766 * RETURNS
5767 * Success: S_OK.
5768 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5769 * E_OUTOFMEMORY, if memory allocation fails.
5771 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5773 return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
5776 /******************************************************************************
5777 * VarBstrFromUI4 (OLEAUT32.231)
5779 * Convert a VT_UI4 to a VT_BSTR.
5781 * PARAMS
5782 * ulIn [I] Source
5783 * lcid [I] LCID for the conversion
5784 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5785 * pbstrOut [O] Destination
5787 * RETURNS
5788 * Success: S_OK.
5789 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5790 * E_OUTOFMEMORY, if memory allocation fails.
5792 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5794 return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
5797 /******************************************************************************
5798 * VarBstrFromDec (OLEAUT32.232)
5800 * Convert a VT_DECIMAL to a VT_BSTR.
5802 * PARAMS
5803 * pDecIn [I] Source
5804 * lcid [I] LCID for the conversion
5805 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5806 * pbstrOut [O] Destination
5808 * RETURNS
5809 * Success: S_OK.
5810 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5811 * E_OUTOFMEMORY, if memory allocation fails.
5813 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5815 if (!pbstrOut)
5816 return E_INVALIDARG;
5818 if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
5820 WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5822 /* Create the basic number string */
5823 *szOut-- = '\0';
5824 szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
5825 if (DEC_SIGN(pDecIn))
5826 dwFlags |= VAR_NEGATIVE;
5828 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5829 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5830 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5832 FIXME("semi-stub\n");
5833 return E_INVALIDARG;
5836 /************************************************************************
5837 * VarBstrFromI8 (OLEAUT32.370)
5839 * Convert a VT_I8 to a VT_BSTR.
5841 * PARAMS
5842 * llIn [I] Source
5843 * lcid [I] LCID for the conversion
5844 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5845 * pbstrOut [O] Destination
5847 * RETURNS
5848 * Success: S_OK.
5849 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5850 * E_OUTOFMEMORY, if memory allocation fails.
5852 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5854 ULONG64 ul64 = llIn;
5856 if (llIn < 0)
5858 ul64 = -llIn;
5859 dwFlags |= VAR_NEGATIVE;
5861 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5864 /************************************************************************
5865 * VarBstrFromUI8 (OLEAUT32.371)
5867 * Convert a VT_UI8 to a VT_BSTR.
5869 * PARAMS
5870 * ullIn [I] Source
5871 * lcid [I] LCID for the conversion
5872 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5873 * pbstrOut [O] Destination
5875 * RETURNS
5876 * Success: S_OK.
5877 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5878 * E_OUTOFMEMORY, if memory allocation fails.
5880 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5882 return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
5885 /**********************************************************************
5886 * VarBstrCat (OLEAUT32.313)
5888 * Concatenate two BSTR values.
5890 * PARAMS
5891 * pbstrLeft [I] Source
5892 * pbstrRight [I] Value to concatenate
5893 * pbstrOut [O] Destination
5895 * RETURNS
5896 * Success: S_OK.
5897 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5898 * E_OUTOFMEMORY, if memory allocation fails.
5900 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
5902 unsigned int len;
5904 if (!pbstrOut)
5905 return E_INVALIDARG;
5907 len = pbstrLeft ? strlenW(pbstrLeft) : 0;
5908 if (pbstrRight)
5909 len += strlenW(pbstrRight);
5911 *pbstrOut = SysAllocStringLen(NULL, len);
5912 if (!*pbstrOut)
5913 return E_OUTOFMEMORY;
5915 (*pbstrOut)[0] = '\0';
5917 if (pbstrLeft)
5918 strcpyW(*pbstrOut, pbstrLeft);
5920 if (pbstrRight)
5921 strcatW(*pbstrOut, pbstrRight);
5923 return S_OK;
5926 /**********************************************************************
5927 * VarBstrCmp (OLEAUT32.314)
5929 * Compare two BSTR values.
5931 * PARAMS
5932 * pbstrLeft [I] Source
5933 * pbstrRight [I] Value to compare
5934 * lcid [I] LCID for the comparison
5935 * dwFlags [I] Flags to pass directly to CompareStringW().
5937 * RETURNS
5938 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5939 * than, equal to or greater than pbstrRight respectively.
5940 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5941 * in which case VARCMP_EQ is returned.
5943 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
5945 if (!pbstrLeft)
5947 if (!pbstrRight || !*pbstrRight)
5948 return VARCMP_EQ;
5949 return VARCMP_NULL;
5951 else if (!pbstrRight)
5953 if (!*pbstrLeft)
5954 return VARCMP_EQ;
5955 return VARCMP_NULL;
5958 return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
5962 * DATE
5965 /******************************************************************************
5966 * VarDateFromUI1 (OLEAUT32.88)
5968 * Convert a VT_UI1 to a VT_DATE.
5970 * PARAMS
5971 * bIn [I] Source
5972 * pdateOut [O] Destination
5974 * RETURNS
5975 * S_OK.
5977 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
5979 return VarR8FromUI1(bIn, pdateOut);
5982 /******************************************************************************
5983 * VarDateFromI2 (OLEAUT32.89)
5985 * Convert a VT_I2 to a VT_DATE.
5987 * PARAMS
5988 * sIn [I] Source
5989 * pdateOut [O] Destination
5991 * RETURNS
5992 * S_OK.
5994 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
5996 return VarR8FromI2(sIn, pdateOut);
5999 /******************************************************************************
6000 * VarDateFromI4 (OLEAUT32.90)
6002 * Convert a VT_I4 to a VT_DATE.
6004 * PARAMS
6005 * lIn [I] Source
6006 * pdateOut [O] Destination
6008 * RETURNS
6009 * S_OK.
6011 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
6013 return VarDateFromR8(lIn, pdateOut);
6016 /******************************************************************************
6017 * VarDateFromR4 (OLEAUT32.91)
6019 * Convert a VT_R4 to a VT_DATE.
6021 * PARAMS
6022 * fltIn [I] Source
6023 * pdateOut [O] Destination
6025 * RETURNS
6026 * S_OK.
6028 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
6030 return VarR8FromR4(fltIn, pdateOut);
6033 /******************************************************************************
6034 * VarDateFromR8 (OLEAUT32.92)
6036 * Convert a VT_R8 to a VT_DATE.
6038 * PARAMS
6039 * dblIn [I] Source
6040 * pdateOut [O] Destination
6042 * RETURNS
6043 * S_OK.
6045 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
6047 if (dblIn <= (DATE_MIN - 1.0) || dblIn >= (DATE_MAX + 1.0)) return DISP_E_OVERFLOW;
6048 *pdateOut = (DATE)dblIn;
6049 return S_OK;
6052 /**********************************************************************
6053 * VarDateFromDisp (OLEAUT32.95)
6055 * Convert a VT_DISPATCH to a VT_DATE.
6057 * PARAMS
6058 * pdispIn [I] Source
6059 * lcid [I] LCID for conversion
6060 * pdateOut [O] Destination
6062 * RETURNS
6063 * Success: S_OK.
6064 * Failure: E_INVALIDARG, if the source value is invalid
6065 * DISP_E_OVERFLOW, if the value will not fit in the destination
6066 * DISP_E_TYPEMISMATCH, if the type cannot be converted
6068 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
6070 return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE);
6073 /******************************************************************************
6074 * VarDateFromBool (OLEAUT32.96)
6076 * Convert a VT_BOOL to a VT_DATE.
6078 * PARAMS
6079 * boolIn [I] Source
6080 * pdateOut [O] Destination
6082 * RETURNS
6083 * S_OK.
6085 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
6087 return VarR8FromBool(boolIn, pdateOut);
6090 /**********************************************************************
6091 * VarDateFromCy (OLEAUT32.93)
6093 * Convert a VT_CY to a VT_DATE.
6095 * PARAMS
6096 * lIn [I] Source
6097 * pdateOut [O] Destination
6099 * RETURNS
6100 * S_OK.
6102 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
6104 return VarR8FromCy(cyIn, pdateOut);
6107 /* Date string parsing */
6108 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
6109 #define DP_DATESEP 0x02 /* Date separator */
6110 #define DP_MONTH 0x04 /* Month name */
6111 #define DP_AM 0x08 /* AM */
6112 #define DP_PM 0x10 /* PM */
6114 typedef struct tagDATEPARSE
6116 DWORD dwCount; /* Number of fields found so far (maximum 6) */
6117 DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
6118 DWORD dwFlags[6]; /* Flags for each field */
6119 DWORD dwValues[6]; /* Value of each field */
6120 } DATEPARSE;
6122 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
6124 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
6126 /* Determine if a day is valid in a given month of a given year */
6127 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
6129 static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
6131 if (day && month && month < 13)
6133 if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
6134 return TRUE;
6136 return FALSE;
6139 /* Possible orders for 3 numbers making up a date */
6140 #define ORDER_MDY 0x01
6141 #define ORDER_YMD 0x02
6142 #define ORDER_YDM 0x04
6143 #define ORDER_DMY 0x08
6144 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
6146 /* Determine a date for a particular locale, from 3 numbers */
6147 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
6148 DWORD offset, SYSTEMTIME *st)
6150 DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
6152 if (!dp->dwCount)
6154 v1 = 30; /* Default to (Variant) 0 date part */
6155 v2 = 12;
6156 v3 = 1899;
6157 goto VARIANT_MakeDate_OK;
6160 v1 = dp->dwValues[offset + 0];
6161 v2 = dp->dwValues[offset + 1];
6162 if (dp->dwCount == 2)
6164 SYSTEMTIME current;
6165 GetSystemTime(&current);
6166 v3 = current.wYear;
6168 else
6169 v3 = dp->dwValues[offset + 2];
6171 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
6173 /* If one number must be a month (Because a month name was given), then only
6174 * consider orders with the month in that position.
6175 * If we took the current year as 'v3', then only allow a year in that position.
6177 if (dp->dwFlags[offset + 0] & DP_MONTH)
6179 dwAllOrders = ORDER_MDY;
6181 else if (dp->dwFlags[offset + 1] & DP_MONTH)
6183 dwAllOrders = ORDER_DMY;
6184 if (dp->dwCount > 2)
6185 dwAllOrders |= ORDER_YMD;
6187 else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
6189 dwAllOrders = ORDER_YDM;
6191 else
6193 dwAllOrders = ORDER_MDY|ORDER_DMY;
6194 if (dp->dwCount > 2)
6195 dwAllOrders |= (ORDER_YMD|ORDER_YDM);
6198 VARIANT_MakeDate_Start:
6199 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
6201 while (dwAllOrders)
6203 DWORD dwTemp;
6205 if (dwCount == 0)
6207 /* First: Try the order given by iDate */
6208 switch (iDate)
6210 case 0: dwTry = dwAllOrders & ORDER_MDY; break;
6211 case 1: dwTry = dwAllOrders & ORDER_DMY; break;
6212 default: dwTry = dwAllOrders & ORDER_YMD; break;
6215 else if (dwCount == 1)
6217 /* Second: Try all the orders compatible with iDate */
6218 switch (iDate)
6220 case 0: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
6221 case 1: dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
6222 default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
6225 else
6227 /* Finally: Try any remaining orders */
6228 dwTry = dwAllOrders;
6231 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
6233 dwCount++;
6234 if (!dwTry)
6235 continue;
6237 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6239 if (dwTry & ORDER_MDY)
6241 if (VARIANT_IsValidMonthDay(v2,v1,v3))
6243 DATE_SWAP(v1,v2);
6244 goto VARIANT_MakeDate_OK;
6246 dwAllOrders &= ~ORDER_MDY;
6248 if (dwTry & ORDER_YMD)
6250 if (VARIANT_IsValidMonthDay(v3,v2,v1))
6252 DATE_SWAP(v1,v3);
6253 goto VARIANT_MakeDate_OK;
6255 dwAllOrders &= ~ORDER_YMD;
6257 if (dwTry & ORDER_YDM)
6259 if (VARIANT_IsValidMonthDay(v2,v3,v1))
6261 DATE_SWAP(v1,v2);
6262 DATE_SWAP(v2,v3);
6263 goto VARIANT_MakeDate_OK;
6265 dwAllOrders &= ~ORDER_YDM;
6267 if (dwTry & ORDER_DMY)
6269 if (VARIANT_IsValidMonthDay(v1,v2,v3))
6270 goto VARIANT_MakeDate_OK;
6271 dwAllOrders &= ~ORDER_DMY;
6273 if (dwTry & ORDER_MYD)
6275 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6276 if (VARIANT_IsValidMonthDay(v3,v1,v2))
6278 DATE_SWAP(v1,v3);
6279 DATE_SWAP(v2,v3);
6280 goto VARIANT_MakeDate_OK;
6282 dwAllOrders &= ~ORDER_MYD;
6286 if (dp->dwCount == 2)
6288 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6289 v3 = 1; /* 1st of the month */
6290 dwAllOrders = ORDER_YMD|ORDER_MYD;
6291 dp->dwCount = 0; /* Don't return to this code path again */
6292 dwCount = 0;
6293 goto VARIANT_MakeDate_Start;
6296 /* No valid dates were able to be constructed */
6297 return DISP_E_TYPEMISMATCH;
6299 VARIANT_MakeDate_OK:
6301 /* Check that the time part is ok */
6302 if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
6303 return DISP_E_TYPEMISMATCH;
6305 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6306 if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
6307 st->wHour += 12;
6308 else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
6309 st->wHour = 0;
6310 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6312 st->wDay = v1;
6313 st->wMonth = v2;
6314 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6315 * be retrieved from:
6316 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6317 * But Wine doesn't have/use that key as at the time of writing.
6319 st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
6320 TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
6321 return S_OK;
6324 /******************************************************************************
6325 * VarDateFromStr [OLEAUT32.94]
6327 * Convert a VT_BSTR to at VT_DATE.
6329 * PARAMS
6330 * strIn [I] String to convert
6331 * lcid [I] Locale identifier for the conversion
6332 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6333 * pdateOut [O] Destination for the converted value
6335 * RETURNS
6336 * Success: S_OK. pdateOut contains the converted value.
6337 * FAILURE: An HRESULT error code indicating the prolem.
6339 * NOTES
6340 * Any date format that can be created using the date formats from lcid
6341 * (Either from kernel Nls functions, variant conversion or formatting) is a
6342 * valid input to this function. In addition, a few more esoteric formats are
6343 * also supported for compatibility with the native version. The date is
6344 * interpreted according to the date settings in the control panel, unless
6345 * the date is invalid in that format, in which the most compatible format
6346 * that produces a valid date will be used.
6348 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
6350 static const USHORT ParseDateTokens[] =
6352 LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
6353 LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
6354 LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
6355 LOCALE_SMONTHNAME13,
6356 LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
6357 LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
6358 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
6359 LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
6360 LOCALE_SABBREVMONTHNAME13,
6361 LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
6362 LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
6363 LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
6364 LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
6365 LOCALE_SABBREVDAYNAME7,
6366 LOCALE_S1159, LOCALE_S2359
6368 static const BYTE ParseDateMonths[] =
6370 1,2,3,4,5,6,7,8,9,10,11,12,13,
6371 1,2,3,4,5,6,7,8,9,10,11,12,13
6373 size_t i;
6374 BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
6375 DATEPARSE dp;
6376 DWORD dwDateSeps = 0, iDate = 0;
6377 HRESULT hRet = S_OK;
6379 if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
6380 (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
6381 return E_INVALIDARG;
6383 if (!strIn)
6384 return DISP_E_TYPEMISMATCH;
6386 *pdateOut = 0.0;
6388 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
6390 memset(&dp, 0, sizeof(dp));
6392 GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
6393 (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
6394 TRACE("iDate is %ld\n", iDate);
6396 /* Get the month/day/am/pm tokens for this locale */
6397 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6399 WCHAR buff[128];
6400 LCTYPE lctype = ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
6402 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6403 * GetAltMonthNames(). We should really cache these strings too.
6405 buff[0] = '\0';
6406 GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
6407 tokens[i] = SysAllocString(buff);
6408 TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
6411 /* Parse the string into our structure */
6412 while (*strIn)
6414 if (dp.dwCount > 6)
6415 break;
6417 if (isdigitW(*strIn))
6419 dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
6420 dp.dwCount++;
6421 strIn--;
6423 else if (isalpha(*strIn))
6425 BOOL bFound = FALSE;
6427 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6429 DWORD dwLen = strlenW(tokens[i]);
6430 if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
6432 if (i <= 25)
6434 dp.dwValues[dp.dwCount] = ParseDateMonths[i];
6435 dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
6436 dp.dwCount++;
6438 else if (i > 39)
6440 if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
6441 hRet = DISP_E_TYPEMISMATCH;
6442 else
6444 dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
6445 dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
6448 strIn += (dwLen - 1);
6449 bFound = TRUE;
6450 break;
6454 if (!bFound)
6456 if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
6457 (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6459 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6460 if (*strIn == 'a' || *strIn == 'A')
6462 dp.dwFlags[dp.dwCount - 1] |= DP_AM;
6463 dp.dwParseFlags |= DP_AM;
6465 else
6467 dp.dwFlags[dp.dwCount - 1] |= DP_PM;
6468 dp.dwParseFlags |= DP_PM;
6470 strIn++;
6472 else
6474 TRACE("No matching token for %s\n", debugstr_w(strIn));
6475 hRet = DISP_E_TYPEMISMATCH;
6476 break;
6480 else if (*strIn == ':' || *strIn == '.')
6482 if (!dp.dwCount || !strIn[1])
6483 hRet = DISP_E_TYPEMISMATCH;
6484 else
6485 dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
6487 else if (*strIn == '-' || *strIn == '/')
6489 dwDateSeps++;
6490 if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
6491 hRet = DISP_E_TYPEMISMATCH;
6492 else
6493 dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
6495 else if (*strIn == ',' || isspaceW(*strIn))
6497 if (*strIn == ',' && !strIn[1])
6498 hRet = DISP_E_TYPEMISMATCH;
6500 else
6502 hRet = DISP_E_TYPEMISMATCH;
6504 strIn++;
6507 if (!dp.dwCount || dp.dwCount > 6 ||
6508 (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6509 hRet = DISP_E_TYPEMISMATCH;
6511 if (SUCCEEDED(hRet))
6513 SYSTEMTIME st;
6514 DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
6516 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
6518 /* Figure out which numbers correspond to which fields.
6520 * This switch statement works based on the fact that native interprets any
6521 * fields that are not joined with a time separator ('.' or ':') as date
6522 * fields. Thus we construct a value from 0-32 where each set bit indicates
6523 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6524 * For valid permutations, we set dwOffset to point to the first date field
6525 * and shorten dp.dwCount by the number of time fields found. The real
6526 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6527 * each date number must represent in the context of iDate.
6529 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6531 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6533 case 0x1: /* TT TTDD TTDDD */
6534 if (dp.dwCount > 3 &&
6535 ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
6536 (dp.dwFlags[4] & (DP_AM|DP_PM))))
6537 hRet = DISP_E_TYPEMISMATCH;
6538 else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
6539 hRet = DISP_E_TYPEMISMATCH;
6540 st.wHour = dp.dwValues[0];
6541 st.wMinute = dp.dwValues[1];
6542 dp.dwCount -= 2;
6543 dwOffset = 2;
6544 break;
6546 case 0x3: /* TTT TTTDD TTTDDD */
6547 if (dp.dwCount > 4 &&
6548 ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
6549 (dp.dwFlags[5] & (DP_AM|DP_PM))))
6550 hRet = DISP_E_TYPEMISMATCH;
6551 else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
6552 hRet = DISP_E_TYPEMISMATCH;
6553 st.wHour = dp.dwValues[0];
6554 st.wMinute = dp.dwValues[1];
6555 st.wSecond = dp.dwValues[2];
6556 dwOffset = 3;
6557 dp.dwCount -= 3;
6558 break;
6560 case 0x4: /* DDTT */
6561 if (dp.dwCount != 4 ||
6562 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6563 hRet = DISP_E_TYPEMISMATCH;
6565 st.wHour = dp.dwValues[2];
6566 st.wMinute = dp.dwValues[3];
6567 dp.dwCount -= 2;
6568 break;
6570 case 0x0: /* T DD DDD TDDD TDDD */
6571 if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
6573 st.wHour = dp.dwValues[0]; /* T */
6574 dp.dwCount = 0;
6575 break;
6577 else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
6579 hRet = DISP_E_TYPEMISMATCH;
6581 else if (dp.dwCount == 3)
6583 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
6585 dp.dwCount = 2;
6586 st.wHour = dp.dwValues[0];
6587 dwOffset = 1;
6588 break;
6590 if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
6592 dp.dwCount = 2;
6593 st.wHour = dp.dwValues[2];
6594 break;
6596 else if (dp.dwParseFlags & (DP_AM|DP_PM))
6597 hRet = DISP_E_TYPEMISMATCH;
6599 else if (dp.dwCount == 4)
6601 dp.dwCount = 3;
6602 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
6604 st.wHour = dp.dwValues[0];
6605 dwOffset = 1;
6607 else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
6609 st.wHour = dp.dwValues[3];
6611 else
6612 hRet = DISP_E_TYPEMISMATCH;
6613 break;
6615 /* .. fall through .. */
6617 case 0x8: /* DDDTT */
6618 if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
6619 (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
6620 (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
6621 dp.dwCount == 4 || dp.dwCount == 6)
6622 hRet = DISP_E_TYPEMISMATCH;
6623 st.wHour = dp.dwValues[3];
6624 st.wMinute = dp.dwValues[4];
6625 if (dp.dwCount == 5)
6626 dp.dwCount -= 2;
6627 break;
6629 case 0xC: /* DDTTT */
6630 if (dp.dwCount != 5 ||
6631 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6632 hRet = DISP_E_TYPEMISMATCH;
6633 st.wHour = dp.dwValues[2];
6634 st.wMinute = dp.dwValues[3];
6635 st.wSecond = dp.dwValues[4];
6636 dp.dwCount -= 3;
6637 break;
6639 case 0x18: /* DDDTTT */
6640 if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
6641 (dp.dwFlags[2] & (DP_AM|DP_PM)))
6642 hRet = DISP_E_TYPEMISMATCH;
6643 st.wHour = dp.dwValues[3];
6644 st.wMinute = dp.dwValues[4];
6645 st.wSecond = dp.dwValues[5];
6646 dp.dwCount -= 3;
6647 break;
6649 default:
6650 hRet = DISP_E_TYPEMISMATCH;
6651 break;
6654 if (SUCCEEDED(hRet))
6656 hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
6658 if (dwFlags & VAR_TIMEVALUEONLY)
6660 st.wYear = 1899;
6661 st.wMonth = 12;
6662 st.wDay = 30;
6664 else if (dwFlags & VAR_DATEVALUEONLY)
6665 st.wHour = st.wMinute = st.wSecond = 0;
6667 /* Finally, convert the value to a VT_DATE */
6668 if (SUCCEEDED(hRet))
6669 hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
6673 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6674 SysFreeString(tokens[i]);
6675 return hRet;
6678 /******************************************************************************
6679 * VarDateFromI1 (OLEAUT32.221)
6681 * Convert a VT_I1 to a VT_DATE.
6683 * PARAMS
6684 * cIn [I] Source
6685 * pdateOut [O] Destination
6687 * RETURNS
6688 * S_OK.
6690 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
6692 return VarR8FromI1(cIn, pdateOut);
6695 /******************************************************************************
6696 * VarDateFromUI2 (OLEAUT32.222)
6698 * Convert a VT_UI2 to a VT_DATE.
6700 * PARAMS
6701 * uiIn [I] Source
6702 * pdateOut [O] Destination
6704 * RETURNS
6705 * S_OK.
6707 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
6709 return VarR8FromUI2(uiIn, pdateOut);
6712 /******************************************************************************
6713 * VarDateFromUI4 (OLEAUT32.223)
6715 * Convert a VT_UI4 to a VT_DATE.
6717 * PARAMS
6718 * ulIn [I] Source
6719 * pdateOut [O] Destination
6721 * RETURNS
6722 * S_OK.
6724 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
6726 return VarDateFromR8(ulIn, pdateOut);
6729 /**********************************************************************
6730 * VarDateFromDec (OLEAUT32.224)
6732 * Convert a VT_DECIMAL to a VT_DATE.
6734 * PARAMS
6735 * pdecIn [I] Source
6736 * pdateOut [O] Destination
6738 * RETURNS
6739 * S_OK.
6741 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
6743 return VarR8FromDec(pdecIn, pdateOut);
6746 /******************************************************************************
6747 * VarDateFromI8 (OLEAUT32.364)
6749 * Convert a VT_I8 to a VT_DATE.
6751 * PARAMS
6752 * llIn [I] Source
6753 * pdateOut [O] Destination
6755 * RETURNS
6756 * Success: S_OK.
6757 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6759 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
6761 if (llIn < DATE_MIN || llIn > DATE_MAX) return DISP_E_OVERFLOW;
6762 *pdateOut = (DATE)llIn;
6763 return S_OK;
6766 /******************************************************************************
6767 * VarDateFromUI8 (OLEAUT32.365)
6769 * Convert a VT_UI8 to a VT_DATE.
6771 * PARAMS
6772 * ullIn [I] Source
6773 * pdateOut [O] Destination
6775 * RETURNS
6776 * Success: S_OK.
6777 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6779 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
6781 if (ullIn > DATE_MAX) return DISP_E_OVERFLOW;
6782 *pdateOut = (DATE)ullIn;
6783 return S_OK;