ReactOS 0.4.17-dev-609-gc4517f4
vartype.c
Go to the documentation of this file.
1/*
2 * Low level variant functions
3 *
4 * Copyright 2003 Jon Griffiths
5 *
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.
10 *
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.
15 *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#define COBJMACROS
22#include "wine/debug.h"
23#include "winbase.h"
24#include "winuser.h"
25#include "winnt.h"
26#include "variant.h"
27#include "resource.h"
28
29#include "locale.h"
30
32
33extern HMODULE hProxyDll;
34
35#define CY_MULTIPLIER 10000 /* 4 dp of precision */
36#define CY_MULTIPLIER_F 10000.0
37#define CY_HALF (CY_MULTIPLIER/2) /* 0.5 */
38#define CY_HALF_F (CY_MULTIPLIER_F/2.0)
39
40/* Copy data from one variant to another. */
41static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
42{
43 switch (vt)
44 {
45 case VT_I1:
46 case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
47 case VT_BOOL:
48 case VT_I2:
49 case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
50 case VT_R4:
51 case VT_INT:
52 case VT_I4:
53 case VT_UINT:
54 case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
55 case VT_R8:
56 case VT_DATE:
57 case VT_CY:
58 case VT_I8:
59 case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
60 case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
61 case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
62 case VT_BSTR: memcpy(pOut, &V_BSTR(srcVar), sizeof(BSTR)); break;
63 default:
64 FIXME("VT_ type %d unhandled, please report!\n", vt);
65 }
66}
67
68/* Macro to inline conversion from a float or double to any integer type,
69 * rounding according to the 'dutch' convention.
70 */
71#define VARIANT_DutchRound(typ, value, res) do { \
72 double whole = value < 0 ? ceil(value) : floor(value); \
73 double fract = value - whole; \
74 if (fract > 0.5) res = (typ)whole + (typ)1; \
75 else if (fract == 0.5) { typ is_odd = (typ)whole & 1; res = whole + is_odd; } \
76 else if (fract >= 0.0) res = (typ)whole; \
77 else if (fract == -0.5) { typ is_odd = (typ)whole & 1; res = whole - is_odd; } \
78 else if (fract > -0.5) res = (typ)whole; \
79 else res = (typ)whole - (typ)1; \
80} while(0)
81
82
83/* Coerce VT_BSTR to a numeric type */
84static HRESULT VARIANT_NumberFromBstr(const OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
85 void* pOut, VARTYPE vt)
86{
87 VARIANTARG dstVar;
88 HRESULT hRet;
89 NUMPARSE np;
90 BYTE rgb[1024];
91
92 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
93 np.cDig = ARRAY_SIZE(rgb);
95
96 hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
97
98 if (SUCCEEDED(hRet))
99 {
100 /* 1 << vt gives us the VTBIT constant for the destination number type */
101 hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
102 if (SUCCEEDED(hRet))
103 VARIANT_CopyData(&dstVar, vt, pOut);
104 }
105 return hRet;
106}
107
108/* Coerce VT_DISPATCH to another type */
109static HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut,
111{
112 static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
113 VARIANTARG srcVar, dstVar;
114 HRESULT hRet;
115
116 if (!pdispIn)
117 return DISP_E_BADVARTYPE;
118
119 /* Get the default 'value' property from the IDispatch */
120 VariantInit(&srcVar);
121 hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
122 &emptyParams, &srcVar, NULL, NULL);
123
124 if (SUCCEEDED(hRet))
125 {
126 /* Convert the property to the requested type */
127 VariantInit(&dstVar);
128 hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, dwFlags, vt);
129 VariantClear(&srcVar);
130
131 if (SUCCEEDED(hRet))
132 VARIANT_CopyData(&dstVar, vt, pOut);
133 }
134 else
135 hRet = DISP_E_TYPEMISMATCH;
136 return hRet;
137}
138
139/* Inline return type */
140#define RETTYP static inline HRESULT
141
142
143/* Simple compiler cast from one type to another */
144#define SIMPLE(dest, src, func) RETTYP _##func(src in, dest* out) { \
145 *out = in; return S_OK; }
146
147/* Compiler cast where input cannot be negative */
148#define NEGTST(dest, src, func) RETTYP _##func(src in, dest* out) { \
149 if (in < 0) { return DISP_E_OVERFLOW; } *out = in; return S_OK; }
150
151/* Compiler cast where input cannot be > some number */
152#define POSTST(dest, src, func, tst) RETTYP _##func(src in, dest* out) { \
153 if (in > (dest)tst) { return DISP_E_OVERFLOW; } *out = in; return S_OK; }
154
155/* Compiler cast where input cannot be < some number or >= some other number */
156#define BOTHTST(dest, src, func, lo, hi) RETTYP _##func(src in, dest* out) { \
157 if (in < (dest)lo || in > hi) { return DISP_E_OVERFLOW; } *out = in; return S_OK; }
158
159/* I1 */
160POSTST(signed char, BYTE, VarI1FromUI1, I1_MAX)
161BOTHTST(signed char, SHORT, VarI1FromI2, I1_MIN, I1_MAX)
162BOTHTST(signed char, LONG, VarI1FromI4, I1_MIN, I1_MAX)
163SIMPLE(signed char, VARIANT_BOOL, VarI1FromBool)
164POSTST(signed char, USHORT, VarI1FromUI2, I1_MAX)
165POSTST(signed char, ULONG, VarI1FromUI4, I1_MAX)
166BOTHTST(signed char, LONG64, VarI1FromI8, I1_MIN, I1_MAX)
167POSTST(signed char, ULONG64, VarI1FromUI8, I1_MAX)
168
169/* UI1 */
172NEGTST(BYTE, signed char, VarUI1FromI1)
178
179/* I2 */
183SIMPLE(SHORT, signed char, VarI2FromI1)
188
189/* UI2 */
194NEGTST(USHORT, signed char, VarUI2FromI1)
198
199/* I4 */
203SIMPLE(LONG, signed char, VarI4FromI1)
208
209/* UI4 */
214NEGTST(ULONG, signed char, VarUI4FromI1)
218
219/* I8 */
222SIMPLE(LONG64, signed char, VarI8FromI1)
226
227/* UI8 */
230NEGTST(ULONG64, signed char, VarUI8FromI1)
234
235/* R4 (float) */
236SIMPLE(float, BYTE, VarR4FromUI1)
237SIMPLE(float, SHORT, VarR4FromI2)
238SIMPLE(float, signed char, VarR4FromI1)
240SIMPLE(float, LONG, VarR4FromI4)
244
245/* R8 (double) */
246SIMPLE(double, BYTE, VarR8FromUI1)
247SIMPLE(double, SHORT, VarR8FromI2)
248SIMPLE(double, float, VarR8FromR4)
249RETTYP _VarR8FromCy(CY i, double* o) { *o = (double)i.int64 / CY_MULTIPLIER_F; return S_OK; }
250SIMPLE(double, DATE, VarR8FromDate)
251SIMPLE(double, signed char, VarR8FromI1)
252SIMPLE(double, USHORT, VarR8FromUI2)
253SIMPLE(double, LONG, VarR8FromI4)
254SIMPLE(double, ULONG, VarR8FromUI4)
255SIMPLE(double, LONG64, VarR8FromI8)
257
258
259/* I1
260 */
261
262/************************************************************************
263 * VarI1FromUI1 (OLEAUT32.244)
264 *
265 * Convert a VT_UI1 to a VT_I1.
266 *
267 * PARAMS
268 * bIn [I] Source
269 * pcOut [O] Destination
270 *
271 * RETURNS
272 * Success: S_OK.
273 * Failure: E_INVALIDARG, if the source value is invalid
274 * DISP_E_OVERFLOW, if the value will not fit in the destination
275 */
276HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
277{
278 return _VarI1FromUI1(bIn, pcOut);
279}
280
281/************************************************************************
282 * VarI1FromI2 (OLEAUT32.245)
283 *
284 * Convert a VT_I2 to a VT_I1.
285 *
286 * PARAMS
287 * sIn [I] Source
288 * pcOut [O] Destination
289 *
290 * RETURNS
291 * Success: S_OK.
292 * Failure: E_INVALIDARG, if the source value is invalid
293 * DISP_E_OVERFLOW, if the value will not fit in the destination
294 */
295HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
296{
297 return _VarI1FromI2(sIn, pcOut);
298}
299
300/************************************************************************
301 * VarI1FromI4 (OLEAUT32.246)
302 *
303 * Convert a VT_I4 to a VT_I1.
304 *
305 * PARAMS
306 * iIn [I] Source
307 * pcOut [O] Destination
308 *
309 * RETURNS
310 * Success: S_OK.
311 * Failure: E_INVALIDARG, if the source value is invalid
312 * DISP_E_OVERFLOW, if the value will not fit in the destination
313 */
314HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
315{
316 return _VarI1FromI4(iIn, pcOut);
317}
318
319/************************************************************************
320 * VarI1FromR4 (OLEAUT32.247)
321 *
322 * Convert a VT_R4 to a VT_I1.
323 *
324 * PARAMS
325 * fltIn [I] Source
326 * pcOut [O] Destination
327 *
328 * RETURNS
329 * Success: S_OK.
330 * Failure: E_INVALIDARG, if the source value is invalid
331 * DISP_E_OVERFLOW, if the value will not fit in the destination
332 */
333HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
334{
335 return VarI1FromR8(fltIn, pcOut);
336}
337
338/************************************************************************
339 * VarI1FromR8 (OLEAUT32.248)
340 *
341 * Convert a VT_R8 to a VT_I1.
342 *
343 * PARAMS
344 * dblIn [I] Source
345 * pcOut [O] Destination
346 *
347 * RETURNS
348 * Success: S_OK.
349 * Failure: E_INVALIDARG, if the source value is invalid
350 * DISP_E_OVERFLOW, if the value will not fit in the destination
351 *
352 * NOTES
353 * See VarI8FromR8() for details concerning rounding.
354 */
355HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
356{
357 if (dblIn < I1_MIN - 0.5 || dblIn >= I1_MAX + 0.5)
358 return DISP_E_OVERFLOW;
359 VARIANT_DutchRound(CHAR, dblIn, *pcOut);
360 return S_OK;
361}
362
363/************************************************************************
364 * VarI1FromDate (OLEAUT32.249)
365 *
366 * Convert a VT_DATE to a VT_I1.
367 *
368 * PARAMS
369 * dateIn [I] Source
370 * pcOut [O] Destination
371 *
372 * RETURNS
373 * Success: S_OK.
374 * Failure: E_INVALIDARG, if the source value is invalid
375 * DISP_E_OVERFLOW, if the value will not fit in the destination
376 */
377HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
378{
379 return VarI1FromR8(dateIn, pcOut);
380}
381
382/************************************************************************
383 * VarI1FromCy (OLEAUT32.250)
384 *
385 * Convert a VT_CY to a VT_I1.
386 *
387 * PARAMS
388 * cyIn [I] Source
389 * pcOut [O] Destination
390 *
391 * RETURNS
392 * Success: S_OK.
393 * Failure: E_INVALIDARG, if the source value is invalid
394 * DISP_E_OVERFLOW, if the value will not fit in the destination
395 */
396HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
397{
398 LONG i = I1_MAX + 1;
399
400 VarI4FromCy(cyIn, &i);
401 return _VarI1FromI4(i, pcOut);
402}
403
404/************************************************************************
405 * VarI1FromStr (OLEAUT32.251)
406 *
407 * Convert a VT_BSTR to a VT_I1.
408 *
409 * PARAMS
410 * strIn [I] Source
411 * lcid [I] LCID for the conversion
412 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
413 * pcOut [O] Destination
414 *
415 * RETURNS
416 * Success: S_OK.
417 * Failure: E_INVALIDARG, if the source value is invalid
418 * DISP_E_OVERFLOW, if the value will not fit in the destination
419 * DISP_E_TYPEMISMATCH, if the type cannot be converted
420 */
421HRESULT WINAPI VarI1FromStr(const OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
422{
423 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pcOut, VT_I1);
424}
425
426/************************************************************************
427 * VarI1FromDisp (OLEAUT32.252)
428 *
429 * Convert a VT_DISPATCH to a VT_I1.
430 *
431 * PARAMS
432 * pdispIn [I] Source
433 * lcid [I] LCID for conversion
434 * pcOut [O] Destination
435 *
436 * RETURNS
437 * Success: S_OK.
438 * Failure: E_INVALIDARG, if the source value is invalid
439 * DISP_E_OVERFLOW, if the value will not fit in the destination
440 * DISP_E_TYPEMISMATCH, if the type cannot be converted
441 */
442HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
443{
444 return VARIANT_FromDisp(pdispIn, lcid, pcOut, VT_I1, 0);
445}
446
447/************************************************************************
448 * VarI1FromBool (OLEAUT32.253)
449 *
450 * Convert a VT_BOOL to a VT_I1.
451 *
452 * PARAMS
453 * boolIn [I] Source
454 * pcOut [O] Destination
455 *
456 * RETURNS
457 * S_OK.
458 */
459HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
460{
461 return _VarI1FromBool(boolIn, pcOut);
462}
463
464/************************************************************************
465 * VarI1FromUI2 (OLEAUT32.254)
466 *
467 * Convert a VT_UI2 to a VT_I1.
468 *
469 * PARAMS
470 * usIn [I] Source
471 * pcOut [O] Destination
472 *
473 * RETURNS
474 * Success: S_OK.
475 * Failure: E_INVALIDARG, if the source value is invalid
476 * DISP_E_OVERFLOW, if the value will not fit in the destination
477 */
478HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
479{
480 return _VarI1FromUI2(usIn, pcOut);
481}
482
483/************************************************************************
484 * VarI1FromUI4 (OLEAUT32.255)
485 *
486 * Convert a VT_UI4 to a VT_I1.
487 *
488 * PARAMS
489 * ulIn [I] Source
490 * pcOut [O] Destination
491 *
492 * RETURNS
493 * Success: S_OK.
494 * Failure: E_INVALIDARG, if the source value is invalid
495 * DISP_E_OVERFLOW, if the value will not fit in the destination
496 * DISP_E_TYPEMISMATCH, if the type cannot be converted
497 */
498HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
499{
500 return _VarI1FromUI4(ulIn, pcOut);
501}
502
503/************************************************************************
504 * VarI1FromDec (OLEAUT32.256)
505 *
506 * Convert a VT_DECIMAL to a VT_I1.
507 *
508 * PARAMS
509 * pDecIn [I] Source
510 * pcOut [O] Destination
511 *
512 * RETURNS
513 * Success: S_OK.
514 * Failure: E_INVALIDARG, if the source value is invalid
515 * DISP_E_OVERFLOW, if the value will not fit in the destination
516 */
517HRESULT WINAPI VarI1FromDec(const DECIMAL *pdecIn, signed char* pcOut)
518{
519 LONG64 i64;
520 HRESULT hRet;
521
522 hRet = VarI8FromDec(pdecIn, &i64);
523
524 if (SUCCEEDED(hRet))
525 hRet = _VarI1FromI8(i64, pcOut);
526 return hRet;
527}
528
529/************************************************************************
530 * VarI1FromI8 (OLEAUT32.376)
531 *
532 * Convert a VT_I8 to a VT_I1.
533 *
534 * PARAMS
535 * llIn [I] Source
536 * pcOut [O] Destination
537 *
538 * RETURNS
539 * Success: S_OK.
540 * Failure: E_INVALIDARG, if the source value is invalid
541 * DISP_E_OVERFLOW, if the value will not fit in the destination
542 */
543HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
544{
545 return _VarI1FromI8(llIn, pcOut);
546}
547
548/************************************************************************
549 * VarI1FromUI8 (OLEAUT32.377)
550 *
551 * Convert a VT_UI8 to a VT_I1.
552 *
553 * PARAMS
554 * ullIn [I] Source
555 * pcOut [O] Destination
556 *
557 * RETURNS
558 * Success: S_OK.
559 * Failure: E_INVALIDARG, if the source value is invalid
560 * DISP_E_OVERFLOW, if the value will not fit in the destination
561 */
562HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
563{
564 return _VarI1FromUI8(ullIn, pcOut);
565}
566
567/* UI1
568 */
569
570/************************************************************************
571 * VarUI1FromI2 (OLEAUT32.130)
572 *
573 * Convert a VT_I2 to a VT_UI1.
574 *
575 * PARAMS
576 * sIn [I] Source
577 * pbOut [O] Destination
578 *
579 * RETURNS
580 * Success: S_OK.
581 * Failure: E_INVALIDARG, if the source value is invalid
582 * DISP_E_OVERFLOW, if the value will not fit in the destination
583 */
585{
586 return _VarUI1FromI2(sIn, pbOut);
587}
588
589/************************************************************************
590 * VarUI1FromI4 (OLEAUT32.131)
591 *
592 * Convert a VT_I4 to a VT_UI1.
593 *
594 * PARAMS
595 * iIn [I] Source
596 * pbOut [O] Destination
597 *
598 * RETURNS
599 * Success: S_OK.
600 * Failure: E_INVALIDARG, if the source value is invalid
601 * DISP_E_OVERFLOW, if the value will not fit in the destination
602 */
604{
605 return _VarUI1FromI4(iIn, pbOut);
606}
607
608/************************************************************************
609 * VarUI1FromR4 (OLEAUT32.132)
610 *
611 * Convert a VT_R4 to a VT_UI1.
612 *
613 * PARAMS
614 * fltIn [I] Source
615 * pbOut [O] Destination
616 *
617 * RETURNS
618 * Success: S_OK.
619 * Failure: E_INVALIDARG, if the source value is invalid
620 * DISP_E_OVERFLOW, if the value will not fit in the destination
621 * DISP_E_TYPEMISMATCH, if the type cannot be converted
622 */
624{
625 return VarUI1FromR8(fltIn, pbOut);
626}
627
628/************************************************************************
629 * VarUI1FromR8 (OLEAUT32.133)
630 *
631 * Convert a VT_R8 to a VT_UI1.
632 *
633 * PARAMS
634 * dblIn [I] Source
635 * pbOut [O] Destination
636 *
637 * RETURNS
638 * Success: S_OK.
639 * Failure: E_INVALIDARG, if the source value is invalid
640 * DISP_E_OVERFLOW, if the value will not fit in the destination
641 *
642 * NOTES
643 * See VarI8FromR8() for details concerning rounding.
644 */
645HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
646{
647 if (dblIn < -0.5 || dblIn >= UI1_MAX + 0.5)
648 return DISP_E_OVERFLOW;
649 VARIANT_DutchRound(BYTE, dblIn, *pbOut);
650 return S_OK;
651}
652
653/************************************************************************
654 * VarUI1FromCy (OLEAUT32.134)
655 *
656 * Convert a VT_CY to a VT_UI1.
657 *
658 * PARAMS
659 * cyIn [I] Source
660 * pbOut [O] Destination
661 *
662 * RETURNS
663 * Success: S_OK.
664 * Failure: E_INVALIDARG, if the source value is invalid
665 * DISP_E_OVERFLOW, if the value will not fit in the destination
666 *
667 * NOTES
668 * Negative values >= -5000 will be converted to 0.
669 */
671{
672 ULONG i = UI1_MAX + 1;
673
674 VarUI4FromCy(cyIn, &i);
675 return _VarUI1FromUI4(i, pbOut);
676}
677
678/************************************************************************
679 * VarUI1FromDate (OLEAUT32.135)
680 *
681 * Convert a VT_DATE to a VT_UI1.
682 *
683 * PARAMS
684 * dateIn [I] Source
685 * pbOut [O] Destination
686 *
687 * RETURNS
688 * Success: S_OK.
689 * Failure: E_INVALIDARG, if the source value is invalid
690 * DISP_E_OVERFLOW, if the value will not fit in the destination
691 */
693{
694 return VarUI1FromR8(dateIn, pbOut);
695}
696
697/************************************************************************
698 * VarUI1FromStr (OLEAUT32.136)
699 *
700 * Convert a VT_BSTR to a VT_UI1.
701 *
702 * PARAMS
703 * strIn [I] Source
704 * lcid [I] LCID for the conversion
705 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
706 * pbOut [O] Destination
707 *
708 * RETURNS
709 * Success: S_OK.
710 * Failure: E_INVALIDARG, if the source value is invalid
711 * DISP_E_OVERFLOW, if the value will not fit in the destination
712 * DISP_E_TYPEMISMATCH, if the type cannot be converted
713 */
715{
716 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pbOut, VT_UI1);
717}
718
719/************************************************************************
720 * VarUI1FromDisp (OLEAUT32.137)
721 *
722 * Convert a VT_DISPATCH to a VT_UI1.
723 *
724 * PARAMS
725 * pdispIn [I] Source
726 * lcid [I] LCID for conversion
727 * pbOut [O] Destination
728 *
729 * RETURNS
730 * Success: S_OK.
731 * Failure: E_INVALIDARG, if the source value is invalid
732 * DISP_E_OVERFLOW, if the value will not fit in the destination
733 * DISP_E_TYPEMISMATCH, if the type cannot be converted
734 */
736{
737 return VARIANT_FromDisp(pdispIn, lcid, pbOut, VT_UI1, 0);
738}
739
740/************************************************************************
741 * VarUI1FromBool (OLEAUT32.138)
742 *
743 * Convert a VT_BOOL to a VT_UI1.
744 *
745 * PARAMS
746 * boolIn [I] Source
747 * pbOut [O] Destination
748 *
749 * RETURNS
750 * S_OK.
751 */
753{
754 return _VarUI1FromBool(boolIn, pbOut);
755}
756
757/************************************************************************
758 * VarUI1FromI1 (OLEAUT32.237)
759 *
760 * Convert a VT_I1 to a VT_UI1.
761 *
762 * PARAMS
763 * cIn [I] Source
764 * pbOut [O] Destination
765 *
766 * RETURNS
767 * Success: S_OK.
768 * Failure: E_INVALIDARG, if the source value is invalid
769 * DISP_E_OVERFLOW, if the value will not fit in the destination
770 */
771HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
772{
773 return _VarUI1FromI1(cIn, pbOut);
774}
775
776/************************************************************************
777 * VarUI1FromUI2 (OLEAUT32.238)
778 *
779 * Convert a VT_UI2 to a VT_UI1.
780 *
781 * PARAMS
782 * usIn [I] Source
783 * pbOut [O] Destination
784 *
785 * RETURNS
786 * Success: S_OK.
787 * Failure: E_INVALIDARG, if the source value is invalid
788 * DISP_E_OVERFLOW, if the value will not fit in the destination
789 */
791{
792 return _VarUI1FromUI2(usIn, pbOut);
793}
794
795/************************************************************************
796 * VarUI1FromUI4 (OLEAUT32.239)
797 *
798 * Convert a VT_UI4 to a VT_UI1.
799 *
800 * PARAMS
801 * ulIn [I] Source
802 * pbOut [O] Destination
803 *
804 * RETURNS
805 * Success: S_OK.
806 * Failure: E_INVALIDARG, if the source value is invalid
807 * DISP_E_OVERFLOW, if the value will not fit in the destination
808 */
810{
811 return _VarUI1FromUI4(ulIn, pbOut);
812}
813
814/************************************************************************
815 * VarUI1FromDec (OLEAUT32.240)
816 *
817 * Convert a VT_DECIMAL to a VT_UI1.
818 *
819 * PARAMS
820 * pDecIn [I] Source
821 * pbOut [O] Destination
822 *
823 * RETURNS
824 * Success: S_OK.
825 * Failure: E_INVALIDARG, if the source value is invalid
826 * DISP_E_OVERFLOW, if the value will not fit in the destination
827 */
829{
830 LONG64 i64;
831 HRESULT hRet;
832
833 hRet = VarI8FromDec(pdecIn, &i64);
834
835 if (SUCCEEDED(hRet))
836 hRet = _VarUI1FromI8(i64, pbOut);
837 return hRet;
838}
839
840/************************************************************************
841 * VarUI1FromI8 (OLEAUT32.372)
842 *
843 * Convert a VT_I8 to a VT_UI1.
844 *
845 * PARAMS
846 * llIn [I] Source
847 * pbOut [O] Destination
848 *
849 * RETURNS
850 * Success: S_OK.
851 * Failure: E_INVALIDARG, if the source value is invalid
852 * DISP_E_OVERFLOW, if the value will not fit in the destination
853 */
855{
856 return _VarUI1FromI8(llIn, pbOut);
857}
858
859/************************************************************************
860 * VarUI1FromUI8 (OLEAUT32.373)
861 *
862 * Convert a VT_UI8 to a VT_UI1.
863 *
864 * PARAMS
865 * ullIn [I] Source
866 * pbOut [O] Destination
867 *
868 * RETURNS
869 * Success: S_OK.
870 * Failure: E_INVALIDARG, if the source value is invalid
871 * DISP_E_OVERFLOW, if the value will not fit in the destination
872 */
874{
875 return _VarUI1FromUI8(ullIn, pbOut);
876}
877
878
879/* I2
880 */
881
882/************************************************************************
883 * VarI2FromUI1 (OLEAUT32.48)
884 *
885 * Convert a VT_UI2 to a VT_I2.
886 *
887 * PARAMS
888 * bIn [I] Source
889 * psOut [O] Destination
890 *
891 * RETURNS
892 * S_OK.
893 */
895{
896 return _VarI2FromUI1(bIn, psOut);
897}
898
899/************************************************************************
900 * VarI2FromI4 (OLEAUT32.49)
901 *
902 * Convert a VT_I4 to a VT_I2.
903 *
904 * PARAMS
905 * iIn [I] Source
906 * psOut [O] Destination
907 *
908 * RETURNS
909 * Success: S_OK.
910 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
911 */
913{
914 return _VarI2FromI4(iIn, psOut);
915}
916
917/************************************************************************
918 * VarI2FromR4 (OLEAUT32.50)
919 *
920 * Convert a VT_R4 to a VT_I2.
921 *
922 * PARAMS
923 * fltIn [I] Source
924 * psOut [O] Destination
925 *
926 * RETURNS
927 * Success: S_OK.
928 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
929 */
931{
932 return VarI2FromR8(fltIn, psOut);
933}
934
935/************************************************************************
936 * VarI2FromR8 (OLEAUT32.51)
937 *
938 * Convert a VT_R8 to a VT_I2.
939 *
940 * PARAMS
941 * dblIn [I] Source
942 * psOut [O] Destination
943 *
944 * RETURNS
945 * Success: S_OK.
946 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
947 *
948 * NOTES
949 * See VarI8FromR8() for details concerning rounding.
950 */
951HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
952{
953 if (dblIn < I2_MIN - 0.5 || dblIn >= I2_MAX + 0.5)
954 return DISP_E_OVERFLOW;
955 VARIANT_DutchRound(SHORT, dblIn, *psOut);
956 return S_OK;
957}
958
959/************************************************************************
960 * VarI2FromCy (OLEAUT32.52)
961 *
962 * Convert a VT_CY to a VT_I2.
963 *
964 * PARAMS
965 * cyIn [I] Source
966 * psOut [O] Destination
967 *
968 * RETURNS
969 * Success: S_OK.
970 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
971 */
973{
974 LONG i = I2_MAX + 1;
975
976 VarI4FromCy(cyIn, &i);
977 return _VarI2FromI4(i, psOut);
978}
979
980/************************************************************************
981 * VarI2FromDate (OLEAUT32.53)
982 *
983 * Convert a VT_DATE to a VT_I2.
984 *
985 * PARAMS
986 * dateIn [I] Source
987 * psOut [O] Destination
988 *
989 * RETURNS
990 * Success: S_OK.
991 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
992 */
994{
995 return VarI2FromR8(dateIn, psOut);
996}
997
998/************************************************************************
999 * VarI2FromStr (OLEAUT32.54)
1000 *
1001 * Convert a VT_BSTR to a VT_I2.
1002 *
1003 * PARAMS
1004 * strIn [I] Source
1005 * lcid [I] LCID for the conversion
1006 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1007 * psOut [O] Destination
1008 *
1009 * RETURNS
1010 * Success: S_OK.
1011 * Failure: E_INVALIDARG, if any parameter is invalid
1012 * DISP_E_OVERFLOW, if the value will not fit in the destination
1013 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1014 */
1016{
1017 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, psOut, VT_I2);
1018}
1019
1020/************************************************************************
1021 * VarI2FromDisp (OLEAUT32.55)
1022 *
1023 * Convert a VT_DISPATCH to a VT_I2.
1024 *
1025 * PARAMS
1026 * pdispIn [I] Source
1027 * lcid [I] LCID for conversion
1028 * psOut [O] Destination
1029 *
1030 * RETURNS
1031 * Success: S_OK.
1032 * Failure: E_INVALIDARG, if pdispIn is invalid,
1033 * DISP_E_OVERFLOW, if the value will not fit in the destination,
1034 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1035 */
1037{
1038 return VARIANT_FromDisp(pdispIn, lcid, psOut, VT_I2, 0);
1039}
1040
1041/************************************************************************
1042 * VarI2FromBool (OLEAUT32.56)
1043 *
1044 * Convert a VT_BOOL to a VT_I2.
1045 *
1046 * PARAMS
1047 * boolIn [I] Source
1048 * psOut [O] Destination
1049 *
1050 * RETURNS
1051 * S_OK.
1052 */
1054{
1055 return _VarI2FromBool(boolIn, psOut);
1056}
1057
1058/************************************************************************
1059 * VarI2FromI1 (OLEAUT32.205)
1060 *
1061 * Convert a VT_I1 to a VT_I2.
1062 *
1063 * PARAMS
1064 * cIn [I] Source
1065 * psOut [O] Destination
1066 *
1067 * RETURNS
1068 * S_OK.
1069 */
1070HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
1071{
1072 return _VarI2FromI1(cIn, psOut);
1073}
1074
1075/************************************************************************
1076 * VarI2FromUI2 (OLEAUT32.206)
1077 *
1078 * Convert a VT_UI2 to a VT_I2.
1079 *
1080 * PARAMS
1081 * usIn [I] Source
1082 * psOut [O] Destination
1083 *
1084 * RETURNS
1085 * Success: S_OK.
1086 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1087 */
1089{
1090 return _VarI2FromUI2(usIn, psOut);
1091}
1092
1093/************************************************************************
1094 * VarI2FromUI4 (OLEAUT32.207)
1095 *
1096 * Convert a VT_UI4 to a VT_I2.
1097 *
1098 * PARAMS
1099 * ulIn [I] Source
1100 * psOut [O] Destination
1101 *
1102 * RETURNS
1103 * Success: S_OK.
1104 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1105 */
1107{
1108 return _VarI2FromUI4(ulIn, psOut);
1109}
1110
1111/************************************************************************
1112 * VarI2FromDec (OLEAUT32.208)
1113 *
1114 * Convert a VT_DECIMAL to a VT_I2.
1115 *
1116 * PARAMS
1117 * pDecIn [I] Source
1118 * psOut [O] Destination
1119 *
1120 * RETURNS
1121 * Success: S_OK.
1122 * Failure: E_INVALIDARG, if the source value is invalid
1123 * DISP_E_OVERFLOW, if the value will not fit in the destination
1124 */
1126{
1127 LONG64 i64;
1128 HRESULT hRet;
1129
1130 hRet = VarI8FromDec(pdecIn, &i64);
1131
1132 if (SUCCEEDED(hRet))
1133 hRet = _VarI2FromI8(i64, psOut);
1134 return hRet;
1135}
1136
1137/************************************************************************
1138 * VarI2FromI8 (OLEAUT32.346)
1139 *
1140 * Convert a VT_I8 to a VT_I2.
1141 *
1142 * PARAMS
1143 * llIn [I] Source
1144 * psOut [O] Destination
1145 *
1146 * RETURNS
1147 * Success: S_OK.
1148 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1149 */
1151{
1152 return _VarI2FromI8(llIn, psOut);
1153}
1154
1155/************************************************************************
1156 * VarI2FromUI8 (OLEAUT32.347)
1157 *
1158 * Convert a VT_UI8 to a VT_I2.
1159 *
1160 * PARAMS
1161 * ullIn [I] Source
1162 * psOut [O] Destination
1163 *
1164 * RETURNS
1165 * Success: S_OK.
1166 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1167 */
1169{
1170 return _VarI2FromUI8(ullIn, psOut);
1171}
1172
1173/* UI2
1174 */
1175
1176/************************************************************************
1177 * VarUI2FromUI1 (OLEAUT32.257)
1178 *
1179 * Convert a VT_UI1 to a VT_UI2.
1180 *
1181 * PARAMS
1182 * bIn [I] Source
1183 * pusOut [O] Destination
1184 *
1185 * RETURNS
1186 * S_OK.
1187 */
1189{
1190 return _VarUI2FromUI1(bIn, pusOut);
1191}
1192
1193/************************************************************************
1194 * VarUI2FromI2 (OLEAUT32.258)
1195 *
1196 * Convert a VT_I2 to a VT_UI2.
1197 *
1198 * PARAMS
1199 * sIn [I] Source
1200 * pusOut [O] Destination
1201 *
1202 * RETURNS
1203 * Success: S_OK.
1204 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1205 */
1207{
1208 return _VarUI2FromI2(sIn, pusOut);
1209}
1210
1211/************************************************************************
1212 * VarUI2FromI4 (OLEAUT32.259)
1213 *
1214 * Convert a VT_I4 to a VT_UI2.
1215 *
1216 * PARAMS
1217 * iIn [I] Source
1218 * pusOut [O] Destination
1219 *
1220 * RETURNS
1221 * Success: S_OK.
1222 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1223 */
1225{
1226 return _VarUI2FromI4(iIn, pusOut);
1227}
1228
1229/************************************************************************
1230 * VarUI2FromR4 (OLEAUT32.260)
1231 *
1232 * Convert a VT_R4 to a VT_UI2.
1233 *
1234 * PARAMS
1235 * fltIn [I] Source
1236 * pusOut [O] Destination
1237 *
1238 * RETURNS
1239 * Success: S_OK.
1240 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1241 */
1243{
1244 return VarUI2FromR8(fltIn, pusOut);
1245}
1246
1247/************************************************************************
1248 * VarUI2FromR8 (OLEAUT32.261)
1249 *
1250 * Convert a VT_R8 to a VT_UI2.
1251 *
1252 * PARAMS
1253 * dblIn [I] Source
1254 * pusOut [O] Destination
1255 *
1256 * RETURNS
1257 * Success: S_OK.
1258 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1259 *
1260 * NOTES
1261 * See VarI8FromR8() for details concerning rounding.
1262 */
1263HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
1264{
1265 if (dblIn < -0.5 || dblIn >= UI2_MAX + 0.5)
1266 return DISP_E_OVERFLOW;
1267 VARIANT_DutchRound(USHORT, dblIn, *pusOut);
1268 return S_OK;
1269}
1270
1271/************************************************************************
1272 * VarUI2FromDate (OLEAUT32.262)
1273 *
1274 * Convert a VT_DATE to a VT_UI2.
1275 *
1276 * PARAMS
1277 * dateIn [I] Source
1278 * pusOut [O] Destination
1279 *
1280 * RETURNS
1281 * Success: S_OK.
1282 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1283 */
1285{
1286 return VarUI2FromR8(dateIn, pusOut);
1287}
1288
1289/************************************************************************
1290 * VarUI2FromCy (OLEAUT32.263)
1291 *
1292 * Convert a VT_CY to a VT_UI2.
1293 *
1294 * PARAMS
1295 * cyIn [I] Source
1296 * pusOut [O] Destination
1297 *
1298 * RETURNS
1299 * Success: S_OK.
1300 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1301 *
1302 * NOTES
1303 * Negative values >= -5000 will be converted to 0.
1304 */
1306{
1307 ULONG i = UI2_MAX + 1;
1308
1309 VarUI4FromCy(cyIn, &i);
1310 return _VarUI2FromUI4(i, pusOut);
1311}
1312
1313/************************************************************************
1314 * VarUI2FromStr (OLEAUT32.264)
1315 *
1316 * Convert a VT_BSTR to a VT_UI2.
1317 *
1318 * PARAMS
1319 * strIn [I] Source
1320 * lcid [I] LCID for the conversion
1321 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1322 * pusOut [O] Destination
1323 *
1324 * RETURNS
1325 * Success: S_OK.
1326 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1327 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1328 */
1330{
1331 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pusOut, VT_UI2);
1332}
1333
1334/************************************************************************
1335 * VarUI2FromDisp (OLEAUT32.265)
1336 *
1337 * Convert a VT_DISPATCH to a VT_UI2.
1338 *
1339 * PARAMS
1340 * pdispIn [I] Source
1341 * lcid [I] LCID for conversion
1342 * pusOut [O] Destination
1343 *
1344 * RETURNS
1345 * Success: S_OK.
1346 * Failure: E_INVALIDARG, if the source value is invalid
1347 * DISP_E_OVERFLOW, if the value will not fit in the destination
1348 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1349 */
1351{
1352 return VARIANT_FromDisp(pdispIn, lcid, pusOut, VT_UI2, 0);
1353}
1354
1355/************************************************************************
1356 * VarUI2FromBool (OLEAUT32.266)
1357 *
1358 * Convert a VT_BOOL to a VT_UI2.
1359 *
1360 * PARAMS
1361 * boolIn [I] Source
1362 * pusOut [O] Destination
1363 *
1364 * RETURNS
1365 * S_OK.
1366 */
1368{
1369 return _VarUI2FromBool(boolIn, pusOut);
1370}
1371
1372/************************************************************************
1373 * VarUI2FromI1 (OLEAUT32.267)
1374 *
1375 * Convert a VT_I1 to a VT_UI2.
1376 *
1377 * PARAMS
1378 * cIn [I] Source
1379 * pusOut [O] Destination
1380 *
1381 * RETURNS
1382 * Success: S_OK.
1383 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1384 */
1385HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
1386{
1387 return _VarUI2FromI1(cIn, pusOut);
1388}
1389
1390/************************************************************************
1391 * VarUI2FromUI4 (OLEAUT32.268)
1392 *
1393 * Convert a VT_UI4 to a VT_UI2.
1394 *
1395 * PARAMS
1396 * ulIn [I] Source
1397 * pusOut [O] Destination
1398 *
1399 * RETURNS
1400 * Success: S_OK.
1401 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1402 */
1404{
1405 return _VarUI2FromUI4(ulIn, pusOut);
1406}
1407
1408/************************************************************************
1409 * VarUI2FromDec (OLEAUT32.269)
1410 *
1411 * Convert a VT_DECIMAL to a VT_UI2.
1412 *
1413 * PARAMS
1414 * pDecIn [I] Source
1415 * pusOut [O] Destination
1416 *
1417 * RETURNS
1418 * Success: S_OK.
1419 * Failure: E_INVALIDARG, if the source value is invalid
1420 * DISP_E_OVERFLOW, if the value will not fit in the destination
1421 */
1423{
1424 LONG64 i64;
1425 HRESULT hRet;
1426
1427 hRet = VarI8FromDec(pdecIn, &i64);
1428
1429 if (SUCCEEDED(hRet))
1430 hRet = _VarUI2FromI8(i64, pusOut);
1431 return hRet;
1432}
1433
1434/************************************************************************
1435 * VarUI2FromI8 (OLEAUT32.378)
1436 *
1437 * Convert a VT_I8 to a VT_UI2.
1438 *
1439 * PARAMS
1440 * llIn [I] Source
1441 * pusOut [O] Destination
1442 *
1443 * RETURNS
1444 * Success: S_OK.
1445 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1446 */
1448{
1449 return _VarUI2FromI8(llIn, pusOut);
1450}
1451
1452/************************************************************************
1453 * VarUI2FromUI8 (OLEAUT32.379)
1454 *
1455 * Convert a VT_UI8 to a VT_UI2.
1456 *
1457 * PARAMS
1458 * ullIn [I] Source
1459 * pusOut [O] Destination
1460 *
1461 * RETURNS
1462 * Success: S_OK.
1463 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1464 */
1466{
1467 return _VarUI2FromUI8(ullIn, pusOut);
1468}
1469
1470/* I4
1471 */
1472
1473/************************************************************************
1474 * VarI4FromUI1 (OLEAUT32.58)
1475 *
1476 * Convert a VT_UI1 to a VT_I4.
1477 *
1478 * PARAMS
1479 * bIn [I] Source
1480 * piOut [O] Destination
1481 *
1482 * RETURNS
1483 * S_OK.
1484 */
1486{
1487 return _VarI4FromUI1(bIn, piOut);
1488}
1489
1490/************************************************************************
1491 * VarI4FromI2 (OLEAUT32.59)
1492 *
1493 * Convert a VT_I2 to a VT_I4.
1494 *
1495 * PARAMS
1496 * sIn [I] Source
1497 * piOut [O] Destination
1498 *
1499 * RETURNS
1500 * Success: S_OK.
1501 * Failure: E_INVALIDARG, if the source value is invalid
1502 * DISP_E_OVERFLOW, if the value will not fit in the destination
1503 */
1505{
1506 return _VarI4FromI2(sIn, piOut);
1507}
1508
1509/************************************************************************
1510 * VarI4FromR4 (OLEAUT32.60)
1511 *
1512 * Convert a VT_R4 to a VT_I4.
1513 *
1514 * PARAMS
1515 * fltIn [I] Source
1516 * piOut [O] Destination
1517 *
1518 * RETURNS
1519 * Success: S_OK.
1520 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1521 */
1523{
1524 return VarI4FromR8(fltIn, piOut);
1525}
1526
1527/************************************************************************
1528 * VarI4FromR8 (OLEAUT32.61)
1529 *
1530 * Convert a VT_R8 to a VT_I4.
1531 *
1532 * PARAMS
1533 * dblIn [I] Source
1534 * piOut [O] Destination
1535 *
1536 * RETURNS
1537 * Success: S_OK.
1538 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1539 *
1540 * NOTES
1541 * See VarI8FromR8() for details concerning rounding.
1542 */
1543HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
1544{
1545 if (dblIn < I4_MIN - 0.5 || dblIn >= I4_MAX + 0.5)
1546 return DISP_E_OVERFLOW;
1547 VARIANT_DutchRound(LONG, dblIn, *piOut);
1548 return S_OK;
1549}
1550
1551/************************************************************************
1552 * VarI4FromCy (OLEAUT32.62)
1553 *
1554 * Convert a VT_CY to a VT_I4.
1555 *
1556 * PARAMS
1557 * cyIn [I] Source
1558 * piOut [O] Destination
1559 *
1560 * RETURNS
1561 * Success: S_OK.
1562 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1563 */
1565{
1566 double d = cyIn.int64 / CY_MULTIPLIER_F;
1567 return VarI4FromR8(d, piOut);
1568}
1569
1570/************************************************************************
1571 * VarI4FromDate (OLEAUT32.63)
1572 *
1573 * Convert a VT_DATE to a VT_I4.
1574 *
1575 * PARAMS
1576 * dateIn [I] Source
1577 * piOut [O] Destination
1578 *
1579 * RETURNS
1580 * Success: S_OK.
1581 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1582 */
1584{
1585 return VarI4FromR8(dateIn, piOut);
1586}
1587
1588/************************************************************************
1589 * VarI4FromStr (OLEAUT32.64)
1590 *
1591 * Convert a VT_BSTR to a VT_I4.
1592 *
1593 * PARAMS
1594 * strIn [I] Source
1595 * lcid [I] LCID for the conversion
1596 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1597 * piOut [O] Destination
1598 *
1599 * RETURNS
1600 * Success: S_OK.
1601 * Failure: E_INVALIDARG, if any parameter is invalid
1602 * DISP_E_OVERFLOW, if the value will not fit in the destination
1603 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1604 */
1606{
1607 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, piOut, VT_I4);
1608}
1609
1610/************************************************************************
1611 * VarI4FromDisp (OLEAUT32.65)
1612 *
1613 * Convert a VT_DISPATCH to a VT_I4.
1614 *
1615 * PARAMS
1616 * pdispIn [I] Source
1617 * lcid [I] LCID for conversion
1618 * piOut [O] Destination
1619 *
1620 * RETURNS
1621 * Success: S_OK.
1622 * Failure: E_INVALIDARG, if the source value is invalid
1623 * DISP_E_OVERFLOW, if the value will not fit in the destination
1624 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1625 */
1627{
1628 return VARIANT_FromDisp(pdispIn, lcid, piOut, VT_I4, 0);
1629}
1630
1631/************************************************************************
1632 * VarI4FromBool (OLEAUT32.66)
1633 *
1634 * Convert a VT_BOOL to a VT_I4.
1635 *
1636 * PARAMS
1637 * boolIn [I] Source
1638 * piOut [O] Destination
1639 *
1640 * RETURNS
1641 * S_OK.
1642 */
1644{
1645 return _VarI4FromBool(boolIn, piOut);
1646}
1647
1648/************************************************************************
1649 * VarI4FromI1 (OLEAUT32.209)
1650 *
1651 * Convert a VT_I1 to a VT_I4.
1652 *
1653 * PARAMS
1654 * cIn [I] Source
1655 * piOut [O] Destination
1656 *
1657 * RETURNS
1658 * S_OK.
1659 */
1660HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
1661{
1662 return _VarI4FromI1(cIn, piOut);
1663}
1664
1665/************************************************************************
1666 * VarI4FromUI2 (OLEAUT32.210)
1667 *
1668 * Convert a VT_UI2 to a VT_I4.
1669 *
1670 * PARAMS
1671 * usIn [I] Source
1672 * piOut [O] Destination
1673 *
1674 * RETURNS
1675 * S_OK.
1676 */
1678{
1679 return _VarI4FromUI2(usIn, piOut);
1680}
1681
1682/************************************************************************
1683 * VarI4FromUI4 (OLEAUT32.211)
1684 *
1685 * Convert a VT_UI4 to a VT_I4.
1686 *
1687 * PARAMS
1688 * ulIn [I] Source
1689 * piOut [O] Destination
1690 *
1691 * RETURNS
1692 * Success: S_OK.
1693 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1694 */
1696{
1697 return _VarI4FromUI4(ulIn, piOut);
1698}
1699
1700/************************************************************************
1701 * VarI4FromDec (OLEAUT32.212)
1702 *
1703 * Convert a VT_DECIMAL to a VT_I4.
1704 *
1705 * PARAMS
1706 * pDecIn [I] Source
1707 * piOut [O] Destination
1708 *
1709 * RETURNS
1710 * Success: S_OK.
1711 * Failure: E_INVALIDARG, if pdecIn is invalid
1712 * DISP_E_OVERFLOW, if the value will not fit in the destination
1713 */
1715{
1716 LONG64 i64;
1717 HRESULT hRet;
1718
1719 hRet = VarI8FromDec(pdecIn, &i64);
1720
1721 if (SUCCEEDED(hRet))
1722 hRet = _VarI4FromI8(i64, piOut);
1723 return hRet;
1724}
1725
1726/************************************************************************
1727 * VarI4FromI8 (OLEAUT32.348)
1728 *
1729 * Convert a VT_I8 to a VT_I4.
1730 *
1731 * PARAMS
1732 * llIn [I] Source
1733 * piOut [O] Destination
1734 *
1735 * RETURNS
1736 * Success: S_OK.
1737 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1738 */
1740{
1741 return _VarI4FromI8(llIn, piOut);
1742}
1743
1744/************************************************************************
1745 * VarI4FromUI8 (OLEAUT32.349)
1746 *
1747 * Convert a VT_UI8 to a VT_I4.
1748 *
1749 * PARAMS
1750 * ullIn [I] Source
1751 * piOut [O] Destination
1752 *
1753 * RETURNS
1754 * Success: S_OK.
1755 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1756 */
1758{
1759 return _VarI4FromUI8(ullIn, piOut);
1760}
1761
1762/* UI4
1763 */
1764
1765/************************************************************************
1766 * VarUI4FromUI1 (OLEAUT32.270)
1767 *
1768 * Convert a VT_UI1 to a VT_UI4.
1769 *
1770 * PARAMS
1771 * bIn [I] Source
1772 * pulOut [O] Destination
1773 *
1774 * RETURNS
1775 * S_OK.
1776 */
1778{
1779 return _VarUI4FromUI1(bIn, pulOut);
1780}
1781
1782/************************************************************************
1783 * VarUI4FromI2 (OLEAUT32.271)
1784 *
1785 * Convert a VT_I2 to a VT_UI4.
1786 *
1787 * PARAMS
1788 * sIn [I] Source
1789 * pulOut [O] Destination
1790 *
1791 * RETURNS
1792 * Success: S_OK.
1793 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1794 */
1796{
1797 return _VarUI4FromI2(sIn, pulOut);
1798}
1799
1800/************************************************************************
1801 * VarUI4FromI4 (OLEAUT32.272)
1802 *
1803 * Convert a VT_I4 to a VT_UI4.
1804 *
1805 * PARAMS
1806 * iIn [I] Source
1807 * pulOut [O] Destination
1808 *
1809 * RETURNS
1810 * Success: S_OK.
1811 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1812 */
1814{
1815 return _VarUI4FromI4(iIn, pulOut);
1816}
1817
1818/************************************************************************
1819 * VarUI4FromR4 (OLEAUT32.273)
1820 *
1821 * Convert a VT_R4 to a VT_UI4.
1822 *
1823 * PARAMS
1824 * fltIn [I] Source
1825 * pulOut [O] Destination
1826 *
1827 * RETURNS
1828 * Success: S_OK.
1829 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1830 */
1832{
1833 return VarUI4FromR8(fltIn, pulOut);
1834}
1835
1836/************************************************************************
1837 * VarUI4FromR8 (OLEAUT32.274)
1838 *
1839 * Convert a VT_R8 to a VT_UI4.
1840 *
1841 * PARAMS
1842 * dblIn [I] Source
1843 * pulOut [O] Destination
1844 *
1845 * RETURNS
1846 * Success: S_OK.
1847 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1848 *
1849 * NOTES
1850 * See VarI8FromR8() for details concerning rounding.
1851 */
1852HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
1853{
1854 if (dblIn < -0.5 || dblIn >= UI4_MAX + 0.5)
1855 return DISP_E_OVERFLOW;
1856 VARIANT_DutchRound(ULONG, dblIn, *pulOut);
1857 return S_OK;
1858}
1859
1860/************************************************************************
1861 * VarUI4FromDate (OLEAUT32.275)
1862 *
1863 * Convert a VT_DATE to a VT_UI4.
1864 *
1865 * PARAMS
1866 * dateIn [I] Source
1867 * pulOut [O] Destination
1868 *
1869 * RETURNS
1870 * Success: S_OK.
1871 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1872 */
1874{
1875 return VarUI4FromR8(dateIn, pulOut);
1876}
1877
1878/************************************************************************
1879 * VarUI4FromCy (OLEAUT32.276)
1880 *
1881 * Convert a VT_CY to a VT_UI4.
1882 *
1883 * PARAMS
1884 * cyIn [I] Source
1885 * pulOut [O] Destination
1886 *
1887 * RETURNS
1888 * Success: S_OK.
1889 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1890 */
1892{
1893 double d = cyIn.int64 / CY_MULTIPLIER_F;
1894 return VarUI4FromR8(d, pulOut);
1895}
1896
1897/************************************************************************
1898 * VarUI4FromStr (OLEAUT32.277)
1899 *
1900 * Convert a VT_BSTR to a VT_UI4.
1901 *
1902 * PARAMS
1903 * strIn [I] Source
1904 * lcid [I] LCID for the conversion
1905 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1906 * pulOut [O] Destination
1907 *
1908 * RETURNS
1909 * Success: S_OK.
1910 * Failure: E_INVALIDARG, if any parameter is invalid
1911 * DISP_E_OVERFLOW, if the value will not fit in the destination
1912 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1913 */
1915{
1916 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pulOut, VT_UI4);
1917}
1918
1919/************************************************************************
1920 * VarUI4FromDisp (OLEAUT32.278)
1921 *
1922 * Convert a VT_DISPATCH to a VT_UI4.
1923 *
1924 * PARAMS
1925 * pdispIn [I] Source
1926 * lcid [I] LCID for conversion
1927 * pulOut [O] Destination
1928 *
1929 * RETURNS
1930 * Success: S_OK.
1931 * Failure: E_INVALIDARG, if the source value is invalid
1932 * DISP_E_OVERFLOW, if the value will not fit in the destination
1933 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1934 */
1936{
1937 return VARIANT_FromDisp(pdispIn, lcid, pulOut, VT_UI4, 0);
1938}
1939
1940/************************************************************************
1941 * VarUI4FromBool (OLEAUT32.279)
1942 *
1943 * Convert a VT_BOOL to a VT_UI4.
1944 *
1945 * PARAMS
1946 * boolIn [I] Source
1947 * pulOut [O] Destination
1948 *
1949 * RETURNS
1950 * S_OK.
1951 */
1953{
1954 return _VarUI4FromBool(boolIn, pulOut);
1955}
1956
1957/************************************************************************
1958 * VarUI4FromI1 (OLEAUT32.280)
1959 *
1960 * Convert a VT_I1 to a VT_UI4.
1961 *
1962 * PARAMS
1963 * cIn [I] Source
1964 * pulOut [O] Destination
1965 *
1966 * RETURNS
1967 * Success: S_OK.
1968 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1969 */
1970HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
1971{
1972 return _VarUI4FromI1(cIn, pulOut);
1973}
1974
1975/************************************************************************
1976 * VarUI4FromUI2 (OLEAUT32.281)
1977 *
1978 * Convert a VT_UI2 to a VT_UI4.
1979 *
1980 * PARAMS
1981 * usIn [I] Source
1982 * pulOut [O] Destination
1983 *
1984 * RETURNS
1985 * S_OK.
1986 */
1988{
1989 return _VarUI4FromUI2(usIn, pulOut);
1990}
1991
1992/************************************************************************
1993 * VarUI4FromDec (OLEAUT32.282)
1994 *
1995 * Convert a VT_DECIMAL to a VT_UI4.
1996 *
1997 * PARAMS
1998 * pDecIn [I] Source
1999 * pulOut [O] Destination
2000 *
2001 * RETURNS
2002 * Success: S_OK.
2003 * Failure: E_INVALIDARG, if pdecIn is invalid
2004 * DISP_E_OVERFLOW, if the value will not fit in the destination
2005 */
2007{
2008 LONG64 i64;
2009 HRESULT hRet;
2010
2011 hRet = VarI8FromDec(pdecIn, &i64);
2012
2013 if (SUCCEEDED(hRet))
2014 hRet = _VarUI4FromI8(i64, pulOut);
2015 return hRet;
2016}
2017
2018/************************************************************************
2019 * VarUI4FromI8 (OLEAUT32.425)
2020 *
2021 * Convert a VT_I8 to a VT_UI4.
2022 *
2023 * PARAMS
2024 * llIn [I] Source
2025 * pulOut [O] Destination
2026 *
2027 * RETURNS
2028 * Success: S_OK.
2029 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2030 */
2032{
2033 return _VarUI4FromI8(llIn, pulOut);
2034}
2035
2036/************************************************************************
2037 * VarUI4FromUI8 (OLEAUT32.426)
2038 *
2039 * Convert a VT_UI8 to a VT_UI4.
2040 *
2041 * PARAMS
2042 * ullIn [I] Source
2043 * pulOut [O] Destination
2044 *
2045 * RETURNS
2046 * Success: S_OK.
2047 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2048 */
2050{
2051 return _VarUI4FromUI8(ullIn, pulOut);
2052}
2053
2054/* I8
2055 */
2056
2057/************************************************************************
2058 * VarI8FromUI1 (OLEAUT32.333)
2059 *
2060 * Convert a VT_UI1 to a VT_I8.
2061 *
2062 * PARAMS
2063 * bIn [I] Source
2064 * pi64Out [O] Destination
2065 *
2066 * RETURNS
2067 * S_OK.
2068 */
2070{
2071 return _VarI8FromUI1(bIn, pi64Out);
2072}
2073
2074
2075/************************************************************************
2076 * VarI8FromI2 (OLEAUT32.334)
2077 *
2078 * Convert a VT_I2 to a VT_I8.
2079 *
2080 * PARAMS
2081 * sIn [I] Source
2082 * pi64Out [O] Destination
2083 *
2084 * RETURNS
2085 * S_OK.
2086 */
2088{
2089 return _VarI8FromI2(sIn, pi64Out);
2090}
2091
2092/************************************************************************
2093 * VarI8FromR4 (OLEAUT32.335)
2094 *
2095 * Convert a VT_R4 to a VT_I8.
2096 *
2097 * PARAMS
2098 * fltIn [I] Source
2099 * pi64Out [O] Destination
2100 *
2101 * RETURNS
2102 * Success: S_OK.
2103 * Failure: E_INVALIDARG, if the source value is invalid
2104 * DISP_E_OVERFLOW, if the value will not fit in the destination
2105 */
2107{
2108 return VarI8FromR8(fltIn, pi64Out);
2109}
2110
2111/************************************************************************
2112 * VarI8FromR8 (OLEAUT32.336)
2113 *
2114 * Convert a VT_R8 to a VT_I8.
2115 *
2116 * PARAMS
2117 * dblIn [I] Source
2118 * pi64Out [O] Destination
2119 *
2120 * RETURNS
2121 * Success: S_OK.
2122 * Failure: E_INVALIDARG, if the source value is invalid
2123 * DISP_E_OVERFLOW, if the value will not fit in the destination
2124 *
2125 * NOTES
2126 * Only values that fit into 63 bits are accepted. Due to rounding issues,
2127 * very high or low values will not be accurately converted.
2128 *
2129 * Numbers are rounded using Dutch rounding, as follows:
2130 *
2131 *| Fractional Part Sign Direction Example
2132 *| --------------- ---- --------- -------
2133 *| < 0.5 + Down 0.4 -> 0.0
2134 *| < 0.5 - Up -0.4 -> 0.0
2135 *| > 0.5 + Up 0.6 -> 1.0
2136 *| < 0.5 - Up -0.6 -> -1.0
2137 *| = 0.5 + Up/Down Down if even, Up if odd
2138 *| = 0.5 - Up/Down Up if even, Down if odd
2139 *
2140 * This system is often used in supermarkets.
2141 */
2142HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
2143{
2144 if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
2145 return DISP_E_OVERFLOW;
2146 VARIANT_DutchRound(LONG64, dblIn, *pi64Out);
2147 return S_OK;
2148}
2149
2150/************************************************************************
2151 * VarI8FromCy (OLEAUT32.337)
2152 *
2153 * Convert a VT_CY to a VT_I8.
2154 *
2155 * PARAMS
2156 * cyIn [I] Source
2157 * pi64Out [O] Destination
2158 *
2159 * RETURNS
2160 * S_OK.
2161 *
2162 * NOTES
2163 * All negative numbers are rounded down by 1, including those that are
2164 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2165 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2166 * for details.
2167 */
2169{
2170 *pi64Out = cyIn.int64 / CY_MULTIPLIER;
2171
2172 if (cyIn.int64 < 0)
2173 (*pi64Out)--; /* Mimic Win32 bug */
2174 else
2175 {
2176 cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.Lo now holds fractional remainder */
2177
2178 if (cyIn.Lo > CY_HALF || (cyIn.Lo == CY_HALF && (*pi64Out & 0x1)))
2179 (*pi64Out)++;
2180 }
2181 return S_OK;
2182}
2183
2184/************************************************************************
2185 * VarI8FromDate (OLEAUT32.338)
2186 *
2187 * Convert a VT_DATE to a VT_I8.
2188 *
2189 * PARAMS
2190 * dateIn [I] Source
2191 * pi64Out [O] Destination
2192 *
2193 * RETURNS
2194 * Success: S_OK.
2195 * Failure: E_INVALIDARG, if the source value is invalid
2196 * DISP_E_OVERFLOW, if the value will not fit in the destination
2197 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2198 */
2200{
2201 return VarI8FromR8(dateIn, pi64Out);
2202}
2203
2204/************************************************************************
2205 * VarI8FromStr (OLEAUT32.339)
2206 *
2207 * Convert a VT_BSTR to a VT_I8.
2208 *
2209 * PARAMS
2210 * strIn [I] Source
2211 * lcid [I] LCID for the conversion
2212 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2213 * pi64Out [O] Destination
2214 *
2215 * RETURNS
2216 * Success: S_OK.
2217 * Failure: E_INVALIDARG, if the source value is invalid
2218 * DISP_E_OVERFLOW, if the value will not fit in the destination
2219 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2220 */
2222{
2223 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pi64Out, VT_I8);
2224}
2225
2226/************************************************************************
2227 * VarI8FromDisp (OLEAUT32.340)
2228 *
2229 * Convert a VT_DISPATCH to a VT_I8.
2230 *
2231 * PARAMS
2232 * pdispIn [I] Source
2233 * lcid [I] LCID for conversion
2234 * pi64Out [O] Destination
2235 *
2236 * RETURNS
2237 * Success: S_OK.
2238 * Failure: E_INVALIDARG, if the source value is invalid
2239 * DISP_E_OVERFLOW, if the value will not fit in the destination
2240 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2241 */
2243{
2244 return VARIANT_FromDisp(pdispIn, lcid, pi64Out, VT_I8, 0);
2245}
2246
2247/************************************************************************
2248 * VarI8FromBool (OLEAUT32.341)
2249 *
2250 * Convert a VT_BOOL to a VT_I8.
2251 *
2252 * PARAMS
2253 * boolIn [I] Source
2254 * pi64Out [O] Destination
2255 *
2256 * RETURNS
2257 * S_OK.
2258 */
2260{
2261 return VarI8FromI2(boolIn, pi64Out);
2262}
2263
2264/************************************************************************
2265 * VarI8FromI1 (OLEAUT32.342)
2266 *
2267 * Convert a VT_I1 to a VT_I8.
2268 *
2269 * PARAMS
2270 * cIn [I] Source
2271 * pi64Out [O] Destination
2272 *
2273 * RETURNS
2274 * S_OK.
2275 */
2276HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
2277{
2278 return _VarI8FromI1(cIn, pi64Out);
2279}
2280
2281/************************************************************************
2282 * VarI8FromUI2 (OLEAUT32.343)
2283 *
2284 * Convert a VT_UI2 to a VT_I8.
2285 *
2286 * PARAMS
2287 * usIn [I] Source
2288 * pi64Out [O] Destination
2289 *
2290 * RETURNS
2291 * S_OK.
2292 */
2294{
2295 return _VarI8FromUI2(usIn, pi64Out);
2296}
2297
2298/************************************************************************
2299 * VarI8FromUI4 (OLEAUT32.344)
2300 *
2301 * Convert a VT_UI4 to a VT_I8.
2302 *
2303 * PARAMS
2304 * ulIn [I] Source
2305 * pi64Out [O] Destination
2306 *
2307 * RETURNS
2308 * S_OK.
2309 */
2311{
2312 return _VarI8FromUI4(ulIn, pi64Out);
2313}
2314
2315/************************************************************************
2316 * VarI8FromDec (OLEAUT32.345)
2317 *
2318 * Convert a VT_DECIMAL to a VT_I8.
2319 *
2320 * PARAMS
2321 * pDecIn [I] Source
2322 * pi64Out [O] Destination
2323 *
2324 * RETURNS
2325 * Success: S_OK.
2326 * Failure: E_INVALIDARG, if the source value is invalid
2327 * DISP_E_OVERFLOW, if the value will not fit in the destination
2328 */
2329HRESULT WINAPI VarI8FromDec(const DECIMAL *pdecIn, LONG64* pi64Out)
2330{
2331 if (!pdecIn->scale)
2332 {
2333 /* This decimal is just a 96 bit integer */
2334 if (pdecIn->sign & ~DECIMAL_NEG)
2335 return E_INVALIDARG;
2336
2337 if (pdecIn->Hi32 || pdecIn->Mid32 & 0x80000000)
2338 return DISP_E_OVERFLOW;
2339
2340 if (pdecIn->sign)
2341 *pi64Out = -pdecIn->Lo64;
2342 else
2343 *pi64Out = pdecIn->Lo64;
2344 return S_OK;
2345 }
2346 else
2347 {
2348 /* Decimal contains a floating point number */
2349 HRESULT hRet;
2350 double dbl;
2351
2352 hRet = VarR8FromDec(pdecIn, &dbl);
2353 if (SUCCEEDED(hRet))
2354 hRet = VarI8FromR8(dbl, pi64Out);
2355 return hRet;
2356 }
2357}
2358
2359/************************************************************************
2360 * VarI8FromUI8 (OLEAUT32.427)
2361 *
2362 * Convert a VT_UI8 to a VT_I8.
2363 *
2364 * PARAMS
2365 * ullIn [I] Source
2366 * pi64Out [O] Destination
2367 *
2368 * RETURNS
2369 * Success: S_OK.
2370 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2371 */
2373{
2374 return _VarI8FromUI8(ullIn, pi64Out);
2375}
2376
2377/* UI8
2378 */
2379
2380/************************************************************************
2381 * VarUI8FromI8 (OLEAUT32.428)
2382 *
2383 * Convert a VT_I8 to a VT_UI8.
2384 *
2385 * PARAMS
2386 * ulIn [I] Source
2387 * pui64Out [O] Destination
2388 *
2389 * RETURNS
2390 * Success: S_OK.
2391 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2392 */
2394{
2395 return _VarUI8FromI8(llIn, pui64Out);
2396}
2397
2398/************************************************************************
2399 * VarUI8FromUI1 (OLEAUT32.429)
2400 *
2401 * Convert a VT_UI1 to a VT_UI8.
2402 *
2403 * PARAMS
2404 * bIn [I] Source
2405 * pui64Out [O] Destination
2406 *
2407 * RETURNS
2408 * S_OK.
2409 */
2411{
2412 return _VarUI8FromUI1(bIn, pui64Out);
2413}
2414
2415/************************************************************************
2416 * VarUI8FromI2 (OLEAUT32.430)
2417 *
2418 * Convert a VT_I2 to a VT_UI8.
2419 *
2420 * PARAMS
2421 * sIn [I] Source
2422 * pui64Out [O] Destination
2423 *
2424 * RETURNS
2425 * S_OK.
2426 */
2428{
2429 return _VarUI8FromI2(sIn, pui64Out);
2430}
2431
2432/************************************************************************
2433 * VarUI8FromR4 (OLEAUT32.431)
2434 *
2435 * Convert a VT_R4 to a VT_UI8.
2436 *
2437 * PARAMS
2438 * fltIn [I] Source
2439 * pui64Out [O] Destination
2440 *
2441 * RETURNS
2442 * Success: S_OK.
2443 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2444 */
2446{
2447 return VarUI8FromR8(fltIn, pui64Out);
2448}
2449
2450/************************************************************************
2451 * VarUI8FromR8 (OLEAUT32.432)
2452 *
2453 * Convert a VT_R8 to a VT_UI8.
2454 *
2455 * PARAMS
2456 * dblIn [I] Source
2457 * pui64Out [O] Destination
2458 *
2459 * RETURNS
2460 * Success: S_OK.
2461 * Failure: E_INVALIDARG, if the source value is invalid
2462 * DISP_E_OVERFLOW, if the value will not fit in the destination
2463 *
2464 * NOTES
2465 * See VarI8FromR8() for details concerning rounding.
2466 */
2467HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
2468{
2469 if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
2470 return DISP_E_OVERFLOW;
2471 VARIANT_DutchRound(ULONG64, dblIn, *pui64Out);
2472 return S_OK;
2473}
2474
2475/************************************************************************
2476 * VarUI8FromCy (OLEAUT32.433)
2477 *
2478 * Convert a VT_CY to a VT_UI8.
2479 *
2480 * PARAMS
2481 * cyIn [I] Source
2482 * pui64Out [O] Destination
2483 *
2484 * RETURNS
2485 * Success: S_OK.
2486 * Failure: E_INVALIDARG, if the source value is invalid
2487 * DISP_E_OVERFLOW, if the value will not fit in the destination
2488 *
2489 * NOTES
2490 * Negative values >= -5000 will be converted to 0.
2491 */
2493{
2494 if (cyIn.int64 < 0)
2495 {
2496 if (cyIn.int64 < -CY_HALF)
2497 return DISP_E_OVERFLOW;
2498 *pui64Out = 0;
2499 }
2500 else
2501 {
2502 *pui64Out = cyIn.int64 / CY_MULTIPLIER;
2503
2504 cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.Lo now holds fractional remainder */
2505
2506 if (cyIn.Lo > CY_HALF || (cyIn.Lo == CY_HALF && (*pui64Out & 0x1)))
2507 (*pui64Out)++;
2508 }
2509 return S_OK;
2510}
2511
2512/************************************************************************
2513 * VarUI8FromDate (OLEAUT32.434)
2514 *
2515 * Convert a VT_DATE to a VT_UI8.
2516 *
2517 * PARAMS
2518 * dateIn [I] Source
2519 * pui64Out [O] Destination
2520 *
2521 * RETURNS
2522 * Success: S_OK.
2523 * Failure: E_INVALIDARG, if the source value is invalid
2524 * DISP_E_OVERFLOW, if the value will not fit in the destination
2525 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2526 */
2528{
2529 return VarUI8FromR8(dateIn, pui64Out);
2530}
2531
2532/************************************************************************
2533 * VarUI8FromStr (OLEAUT32.435)
2534 *
2535 * Convert a VT_BSTR to a VT_UI8.
2536 *
2537 * PARAMS
2538 * strIn [I] Source
2539 * lcid [I] LCID for the conversion
2540 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2541 * pui64Out [O] Destination
2542 *
2543 * RETURNS
2544 * Success: S_OK.
2545 * Failure: E_INVALIDARG, if the source value is invalid
2546 * DISP_E_OVERFLOW, if the value will not fit in the destination
2547 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2548 */
2550{
2551 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pui64Out, VT_UI8);
2552}
2553
2554/************************************************************************
2555 * VarUI8FromDisp (OLEAUT32.436)
2556 *
2557 * Convert a VT_DISPATCH to a VT_UI8.
2558 *
2559 * PARAMS
2560 * pdispIn [I] Source
2561 * lcid [I] LCID for conversion
2562 * pui64Out [O] Destination
2563 *
2564 * RETURNS
2565 * Success: S_OK.
2566 * Failure: E_INVALIDARG, if the source value is invalid
2567 * DISP_E_OVERFLOW, if the value will not fit in the destination
2568 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2569 */
2571{
2572 return VARIANT_FromDisp(pdispIn, lcid, pui64Out, VT_UI8, 0);
2573}
2574
2575/************************************************************************
2576 * VarUI8FromBool (OLEAUT32.437)
2577 *
2578 * Convert a VT_BOOL to a VT_UI8.
2579 *
2580 * PARAMS
2581 * boolIn [I] Source
2582 * pui64Out [O] Destination
2583 *
2584 * RETURNS
2585 * Success: S_OK.
2586 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2587 */
2589{
2590 return VarI8FromI2(boolIn, (LONG64 *)pui64Out);
2591}
2592/************************************************************************
2593 * VarUI8FromI1 (OLEAUT32.438)
2594 *
2595 * Convert a VT_I1 to a VT_UI8.
2596 *
2597 * PARAMS
2598 * cIn [I] Source
2599 * pui64Out [O] Destination
2600 *
2601 * RETURNS
2602 * Success: S_OK.
2603 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2604 */
2605HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
2606{
2607 return _VarUI8FromI1(cIn, pui64Out);
2608}
2609
2610/************************************************************************
2611 * VarUI8FromUI2 (OLEAUT32.439)
2612 *
2613 * Convert a VT_UI2 to a VT_UI8.
2614 *
2615 * PARAMS
2616 * usIn [I] Source
2617 * pui64Out [O] Destination
2618 *
2619 * RETURNS
2620 * S_OK.
2621 */
2623{
2624 return _VarUI8FromUI2(usIn, pui64Out);
2625}
2626
2627/************************************************************************
2628 * VarUI8FromUI4 (OLEAUT32.440)
2629 *
2630 * Convert a VT_UI4 to a VT_UI8.
2631 *
2632 * PARAMS
2633 * ulIn [I] Source
2634 * pui64Out [O] Destination
2635 *
2636 * RETURNS
2637 * S_OK.
2638 */
2640{
2641 return _VarUI8FromUI4(ulIn, pui64Out);
2642}
2643
2644/************************************************************************
2645 * VarUI8FromDec (OLEAUT32.441)
2646 *
2647 * Convert a VT_DECIMAL to a VT_UI8.
2648 *
2649 * PARAMS
2650 * pDecIn [I] Source
2651 * pui64Out [O] Destination
2652 *
2653 * RETURNS
2654 * Success: S_OK.
2655 * Failure: E_INVALIDARG, if the source value is invalid
2656 * DISP_E_OVERFLOW, if the value will not fit in the destination
2657 *
2658 * NOTES
2659 * Under native Win32, if the source value has a scale of 0, its sign is
2660 * ignored, i.e. this function takes the absolute value rather than fail
2661 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2662 * (use VarAbs() on pDecIn first if you really want this behaviour).
2663 */
2664HRESULT WINAPI VarUI8FromDec(const DECIMAL *pdecIn, ULONG64* pui64Out)
2665{
2666 if (!pdecIn->scale)
2667 {
2668 /* This decimal is just a 96 bit integer */
2669 if (pdecIn->sign & ~DECIMAL_NEG)
2670 return E_INVALIDARG;
2671
2672 if (pdecIn->Hi32)
2673 return DISP_E_OVERFLOW;
2674
2675 if (pdecIn->sign)
2676 {
2677 WARN("Sign would be ignored under Win32!\n");
2678 return DISP_E_OVERFLOW;
2679 }
2680
2681 *pui64Out = pdecIn->Lo64;
2682 return S_OK;
2683 }
2684 else
2685 {
2686 /* Decimal contains a floating point number */
2687 HRESULT hRet;
2688 double dbl;
2689
2690 hRet = VarR8FromDec(pdecIn, &dbl);
2691 if (SUCCEEDED(hRet))
2692 hRet = VarUI8FromR8(dbl, pui64Out);
2693 return hRet;
2694 }
2695}
2696
2697/* R4
2698 */
2699
2700/************************************************************************
2701 * VarR4FromUI1 (OLEAUT32.68)
2702 *
2703 * Convert a VT_UI1 to a VT_R4.
2704 *
2705 * PARAMS
2706 * bIn [I] Source
2707 * pFltOut [O] Destination
2708 *
2709 * RETURNS
2710 * S_OK.
2711 */
2712HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
2713{
2714 return _VarR4FromUI1(bIn, pFltOut);
2715}
2716
2717/************************************************************************
2718 * VarR4FromI2 (OLEAUT32.69)
2719 *
2720 * Convert a VT_I2 to a VT_R4.
2721 *
2722 * PARAMS
2723 * sIn [I] Source
2724 * pFltOut [O] Destination
2725 *
2726 * RETURNS
2727 * S_OK.
2728 */
2729HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
2730{
2731 return _VarR4FromI2(sIn, pFltOut);
2732}
2733
2734/************************************************************************
2735 * VarR4FromI4 (OLEAUT32.70)
2736 *
2737 * Convert a VT_I4 to a VT_R4.
2738 *
2739 * PARAMS
2740 * sIn [I] Source
2741 * pFltOut [O] Destination
2742 *
2743 * RETURNS
2744 * S_OK.
2745 */
2746HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
2747{
2748 return _VarR4FromI4(lIn, pFltOut);
2749}
2750
2751/************************************************************************
2752 * VarR4FromR8 (OLEAUT32.71)
2753 *
2754 * Convert a VT_R8 to a VT_R4.
2755 *
2756 * PARAMS
2757 * dblIn [I] Source
2758 * pFltOut [O] Destination
2759 *
2760 * RETURNS
2761 * Success: S_OK.
2762 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2763 */
2764HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
2765{
2766 double d = dblIn < 0.0 ? -dblIn : dblIn;
2767 if (d > R4_MAX) return DISP_E_OVERFLOW;
2768 *pFltOut = dblIn;
2769 return S_OK;
2770}
2771
2772/************************************************************************
2773 * VarR4FromCy (OLEAUT32.72)
2774 *
2775 * Convert a VT_CY to a VT_R4.
2776 *
2777 * PARAMS
2778 * cyIn [I] Source
2779 * pFltOut [O] Destination
2780 *
2781 * RETURNS
2782 * S_OK.
2783 */
2784HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
2785{
2786 *pFltOut = (double)cyIn.int64 / CY_MULTIPLIER_F;
2787 return S_OK;
2788}
2789
2790/************************************************************************
2791 * VarR4FromDate (OLEAUT32.73)
2792 *
2793 * Convert a VT_DATE to a VT_R4.
2794 *
2795 * PARAMS
2796 * dateIn [I] Source
2797 * pFltOut [O] Destination
2798 *
2799 * RETURNS
2800 * Success: S_OK.
2801 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2802 */
2803HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
2804{
2805 return VarR4FromR8(dateIn, pFltOut);
2806}
2807
2808/************************************************************************
2809 * VarR4FromStr (OLEAUT32.74)
2810 *
2811 * Convert a VT_BSTR to a VT_R4.
2812 *
2813 * PARAMS
2814 * strIn [I] Source
2815 * lcid [I] LCID for the conversion
2816 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2817 * pFltOut [O] Destination
2818 *
2819 * RETURNS
2820 * Success: S_OK.
2821 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2822 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2823 */
2824HRESULT WINAPI VarR4FromStr(const OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
2825{
2826 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pFltOut, VT_R4);
2827}
2828
2829/************************************************************************
2830 * VarR4FromDisp (OLEAUT32.75)
2831 *
2832 * Convert a VT_DISPATCH to a VT_R4.
2833 *
2834 * PARAMS
2835 * pdispIn [I] Source
2836 * lcid [I] LCID for conversion
2837 * pFltOut [O] Destination
2838 *
2839 * RETURNS
2840 * Success: S_OK.
2841 * Failure: E_INVALIDARG, if the source value is invalid
2842 * DISP_E_OVERFLOW, if the value will not fit in the destination
2843 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2844 */
2845HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
2846{
2847 return VARIANT_FromDisp(pdispIn, lcid, pFltOut, VT_R4, 0);
2848}
2849
2850/************************************************************************
2851 * VarR4FromBool (OLEAUT32.76)
2852 *
2853 * Convert a VT_BOOL to a VT_R4.
2854 *
2855 * PARAMS
2856 * boolIn [I] Source
2857 * pFltOut [O] Destination
2858 *
2859 * RETURNS
2860 * S_OK.
2861 */
2863{
2864 return VarR4FromI2(boolIn, pFltOut);
2865}
2866
2867/************************************************************************
2868 * VarR4FromI1 (OLEAUT32.213)
2869 *
2870 * Convert a VT_I1 to a VT_R4.
2871 *
2872 * PARAMS
2873 * cIn [I] Source
2874 * pFltOut [O] Destination
2875 *
2876 * RETURNS
2877 * Success: S_OK.
2878 * Failure: E_INVALIDARG, if the source value is invalid
2879 * DISP_E_OVERFLOW, if the value will not fit in the destination
2880 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2881 */
2882HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
2883{
2884 return _VarR4FromI1(cIn, pFltOut);
2885}
2886
2887/************************************************************************
2888 * VarR4FromUI2 (OLEAUT32.214)
2889 *
2890 * Convert a VT_UI2 to a VT_R4.
2891 *
2892 * PARAMS
2893 * usIn [I] Source
2894 * pFltOut [O] Destination
2895 *
2896 * RETURNS
2897 * Success: S_OK.
2898 * Failure: E_INVALIDARG, if the source value is invalid
2899 * DISP_E_OVERFLOW, if the value will not fit in the destination
2900 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2901 */
2902HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
2903{
2904 return _VarR4FromUI2(usIn, pFltOut);
2905}
2906
2907/************************************************************************
2908 * VarR4FromUI4 (OLEAUT32.215)
2909 *
2910 * Convert a VT_UI4 to a VT_R4.
2911 *
2912 * PARAMS
2913 * ulIn [I] Source
2914 * pFltOut [O] Destination
2915 *
2916 * RETURNS
2917 * Success: S_OK.
2918 * Failure: E_INVALIDARG, if the source value is invalid
2919 * DISP_E_OVERFLOW, if the value will not fit in the destination
2920 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2921 */
2922HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
2923{
2924 return _VarR4FromUI4(ulIn, pFltOut);
2925}
2926
2927/************************************************************************
2928 * VarR4FromDec (OLEAUT32.216)
2929 *
2930 * Convert a VT_DECIMAL to a VT_R4.
2931 *
2932 * PARAMS
2933 * pDecIn [I] Source
2934 * pFltOut [O] Destination
2935 *
2936 * RETURNS
2937 * Success: S_OK.
2938 * Failure: E_INVALIDARG, if the source value is invalid.
2939 */
2940HRESULT WINAPI VarR4FromDec(const DECIMAL* pDecIn, float *pFltOut)
2941{
2942 BYTE scale = pDecIn->scale;
2943 double divisor = 1.0;
2944 double highPart;
2945
2946 if (scale > DEC_MAX_SCALE || pDecIn->sign & ~DECIMAL_NEG)
2947 return E_INVALIDARG;
2948
2949 while (scale--)
2950 divisor *= 10.0;
2951
2952 if (pDecIn->sign)
2953 divisor = -divisor;
2954
2955 if (pDecIn->Hi32)
2956 {
2957 highPart = (double)pDecIn->Hi32 / divisor;
2958 highPart *= 4294967296.0F;
2959 highPart *= 4294967296.0F;
2960 }
2961 else
2962 highPart = 0.0;
2963
2964 *pFltOut = (double)pDecIn->Lo64 / divisor + highPart;
2965 return S_OK;
2966}
2967
2968/************************************************************************
2969 * VarR4FromI8 (OLEAUT32.360)
2970 *
2971 * Convert a VT_I8 to a VT_R4.
2972 *
2973 * PARAMS
2974 * ullIn [I] Source
2975 * pFltOut [O] Destination
2976 *
2977 * RETURNS
2978 * S_OK.
2979 */
2980HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2981{
2982 return _VarR4FromI8(llIn, pFltOut);
2983}
2984
2985/************************************************************************
2986 * VarR4FromUI8 (OLEAUT32.361)
2987 *
2988 * Convert a VT_UI8 to a VT_R4.
2989 *
2990 * PARAMS
2991 * ullIn [I] Source
2992 * pFltOut [O] Destination
2993 *
2994 * RETURNS
2995 * S_OK.
2996 */
2997HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
2998{
2999 return _VarR4FromUI8(ullIn, pFltOut);
3000}
3001
3002/************************************************************************
3003 * VarR4CmpR8 (OLEAUT32.316)
3004 *
3005 * Compare a VT_R4 to a VT_R8.
3006 *
3007 * PARAMS
3008 * fltLeft [I] Source
3009 * dblRight [I] Value to compare
3010 *
3011 * RETURNS
3012 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
3013 * equal to or greater than dblRight respectively.
3014 */
3015HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
3016{
3017 if (fltLeft < dblRight)
3018 return VARCMP_LT;
3019 else if (fltLeft > dblRight)
3020 return VARCMP_GT;
3021 return VARCMP_EQ;
3022}
3023
3024/* R8
3025 */
3026
3027/************************************************************************
3028 * VarR8FromUI1 (OLEAUT32.78)
3029 *
3030 * Convert a VT_UI1 to a VT_R8.
3031 *
3032 * PARAMS
3033 * bIn [I] Source
3034 * pDblOut [O] Destination
3035 *
3036 * RETURNS
3037 * S_OK.
3038 */
3039HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
3040{
3041 return _VarR8FromUI1(bIn, pDblOut);
3042}
3043
3044/************************************************************************
3045 * VarR8FromI2 (OLEAUT32.79)
3046 *
3047 * Convert a VT_I2 to a VT_R8.
3048 *
3049 * PARAMS
3050 * sIn [I] Source
3051 * pDblOut [O] Destination
3052 *
3053 * RETURNS
3054 * S_OK.
3055 */
3056HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
3057{
3058 return _VarR8FromI2(sIn, pDblOut);
3059}
3060
3061/************************************************************************
3062 * VarR8FromI4 (OLEAUT32.80)
3063 *
3064 * Convert a VT_I4 to a VT_R8.
3065 *
3066 * PARAMS
3067 * sIn [I] Source
3068 * pDblOut [O] Destination
3069 *
3070 * RETURNS
3071 * S_OK.
3072 */
3073HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
3074{
3075 return _VarR8FromI4(lIn, pDblOut);
3076}
3077
3078/************************************************************************
3079 * VarR8FromR4 (OLEAUT32.81)
3080 *
3081 * Convert a VT_R4 to a VT_R8.
3082 *
3083 * PARAMS
3084 * fltIn [I] Source
3085 * pDblOut [O] Destination
3086 *
3087 * RETURNS
3088 * S_OK.
3089 */
3090HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
3091{
3092 return _VarR8FromR4(fltIn, pDblOut);
3093}
3094
3095/************************************************************************
3096 * VarR8FromCy (OLEAUT32.82)
3097 *
3098 * Convert a VT_CY to a VT_R8.
3099 *
3100 * PARAMS
3101 * cyIn [I] Source
3102 * pDblOut [O] Destination
3103 *
3104 * RETURNS
3105 * S_OK.
3106 */
3107HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
3108{
3109 return _VarR8FromCy(cyIn, pDblOut);
3110}
3111
3112/************************************************************************
3113 * VarR8FromDate (OLEAUT32.83)
3114 *
3115 * Convert a VT_DATE to a VT_R8.
3116 *
3117 * PARAMS
3118 * dateIn [I] Source
3119 * pDblOut [O] Destination
3120 *
3121 * RETURNS
3122 * S_OK.
3123 */
3124HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
3125{
3126 return _VarR8FromDate(dateIn, pDblOut);
3127}
3128
3129/************************************************************************
3130 * VarR8FromStr (OLEAUT32.84)
3131 *
3132 * Convert a VT_BSTR to a VT_R8.
3133 *
3134 * PARAMS
3135 * strIn [I] Source
3136 * lcid [I] LCID for the conversion
3137 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3138 * pDblOut [O] Destination
3139 *
3140 * RETURNS
3141 * Success: S_OK.
3142 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3143 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3144 */
3145HRESULT WINAPI VarR8FromStr(const OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3146{
3147 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDblOut, VT_R8);
3148}
3149
3150/************************************************************************
3151 * VarR8FromDisp (OLEAUT32.85)
3152 *
3153 * Convert a VT_DISPATCH to a VT_R8.
3154 *
3155 * PARAMS
3156 * pdispIn [I] Source
3157 * lcid [I] LCID for conversion
3158 * pDblOut [O] Destination
3159 *
3160 * RETURNS
3161 * Success: S_OK.
3162 * Failure: E_INVALIDARG, if the source value is invalid
3163 * DISP_E_OVERFLOW, if the value will not fit in the destination
3164 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3165 */
3166HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3167{
3168 return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8, 0);
3169}
3170
3171/************************************************************************
3172 * VarR8FromBool (OLEAUT32.86)
3173 *
3174 * Convert a VT_BOOL to a VT_R8.
3175 *
3176 * PARAMS
3177 * boolIn [I] Source
3178 * pDblOut [O] Destination
3179 *
3180 * RETURNS
3181 * S_OK.
3182 */
3184{
3185 return VarR8FromI2(boolIn, pDblOut);
3186}
3187
3188/************************************************************************
3189 * VarR8FromI1 (OLEAUT32.217)
3190 *
3191 * Convert a VT_I1 to a VT_R8.
3192 *
3193 * PARAMS
3194 * cIn [I] Source
3195 * pDblOut [O] Destination
3196 *
3197 * RETURNS
3198 * Success: S_OK.
3199 * Failure: E_INVALIDARG, if the source value is invalid
3200 * DISP_E_OVERFLOW, if the value will not fit in the destination
3201 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3202 */
3203HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3204{
3205 return _VarR8FromI1(cIn, pDblOut);
3206}
3207
3208/************************************************************************
3209 * VarR8FromUI2 (OLEAUT32.218)
3210 *
3211 * Convert a VT_UI2 to a VT_R8.
3212 *
3213 * PARAMS
3214 * usIn [I] Source
3215 * pDblOut [O] Destination
3216 *
3217 * RETURNS
3218 * Success: S_OK.
3219 * Failure: E_INVALIDARG, if the source value is invalid
3220 * DISP_E_OVERFLOW, if the value will not fit in the destination
3221 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3222 */
3223HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3224{
3225 return _VarR8FromUI2(usIn, pDblOut);
3226}
3227
3228/************************************************************************
3229 * VarR8FromUI4 (OLEAUT32.219)
3230 *
3231 * Convert a VT_UI4 to a VT_R8.
3232 *
3233 * PARAMS
3234 * ulIn [I] Source
3235 * pDblOut [O] Destination
3236 *
3237 * RETURNS
3238 * Success: S_OK.
3239 * Failure: E_INVALIDARG, if the source value is invalid
3240 * DISP_E_OVERFLOW, if the value will not fit in the destination
3241 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3242 */
3243HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3244{
3245 return _VarR8FromUI4(ulIn, pDblOut);
3246}
3247
3248/************************************************************************
3249 * VarR8FromDec (OLEAUT32.220)
3250 *
3251 * Convert a VT_DECIMAL to a VT_R8.
3252 *
3253 * PARAMS
3254 * pDecIn [I] Source
3255 * pDblOut [O] Destination
3256 *
3257 * RETURNS
3258 * Success: S_OK.
3259 * Failure: E_INVALIDARG, if the source value is invalid.
3260 */
3261HRESULT WINAPI VarR8FromDec(const DECIMAL* pDecIn, double *pDblOut)
3262{
3263 BYTE scale = pDecIn->scale;
3264 double divisor = 1.0, highPart;
3265
3266 if (scale > DEC_MAX_SCALE || pDecIn->sign & ~DECIMAL_NEG)
3267 return E_INVALIDARG;
3268
3269 while (scale--)
3270 divisor *= 10;
3271
3272 if (pDecIn->sign)
3273 divisor = -divisor;
3274
3275 if (pDecIn->Hi32)
3276 {
3277 highPart = (double)pDecIn->Hi32 / divisor;
3278 highPart *= 4294967296.0F;
3279 highPart *= 4294967296.0F;
3280 }
3281 else
3282 highPart = 0.0;
3283
3284 *pDblOut = (double)pDecIn->Lo64 / divisor + highPart;
3285 return S_OK;
3286}
3287
3288/************************************************************************
3289 * VarR8FromI8 (OLEAUT32.362)
3290 *
3291 * Convert a VT_I8 to a VT_R8.
3292 *
3293 * PARAMS
3294 * ullIn [I] Source
3295 * pDblOut [O] Destination
3296 *
3297 * RETURNS
3298 * S_OK.
3299 */
3300HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3301{
3302 return _VarR8FromI8(llIn, pDblOut);
3303}
3304
3305/************************************************************************
3306 * VarR8FromUI8 (OLEAUT32.363)
3307 *
3308 * Convert a VT_UI8 to a VT_R8.
3309 *
3310 * PARAMS
3311 * ullIn [I] Source
3312 * pDblOut [O] Destination
3313 *
3314 * RETURNS
3315 * S_OK.
3316 */
3317HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3318{
3319 return _VarR8FromUI8(ullIn, pDblOut);
3320}
3321
3322/************************************************************************
3323 * VarR8Pow (OLEAUT32.315)
3324 *
3325 * Raise a VT_R8 to a power.
3326 *
3327 * PARAMS
3328 * dblLeft [I] Source
3329 * dblPow [I] Power to raise dblLeft by
3330 * pDblOut [O] Destination
3331 *
3332 * RETURNS
3333 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3334 */
3335HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3336{
3337 *pDblOut = pow(dblLeft, dblPow);
3338 return S_OK;
3339}
3340
3341/************************************************************************
3342 * VarR8Round (OLEAUT32.317)
3343 *
3344 * Round a VT_R8 to a given number of decimal points.
3345 *
3346 * PARAMS
3347 * dblIn [I] Source
3348 * nDig [I] Number of decimal points to round to
3349 * pDblOut [O] Destination for rounded number
3350 *
3351 * RETURNS
3352 * Success: S_OK. pDblOut is rounded to nDig digits.
3353 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3354 *
3355 * NOTES
3356 * The native version of this function rounds using the internal
3357 * binary representation of the number. Wine uses the dutch rounding
3358 * convention, so therefore small differences can occur in the value returned.
3359 * MSDN says that you should use your own rounding function if you want
3360 * rounding to be predictable in your application.
3361 */
3362HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3363{
3364 double scale, whole, fract;
3365
3366 if (nDig < 0)
3367 return E_INVALIDARG;
3368
3369 scale = pow(10.0, nDig);
3370
3371 dblIn *= scale;
3372 whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3373 fract = dblIn - whole;
3374
3375 if (fract > 0.5)
3376 dblIn = whole + 1.0;
3377 else if (fract == 0.5)
3378 dblIn = whole + fmod(whole, 2.0);
3379 else if (fract >= 0.0)
3380 dblIn = whole;
3381 else if (fract == -0.5)
3382 dblIn = whole + fmod(whole, 2.0);
3383 else if (fract > -0.5)
3384 dblIn = whole;
3385 else
3386 dblIn = whole - 1.0;
3387
3388 *pDblOut = dblIn / scale;
3389 return S_OK;
3390}
3391
3392/* CY
3393 */
3394
3395/* Powers of 10 from 0..4 D.P. */
3396static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3398
3399/************************************************************************
3400 * VarCyFromUI1 (OLEAUT32.98)
3401 *
3402 * Convert a VT_UI1 to a VT_CY.
3403 *
3404 * PARAMS
3405 * bIn [I] Source
3406 * pCyOut [O] Destination
3407 *
3408 * RETURNS
3409 * Success: S_OK.
3410 * Failure: E_INVALIDARG, if the source value is invalid
3411 * DISP_E_OVERFLOW, if the value will not fit in the destination
3412 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3413 */
3415{
3416 pCyOut->int64 = (ULONG64)bIn * CY_MULTIPLIER;
3417 return S_OK;
3418}
3419
3420/************************************************************************
3421 * VarCyFromI2 (OLEAUT32.99)
3422 *
3423 * Convert a VT_I2 to a VT_CY.
3424 *
3425 * PARAMS
3426 * sIn [I] Source
3427 * pCyOut [O] Destination
3428 *
3429 * RETURNS
3430 * Success: S_OK.
3431 * Failure: E_INVALIDARG, if the source value is invalid
3432 * DISP_E_OVERFLOW, if the value will not fit in the destination
3433 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3434 */
3436{
3437 pCyOut->int64 = (LONG64)sIn * CY_MULTIPLIER;
3438 return S_OK;
3439}
3440
3441/************************************************************************
3442 * VarCyFromI4 (OLEAUT32.100)
3443 *
3444 * Convert a VT_I4 to a VT_CY.
3445 *
3446 * PARAMS
3447 * sIn [I] Source
3448 * pCyOut [O] Destination
3449 *
3450 * RETURNS
3451 * Success: S_OK.
3452 * Failure: E_INVALIDARG, if the source value is invalid
3453 * DISP_E_OVERFLOW, if the value will not fit in the destination
3454 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3455 */
3457{
3458 pCyOut->int64 = (LONG64)lIn * CY_MULTIPLIER;
3459 return S_OK;
3460}
3461
3462/************************************************************************
3463 * VarCyFromR4 (OLEAUT32.101)
3464 *
3465 * Convert a VT_R4 to a VT_CY.
3466 *
3467 * PARAMS
3468 * fltIn [I] Source
3469 * pCyOut [O] Destination
3470 *
3471 * RETURNS
3472 * Success: S_OK.
3473 * Failure: E_INVALIDARG, if the source value is invalid
3474 * DISP_E_OVERFLOW, if the value will not fit in the destination
3475 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3476 */
3478{
3479 return VarCyFromR8(fltIn, pCyOut);
3480}
3481
3482/************************************************************************
3483 * VarCyFromR8 (OLEAUT32.102)
3484 *
3485 * Convert a VT_R8 to a VT_CY.
3486 *
3487 * PARAMS
3488 * dblIn [I] Source
3489 * pCyOut [O] Destination
3490 *
3491 * RETURNS
3492 * Success: S_OK.
3493 * Failure: E_INVALIDARG, if the source value is invalid
3494 * DISP_E_OVERFLOW, if the value will not fit in the destination
3495 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3496 */
3497HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3498{
3499#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3500 /* This code gives identical results to Win32 on Intel.
3501 * Here we use fp exceptions to catch overflows when storing the value.
3502 */
3503 static const unsigned short r8_fpcontrol = 0x137f;
3504 static const double r8_multiplier = CY_MULTIPLIER_F;
3505 unsigned short old_fpcontrol, result_fpstatus;
3506
3507 /* Clear exceptions, save the old fp state and load the new state */
3508 __asm__ __volatile__( "fnclex" );
3509 __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
3510 __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
3511 /* Perform the conversion. */
3512 __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
3513 __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
3514 __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
3515 /* Save the resulting fp state, load the old state and clear exceptions */
3516 __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
3517 __asm__ __volatile__( "fnclex" );
3518 __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
3519
3520 if (result_fpstatus & 0x9) /* Overflow | Invalid */
3521 return DISP_E_OVERFLOW;
3522#else
3523 /* This version produces slightly different results for boundary cases */
3524 if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3525 return DISP_E_OVERFLOW;
3526 dblIn *= CY_MULTIPLIER_F;
3527 VARIANT_DutchRound(LONG64, dblIn, pCyOut->int64);
3528#endif
3529 return S_OK;
3530}
3531
3532/************************************************************************
3533 * VarCyFromDate (OLEAUT32.103)
3534 *
3535 * Convert a VT_DATE to a VT_CY.
3536 *
3537 * PARAMS
3538 * dateIn [I] Source
3539 * pCyOut [O] Destination
3540 *
3541 * RETURNS
3542 * Success: S_OK.
3543 * Failure: E_INVALIDARG, if the source value is invalid
3544 * DISP_E_OVERFLOW, if the value will not fit in the destination
3545 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3546 */
3548{
3549 return VarCyFromR8(dateIn, pCyOut);
3550}
3551
3552/************************************************************************
3553 * VarCyFromStr (OLEAUT32.104)
3554 *
3555 * Convert a VT_BSTR to a VT_CY.
3556 *
3557 * PARAMS
3558 * strIn [I] Source
3559 * lcid [I] LCID for the conversion
3560 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3561 * pCyOut [O] Destination
3562 *
3563 * RETURNS
3564 * Success: S_OK.
3565 * Failure: E_INVALIDARG, if the source value is invalid
3566 * DISP_E_OVERFLOW, if the value will not fit in the destination
3567 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3568 */
3570{
3571 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pCyOut, VT_CY);
3572}
3573
3574/************************************************************************
3575 * VarCyFromDisp (OLEAUT32.105)
3576 *
3577 * Convert a VT_DISPATCH to a VT_CY.
3578 *
3579 * PARAMS
3580 * pdispIn [I] Source
3581 * lcid [I] LCID for conversion
3582 * pCyOut [O] Destination
3583 *
3584 * RETURNS
3585 * Success: S_OK.
3586 * Failure: E_INVALIDARG, if the source value is invalid
3587 * DISP_E_OVERFLOW, if the value will not fit in the destination
3588 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3589 */
3591{
3592 return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY, 0);
3593}
3594
3595/************************************************************************
3596 * VarCyFromBool (OLEAUT32.106)
3597 *
3598 * Convert a VT_BOOL to a VT_CY.
3599 *
3600 * PARAMS
3601 * boolIn [I] Source
3602 * pCyOut [O] Destination
3603 *
3604 * RETURNS
3605 * Success: S_OK.
3606 * Failure: E_INVALIDARG, if the source value is invalid
3607 * DISP_E_OVERFLOW, if the value will not fit in the destination
3608 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3609 *
3610 * NOTES
3611 * While the sign of the boolean is stored in the currency, the value is
3612 * converted to either 0 or 1.
3613 */
3615{
3616 pCyOut->int64 = (LONG64)boolIn * CY_MULTIPLIER;
3617 return S_OK;
3618}
3619
3620/************************************************************************
3621 * VarCyFromI1 (OLEAUT32.225)
3622 *
3623 * Convert a VT_I1 to a VT_CY.
3624 *
3625 * PARAMS
3626 * cIn [I] Source
3627 * pCyOut [O] Destination
3628 *
3629 * RETURNS
3630 * Success: S_OK.
3631 * Failure: E_INVALIDARG, if the source value is invalid
3632 * DISP_E_OVERFLOW, if the value will not fit in the destination
3633 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3634 */
3635HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3636{
3637 pCyOut->int64 = (LONG64)cIn * CY_MULTIPLIER;
3638 return S_OK;
3639}
3640
3641/************************************************************************
3642 * VarCyFromUI2 (OLEAUT32.226)
3643 *
3644 * Convert a VT_UI2 to a VT_CY.
3645 *
3646 * PARAMS
3647 * usIn [I] Source
3648 * pCyOut [O] Destination
3649 *
3650 * RETURNS
3651 * Success: S_OK.
3652 * Failure: E_INVALIDARG, if the source value is invalid
3653 * DISP_E_OVERFLOW, if the value will not fit in the destination
3654 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3655 */
3657{
3658 pCyOut->int64 = (ULONG64)usIn * CY_MULTIPLIER;
3659 return S_OK;
3660}
3661
3662/************************************************************************
3663 * VarCyFromUI4 (OLEAUT32.227)
3664 *
3665 * Convert a VT_UI4 to a VT_CY.
3666 *
3667 * PARAMS
3668 * ulIn [I] Source
3669 * pCyOut [O] Destination
3670 *
3671 * RETURNS
3672 * Success: S_OK.
3673 * Failure: E_INVALIDARG, if the source value is invalid
3674 * DISP_E_OVERFLOW, if the value will not fit in the destination
3675 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3676 */
3678{
3679 pCyOut->int64 = (ULONG64)ulIn * CY_MULTIPLIER;
3680 return S_OK;
3681}
3682
3683/************************************************************************
3684 * VarCyFromDec (OLEAUT32.228)
3685 *
3686 * Convert a VT_DECIMAL to a VT_CY.
3687 *
3688 * PARAMS
3689 * pdecIn [I] Source
3690 * pCyOut [O] Destination
3691 *
3692 * RETURNS
3693 * Success: S_OK.
3694 * Failure: E_INVALIDARG, if the source value is invalid
3695 * DISP_E_OVERFLOW, if the value will not fit in the destination
3696 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3697 */
3698HRESULT WINAPI VarCyFromDec(const DECIMAL* pdecIn, CY* pCyOut)
3699{
3700 DECIMAL rounded;
3701 HRESULT hRet;
3702
3703 hRet = VarDecRound(pdecIn, 4, &rounded);
3704
3705 if (SUCCEEDED(hRet))
3706 {
3707 double d;
3708
3709 if (rounded.Hi32)
3710 return DISP_E_OVERFLOW;
3711
3712 /* Note: Without the casts this promotes to int64 which loses precision */
3713 d = (double)rounded.Lo64 / (double)CY_Divisors[rounded.scale];
3714 if (rounded.sign)
3715 d = -d;
3716 return VarCyFromR8(d, pCyOut);
3717 }
3718 return hRet;
3719}
3720
3721/************************************************************************
3722 * VarCyFromI8 (OLEAUT32.366)
3723 *
3724 * Convert a VT_I8 to a VT_CY.
3725 *
3726 * PARAMS
3727 * ullIn [I] Source
3728 * pCyOut [O] Destination
3729 *
3730 * RETURNS
3731 * Success: S_OK.
3732 * Failure: E_INVALIDARG, if the source value is invalid
3733 * DISP_E_OVERFLOW, if the value will not fit in the destination
3734 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3735 */
3737{
3738 if (llIn <= (I8_MIN/CY_MULTIPLIER) || llIn >= (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
3739 pCyOut->int64 = llIn * CY_MULTIPLIER;
3740 return S_OK;
3741}
3742
3743/************************************************************************
3744 * VarCyFromUI8 (OLEAUT32.375)
3745 *
3746 * Convert a VT_UI8 to a VT_CY.
3747 *
3748 * PARAMS
3749 * ullIn [I] Source
3750 * pCyOut [O] Destination
3751 *
3752 * RETURNS
3753 * Success: S_OK.
3754 * Failure: E_INVALIDARG, if the source value is invalid
3755 * DISP_E_OVERFLOW, if the value will not fit in the destination
3756 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3757 */
3759{
3760 if (ullIn > (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
3761 pCyOut->int64 = ullIn * CY_MULTIPLIER;
3762 return S_OK;
3763}
3764
3765/************************************************************************
3766 * VarCyAdd (OLEAUT32.299)
3767 *
3768 * Add one CY to another.
3769 *
3770 * PARAMS
3771 * cyLeft [I] Source
3772 * cyRight [I] Value to add
3773 * pCyOut [O] Destination
3774 *
3775 * RETURNS
3776 * Success: S_OK.
3777 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3778 */
3779HRESULT WINAPI VarCyAdd(CY cyLeft, CY cyRight, CY* pCyOut)
3780{
3781 double l,r;
3782 _VarR8FromCy(cyLeft, &l);
3783 _VarR8FromCy(cyRight, &r);
3784 l = l + r;
3785 return VarCyFromR8(l, pCyOut);
3786}
3787
3788/************************************************************************
3789 * VarCyMul (OLEAUT32.303)
3790 *
3791 * Multiply one CY by another.
3792 *
3793 * PARAMS
3794 * cyLeft [I] Source
3795 * cyRight [I] Value to multiply by
3796 * pCyOut [O] Destination
3797 *
3798 * RETURNS
3799 * Success: S_OK.
3800 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3801 */
3802HRESULT WINAPI VarCyMul(CY cyLeft, CY cyRight, CY* pCyOut)
3803{
3804 double l,r;
3805 _VarR8FromCy(cyLeft, &l);
3806 _VarR8FromCy(cyRight, &r);
3807 l = l * r;
3808 return VarCyFromR8(l, pCyOut);
3809}
3810
3811/************************************************************************
3812 * VarCyMulI4 (OLEAUT32.304)
3813 *
3814 * Multiply one CY by a VT_I4.
3815 *
3816 * PARAMS
3817 * cyLeft [I] Source
3818 * lRight [I] Value to multiply by
3819 * pCyOut [O] Destination
3820 *
3821 * RETURNS
3822 * Success: S_OK.
3823 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3824 */
3825HRESULT WINAPI VarCyMulI4(CY cyLeft, LONG lRight, CY* pCyOut)
3826{
3827 double d;
3828
3829 _VarR8FromCy(cyLeft, &d);
3830 d = d * lRight;
3831 return VarCyFromR8(d, pCyOut);
3832}
3833
3834/************************************************************************
3835 * VarCySub (OLEAUT32.305)
3836 *
3837 * Subtract one CY from another.
3838 *
3839 * PARAMS
3840 * cyLeft [I] Source
3841 * cyRight [I] Value to subtract
3842 * pCyOut [O] Destination
3843 *
3844 * RETURNS
3845 * Success: S_OK.
3846 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3847 */
3848HRESULT WINAPI VarCySub(CY cyLeft, CY cyRight, CY* pCyOut)
3849{
3850 double l,r;
3851 _VarR8FromCy(cyLeft, &l);
3852 _VarR8FromCy(cyRight, &r);
3853 l = l - r;
3854 return VarCyFromR8(l, pCyOut);
3855}
3856
3857/************************************************************************
3858 * VarCyAbs (OLEAUT32.306)
3859 *
3860 * Convert a VT_CY into its absolute value.
3861 *
3862 * PARAMS
3863 * cyIn [I] Source
3864 * pCyOut [O] Destination
3865 *
3866 * RETURNS
3867 * Success: S_OK. pCyOut contains the absolute value.
3868 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3869 */
3871{
3872 if (cyIn.Hi == 0x80000000 && !cyIn.Lo)
3873 return DISP_E_OVERFLOW;
3874
3875 pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3876 return S_OK;
3877}
3878
3879/************************************************************************
3880 * VarCyFix (OLEAUT32.307)
3881 *
3882 * Return the integer part of a VT_CY.
3883 *
3884 * PARAMS
3885 * cyIn [I] Source
3886 * pCyOut [O] Destination
3887 *
3888 * RETURNS
3889 * Success: S_OK.
3890 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3891 *
3892 * NOTES
3893 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3894 * negative numbers away from 0, while this function rounds them towards zero.
3895 */
3897{
3898 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3899 pCyOut->int64 *= CY_MULTIPLIER;
3900 return S_OK;
3901}
3902
3903/************************************************************************
3904 * VarCyInt (OLEAUT32.308)
3905 *
3906 * Return the integer part of a VT_CY.
3907 *
3908 * PARAMS
3909 * cyIn [I] Source
3910 * pCyOut [O] Destination
3911 *
3912 * RETURNS
3913 * Success: S_OK.
3914 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3915 *
3916 * NOTES
3917 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3918 * negative numbers towards 0, while this function rounds them away from zero.
3919 */
3921{
3922 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3923 pCyOut->int64 *= CY_MULTIPLIER;
3924
3925 if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3926 {
3927 pCyOut->int64 -= CY_MULTIPLIER;
3928 }
3929 return S_OK;
3930}
3931
3932/************************************************************************
3933 * VarCyNeg (OLEAUT32.309)
3934 *
3935 * Change the sign of a VT_CY.
3936 *
3937 * PARAMS
3938 * cyIn [I] Source
3939 * pCyOut [O] Destination
3940 *
3941 * RETURNS
3942 * Success: S_OK.
3943 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3944 */
3946{
3947 if (cyIn.Hi == 0x80000000 && !cyIn.Lo)
3948 return DISP_E_OVERFLOW;
3949
3950 pCyOut->int64 = -cyIn.int64;
3951 return S_OK;
3952}
3953
3954/************************************************************************
3955 * VarCyRound (OLEAUT32.310)
3956 *
3957 * Change the precision of a VT_CY.
3958 *
3959 * PARAMS
3960 * cyIn [I] Source
3961 * cDecimals [I] New number of decimals to keep
3962 * pCyOut [O] Destination
3963 *
3964 * RETURNS
3965 * Success: S_OK.
3966 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3967 */
3968HRESULT WINAPI VarCyRound(CY cyIn, int cDecimals, CY* pCyOut)
3969{
3970 if (cDecimals < 0)
3971 return E_INVALIDARG;
3972
3973 if (cDecimals > 3)
3974 {
3975 /* Rounding to more precision than we have */
3976 *pCyOut = cyIn;
3977 return S_OK;
3978 }
3979 else
3980 {
3981 double d, div = CY_Divisors[cDecimals];
3982
3983 _VarR8FromCy(cyIn, &d);
3984 d = d * div;
3986 d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3988 return S_OK;
3989 }
3990}
3991
3992/************************************************************************
3993 * VarCyCmp (OLEAUT32.311)
3994 *
3995 * Compare two VT_CY values.
3996 *
3997 * PARAMS
3998 * cyLeft [I] Source
3999 * cyRight [I] Value to compare
4000 *
4001 * RETURNS
4002 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
4003 * compare is less, equal or greater than source respectively.
4004 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4005 */
4006HRESULT WINAPI VarCyCmp(CY cyLeft, CY cyRight)
4007{
4008 HRESULT hRet;
4009 CY result;
4010
4011 /* Subtract right from left, and compare the result to 0 */
4012 hRet = VarCySub(cyLeft, cyRight, &result);
4013
4014 if (SUCCEEDED(hRet))
4015 {
4016 if (result.int64 < 0)
4017 hRet = (HRESULT)VARCMP_LT;
4018 else if (result.int64 > 0)
4019 hRet = (HRESULT)VARCMP_GT;
4020 else
4021 hRet = (HRESULT)VARCMP_EQ;
4022 }
4023 return hRet;
4024}
4025
4026/************************************************************************
4027 * VarCyCmpR8 (OLEAUT32.312)
4028 *
4029 * Compare a VT_CY to a double
4030 *
4031 * PARAMS
4032 * cyLeft [I] Currency Source
4033 * dblRight [I] double to compare to cyLeft
4034 *
4035 * RETURNS
4036 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
4037 * less than, equal to or greater than cyLeft respectively.
4038 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4039 */
4040HRESULT WINAPI VarCyCmpR8(CY cyLeft, double dblRight)
4041{
4042 HRESULT hRet;
4043 CY cyRight;
4044
4045 hRet = VarCyFromR8(dblRight, &cyRight);
4046
4047 if (SUCCEEDED(hRet))
4048 hRet = VarCyCmp(cyLeft, cyRight);
4049
4050 return hRet;
4051}
4052
4053/************************************************************************
4054 * VarCyMulI8 (OLEAUT32.329)
4055 *
4056 * Multiply a VT_CY by a VT_I8.
4057 *
4058 * PARAMS
4059 * cyLeft [I] Source
4060 * llRight [I] Value to multiply by
4061 * pCyOut [O] Destination
4062 *
4063 * RETURNS
4064 * Success: S_OK.
4065 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4066 */
4067HRESULT WINAPI VarCyMulI8(CY cyLeft, LONG64 llRight, CY* pCyOut)
4068{
4069 double d;
4070
4071 _VarR8FromCy(cyLeft, &d);
4072 d = d * (double)llRight;
4073 return VarCyFromR8(d, pCyOut);
4074}
4075
4076/* DECIMAL
4077 */
4078
4079/************************************************************************
4080 * VarDecFromUI1 (OLEAUT32.190)
4081 *
4082 * Convert a VT_UI1 to a DECIMAL.
4083 *
4084 * PARAMS
4085 * bIn [I] Source
4086 * pDecOut [O] Destination
4087 *
4088 * RETURNS
4089 * S_OK.
4090 */
4092{
4093 return VarDecFromUI4(bIn, pDecOut);
4094}
4095
4096/************************************************************************
4097 * VarDecFromI2 (OLEAUT32.191)
4098 *
4099 * Convert a VT_I2 to a DECIMAL.
4100 *
4101 * PARAMS
4102 * sIn [I] Source
4103 * pDecOut [O] Destination
4104 *
4105 * RETURNS
4106 * S_OK.
4107 */
4109{
4110 return VarDecFromI4(sIn, pDecOut);
4111}
4112
4113/************************************************************************
4114 * VarDecFromI4 (OLEAUT32.192)
4115 *
4116 * Convert a VT_I4 to a DECIMAL.
4117 *
4118 * PARAMS
4119 * sIn [I] Source
4120 * pDecOut [O] Destination
4121 *
4122 * RETURNS
4123 * S_OK.
4124 */
4126{
4127 pDecOut->Hi32 = 0;
4128 pDecOut->Mid32 = 0;
4129 pDecOut->scale = 0;
4130
4131 if (lIn < 0)
4132 {
4133 pDecOut->sign = DECIMAL_NEG;
4134 pDecOut->Lo32 = -lIn;
4135 }
4136 else
4137 {
4138 pDecOut->sign = DECIMAL_POS;
4139 pDecOut->Lo32 = lIn;
4140 }
4141 return S_OK;
4142}
4143
4144/* internal representation of the value stored in a DECIMAL. The bytes are
4145 stored from LSB at index 0 to MSB at index 11
4146 */
4147typedef struct DECIMAL_internal
4148{
4149 DWORD bitsnum[3]; /* 96 significant bits, unsigned */
4150 unsigned char scale; /* number scaled * 10 ^ -(scale) */
4151 unsigned int sign : 1; /* 0 - positive, 1 - negative */
4153
4156static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to);
4157static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to);
4158static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor);
4159static BOOL VARIANT_int_iszero(const DWORD * p, unsigned int n);
4160
4161/************************************************************************
4162 * VarDecFromR4 (OLEAUT32.193)
4163 *
4164 * Convert a VT_R4 to a DECIMAL.
4165 *
4166 * PARAMS
4167 * fltIn [I] Source
4168 * pDecOut [O] Destination
4169 *
4170 * RETURNS
4171 * S_OK.
4172 */
4174{
4175 VARIANT_DI di;
4176 HRESULT hres;
4177
4178 hres = VARIANT_DI_FromR4(fltIn, &di);
4179 if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
4180 return hres;
4181}
4182
4183/************************************************************************
4184 * VarDecFromR8 (OLEAUT32.194)
4185 *
4186 * Convert a VT_R8 to a DECIMAL.
4187 *
4188 * PARAMS
4189 * dblIn [I] Source
4190 * pDecOut [O] Destination
4191 *
4192 * RETURNS
4193 * S_OK.
4194 */
4195HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4196{
4197 VARIANT_DI di;
4198 HRESULT hres;
4199
4200 hres = VARIANT_DI_FromR8(dblIn, &di);
4201 if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
4202 return hres;
4203}
4204
4205/************************************************************************
4206 * VarDecFromDate (OLEAUT32.195)
4207 *
4208 * Convert a VT_DATE to a DECIMAL.
4209 *
4210 * PARAMS
4211 * dateIn [I] Source
4212 * pDecOut [O] Destination
4213 *
4214 * RETURNS
4215 * S_OK.
4216 */
4218{
4219 return VarDecFromR8(dateIn, pDecOut);
4220}
4221
4222/************************************************************************
4223 * VarDecFromCy (OLEAUT32.196)
4224 *
4225 * Convert a VT_CY to a DECIMAL.
4226 *
4227 * PARAMS
4228 * cyIn [I] Source
4229 * pDecOut [O] Destination
4230 *
4231 * RETURNS
4232 * S_OK.
4233 */
4235{
4236 pDecOut->Hi32 = 0;
4237 pDecOut->scale = 4;
4238
4239 if (cyIn.int64 < 0)
4240 {
4241 pDecOut->sign = DECIMAL_NEG;
4242 pDecOut->Lo64 = -cyIn.int64;
4243 }
4244 else
4245 {
4246 pDecOut->sign = DECIMAL_POS;
4247 pDecOut->Lo64 = cyIn.int64;
4248 }
4249 return S_OK;
4250}
4251
4252/************************************************************************
4253 * VarDecFromStr (OLEAUT32.197)
4254 *
4255 * Convert a VT_BSTR to a DECIMAL.
4256 *
4257 * PARAMS
4258 * strIn [I] Source
4259 * lcid [I] LCID for the conversion
4260 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4261 * pDecOut [O] Destination
4262 *
4263 * RETURNS
4264 * Success: S_OK.
4265 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4266 */
4268{
4269 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDecOut, VT_DECIMAL);
4270}
4271
4272/************************************************************************
4273 * VarDecFromDisp (OLEAUT32.198)
4274 *
4275 * Convert a VT_DISPATCH to a DECIMAL.
4276 *
4277 * PARAMS
4278 * pdispIn [I] Source
4279 * lcid [I] LCID for conversion
4280 * pDecOut [O] Destination
4281 *
4282 * RETURNS
4283 * Success: S_OK.
4284 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4285 */
4287{
4288 return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL, 0);
4289}
4290
4291/************************************************************************
4292 * VarDecFromBool (OLEAUT32.199)
4293 *
4294 * Convert a VT_BOOL to a DECIMAL.
4295 *
4296 * PARAMS
4297 * bIn [I] Source
4298 * pDecOut [O] Destination
4299 *
4300 * RETURNS
4301 * S_OK.
4302 *
4303 * NOTES
4304 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4305 */
4307{
4308 pDecOut->Hi32 = 0;
4309 pDecOut->scale = 0;
4310 if (bIn)
4311 {
4312 pDecOut->sign = DECIMAL_NEG;
4313 pDecOut->Lo64 = 1;
4314 }
4315 else
4316 {
4317 pDecOut->sign = DECIMAL_POS;
4318 pDecOut->Lo64 = 0;
4319 }
4320 return S_OK;
4321}
4322
4323/************************************************************************
4324 * VarDecFromI1 (OLEAUT32.241)
4325 *
4326 * Convert a VT_I1 to a DECIMAL.
4327 *
4328 * PARAMS
4329 * cIn [I] Source
4330 * pDecOut [O] Destination
4331 *
4332 * RETURNS
4333 * S_OK.
4334 */
4335HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4336{
4337 return VarDecFromI4(cIn, pDecOut);
4338}
4339
4340/************************************************************************
4341 * VarDecFromUI2 (OLEAUT32.242)
4342 *
4343 * Convert a VT_UI2 to a DECIMAL.
4344 *
4345 * PARAMS
4346 * usIn [I] Source
4347 * pDecOut [O] Destination
4348 *
4349 * RETURNS
4350 * S_OK.
4351 */
4353{
4354 return VarDecFromUI4(usIn, pDecOut);
4355}
4356
4357/************************************************************************
4358 * VarDecFromUI4 (OLEAUT32.243)
4359 *
4360 * Convert a VT_UI4 to a DECIMAL.
4361 *
4362 * PARAMS
4363 * ulIn [I] Source
4364 * pDecOut [O] Destination
4365 *
4366 * RETURNS
4367 * S_OK.
4368 */
4370{
4371 pDecOut->sign = DECIMAL_POS;
4372 pDecOut->scale = 0;
4373 pDecOut->Hi32 = 0;
4374 pDecOut->Lo64 = ulIn;
4375 return S_OK;
4376}
4377
4378/************************************************************************
4379 * VarDecFromI8 (OLEAUT32.374)
4380 *
4381 * Convert a VT_I8 to a DECIMAL.
4382 *
4383 * PARAMS
4384 * llIn [I] Source
4385 * pDecOut [O] Destination
4386 *
4387 * RETURNS
4388 * S_OK.
4389 */
4391{
4392 pDecOut->Hi32 = 0;
4393 pDecOut->scale = 0;
4394
4395 if (llIn < 0)
4396 {
4397 pDecOut->sign = DECIMAL_NEG;
4398 pDecOut->Lo64 = -llIn;
4399 }
4400 else
4401 {
4402 pDecOut->sign = DECIMAL_POS;
4403 pDecOut->Lo64 = llIn;
4404 }
4405 return S_OK;
4406}
4407
4408/************************************************************************
4409 * VarDecFromUI8 (OLEAUT32.375)
4410 *
4411 * Convert a VT_UI8 to a DECIMAL.
4412 *
4413 * PARAMS
4414 * ullIn [I] Source
4415 * pDecOut [O] Destination
4416 *
4417 * RETURNS
4418 * S_OK.
4419 */
4421{
4422 pDecOut->sign = DECIMAL_POS;
4423 pDecOut->scale = 0;
4424 pDecOut->Hi32 = 0;
4425 pDecOut->Lo64 = ullIn;
4426 return S_OK;
4427}
4428
4429/* Make two DECIMALS the same scale; used by math functions below */
4430static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4431 const DECIMAL** ppDecRight,
4432 DECIMAL pDecOut[2])
4433{
4434 static DECIMAL scaleFactor;
4435 unsigned char remainder;
4436 DECIMAL decTemp;
4437 VARIANT_DI di;
4438 int scaleAmount, i;
4439
4440 if ((*ppDecLeft)->sign & ~DECIMAL_NEG || (*ppDecRight)->sign & ~DECIMAL_NEG)
4441 return E_INVALIDARG;
4442
4443 scaleFactor.Lo32 = 10;
4444
4445 i = scaleAmount = (*ppDecLeft)->scale - (*ppDecRight)->scale;
4446
4447 if (!scaleAmount)
4448 return S_OK; /* Same scale */
4449
4450 if (scaleAmount > 0)
4451 {
4452 decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4453 *ppDecRight = &pDecOut[0];
4454 }
4455 else
4456 {
4457 decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4458 *ppDecLeft = &pDecOut[0];
4459 i = -scaleAmount;
4460 }
4461
4462 /* Multiply up the value to be scaled by the correct amount (if possible) */
4463 while (i > 0 && SUCCEEDED(VarDecMul(&decTemp, &scaleFactor, &pDecOut[0])))
4464 {
4465 decTemp = pDecOut[0];
4466 i--;
4467 }
4468
4469 if (!i)
4470 {
4471 pDecOut[0].scale += (scaleAmount > 0) ? scaleAmount : (-scaleAmount);
4472 return S_OK; /* Same scale */
4473 }
4474
4475 /* Scaling further not possible, reduce accuracy of other argument */
4476 pDecOut[0] = decTemp;
4477 if (scaleAmount > 0)
4478 {
4479 pDecOut[0].scale += scaleAmount - i;
4480 VARIANT_DIFromDec(*ppDecLeft, &di);
4481 *ppDecLeft = &pDecOut[1];
4482 }
4483 else
4484 {
4485 pDecOut[0].scale += (-scaleAmount) - i;
4486 VARIANT_DIFromDec(*ppDecRight, &di);
4487 *ppDecRight = &pDecOut[1];
4488 }
4489
4490 di.scale -= i;
4491 remainder = 0;
4492 while (i-- > 0 && !VARIANT_int_iszero(di.bitsnum, ARRAY_SIZE(di.bitsnum)))
4493 {
4495 if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
4496 }
4497
4498 /* round up the result - native oleaut32 does this */
4499 if (remainder >= 5) {
4500 for (remainder = 1, i = 0; i < ARRAY_SIZE(di.bitsnum) && remainder; i++) {
4501 ULONGLONG digit = di.bitsnum[i] + 1;
4502 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4503 di.bitsnum[i] = digit & 0xFFFFFFFF;
4504 }
4505 }
4506
4507 VARIANT_DecFromDI(&di, &pDecOut[1]);
4508 return S_OK;
4509}
4510
4511/* Add two unsigned 32 bit values with overflow */
4512static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4513{
4514 ULARGE_INTEGER ul64;
4515
4516 ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4517 *pulHigh = ul64.HighPart;
4518 return ul64.LowPart;
4519}
4520
4521/* Subtract two unsigned 32 bit values with underflow */
4522static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4523{
4524 BOOL invert = FALSE;
4525 ULARGE_INTEGER ul64;
4526
4527 ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4528 if (ulLeft < ulRight)
4529 invert = TRUE;
4530
4531 if (ul64.QuadPart > (ULONG64)*pulHigh)
4532 ul64.QuadPart -= (ULONG64)*pulHigh;
4533 else
4534 {
4535 ul64.QuadPart -= (ULONG64)*pulHigh;
4536 invert = TRUE;
4537 }
4538 if (invert)
4539 ul64.HighPart = -ul64.HighPart ;
4540
4541 *pulHigh = ul64.HighPart;
4542 return ul64.LowPart;
4543}
4544
4545/* Multiply two unsigned 32 bit values with overflow */
4546static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4547{
4548 ULARGE_INTEGER ul64;
4549
4550 ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4551 *pulHigh = ul64.HighPart;
4552 return ul64.LowPart;
4553}
4554
4555/* Compare two decimals that have the same scale */
4556static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4557{
4558 if ( pDecLeft->Hi32 < pDecRight->Hi32 ||
4559 (pDecLeft->Hi32 <= pDecRight->Hi32 && pDecLeft->Lo64 < pDecRight->Lo64))
4560 return -1;
4561 else if (pDecLeft->Hi32 == pDecRight->Hi32 && pDecLeft->Lo64 == pDecRight->Lo64)
4562 return 0;
4563 return 1;
4564}
4565
4566/************************************************************************
4567 * VarDecAdd (OLEAUT32.177)
4568 *
4569 * Add one DECIMAL to another.
4570 *
4571 * PARAMS
4572 * pDecLeft [I] Source
4573 * pDecRight [I] Value to add
4574 * pDecOut [O] Destination
4575 *
4576 * RETURNS
4577 * Success: S_OK.
4578 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4579 */
4580HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4581{
4582 HRESULT hRet;
4583 DECIMAL scaled[2];
4584
4585 hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, scaled);
4586
4587 if (SUCCEEDED(hRet))
4588 {
4589 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4590 ULONG overflow = 0;
4592 int cmp;
4593
4594 /* Correct for the sign of the result */
4595 if (pDecLeft->sign && pDecRight->sign)
4596 {
4597 /* -x + -y : Negative */
4598 sign = DECIMAL_NEG;
4599 goto VarDecAdd_AsPositive;
4600 }
4601 else if (pDecLeft->sign && !pDecRight->sign)
4602 {
4603 cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4604
4605 /* -x + y : Negative if x > y */
4606 if (cmp > 0)
4607 {
4608 sign = DECIMAL_NEG;
4609VarDecAdd_AsNegative:
4610 pDecOut->Lo32 = VARIANT_Sub(pDecLeft->Lo32, pDecRight->Lo32, &overflow);
4611 pDecOut->Mid32 = VARIANT_Sub(pDecLeft->Mid32, pDecRight->Mid32, &overflow);
4612 pDecOut->Hi32 = VARIANT_Sub(pDecLeft->Hi32, pDecRight->Hi32, &overflow);
4613 }
4614 else
4615 {
4616VarDecAdd_AsInvertedNegative:
4617 pDecOut->Lo32 = VARIANT_Sub(pDecRight->Lo32, pDecLeft->Lo32, &overflow);
4618 pDecOut->Mid32 = VARIANT_Sub(pDecRight->Mid32, pDecLeft->Mid32, &overflow);
4619 pDecOut->Hi32 = VARIANT_Sub(pDecRight->Hi32, pDecLeft->Hi32, &overflow);
4620 }
4621 }
4622 else if (!pDecLeft->sign && pDecRight->sign)
4623 {
4624 cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4625
4626 /* x + -y : Negative if x <= y */
4627 if (cmp <= 0)
4628 {
4629 sign = DECIMAL_NEG;
4630 goto VarDecAdd_AsInvertedNegative;
4631 }
4632 goto VarDecAdd_AsNegative;
4633 }
4634 else
4635 {
4636 /* x + y : Positive */
4637VarDecAdd_AsPositive:
4638 pDecOut->Lo32 = VARIANT_Add(pDecLeft->Lo32, pDecRight->Lo32, &overflow);
4639 pDecOut->Mid32 = VARIANT_Add(pDecLeft->Mid32, pDecRight->Mid32, &overflow);
4640 pDecOut->Hi32 = VARIANT_Add(pDecLeft->Hi32, pDecRight->Hi32, &overflow);
4641
4642 if (overflow)
4643 {
4644 int i;
4645 DWORD n[4];
4646 unsigned char remainder;
4647
4648 if (!pDecLeft->scale)
4649 return DISP_E_OVERFLOW;
4650
4651 pDecOut->scale = pDecLeft->scale - 1;
4652 pDecOut->sign = sign;
4653
4654 n[0] = pDecOut->Lo32;
4655 n[1] = pDecOut->Mid32;
4656 n[2] = pDecOut->Hi32;
4657 n[3] = overflow;
4658
4660
4661 /* round up the result */
4662 if (remainder >= 5)
4663 {
4664 for (remainder = 1, i = 0; i < ARRAY_SIZE(n) && remainder; i++)
4665 {
4666 ULONGLONG digit = n[i] + 1;
4667 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4668 n[i] = digit & 0xFFFFFFFF;
4669 }
4670 }
4671
4672 pDecOut->Lo32 = n[0] ;
4673 pDecOut->Mid32 = n[1];
4674 pDecOut->Hi32 = n[2];
4675
4676 return S_OK;
4677 }
4678 }
4679
4680 if (overflow)
4681 return DISP_E_OVERFLOW; /* overflowed */
4682
4683 pDecOut->scale = pDecLeft->scale;
4684 pDecOut->sign = sign;
4685 }
4686 return hRet;
4687}
4688
4689/* translate from external DECIMAL format into an internal representation */
4690static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to)
4691{
4692 to->scale = from->scale;
4693 to->sign = from->sign ? 1 : 0;
4694
4695 to->bitsnum[0] = from->Lo32;
4696 to->bitsnum[1] = from->Mid32;
4697 to->bitsnum[2] = from->Hi32;
4698}
4699
4700static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to)
4701{
4702 to->sign = from->sign ? DECIMAL_NEG : DECIMAL_POS;
4703 to->scale = from->scale;
4704 to->Lo32 = from->bitsnum[0];
4705 to->Mid32 = from->bitsnum[1];
4706 to->Hi32 = from->bitsnum[2];
4707}
4708
4709/* clear an internal representation of a DECIMAL */
4711{
4712 memset(i, 0, sizeof(VARIANT_DI));
4713}
4714
4715/* divide the (unsigned) number stored in p (LSB) by a byte value (<= 0xff). Any nonzero
4716 size is supported. The value in p is replaced by the quotient of the division, and
4717 the remainder is returned as a result. This routine is most often used with a divisor
4718 of 10 in order to scale up numbers, and in the DECIMAL->string conversion.
4719 */
4720static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor)
4721{
4722 if (divisor == 0) {
4723 /* division by 0 */
4724 return 0xFF;
4725 } else if (divisor == 1) {
4726 /* dividend remains unchanged */
4727 return 0;
4728 } else {
4729 unsigned char remainder = 0;
4730 ULONGLONG iTempDividend;
4731 signed int i;
4732
4733 for (i = n - 1; i >= 0 && !p[i]; i--); /* skip leading zeros */
4734 for (; i >= 0; i--) {
4735 iTempDividend = ((ULONGLONG)remainder << 32) + p[i];
4736 remainder = iTempDividend % divisor;
4737 p[i] = iTempDividend / divisor;
4738 }
4739
4740 return remainder;
4741 }
4742}
4743
4744/* check to test if encoded number is a zero. Returns 1 if zero, 0 for nonzero */
4745static BOOL VARIANT_int_iszero(const DWORD * p, unsigned int n)
4746{
4747 for (; n > 0; n--) if (*p++ != 0) return FALSE;
4748 return TRUE;
4749}
4750
4751/* multiply two DECIMALS, without changing either one, and place result in third
4752 parameter. Result is normalized when scale is > 0. Attempts to remove significant
4753 digits when scale > 0 in order to fit an overflowing result. Final overflow
4754 flag is returned.
4755 */
4756static int VARIANT_DI_mul(const VARIANT_DI * a, const VARIANT_DI * b, VARIANT_DI * result)
4757{
4758 BOOL r_overflow = FALSE;
4759 DWORD running[6];
4760 signed int mulstart;
4761
4763 result->sign = (a->sign ^ b->sign) ? 1 : 0;
4764
4765 /* Multiply 128-bit operands into a (max) 256-bit result. The scale
4766 of the result is formed by adding the scales of the operands.
4767 */
4768 result->scale = a->scale + b->scale;
4769 memset(running, 0, sizeof(running));
4770
4771 /* count number of leading zero-bytes in operand A */
4772 for (mulstart = ARRAY_SIZE(a->bitsnum) - 1; mulstart >= 0 && !a->bitsnum[mulstart]; mulstart--);
4773 if (mulstart < 0) {
4774 /* result is 0, because operand A is 0 */
4775 result->scale = 0;
4776 result->sign = 0;
4777 } else {
4778 unsigned char remainder = 0;
4779 int iA;
4780
4781 /* perform actual multiplication */
4782 for (iA = 0; iA <= mulstart; iA++) {
4783 ULONG iOverflowMul;
4784 int iB;
4785
4786 for (iOverflowMul = 0, iB = 0; iB < ARRAY_SIZE(b->bitsnum); iB++) {
4787 ULONG iRV;
4788 int iR;
4789
4790 iRV = VARIANT_Mul(b->bitsnum[iB], a->bitsnum[iA], &iOverflowMul);
4791 iR = iA + iB;
4792 do {
4793 running[iR] = VARIANT_Add(running[iR], 0, &iRV);
4794 iR++;
4795 } while (iRV);
4796 }
4797 }
4798
4799/* Too bad - native oleaut does not do this, so we should not either */
4800#if 0
4801 /* While the result is divisible by 10, and the scale > 0, divide by 10.
4802 This operation should not lose significant digits, and gives an
4803 opportunity to reduce the possibility of overflows in future
4804 operations issued by the application.
4805 */
4806 while (result->scale > 0) {
4807 memcpy(quotient, running, sizeof(quotient));
4808 remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
4809 if (remainder > 0) break;
4810 memcpy(running, quotient, sizeof(quotient));
4811 result->scale--;
4812 }
4813#endif
4814 /* While the 256-bit result overflows, and the scale > 0, divide by 10.
4815 This operation *will* lose significant digits of the result because
4816 all the factors of 10 were consumed by the previous operation.
4817 */
4818 while (result->scale > 0 && !VARIANT_int_iszero(running + ARRAY_SIZE(result->bitsnum),
4819 ARRAY_SIZE(running) - ARRAY_SIZE(result->bitsnum))) {
4820
4821 remainder = VARIANT_int_divbychar(running, ARRAY_SIZE(running), 10);
4822 if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
4823 result->scale--;
4824 }
4825
4826 /* round up the result - native oleaut32 does this */
4827 if (remainder >= 5) {
4828 unsigned int i;
4829 for (remainder = 1, i = 0; i < ARRAY_SIZE(running) && remainder; i++) {
4830 ULONGLONG digit = running[i] + 1;
4831 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4832 running[i] = digit & 0xFFFFFFFF;
4833 }
4834 }
4835
4836 /* Signal overflow if scale == 0 and 256-bit result still overflows,
4837 and copy result bits into result structure
4838 */
4839 r_overflow = !VARIANT_int_iszero(running + ARRAY_SIZE(result->bitsnum),
4840 ARRAY_SIZE(running) - ARRAY_SIZE(result->bitsnum));
4841 memcpy(result->bitsnum, running, sizeof(result->bitsnum));
4842 }
4843 return r_overflow;
4844}
4845
4846/* cast DECIMAL into string. Any scale should be handled properly. en_US locale is
4847 hardcoded (period for decimal separator, dash as negative sign). Returns TRUE for
4848 success, FALSE if insufficient space in output buffer.
4849 */
4850static BOOL VARIANT_DI_tostringW(const VARIANT_DI * a, WCHAR * s, unsigned int n)
4851{
4852 BOOL overflow = FALSE;
4853 DWORD quotient[3];
4854 unsigned char remainder;
4855 unsigned int i;
4856
4857 /* place negative sign */
4858 if (!VARIANT_int_iszero(a->bitsnum, ARRAY_SIZE(a->bitsnum)) && a->sign) {
4859 if (n > 0) {
4860 *s++ = '-';
4861 n--;
4862 }
4863 else overflow = TRUE;
4864 }
4865
4866 /* prepare initial 0 */
4867 if (!overflow) {
4868 if (n >= 2) {
4869 s[0] = '0';
4870 s[1] = '\0';
4871 } else overflow = TRUE;
4872 }
4873
4874 i = 0;
4875 memcpy(quotient, a->bitsnum, sizeof(a->bitsnum));
4876 while (!overflow && !VARIANT_int_iszero(quotient, ARRAY_SIZE(quotient))) {
4877 remainder = VARIANT_int_divbychar(quotient, ARRAY_SIZE(quotient), 10);
4878 if (i + 2 > n) {
4879 overflow = TRUE;
4880 } else {
4881 s[i++] = '0' + remainder;
4882 s[i] = '\0';
4883 }
4884 }
4885
4886 if (!overflow && !VARIANT_int_iszero(a->bitsnum, ARRAY_SIZE(a->bitsnum))) {
4887
4888 /* reverse order of digits */
4889 WCHAR * x = s; WCHAR * y = s + i - 1;
4890 while (x < y) {
4891 *x ^= *y;
4892 *y ^= *x;
4893 *x++ ^= *y--;
4894 }
4895
4896 /* check for decimal point. "i" now has string length */
4897 if (i <= a->scale) {
4898 unsigned int numzeroes = a->scale + 1 - i;
4899 if (i + 1 + numzeroes >= n) {
4900 overflow = TRUE;
4901 } else {
4902 memmove(s + numzeroes, s, (i + 1) * sizeof(WCHAR));
4903 i += numzeroes;
4904 while (numzeroes > 0) {
4905 s[--numzeroes] = '0';
4906 }
4907 }
4908 }
4909
4910 /* place decimal point */
4911 if (a->scale > 0) {
4912 unsigned int periodpos = i - a->scale;
4913 if (i + 2 >= n) {
4914 overflow = TRUE;
4915 } else {
4916 memmove(s + periodpos + 1, s + periodpos, (i + 1 - periodpos) * sizeof(WCHAR));
4917 s[periodpos] = '.'; i++;
4918
4919 /* remove extra zeros at the end, if any */
4920 while (s[i - 1] == '0') s[--i] = '\0';
4921 if (s[i - 1] == '.') s[--i] = '\0';
4922 }
4923 }
4924 }
4925
4926 return !overflow;
4927}
4928
4929/* shift the bits of a DWORD array to the left. p[0] is assumed LSB */
4930static void VARIANT_int_shiftleft(DWORD * p, unsigned int n, unsigned int shift)
4931{
4932 DWORD shifted;
4933 unsigned int i;
4934
4935 /* shift whole DWORDs to the left */
4936 while (shift >= 32)
4937 {
4938 memmove(p + 1, p, (n - 1) * sizeof(DWORD));
4939 *p = 0; shift -= 32;
4940 }
4941
4942 /* shift remainder (1..31 bits) */
4943 shifted = 0;
4944 if (shift > 0) for (i = 0; i < n; i++)
4945 {
4946 DWORD b;
4947 b = p[i] >> (32 - shift);
4948 p[i] = (p[i] << shift) | shifted;
4949 shifted = b;
4950 }
4951}
4952
4953/* add the (unsigned) numbers stored in two DWORD arrays with LSB at index 0.
4954 Value at v is incremented by the value at p. Any size is supported, provided
4955 that v is not shorter than p. Any unapplied carry is returned as a result.
4956 */
4957static unsigned char VARIANT_int_add(DWORD * v, unsigned int nv, const DWORD * p,
4958 unsigned int np)
4959{
4960 unsigned char carry = 0;
4961
4962 if (nv >= np) {
4963 ULONGLONG sum;
4964 unsigned int i;
4965
4966 for (i = 0; i < np; i++) {
4967 sum = (ULONGLONG)v[i]
4968 + (ULONGLONG)p[i]
4969 + (ULONGLONG)carry;
4970 v[i] = sum & 0xffffffff;
4971 carry = sum >> 32;
4972 }
4973 for (; i < nv && carry; i++) {
4974 sum = (ULONGLONG)v[i]
4975 + (ULONGLONG)carry;
4976 v[i] = sum & 0xffffffff;
4977 carry = sum >> 32;
4978 }
4979 }
4980 return carry;
4981}
4982
4983/* perform integral division with operand p as dividend. Parameter n indicates
4984 number of available DWORDs in divisor p, but available space in p must be
4985 actually at least 2 * n DWORDs, because the remainder of the integral
4986 division is built in the next n DWORDs past the start of the quotient. This
4987 routine replaces the dividend in p with the quotient, and appends n
4988 additional DWORDs for the remainder.
4989
4990 Thanks to Lee & Mark Atkinson for their book _Using_C_ (my very first book on
4991 C/C++ :-) where the "longhand binary division" algorithm was exposed for the
4992 source code to the VLI (Very Large Integer) division operator. This algorithm
4993 was then heavily modified by me (Alex Villacis Lasso) in order to handle
4994 variably-scaled integers such as the MS DECIMAL representation.
4995 */
4996static void VARIANT_int_div(DWORD * p, unsigned int n, const DWORD * divisor,
4997 unsigned int dn)
4998{
4999 unsigned int i;
5000 DWORD tempsub[8];
5001 DWORD * negdivisor = tempsub + n;
5002
5003 /* build 2s-complement of divisor */
5004 for (i = 0; i < n; i++) negdivisor[i] = (i < dn) ? ~divisor[i] : 0xFFFFFFFF;
5005 p[n] = 1;
5006 VARIANT_int_add(negdivisor, n, p + n, 1);
5007 memset(p + n, 0, n * sizeof(DWORD));
5008
5009 /* skip all leading zero DWORDs in quotient */
5010 for (i = 0; i < n && !p[n - 1]; i++) VARIANT_int_shiftleft(p, n, 32);
5011 /* i is now number of DWORDs left to process */
5012 for (i <<= 5; i < (n << 5); i++) {
5013 VARIANT_int_shiftleft(p, n << 1, 1); /* shl quotient+remainder */
5014
5015 /* trial subtraction */
5016 memcpy(tempsub, p + n, n * sizeof(DWORD));
5017 VARIANT_int_add(tempsub, n, negdivisor, n);
5018
5019 /* check whether result of subtraction was negative */
5020 if ((tempsub[n - 1] & 0x80000000) == 0) {
5021 memcpy(p + n, tempsub, n * sizeof(DWORD));
5022 p[0] |= 1;
5023 }
5024 }
5025}
5026
5027/* perform integral multiplication by a byte operand. Used for scaling by 10 */
5028static unsigned char VARIANT_int_mulbychar(DWORD * p, unsigned int n, unsigned char m)
5029{
5030 unsigned int i;
5031 ULONG iOverflowMul;
5032
5033 for (iOverflowMul = 0, i = 0; i < n; i++)
5034 p[i] = VARIANT_Mul(p[i], m, &iOverflowMul);
5035 return (unsigned char)iOverflowMul;
5036}
5037
5038/* increment value in A by the value indicated in B, with scale adjusting.
5039 Modifies parameters by adjusting scales. Returns 0 if addition was
5040 successful, nonzero if a parameter underflowed before it could be
5041 successfully used in the addition.
5042 */
5044 DWORD * a, int * ascale, unsigned int an,
5045 DWORD * b, int * bscale, unsigned int bn)
5046{
5047 int underflow = 0;
5048
5049 if (VARIANT_int_iszero(a, an)) {
5050 /* if A is zero, copy B into A, after removing digits */
5051 while (bn > an && !VARIANT_int_iszero(b + an, bn - an)) {
5052 VARIANT_int_divbychar(b, bn, 10);
5053 (*bscale)--;
5054 }
5055 memcpy(a, b, an * sizeof(DWORD));
5056 *ascale = *bscale;
5057 } else if (!VARIANT_int_iszero(b, bn)) {
5058 unsigned int tn = an + 1;
5059 DWORD t[5];
5060
5061 if (bn + 1 > tn) tn = bn + 1;
5062 if (*ascale != *bscale) {
5063 /* first (optimistic) try - try to scale down the one with the bigger
5064 scale, while this number is divisible by 10 */
5065 DWORD * digitchosen;
5066 unsigned int nchosen;
5067 int * scalechosen;
5068 int targetscale;
5069
5070 if (*ascale < *bscale) {
5071 targetscale = *ascale;
5072 scalechosen = bscale;
5073 digitchosen = b;
5074 nchosen = bn;
5075 } else {
5076 targetscale = *bscale;
5077 scalechosen = ascale;
5078 digitchosen = a;
5079 nchosen = an;
5080 }
5081 memset(t, 0, tn * sizeof(DWORD));
5082 memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5083
5084 /* divide by 10 until target scale is reached */
5085 while (*scalechosen > targetscale) {
5086 unsigned char remainder = VARIANT_int_divbychar(t, tn, 10);
5087 if (!remainder) {
5088 (*scalechosen)--;
5089 memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5090 } else break;
5091 }
5092 }
5093
5094 if (*ascale != *bscale) {
5095 DWORD * digitchosen;
5096 unsigned int nchosen;
5097 int * scalechosen;
5098 int targetscale;
5099
5100 /* try to scale up the one with the smaller scale */
5101 if (*ascale > *bscale) {
5102 targetscale = *ascale;
5103 scalechosen = bscale;
5104 digitchosen = b;
5105 nchosen = bn;
5106 } else {
5107 targetscale = *bscale;
5108 scalechosen = ascale;
5109 digitchosen = a;
5110 nchosen = an;
5111 }
5112 memset(t, 0, tn * sizeof(DWORD));
5113 memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5114
5115 /* multiply by 10 until target scale is reached, or
5116 significant bytes overflow the number
5117 */
5118 while (*scalechosen < targetscale && t[nchosen] == 0) {
5119 VARIANT_int_mulbychar(t, tn, 10);
5120 if (t[nchosen] == 0) {
5121 /* still does not overflow */
5122 (*scalechosen)++;
5123 memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5124 }
5125 }
5126 }
5127
5128 if (*ascale != *bscale) {
5129 /* still different? try to scale down the one with the bigger scale
5130 (this *will* lose significant digits) */
5131 DWORD * digitchosen;
5132 unsigned int nchosen;
5133 int * scalechosen;
5134 int targetscale;
5135
5136 if (*ascale < *bscale) {
5137 targetscale = *ascale;
5138 scalechosen = bscale;
5139 digitchosen = b;
5140 nchosen = bn;
5141 } else {
5142 targetscale = *bscale;
5143 scalechosen = ascale;
5144 digitchosen = a;
5145 nchosen = an;
5146 }
5147 memset(t, 0, tn * sizeof(DWORD));
5148 memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5149
5150 /* divide by 10 until target scale is reached */
5151 while (*scalechosen > targetscale) {
5152 VARIANT_int_divbychar(t, tn, 10);
5153 (*scalechosen)--;
5154 memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5155 }
5156 }
5157
5158 /* check whether any of the operands still has significant digits
5159 (underflow case 1)
5160 */
5161 if (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn)) {
5162 underflow = 1;
5163 } else {
5164 /* at this step, both numbers have the same scale and can be added
5165 as integers. However, the result might not fit in A, so further
5166 scaling down might be necessary.
5167 */
5168 while (!underflow) {
5169 memset(t, 0, tn * sizeof(DWORD));
5170 memcpy(t, a, an * sizeof(DWORD));
5171
5172 VARIANT_int_add(t, tn, b, bn);
5173 if (VARIANT_int_iszero(t + an, tn - an)) {
5174 /* addition was successful */
5175 memcpy(a, t, an * sizeof(DWORD));
5176 break;
5177 } else {
5178 /* addition overflowed - remove significant digits
5179 from both operands and try again */
5180 VARIANT_int_divbychar(a, an, 10); (*ascale)--;
5181 VARIANT_int_divbychar(b, bn, 10); (*bscale)--;
5182 /* check whether any operand keeps significant digits after
5183 scaledown (underflow case 2)
5184 */
5185 underflow = (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn));
5186 }
5187 }
5188 }
5189 }
5190 return underflow;
5191}
5192
5193/* perform complete DECIMAL division in the internal representation. Returns
5194 0 if the division was completed (even if quotient is set to 0), or nonzero
5195 in case of quotient overflow.
5196 */
5197static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * divisor,
5198 VARIANT_DI * quotient, BOOL round_remainder)
5199{
5200 HRESULT r_overflow = S_OK;
5201
5202 if (VARIANT_int_iszero(divisor->bitsnum, ARRAY_SIZE(divisor->bitsnum))) {
5203 /* division by 0 */
5204 r_overflow = DISP_E_DIVBYZERO;
5205 } else if (VARIANT_int_iszero(dividend->bitsnum, ARRAY_SIZE(dividend->bitsnum))) {
5206 VARIANT_DI_clear(quotient);
5207 } else {
5208 int quotientscale, remainderscale, tempquotientscale;
5209 DWORD remainderplusquotient[8];
5210 int underflow;
5211
5212 quotientscale = remainderscale = (int)dividend->scale - (int)divisor->scale;
5213 tempquotientscale = quotientscale;
5214 VARIANT_DI_clear(quotient);
5215 quotient->sign = (dividend->sign ^ divisor->sign) ? 1 : 0;
5216
5217 /* The following strategy is used for division
5218 1) if there was a nonzero remainder from previous iteration, use it as
5219 dividend for this iteration, else (for first iteration) use intended
5220 dividend
5221 2) perform integer division in temporary buffer, develop quotient in
5222 low-order part, remainder in high-order part
5223 3) add quotient from step 2 to final result, with possible loss of
5224 significant digits
5225 4) multiply integer part of remainder by 10, while incrementing the
5226 scale of the remainder. This operation preserves the intended value
5227 of the remainder.
5228 5) loop to step 1 until one of the following is true:
5229 a) remainder is zero (exact division achieved)
5230 b) addition in step 3 fails to modify bits in quotient (remainder underflow)
5231 */
5232 memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5233 memcpy(remainderplusquotient, dividend->bitsnum, sizeof(dividend->bitsnum));
5234 do {
5235 VARIANT_int_div(remainderplusquotient, 4, divisor->bitsnum, ARRAY_SIZE(divisor->bitsnum));
5236 underflow = VARIANT_int_addlossy( quotient->bitsnum, &quotientscale,
5237 ARRAY_SIZE(quotient->bitsnum), remainderplusquotient, &tempquotientscale, 4);
5238 if (round_remainder) {
5239 if(remainderplusquotient[4] >= 5){
5240 unsigned int i;
5241 unsigned char remainder = 1;
5242 for (i = 0; i < ARRAY_SIZE(quotient->bitsnum) && remainder; i++) {
5243 ULONGLONG digit = quotient->bitsnum[i] + 1;
5244 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
5245 quotient->bitsnum[i] = digit & 0xFFFFFFFF;
5246 }
5247 }
5248 memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5249 } else {
5250 VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
5251 memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
5252 }
5253 tempquotientscale = ++remainderscale;
5254 } while (!underflow && !VARIANT_int_iszero(remainderplusquotient + 4, 4));
5255
5256 /* quotient scale might now be negative (extremely big number). If, so, try
5257 to multiply quotient by 10 (without overflowing), while adjusting the scale,
5258 until scale is 0. If this cannot be done, it is a real overflow.
5259 */
5260 while (r_overflow == S_OK && quotientscale < 0) {
5261 memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5262 memcpy(remainderplusquotient, quotient->bitsnum, sizeof(quotient->bitsnum));
5263 VARIANT_int_mulbychar(remainderplusquotient, ARRAY_SIZE(remainderplusquotient), 10);
5264 if (VARIANT_int_iszero(remainderplusquotient + ARRAY_SIZE(quotient->bitsnum),
5265 ARRAY_SIZE(remainderplusquotient) - ARRAY_SIZE(quotient->bitsnum))) {
5266 quotientscale++;
5267 memcpy(quotient->bitsnum, remainderplusquotient, sizeof(quotient->bitsnum));
5268 } else r_overflow = DISP_E_OVERFLOW;
5269 }
5270 if (r_overflow == S_OK) {
5271 if (quotientscale <= 255) quotient->scale = quotientscale;
5272 else VARIANT_DI_clear(quotient);
5273 }
5274 }
5275 return r_overflow;
5276}
5277
5278/* This procedure receives a VARIANT_DI with a defined mantissa and sign, but
5279 with an undefined scale, which will be assigned to (if possible). It also
5280 receives an exponent of 2. This procedure will then manipulate the mantissa
5281 and calculate a corresponding scale, so that the exponent2 value is assimilated
5282 into the VARIANT_DI and is therefore no longer necessary. Returns S_OK if
5283 successful, or DISP_E_OVERFLOW if the represented value is too big to fit into
5284 a DECIMAL. */
5285static HRESULT VARIANT_DI_normalize(VARIANT_DI * val, int exponent2, BOOL isDouble)
5286{
5287 HRESULT hres = S_OK;
5288 int exponent5, exponent10;
5289
5290 /* A factor of 2^exponent2 is equivalent to (10^exponent2)/(5^exponent2), and
5291 thus equal to (5^-exponent2)*(10^exponent2). After all manipulations,
5292 exponent10 might be used to set the VARIANT_DI scale directly. However,
5293 the value of 5^-exponent5 must be assimilated into the VARIANT_DI. */
5294 exponent5 = -exponent2;
5295 exponent10 = exponent2;
5296
5297 /* Handle exponent5 > 0 */
5298 while (exponent5 > 0) {
5299 char bPrevCarryBit;
5300 char bCurrCarryBit;
5301
5302 /* In order to multiply the value represented by the VARIANT_DI by 5, it
5303 is best to multiply by 10/2. Therefore, exponent10 is incremented, and
5304 somehow the mantissa should be divided by 2. */
5305 if ((val->bitsnum[0] & 1) == 0) {
5306 /* The mantissa is divisible by 2. Therefore the division can be done
5307 without losing significant digits. */
5308 exponent10++; exponent5--;
5309
5310 /* Shift right */
5311 bPrevCarryBit = val->bitsnum[2] & 1;
5312 val->bitsnum[2] >>= 1;
5313 bCurrCarryBit = val->bitsnum[1] & 1;
5314 val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
5315 val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
5316 } else {
5317 /* The mantissa is NOT divisible by 2. Therefore the mantissa should
5318 be multiplied by 5, unless the multiplication overflows. */
5319 DWORD temp_bitsnum[3];
5320
5321 exponent5--;
5322
5323 memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5324 if (0 == VARIANT_int_mulbychar(temp_bitsnum, 3, 5)) {
5325 /* Multiplication succeeded without overflow, so copy result back
5326 into VARIANT_DI */
5327 memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5328
5329 /* Mask out 3 extraneous bits introduced by the multiply */
5330 } else {
5331 /* Multiplication by 5 overflows. The mantissa should be divided
5332 by 2, and therefore will lose significant digits. */
5333 exponent10++;
5334
5335 /* Shift right */
5336 bPrevCarryBit = val->bitsnum[2] & 1;
5337 val->bitsnum[2] >>= 1;
5338 bCurrCarryBit = val->bitsnum[1] & 1;
5339 val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
5340 val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
5341 }
5342 }
5343 }
5344
5345 /* Handle exponent5 < 0 */
5346 while (exponent5 < 0) {
5347 /* In order to divide the value represented by the VARIANT_DI by 5, it
5348 is best to multiply by 2/10. Therefore, exponent10 is decremented,
5349 and the mantissa should be multiplied by 2 */
5350 if ((val->bitsnum[2] & 0x80000000) == 0) {
5351 /* The mantissa can withstand a shift-left without overflowing */
5352 exponent10--; exponent5++;
5353 VARIANT_int_shiftleft(val->bitsnum, 3, 1);
5354 } else {
5355 /* The mantissa would overflow if shifted. Therefore it should be
5356 directly divided by 5. This will lose significant digits, unless
5357 by chance the mantissa happens to be divisible by 5 */
5358 exponent5++;
5359 VARIANT_int_divbychar(val->bitsnum, 3, 5);
5360 }
5361 }
5362
5363 /* At this point, the mantissa has assimilated the exponent5, but the
5364 exponent10 might not be suitable for assignment. The exponent10 must be
5365 in the range [-DEC_MAX_SCALE..0], so the mantissa must be scaled up or
5366 down appropriately. */
5367 while (hres == S_OK && exponent10 > 0) {
5368 /* In order to bring exponent10 down to 0, the mantissa should be
5369 multiplied by 10 to compensate. If the exponent10 is too big, this
5370 will cause the mantissa to overflow. */
5371 if (0 == VARIANT_int_mulbychar(val->bitsnum, 3, 10)) {
5372 exponent10--;
5373 } else {
5375 }
5376 }
5377 while (exponent10 < -DEC_MAX_SCALE) {
5378 int rem10;
5379 /* In order to bring exponent up to -DEC_MAX_SCALE, the mantissa should
5380 be divided by 10 to compensate. If the exponent10 is too small, this
5381 will cause the mantissa to underflow and become 0 */
5382 rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5383 exponent10++;
5384 if (VARIANT_int_iszero(val->bitsnum, 3)) {
5385 /* Underflow, unable to keep dividing */
5386 exponent10 = 0;
5387 } else if (rem10 >= 5) {
5388 DWORD x = 1;
5389 VARIANT_int_add(val->bitsnum, 3, &x, 1);
5390 }
5391 }
5392 /* This step is required in order to remove excess bits of precision from the
5393 end of the bit representation, down to the precision guaranteed by the
5394 floating point number. */
5395 if (isDouble) {
5396 while (exponent10 < 0 && (val->bitsnum[2] != 0 || (val->bitsnum[1] & 0xFFE00000) != 0)) {
5397 int rem10;
5398
5399 rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5400 exponent10++;
5401 if (rem10 >= 5) {
5402 DWORD x = 1;
5403 VARIANT_int_add(val->bitsnum, 3, &x, 1);
5404 }
5405 }
5406 } else {
5407 while (exponent10 < 0 && (val->bitsnum[2] != 0 || val->bitsnum[1] != 0 ||
5408 (val->bitsnum[2] == 0 && val->bitsnum[1] == 0 && (val->bitsnum[0] & 0xFF000000) != 0))) {
5409 int rem10;
5410
5411 rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5412 exponent10++;
5413 if (rem10 >= 5) {
5414 DWORD x = 1;
5415 VARIANT_int_add(val->bitsnum, 3, &x, 1);
5416 }
5417 }
5418 }
5419 /* Remove multiples of 10 from the representation */
5420 while (exponent10 < 0) {
5421 DWORD temp_bitsnum[3];
5422
5423 memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5424 if (0 == VARIANT_int_divbychar(temp_bitsnum, 3, 10)) {
5425 exponent10++;
5426 memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5427 } else break;
5428 }
5429
5430 /* Scale assignment */
5431 if (hres == S_OK) val->scale = -exponent10;
5432
5433 return hres;
5434}
5435
5436typedef union
5437{
5438 struct
5439 {
5440 unsigned int m : 23;
5441 unsigned int exp_bias : 8;
5442 unsigned int sign : 1;
5443 } i;
5444 float f;
5445} R4_FIELDS;
5446
5447/* Convert a 32-bit floating point number into a DECIMAL, without using an
5448 intermediate string step. */
5450{
5451 HRESULT hres = S_OK;
5452 R4_FIELDS fx;
5453
5454 fx.f = source;
5455
5456 /* Detect special cases */
5457 if (fx.i.m == 0 && fx.i.exp_bias == 0) {
5458 /* Floating-point zero */
5460 } else if (fx.i.m == 0 && fx.i.exp_bias == 0xFF) {
5461 /* Floating-point infinity */
5463 } else if (fx.i.exp_bias == 0xFF) {
5464 /* Floating-point NaN */
5466 } else {
5467 int exponent2;
5469
5470 exponent2 = fx.i.exp_bias - 127; /* Get unbiased exponent */
5471 dest->sign = fx.i.sign; /* Sign is simply copied */
5472
5473 /* Copy significant bits to VARIANT_DI mantissa */
5474 dest->bitsnum[0] = fx.i.m;
5475 dest->bitsnum[0] &= 0x007FFFFF;
5476 if (fx.i.exp_bias == 0) {
5477 /* Denormalized number - correct exponent */
5478 exponent2++;
5479 } else {
5480 /* Add hidden bit to mantissa */
5481 dest->bitsnum[0] |= 0x00800000;
5482 }
5483
5484 /* The act of copying a FP mantissa as integer bits is equivalent to
5485 shifting left the mantissa 23 bits. The exponent2 is reduced to
5486 compensate. */
5487 exponent2 -= 23;
5488
5489 hres = VARIANT_DI_normalize(dest, exponent2, FALSE);
5490 }
5491
5492 return hres;
5493}
5494
5495typedef union
5496{
5497 struct
5498 {
5499 unsigned int m_lo : 32; /* 52 bits of precision */
5500 unsigned int m_hi : 20;
5501 unsigned int exp_bias : 11; /* bias == 1023 */
5502 unsigned int sign : 1;
5503 } i;
5504 double d;
5505} R8_FIELDS;
5506
5507/* Convert a 64-bit floating point number into a DECIMAL, without using an
5508 intermediate string step. */
5510{
5511 HRESULT hres = S_OK;
5512 R8_FIELDS fx;
5513
5514 fx.d = source;
5515
5516 /* Detect special cases */
5517 if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0) {
5518 /* Floating-point zero */
5520 } else if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0x7FF) {
5521 /* Floating-point infinity */
5523 } else if (fx.i.exp_bias == 0x7FF) {
5524 /* Floating-point NaN */
5526 } else {
5527 int exponent2;
5529
5530 exponent2 = fx.i.exp_bias - 1023; /* Get unbiased exponent */
5531 dest->sign = fx.i.sign; /* Sign is simply copied */
5532
5533 /* Copy significant bits to VARIANT_DI mantissa */
5534 dest->bitsnum[0] = fx.i.m_lo;
5535 dest->bitsnum[1] = fx.i.m_hi;
5536 dest->bitsnum[1] &= 0x000FFFFF;
5537 if (fx.i.exp_bias == 0) {
5538 /* Denormalized number - correct exponent */
5539 exponent2++;
5540 } else {
5541 /* Add hidden bit to mantissa */
5542 dest->bitsnum[1] |= 0x00100000;
5543 }
5544
5545 /* The act of copying a FP mantissa as integer bits is equivalent to
5546 shifting left the mantissa 52 bits. The exponent2 is reduced to
5547 compensate. */
5548 exponent2 -= 52;
5549
5550 hres = VARIANT_DI_normalize(dest, exponent2, TRUE);
5551 }
5552
5553 return hres;
5554}
5555
5556static HRESULT VARIANT_do_division(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut,
5557 BOOL round)
5558{
5559 HRESULT hRet = S_OK;
5560 VARIANT_DI di_left, di_right, di_result;
5561 HRESULT divresult;
5562
5563 VARIANT_DIFromDec(pDecLeft, &di_left);
5564 VARIANT_DIFromDec(pDecRight, &di_right);
5565 divresult = VARIANT_DI_div(&di_left, &di_right, &di_result, round);
5566 if (divresult != S_OK)
5567 {
5568 /* division actually overflowed */
5569 hRet = divresult;
5570 }
5571 else
5572 {
5573 hRet = S_OK;
5574
5575 if (di_result.scale > DEC_MAX_SCALE)
5576 {
5577 unsigned char remainder = 0;
5578
5579 /* division underflowed. In order to comply with the MSDN
5580 specifications for DECIMAL ranges, some significant digits
5581 must be removed
5582 */
5583 WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5584 di_result.scale);
5585 while (di_result.scale > DEC_MAX_SCALE &&
5586 !VARIANT_int_iszero(di_result.bitsnum, ARRAY_SIZE(di_result.bitsnum)))
5587 {
5588 remainder = VARIANT_int_divbychar(di_result.bitsnum, ARRAY_SIZE(di_result.bitsnum), 10);
5589 di_result.scale--;
5590 }
5591 if (di_result.scale > DEC_MAX_SCALE)
5592 {
5593 WARN("result underflowed, setting to 0\n");
5594 di_result.scale = 0;
5595 di_result.sign = 0;
5596 }
5597 else if (remainder >= 5) /* round up result - native oleaut32 does this */
5598 {
5599 unsigned int i;
5600 for (remainder = 1, i = 0; i < ARRAY_SIZE(di_result.bitsnum) && remainder; i++) {
5601 ULONGLONG digit = di_result.bitsnum[i] + 1;
5602 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
5603 di_result.bitsnum[i] = digit & 0xFFFFFFFF;
5604 }
5605 }
5606 }
5607 VARIANT_DecFromDI(&di_result, pDecOut);
5608 }
5609 return hRet;
5610}
5611
5612/************************************************************************
5613 * VarDecDiv (OLEAUT32.178)
5614 *
5615 * Divide one DECIMAL by another.
5616 *
5617 * PARAMS
5618 * pDecLeft [I] Source
5619 * pDecRight [I] Value to divide by
5620 * pDecOut [O] Destination
5621 *
5622 * RETURNS
5623 * Success: S_OK.
5624 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5625 */
5626HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5627{
5628 if (!pDecLeft || !pDecRight || !pDecOut) return E_INVALIDARG;
5629
5630 return VARIANT_do_division(pDecLeft, pDecRight, pDecOut, FALSE);
5631}
5632
5633/************************************************************************
5634 * VarDecMul (OLEAUT32.179)
5635 *
5636 * Multiply one DECIMAL by another.
5637 *
5638 * PARAMS
5639 * pDecLeft [I] Source
5640 * pDecRight [I] Value to multiply by
5641 * pDecOut [O] Destination
5642 *
5643 * RETURNS
5644 * Success: S_OK.
5645 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5646 */
5647HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5648{
5649 HRESULT hRet = S_OK;
5650 VARIANT_DI di_left, di_right, di_result;
5651 int mulresult;
5652
5653 VARIANT_DIFromDec(pDecLeft, &di_left);
5654 VARIANT_DIFromDec(pDecRight, &di_right);
5655 mulresult = VARIANT_DI_mul(&di_left, &di_right, &di_result);
5656 if (mulresult)
5657 {
5658 /* multiplication actually overflowed */
5659 hRet = DISP_E_OVERFLOW;
5660 }
5661 else
5662 {
5663 if (di_result.scale > DEC_MAX_SCALE)
5664 {
5665 /* multiplication underflowed. In order to comply with the MSDN
5666 specifications for DECIMAL ranges, some significant digits
5667 must be removed
5668 */
5669 WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5670 di_result.scale);
5671 while (di_result.scale > DEC_MAX_SCALE &&
5672 !VARIANT_int_iszero(di_result.bitsnum, ARRAY_SIZE(di_result.bitsnum)))
5673 {
5674 VARIANT_int_divbychar(di_result.bitsnum, ARRAY_SIZE(di_result.bitsnum), 10);
5675 di_result.scale--;
5676 }
5677 if (di_result.scale > DEC_MAX_SCALE)
5678 {
5679 WARN("result underflowed, setting to 0\n");
5680 di_result.scale = 0;
5681 di_result.sign = 0;
5682 }
5683 }
5684 VARIANT_DecFromDI(&di_result, pDecOut);
5685 }
5686 return hRet;
5687}
5688
5689/************************************************************************
5690 * VarDecSub (OLEAUT32.181)
5691 *
5692 * Subtract one DECIMAL from another.
5693 *
5694 * PARAMS
5695 * pDecLeft [I] Source
5696 * pDecRight [I] DECIMAL to subtract from pDecLeft
5697 * pDecOut [O] Destination
5698 *
5699 * RETURNS
5700 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5701 */
5702HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5703{
5704 DECIMAL decRight;
5705
5706 /* Implement as addition of the negative */
5707 VarDecNeg(pDecRight, &decRight);
5708 return VarDecAdd(pDecLeft, &decRight, pDecOut);
5709}
5710
5711/************************************************************************
5712 * VarDecAbs (OLEAUT32.182)
5713 *
5714 * Convert a DECIMAL into its absolute value.
5715 *
5716 * PARAMS
5717 * pDecIn [I] Source
5718 * pDecOut [O] Destination
5719 *
5720 * RETURNS
5721 * S_OK. This function does not fail.
5722 */
5723HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5724{
5725 *pDecOut = *pDecIn;
5726 pDecOut->sign &= ~DECIMAL_NEG;
5727 return S_OK;
5728}
5729
5730/************************************************************************
5731 * VarDecFix (OLEAUT32.187)
5732 *
5733 * Return the integer portion of a DECIMAL.
5734 *
5735 * PARAMS
5736 * pDecIn [I] Source
5737 * pDecOut [O] Destination
5738 *
5739 * RETURNS
5740 * Success: S_OK.
5741 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5742 *
5743 * NOTES
5744 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
5745 * negative numbers away from 0, while this function rounds them towards zero.
5746 */
5747HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5748{
5749 double dbl;
5750 HRESULT hr;
5751
5752 if (pDecIn->sign & ~DECIMAL_NEG)
5753 return E_INVALIDARG;
5754
5755 if (!pDecIn->scale)
5756 {
5757 *pDecOut = *pDecIn; /* Already an integer */
5758 return S_OK;
5759 }
5760
5761 hr = VarR8FromDec(pDecIn, &dbl);
5762 if (SUCCEEDED(hr)) {
5763 LONGLONG rounded = dbl;
5764
5765 hr = VarDecFromI8(rounded, pDecOut);
5766 }
5767 return hr;
5768}
5769
5770/************************************************************************
5771 * VarDecInt (OLEAUT32.188)
5772 *
5773 * Return the integer portion of a DECIMAL.
5774 *
5775 * PARAMS
5776 * pDecIn [I] Source
5777 * pDecOut [O] Destination
5778 *
5779 * RETURNS
5780 * Success: S_OK.
5781 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5782 *
5783 * NOTES
5784 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
5785 * negative numbers towards 0, while this function rounds them away from zero.
5786 */
5787HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5788{
5789 double dbl;
5790 HRESULT hr;
5791
5792 if (pDecIn->sign & ~DECIMAL_NEG)
5793 return E_INVALIDARG;
5794
5795 if (!(pDecIn->sign & DECIMAL_NEG) || !pDecIn->scale)
5796 return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
5797
5798 hr = VarR8FromDec(pDecIn, &dbl);
5799 if (SUCCEEDED(hr)) {
5800 LONGLONG rounded = dbl >= 0.0 ? dbl + 0.5 : dbl - 0.5;
5801
5802 hr = VarDecFromI8(rounded, pDecOut);
5803 }
5804 return hr;
5805}
5806
5807/************************************************************************
5808 * VarDecNeg (OLEAUT32.189)
5809 *
5810 * Change the sign of a DECIMAL.
5811 *
5812 * PARAMS
5813 * pDecIn [I] Source
5814 * pDecOut [O] Destination
5815 *
5816 * RETURNS
5817 * S_OK. This function does not fail.
5818 */
5819HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5820{
5821 *pDecOut = *pDecIn;
5822 pDecOut->sign ^= DECIMAL_NEG;
5823 return S_OK;
5824}
5825
5826/************************************************************************
5827 * VarDecRound (OLEAUT32.203)
5828 *
5829 * Change the precision of a DECIMAL.
5830 *
5831 * PARAMS
5832 * pDecIn [I] Source
5833 * cDecimals [I] New number of decimals to keep
5834 * pDecOut [O] Destination
5835 *
5836 * RETURNS
5837 * Success: S_OK. pDecOut contains the rounded value.
5838 * Failure: E_INVALIDARG if any argument is invalid.
5839 */
5840HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
5841{
5842 DECIMAL divisor, tmp;
5843 HRESULT hr;
5844 unsigned int i;
5845
5846 if (cDecimals < 0 || (pDecIn->sign & ~DECIMAL_NEG) || pDecIn->scale > DEC_MAX_SCALE)
5847 return E_INVALIDARG;
5848
5849 if (cDecimals >= pDecIn->scale)
5850 {
5851 *pDecOut = *pDecIn; /* More precision than we have */
5852 return S_OK;
5853 }
5854
5855 /* truncate significant digits and rescale */
5856 memset(&divisor, 0, sizeof(divisor));
5857 divisor.Lo64 = 1;
5858
5859 memset(&tmp, 0, sizeof(tmp));
5860 tmp.Lo64 = 10;
5861 for (i = 0; i < pDecIn->scale - cDecimals; ++i)
5862 {
5863 hr = VarDecMul(&divisor, &tmp, &divisor);
5864 if (FAILED(hr))
5865 return hr;
5866 }
5867
5868 hr = VARIANT_do_division(pDecIn, &divisor, pDecOut, TRUE);
5869 if (FAILED(hr))
5870 return hr;
5871
5872 pDecOut->scale = cDecimals;
5873
5874 return S_OK;
5875}
5876
5877/************************************************************************
5878 * VarDecCmp (OLEAUT32.204)
5879 *
5880 * Compare two DECIMAL values.
5881 *
5882 * PARAMS
5883 * pDecLeft [I] Source
5884 * pDecRight [I] Value to compare
5885 *
5886 * RETURNS
5887 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
5888 * is less than, equal to or greater than pDecRight respectively.
5889 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5890 */
5891HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
5892{
5893 HRESULT hRet;
5895
5896 if (!pDecLeft || !pDecRight)
5897 return VARCMP_NULL;
5898
5899 if ((!(pDecLeft->sign & DECIMAL_NEG)) && (pDecRight->sign & DECIMAL_NEG) &&
5900 (pDecLeft->Hi32 || pDecLeft->Lo64))
5901 return VARCMP_GT;
5902 else if ((pDecLeft->sign & DECIMAL_NEG) && (!(pDecRight->sign & DECIMAL_NEG)) &&
5903 (pDecLeft->Hi32 || pDecLeft->Lo64))
5904 return VARCMP_LT;
5905
5906 /* Subtract right from left, and compare the result to 0 */
5907 hRet = VarDecSub(pDecLeft, pDecRight, &result);
5908
5909 if (SUCCEEDED(hRet))
5910 {
5911 int non_zero = result.Hi32 || result.Lo64;
5912
5913 if ((result.sign & DECIMAL_NEG) && non_zero)
5914 hRet = (HRESULT)VARCMP_LT;
5915 else if (non_zero)
5916 hRet = (HRESULT)VARCMP_GT;
5917 else
5918 hRet = (HRESULT)VARCMP_EQ;
5919 }
5920 return hRet;
5921}
5922
5923/************************************************************************
5924 * VarDecCmpR8 (OLEAUT32.298)
5925 *
5926 * Compare a DECIMAL to a double
5927 *
5928 * PARAMS
5929 * pDecLeft [I] DECIMAL Source
5930 * dblRight [I] double to compare to pDecLeft
5931 *
5932 * RETURNS
5933 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
5934 * is less than, equal to or greater than pDecLeft respectively.
5935 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5936 */
5937HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
5938{
5939 HRESULT hRet;
5940 DECIMAL decRight;
5941
5942 hRet = VarDecFromR8(dblRight, &decRight);
5943
5944 if (SUCCEEDED(hRet))
5945 hRet = VarDecCmp(pDecLeft, &decRight);
5946
5947 return hRet;
5948}
5949
5950/* BOOL
5951 */
5952
5953/************************************************************************
5954 * VarBoolFromUI1 (OLEAUT32.118)
5955 *
5956 * Convert a VT_UI1 to a VT_BOOL.
5957 *
5958 * PARAMS
5959 * bIn [I] Source
5960 * pBoolOut [O] Destination
5961 *
5962 * RETURNS
5963 * S_OK.
5964 */
5966{
5967 *pBoolOut = bIn ? VARIANT_TRUE : VARIANT_FALSE;
5968 return S_OK;
5969}
5970
5971/************************************************************************
5972 * VarBoolFromI2 (OLEAUT32.119)
5973 *
5974 * Convert a VT_I2 to a VT_BOOL.
5975 *
5976 * PARAMS
5977 * sIn [I] Source
5978 * pBoolOut [O] Destination
5979 *
5980 * RETURNS
5981 * S_OK.
5982 */
5984{
5985 *pBoolOut = sIn ? VARIANT_TRUE : VARIANT_FALSE;
5986 return S_OK;
5987}
5988
5989/************************************************************************
5990 * VarBoolFromI4 (OLEAUT32.120)
5991 *
5992 * Convert a VT_I4 to a VT_BOOL.
5993 *
5994 * PARAMS
5995 * sIn [I] Source
5996 * pBoolOut [O] Destination
5997 *
5998 * RETURNS
5999 * S_OK.
6000 */
6002{
6003 *pBoolOut = lIn ? VARIANT_TRUE : VARIANT_FALSE;
6004 return S_OK;
6005}
6006
6007/************************************************************************
6008 * VarBoolFromR4 (OLEAUT32.121)
6009 *
6010 * Convert a VT_R4 to a VT_BOOL.
6011 *
6012 * PARAMS
6013 * fltIn [I] Source
6014 * pBoolOut [O] Destination
6015 *
6016 * RETURNS
6017 * S_OK.
6018 */
6020{
6021 *pBoolOut = fltIn ? VARIANT_TRUE : VARIANT_FALSE;
6022 return S_OK;
6023}
6024
6025/************************************************************************
6026 * VarBoolFromR8 (OLEAUT32.122)
6027 *
6028 * Convert a VT_R8 to a VT_BOOL.
6029 *
6030 * PARAMS
6031 * dblIn [I] Source
6032 * pBoolOut [O] Destination
6033 *
6034 * RETURNS
6035 * S_OK.
6036 */
6038{
6039 *pBoolOut = dblIn ? VARIANT_TRUE : VARIANT_FALSE;
6040 return S_OK;
6041}
6042
6043/************************************************************************
6044 * VarBoolFromDate (OLEAUT32.123)
6045 *
6046 * Convert a VT_DATE to a VT_BOOL.
6047 *
6048 * PARAMS
6049 * dateIn [I] Source
6050 * pBoolOut [O] Destination
6051 *
6052 * RETURNS
6053 * S_OK.
6054 */
6056{
6057 *pBoolOut = dateIn ? VARIANT_TRUE : VARIANT_FALSE;
6058 return S_OK;
6059}
6060
6061/************************************************************************
6062 * VarBoolFromCy (OLEAUT32.124)
6063 *
6064 * Convert a VT_CY to a VT_BOOL.
6065 *
6066 * PARAMS
6067 * cyIn [I] Source
6068 * pBoolOut [O] Destination
6069 *
6070 * RETURNS
6071 * S_OK.
6072 */
6074{
6075 *pBoolOut = cyIn.int64 ? VARIANT_TRUE : VARIANT_FALSE;
6076 return S_OK;
6077}
6078
6079/************************************************************************
6080 * VARIANT_GetLocalisedText [internal]
6081 *
6082 * Get a localized string from the resources
6083 *
6084 */
6086{
6087 HRSRC hrsrc;
6088
6090 MAKEINTRESOURCEW((dwId >> 4) + 1), langId );
6091 if (hrsrc)
6092 {
6093 HGLOBAL hmem = LoadResource( hProxyDll, hrsrc );
6094
6095 if (hmem)
6096 {
6097 const WCHAR *p;
6098 unsigned int i;
6099
6100 p = LockResource( hmem );
6101 for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
6102
6103 memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
6104 lpszDest[*p] = '\0';
6105 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
6106 return TRUE;
6107 }
6108 }
6109 return FALSE;
6110}
6111
6112/************************************************************************
6113 * VarBoolFromStr (OLEAUT32.125)
6114 *
6115 * Convert a VT_BSTR to a VT_BOOL.
6116 *
6117 * PARAMS
6118 * strIn [I] Source
6119 * lcid [I] LCID for the conversion
6120 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6121 * pBoolOut [O] Destination
6122 *
6123 * RETURNS
6124 * Success: S_OK.
6125 * Failure: E_INVALIDARG, if pBoolOut is invalid.
6126 * DISP_E_TYPEMISMATCH, if the type cannot be converted
6127 *
6128 * NOTES
6129 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
6130 * it may contain (in any case mapping) the text "true" or "false".
6131 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
6132 * localised text of "True" or "False" in the language specified by lcid.
6133 * - If none of these matches occur, the string is treated as a numeric string
6134 * and the boolean pBoolOut will be set according to whether the number is zero
6135 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
6136 * - If the text is not numeric and does not match any of the above, then
6137 * DISP_E_TYPEMISMATCH is returned.
6138 */
6140{
6141 WCHAR szBuff[64];
6143 HRESULT hRes = S_OK;
6144
6145 if (!strIn || !pBoolOut)
6146 return DISP_E_TYPEMISMATCH;
6147
6148 /* Check if we should be comparing against localised text */
6149 if (dwFlags & VAR_LOCALBOOL)
6150 {
6151 /* Convert our LCID into a usable value */
6153
6154 langId = LANGIDFROMLCID(lcid);
6155
6156 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
6158
6159 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
6160 * I don't think this is needed unless any of the localised text strings
6161 * contain characters that can be so mapped. In the event that this is
6162 * true for a given language (possibly some Asian languages), then strIn
6163 * should be mapped here _only_ if langId is an Id for which this can occur.
6164 */
6165 }
6166
6167 /* Note that if we are not comparing against localised strings, langId
6168 * will have its default value of LANG_ENGLISH. This allows us to mimic
6169 * the native behaviour of always checking against English strings even
6170 * after we've checked for localised ones.
6171 */
6172VarBoolFromStr_CheckLocalised:
6173 if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
6174 {
6175 /* Compare against localised strings, ignoring case */
6176 if (!wcsicmp(strIn, szBuff))
6177 {
6178 *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
6179 return hRes;
6180 }
6181 VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
6182 if (!wcsicmp(strIn, szBuff))
6183 {
6184 *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
6185 return hRes;
6186 }
6187 }
6188
6189 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
6190 {
6191 /* We have checked the localised text, now check English */
6193 goto VarBoolFromStr_CheckLocalised;
6194 }
6195
6196 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
6197 if (!wcscmp(strIn, L"#FALSE#"))
6198 *pBoolOut = VARIANT_FALSE;
6199 else if (!wcscmp(strIn, L"#TRUE#"))
6200 *pBoolOut = VARIANT_TRUE;
6201 else
6202 {
6203 double d;
6204
6205 /* If this string is a number, convert it as one */
6206 hRes = VarR8FromStr(strIn, lcid, dwFlags, &d);
6207 if (SUCCEEDED(hRes)) *pBoolOut = d ? VARIANT_TRUE : VARIANT_FALSE;
6208 }
6209 return hRes;
6210}
6211
6212/************************************************************************
6213 * VarBoolFromDisp (OLEAUT32.126)
6214 *
6215 * Convert a VT_DISPATCH to a VT_BOOL.
6216 *
6217 * PARAMS
6218 * pdispIn [I] Source
6219 * lcid [I] LCID for conversion
6220 * pBoolOut [O] Destination
6221 *
6222 * RETURNS
6223 * Success: S_OK.
6224 * Failure: E_INVALIDARG, if the source value is invalid
6225 * DISP_E_OVERFLOW, if the value will not fit in the destination
6226 * DISP_E_TYPEMISMATCH, if the type cannot be converted
6227 */
6229{
6230 return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL, 0);
6231}
6232
6233/************************************************************************
6234 * VarBoolFromI1 (OLEAUT32.233)
6235 *
6236 * Convert a VT_I1 to a VT_BOOL.
6237 *
6238 * PARAMS
6239 * cIn [I] Source
6240 * pBoolOut [O] Destination
6241 *
6242 * RETURNS
6243 * S_OK.
6244 */
6245HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
6246{
6247 *pBoolOut = cIn ? VARIANT_TRUE : VARIANT_FALSE;
6248 return S_OK;
6249}
6250
6251/************************************************************************
6252 * VarBoolFromUI2 (OLEAUT32.234)
6253 *
6254 * Convert a VT_UI2 to a VT_BOOL.
6255 *
6256 * PARAMS
6257 * usIn [I] Source
6258 * pBoolOut [O] Destination
6259 *
6260 * RETURNS
6261 * S_OK.
6262 */
6264{
6265 *pBoolOut = usIn ? VARIANT_TRUE : VARIANT_FALSE;
6266 return S_OK;
6267}
6268
6269/************************************************************************
6270 * VarBoolFromUI4 (OLEAUT32.235)
6271 *
6272 * Convert a VT_UI4 to a VT_BOOL.
6273 *
6274 * PARAMS
6275 * ulIn [I] Source
6276 * pBoolOut [O] Destination
6277 *
6278 * RETURNS
6279 * S_OK.
6280 */
6282{
6283 *pBoolOut = ulIn ? VARIANT_TRUE : VARIANT_FALSE;
6284 return S_OK;
6285}
6286
6287/************************************************************************
6288 * VarBoolFromDec (OLEAUT32.236)
6289 *
6290 * Convert a VT_DECIMAL to a VT_BOOL.
6291 *
6292 * PARAMS
6293 * pDecIn [I] Source
6294 * pBoolOut [O] Destination
6295 *
6296 * RETURNS
6297 * Success: S_OK.
6298 * Failure: E_INVALIDARG, if pDecIn is invalid.
6299 */
6301{
6302 if (pDecIn->scale > DEC_MAX_SCALE || (pDecIn->sign & ~DECIMAL_NEG))
6303 return E_INVALIDARG;
6304
6305 if (pDecIn->Hi32 || pDecIn->Lo64)
6306 *pBoolOut = VARIANT_TRUE;
6307 else
6308 *pBoolOut = VARIANT_FALSE;
6309 return S_OK;
6310}
6311
6312/************************************************************************
6313 * VarBoolFromI8 (OLEAUT32.370)
6314 *
6315 * Convert a VT_I8 to a VT_BOOL.
6316 *
6317 * PARAMS
6318 * ullIn [I] Source
6319 * pBoolOut [O] Destination
6320 *
6321 * RETURNS
6322 * S_OK.
6323 */
6325{
6326 *pBoolOut = llIn ? VARIANT_TRUE : VARIANT_FALSE;
6327 return S_OK;
6328}
6329
6330/************************************************************************
6331 * VarBoolFromUI8 (OLEAUT32.371)
6332 *
6333 * Convert a VT_UI8 to a VT_BOOL.
6334 *
6335 * PARAMS
6336 * ullIn [I] Source
6337 * pBoolOut [O] Destination
6338 *
6339 * RETURNS
6340 * S_OK.
6341 */
6343{
6344 *pBoolOut = ullIn ? VARIANT_TRUE : VARIANT_FALSE;
6345 return S_OK;
6346}
6347
6348/* BSTR
6349 */
6350
6351/* Write a number from a UI8 and sign */
6353{
6354 do
6355 {
6356 WCHAR ulNextDigit = ulVal % 10;
6357
6358 *szOut-- = '0' + ulNextDigit;
6359 ulVal = (ulVal - ulNextDigit) / 10;
6360 } while (ulVal);
6361
6362 szOut++;
6363 return szOut;
6364}
6365
6366/* Create a (possibly localised) BSTR from a UI8 and sign */
6368{
6369 WCHAR szConverted[256];
6370
6371 if (dwFlags & VAR_NEGATIVE)
6372 *--szOut = '-';
6373
6374 if (dwFlags & LOCALE_USE_NLS)
6375 {
6376 /* Format the number for the locale */
6377 szConverted[0] = '\0';
6379 szOut, NULL, szConverted, ARRAY_SIZE(szConverted));
6380 szOut = szConverted;
6381 }
6382 return SysAllocStringByteLen((LPCSTR)szOut, lstrlenW(szOut) * sizeof(WCHAR));
6383}
6384
6385/* Create a (possibly localised) BSTR from a UI8 and sign */
6387{
6388 WCHAR szBuff[64], *szOut = szBuff + ARRAY_SIZE(szBuff) - 1;
6389
6390 if (!pbstrOut)
6391 return E_INVALIDARG;
6392
6393 /* Create the basic number string */
6394 *szOut-- = '\0';
6395 szOut = VARIANT_WriteNumber(ulVal, szOut);
6396
6397 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
6398 TRACE("returning %s\n", debugstr_w(*pbstrOut));
6399 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6400}
6401
6402/******************************************************************************
6403 * VarBstrFromUI1 (OLEAUT32.108)
6404 *
6405 * Convert a VT_UI1 to a VT_BSTR.
6406 *
6407 * PARAMS
6408 * bIn [I] Source
6409 * lcid [I] LCID for the conversion
6410 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6411 * pbstrOut [O] Destination
6412 *
6413 * RETURNS
6414 * Success: S_OK.
6415 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6416 * E_OUTOFMEMORY, if memory allocation fails.
6417 */
6419{
6420 return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
6421}
6422
6423/******************************************************************************
6424 * VarBstrFromI2 (OLEAUT32.109)
6425 *
6426 * Convert a VT_I2 to a VT_BSTR.
6427 *
6428 * PARAMS
6429 * sIn [I] Source
6430 * lcid [I] LCID for the conversion
6431 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6432 * pbstrOut [O] Destination
6433 *
6434 * RETURNS
6435 * Success: S_OK.
6436 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6437 * E_OUTOFMEMORY, if memory allocation fails.
6438 */
6440{
6441 ULONG64 ul64 = sIn;
6442
6443 if (sIn < 0)
6444 {
6445 ul64 = -sIn;
6447 }
6448 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6449}
6450
6451/******************************************************************************
6452 * VarBstrFromI4 (OLEAUT32.110)
6453 *
6454 * Convert a VT_I4 to a VT_BSTR.
6455 *
6456 * PARAMS
6457 * lIn [I] Source
6458 * lcid [I] LCID for the conversion
6459 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6460 * pbstrOut [O] Destination
6461 *
6462 * RETURNS
6463 * Success: S_OK.
6464 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6465 * E_OUTOFMEMORY, if memory allocation fails.
6466 */
6468{
6469 ULONG64 ul64 = lIn;
6470
6471 if (lIn < 0)
6472 {
6473 ul64 = -(LONG64)lIn;
6475 }
6476 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6477}
6478
6480{
6481 BSTR bstrOut;
6482 WCHAR lpDecimalSep[16];
6483
6484 /* Native oleaut32 uses the locale-specific decimal separator even in the
6485 absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin
6486 American locales will see "one thousand and one tenth" as "1000,1"
6487 instead of "1000.1" (notice the comma). The following code checks for
6488 the need to replace the decimal separator, and if so, will prepare an
6489 appropriate NUMBERFMTW structure to do the job via GetNumberFormatW().
6490 */
6492 lpDecimalSep, ARRAY_SIZE(lpDecimalSep));
6493 if (lpDecimalSep[0] == '.' && lpDecimalSep[1] == '\0')
6494 {
6495 /* locale is compatible with English - return original string */
6496 bstrOut = SysAllocString(buff);
6497 }
6498 else
6499 {
6500 WCHAR *p, *e;
6501 WCHAR numbuff[256];
6502 WCHAR empty[] = L"";
6503 NUMBERFMTW minFormat;
6504
6505 minFormat.NumDigits = 0;
6506 minFormat.Grouping = 0;
6507 minFormat.lpDecimalSep = lpDecimalSep;
6508 minFormat.lpThousandSep = empty;
6509 minFormat.NegativeOrder = 1; /* NLS_NEG_LEFT */
6510
6511 GetLocaleInfoW(lcid, LOCALE_ILZERO | LOCALE_RETURN_NUMBER | (dwFlags & LOCALE_NOUSEROVERRIDE),
6512 (WCHAR *)&minFormat.LeadingZero, sizeof(DWORD)/sizeof(WCHAR) );
6513
6514 /* count number of decimal digits in string */
6515 p = wcschr(buff, '.');
6516 e = wcschr(p ? ++p : buff, 'E');
6517 if (p) minFormat.NumDigits = e ? e - p : lstrlenW(p);
6518
6519 if (e) *e = '\0';
6520 numbuff[0] = '\0';
6521 if (!GetNumberFormatW(lcid, 0, buff, &minFormat, numbuff, ARRAY_SIZE(numbuff)))
6522 {
6523 WARN("GetNumberFormatW() failed, returning raw number string instead\n");
6524 bstrOut = SysAllocString(buff);
6525 }
6526 else
6527 {
6528 if (e)
6529 {
6530 *e = 'E';
6531 wcscat(numbuff, e);
6532 }
6533 TRACE("created minimal NLS string %s\n", debugstr_w(numbuff));
6534 bstrOut = SysAllocString(numbuff);
6535 }
6536 }
6537 return bstrOut;
6538}
6539
6541 BSTR* pbstrOut, int ndigits)
6542{
6543#ifndef __REACTOS__
6545#endif
6546 WCHAR *e, buff[256];
6547 int len;
6548
6549 if (!pbstrOut)
6550 return E_INVALIDARG;
6551
6552#ifdef __REACTOS__ /* FIXME: Inspect */
6553 len = swprintf(buff, ARRAY_SIZE(buff), L"%.*G", ndigits, dblIn);
6554#else
6555 if (!(locale = _create_locale(LC_ALL, "C"))) return E_OUTOFMEMORY;
6556 len = _swprintf_l(buff, ARRAY_SIZE(buff), L"%.*G", locale, ndigits, dblIn);
6557#endif
6558 e = wcschr(buff, 'E');
6559 if (e)
6560 {
6561 int extra_decimals;
6562 WCHAR *dot;
6563
6564 dot = wcschr(buff, '.');
6565 extra_decimals = dot ? e - dot - 2 : 0;
6566 if (labs(wcstol(e+1, NULL, 10)) + extra_decimals < ndigits)
6567 {
6568#ifdef __REACTOS__ /* FIXME: Inspect */
6569 len = swprintf(buff, ARRAY_SIZE(buff), L"%.*f", ndigits, dblIn);
6570#else
6571 len = _swprintf_l(buff, ARRAY_SIZE(buff), L"%.*f", locale, ndigits, dblIn);
6572#endif
6573 while (len > 0 && (buff[len-1] == '0')) len--;
6574 }
6575 }
6576 buff[len] = 0;
6577#ifndef __REACTOS__
6579#endif
6580
6581 /* Negative zeroes are disallowed (some applications depend on this).
6582 If buff starts with a minus, and then nothing follows but zeroes
6583 and/or a period, it is a negative zero and is replaced with a
6584 canonical zero. This duplicates native oleaut32 behavior.
6585 */
6586 if (buff[0] == '-')
6587 {
6588 if (lstrlenW(buff + 1) == wcsspn(buff + 1, L"0."))
6589 { buff[0] = '0'; buff[1] = '\0'; }
6590 }
6591
6592 TRACE("created string %s\n", debugstr_w(buff));
6593 if (dwFlags & LOCALE_USE_NLS)
6594 {
6595 WCHAR numbuff[256];
6596
6597 /* Format the number for the locale */
6598 numbuff[0] = '\0';
6600 buff, NULL, numbuff, ARRAY_SIZE(numbuff));
6601 TRACE("created NLS string %s\n", debugstr_w(numbuff));
6602 *pbstrOut = SysAllocString(numbuff);
6603 }
6604 else
6605 {
6607 }
6608 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6609}
6610
6611/******************************************************************************
6612 * VarBstrFromR4 (OLEAUT32.111)
6613 *
6614 * Convert a VT_R4 to a VT_BSTR.
6615 *
6616 * PARAMS
6617 * fltIn [I] Source
6618 * lcid [I] LCID for the conversion
6619 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6620 * pbstrOut [O] Destination
6621 *
6622 * RETURNS
6623 * Success: S_OK.
6624 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6625 * E_OUTOFMEMORY, if memory allocation fails.
6626 */
6628{
6629 return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, 7);
6630}
6631
6632/******************************************************************************
6633 * VarBstrFromR8 (OLEAUT32.112)
6634 *
6635 * Convert a VT_R8 to a VT_BSTR.
6636 *
6637 * PARAMS
6638 * dblIn [I] Source
6639 * lcid [I] LCID for the conversion
6640 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6641 * pbstrOut [O] Destination
6642 *
6643 * RETURNS
6644 * Success: S_OK.
6645 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6646 * E_OUTOFMEMORY, if memory allocation fails.
6647 */
6649{
6650 return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, 15);
6651}
6652
6653/******************************************************************************
6654 * VarBstrFromCy [OLEAUT32.113]
6655 *
6656 * Convert a VT_CY to a VT_BSTR.
6657 *
6658 * PARAMS
6659 * cyIn [I] Source
6660 * lcid [I] LCID for the conversion
6661 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6662 * pbstrOut [O] Destination
6663 *
6664 * RETURNS
6665 * Success: S_OK.
6666 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6667 * E_OUTOFMEMORY, if memory allocation fails.
6668 */
6670{
6671 WCHAR buff[256];
6672 VARIANT_DI decVal;
6673
6674 if (!pbstrOut)
6675 return E_INVALIDARG;
6676
6677 decVal.scale = 4;
6678 decVal.sign = 0;
6679 decVal.bitsnum[0] = cyIn.Lo;
6680 decVal.bitsnum[1] = cyIn.Hi;
6681 if (cyIn.Hi & 0x80000000UL) {
6682 DWORD one = 1;
6683
6684 /* Negative number! */
6685 decVal.sign = 1;
6686 decVal.bitsnum[0] = ~decVal.bitsnum[0];
6687 decVal.bitsnum[1] = ~decVal.bitsnum[1];
6688 VARIANT_int_add(decVal.bitsnum, 3, &one, 1);
6689 }
6690 decVal.bitsnum[2] = 0;
6692
6693 if (dwFlags & LOCALE_USE_NLS)
6694 {
6695 WCHAR cybuff[256];
6696
6697 /* Format the currency for the locale */
6698 cybuff[0] = '\0';
6700 buff, NULL, cybuff, ARRAY_SIZE(cybuff));
6701 *pbstrOut = SysAllocString(cybuff);
6702 }
6703 else
6705
6706 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6707}
6708
6709static inline int output_int_len(int o, int min_len, WCHAR *date, int date_len)
6710{
6711 int len, tmp;
6712
6713 if(min_len >= date_len)
6714 return -1;
6715
6716 for(len=0, tmp=o; tmp; tmp/=10) len++;
6717 if(!len) len++;
6718 if(len >= date_len)
6719 return -1;
6720
6721 for(tmp=min_len-len; tmp>0; tmp--)
6722 *date++ = '0';
6723 for(tmp=len; tmp>0; tmp--, o/=10)
6724 date[tmp-1] = '0' + o%10;
6725 return min_len>len ? min_len : len;
6726}
6727
6728/* format date string, similar to GetDateFormatW function but works on bigger range of dates */
6730 const WCHAR *fmt, WCHAR *date, int date_len)
6731{
6732 static const LCTYPE dayname[] = {
6735 };
6736 static const LCTYPE sdayname[] = {
6740 };
6741 static const LCTYPE monthname[] = {
6745 };
6746 static const LCTYPE smonthname[] = {
6751 };
6752
6754 FIXME("ignoring flags %lx\n", flags);
6756
6757 while(*fmt && date_len) {
6758 int count = 1;
6759
6760 switch(*fmt) {
6761 case 'd':
6762 case 'M':
6763 case 'y':
6764 case 'g':
6765 while(*fmt == *(fmt+count))
6766 count++;
6767 fmt += count-1;
6768 }
6769
6770 switch(*fmt) {
6771 case 'd':
6772 if(count >= 4)
6773 count = GetLocaleInfoW(lcid, dayname[st->wDayOfWeek] | flags, date, date_len)-1;
6774 else if(count == 3)
6775 count = GetLocaleInfoW(lcid, sdayname[st->wDayOfWeek] | flags, date, date_len)-1;
6776 else
6777 count = output_int_len(st->wDay, count, date, date_len);
6778 break;
6779 case 'M':
6780 if(count >= 4)
6781 count = GetLocaleInfoW(lcid, monthname[st->wMonth-1] | flags, date, date_len)-1;
6782 else if(count == 3)
6783 count = GetLocaleInfoW(lcid, smonthname[st->wMonth-1] | flags, date, date_len)-1;
6784 else
6785 count = output_int_len(st->wMonth, count, date, date_len);
6786 break;
6787 case 'y':
6788 if(count >= 3)
6789 count = output_int_len(st->wYear, 0, date, date_len);
6790 else
6791 count = output_int_len(st->wYear%100, count, date, date_len);
6792 break;
6793 case 'g':
6794 if(count == 2) {
6795 FIXME("Should be using GetCalendarInfo(CAL_SERASTRING), defaulting to 'AD'\n");
6796
6797 *date++ = 'A';
6798 date_len--;
6799 if(date_len)
6800 *date = 'D';
6801 else
6802 count = -1;
6803 break;
6804 }
6805 /* fall through */
6806 default:
6807 *date = *fmt;
6808 }
6809
6810 if(count < 0)
6811 break;
6812 fmt++;
6813 date += count;
6814 date_len -= count;
6815 }
6816
6817 if(!date_len)
6818 return FALSE;
6819 *date++ = 0;
6820 return TRUE;
6821}
6822
6823/******************************************************************************
6824 * VarBstrFromDate [OLEAUT32.114]
6825 *
6826 * Convert a VT_DATE to a VT_BSTR.
6827 *
6828 * PARAMS
6829 * dateIn [I] Source
6830 * lcid [I] LCID for the conversion
6831 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6832 * pbstrOut [O] Destination
6833 *
6834 * RETURNS
6835 * Success: S_OK.
6836 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
6837 * E_OUTOFMEMORY, if memory allocation fails.
6838 */
6840{
6841 SYSTEMTIME st;
6843 WCHAR date[128], fmt_buff[80], *time;
6844
6845 TRACE("%g, %#lx, %#lx, %p.\n", dateIn, lcid, dwFlags, pbstrOut);
6846
6847 if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
6848 return E_INVALIDARG;
6849
6850 *pbstrOut = NULL;
6851
6853 st.wYear += 553; /* Use the Thai buddhist calendar year */
6855 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
6856
6857 if (dwFlags & LOCALE_USE_NLS)
6859 else
6860 {
6861 double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
6862 double partial = dateIn - whole;
6863
6864 if (whole == 0.0)
6866 else if (partial > -1e-12 && partial < 1e-12)
6868 }
6869
6871 date[0] = '\0';
6872 else
6873 if (!GetLocaleInfoW(lcid, LOCALE_SSHORTDATE, fmt_buff, ARRAY_SIZE(fmt_buff)) ||
6874 !get_date_format(lcid, dwFlags, &st, fmt_buff, date, ARRAY_SIZE(date)))
6875 return E_INVALIDARG;
6876
6877 if (!(dwFlags & VAR_DATEVALUEONLY))
6878 {
6879 time = date + lstrlenW(date);
6880 if (time != date)
6881 *time++ = ' ';
6883 return E_INVALIDARG;
6884 }
6885
6886 *pbstrOut = SysAllocString(date);
6887 if (*pbstrOut)
6888 TRACE("returning %s\n", debugstr_w(*pbstrOut));
6889 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6890}
6891
6892/******************************************************************************
6893 * VarBstrFromBool (OLEAUT32.116)
6894 *
6895 * Convert a VT_BOOL to a VT_BSTR.
6896 *
6897 * PARAMS
6898 * boolIn [I] Source
6899 * lcid [I] LCID for the conversion
6900 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6901 * pbstrOut [O] Destination
6902 *
6903 * RETURNS
6904 * Success: S_OK.
6905 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6906 * E_OUTOFMEMORY, if memory allocation fails.
6907 *
6908 * NOTES
6909 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
6910 * localised text of "True" or "False". To convert a bool into a
6911 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
6912 */
6914{
6915 WCHAR szBuff[64];
6916 DWORD dwResId = IDS_TRUE;
6917 LANGID langId;
6918
6919 TRACE("%d, %#lx, %#lx, %p.\n", boolIn, lcid, dwFlags, pbstrOut);
6920
6921 if (!pbstrOut)
6922 return E_INVALIDARG;
6923
6924 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
6925 * for variant formatting */
6927 {
6928 case VAR_BOOLONOFF:
6929 dwResId = IDS_ON;
6930 break;
6931 case VAR_BOOLYESNO:
6932 dwResId = IDS_YES;
6933 break;
6934 case VAR_LOCALBOOL:
6935 break;
6936 default:
6938 }
6939
6941 langId = LANGIDFROMLCID(lcid);
6942 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
6944
6945 if (boolIn == VARIANT_FALSE)
6946 dwResId++; /* Use negative form */
6947
6948VarBstrFromBool_GetLocalised:
6949 if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
6950 {
6951 *pbstrOut = SysAllocString(szBuff);
6952 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6953 }
6954
6955 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
6956 {
6958 goto VarBstrFromBool_GetLocalised;
6959 }
6960
6961 /* Should never get here */
6962 WARN("Failed to load bool text!\n");
6963 return E_OUTOFMEMORY;
6964}
6965
6966/******************************************************************************
6967 * VarBstrFromI1 (OLEAUT32.229)
6968 *
6969 * Convert a VT_I1 to a VT_BSTR.
6970 *
6971 * PARAMS
6972 * cIn [I] Source
6973 * lcid [I] LCID for the conversion
6974 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6975 * pbstrOut [O] Destination
6976 *
6977 * RETURNS
6978 * Success: S_OK.
6979 * Failure: E_INVALIDARG, if pbstrOut is invalid.
6980 * E_OUTOFMEMORY, if memory allocation fails.
6981 */
6982HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6983{
6984 ULONG64 ul64 = cIn;
6985
6986 if (cIn < 0)
6987 {
6988 ul64 = -cIn;
6990 }
6991 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6992}
6993
6994/******************************************************************************
6995 * VarBstrFromUI2 (OLEAUT32.230)
6996 *
6997 * Convert a VT_UI2 to a VT_BSTR.
6998 *
6999 * PARAMS
7000 * usIn [I] Source
7001 * lcid [I] LCID for the conversion
7002 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7003 * pbstrOut [O] Destination
7004 *
7005 * RETURNS
7006 * Success: S_OK.
7007 * Failure: E_INVALIDARG, if pbstrOut is invalid.
7008 * E_OUTOFMEMORY, if memory allocation fails.
7009 */
7011{
7012 return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
7013}
7014
7015/******************************************************************************
7016 * VarBstrFromUI4 (OLEAUT32.231)
7017 *
7018 * Convert a VT_UI4 to a VT_BSTR.
7019 *
7020 * PARAMS
7021 * ulIn [I] Source
7022 * lcid [I] LCID for the conversion
7023 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7024 * pbstrOut [O] Destination
7025 *
7026 * RETURNS
7027 * Success: S_OK.
7028 * Failure: E_INVALIDARG, if pbstrOut is invalid.
7029 * E_OUTOFMEMORY, if memory allocation fails.
7030 */
7032{
7033 return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
7034}
7035
7036/******************************************************************************
7037 * VarBstrFromDec (OLEAUT32.232)
7038 *
7039 * Convert a VT_DECIMAL to a VT_BSTR.
7040 *
7041 * PARAMS
7042 * pDecIn [I] Source
7043 * lcid [I] LCID for the conversion
7044 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7045 * pbstrOut [O] Destination
7046 *
7047 * RETURNS
7048 * Success: S_OK.
7049 * Failure: E_INVALIDARG, if pbstrOut is invalid.
7050 * E_OUTOFMEMORY, if memory allocation fails.
7051 */
7053{
7054 WCHAR buff[256];
7056
7057 if (!pbstrOut)
7058 return E_INVALIDARG;
7059
7060 VARIANT_DIFromDec(pDecIn, &temp);
7062
7063 if (dwFlags & LOCALE_USE_NLS)
7064 {
7065 WCHAR numbuff[256];
7066
7067 /* Format the number for the locale */
7068 numbuff[0] = '\0';
7070 buff, NULL, numbuff, ARRAY_SIZE(numbuff));
7071 TRACE("created NLS string %s\n", debugstr_w(numbuff));
7072 *pbstrOut = SysAllocString(numbuff);
7073 }
7074 else
7075 {
7077 }
7078
7079 TRACE("returning %s\n", debugstr_w(*pbstrOut));
7080 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
7081}
7082
7083/************************************************************************
7084 * VarBstrFromI8 (OLEAUT32.370)
7085 *
7086 * Convert a VT_I8 to a VT_BSTR.
7087 *
7088 * PARAMS
7089 * llIn [I] Source
7090 * lcid [I] LCID for the conversion
7091 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7092 * pbstrOut [O] Destination
7093 *
7094 * RETURNS
7095 * Success: S_OK.
7096 * Failure: E_INVALIDARG, if pbstrOut is invalid.
7097 * E_OUTOFMEMORY, if memory allocation fails.
7098 */
7100{
7101 ULONG64 ul64 = llIn;
7102
7103 if (llIn < 0)
7104 {
7105 ul64 = -llIn;
7107 }
7108 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
7109}
7110
7111/************************************************************************
7112 * VarBstrFromUI8 (OLEAUT32.371)
7113 *
7114 * Convert a VT_UI8 to a VT_BSTR.
7115 *
7116 * PARAMS
7117 * ullIn [I] Source
7118 * lcid [I] LCID for the conversion
7119 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7120 * pbstrOut [O] Destination
7121 *
7122 * RETURNS
7123 * Success: S_OK.
7124 * Failure: E_INVALIDARG, if pbstrOut is invalid.
7125 * E_OUTOFMEMORY, if memory allocation fails.
7126 */
7128{
7129 return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
7130}
7131
7132/************************************************************************
7133 * VarBstrFromDisp (OLEAUT32.115)
7134 *
7135 * Convert a VT_DISPATCH to a BSTR.
7136 *
7137 * PARAMS
7138 * pdispIn [I] Source
7139 * lcid [I] LCID for conversion
7140 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7141 * pbstrOut [O] Destination
7142 *
7143 * RETURNS
7144 * Success: S_OK.
7145 * Failure: E_INVALIDARG, if the source value is invalid
7146 * DISP_E_TYPEMISMATCH, if the type cannot be converted
7147 */
7149{
7150 return VARIANT_FromDisp(pdispIn, lcid, pbstrOut, VT_BSTR, dwFlags);
7151}
7152
7153/**********************************************************************
7154 * VarBstrCat (OLEAUT32.313)
7155 *
7156 * Concatenate two BSTR values.
7157 *
7158 * PARAMS
7159 * pbstrLeft [I] Source
7160 * pbstrRight [I] Value to concatenate
7161 * pbstrOut [O] Destination
7162 *
7163 * RETURNS
7164 * Success: S_OK.
7165 * Failure: E_INVALIDARG, if pbstrOut is invalid.
7166 * E_OUTOFMEMORY, if memory allocation fails.
7167 */
7168HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
7169{
7170 unsigned int lenLeft, lenRight;
7171
7172 TRACE("%s,%s,%p\n",
7173 debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
7174 debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), pbstrOut);
7175
7176 if (!pbstrOut)
7177 return E_INVALIDARG;
7178
7179 /* use byte length here to properly handle ansi-allocated BSTRs */
7180 lenLeft = pbstrLeft ? SysStringByteLen(pbstrLeft) : 0;
7181 lenRight = pbstrRight ? SysStringByteLen(pbstrRight) : 0;
7182
7183 *pbstrOut = SysAllocStringByteLen(NULL, lenLeft + lenRight);
7184 if (!*pbstrOut)
7185 return E_OUTOFMEMORY;
7186
7187 (*pbstrOut)[0] = '\0';
7188
7189 if (pbstrLeft)
7190 memcpy(*pbstrOut, pbstrLeft, lenLeft);
7191
7192 if (pbstrRight)
7193 memcpy((CHAR*)*pbstrOut + lenLeft, pbstrRight, lenRight);
7194
7195 TRACE("%s\n", debugstr_wn(*pbstrOut, SysStringLen(*pbstrOut)));
7196 return S_OK;
7197}
7198
7199/**********************************************************************
7200 * VarBstrCmp (OLEAUT32.314)
7201 *
7202 * Compare two BSTR values.
7203 *
7204 * PARAMS
7205 * pbstrLeft [I] Source
7206 * pbstrRight [I] Value to compare
7207 * lcid [I] LCID for the comparison
7208 * dwFlags [I] Flags to pass directly to CompareStringW().
7209 *
7210 * RETURNS
7211 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
7212 * than, equal to or greater than pbstrRight respectively.
7213 *
7214 * NOTES
7215 * VARCMP_NULL is NOT returned if either string is NULL unlike MSDN
7216 * states. A NULL BSTR pointer is equivalent to an empty string.
7217 * If LCID is equal to 0, a byte by byte comparison is performed.
7218 */
7220{
7221 HRESULT hres;
7222 int ret;
7223
7224 TRACE("%s, %s, %#lx, %#lx.\n",
7225 debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
7226 debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), lcid, dwFlags);
7227
7228 if (!pbstrLeft || !*pbstrLeft)
7229 {
7230 if (pbstrRight && *pbstrRight)
7231 return VARCMP_LT;
7232 }
7233 else if (!pbstrRight || !*pbstrRight)
7234 return VARCMP_GT;
7235
7236 if (lcid == 0)
7237 {
7238 unsigned int lenLeft = SysStringByteLen(pbstrLeft);
7239 unsigned int lenRight = SysStringByteLen(pbstrRight);
7240 ret = memcmp(pbstrLeft, pbstrRight, min(lenLeft, lenRight));
7241 if (ret < 0)
7242 return VARCMP_LT;
7243 if (ret > 0)
7244 return VARCMP_GT;
7245 if (lenLeft < lenRight)
7246 return VARCMP_LT;
7247 if (lenLeft > lenRight)
7248 return VARCMP_GT;
7249 return VARCMP_EQ;
7250 }
7251 else
7252 {
7253 unsigned int lenLeft = SysStringLen(pbstrLeft);
7254 unsigned int lenRight = SysStringLen(pbstrRight);
7255
7256 if (lenLeft == 0 || lenRight == 0)
7257 {
7258 if (lenLeft == 0 && lenRight == 0) return VARCMP_EQ;
7259 return lenLeft < lenRight ? VARCMP_LT : VARCMP_GT;
7260 }
7261
7262 hres = CompareStringW(lcid, dwFlags, pbstrLeft, lenLeft,
7263 pbstrRight, lenRight) - CSTR_LESS_THAN;
7264 TRACE("%ld\n", hres);
7265 return hres;
7266 }
7267}
7268
7269/*
7270 * DATE
7271 */
7272
7273/******************************************************************************
7274 * VarDateFromUI1 (OLEAUT32.88)
7275 *
7276 * Convert a VT_UI1 to a VT_DATE.
7277 *
7278 * PARAMS
7279 * bIn [I] Source
7280 * pdateOut [O] Destination
7281 *
7282 * RETURNS
7283 * S_OK.
7284 */
7286{
7287 return VarR8FromUI1(bIn, pdateOut);
7288}
7289
7290/******************************************************************************
7291 * VarDateFromI2 (OLEAUT32.89)
7292 *
7293 * Convert a VT_I2 to a VT_DATE.
7294 *
7295 * PARAMS
7296 * sIn [I] Source
7297 * pdateOut [O] Destination
7298 *
7299 * RETURNS
7300 * S_OK.
7301 */
7302HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
7303{
7304 return VarR8FromI2(sIn, pdateOut);
7305}
7306
7307/******************************************************************************
7308 * VarDateFromI4 (OLEAUT32.90)
7309 *
7310 * Convert a VT_I4 to a VT_DATE.
7311 *
7312 * PARAMS
7313 * lIn [I] Source
7314 * pdateOut [O] Destination
7315 *
7316 * RETURNS
7317 * S_OK.
7318 */
7320{
7321 return VarDateFromR8(lIn, pdateOut);
7322}
7323
7324/******************************************************************************
7325 * VarDateFromR4 (OLEAUT32.91)
7326 *
7327 * Convert a VT_R4 to a VT_DATE.
7328 *
7329 * PARAMS
7330 * fltIn [I] Source
7331 * pdateOut [O] Destination
7332 *
7333 * RETURNS
7334 * S_OK.
7335 */
7337{
7338 return VarR8FromR4(fltIn, pdateOut);
7339}
7340
7341/******************************************************************************
7342 * VarDateFromR8 (OLEAUT32.92)
7343 *
7344 * Convert a VT_R8 to a VT_DATE.
7345 *
7346 * PARAMS
7347 * dblIn [I] Source
7348 * pdateOut [O] Destination
7349 *
7350 * RETURNS
7351 * S_OK.
7352 */
7353HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
7354{
7355 if (dblIn <= (DATE_MIN - 1.0) || dblIn >= (DATE_MAX + 1.0)) return DISP_E_OVERFLOW;
7356 *pdateOut = (DATE)dblIn;
7357 return S_OK;
7358}
7359
7360/**********************************************************************
7361 * VarDateFromDisp (OLEAUT32.95)
7362 *
7363 * Convert a VT_DISPATCH to a VT_DATE.
7364 *
7365 * PARAMS
7366 * pdispIn [I] Source
7367 * lcid [I] LCID for conversion
7368 * pdateOut [O] Destination
7369 *
7370 * RETURNS
7371 * Success: S_OK.
7372 * Failure: E_INVALIDARG, if the source value is invalid
7373 * DISP_E_OVERFLOW, if the value will not fit in the destination
7374 * DISP_E_TYPEMISMATCH, if the type cannot be converted
7375 */
7377{
7378 return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE, 0);
7379}
7380
7381/******************************************************************************
7382 * VarDateFromBool (OLEAUT32.96)
7383 *
7384 * Convert a VT_BOOL to a VT_DATE.
7385 *
7386 * PARAMS
7387 * boolIn [I] Source
7388 * pdateOut [O] Destination
7389 *
7390 * RETURNS
7391 * S_OK.
7392 */
7394{
7395 return VarR8FromBool(boolIn, pdateOut);
7396}
7397
7398/**********************************************************************
7399 * VarDateFromCy (OLEAUT32.93)
7400 *
7401 * Convert a VT_CY to a VT_DATE.
7402 *
7403 * PARAMS
7404 * lIn [I] Source
7405 * pdateOut [O] Destination
7406 *
7407 * RETURNS
7408 * S_OK.
7409 */
7411{
7412 return VarR8FromCy(cyIn, pdateOut);
7413}
7414
7415/* Date string parsing */
7416#define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
7417#define DP_DATESEP 0x02 /* Date separator */
7418#define DP_MONTH 0x04 /* Month name */
7419#define DP_AM 0x08 /* AM */
7420#define DP_PM 0x10 /* PM */
7421
7422typedef struct tagDATEPARSE
7423{
7424 DWORD dwCount; /* Number of fields found so far (maximum 6) */
7425 DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
7426 DWORD dwFlags[6]; /* Flags for each field */
7427 DWORD dwValues[6]; /* Value of each field */
7429
7430#define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
7431
7432#define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
7433
7434/* Determine if a day is valid in a given month of a given year */
7436{
7437 static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
7438
7439 if (day && month && month < 13)
7440 {
7441 if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
7442 return TRUE;
7443 }
7444 return FALSE;
7445}
7446
7447/* Possible orders for 3 numbers making up a date */
7448#define ORDER_MDY 0x01
7449#define ORDER_YMD 0x02
7450#define ORDER_YDM 0x04
7451#define ORDER_DMY 0x08
7452#define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
7453
7454/* Determine a date for a particular locale, from 3 numbers */
7455static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
7456 DWORD offset, SYSTEMTIME *st)
7457{
7458 DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
7459
7460 if (!dp->dwCount)
7461 {
7462 v1 = 30; /* Default to (Variant) 0 date part */
7463 v2 = 12;
7464 v3 = 1899;
7465 goto VARIANT_MakeDate_OK;
7466 }
7467
7468 v1 = dp->dwValues[offset + 0];
7469 v2 = dp->dwValues[offset + 1];
7470 if (dp->dwCount == 2)
7471 {
7474 v3 = current.wYear;
7475 }
7476 else
7477 v3 = dp->dwValues[offset + 2];
7478
7479 TRACE("%ld, %ld, %ld, %ld, %ld.\n", v1, v2, v3, iDate, offset);
7480
7481 /* If one number must be a month (Because a month name was given), then only
7482 * consider orders with the month in that position.
7483 * If we took the current year as 'v3', then only allow a year in that position.
7484 */
7485 if (dp->dwFlags[offset + 0] & DP_MONTH)
7486 {
7487 dwAllOrders = ORDER_MDY;
7488 }
7489 else if (dp->dwFlags[offset + 1] & DP_MONTH)
7490 {
7491 dwAllOrders = ORDER_DMY;
7492 if (dp->dwCount > 2)
7493 dwAllOrders |= ORDER_YMD;
7494 }
7495 else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
7496 {
7497 dwAllOrders = ORDER_YDM;
7498 }
7499 else
7500 {
7501 dwAllOrders = ORDER_MDY|ORDER_DMY;
7502 if (dp->dwCount > 2)
7503 dwAllOrders |= (ORDER_YMD|ORDER_YDM);
7504 }
7505
7506VARIANT_MakeDate_Start:
7507 TRACE("dwAllOrders is %#lx\n", dwAllOrders);
7508
7509 while (dwAllOrders)
7510 {
7511 DWORD dwTemp;
7512
7513 if (dwCount == 0)
7514 {
7515 /* First: Try the order given by iDate */
7516 switch (iDate)
7517 {
7518 case 0: dwTry = dwAllOrders & ORDER_MDY; break;
7519 case 1: dwTry = dwAllOrders & ORDER_DMY; break;
7520 default: dwTry = dwAllOrders & ORDER_YMD; break;
7521 }
7522 }
7523 else if (dwCount == 1)
7524 {
7525 /* Second: Try all the orders compatible with iDate */
7526 switch (iDate)
7527 {
7528 case 0: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
7529 case 1: dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YDM|ORDER_MYD); break;
7530 default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
7531 }
7532 }
7533 else
7534 {
7535 /* Finally: Try any remaining orders */
7536 dwTry = dwAllOrders;
7537 }
7538
7539 TRACE("Attempt %ld, dwTry is %#lx\n", dwCount, dwTry);
7540
7541 dwCount++;
7542 if (!dwTry)
7543 continue;
7544
7545#define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
7546
7547 if (dwTry & ORDER_MDY)
7548 {
7550 {
7551 DATE_SWAP(v1,v2);
7552 goto VARIANT_MakeDate_OK;
7553 }
7554 dwAllOrders &= ~ORDER_MDY;
7555 }
7556 if (dwTry & ORDER_YMD)
7557 {
7559 {
7560 DATE_SWAP(v1,v3);
7561 goto VARIANT_MakeDate_OK;
7562 }
7563 dwAllOrders &= ~ORDER_YMD;
7564 }
7565 if (dwTry & ORDER_YDM)
7566 {
7568 {
7569 DATE_SWAP(v1,v2);
7570 DATE_SWAP(v2,v3);
7571 goto VARIANT_MakeDate_OK;
7572 }
7573 dwAllOrders &= ~ORDER_YDM;
7574 }
7575 if (dwTry & ORDER_DMY)
7576 {
7578 goto VARIANT_MakeDate_OK;
7579 dwAllOrders &= ~ORDER_DMY;
7580 }
7581 if (dwTry & ORDER_MYD)
7582 {
7583 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
7585 {
7586 DATE_SWAP(v1,v3);
7587 DATE_SWAP(v2,v3);
7588 goto VARIANT_MakeDate_OK;
7589 }
7590 dwAllOrders &= ~ORDER_MYD;
7591 }
7592 }
7593
7594 if (dp->dwCount == 2)
7595 {
7596 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
7597 v3 = 1; /* 1st of the month */
7598 dwAllOrders = ORDER_YMD|ORDER_MYD;
7599 dp->dwCount = 0; /* Don't return to this code path again */
7600 dwCount = 0;
7601 goto VARIANT_MakeDate_Start;
7602 }
7603
7604 /* No valid dates were able to be constructed */
7605 return DISP_E_TYPEMISMATCH;
7606
7607VARIANT_MakeDate_OK:
7608
7609 /* Check that the time part is ok */
7610 if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
7611 return DISP_E_TYPEMISMATCH;
7612
7613 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
7614 if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
7615 st->wHour += 12;
7616 else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
7617 st->wHour = 0;
7618 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
7619
7620 st->wDay = v1;
7621 st->wMonth = v2;
7622 /* FIXME: For 2 digit dates old versions of Windows used 29 but
7623 * Windows 10 1903 and greater use 49. This cutoff may also be modified by
7624 * setting the value as a string for the relevant calendar id in the
7625 * registry.
7626 *
7627 * For instance to emulate old Windows versions:
7628 * [HKCU\Control Panel\International\Calendars\TwoDigitYearMax]
7629 * "1"="29"
7630 * (also 2, 9, 10, 11 and 12 for the other Gregorian calendars)
7631 *
7632 * But Wine doesn't have/use that key at the time of writing.
7633 */
7634 st->wYear = v3 <= 49 ? 2000 + v3 : v3 <= 99 ? 1900 + v3 : v3;
7635 TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
7636 return S_OK;
7637}
7638
7639/******************************************************************************
7640 * VarDateFromStr [OLEAUT32.94]
7641 *
7642 * Convert a VT_BSTR to at VT_DATE.
7643 *
7644 * PARAMS
7645 * strIn [I] String to convert
7646 * lcid [I] Locale identifier for the conversion
7647 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
7648 * pdateOut [O] Destination for the converted value
7649 *
7650 * RETURNS
7651 * Success: S_OK. pdateOut contains the converted value.
7652 * FAILURE: An HRESULT error code indicating the problem.
7653 *
7654 * NOTES
7655 * Any date format that can be created using the date formats from lcid
7656 * (Either from kernel Nls functions, variant conversion or formatting) is a
7657 * valid input to this function. In addition, a few more esoteric formats are
7658 * also supported for compatibility with the native version. The date is
7659 * interpreted according to the date settings in the control panel, unless
7660 * the date is invalid in that format, in which the most compatible format
7661 * that produces a valid date will be used.
7662 */
7664{
7665 static const USHORT ParseDateTokens[] =
7666 {
7683 };
7684 static const BYTE ParseDateMonths[] =
7685 {
7686 1,2,3,4,5,6,7,8,9,10,11,12,13,
7687 1,2,3,4,5,6,7,8,9,10,11,12,13
7688 };
7689 unsigned int i;
7690 BSTR tokens[ARRAY_SIZE(ParseDateTokens)];
7691 DATEPARSE dp;
7692 DWORD dwDateSeps = 0, iDate = 0;
7693 HRESULT hRet = S_OK;
7694
7697 return E_INVALIDARG;
7698
7699 if (!strIn)
7700 return DISP_E_TYPEMISMATCH;
7701
7702 *pdateOut = 0.0;
7703
7704 TRACE("%s, %#lx, %#lx, %p.\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
7705
7706 memset(&dp, 0, sizeof(dp));
7707
7709 (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
7710 TRACE("iDate is %ld\n", iDate);
7711
7712 /* Get the month/day/am/pm tokens for this locale */
7713 for (i = 0; i < ARRAY_SIZE(tokens); i++)
7714 {
7715 WCHAR buff[128];
7716 LCTYPE lctype = ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
7717
7718 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
7719 * GetAltMonthNames(). We should really cache these strings too.
7720 */
7721 buff[0] = '\0';
7723 tokens[i] = SysAllocString(buff);
7724 TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
7725 }
7726
7727 /* Parse the string into our structure */
7728 while (*strIn)
7729 {
7730 if ('0' <= *strIn && *strIn <= '9')
7731 {
7732 OLECHAR* end;
7733 if (dp.dwCount >= 6)
7734 {
7735 hRet = DISP_E_TYPEMISMATCH;
7736 break;
7737 }
7738 dp.dwValues[dp.dwCount] = wcstoul(strIn, &end, 10);
7739 dp.dwCount++;
7740 strIn = end - 1;
7741 }
7742 else if (iswalpha(*strIn))
7743 {
7744 BOOL bFound = FALSE;
7745
7746 for (i = 0; i < ARRAY_SIZE(tokens); i++)
7747 {
7748 DWORD dwLen = lstrlenW(tokens[i]);
7749 if (dwLen && !wcsnicmp(strIn, tokens[i], dwLen))
7750 {
7751 if (i <= 25)
7752 {
7753 if (dp.dwCount >= 6)
7754 hRet = DISP_E_TYPEMISMATCH;
7755 else
7756 {
7757 dp.dwValues[dp.dwCount] = ParseDateMonths[i];
7758 dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
7759 dp.dwCount++;
7760 }
7761 }
7762 else if (i > 39 && i < 42)
7763 {
7764 if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
7765 hRet = DISP_E_TYPEMISMATCH;
7766 else
7767 {
7768 dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
7769 dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
7770 }
7771 }
7772 strIn += (dwLen - 1);
7773 bFound = TRUE;
7774 break;
7775 }
7776 }
7777
7778 if (!bFound)
7779 {
7780 if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
7781 (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7782 {
7783 /* Special case - 'a' and 'p' are recognised as short for am/pm */
7784 if (*strIn == 'a' || *strIn == 'A')
7785 {
7786 dp.dwFlags[dp.dwCount - 1] |= DP_AM;
7787 dp.dwParseFlags |= DP_AM;
7788 }
7789 else
7790 {
7791 dp.dwFlags[dp.dwCount - 1] |= DP_PM;
7792 dp.dwParseFlags |= DP_PM;
7793 }
7794 strIn++;
7795 }
7796 else
7797 {
7798 TRACE("No matching token for %s\n", debugstr_w(strIn));
7799 hRet = DISP_E_TYPEMISMATCH;
7800 break;
7801 }
7802 }
7803 }
7804 else if (*strIn == ':' || *strIn == '.')
7805 {
7806 if (!dp.dwCount || !strIn[1])
7807 hRet = DISP_E_TYPEMISMATCH;
7808 else
7809 if (tokens[42][0] == *strIn)
7810 {
7811 dwDateSeps++;
7812 if (dwDateSeps > 2)
7813 hRet = DISP_E_TYPEMISMATCH;
7814 else
7815 dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
7816 }
7817 else
7818 dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
7819 }
7820 else if (*strIn == '-' || *strIn == '/')
7821 {
7822 dwDateSeps++;
7823 if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
7824 hRet = DISP_E_TYPEMISMATCH;
7825 else
7826 dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
7827 }
7828 else if (*strIn == ',' || iswspace(*strIn))
7829 {
7830 if (*strIn == ',' && !strIn[1])
7831 hRet = DISP_E_TYPEMISMATCH;
7832 }
7833 else
7834 {
7835 hRet = DISP_E_TYPEMISMATCH;
7836 }
7837 strIn++;
7838 }
7839
7840 if (!dp.dwCount || dp.dwCount > 6 ||
7841 (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7842 hRet = DISP_E_TYPEMISMATCH;
7843
7844 if (SUCCEEDED(hRet))
7845 {
7846 SYSTEMTIME st;
7847 DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
7848
7849 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
7850
7851 /* Figure out which numbers correspond to which fields.
7852 *
7853 * This switch statement works based on the fact that native interprets any
7854 * fields that are not joined with a time separator ('.' or ':') as date
7855 * fields. Thus we construct a value from 0-32 where each set bit indicates
7856 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
7857 * For valid permutations, we set dwOffset to point to the first date field
7858 * and shorten dp.dwCount by the number of time fields found. The real
7859 * magic here occurs in VARIANT_MakeDate() above, where we determine what
7860 * each date number must represent in the context of iDate.
7861 */
7862 TRACE("%#lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
7863
7864 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
7865 {
7866 case 0x1: /* TT TTDD TTDDD */
7867 if (dp.dwCount > 3 &&
7868 ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
7869 (dp.dwFlags[4] & (DP_AM|DP_PM))))
7870 hRet = DISP_E_TYPEMISMATCH;
7871 else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
7872 hRet = DISP_E_TYPEMISMATCH;
7873 st.wHour = dp.dwValues[0];
7874 st.wMinute = dp.dwValues[1];
7875 dp.dwCount -= 2;
7876 dwOffset = 2;
7877 break;
7878
7879 case 0x3: /* TTT TTTDD TTTDDD */
7880 if (dp.dwCount > 4 &&
7881 ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
7882 (dp.dwFlags[5] & (DP_AM|DP_PM))))
7883 hRet = DISP_E_TYPEMISMATCH;
7884 else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
7885 hRet = DISP_E_TYPEMISMATCH;
7886 st.wHour = dp.dwValues[0];
7887 st.wMinute = dp.dwValues[1];
7888 st.wSecond = dp.dwValues[2];
7889 dwOffset = 3;
7890 dp.dwCount -= 3;
7891 break;
7892
7893 case 0x4: /* DDTT */
7894 if (dp.dwCount != 4 ||
7895 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7896 hRet = DISP_E_TYPEMISMATCH;
7897
7898 st.wHour = dp.dwValues[2];
7899 st.wMinute = dp.dwValues[3];
7900 dp.dwCount -= 2;
7901 break;
7902
7903 case 0x0: /* T DD DDD TDDD TDDD */
7904 if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
7905 {
7906 st.wHour = dp.dwValues[0]; /* T */
7907 dp.dwCount = 0;
7908 break;
7909 }
7910 else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
7911 {
7912 hRet = DISP_E_TYPEMISMATCH;
7913 }
7914 else if (dp.dwCount == 3)
7915 {
7916 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
7917 {
7918 dp.dwCount = 2;
7919 st.wHour = dp.dwValues[0];
7920 dwOffset = 1;
7921 break;
7922 }
7923 if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
7924 {
7925 dp.dwCount = 2;
7926 st.wHour = dp.dwValues[2];
7927 break;
7928 }
7929 else if (dp.dwParseFlags & (DP_AM|DP_PM))
7930 hRet = DISP_E_TYPEMISMATCH;
7931 }
7932 else if (dp.dwCount == 4)
7933 {
7934 dp.dwCount = 3;
7935 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
7936 {
7937 st.wHour = dp.dwValues[0];
7938 dwOffset = 1;
7939 }
7940 else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
7941 {
7942 st.wHour = dp.dwValues[3];
7943 }
7944 else
7945 hRet = DISP_E_TYPEMISMATCH;
7946 break;
7947 }
7948 /* .. fall through .. */
7949
7950 case 0x8: /* DDDTT */
7951 if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
7952 (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
7953 (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
7954 dp.dwCount == 4 || dp.dwCount == 6)
7955 hRet = DISP_E_TYPEMISMATCH;
7956 st.wHour = dp.dwValues[3];
7957 st.wMinute = dp.dwValues[4];
7958 if (dp.dwCount == 5)
7959 dp.dwCount -= 2;
7960 break;
7961
7962 case 0xC: /* DDTTT */
7963 if (dp.dwCount != 5 ||
7964 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7965 hRet = DISP_E_TYPEMISMATCH;
7966 st.wHour = dp.dwValues[2];
7967 st.wMinute = dp.dwValues[3];
7968 st.wSecond = dp.dwValues[4];
7969 dp.dwCount -= 3;
7970 break;
7971
7972 case 0x18: /* DDDTTT */
7973 if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
7974 (dp.dwFlags[2] & (DP_AM|DP_PM)))
7975 hRet = DISP_E_TYPEMISMATCH;
7976 st.wHour = dp.dwValues[3];
7977 st.wMinute = dp.dwValues[4];
7978 st.wSecond = dp.dwValues[5];
7979 dp.dwCount -= 3;
7980 break;
7981
7982 default:
7983 hRet = DISP_E_TYPEMISMATCH;
7984 break;
7985 }
7986
7987 if (SUCCEEDED(hRet))
7988 {
7989 hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
7990
7992 {
7993 st.wYear = 1899;
7994 st.wMonth = 12;
7995 st.wDay = 30;
7996 }
7997 else if (dwFlags & VAR_DATEVALUEONLY)
7998 st.wHour = st.wMinute = st.wSecond = 0;
7999
8000 /* Finally, convert the value to a VT_DATE */
8001 if (SUCCEEDED(hRet))
8002 hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
8003 }
8004 }
8005
8006 for (i = 0; i < ARRAY_SIZE(tokens); i++)
8007 SysFreeString(tokens[i]);
8008 return hRet;
8009}
8010
8011/******************************************************************************
8012 * VarDateFromI1 (OLEAUT32.221)
8013 *
8014 * Convert a VT_I1 to a VT_DATE.
8015 *
8016 * PARAMS
8017 * cIn [I] Source
8018 * pdateOut [O] Destination
8019 *
8020 * RETURNS
8021 * S_OK.
8022 */
8023HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
8024{
8025 return VarR8FromI1(cIn, pdateOut);
8026}
8027
8028/******************************************************************************
8029 * VarDateFromUI2 (OLEAUT32.222)
8030 *
8031 * Convert a VT_UI2 to a VT_DATE.
8032 *
8033 * PARAMS
8034 * uiIn [I] Source
8035 * pdateOut [O] Destination
8036 *
8037 * RETURNS
8038 * S_OK.
8039 */
8041{
8042 return VarR8FromUI2(uiIn, pdateOut);
8043}
8044
8045/******************************************************************************
8046 * VarDateFromUI4 (OLEAUT32.223)
8047 *
8048 * Convert a VT_UI4 to a VT_DATE.
8049 *
8050 * PARAMS
8051 * ulIn [I] Source
8052 * pdateOut [O] Destination
8053 *
8054 * RETURNS
8055 * S_OK.
8056 */
8058{
8059 return VarDateFromR8(ulIn, pdateOut);
8060}
8061
8062/**********************************************************************
8063 * VarDateFromDec (OLEAUT32.224)
8064 *
8065 * Convert a VT_DECIMAL to a VT_DATE.
8066 *
8067 * PARAMS
8068 * pdecIn [I] Source
8069 * pdateOut [O] Destination
8070 *
8071 * RETURNS
8072 * S_OK.
8073 */
8074HRESULT WINAPI VarDateFromDec(const DECIMAL *pdecIn, DATE* pdateOut)
8075{
8076 return VarR8FromDec(pdecIn, pdateOut);
8077}
8078
8079/******************************************************************************
8080 * VarDateFromI8 (OLEAUT32.364)
8081 *
8082 * Convert a VT_I8 to a VT_DATE.
8083 *
8084 * PARAMS
8085 * llIn [I] Source
8086 * pdateOut [O] Destination
8087 *
8088 * RETURNS
8089 * Success: S_OK.
8090 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
8091 */
8093{
8094 if (llIn < DATE_MIN || llIn > DATE_MAX) return DISP_E_OVERFLOW;
8095 *pdateOut = (DATE)llIn;
8096 return S_OK;
8097}
8098
8099/******************************************************************************
8100 * VarDateFromUI8 (OLEAUT32.365)
8101 *
8102 * Convert a VT_UI8 to a VT_DATE.
8103 *
8104 * PARAMS
8105 * ullIn [I] Source
8106 * pdateOut [O] Destination
8107 *
8108 * RETURNS
8109 * Success: S_OK.
8110 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
8111 */
8113{
8114 if (ullIn > DATE_MAX) return DISP_E_OVERFLOW;
8115 *pdateOut = (DATE)ullIn;
8116 return S_OK;
8117}
WCHAR lpszDest[260]
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define IDS_YES
Definition: resource.h:16
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
r l[0]
Definition: byte_order.h:168
Definition: _locale.h:75
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR empty[1]
Definition: string.c:47
double DATE
Definition: compat.h:2253
#define wcschr
Definition: compat.h:17
#define wcsnicmp
Definition: compat.h:14
WCHAR OLECHAR
Definition: compat.h:2292
OLECHAR * BSTR
Definition: compat.h:2293
unsigned short VARTYPE
Definition: compat.h:2254
short VARIANT_BOOL
Definition: compat.h:2290
@ VT_UI8
Definition: compat.h:2315
@ VT_BSTR
Definition: compat.h:2303
@ VT_INT
Definition: compat.h:2316
@ VT_R4
Definition: compat.h:2299
@ VT_UI2
Definition: compat.h:2312
@ VT_DECIMAL
Definition: compat.h:2309
@ VT_R8
Definition: compat.h:2300
@ VT_CY
Definition: compat.h:2301
@ VT_I8
Definition: compat.h:2314
@ VT_I1
Definition: compat.h:2310
@ VT_I4
Definition: compat.h:2298
@ VT_INT_PTR
Definition: compat.h:2327
@ VT_DATE
Definition: compat.h:2302
@ VT_BOOL
Definition: compat.h:2306
@ VT_I2
Definition: compat.h:2297
@ VT_UI4
Definition: compat.h:2313
@ VT_UINT
Definition: compat.h:2317
@ VT_UI1
Definition: compat.h:2311
#define wcsicmp
Definition: compat.h:15
#define lstrlenW
Definition: compat.h:750
static DOUBLE day(DOUBLE time)
Definition: date.c:75
VOID WINAPI GetSystemTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:304
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang)
Definition: res.c:164
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:3946
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1675
LCID WINAPI ConvertDefaultLocale(LCID lcid)
Definition: locale.c:2879
LCID lcid
Definition: locale.c:5660
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
_ACRTIMP __msvcrt_ulong __cdecl wcstoul(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2917
_ACRTIMP __msvcrt_long __cdecl wcstol(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2752
_ACRTIMP size_t __cdecl wcsspn(const wchar_t *, const wchar_t *)
Definition: wcs.c:513
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP void __cdecl _free_locale(_locale_t)
Definition: locale.c:1183
_ACRTIMP _locale_t __cdecl _create_locale(int, const char *)
Definition: locale.c:1981
#define LC_ALL
Definition: locale.h:25
_ACRTIMP double __cdecl ceil(double)
Definition: ceil.c:18
_ACRTIMP double __cdecl fmod(double, double)
_ACRTIMP double __cdecl remainder(double, double)
Definition: remainder.c:75
_ACRTIMP double __cdecl floor(double)
Definition: floor.c:18
_ACRTIMP __msvcrt_long __cdecl labs(__msvcrt_long)
Definition: math.c:680
_ACRTIMP div_t __cdecl div(int, int)
Definition: math.c:2081
#define IDS_TRUE
Definition: resource.h:26
#define IDS_FALSE
Definition: resource.h:27
#define IDS_ON
Definition: resource.h:30
HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE *pbOut)
Definition: vartype.c:603
HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64 *pui64Out)
Definition: vartype.c:2622
HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
Definition: vartype.c:1757
HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6418
HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT *pusOut)
Definition: vartype.c:1305
HRESULT WINAPI VarCyMul(CY cyLeft, CY cyRight, CY *pCyOut)
Definition: vartype.c:3802
HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64 *pui64Out)
Definition: vartype.c:2492
static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
Definition: vartype.c:7435
static BOOL VARIANT_int_iszero(const DWORD *p, unsigned int n)
Definition: vartype.c:4745
HRESULT WINAPI VarCyFromR8(double dblIn, CY *pCyOut)
Definition: vartype.c:3497
HRESULT WINAPI VarCyInt(CY cyIn, CY *pCyOut)
Definition: vartype.c:3920
HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT *psOut)
Definition: vartype.c:894
HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
Definition: vartype.c:2882
HRESULT WINAPI VarCyMulI4(CY cyLeft, LONG lRight, CY *pCyOut)
Definition: vartype.c:3825
HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
Definition: vartype.c:1813
#define ORDER_MDY
Definition: vartype.c:7448
HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6913
HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY *pCyOut)
Definition: vartype.c:3414
HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
Definition: vartype.c:2997
#define CY_HALF
Definition: vartype.c:37
HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT *psOut)
Definition: vartype.c:1053
HRESULT WINAPI VarDateFromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, DATE *pdateOut)
Definition: vartype.c:7663
HRESULT WINAPI VarDecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
Definition: vartype.c:5891
HRESULT WINAPI VarUI2FromDisp(IDispatch *pdispIn, LCID lcid, USHORT *pusOut)
Definition: vartype.c:1350
#define DP_TIMESEP
Definition: vartype.c:7416
HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:5965
HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE *pbOut)
Definition: vartype.c:809
HRESULT WINAPI VarI1FromR8(double dblIn, signed char *pcOut)
Definition: vartype.c:355
HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char *pcOut)
Definition: vartype.c:333
HRESULT WINAPI VarUI4FromDisp(IDispatch *pdispIn, LCID lcid, ULONG *pulOut)
Definition: vartype.c:1935
HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY *pCyOut)
Definition: vartype.c:3656
HRESULT WINAPI VarI1FromDisp(IDispatch *pdispIn, LCID lcid, signed char *pcOut)
Definition: vartype.c:442
HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL *pDecOut)
Definition: vartype.c:4234
HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
Definition: vartype.c:3056
#define DP_DATESEP
Definition: vartype.c:7417
HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
Definition: vartype.c:1987
#define RETTYP
Definition: vartype.c:140
HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char *pcOut)
Definition: vartype.c:478
HRESULT WINAPI VarCyFix(CY cyIn, CY *pCyOut)
Definition: vartype.c:3896
HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
Definition: vartype.c:3107
HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char *pcOut)
Definition: vartype.c:498
HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6648
HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
Definition: vartype.c:1970
HRESULT WINAPI VarI4FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
Definition: vartype.c:1605
HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT *psOut)
Definition: vartype.c:1168
HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
Definition: vartype.c:3015
HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64 *pi64Out)
Definition: vartype.c:2069
HRESULT WINAPI VarDecCmpR8(const DECIMAL *pDecLeft, double dblRight)
Definition: vartype.c:5937
HRESULT WINAPI VarDecAdd(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut)
Definition: vartype.c:4580
HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6439
HRESULT WINAPI VarCyAbs(CY cyIn, CY *pCyOut)
Definition: vartype.c:3870
static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG *pulHigh)
Definition: vartype.c:4546
HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
Definition: vartype.c:1643
static int output_int_len(int o, int min_len, WCHAR *date, int date_len)
Definition: vartype.c:6709
HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64 *pui64Out)
Definition: vartype.c:2639
HRESULT WINAPI VarI8FromDisp(IDispatch *pdispIn, LCID lcid, LONG64 *pi64Out)
Definition: vartype.c:2242
#define BOTHTST(dest, src, func, lo, hi)
Definition: vartype.c:156
static int VARIANT_DI_mul(const VARIANT_DI *a, const VARIANT_DI *b, VARIANT_DI *result)
Definition: vartype.c:4756
HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE *pbOut)
Definition: vartype.c:645
HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char *pcOut)
Definition: vartype.c:295
HRESULT WINAPI VarDateFromDisp(IDispatch *pdispIn, LCID lcid, DATE *pdateOut)
Definition: vartype.c:7376
HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6467
HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL *pDecOut)
Definition: vartype.c:4108
HRESULT WINAPI VarI8FromR8(double dblIn, LONG64 *pi64Out)
Definition: vartype.c:2142
HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
Definition: vartype.c:3300
HRESULT WINAPI VarDecRound(const DECIMAL *pDecIn, int cDecimals, DECIMAL *pDecOut)
Definition: vartype.c:5840
static HRESULT VARIANT_DI_div(const VARIANT_DI *dividend, const VARIANT_DI *divisor, VARIANT_DI *quotient, BOOL round_remainder)
Definition: vartype.c:5197
static void VARIANT_DIFromDec(const DECIMAL *from, VARIANT_DI *to)
Definition: vartype.c:4690
HRESULT WINAPI VarR4FromDisp(IDispatch *pdispIn, LCID lcid, float *pFltOut)
Definition: vartype.c:2845
HRESULT WINAPI VarDateFromI1(signed char cIn, DATE *pdateOut)
Definition: vartype.c:8023
HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT *pusOut)
Definition: vartype.c:1385
#define NEGTST(dest, src, func)
Definition: vartype.c:148
HRESULT WINAPI VarR8FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
Definition: vartype.c:3145
HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL *pDecOut)
Definition: vartype.c:4091
HMODULE hProxyDll
Definition: combase.c:40
HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT *pusOut)
Definition: vartype.c:1224
HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE *pbOut)
Definition: vartype.c:623
HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char *pcOut)
Definition: vartype.c:276
HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL *pDecOut)
Definition: vartype.c:4195
HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64 *pi64Out)
Definition: vartype.c:2372
HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
Definition: vartype.c:1504
HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE *pdateOut)
Definition: vartype.c:8112
HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE *pdateOut)
Definition: vartype.c:7336
HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6324
HRESULT WINAPI VarCyMulI8(CY cyLeft, LONG64 llRight, CY *pCyOut)
Definition: vartype.c:4067
static HRESULT VARIANT_do_division(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut, BOOL round)
Definition: vartype.c:5556
HRESULT WINAPI VarI1FromI4(LONG iIn, signed char *pcOut)
Definition: vartype.c:314
#define DP_AM
Definition: vartype.c:7419
static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG *pulHigh)
Definition: vartype.c:4512
HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
Definition: vartype.c:1677
HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64 *pi64Out)
Definition: vartype.c:2199
HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
Definition: vartype.c:1583
HRESULT WINAPI VarDecFix(const DECIMAL *pDecIn, DECIMAL *pDecOut)
Definition: vartype.c:5747
HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64 *pi64Out)
Definition: vartype.c:2168
static WCHAR * VARIANT_WriteNumber(ULONG64 ulVal, WCHAR *szOut)
Definition: vartype.c:6352
#define ORDER_YMD
Definition: vartype.c:7449
static HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate, DWORD offset, SYSTEMTIME *st)
Definition: vartype.c:7455
static BSTR VARIANT_BstrReplaceDecimal(const WCHAR *buff, LCID lcid, ULONG dwFlags)
Definition: vartype.c:6479
HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6669
HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64 *pui64Out)
Definition: vartype.c:2588
HRESULT WINAPI VarI1FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, signed char *pcOut)
Definition: vartype.c:421
HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64 *pi64Out)
Definition: vartype.c:2087
HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
Definition: vartype.c:3223
HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64 *pui64Out)
Definition: vartype.c:2445
HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE *pbOut)
Definition: vartype.c:670
HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:5983
HRESULT WINAPI VarI2FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, SHORT *psOut)
Definition: vartype.c:1015
HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE *pdateOut)
Definition: vartype.c:7285
HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
Definition: vartype.c:3124
HRESULT WINAPI VarDecFromDisp(IDispatch *pdispIn, LCID lcid, DECIMAL *pDecOut)
Definition: vartype.c:4286
#define DP_PM
Definition: vartype.c:7420
HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
Definition: vartype.c:2922
HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY *pCyOut)
Definition: vartype.c:3614
HRESULT WINAPI VarI4FromDisp(IDispatch *pdispIn, LCID lcid, LONG *piOut)
Definition: vartype.c:1626
HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT *psOut)
Definition: vartype.c:1070
HRESULT WINAPI VarCyRound(CY cyIn, int cDecimals, CY *pCyOut)
Definition: vartype.c:3968
HRESULT WINAPI VarUI4FromDec(const DECIMAL *pdecIn, ULONG *pulOut)
Definition: vartype.c:2006
HRESULT WINAPI VarCyFromDate(DATE dateIn, CY *pCyOut)
Definition: vartype.c:3547
HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
Definition: vartype.c:1543
HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64 *pi64Out)
Definition: vartype.c:2106
HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6001
HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
Definition: vartype.c:2712
HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
Definition: vartype.c:1660
HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6073
#define CY_MULTIPLIER
Definition: vartype.c:35
static unsigned char VARIANT_int_add(DWORD *v, unsigned int nv, const DWORD *p, unsigned int np)
Definition: vartype.c:4957
HRESULT WINAPI VarR4FromDec(const DECIMAL *pDecIn, float *pFltOut)
Definition: vartype.c:2940
#define IsLeapYear(y)
Definition: vartype.c:7432
static int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
Definition: vartype.c:4556
static void VARIANT_DI_clear(VARIANT_DI *i)
Definition: vartype.c:4710
HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT *psOut)
Definition: vartype.c:993
HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE *pbOut)
Definition: vartype.c:873
HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL *pDecOut)
Definition: vartype.c:4173
HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
Definition: vartype.c:1852
HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6839
HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT *psOut)
Definition: vartype.c:1150
HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6019
HRESULT WINAPI VarDecSub(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut)
Definition: vartype.c:5702
#define ORDER_DMY
Definition: vartype.c:7451
HRESULT WINAPI VarUI2FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, USHORT *pusOut)
Definition: vartype.c:1329
HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
Definition: vartype.c:3317
HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
Definition: vartype.c:1795
HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT *psOut)
Definition: vartype.c:1088
HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
Definition: vartype.c:2784
#define TIMEFLAG(i)
Definition: vartype.c:7430
HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT *pusOut)
Definition: vartype.c:1447
HRESULT WINAPI VarCyFromDec(const DECIMAL *pdecIn, CY *pCyOut)
Definition: vartype.c:3698
#define VARIANT_DutchRound(typ, value, res)
Definition: vartype.c:71
HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE *pbOut)
Definition: vartype.c:584
HRESULT WINAPI VarI2FromDec(const DECIMAL *pdecIn, SHORT *psOut)
Definition: vartype.c:1125
static HRESULT VARIANT_DI_normalize(VARIANT_DI *val, int exponent2, BOOL isDouble)
Definition: vartype.c:5285
HRESULT WINAPI VarCyCmpR8(CY cyLeft, double dblRight)
Definition: vartype.c:4040
HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
Definition: vartype.c:1739
HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64 *pui64Out)
Definition: vartype.c:2467
HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64 *pui64Out)
Definition: vartype.c:2527
HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64 *pi64Out)
Definition: vartype.c:2276
#define POSTST(dest, src, func, tst)
Definition: vartype.c:152
HRESULT WINAPI VarDecNeg(const DECIMAL *pDecIn, DECIMAL *pDecOut)
Definition: vartype.c:5819
HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
Definition: vartype.c:2729
HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char *pcOut)
Definition: vartype.c:562
HRESULT WINAPI VarUI8FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, ULONG64 *pui64Out)
Definition: vartype.c:2549
static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI *dest)
Definition: vartype.c:5449
HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
Definition: vartype.c:3362
HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
Definition: vartype.c:7219
static HRESULT VARIANT_FromDisp(IDispatch *pdispIn, LCID lcid, void *pOut, VARTYPE vt, DWORD dwFlags)
Definition: vartype.c:109
HRESULT WINAPI VarUI8FromDisp(IDispatch *pdispIn, LCID lcid, ULONG64 *pui64Out)
Definition: vartype.c:2570
HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
Definition: vartype.c:2031
HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
Definition: vartype.c:3243
HRESULT WINAPI VarUI1FromDec(const DECIMAL *pdecIn, BYTE *pbOut)
Definition: vartype.c:828
HRESULT WINAPI VarUI2FromDec(const DECIMAL *pdecIn, USHORT *pusOut)
Definition: vartype.c:1422
HRESULT WINAPI VarI4FromDec(const DECIMAL *pdecIn, LONG *piOut)
Definition: vartype.c:1714
static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI *dest)
Definition: vartype.c:5509
HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT *pusOut)
Definition: vartype.c:1284
HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL *pDecOut)
Definition: vartype.c:4420
HRESULT WINAPI VarI2FromDisp(IDispatch *pdispIn, LCID lcid, SHORT *psOut)
Definition: vartype.c:1036
HRESULT WINAPI VarDateFromCy(CY cyIn, DATE *pdateOut)
Definition: vartype.c:7410
HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT *pusOut)
Definition: vartype.c:1188
HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6055
HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE *pdateOut)
Definition: vartype.c:8057
HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
Definition: vartype.c:3073
HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL *pDecOut)
Definition: vartype.c:4352
HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY *pCyOut)
Definition: vartype.c:3736
HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE *pdateOut)
Definition: vartype.c:7393
HRESULT WINAPI VarI1FromDec(const DECIMAL *pdecIn, signed char *pcOut)
Definition: vartype.c:517
HRESULT WINAPI VarI2FromR8(double dblIn, SHORT *psOut)
Definition: vartype.c:951
HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL *pDecOut)
Definition: vartype.c:4306
HRESULT WINAPI VarCyCmp(CY cyLeft, CY cyRight)
Definition: vartype.c:4006
HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char *pcOut)
Definition: vartype.c:459
HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
Definition: vartype.c:2902
HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
Definition: vartype.c:2049
HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:7099
HRESULT WINAPI VarDecAbs(const DECIMAL *pDecIn, DECIMAL *pDecOut)
Definition: vartype.c:5723
struct tagDATEPARSE DATEPARSE
static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG *pulHigh)
Definition: vartype.c:4522
HRESULT WINAPI VarUI4FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
Definition: vartype.c:1914
#define ORDER_MYD
Definition: vartype.c:7452
HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT *pusOut)
Definition: vartype.c:1367
HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE *pbOut)
Definition: vartype.c:790
static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
Definition: vartype.c:6367
RETTYP _VarR8FromCy(CY i, double *o)
Definition: vartype.c:249
HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL *pDecOut)
Definition: vartype.c:4369
HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE *pbOut)
Definition: vartype.c:854
HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT *psOut)
Definition: vartype.c:930
HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL *pDecOut)
Definition: vartype.c:4125
HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:7127
#define CY_MULTIPLIER_F
Definition: vartype.c:36
HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
Definition: vartype.c:1564
HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6342
HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
Definition: vartype.c:1831
HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64 *pui64Out)
Definition: vartype.c:2393
HRESULT WINAPI VarR8FromDisp(IDispatch *pdispIn, LCID lcid, double *pDblOut)
Definition: vartype.c:3166
static void VARIANT_int_div(DWORD *p, unsigned int n, const DWORD *divisor, unsigned int dn)
Definition: vartype.c:4996
HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT *pusOut)
Definition: vartype.c:1403
HRESULT WINAPI VarBoolFromDec(const DECIMAL *pDecIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6300
HRESULT WINAPI VarUI1FromDisp(IDispatch *pdispIn, LCID lcid, BYTE *pbOut)
Definition: vartype.c:735
HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE *pbOut)
Definition: vartype.c:752
HRESULT WINAPI VarBoolFromDisp(IDispatch *pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6228
static void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
Definition: vartype.c:41
HRESULT WINAPI VarDecInt(const DECIMAL *pDecIn, DECIMAL *pDecOut)
Definition: vartype.c:5787
HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY *pCyOut)
Definition: vartype.c:3477
HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
Definition: vartype.c:2803
HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
Definition: vartype.c:1485
HRESULT WINAPI VarCyNeg(CY cyIn, CY *pCyOut)
Definition: vartype.c:3945
HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
Definition: vartype.c:2746
static HRESULT VARIANT_NumberFromBstr(const OLECHAR *pStrIn, LCID lcid, ULONG ulFlags, void *pOut, VARTYPE vt)
Definition: vartype.c:84
HRESULT WINAPI VarCyFromI4(LONG lIn, CY *pCyOut)
Definition: vartype.c:3456
HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6263
HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT *pusOut)
Definition: vartype.c:1465
static unsigned char VARIANT_int_divbychar(DWORD *p, unsigned int n, unsigned char divisor)
Definition: vartype.c:4720
HRESULT WINAPI VarCySub(CY cyLeft, CY cyRight, CY *pCyOut)
Definition: vartype.c:3848
HRESULT WINAPI VarCyFromDisp(IDispatch *pdispIn, LCID lcid, CY *pCyOut)
Definition: vartype.c:3590
HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT *psOut)
Definition: vartype.c:1106
HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
Definition: vartype.c:1952
HRESULT WINAPI VarDecMul(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut)
Definition: vartype.c:5647
static HRESULT VARIANT_DecScale(const DECIMAL **ppDecLeft, const DECIMAL **ppDecRight, DECIMAL pDecOut[2])
Definition: vartype.c:4430
HRESULT WINAPI VarI8FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, LONG64 *pi64Out)
Definition: vartype.c:2221
HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY *pCyOut)
Definition: vartype.c:3758
HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64 *pi64Out)
Definition: vartype.c:2310
HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
Definition: vartype.c:1891
static const int CY_Divisors[5]
Definition: vartype.c:3396
HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64 *pui64Out)
Definition: vartype.c:2410
HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
Definition: vartype.c:3203
HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
Definition: vartype.c:2862
HRESULT WINAPI VarI8FromDec(const DECIMAL *pdecIn, LONG64 *pi64Out)
Definition: vartype.c:2329
HRESULT WINAPI VarR8FromDec(const DECIMAL *pDecIn, double *pDblOut)
Definition: vartype.c:3261
HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64 *pui64Out)
Definition: vartype.c:2427
HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6627
HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE *pbOut)
Definition: vartype.c:771
HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6037
HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE *pbOut)
Definition: vartype.c:692
HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6281
HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
Definition: vartype.c:3039
HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL *pDecOut)
Definition: vartype.c:4217
HRESULT WINAPI VarBstrFromDisp(IDispatch *pdispIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:7148
HRESULT WINAPI VarDecDiv(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut)
Definition: vartype.c:5626
struct DECIMAL_internal VARIANT_DI
HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
Definition: vartype.c:2980
HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
Definition: vartype.c:3183
HRESULT WINAPI VarUI8FromDec(const DECIMAL *pdecIn, ULONG64 *pui64Out)
Definition: vartype.c:2664
HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char *pcOut)
Definition: vartype.c:543
HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY *pCyOut)
Definition: vartype.c:3677
HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE *pdateOut)
Definition: vartype.c:8040
HRESULT WINAPI VarDateFromR8(double dblIn, DATE *pdateOut)
Definition: vartype.c:7353
HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT *pusOut)
Definition: vartype.c:1206
static BOOL VARIANT_DI_tostringW(const VARIANT_DI *a, WCHAR *s, unsigned int n)
Definition: vartype.c:4850
HRESULT WINAPI VarBstrFromDec(const DECIMAL *pDecIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:7052
HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char *pcOut)
Definition: vartype.c:377
HRESULT WINAPI VarDateFromI2(short sIn, DATE *pdateOut)
Definition: vartype.c:7302
#define ORDER_YDM
Definition: vartype.c:7450
HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT *psOut)
Definition: vartype.c:972
HRESULT WINAPI VarI1FromCy(CY cyIn, signed char *pcOut)
Definition: vartype.c:396
static void VARIANT_int_shiftleft(DWORD *p, unsigned int n, unsigned int shift)
Definition: vartype.c:4930
HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
Definition: vartype.c:1873
HRESULT WINAPI VarDateFromI4(LONG lIn, DATE *pdateOut)
Definition: vartype.c:7319
HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
Definition: vartype.c:1777
HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:7010
HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64 *pi64Out)
Definition: vartype.c:2259
HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
Definition: vartype.c:7168
HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL *pDecOut)
Definition: vartype.c:4335
HRESULT WINAPI VarBoolFromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6139
HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64 *pi64Out)
Definition: vartype.c:2293
HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE *pdateOut)
Definition: vartype.c:8092
HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT *pusOut)
Definition: vartype.c:1242
HRESULT WINAPI VarCyFromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pCyOut)
Definition: vartype.c:3569
HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT *pusOut)
Definition: vartype.c:1263
#define SIMPLE(dest, src, func)
Definition: vartype.c:144
HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
Definition: vartype.c:3335
HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT *psOut)
Definition: vartype.c:912
HRESULT WINAPI VarDecFromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, DECIMAL *pDecOut)
Definition: vartype.c:4267
HRESULT WINAPI VarUI1FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, BYTE *pbOut)
Definition: vartype.c:714
HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
Definition: vartype.c:6245
HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
Definition: vartype.c:1695
HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64 *pui64Out)
Definition: vartype.c:2605
HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:7031
HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
Definition: vartype.c:2764
HRESULT WINAPI VarCyFromI2(SHORT sIn, CY *pCyOut)
Definition: vartype.c:3435
#define DP_MONTH
Definition: vartype.c:7418
HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL *pDecOut)
Definition: vartype.c:4390
BOOL get_date_format(LCID lcid, DWORD flags, const SYSTEMTIME *st, const WCHAR *fmt, WCHAR *date, int date_len)
Definition: vartype.c:6729
static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut, int ndigits)
Definition: vartype.c:6540
static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
Definition: vartype.c:6085
static unsigned char VARIANT_int_mulbychar(DWORD *p, unsigned int n, unsigned char m)
Definition: vartype.c:5028
HRESULT WINAPI VarR4FromStr(const OLECHAR *strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
Definition: vartype.c:2824
HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
Definition: vartype.c:3090
#define DATE_SWAP(x, y)
static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6386
static int VARIANT_int_addlossy(DWORD *a, int *ascale, unsigned int an, DWORD *b, int *bscale, unsigned int bn)
Definition: vartype.c:5043
HRESULT WINAPI VarCyAdd(CY cyLeft, CY cyRight, CY *pCyOut)
Definition: vartype.c:3779
HRESULT WINAPI VarCyFromI1(signed char cIn, CY *pCyOut)
Definition: vartype.c:3635
static void VARIANT_DecFromDI(const VARIANT_DI *from, DECIMAL *to)
Definition: vartype.c:4700
HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
Definition: vartype.c:1522
HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
Definition: vartype.c:6982
HRESULT WINAPI VarDateFromDec(const DECIMAL *pdecIn, DATE *pdateOut)
Definition: vartype.c:8074
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static const WCHAR month[12][4]
Definition: session.c:2528
#define swprintf
Definition: precomp.h:40
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
double pow(double x, double y)
Definition: freeldr.c:179
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLboolean invert
Definition: gl.h:1949
GLdouble n
Definition: glext.h:7729
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLintptr offset
Definition: glext.h:5920
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLuint divisor
Definition: glext.h:6313
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:6064
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat v1
Definition: glext.h:6062
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define d
Definition: ke_i.h:81
#define e
Definition: ke_i.h:82
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, LPCWSTR lpszValue, const NUMBERFMTW *lpFormat, LPWSTR lpNumberStr, int cchOut)
Definition: lcformat.c:1130
INT WINAPI GetCurrencyFormatW(LCID lcid, DWORD dwFlags, LPCWSTR lpszValue, const CURRENCYFMTW *lpFormat, LPWSTR lpCurrencyStr, int cchOut)
Definition: lcformat.c:1401
INT WINAPI GetTimeFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, INT cchOut)
Definition: lcformat.c:1101
USHORT LANGID
Definition: mui.h:9
#define sign(x)
Definition: mapdesc.cc:613
__u16 date
Definition: mkdosfs.c:8
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
struct task_struct * current
Definition: linux.c:32
unsigned __int64 ULONG64
Definition: imports.h:198
HRESULT hres
Definition: protocol.c:465
static size_t double int ndigits
Definition: printf.c:52
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:91
#define cmp(status, error)
Definition: error.c:118
static char * dest
Definition: rtl.c:149
#define shift
Definition: input.c:3280
#define min(a, b)
Definition: monoChain.cc:55
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define SORT_DEFAULT
#define MAKELCID(lgid, srtid)
UINT WINAPI SysStringByteLen(BSTR str)
Definition: oleaut.c:217
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:240
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:198
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:273
BSTR WINAPI DECLSPEC_HOTPATCH SysAllocStringByteLen(LPCSTR str, UINT len)
Definition: oleaut.c:430
#define VARCMP_LT
Definition: oleauto.h:657
#define V_UI1(A)
Definition: oleauto.h:266
#define VAR_CALENDAR_GREGORIAN
Definition: oleauto.h:334
#define VARCMP_NULL
Definition: oleauto.h:660
#define VAR_CALENDAR_THAI
Definition: oleauto.h:333
#define VARCMP_EQ
Definition: oleauto.h:658
#define VAR_DATEVALUEONLY
Definition: oleauto.h:327
#define V_UI2(A)
Definition: oleauto.h:268
#define VARCMP_GT
Definition: oleauto.h:659
#define VAR_LOCALBOOL
Definition: oleauto.h:330
#define V_INT_PTR(A)
Definition: oleauto.h:257
#define V_BSTR(A)
Definition: oleauto.h:226
#define LOCALE_USE_NLS
Definition: oleauto.h:338
#define VAR_CALENDAR_HIJRI
Definition: oleauto.h:329
#define V_DECIMAL(A)
Definition: oleauto.h:236
#define V_UI4(A)
Definition: oleauto.h:270
#define DISPATCH_PROPERTYGET
Definition: oleauto.h:1007
#define VAR_TIMEVALUEONLY
Definition: oleauto.h:326
#define V_UI8(A)
Definition: oleauto.h:272
#define NUMPRS_STD
Definition: oleauto.h:748
#define round(x)
Definition: opentype.c:47
#define RT_STRING
Definition: pedump.c:368
short WCHAR
Definition: pedump.c:58
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
char CHAR
Definition: pedump.c:57
#define IID_NULL
Definition: guiddef.h:98
_In_ DWORD _In_ DWORD dwOffset
Definition: ntgdi.h:2033
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tpush %rbx\n" "\t.seh_pushreg %rbx\n" "\tpush %rdi\n" "\t.seh_pushreg %rdi\n" "\tpush %rsi\n" "\t.seh_pushreg %rsi\n" "\tpush %r12\n" "\t.seh_pushreg %r12\n" "\tpush %r13\n" "\t.seh_pushreg %r13\n" "\tpush %r14\n" "\t.seh_pushreg %r14\n" "\tpush %r15\n" "\t.seh_pushreg %r15\n" "\tsub $40, %rsp\n" "\t.seh_stackalloc 40\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $40, %rsp\n" "\tpop %r15\n" "\tpop %r14\n" "\tpop %r13\n" "\tpop %r12\n" "\tpop %rsi\n" "\tpop %rdi\n" "\tpop %rbx\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
static calc_node_t temp
Definition: rpn_ieee.c:38
#define iswspace(_c)
Definition: ctype.h:669
#define iswalpha(_c)
Definition: ctype.h:664
#define LANG_NEUTRAL
Definition: nls.h:22
#define MAKELANGID(p, s)
Definition: nls.h:15
#define LANG_ENGLISH
Definition: nls.h:52
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define SUBLANG_DEFAULT
Definition: nls.h:168
DWORD LCID
Definition: nls.h:13
#define PRIMARYLANGID(l)
Definition: nls.h:16
wcscat
#define memset(x, y, z)
Definition: compat.h:39
int one
Definition: sehframes.cpp:28
static const char *static const char const char DWORD void DWORD *static const char const char DWORD void DWORD *static const char DWORD DWORD void * buff
Definition: shcore.c:41
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
unsigned int sign
Definition: vartype.c:4151
DWORD bitsnum[3]
Definition: vartype.c:4149
unsigned char scale
Definition: vartype.c:4150
ULONG dwInFlags
Definition: oleauto.h:728
INT cDig
Definition: oleauto.h:727
WORD wMilliseconds
Definition: minwinbase.h:263
WORD wSecond
Definition: minwinbase.h:262
WORD wMinute
Definition: minwinbase.h:261
WORD wDayOfWeek
Definition: minwinbase.h:258
$ULONG LowPart
Definition: ntbasedef.h:581
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
$ULONG HighPart
Definition: ntbasedef.h:582
UINT NumDigits
Definition: winnls.h:726
LPWSTR lpDecimalSep
Definition: winnls.h:729
UINT Grouping
Definition: winnls.h:728
UINT NegativeOrder
Definition: winnls.h:731
LPWSTR lpThousandSep
Definition: winnls.h:730
UINT LeadingZero
Definition: winnls.h:727
Definition: dsound.c:943
DWORD dwParseFlags
Definition: vartype.c:7425
DWORD dwCount
Definition: vartype.c:7424
DWORD dwFlags[6]
Definition: vartype.c:7426
DWORD dwValues[6]
Definition: vartype.c:7427
ULONG Hi32
Definition: compat.h:2276
BYTE sign
Definition: compat.h:2272
ULONG Lo32
Definition: compat.h:2283
BYTE scale
Definition: compat.h:2271
ULONG Mid32
Definition: compat.h:2284
ULONGLONG Lo64
Definition: compat.h:2287
DWORD dwFormatFlags
Definition: trayclock.cpp:31
GLfixed fx
Definition: tritemp.h:484
const char * LPCSTR
Definition: typedefs.h:52
int32_t INT_PTR
Definition: typedefs.h:64
int64_t LONG64
Definition: typedefs.h:68
float FLOAT
Definition: typedefs.h:69
uint16_t * LPWSTR
Definition: typedefs.h:56
int64_t LONGLONG
Definition: typedefs.h:68
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG
Definition: typedefs.h:59
double DOUBLE
Definition: typedefs.h:70
unsigned int exp_bias
Definition: vartype.c:5441
unsigned int sign
Definition: vartype.c:5442
float f
Definition: vartype.c:5444
unsigned int m
Definition: vartype.c:5440
double d
Definition: vartype.c:5504
unsigned int sign
Definition: vartype.c:5502
unsigned int m_hi
Definition: vartype.c:5500
unsigned int exp_bias
Definition: vartype.c:5501
unsigned int m_lo
Definition: vartype.c:5499
Definition: compat.h:2255
ULONG Lo
Definition: compat.h:2261
LONG Hi
Definition: compat.h:2262
LONGLONG int64
Definition: compat.h:2265
HRESULT WINAPI VarParseNumFromStr(const OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, NUMPARSE *pNumprs, BYTE *rgbDig)
Definition: variant.c:1578
INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt)
Definition: variant.c:1294
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:626
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG *pvargDest, const VARIANTARG *pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
Definition: variant.c:965
HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig, ULONG dwVtBits, VARIANT *pVarDst)
Definition: variant.c:2060
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:547
INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut)
Definition: variant.c:1263
#define UI4_MIN
Definition: variant.h:62
#define I8_MAX
Definition: variant.h:63
#define I2_MIN
Definition: variant.h:56
#define UI2_MIN
Definition: variant.h:58
#define DATE_MAX
Definition: variant.h:67
#define I4_MAX
Definition: variant.h:59
#define I2_MAX
Definition: variant.h:55
#define R4_MAX
Definition: variant.h:69
#define I8_MIN
Definition: variant.h:64
#define I1_MIN
Definition: variant.h:52
#define UI2_MAX
Definition: variant.h:57
#define UI1_MIN
Definition: variant.h:54
#define VAR_NEGATIVE
Definition: variant.h:82
#define I4_MIN
Definition: variant.h:60
#define UI4_MAX
Definition: variant.h:61
#define DATE_MIN
Definition: variant.h:68
#define I1_MAX
Definition: variant.h:51
#define DECIMAL_POS
Definition: variant.h:75
#define VAR_BOOLONOFF
Definition: variant.h:80
#define VAR_BOOLYESNO
Definition: variant.h:81
#define DEC_MAX_SCALE
Definition: variant.h:77
#define UI1_MAX
Definition: variant.h:53
_In_ ULONG _In_ ULONG rgb
Definition: winddi.h:3521
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define DISP_E_OVERFLOW
Definition: winerror.h:3622
#define DISP_E_BADVARTYPE
Definition: winerror.h:3620
#define DISP_E_TYPEMISMATCH
Definition: winerror.h:3617
#define DISP_E_DIVBYZERO
Definition: winerror.h:3630
#define LOCALE_SABBREVMONTHNAME10
Definition: winnls.h:123
#define LOCALE_SMONTHNAME12
Definition: winnls.h:112
#define LOCALE_SMONTHNAME5
Definition: winnls.h:105
#define LOCALE_SDATE
Definition: winnls.h:68
#define LOCALE_SDAYNAME5
Definition: winnls.h:91
#define LOCALE_SABBREVMONTHNAME9
Definition: winnls.h:122
#define LOCALE_SABBREVMONTHNAME11
Definition: winnls.h:124
#define LOCALE_SABBREVDAYNAME5
Definition: winnls.h:98
#define LOCALE_SABBREVDAYNAME2
Definition: winnls.h:95
#define LOCALE_SABBREVMONTHNAME2
Definition: winnls.h:115
#define LOCALE_SMONTHNAME13
Definition: winnls.h:113
#define LOCALE_SMONTHNAME3
Definition: winnls.h:103
#define LOCALE_SDECIMAL
Definition: winnls.h:52
#define LOCALE_SMONTHNAME11
Definition: winnls.h:111
#define LOCALE_SMONTHNAME8
Definition: winnls.h:108
#define LOCALE_IDATE
Definition: winnls.h:73
#define LOCALE_SMONTHNAME4
Definition: winnls.h:104
#define LOCALE_SABBREVMONTHNAME13
Definition: winnls.h:126
#define LOCALE_SDAYNAME1
Definition: winnls.h:87
#define LOCALE_SMONTHNAME7
Definition: winnls.h:107
#define LOCALE_S1159
Definition: winnls.h:81
#define LOCALE_SSHORTDATE
Definition: winnls.h:70
#define LOCALE_SABBREVMONTHNAME4
Definition: winnls.h:117
#define LOCALE_SABBREVDAYNAME4
Definition: winnls.h:97
#define LOCALE_SMONTHNAME1
Definition: winnls.h:101
#define LOCALE_SABBREVMONTHNAME3
Definition: winnls.h:116
#define LOCALE_SDAYNAME7
Definition: winnls.h:93
#define LOCALE_SDAYNAME2
Definition: winnls.h:88
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:114
#define LOCALE_NOUSEROVERRIDE
Definition: winnls.h:19
#define LOCALE_SABBREVDAYNAME6
Definition: winnls.h:99
#define LOCALE_SMONTHNAME2
Definition: winnls.h:102
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:94
#define LOCALE_SABBREVMONTHNAME6
Definition: winnls.h:119
#define LOCALE_SMONTHNAME6
Definition: winnls.h:106
DWORD LCTYPE
Definition: winnls.h:592
#define LOCALE_SDAYNAME3
Definition: winnls.h:89
#define CSTR_LESS_THAN
Definition: winnls.h:507
#define LOCALE_S2359
Definition: winnls.h:82
#define LOCALE_SABBREVDAYNAME3
Definition: winnls.h:96
#define LOCALE_ILZERO
Definition: winnls.h:56
#define LOCALE_SABBREVMONTHNAME5
Definition: winnls.h:118
#define LOCALE_SABBREVMONTHNAME7
Definition: winnls.h:120
#define LOCALE_SABBREVMONTHNAME8
Definition: winnls.h:121
#define LOCALE_SDAYNAME4
Definition: winnls.h:90
#define LOCALE_SMONTHNAME10
Definition: winnls.h:110
#define LOCALE_SMONTHNAME9
Definition: winnls.h:109
#define LOCALE_SABBREVMONTHNAME12
Definition: winnls.h:125
#define LOCALE_SDAYNAME6
Definition: winnls.h:92
#define LOCALE_SABBREVDAYNAME7
Definition: winnls.h:100
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
unsigned char BYTE
Definition: xxhash.c:193