ReactOS  0.4.14-dev-608-gd495a4f
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 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
24 
25 #include <wchar.h>
26 
27 #include "wine/debug.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winnt.h"
31 #include "variant.h"
32 #include "resource.h"
33 
35 
36 extern HMODULE hProxyDll DECLSPEC_HIDDEN;
37 
38 #define CY_MULTIPLIER 10000 /* 4 dp of precision */
39 #define CY_MULTIPLIER_F 10000.0
40 #define CY_HALF (CY_MULTIPLIER/2) /* 0.5 */
41 #define CY_HALF_F (CY_MULTIPLIER_F/2.0)
42 
43 static const WCHAR szFloatFormatW[] = { '%','.','7','G','\0' };
44 static const WCHAR szDoubleFormatW[] = { '%','.','1','5','G','\0' };
45 
46 /* Copy data from one variant to another. */
47 static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
48 {
49  switch (vt)
50  {
51  case VT_I1:
52  case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
53  case VT_BOOL:
54  case VT_I2:
55  case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
56  case VT_R4:
57  case VT_INT:
58  case VT_I4:
59  case VT_UINT:
60  case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
61  case VT_R8:
62  case VT_DATE:
63  case VT_CY:
64  case VT_I8:
65  case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
66  case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
67  case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
68  case VT_BSTR: memcpy(pOut, &V_BSTR(srcVar), sizeof(BSTR)); break;
69  default:
70  FIXME("VT_ type %d unhandled, please report!\n", vt);
71  }
72 }
73 
74 /* Macro to inline conversion from a float or double to any integer type,
75  * rounding according to the 'dutch' convention.
76  */
77 #define VARIANT_DutchRound(typ, value, res) do { \
78  double whole = value < 0 ? ceil(value) : floor(value); \
79  double fract = value - whole; \
80  if (fract > 0.5) res = (typ)whole + (typ)1; \
81  else if (fract == 0.5) { typ is_odd = (typ)whole & 1; res = whole + is_odd; } \
82  else if (fract >= 0.0) res = (typ)whole; \
83  else if (fract == -0.5) { typ is_odd = (typ)whole & 1; res = whole - is_odd; } \
84  else if (fract > -0.5) res = (typ)whole; \
85  else res = (typ)whole - (typ)1; \
86 } while(0)
87 
88 
89 /* Coerce VT_BSTR to a numeric type */
90 static HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
91  void* pOut, VARTYPE vt)
92 {
93  VARIANTARG dstVar;
94  HRESULT hRet;
95  NUMPARSE np;
96  BYTE rgb[1024];
97 
98  /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
99  np.cDig = ARRAY_SIZE(rgb);
100  np.dwInFlags = NUMPRS_STD;
101 
102  hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
103 
104  if (SUCCEEDED(hRet))
105  {
106  /* 1 << vt gives us the VTBIT constant for the destination number type */
107  hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
108  if (SUCCEEDED(hRet))
109  VARIANT_CopyData(&dstVar, vt, pOut);
110  }
111  return hRet;
112 }
113 
114 /* Coerce VT_DISPATCH to another type */
115 static HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut,
117 {
118  static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
119  VARIANTARG srcVar, dstVar;
120  HRESULT hRet;
121 
122  if (!pdispIn)
123  return DISP_E_BADVARTYPE;
124 
125  /* Get the default 'value' property from the IDispatch */
126  VariantInit(&srcVar);
127  hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
128  &emptyParams, &srcVar, NULL, NULL);
129 
130  if (SUCCEEDED(hRet))
131  {
132  /* Convert the property to the requested type */
133  VariantInit(&dstVar);
134  hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, dwFlags, vt);
135  VariantClear(&srcVar);
136 
137  if (SUCCEEDED(hRet))
138  VARIANT_CopyData(&dstVar, vt, pOut);
139  }
140  else
141  hRet = DISP_E_TYPEMISMATCH;
142  return hRet;
143 }
144 
145 /* Inline return type */
146 #define RETTYP static inline HRESULT
147 
148 
149 /* Simple compiler cast from one type to another */
150 #define SIMPLE(dest, src, func) RETTYP _##func(src in, dest* out) { \
151  *out = in; return S_OK; }
152 
153 /* Compiler cast where input cannot be negative */
154 #define NEGTST(dest, src, func) RETTYP _##func(src in, dest* out) { \
155  if (in < 0) return DISP_E_OVERFLOW; *out = in; return S_OK; }
156 
157 /* Compiler cast where input cannot be > some number */
158 #define POSTST(dest, src, func, tst) RETTYP _##func(src in, dest* out) { \
159  if (in > (dest)tst) return DISP_E_OVERFLOW; *out = in; return S_OK; }
160 
161 /* Compiler cast where input cannot be < some number or >= some other number */
162 #define BOTHTST(dest, src, func, lo, hi) RETTYP _##func(src in, dest* out) { \
163  if (in < (dest)lo || in > hi) return DISP_E_OVERFLOW; *out = in; return S_OK; }
164 
165 /* I1 */
166 POSTST(signed char, BYTE, VarI1FromUI1, I1_MAX)
167 BOTHTST(signed char, SHORT, VarI1FromI2, I1_MIN, I1_MAX)
168 BOTHTST(signed char, LONG, VarI1FromI4, I1_MIN, I1_MAX)
169 SIMPLE(signed char, VARIANT_BOOL, VarI1FromBool)
170 POSTST(signed char, USHORT, VarI1FromUI2, I1_MAX)
171 POSTST(signed char, ULONG, VarI1FromUI4, I1_MAX)
172 BOTHTST(signed char, LONG64, VarI1FromI8, I1_MIN, I1_MAX)
173 POSTST(signed char, ULONG64, VarI1FromUI8, I1_MAX)
174 
175 /* UI1 */
178 NEGTST(BYTE, signed char, VarUI1FromI1)
184 
185 /* I2 */
189 SIMPLE(SHORT, signed char, VarI2FromI1)
194 
195 /* UI2 */
200 NEGTST(USHORT, signed char, VarUI2FromI1)
204 
205 /* I4 */
209 SIMPLE(LONG, signed char, VarI4FromI1)
214 
215 /* UI4 */
220 NEGTST(ULONG, signed char, VarUI4FromI1)
224 
225 /* I8 */
228 SIMPLE(LONG64, signed char, VarI8FromI1)
232 
233 /* UI8 */
236 NEGTST(ULONG64, signed char, VarUI8FromI1)
240 
241 /* R4 (float) */
242 SIMPLE(float, BYTE, VarR4FromUI1)
243 SIMPLE(float, SHORT, VarR4FromI2)
244 SIMPLE(float, signed char, VarR4FromI1)
245 SIMPLE(float, USHORT, VarR4FromUI2)
246 SIMPLE(float, LONG, VarR4FromI4)
247 SIMPLE(float, ULONG, VarR4FromUI4)
248 SIMPLE(float, LONG64, VarR4FromI8)
249 SIMPLE(float, ULONG64, VarR4FromUI8)
250 
251 /* R8 (double) */
252 SIMPLE(double, BYTE, VarR8FromUI1)
253 SIMPLE(double, SHORT, VarR8FromI2)
254 SIMPLE(double, float, VarR8FromR4)
255 RETTYP _VarR8FromCy(CY i, double* o) { *o = (double)i.int64 / CY_MULTIPLIER_F; return S_OK; }
256 SIMPLE(double, DATE, VarR8FromDate)
257 SIMPLE(double, signed char, VarR8FromI1)
258 SIMPLE(double, USHORT, VarR8FromUI2)
259 SIMPLE(double, LONG, VarR8FromI4)
260 SIMPLE(double, ULONG, VarR8FromUI4)
261 SIMPLE(double, LONG64, VarR8FromI8)
262 SIMPLE(double, ULONG64, VarR8FromUI8)
263 
264 
265 /* I1
266  */
267 
268 /************************************************************************
269  * VarI1FromUI1 (OLEAUT32.244)
270  *
271  * Convert a VT_UI1 to a VT_I1.
272  *
273  * PARAMS
274  * bIn [I] Source
275  * pcOut [O] Destination
276  *
277  * RETURNS
278  * Success: S_OK.
279  * Failure: E_INVALIDARG, if the source value is invalid
280  * DISP_E_OVERFLOW, if the value will not fit in the destination
281  */
282 HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
283 {
284  return _VarI1FromUI1(bIn, pcOut);
285 }
286 
287 /************************************************************************
288  * VarI1FromI2 (OLEAUT32.245)
289  *
290  * Convert a VT_I2 to a VT_I1.
291  *
292  * PARAMS
293  * sIn [I] Source
294  * pcOut [O] Destination
295  *
296  * RETURNS
297  * Success: S_OK.
298  * Failure: E_INVALIDARG, if the source value is invalid
299  * DISP_E_OVERFLOW, if the value will not fit in the destination
300  */
301 HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
302 {
303  return _VarI1FromI2(sIn, pcOut);
304 }
305 
306 /************************************************************************
307  * VarI1FromI4 (OLEAUT32.246)
308  *
309  * Convert a VT_I4 to a VT_I1.
310  *
311  * PARAMS
312  * iIn [I] Source
313  * pcOut [O] Destination
314  *
315  * RETURNS
316  * Success: S_OK.
317  * Failure: E_INVALIDARG, if the source value is invalid
318  * DISP_E_OVERFLOW, if the value will not fit in the destination
319  */
320 HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
321 {
322  return _VarI1FromI4(iIn, pcOut);
323 }
324 
325 /************************************************************************
326  * VarI1FromR4 (OLEAUT32.247)
327  *
328  * Convert a VT_R4 to a VT_I1.
329  *
330  * PARAMS
331  * fltIn [I] Source
332  * pcOut [O] Destination
333  *
334  * RETURNS
335  * Success: S_OK.
336  * Failure: E_INVALIDARG, if the source value is invalid
337  * DISP_E_OVERFLOW, if the value will not fit in the destination
338  */
339 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
340 {
341  return VarI1FromR8(fltIn, pcOut);
342 }
343 
344 /************************************************************************
345  * VarI1FromR8 (OLEAUT32.248)
346  *
347  * Convert a VT_R8 to a VT_I1.
348  *
349  * PARAMS
350  * dblIn [I] Source
351  * pcOut [O] Destination
352  *
353  * RETURNS
354  * Success: S_OK.
355  * Failure: E_INVALIDARG, if the source value is invalid
356  * DISP_E_OVERFLOW, if the value will not fit in the destination
357  *
358  * NOTES
359  * See VarI8FromR8() for details concerning rounding.
360  */
361 HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
362 {
363  if (dblIn < I1_MIN - 0.5 || dblIn >= I1_MAX + 0.5)
364  return DISP_E_OVERFLOW;
365  VARIANT_DutchRound(CHAR, dblIn, *pcOut);
366  return S_OK;
367 }
368 
369 /************************************************************************
370  * VarI1FromDate (OLEAUT32.249)
371  *
372  * Convert a VT_DATE to a VT_I1.
373  *
374  * PARAMS
375  * dateIn [I] Source
376  * pcOut [O] Destination
377  *
378  * RETURNS
379  * Success: S_OK.
380  * Failure: E_INVALIDARG, if the source value is invalid
381  * DISP_E_OVERFLOW, if the value will not fit in the destination
382  */
383 HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
384 {
385  return VarI1FromR8(dateIn, pcOut);
386 }
387 
388 /************************************************************************
389  * VarI1FromCy (OLEAUT32.250)
390  *
391  * Convert a VT_CY to a VT_I1.
392  *
393  * PARAMS
394  * cyIn [I] Source
395  * pcOut [O] Destination
396  *
397  * RETURNS
398  * Success: S_OK.
399  * Failure: E_INVALIDARG, if the source value is invalid
400  * DISP_E_OVERFLOW, if the value will not fit in the destination
401  */
402 HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
403 {
404  LONG i = I1_MAX + 1;
405 
406  VarI4FromCy(cyIn, &i);
407  return _VarI1FromI4(i, pcOut);
408 }
409 
410 /************************************************************************
411  * VarI1FromStr (OLEAUT32.251)
412  *
413  * Convert a VT_BSTR to a VT_I1.
414  *
415  * PARAMS
416  * strIn [I] Source
417  * lcid [I] LCID for the conversion
418  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
419  * pcOut [O] Destination
420  *
421  * RETURNS
422  * Success: S_OK.
423  * Failure: E_INVALIDARG, if the source value is invalid
424  * DISP_E_OVERFLOW, if the value will not fit in the destination
425  * DISP_E_TYPEMISMATCH, if the type cannot be converted
426  */
427 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
428 {
429  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pcOut, VT_I1);
430 }
431 
432 /************************************************************************
433  * VarI1FromDisp (OLEAUT32.252)
434  *
435  * Convert a VT_DISPATCH to a VT_I1.
436  *
437  * PARAMS
438  * pdispIn [I] Source
439  * lcid [I] LCID for conversion
440  * pcOut [O] Destination
441  *
442  * RETURNS
443  * Success: S_OK.
444  * Failure: E_INVALIDARG, if the source value is invalid
445  * DISP_E_OVERFLOW, if the value will not fit in the destination
446  * DISP_E_TYPEMISMATCH, if the type cannot be converted
447  */
448 HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
449 {
450  return VARIANT_FromDisp(pdispIn, lcid, pcOut, VT_I1, 0);
451 }
452 
453 /************************************************************************
454  * VarI1FromBool (OLEAUT32.253)
455  *
456  * Convert a VT_BOOL to a VT_I1.
457  *
458  * PARAMS
459  * boolIn [I] Source
460  * pcOut [O] Destination
461  *
462  * RETURNS
463  * S_OK.
464  */
465 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
466 {
467  return _VarI1FromBool(boolIn, pcOut);
468 }
469 
470 /************************************************************************
471  * VarI1FromUI2 (OLEAUT32.254)
472  *
473  * Convert a VT_UI2 to a VT_I1.
474  *
475  * PARAMS
476  * usIn [I] Source
477  * pcOut [O] Destination
478  *
479  * RETURNS
480  * Success: S_OK.
481  * Failure: E_INVALIDARG, if the source value is invalid
482  * DISP_E_OVERFLOW, if the value will not fit in the destination
483  */
484 HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
485 {
486  return _VarI1FromUI2(usIn, pcOut);
487 }
488 
489 /************************************************************************
490  * VarI1FromUI4 (OLEAUT32.255)
491  *
492  * Convert a VT_UI4 to a VT_I1.
493  *
494  * PARAMS
495  * ulIn [I] Source
496  * pcOut [O] Destination
497  *
498  * RETURNS
499  * Success: S_OK.
500  * Failure: E_INVALIDARG, if the source value is invalid
501  * DISP_E_OVERFLOW, if the value will not fit in the destination
502  * DISP_E_TYPEMISMATCH, if the type cannot be converted
503  */
504 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
505 {
506  return _VarI1FromUI4(ulIn, pcOut);
507 }
508 
509 /************************************************************************
510  * VarI1FromDec (OLEAUT32.256)
511  *
512  * Convert a VT_DECIMAL to a VT_I1.
513  *
514  * PARAMS
515  * pDecIn [I] Source
516  * pcOut [O] Destination
517  *
518  * RETURNS
519  * Success: S_OK.
520  * Failure: E_INVALIDARG, if the source value is invalid
521  * DISP_E_OVERFLOW, if the value will not fit in the destination
522  */
523 HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
524 {
525  LONG64 i64;
526  HRESULT hRet;
527 
528  hRet = VarI8FromDec(pdecIn, &i64);
529 
530  if (SUCCEEDED(hRet))
531  hRet = _VarI1FromI8(i64, pcOut);
532  return hRet;
533 }
534 
535 /************************************************************************
536  * VarI1FromI8 (OLEAUT32.376)
537  *
538  * Convert a VT_I8 to a VT_I1.
539  *
540  * PARAMS
541  * llIn [I] Source
542  * pcOut [O] Destination
543  *
544  * RETURNS
545  * Success: S_OK.
546  * Failure: E_INVALIDARG, if the source value is invalid
547  * DISP_E_OVERFLOW, if the value will not fit in the destination
548  */
549 HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
550 {
551  return _VarI1FromI8(llIn, pcOut);
552 }
553 
554 /************************************************************************
555  * VarI1FromUI8 (OLEAUT32.377)
556  *
557  * Convert a VT_UI8 to a VT_I1.
558  *
559  * PARAMS
560  * ullIn [I] Source
561  * pcOut [O] Destination
562  *
563  * RETURNS
564  * Success: S_OK.
565  * Failure: E_INVALIDARG, if the source value is invalid
566  * DISP_E_OVERFLOW, if the value will not fit in the destination
567  */
568 HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
569 {
570  return _VarI1FromUI8(ullIn, pcOut);
571 }
572 
573 /* UI1
574  */
575 
576 /************************************************************************
577  * VarUI1FromI2 (OLEAUT32.130)
578  *
579  * Convert a VT_I2 to a VT_UI1.
580  *
581  * PARAMS
582  * sIn [I] Source
583  * pbOut [O] Destination
584  *
585  * RETURNS
586  * Success: S_OK.
587  * Failure: E_INVALIDARG, if the source value is invalid
588  * DISP_E_OVERFLOW, if the value will not fit in the destination
589  */
591 {
592  return _VarUI1FromI2(sIn, pbOut);
593 }
594 
595 /************************************************************************
596  * VarUI1FromI4 (OLEAUT32.131)
597  *
598  * Convert a VT_I4 to a VT_UI1.
599  *
600  * PARAMS
601  * iIn [I] Source
602  * pbOut [O] Destination
603  *
604  * RETURNS
605  * Success: S_OK.
606  * Failure: E_INVALIDARG, if the source value is invalid
607  * DISP_E_OVERFLOW, if the value will not fit in the destination
608  */
610 {
611  return _VarUI1FromI4(iIn, pbOut);
612 }
613 
614 /************************************************************************
615  * VarUI1FromR4 (OLEAUT32.132)
616  *
617  * Convert a VT_R4 to a VT_UI1.
618  *
619  * PARAMS
620  * fltIn [I] Source
621  * pbOut [O] Destination
622  *
623  * RETURNS
624  * Success: S_OK.
625  * Failure: E_INVALIDARG, if the source value is invalid
626  * DISP_E_OVERFLOW, if the value will not fit in the destination
627  * DISP_E_TYPEMISMATCH, if the type cannot be converted
628  */
630 {
631  return VarUI1FromR8(fltIn, pbOut);
632 }
633 
634 /************************************************************************
635  * VarUI1FromR8 (OLEAUT32.133)
636  *
637  * Convert a VT_R8 to a VT_UI1.
638  *
639  * PARAMS
640  * dblIn [I] Source
641  * pbOut [O] Destination
642  *
643  * RETURNS
644  * Success: S_OK.
645  * Failure: E_INVALIDARG, if the source value is invalid
646  * DISP_E_OVERFLOW, if the value will not fit in the destination
647  *
648  * NOTES
649  * See VarI8FromR8() for details concerning rounding.
650  */
651 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
652 {
653  if (dblIn < -0.5 || dblIn >= UI1_MAX + 0.5)
654  return DISP_E_OVERFLOW;
655  VARIANT_DutchRound(BYTE, dblIn, *pbOut);
656  return S_OK;
657 }
658 
659 /************************************************************************
660  * VarUI1FromCy (OLEAUT32.134)
661  *
662  * Convert a VT_CY to a VT_UI1.
663  *
664  * PARAMS
665  * cyIn [I] Source
666  * pbOut [O] Destination
667  *
668  * RETURNS
669  * Success: S_OK.
670  * Failure: E_INVALIDARG, if the source value is invalid
671  * DISP_E_OVERFLOW, if the value will not fit in the destination
672  *
673  * NOTES
674  * Negative values >= -5000 will be converted to 0.
675  */
677 {
678  ULONG i = UI1_MAX + 1;
679 
680  VarUI4FromCy(cyIn, &i);
681  return _VarUI1FromUI4(i, pbOut);
682 }
683 
684 /************************************************************************
685  * VarUI1FromDate (OLEAUT32.135)
686  *
687  * Convert a VT_DATE to a VT_UI1.
688  *
689  * PARAMS
690  * dateIn [I] Source
691  * pbOut [O] Destination
692  *
693  * RETURNS
694  * Success: S_OK.
695  * Failure: E_INVALIDARG, if the source value is invalid
696  * DISP_E_OVERFLOW, if the value will not fit in the destination
697  */
699 {
700  return VarUI1FromR8(dateIn, pbOut);
701 }
702 
703 /************************************************************************
704  * VarUI1FromStr (OLEAUT32.136)
705  *
706  * Convert a VT_BSTR to a VT_UI1.
707  *
708  * PARAMS
709  * strIn [I] Source
710  * lcid [I] LCID for the conversion
711  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
712  * pbOut [O] Destination
713  *
714  * RETURNS
715  * Success: S_OK.
716  * Failure: E_INVALIDARG, if the source value is invalid
717  * DISP_E_OVERFLOW, if the value will not fit in the destination
718  * DISP_E_TYPEMISMATCH, if the type cannot be converted
719  */
721 {
722  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pbOut, VT_UI1);
723 }
724 
725 /************************************************************************
726  * VarUI1FromDisp (OLEAUT32.137)
727  *
728  * Convert a VT_DISPATCH to a VT_UI1.
729  *
730  * PARAMS
731  * pdispIn [I] Source
732  * lcid [I] LCID for conversion
733  * pbOut [O] Destination
734  *
735  * RETURNS
736  * Success: S_OK.
737  * Failure: E_INVALIDARG, if the source value is invalid
738  * DISP_E_OVERFLOW, if the value will not fit in the destination
739  * DISP_E_TYPEMISMATCH, if the type cannot be converted
740  */
742 {
743  return VARIANT_FromDisp(pdispIn, lcid, pbOut, VT_UI1, 0);
744 }
745 
746 /************************************************************************
747  * VarUI1FromBool (OLEAUT32.138)
748  *
749  * Convert a VT_BOOL to a VT_UI1.
750  *
751  * PARAMS
752  * boolIn [I] Source
753  * pbOut [O] Destination
754  *
755  * RETURNS
756  * S_OK.
757  */
759 {
760  return _VarUI1FromBool(boolIn, pbOut);
761 }
762 
763 /************************************************************************
764  * VarUI1FromI1 (OLEAUT32.237)
765  *
766  * Convert a VT_I1 to a VT_UI1.
767  *
768  * PARAMS
769  * cIn [I] Source
770  * pbOut [O] Destination
771  *
772  * RETURNS
773  * Success: S_OK.
774  * Failure: E_INVALIDARG, if the source value is invalid
775  * DISP_E_OVERFLOW, if the value will not fit in the destination
776  */
777 HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
778 {
779  return _VarUI1FromI1(cIn, pbOut);
780 }
781 
782 /************************************************************************
783  * VarUI1FromUI2 (OLEAUT32.238)
784  *
785  * Convert a VT_UI2 to a VT_UI1.
786  *
787  * PARAMS
788  * usIn [I] Source
789  * pbOut [O] Destination
790  *
791  * RETURNS
792  * Success: S_OK.
793  * Failure: E_INVALIDARG, if the source value is invalid
794  * DISP_E_OVERFLOW, if the value will not fit in the destination
795  */
797 {
798  return _VarUI1FromUI2(usIn, pbOut);
799 }
800 
801 /************************************************************************
802  * VarUI1FromUI4 (OLEAUT32.239)
803  *
804  * Convert a VT_UI4 to a VT_UI1.
805  *
806  * PARAMS
807  * ulIn [I] Source
808  * pbOut [O] Destination
809  *
810  * RETURNS
811  * Success: S_OK.
812  * Failure: E_INVALIDARG, if the source value is invalid
813  * DISP_E_OVERFLOW, if the value will not fit in the destination
814  */
816 {
817  return _VarUI1FromUI4(ulIn, pbOut);
818 }
819 
820 /************************************************************************
821  * VarUI1FromDec (OLEAUT32.240)
822  *
823  * Convert a VT_DECIMAL to a VT_UI1.
824  *
825  * PARAMS
826  * pDecIn [I] Source
827  * pbOut [O] Destination
828  *
829  * RETURNS
830  * Success: S_OK.
831  * Failure: E_INVALIDARG, if the source value is invalid
832  * DISP_E_OVERFLOW, if the value will not fit in the destination
833  */
835 {
836  LONG64 i64;
837  HRESULT hRet;
838 
839  hRet = VarI8FromDec(pdecIn, &i64);
840 
841  if (SUCCEEDED(hRet))
842  hRet = _VarUI1FromI8(i64, pbOut);
843  return hRet;
844 }
845 
846 /************************************************************************
847  * VarUI1FromI8 (OLEAUT32.372)
848  *
849  * Convert a VT_I8 to a VT_UI1.
850  *
851  * PARAMS
852  * llIn [I] Source
853  * pbOut [O] Destination
854  *
855  * RETURNS
856  * Success: S_OK.
857  * Failure: E_INVALIDARG, if the source value is invalid
858  * DISP_E_OVERFLOW, if the value will not fit in the destination
859  */
861 {
862  return _VarUI1FromI8(llIn, pbOut);
863 }
864 
865 /************************************************************************
866  * VarUI1FromUI8 (OLEAUT32.373)
867  *
868  * Convert a VT_UI8 to a VT_UI1.
869  *
870  * PARAMS
871  * ullIn [I] Source
872  * pbOut [O] Destination
873  *
874  * RETURNS
875  * Success: S_OK.
876  * Failure: E_INVALIDARG, if the source value is invalid
877  * DISP_E_OVERFLOW, if the value will not fit in the destination
878  */
880 {
881  return _VarUI1FromUI8(ullIn, pbOut);
882 }
883 
884 
885 /* I2
886  */
887 
888 /************************************************************************
889  * VarI2FromUI1 (OLEAUT32.48)
890  *
891  * Convert a VT_UI2 to a VT_I2.
892  *
893  * PARAMS
894  * bIn [I] Source
895  * psOut [O] Destination
896  *
897  * RETURNS
898  * S_OK.
899  */
901 {
902  return _VarI2FromUI1(bIn, psOut);
903 }
904 
905 /************************************************************************
906  * VarI2FromI4 (OLEAUT32.49)
907  *
908  * Convert a VT_I4 to a VT_I2.
909  *
910  * PARAMS
911  * iIn [I] Source
912  * psOut [O] Destination
913  *
914  * RETURNS
915  * Success: S_OK.
916  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
917  */
919 {
920  return _VarI2FromI4(iIn, psOut);
921 }
922 
923 /************************************************************************
924  * VarI2FromR4 (OLEAUT32.50)
925  *
926  * Convert a VT_R4 to a VT_I2.
927  *
928  * PARAMS
929  * fltIn [I] Source
930  * psOut [O] Destination
931  *
932  * RETURNS
933  * Success: S_OK.
934  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
935  */
937 {
938  return VarI2FromR8(fltIn, psOut);
939 }
940 
941 /************************************************************************
942  * VarI2FromR8 (OLEAUT32.51)
943  *
944  * Convert a VT_R8 to a VT_I2.
945  *
946  * PARAMS
947  * dblIn [I] Source
948  * psOut [O] Destination
949  *
950  * RETURNS
951  * Success: S_OK.
952  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
953  *
954  * NOTES
955  * See VarI8FromR8() for details concerning rounding.
956  */
957 HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
958 {
959  if (dblIn < I2_MIN - 0.5 || dblIn >= I2_MAX + 0.5)
960  return DISP_E_OVERFLOW;
961  VARIANT_DutchRound(SHORT, dblIn, *psOut);
962  return S_OK;
963 }
964 
965 /************************************************************************
966  * VarI2FromCy (OLEAUT32.52)
967  *
968  * Convert a VT_CY to a VT_I2.
969  *
970  * PARAMS
971  * cyIn [I] Source
972  * psOut [O] Destination
973  *
974  * RETURNS
975  * Success: S_OK.
976  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
977  */
979 {
980  LONG i = I2_MAX + 1;
981 
982  VarI4FromCy(cyIn, &i);
983  return _VarI2FromI4(i, psOut);
984 }
985 
986 /************************************************************************
987  * VarI2FromDate (OLEAUT32.53)
988  *
989  * Convert a VT_DATE to a VT_I2.
990  *
991  * PARAMS
992  * dateIn [I] Source
993  * psOut [O] Destination
994  *
995  * RETURNS
996  * Success: S_OK.
997  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
998  */
1000 {
1001  return VarI2FromR8(dateIn, psOut);
1002 }
1003 
1004 /************************************************************************
1005  * VarI2FromStr (OLEAUT32.54)
1006  *
1007  * Convert a VT_BSTR to a VT_I2.
1008  *
1009  * PARAMS
1010  * strIn [I] Source
1011  * lcid [I] LCID for the conversion
1012  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1013  * psOut [O] Destination
1014  *
1015  * RETURNS
1016  * Success: S_OK.
1017  * Failure: E_INVALIDARG, if any parameter is invalid
1018  * DISP_E_OVERFLOW, if the value will not fit in the destination
1019  * DISP_E_TYPEMISMATCH, if the type cannot be converted
1020  */
1022 {
1023  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, psOut, VT_I2);
1024 }
1025 
1026 /************************************************************************
1027  * VarI2FromDisp (OLEAUT32.55)
1028  *
1029  * Convert a VT_DISPATCH to a VT_I2.
1030  *
1031  * PARAMS
1032  * pdispIn [I] Source
1033  * lcid [I] LCID for conversion
1034  * psOut [O] Destination
1035  *
1036  * RETURNS
1037  * Success: S_OK.
1038  * Failure: E_INVALIDARG, if pdispIn is invalid,
1039  * DISP_E_OVERFLOW, if the value will not fit in the destination,
1040  * DISP_E_TYPEMISMATCH, if the type cannot be converted
1041  */
1043 {
1044  return VARIANT_FromDisp(pdispIn, lcid, psOut, VT_I2, 0);
1045 }
1046 
1047 /************************************************************************
1048  * VarI2FromBool (OLEAUT32.56)
1049  *
1050  * Convert a VT_BOOL to a VT_I2.
1051  *
1052  * PARAMS
1053  * boolIn [I] Source
1054  * psOut [O] Destination
1055  *
1056  * RETURNS
1057  * S_OK.
1058  */
1060 {
1061  return _VarI2FromBool(boolIn, psOut);
1062 }
1063 
1064 /************************************************************************
1065  * VarI2FromI1 (OLEAUT32.205)
1066  *
1067  * Convert a VT_I1 to a VT_I2.
1068  *
1069  * PARAMS
1070  * cIn [I] Source
1071  * psOut [O] Destination
1072  *
1073  * RETURNS
1074  * S_OK.
1075  */
1076 HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
1077 {
1078  return _VarI2FromI1(cIn, psOut);
1079 }
1080 
1081 /************************************************************************
1082  * VarI2FromUI2 (OLEAUT32.206)
1083  *
1084  * Convert a VT_UI2 to a VT_I2.
1085  *
1086  * PARAMS
1087  * usIn [I] Source
1088  * psOut [O] Destination
1089  *
1090  * RETURNS
1091  * Success: S_OK.
1092  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1093  */
1095 {
1096  return _VarI2FromUI2(usIn, psOut);
1097 }
1098 
1099 /************************************************************************
1100  * VarI2FromUI4 (OLEAUT32.207)
1101  *
1102  * Convert a VT_UI4 to a VT_I2.
1103  *
1104  * PARAMS
1105  * ulIn [I] Source
1106  * psOut [O] Destination
1107  *
1108  * RETURNS
1109  * Success: S_OK.
1110  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1111  */
1113 {
1114  return _VarI2FromUI4(ulIn, psOut);
1115 }
1116 
1117 /************************************************************************
1118  * VarI2FromDec (OLEAUT32.208)
1119  *
1120  * Convert a VT_DECIMAL to a VT_I2.
1121  *
1122  * PARAMS
1123  * pDecIn [I] Source
1124  * psOut [O] Destination
1125  *
1126  * RETURNS
1127  * Success: S_OK.
1128  * Failure: E_INVALIDARG, if the source value is invalid
1129  * DISP_E_OVERFLOW, if the value will not fit in the destination
1130  */
1132 {
1133  LONG64 i64;
1134  HRESULT hRet;
1135 
1136  hRet = VarI8FromDec(pdecIn, &i64);
1137 
1138  if (SUCCEEDED(hRet))
1139  hRet = _VarI2FromI8(i64, psOut);
1140  return hRet;
1141 }
1142 
1143 /************************************************************************
1144  * VarI2FromI8 (OLEAUT32.346)
1145  *
1146  * Convert a VT_I8 to a VT_I2.
1147  *
1148  * PARAMS
1149  * llIn [I] Source
1150  * psOut [O] Destination
1151  *
1152  * RETURNS
1153  * Success: S_OK.
1154  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1155  */
1157 {
1158  return _VarI2FromI8(llIn, psOut);
1159 }
1160 
1161 /************************************************************************
1162  * VarI2FromUI8 (OLEAUT32.347)
1163  *
1164  * Convert a VT_UI8 to a VT_I2.
1165  *
1166  * PARAMS
1167  * ullIn [I] Source
1168  * psOut [O] Destination
1169  *
1170  * RETURNS
1171  * Success: S_OK.
1172  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1173  */
1175 {
1176  return _VarI2FromUI8(ullIn, psOut);
1177 }
1178 
1179 /* UI2
1180  */
1181 
1182 /************************************************************************
1183  * VarUI2FromUI1 (OLEAUT32.257)
1184  *
1185  * Convert a VT_UI1 to a VT_UI2.
1186  *
1187  * PARAMS
1188  * bIn [I] Source
1189  * pusOut [O] Destination
1190  *
1191  * RETURNS
1192  * S_OK.
1193  */
1195 {
1196  return _VarUI2FromUI1(bIn, pusOut);
1197 }
1198 
1199 /************************************************************************
1200  * VarUI2FromI2 (OLEAUT32.258)
1201  *
1202  * Convert a VT_I2 to a VT_UI2.
1203  *
1204  * PARAMS
1205  * sIn [I] Source
1206  * pusOut [O] Destination
1207  *
1208  * RETURNS
1209  * Success: S_OK.
1210  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1211  */
1213 {
1214  return _VarUI2FromI2(sIn, pusOut);
1215 }
1216 
1217 /************************************************************************
1218  * VarUI2FromI4 (OLEAUT32.259)
1219  *
1220  * Convert a VT_I4 to a VT_UI2.
1221  *
1222  * PARAMS
1223  * iIn [I] Source
1224  * pusOut [O] Destination
1225  *
1226  * RETURNS
1227  * Success: S_OK.
1228  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1229  */
1231 {
1232  return _VarUI2FromI4(iIn, pusOut);
1233 }
1234 
1235 /************************************************************************
1236  * VarUI2FromR4 (OLEAUT32.260)
1237  *
1238  * Convert a VT_R4 to a VT_UI2.
1239  *
1240  * PARAMS
1241  * fltIn [I] Source
1242  * pusOut [O] Destination
1243  *
1244  * RETURNS
1245  * Success: S_OK.
1246  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1247  */
1249 {
1250  return VarUI2FromR8(fltIn, pusOut);
1251 }
1252 
1253 /************************************************************************
1254  * VarUI2FromR8 (OLEAUT32.261)
1255  *
1256  * Convert a VT_R8 to a VT_UI2.
1257  *
1258  * PARAMS
1259  * dblIn [I] Source
1260  * pusOut [O] Destination
1261  *
1262  * RETURNS
1263  * Success: S_OK.
1264  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1265  *
1266  * NOTES
1267  * See VarI8FromR8() for details concerning rounding.
1268  */
1269 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
1270 {
1271  if (dblIn < -0.5 || dblIn >= UI2_MAX + 0.5)
1272  return DISP_E_OVERFLOW;
1273  VARIANT_DutchRound(USHORT, dblIn, *pusOut);
1274  return S_OK;
1275 }
1276 
1277 /************************************************************************
1278  * VarUI2FromDate (OLEAUT32.262)
1279  *
1280  * Convert a VT_DATE to a VT_UI2.
1281  *
1282  * PARAMS
1283  * dateIn [I] Source
1284  * pusOut [O] Destination
1285  *
1286  * RETURNS
1287  * Success: S_OK.
1288  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1289  */
1291 {
1292  return VarUI2FromR8(dateIn, pusOut);
1293 }
1294 
1295 /************************************************************************
1296  * VarUI2FromCy (OLEAUT32.263)
1297  *
1298  * Convert a VT_CY to a VT_UI2.
1299  *
1300  * PARAMS
1301  * cyIn [I] Source
1302  * pusOut [O] Destination
1303  *
1304  * RETURNS
1305  * Success: S_OK.
1306  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1307  *
1308  * NOTES
1309  * Negative values >= -5000 will be converted to 0.
1310  */
1312 {
1313  ULONG i = UI2_MAX + 1;
1314 
1315  VarUI4FromCy(cyIn, &i);
1316  return _VarUI2FromUI4(i, pusOut);
1317 }
1318 
1319 /************************************************************************
1320  * VarUI2FromStr (OLEAUT32.264)
1321  *
1322  * Convert a VT_BSTR to a VT_UI2.
1323  *
1324  * PARAMS
1325  * strIn [I] Source
1326  * lcid [I] LCID for the conversion
1327  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1328  * pusOut [O] Destination
1329  *
1330  * RETURNS
1331  * Success: S_OK.
1332  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1333  * DISP_E_TYPEMISMATCH, if the type cannot be converted
1334  */
1336 {
1337  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pusOut, VT_UI2);
1338 }
1339 
1340 /************************************************************************
1341  * VarUI2FromDisp (OLEAUT32.265)
1342  *
1343  * Convert a VT_DISPATCH to a VT_UI2.
1344  *
1345  * PARAMS
1346  * pdispIn [I] Source
1347  * lcid [I] LCID for conversion
1348  * pusOut [O] Destination
1349  *
1350  * RETURNS
1351  * Success: S_OK.
1352  * Failure: E_INVALIDARG, if the source value is invalid
1353  * DISP_E_OVERFLOW, if the value will not fit in the destination
1354  * DISP_E_TYPEMISMATCH, if the type cannot be converted
1355  */
1357 {
1358  return VARIANT_FromDisp(pdispIn, lcid, pusOut, VT_UI2, 0);
1359 }
1360 
1361 /************************************************************************
1362  * VarUI2FromBool (OLEAUT32.266)
1363  *
1364  * Convert a VT_BOOL to a VT_UI2.
1365  *
1366  * PARAMS
1367  * boolIn [I] Source
1368  * pusOut [O] Destination
1369  *
1370  * RETURNS
1371  * S_OK.
1372  */
1374 {
1375  return _VarUI2FromBool(boolIn, pusOut);
1376 }
1377 
1378 /************************************************************************
1379  * VarUI2FromI1 (OLEAUT32.267)
1380  *
1381  * Convert a VT_I1 to a VT_UI2.
1382  *
1383  * PARAMS
1384  * cIn [I] Source
1385  * pusOut [O] Destination
1386  *
1387  * RETURNS
1388  * Success: S_OK.
1389  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1390  */
1391 HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
1392 {
1393  return _VarUI2FromI1(cIn, pusOut);
1394 }
1395 
1396 /************************************************************************
1397  * VarUI2FromUI4 (OLEAUT32.268)
1398  *
1399  * Convert a VT_UI4 to a VT_UI2.
1400  *
1401  * PARAMS
1402  * ulIn [I] Source
1403  * pusOut [O] Destination
1404  *
1405  * RETURNS
1406  * Success: S_OK.
1407  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1408  */
1410 {
1411  return _VarUI2FromUI4(ulIn, pusOut);
1412 }
1413 
1414 /************************************************************************
1415  * VarUI2FromDec (OLEAUT32.269)
1416  *
1417  * Convert a VT_DECIMAL to a VT_UI2.
1418  *
1419  * PARAMS
1420  * pDecIn [I] Source
1421  * pusOut [O] Destination
1422  *
1423  * RETURNS
1424  * Success: S_OK.
1425  * Failure: E_INVALIDARG, if the source value is invalid
1426  * DISP_E_OVERFLOW, if the value will not fit in the destination
1427  */
1429 {
1430  LONG64 i64;
1431  HRESULT hRet;
1432 
1433  hRet = VarI8FromDec(pdecIn, &i64);
1434 
1435  if (SUCCEEDED(hRet))
1436  hRet = _VarUI2FromI8(i64, pusOut);
1437  return hRet;
1438 }
1439 
1440 /************************************************************************
1441  * VarUI2FromI8 (OLEAUT32.378)
1442  *
1443  * Convert a VT_I8 to a VT_UI2.
1444  *
1445  * PARAMS
1446  * llIn [I] Source
1447  * pusOut [O] Destination
1448  *
1449  * RETURNS
1450  * Success: S_OK.
1451  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1452  */
1454 {
1455  return _VarUI2FromI8(llIn, pusOut);
1456 }
1457 
1458 /************************************************************************
1459  * VarUI2FromUI8 (OLEAUT32.379)
1460  *
1461  * Convert a VT_UI8 to a VT_UI2.
1462  *
1463  * PARAMS
1464  * ullIn [I] Source
1465  * pusOut [O] Destination
1466  *
1467  * RETURNS
1468  * Success: S_OK.
1469  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1470  */
1472 {
1473  return _VarUI2FromUI8(ullIn, pusOut);
1474 }
1475 
1476 /* I4
1477  */
1478 
1479 /************************************************************************
1480  * VarI4FromUI1 (OLEAUT32.58)
1481  *
1482  * Convert a VT_UI1 to a VT_I4.
1483  *
1484  * PARAMS
1485  * bIn [I] Source
1486  * piOut [O] Destination
1487  *
1488  * RETURNS
1489  * S_OK.
1490  */
1492 {
1493  return _VarI4FromUI1(bIn, piOut);
1494 }
1495 
1496 /************************************************************************
1497  * VarI4FromI2 (OLEAUT32.59)
1498  *
1499  * Convert a VT_I2 to a VT_I4.
1500  *
1501  * PARAMS
1502  * sIn [I] Source
1503  * piOut [O] Destination
1504  *
1505  * RETURNS
1506  * Success: S_OK.
1507  * Failure: E_INVALIDARG, if the source value is invalid
1508  * DISP_E_OVERFLOW, if the value will not fit in the destination
1509  */
1511 {
1512  return _VarI4FromI2(sIn, piOut);
1513 }
1514 
1515 /************************************************************************
1516  * VarI4FromR4 (OLEAUT32.60)
1517  *
1518  * Convert a VT_R4 to a VT_I4.
1519  *
1520  * PARAMS
1521  * fltIn [I] Source
1522  * piOut [O] Destination
1523  *
1524  * RETURNS
1525  * Success: S_OK.
1526  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1527  */
1529 {
1530  return VarI4FromR8(fltIn, piOut);
1531 }
1532 
1533 /************************************************************************
1534  * VarI4FromR8 (OLEAUT32.61)
1535  *
1536  * Convert a VT_R8 to a VT_I4.
1537  *
1538  * PARAMS
1539  * dblIn [I] Source
1540  * piOut [O] Destination
1541  *
1542  * RETURNS
1543  * Success: S_OK.
1544  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1545  *
1546  * NOTES
1547  * See VarI8FromR8() for details concerning rounding.
1548  */
1549 HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
1550 {
1551  if (dblIn < I4_MIN - 0.5 || dblIn >= I4_MAX + 0.5)
1552  return DISP_E_OVERFLOW;
1553  VARIANT_DutchRound(LONG, dblIn, *piOut);
1554  return S_OK;
1555 }
1556 
1557 /************************************************************************
1558  * VarI4FromCy (OLEAUT32.62)
1559  *
1560  * Convert a VT_CY to a VT_I4.
1561  *
1562  * PARAMS
1563  * cyIn [I] Source
1564  * piOut [O] Destination
1565  *
1566  * RETURNS
1567  * Success: S_OK.
1568  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1569  */
1571 {
1572  double d = cyIn.int64 / CY_MULTIPLIER_F;
1573  return VarI4FromR8(d, piOut);
1574 }
1575 
1576 /************************************************************************
1577  * VarI4FromDate (OLEAUT32.63)
1578  *
1579  * Convert a VT_DATE to a VT_I4.
1580  *
1581  * PARAMS
1582  * dateIn [I] Source
1583  * piOut [O] Destination
1584  *
1585  * RETURNS
1586  * Success: S_OK.
1587  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1588  */
1590 {
1591  return VarI4FromR8(dateIn, piOut);
1592 }
1593 
1594 /************************************************************************
1595  * VarI4FromStr (OLEAUT32.64)
1596  *
1597  * Convert a VT_BSTR to a VT_I4.
1598  *
1599  * PARAMS
1600  * strIn [I] Source
1601  * lcid [I] LCID for the conversion
1602  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1603  * piOut [O] Destination
1604  *
1605  * RETURNS
1606  * Success: S_OK.
1607  * Failure: E_INVALIDARG, if any parameter is invalid
1608  * DISP_E_OVERFLOW, if the value will not fit in the destination
1609  * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1610  */
1612 {
1613  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, piOut, VT_I4);
1614 }
1615 
1616 /************************************************************************
1617  * VarI4FromDisp (OLEAUT32.65)
1618  *
1619  * Convert a VT_DISPATCH to a VT_I4.
1620  *
1621  * PARAMS
1622  * pdispIn [I] Source
1623  * lcid [I] LCID for conversion
1624  * piOut [O] Destination
1625  *
1626  * RETURNS
1627  * Success: S_OK.
1628  * Failure: E_INVALIDARG, if the source value is invalid
1629  * DISP_E_OVERFLOW, if the value will not fit in the destination
1630  * DISP_E_TYPEMISMATCH, if the type cannot be converted
1631  */
1633 {
1634  return VARIANT_FromDisp(pdispIn, lcid, piOut, VT_I4, 0);
1635 }
1636 
1637 /************************************************************************
1638  * VarI4FromBool (OLEAUT32.66)
1639  *
1640  * Convert a VT_BOOL to a VT_I4.
1641  *
1642  * PARAMS
1643  * boolIn [I] Source
1644  * piOut [O] Destination
1645  *
1646  * RETURNS
1647  * S_OK.
1648  */
1650 {
1651  return _VarI4FromBool(boolIn, piOut);
1652 }
1653 
1654 /************************************************************************
1655  * VarI4FromI1 (OLEAUT32.209)
1656  *
1657  * Convert a VT_I1 to a VT_I4.
1658  *
1659  * PARAMS
1660  * cIn [I] Source
1661  * piOut [O] Destination
1662  *
1663  * RETURNS
1664  * S_OK.
1665  */
1666 HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
1667 {
1668  return _VarI4FromI1(cIn, piOut);
1669 }
1670 
1671 /************************************************************************
1672  * VarI4FromUI2 (OLEAUT32.210)
1673  *
1674  * Convert a VT_UI2 to a VT_I4.
1675  *
1676  * PARAMS
1677  * usIn [I] Source
1678  * piOut [O] Destination
1679  *
1680  * RETURNS
1681  * S_OK.
1682  */
1684 {
1685  return _VarI4FromUI2(usIn, piOut);
1686 }
1687 
1688 /************************************************************************
1689  * VarI4FromUI4 (OLEAUT32.211)
1690  *
1691  * Convert a VT_UI4 to a VT_I4.
1692  *
1693  * PARAMS
1694  * ulIn [I] Source
1695  * piOut [O] Destination
1696  *
1697  * RETURNS
1698  * Success: S_OK.
1699  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1700  */
1702 {
1703  return _VarI4FromUI4(ulIn, piOut);
1704 }
1705 
1706 /************************************************************************
1707  * VarI4FromDec (OLEAUT32.212)
1708  *
1709  * Convert a VT_DECIMAL to a VT_I4.
1710  *
1711  * PARAMS
1712  * pDecIn [I] Source
1713  * piOut [O] Destination
1714  *
1715  * RETURNS
1716  * Success: S_OK.
1717  * Failure: E_INVALIDARG, if pdecIn is invalid
1718  * DISP_E_OVERFLOW, if the value will not fit in the destination
1719  */
1721 {
1722  LONG64 i64;
1723  HRESULT hRet;
1724 
1725  hRet = VarI8FromDec(pdecIn, &i64);
1726 
1727  if (SUCCEEDED(hRet))
1728  hRet = _VarI4FromI8(i64, piOut);
1729  return hRet;
1730 }
1731 
1732 /************************************************************************
1733  * VarI4FromI8 (OLEAUT32.348)
1734  *
1735  * Convert a VT_I8 to a VT_I4.
1736  *
1737  * PARAMS
1738  * llIn [I] Source
1739  * piOut [O] Destination
1740  *
1741  * RETURNS
1742  * Success: S_OK.
1743  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1744  */
1746 {
1747  return _VarI4FromI8(llIn, piOut);
1748 }
1749 
1750 /************************************************************************
1751  * VarI4FromUI8 (OLEAUT32.349)
1752  *
1753  * Convert a VT_UI8 to a VT_I4.
1754  *
1755  * PARAMS
1756  * ullIn [I] Source
1757  * piOut [O] Destination
1758  *
1759  * RETURNS
1760  * Success: S_OK.
1761  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1762  */
1764 {
1765  return _VarI4FromUI8(ullIn, piOut);
1766 }
1767 
1768 /* UI4
1769  */
1770 
1771 /************************************************************************
1772  * VarUI4FromUI1 (OLEAUT32.270)
1773  *
1774  * Convert a VT_UI1 to a VT_UI4.
1775  *
1776  * PARAMS
1777  * bIn [I] Source
1778  * pulOut [O] Destination
1779  *
1780  * RETURNS
1781  * S_OK.
1782  */
1784 {
1785  return _VarUI4FromUI1(bIn, pulOut);
1786 }
1787 
1788 /************************************************************************
1789  * VarUI4FromI2 (OLEAUT32.271)
1790  *
1791  * Convert a VT_I2 to a VT_UI4.
1792  *
1793  * PARAMS
1794  * sIn [I] Source
1795  * pulOut [O] Destination
1796  *
1797  * RETURNS
1798  * Success: S_OK.
1799  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1800  */
1802 {
1803  return _VarUI4FromI2(sIn, pulOut);
1804 }
1805 
1806 /************************************************************************
1807  * VarUI4FromI4 (OLEAUT32.272)
1808  *
1809  * Convert a VT_I4 to a VT_UI4.
1810  *
1811  * PARAMS
1812  * iIn [I] Source
1813  * pulOut [O] Destination
1814  *
1815  * RETURNS
1816  * Success: S_OK.
1817  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1818  */
1820 {
1821  return _VarUI4FromI4(iIn, pulOut);
1822 }
1823 
1824 /************************************************************************
1825  * VarUI4FromR4 (OLEAUT32.273)
1826  *
1827  * Convert a VT_R4 to a VT_UI4.
1828  *
1829  * PARAMS
1830  * fltIn [I] Source
1831  * pulOut [O] Destination
1832  *
1833  * RETURNS
1834  * Success: S_OK.
1835  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1836  */
1838 {
1839  return VarUI4FromR8(fltIn, pulOut);
1840 }
1841 
1842 /************************************************************************
1843  * VarUI4FromR8 (OLEAUT32.274)
1844  *
1845  * Convert a VT_R8 to a VT_UI4.
1846  *
1847  * PARAMS
1848  * dblIn [I] Source
1849  * pulOut [O] Destination
1850  *
1851  * RETURNS
1852  * Success: S_OK.
1853  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1854  *
1855  * NOTES
1856  * See VarI8FromR8() for details concerning rounding.
1857  */
1858 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
1859 {
1860  if (dblIn < -0.5 || dblIn >= UI4_MAX + 0.5)
1861  return DISP_E_OVERFLOW;
1862  VARIANT_DutchRound(ULONG, dblIn, *pulOut);
1863  return S_OK;
1864 }
1865 
1866 /************************************************************************
1867  * VarUI4FromDate (OLEAUT32.275)
1868  *
1869  * Convert a VT_DATE to a VT_UI4.
1870  *
1871  * PARAMS
1872  * dateIn [I] Source
1873  * pulOut [O] Destination
1874  *
1875  * RETURNS
1876  * Success: S_OK.
1877  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1878  */
1880 {
1881  return VarUI4FromR8(dateIn, pulOut);
1882 }
1883 
1884 /************************************************************************
1885  * VarUI4FromCy (OLEAUT32.276)
1886  *
1887  * Convert a VT_CY to a VT_UI4.
1888  *
1889  * PARAMS
1890  * cyIn [I] Source
1891  * pulOut [O] Destination
1892  *
1893  * RETURNS
1894  * Success: S_OK.
1895  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1896  */
1898 {
1899  double d = cyIn.int64 / CY_MULTIPLIER_F;
1900  return VarUI4FromR8(d, pulOut);
1901 }
1902 
1903 /************************************************************************
1904  * VarUI4FromStr (OLEAUT32.277)
1905  *
1906  * Convert a VT_BSTR to a VT_UI4.
1907  *
1908  * PARAMS
1909  * strIn [I] Source
1910  * lcid [I] LCID for the conversion
1911  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1912  * pulOut [O] Destination
1913  *
1914  * RETURNS
1915  * Success: S_OK.
1916  * Failure: E_INVALIDARG, if any parameter is invalid
1917  * DISP_E_OVERFLOW, if the value will not fit in the destination
1918  * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1919  */
1921 {
1922  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pulOut, VT_UI4);
1923 }
1924 
1925 /************************************************************************
1926  * VarUI4FromDisp (OLEAUT32.278)
1927  *
1928  * Convert a VT_DISPATCH to a VT_UI4.
1929  *
1930  * PARAMS
1931  * pdispIn [I] Source
1932  * lcid [I] LCID for conversion
1933  * pulOut [O] Destination
1934  *
1935  * RETURNS
1936  * Success: S_OK.
1937  * Failure: E_INVALIDARG, if the source value is invalid
1938  * DISP_E_OVERFLOW, if the value will not fit in the destination
1939  * DISP_E_TYPEMISMATCH, if the type cannot be converted
1940  */
1942 {
1943  return VARIANT_FromDisp(pdispIn, lcid, pulOut, VT_UI4, 0);
1944 }
1945 
1946 /************************************************************************
1947  * VarUI4FromBool (OLEAUT32.279)
1948  *
1949  * Convert a VT_BOOL to a VT_UI4.
1950  *
1951  * PARAMS
1952  * boolIn [I] Source
1953  * pulOut [O] Destination
1954  *
1955  * RETURNS
1956  * S_OK.
1957  */
1959 {
1960  return _VarUI4FromBool(boolIn, pulOut);
1961 }
1962 
1963 /************************************************************************
1964  * VarUI4FromI1 (OLEAUT32.280)
1965  *
1966  * Convert a VT_I1 to a VT_UI4.
1967  *
1968  * PARAMS
1969  * cIn [I] Source
1970  * pulOut [O] Destination
1971  *
1972  * RETURNS
1973  * Success: S_OK.
1974  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1975  */
1976 HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
1977 {
1978  return _VarUI4FromI1(cIn, pulOut);
1979 }
1980 
1981 /************************************************************************
1982  * VarUI4FromUI2 (OLEAUT32.281)
1983  *
1984  * Convert a VT_UI2 to a VT_UI4.
1985  *
1986  * PARAMS
1987  * usIn [I] Source
1988  * pulOut [O] Destination
1989  *
1990  * RETURNS
1991  * S_OK.
1992  */
1994 {
1995  return _VarUI4FromUI2(usIn, pulOut);
1996 }
1997 
1998 /************************************************************************
1999  * VarUI4FromDec (OLEAUT32.282)
2000  *
2001  * Convert a VT_DECIMAL to a VT_UI4.
2002  *
2003  * PARAMS
2004  * pDecIn [I] Source
2005  * pulOut [O] Destination
2006  *
2007  * RETURNS
2008  * Success: S_OK.
2009  * Failure: E_INVALIDARG, if pdecIn is invalid
2010  * DISP_E_OVERFLOW, if the value will not fit in the destination
2011  */
2013 {
2014  LONG64 i64;
2015  HRESULT hRet;
2016 
2017  hRet = VarI8FromDec(pdecIn, &i64);
2018 
2019  if (SUCCEEDED(hRet))
2020  hRet = _VarUI4FromI8(i64, pulOut);
2021  return hRet;
2022 }
2023 
2024 /************************************************************************
2025  * VarUI4FromI8 (OLEAUT32.425)
2026  *
2027  * Convert a VT_I8 to a VT_UI4.
2028  *
2029  * PARAMS
2030  * llIn [I] Source
2031  * pulOut [O] Destination
2032  *
2033  * RETURNS
2034  * Success: S_OK.
2035  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2036  */
2038 {
2039  return _VarUI4FromI8(llIn, pulOut);
2040 }
2041 
2042 /************************************************************************
2043  * VarUI4FromUI8 (OLEAUT32.426)
2044  *
2045  * Convert a VT_UI8 to a VT_UI4.
2046  *
2047  * PARAMS
2048  * ullIn [I] Source
2049  * pulOut [O] Destination
2050  *
2051  * RETURNS
2052  * Success: S_OK.
2053  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2054  */
2056 {
2057  return _VarUI4FromUI8(ullIn, pulOut);
2058 }
2059 
2060 /* I8
2061  */
2062 
2063 /************************************************************************
2064  * VarI8FromUI1 (OLEAUT32.333)
2065  *
2066  * Convert a VT_UI1 to a VT_I8.
2067  *
2068  * PARAMS
2069  * bIn [I] Source
2070  * pi64Out [O] Destination
2071  *
2072  * RETURNS
2073  * S_OK.
2074  */
2076 {
2077  return _VarI8FromUI1(bIn, pi64Out);
2078 }
2079 
2080 
2081 /************************************************************************
2082  * VarI8FromI2 (OLEAUT32.334)
2083  *
2084  * Convert a VT_I2 to a VT_I8.
2085  *
2086  * PARAMS
2087  * sIn [I] Source
2088  * pi64Out [O] Destination
2089  *
2090  * RETURNS
2091  * S_OK.
2092  */
2094 {
2095  return _VarI8FromI2(sIn, pi64Out);
2096 }
2097 
2098 /************************************************************************
2099  * VarI8FromR4 (OLEAUT32.335)
2100  *
2101  * Convert a VT_R4 to a VT_I8.
2102  *
2103  * PARAMS
2104  * fltIn [I] Source
2105  * pi64Out [O] Destination
2106  *
2107  * RETURNS
2108  * Success: S_OK.
2109  * Failure: E_INVALIDARG, if the source value is invalid
2110  * DISP_E_OVERFLOW, if the value will not fit in the destination
2111  */
2113 {
2114  return VarI8FromR8(fltIn, pi64Out);
2115 }
2116 
2117 /************************************************************************
2118  * VarI8FromR8 (OLEAUT32.336)
2119  *
2120  * Convert a VT_R8 to a VT_I8.
2121  *
2122  * PARAMS
2123  * dblIn [I] Source
2124  * pi64Out [O] Destination
2125  *
2126  * RETURNS
2127  * Success: S_OK.
2128  * Failure: E_INVALIDARG, if the source value is invalid
2129  * DISP_E_OVERFLOW, if the value will not fit in the destination
2130  *
2131  * NOTES
2132  * Only values that fit into 63 bits are accepted. Due to rounding issues,
2133  * very high or low values will not be accurately converted.
2134  *
2135  * Numbers are rounded using Dutch rounding, as follows:
2136  *
2137  *| Fractional Part Sign Direction Example
2138  *| --------------- ---- --------- -------
2139  *| < 0.5 + Down 0.4 -> 0.0
2140  *| < 0.5 - Up -0.4 -> 0.0
2141  *| > 0.5 + Up 0.6 -> 1.0
2142  *| < 0.5 - Up -0.6 -> -1.0
2143  *| = 0.5 + Up/Down Down if even, Up if odd
2144  *| = 0.5 - Up/Down Up if even, Down if odd
2145  *
2146  * This system is often used in supermarkets.
2147  */
2148 HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
2149 {
2150  if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
2151  return DISP_E_OVERFLOW;
2152  VARIANT_DutchRound(LONG64, dblIn, *pi64Out);
2153  return S_OK;
2154 }
2155 
2156 /************************************************************************
2157  * VarI8FromCy (OLEAUT32.337)
2158  *
2159  * Convert a VT_CY to a VT_I8.
2160  *
2161  * PARAMS
2162  * cyIn [I] Source
2163  * pi64Out [O] Destination
2164  *
2165  * RETURNS
2166  * S_OK.
2167  *
2168  * NOTES
2169  * All negative numbers are rounded down by 1, including those that are
2170  * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2171  * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2172  * for details.
2173  */
2175 {
2176  *pi64Out = cyIn.int64 / CY_MULTIPLIER;
2177 
2178  if (cyIn.int64 < 0)
2179  (*pi64Out)--; /* Mimic Win32 bug */
2180  else
2181  {
2182  cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2183 
2184  if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
2185  (*pi64Out)++;
2186  }
2187  return S_OK;
2188 }
2189 
2190 /************************************************************************
2191  * VarI8FromDate (OLEAUT32.338)
2192  *
2193  * Convert a VT_DATE to a VT_I8.
2194  *
2195  * PARAMS
2196  * dateIn [I] Source
2197  * pi64Out [O] Destination
2198  *
2199  * RETURNS
2200  * Success: S_OK.
2201  * Failure: E_INVALIDARG, if the source value is invalid
2202  * DISP_E_OVERFLOW, if the value will not fit in the destination
2203  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2204  */
2206 {
2207  return VarI8FromR8(dateIn, pi64Out);
2208 }
2209 
2210 /************************************************************************
2211  * VarI8FromStr (OLEAUT32.339)
2212  *
2213  * Convert a VT_BSTR to a VT_I8.
2214  *
2215  * PARAMS
2216  * strIn [I] Source
2217  * lcid [I] LCID for the conversion
2218  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2219  * pi64Out [O] Destination
2220  *
2221  * RETURNS
2222  * Success: S_OK.
2223  * Failure: E_INVALIDARG, if the source value is invalid
2224  * DISP_E_OVERFLOW, if the value will not fit in the destination
2225  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2226  */
2228 {
2229  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pi64Out, VT_I8);
2230 }
2231 
2232 /************************************************************************
2233  * VarI8FromDisp (OLEAUT32.340)
2234  *
2235  * Convert a VT_DISPATCH to a VT_I8.
2236  *
2237  * PARAMS
2238  * pdispIn [I] Source
2239  * lcid [I] LCID for conversion
2240  * pi64Out [O] Destination
2241  *
2242  * RETURNS
2243  * Success: S_OK.
2244  * Failure: E_INVALIDARG, if the source value is invalid
2245  * DISP_E_OVERFLOW, if the value will not fit in the destination
2246  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2247  */
2249 {
2250  return VARIANT_FromDisp(pdispIn, lcid, pi64Out, VT_I8, 0);
2251 }
2252 
2253 /************************************************************************
2254  * VarI8FromBool (OLEAUT32.341)
2255  *
2256  * Convert a VT_BOOL to a VT_I8.
2257  *
2258  * PARAMS
2259  * boolIn [I] Source
2260  * pi64Out [O] Destination
2261  *
2262  * RETURNS
2263  * S_OK.
2264  */
2266 {
2267  return VarI8FromI2(boolIn, pi64Out);
2268 }
2269 
2270 /************************************************************************
2271  * VarI8FromI1 (OLEAUT32.342)
2272  *
2273  * Convert a VT_I1 to a VT_I8.
2274  *
2275  * PARAMS
2276  * cIn [I] Source
2277  * pi64Out [O] Destination
2278  *
2279  * RETURNS
2280  * S_OK.
2281  */
2282 HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
2283 {
2284  return _VarI8FromI1(cIn, pi64Out);
2285 }
2286 
2287 /************************************************************************
2288  * VarI8FromUI2 (OLEAUT32.343)
2289  *
2290  * Convert a VT_UI2 to a VT_I8.
2291  *
2292  * PARAMS
2293  * usIn [I] Source
2294  * pi64Out [O] Destination
2295  *
2296  * RETURNS
2297  * S_OK.
2298  */
2300 {
2301  return _VarI8FromUI2(usIn, pi64Out);
2302 }
2303 
2304 /************************************************************************
2305  * VarI8FromUI4 (OLEAUT32.344)
2306  *
2307  * Convert a VT_UI4 to a VT_I8.
2308  *
2309  * PARAMS
2310  * ulIn [I] Source
2311  * pi64Out [O] Destination
2312  *
2313  * RETURNS
2314  * S_OK.
2315  */
2317 {
2318  return _VarI8FromUI4(ulIn, pi64Out);
2319 }
2320 
2321 /************************************************************************
2322  * VarI8FromDec (OLEAUT32.345)
2323  *
2324  * Convert a VT_DECIMAL to a VT_I8.
2325  *
2326  * PARAMS
2327  * pDecIn [I] Source
2328  * pi64Out [O] Destination
2329  *
2330  * RETURNS
2331  * Success: S_OK.
2332  * Failure: E_INVALIDARG, if the source value is invalid
2333  * DISP_E_OVERFLOW, if the value will not fit in the destination
2334  */
2336 {
2337  if (!DEC_SCALE(pdecIn))
2338  {
2339  /* This decimal is just a 96 bit integer */
2340  if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2341  return E_INVALIDARG;
2342 
2343  if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
2344  return DISP_E_OVERFLOW;
2345 
2346  if (DEC_SIGN(pdecIn))
2347  *pi64Out = -DEC_LO64(pdecIn);
2348  else
2349  *pi64Out = DEC_LO64(pdecIn);
2350  return S_OK;
2351  }
2352  else
2353  {
2354  /* Decimal contains a floating point number */
2355  HRESULT hRet;
2356  double dbl;
2357 
2358  hRet = VarR8FromDec(pdecIn, &dbl);
2359  if (SUCCEEDED(hRet))
2360  hRet = VarI8FromR8(dbl, pi64Out);
2361  return hRet;
2362  }
2363 }
2364 
2365 /************************************************************************
2366  * VarI8FromUI8 (OLEAUT32.427)
2367  *
2368  * Convert a VT_UI8 to a VT_I8.
2369  *
2370  * PARAMS
2371  * ullIn [I] Source
2372  * pi64Out [O] Destination
2373  *
2374  * RETURNS
2375  * Success: S_OK.
2376  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2377  */
2379 {
2380  return _VarI8FromUI8(ullIn, pi64Out);
2381 }
2382 
2383 /* UI8
2384  */
2385 
2386 /************************************************************************
2387  * VarUI8FromI8 (OLEAUT32.428)
2388  *
2389  * Convert a VT_I8 to a VT_UI8.
2390  *
2391  * PARAMS
2392  * ulIn [I] Source
2393  * pui64Out [O] Destination
2394  *
2395  * RETURNS
2396  * Success: S_OK.
2397  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2398  */
2400 {
2401  return _VarUI8FromI8(llIn, pui64Out);
2402 }
2403 
2404 /************************************************************************
2405  * VarUI8FromUI1 (OLEAUT32.429)
2406  *
2407  * Convert a VT_UI1 to a VT_UI8.
2408  *
2409  * PARAMS
2410  * bIn [I] Source
2411  * pui64Out [O] Destination
2412  *
2413  * RETURNS
2414  * S_OK.
2415  */
2417 {
2418  return _VarUI8FromUI1(bIn, pui64Out);
2419 }
2420 
2421 /************************************************************************
2422  * VarUI8FromI2 (OLEAUT32.430)
2423  *
2424  * Convert a VT_I2 to a VT_UI8.
2425  *
2426  * PARAMS
2427  * sIn [I] Source
2428  * pui64Out [O] Destination
2429  *
2430  * RETURNS
2431  * S_OK.
2432  */
2434 {
2435  return _VarUI8FromI2(sIn, pui64Out);
2436 }
2437 
2438 /************************************************************************
2439  * VarUI8FromR4 (OLEAUT32.431)
2440  *
2441  * Convert a VT_R4 to a VT_UI8.
2442  *
2443  * PARAMS
2444  * fltIn [I] Source
2445  * pui64Out [O] Destination
2446  *
2447  * RETURNS
2448  * Success: S_OK.
2449  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2450  */
2452 {
2453  return VarUI8FromR8(fltIn, pui64Out);
2454 }
2455 
2456 /************************************************************************
2457  * VarUI8FromR8 (OLEAUT32.432)
2458  *
2459  * Convert a VT_R8 to a VT_UI8.
2460  *
2461  * PARAMS
2462  * dblIn [I] Source
2463  * pui64Out [O] Destination
2464  *
2465  * RETURNS
2466  * Success: S_OK.
2467  * Failure: E_INVALIDARG, if the source value is invalid
2468  * DISP_E_OVERFLOW, if the value will not fit in the destination
2469  *
2470  * NOTES
2471  * See VarI8FromR8() for details concerning rounding.
2472  */
2473 HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
2474 {
2475  if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
2476  return DISP_E_OVERFLOW;
2477  VARIANT_DutchRound(ULONG64, dblIn, *pui64Out);
2478  return S_OK;
2479 }
2480 
2481 /************************************************************************
2482  * VarUI8FromCy (OLEAUT32.433)
2483  *
2484  * Convert a VT_CY to a VT_UI8.
2485  *
2486  * PARAMS
2487  * cyIn [I] Source
2488  * pui64Out [O] Destination
2489  *
2490  * RETURNS
2491  * Success: S_OK.
2492  * Failure: E_INVALIDARG, if the source value is invalid
2493  * DISP_E_OVERFLOW, if the value will not fit in the destination
2494  *
2495  * NOTES
2496  * Negative values >= -5000 will be converted to 0.
2497  */
2499 {
2500  if (cyIn.int64 < 0)
2501  {
2502  if (cyIn.int64 < -CY_HALF)
2503  return DISP_E_OVERFLOW;
2504  *pui64Out = 0;
2505  }
2506  else
2507  {
2508  *pui64Out = cyIn.int64 / CY_MULTIPLIER;
2509 
2510  cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2511 
2512  if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
2513  (*pui64Out)++;
2514  }
2515  return S_OK;
2516 }
2517 
2518 /************************************************************************
2519  * VarUI8FromDate (OLEAUT32.434)
2520  *
2521  * Convert a VT_DATE to a VT_UI8.
2522  *
2523  * PARAMS
2524  * dateIn [I] Source
2525  * pui64Out [O] Destination
2526  *
2527  * RETURNS
2528  * Success: S_OK.
2529  * Failure: E_INVALIDARG, if the source value is invalid
2530  * DISP_E_OVERFLOW, if the value will not fit in the destination
2531  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2532  */
2534 {
2535  return VarUI8FromR8(dateIn, pui64Out);
2536 }
2537 
2538 /************************************************************************
2539  * VarUI8FromStr (OLEAUT32.435)
2540  *
2541  * Convert a VT_BSTR to a VT_UI8.
2542  *
2543  * PARAMS
2544  * strIn [I] Source
2545  * lcid [I] LCID for the conversion
2546  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2547  * pui64Out [O] Destination
2548  *
2549  * RETURNS
2550  * Success: S_OK.
2551  * Failure: E_INVALIDARG, if the source value is invalid
2552  * DISP_E_OVERFLOW, if the value will not fit in the destination
2553  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2554  */
2556 {
2557  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pui64Out, VT_UI8);
2558 }
2559 
2560 /************************************************************************
2561  * VarUI8FromDisp (OLEAUT32.436)
2562  *
2563  * Convert a VT_DISPATCH to a VT_UI8.
2564  *
2565  * PARAMS
2566  * pdispIn [I] Source
2567  * lcid [I] LCID for conversion
2568  * pui64Out [O] Destination
2569  *
2570  * RETURNS
2571  * Success: S_OK.
2572  * Failure: E_INVALIDARG, if the source value is invalid
2573  * DISP_E_OVERFLOW, if the value will not fit in the destination
2574  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2575  */
2577 {
2578  return VARIANT_FromDisp(pdispIn, lcid, pui64Out, VT_UI8, 0);
2579 }
2580 
2581 /************************************************************************
2582  * VarUI8FromBool (OLEAUT32.437)
2583  *
2584  * Convert a VT_BOOL to a VT_UI8.
2585  *
2586  * PARAMS
2587  * boolIn [I] Source
2588  * pui64Out [O] Destination
2589  *
2590  * RETURNS
2591  * Success: S_OK.
2592  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2593  */
2595 {
2596  return VarI8FromI2(boolIn, (LONG64 *)pui64Out);
2597 }
2598 /************************************************************************
2599  * VarUI8FromI1 (OLEAUT32.438)
2600  *
2601  * Convert a VT_I1 to a VT_UI8.
2602  *
2603  * PARAMS
2604  * cIn [I] Source
2605  * pui64Out [O] Destination
2606  *
2607  * RETURNS
2608  * Success: S_OK.
2609  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2610  */
2611 HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
2612 {
2613  return _VarUI8FromI1(cIn, pui64Out);
2614 }
2615 
2616 /************************************************************************
2617  * VarUI8FromUI2 (OLEAUT32.439)
2618  *
2619  * Convert a VT_UI2 to a VT_UI8.
2620  *
2621  * PARAMS
2622  * usIn [I] Source
2623  * pui64Out [O] Destination
2624  *
2625  * RETURNS
2626  * S_OK.
2627  */
2629 {
2630  return _VarUI8FromUI2(usIn, pui64Out);
2631 }
2632 
2633 /************************************************************************
2634  * VarUI8FromUI4 (OLEAUT32.440)
2635  *
2636  * Convert a VT_UI4 to a VT_UI8.
2637  *
2638  * PARAMS
2639  * ulIn [I] Source
2640  * pui64Out [O] Destination
2641  *
2642  * RETURNS
2643  * S_OK.
2644  */
2646 {
2647  return _VarUI8FromUI4(ulIn, pui64Out);
2648 }
2649 
2650 /************************************************************************
2651  * VarUI8FromDec (OLEAUT32.441)
2652  *
2653  * Convert a VT_DECIMAL to a VT_UI8.
2654  *
2655  * PARAMS
2656  * pDecIn [I] Source
2657  * pui64Out [O] Destination
2658  *
2659  * RETURNS
2660  * Success: S_OK.
2661  * Failure: E_INVALIDARG, if the source value is invalid
2662  * DISP_E_OVERFLOW, if the value will not fit in the destination
2663  *
2664  * NOTES
2665  * Under native Win32, if the source value has a scale of 0, its sign is
2666  * ignored, i.e. this function takes the absolute value rather than fail
2667  * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2668  * (use VarAbs() on pDecIn first if you really want this behaviour).
2669  */
2671 {
2672  if (!DEC_SCALE(pdecIn))
2673  {
2674  /* This decimal is just a 96 bit integer */
2675  if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2676  return E_INVALIDARG;
2677 
2678  if (DEC_HI32(pdecIn))
2679  return DISP_E_OVERFLOW;
2680 
2681  if (DEC_SIGN(pdecIn))
2682  {
2683  WARN("Sign would be ignored under Win32!\n");
2684  return DISP_E_OVERFLOW;
2685  }
2686 
2687  *pui64Out = DEC_LO64(pdecIn);
2688  return S_OK;
2689  }
2690  else
2691  {
2692  /* Decimal contains a floating point number */
2693  HRESULT hRet;
2694  double dbl;
2695 
2696  hRet = VarR8FromDec(pdecIn, &dbl);
2697  if (SUCCEEDED(hRet))
2698  hRet = VarUI8FromR8(dbl, pui64Out);
2699  return hRet;
2700  }
2701 }
2702 
2703 /* R4
2704  */
2705 
2706 /************************************************************************
2707  * VarR4FromUI1 (OLEAUT32.68)
2708  *
2709  * Convert a VT_UI1 to a VT_R4.
2710  *
2711  * PARAMS
2712  * bIn [I] Source
2713  * pFltOut [O] Destination
2714  *
2715  * RETURNS
2716  * S_OK.
2717  */
2718 HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
2719 {
2720  return _VarR4FromUI1(bIn, pFltOut);
2721 }
2722 
2723 /************************************************************************
2724  * VarR4FromI2 (OLEAUT32.69)
2725  *
2726  * Convert a VT_I2 to a VT_R4.
2727  *
2728  * PARAMS
2729  * sIn [I] Source
2730  * pFltOut [O] Destination
2731  *
2732  * RETURNS
2733  * S_OK.
2734  */
2735 HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
2736 {
2737  return _VarR4FromI2(sIn, pFltOut);
2738 }
2739 
2740 /************************************************************************
2741  * VarR4FromI4 (OLEAUT32.70)
2742  *
2743  * Convert a VT_I4 to a VT_R4.
2744  *
2745  * PARAMS
2746  * sIn [I] Source
2747  * pFltOut [O] Destination
2748  *
2749  * RETURNS
2750  * S_OK.
2751  */
2752 HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
2753 {
2754  return _VarR4FromI4(lIn, pFltOut);
2755 }
2756 
2757 /************************************************************************
2758  * VarR4FromR8 (OLEAUT32.71)
2759  *
2760  * Convert a VT_R8 to a VT_R4.
2761  *
2762  * PARAMS
2763  * dblIn [I] Source
2764  * pFltOut [O] Destination
2765  *
2766  * RETURNS
2767  * Success: S_OK.
2768  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2769  */
2770 HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
2771 {
2772  double d = dblIn < 0.0 ? -dblIn : dblIn;
2773  if (d > R4_MAX) return DISP_E_OVERFLOW;
2774  *pFltOut = dblIn;
2775  return S_OK;
2776 }
2777 
2778 /************************************************************************
2779  * VarR4FromCy (OLEAUT32.72)
2780  *
2781  * Convert a VT_CY to a VT_R4.
2782  *
2783  * PARAMS
2784  * cyIn [I] Source
2785  * pFltOut [O] Destination
2786  *
2787  * RETURNS
2788  * S_OK.
2789  */
2790 HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
2791 {
2792  *pFltOut = (double)cyIn.int64 / CY_MULTIPLIER_F;
2793  return S_OK;
2794 }
2795 
2796 /************************************************************************
2797  * VarR4FromDate (OLEAUT32.73)
2798  *
2799  * Convert a VT_DATE to a VT_R4.
2800  *
2801  * PARAMS
2802  * dateIn [I] Source
2803  * pFltOut [O] Destination
2804  *
2805  * RETURNS
2806  * Success: S_OK.
2807  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2808  */
2809 HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
2810 {
2811  return VarR4FromR8(dateIn, pFltOut);
2812 }
2813 
2814 /************************************************************************
2815  * VarR4FromStr (OLEAUT32.74)
2816  *
2817  * Convert a VT_BSTR to a VT_R4.
2818  *
2819  * PARAMS
2820  * strIn [I] Source
2821  * lcid [I] LCID for the conversion
2822  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2823  * pFltOut [O] Destination
2824  *
2825  * RETURNS
2826  * Success: S_OK.
2827  * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2828  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2829  */
2830 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
2831 {
2832  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pFltOut, VT_R4);
2833 }
2834 
2835 /************************************************************************
2836  * VarR4FromDisp (OLEAUT32.75)
2837  *
2838  * Convert a VT_DISPATCH to a VT_R4.
2839  *
2840  * PARAMS
2841  * pdispIn [I] Source
2842  * lcid [I] LCID for conversion
2843  * pFltOut [O] Destination
2844  *
2845  * RETURNS
2846  * Success: S_OK.
2847  * Failure: E_INVALIDARG, if the source value is invalid
2848  * DISP_E_OVERFLOW, if the value will not fit in the destination
2849  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2850  */
2851 HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
2852 {
2853  return VARIANT_FromDisp(pdispIn, lcid, pFltOut, VT_R4, 0);
2854 }
2855 
2856 /************************************************************************
2857  * VarR4FromBool (OLEAUT32.76)
2858  *
2859  * Convert a VT_BOOL to a VT_R4.
2860  *
2861  * PARAMS
2862  * boolIn [I] Source
2863  * pFltOut [O] Destination
2864  *
2865  * RETURNS
2866  * S_OK.
2867  */
2868 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
2869 {
2870  return VarR4FromI2(boolIn, pFltOut);
2871 }
2872 
2873 /************************************************************************
2874  * VarR4FromI1 (OLEAUT32.213)
2875  *
2876  * Convert a VT_I1 to a VT_R4.
2877  *
2878  * PARAMS
2879  * cIn [I] Source
2880  * pFltOut [O] Destination
2881  *
2882  * RETURNS
2883  * Success: S_OK.
2884  * Failure: E_INVALIDARG, if the source value is invalid
2885  * DISP_E_OVERFLOW, if the value will not fit in the destination
2886  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2887  */
2888 HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
2889 {
2890  return _VarR4FromI1(cIn, pFltOut);
2891 }
2892 
2893 /************************************************************************
2894  * VarR4FromUI2 (OLEAUT32.214)
2895  *
2896  * Convert a VT_UI2 to a VT_R4.
2897  *
2898  * PARAMS
2899  * usIn [I] Source
2900  * pFltOut [O] Destination
2901  *
2902  * RETURNS
2903  * Success: S_OK.
2904  * Failure: E_INVALIDARG, if the source value is invalid
2905  * DISP_E_OVERFLOW, if the value will not fit in the destination
2906  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2907  */
2908 HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
2909 {
2910  return _VarR4FromUI2(usIn, pFltOut);
2911 }
2912 
2913 /************************************************************************
2914  * VarR4FromUI4 (OLEAUT32.215)
2915  *
2916  * Convert a VT_UI4 to a VT_R4.
2917  *
2918  * PARAMS
2919  * ulIn [I] Source
2920  * pFltOut [O] Destination
2921  *
2922  * RETURNS
2923  * Success: S_OK.
2924  * Failure: E_INVALIDARG, if the source value is invalid
2925  * DISP_E_OVERFLOW, if the value will not fit in the destination
2926  * DISP_E_TYPEMISMATCH, if the type cannot be converted
2927  */
2928 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
2929 {
2930  return _VarR4FromUI4(ulIn, pFltOut);
2931 }
2932 
2933 /************************************************************************
2934  * VarR4FromDec (OLEAUT32.216)
2935  *
2936  * Convert a VT_DECIMAL to a VT_R4.
2937  *
2938  * PARAMS
2939  * pDecIn [I] Source
2940  * pFltOut [O] Destination
2941  *
2942  * RETURNS
2943  * Success: S_OK.
2944  * Failure: E_INVALIDARG, if the source value is invalid.
2945  */
2946 HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
2947 {
2948  BYTE scale = DEC_SCALE(pDecIn);
2949  double divisor = 1.0;
2950  double highPart;
2951 
2952  if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
2953  return E_INVALIDARG;
2954 
2955  while (scale--)
2956  divisor *= 10.0;
2957 
2958  if (DEC_SIGN(pDecIn))
2959  divisor = -divisor;
2960 
2961  if (DEC_HI32(pDecIn))
2962  {
2963  highPart = (double)DEC_HI32(pDecIn) / divisor;
2964  highPart *= 4294967296.0F;
2965  highPart *= 4294967296.0F;
2966  }
2967  else
2968  highPart = 0.0;
2969 
2970  *pFltOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
2971  return S_OK;
2972 }
2973 
2974 /************************************************************************
2975  * VarR4FromI8 (OLEAUT32.360)
2976  *
2977  * Convert a VT_I8 to a VT_R4.
2978  *
2979  * PARAMS
2980  * ullIn [I] Source
2981  * pFltOut [O] Destination
2982  *
2983  * RETURNS
2984  * S_OK.
2985  */
2986 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2987 {
2988  return _VarR4FromI8(llIn, pFltOut);
2989 }
2990 
2991 /************************************************************************
2992  * VarR4FromUI8 (OLEAUT32.361)
2993  *
2994  * Convert a VT_UI8 to a VT_R4.
2995  *
2996  * PARAMS
2997  * ullIn [I] Source
2998  * pFltOut [O] Destination
2999  *
3000  * RETURNS
3001  * S_OK.
3002  */
3003 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
3004 {
3005  return _VarR4FromUI8(ullIn, pFltOut);
3006 }
3007 
3008 /************************************************************************
3009  * VarR4CmpR8 (OLEAUT32.316)
3010  *
3011  * Compare a VT_R4 to a VT_R8.
3012  *
3013  * PARAMS
3014  * fltLeft [I] Source
3015  * dblRight [I] Value to compare
3016  *
3017  * RETURNS
3018  * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
3019  * equal to or greater than dblRight respectively.
3020  */
3021 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
3022 {
3023  if (fltLeft < dblRight)
3024  return VARCMP_LT;
3025  else if (fltLeft > dblRight)
3026  return VARCMP_GT;
3027  return VARCMP_EQ;
3028 }
3029 
3030 /* R8
3031  */
3032 
3033 /************************************************************************
3034  * VarR8FromUI1 (OLEAUT32.78)
3035  *
3036  * Convert a VT_UI1 to a VT_R8.
3037  *
3038  * PARAMS
3039  * bIn [I] Source
3040  * pDblOut [O] Destination
3041  *
3042  * RETURNS
3043  * S_OK.
3044  */
3045 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
3046 {
3047  return _VarR8FromUI1(bIn, pDblOut);
3048 }
3049 
3050 /************************************************************************
3051  * VarR8FromI2 (OLEAUT32.79)
3052  *
3053  * Convert a VT_I2 to a VT_R8.
3054  *
3055  * PARAMS
3056  * sIn [I] Source
3057  * pDblOut [O] Destination
3058  *
3059  * RETURNS
3060  * S_OK.
3061  */
3062 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
3063 {
3064  return _VarR8FromI2(sIn, pDblOut);
3065 }
3066 
3067 /************************************************************************
3068  * VarR8FromI4 (OLEAUT32.80)
3069  *
3070  * Convert a VT_I4 to a VT_R8.
3071  *
3072  * PARAMS
3073  * sIn [I] Source
3074  * pDblOut [O] Destination
3075  *
3076  * RETURNS
3077  * S_OK.
3078  */
3079 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
3080 {
3081  return _VarR8FromI4(lIn, pDblOut);
3082 }
3083 
3084 /************************************************************************
3085  * VarR8FromR4 (OLEAUT32.81)
3086  *
3087  * Convert a VT_R4 to a VT_R8.
3088  *
3089  * PARAMS
3090  * fltIn [I] Source
3091  * pDblOut [O] Destination
3092  *
3093  * RETURNS
3094  * S_OK.
3095  */
3096 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
3097 {
3098  return _VarR8FromR4(fltIn, pDblOut);
3099 }
3100 
3101 /************************************************************************
3102  * VarR8FromCy (OLEAUT32.82)
3103  *
3104  * Convert a VT_CY to a VT_R8.
3105  *
3106  * PARAMS
3107  * cyIn [I] Source
3108  * pDblOut [O] Destination
3109  *
3110  * RETURNS
3111  * S_OK.
3112  */
3113 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
3114 {
3115  return _VarR8FromCy(cyIn, pDblOut);
3116 }
3117 
3118 /************************************************************************
3119  * VarR8FromDate (OLEAUT32.83)
3120  *
3121  * Convert a VT_DATE to a VT_R8.
3122  *
3123  * PARAMS
3124  * dateIn [I] Source
3125  * pDblOut [O] Destination
3126  *
3127  * RETURNS
3128  * S_OK.
3129  */
3130 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
3131 {
3132  return _VarR8FromDate(dateIn, pDblOut);
3133 }
3134 
3135 /************************************************************************
3136  * VarR8FromStr (OLEAUT32.84)
3137  *
3138  * Convert a VT_BSTR to a VT_R8.
3139  *
3140  * PARAMS
3141  * strIn [I] Source
3142  * lcid [I] LCID for the conversion
3143  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3144  * pDblOut [O] Destination
3145  *
3146  * RETURNS
3147  * Success: S_OK.
3148  * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3149  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3150  */
3151 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3152 {
3153  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDblOut, VT_R8);
3154 }
3155 
3156 /************************************************************************
3157  * VarR8FromDisp (OLEAUT32.85)
3158  *
3159  * Convert a VT_DISPATCH to a VT_R8.
3160  *
3161  * PARAMS
3162  * pdispIn [I] Source
3163  * lcid [I] LCID for conversion
3164  * pDblOut [O] Destination
3165  *
3166  * RETURNS
3167  * Success: S_OK.
3168  * Failure: E_INVALIDARG, if the source value is invalid
3169  * DISP_E_OVERFLOW, if the value will not fit in the destination
3170  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3171  */
3172 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3173 {
3174  return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8, 0);
3175 }
3176 
3177 /************************************************************************
3178  * VarR8FromBool (OLEAUT32.86)
3179  *
3180  * Convert a VT_BOOL to a VT_R8.
3181  *
3182  * PARAMS
3183  * boolIn [I] Source
3184  * pDblOut [O] Destination
3185  *
3186  * RETURNS
3187  * S_OK.
3188  */
3189 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
3190 {
3191  return VarR8FromI2(boolIn, pDblOut);
3192 }
3193 
3194 /************************************************************************
3195  * VarR8FromI1 (OLEAUT32.217)
3196  *
3197  * Convert a VT_I1 to a VT_R8.
3198  *
3199  * PARAMS
3200  * cIn [I] Source
3201  * pDblOut [O] Destination
3202  *
3203  * RETURNS
3204  * Success: S_OK.
3205  * Failure: E_INVALIDARG, if the source value is invalid
3206  * DISP_E_OVERFLOW, if the value will not fit in the destination
3207  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3208  */
3209 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3210 {
3211  return _VarR8FromI1(cIn, pDblOut);
3212 }
3213 
3214 /************************************************************************
3215  * VarR8FromUI2 (OLEAUT32.218)
3216  *
3217  * Convert a VT_UI2 to a VT_R8.
3218  *
3219  * PARAMS
3220  * usIn [I] Source
3221  * pDblOut [O] Destination
3222  *
3223  * RETURNS
3224  * Success: S_OK.
3225  * Failure: E_INVALIDARG, if the source value is invalid
3226  * DISP_E_OVERFLOW, if the value will not fit in the destination
3227  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3228  */
3229 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3230 {
3231  return _VarR8FromUI2(usIn, pDblOut);
3232 }
3233 
3234 /************************************************************************
3235  * VarR8FromUI4 (OLEAUT32.219)
3236  *
3237  * Convert a VT_UI4 to a VT_R8.
3238  *
3239  * PARAMS
3240  * ulIn [I] Source
3241  * pDblOut [O] Destination
3242  *
3243  * RETURNS
3244  * Success: S_OK.
3245  * Failure: E_INVALIDARG, if the source value is invalid
3246  * DISP_E_OVERFLOW, if the value will not fit in the destination
3247  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3248  */
3249 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3250 {
3251  return _VarR8FromUI4(ulIn, pDblOut);
3252 }
3253 
3254 /************************************************************************
3255  * VarR8FromDec (OLEAUT32.220)
3256  *
3257  * Convert a VT_DECIMAL to a VT_R8.
3258  *
3259  * PARAMS
3260  * pDecIn [I] Source
3261  * pDblOut [O] Destination
3262  *
3263  * RETURNS
3264  * Success: S_OK.
3265  * Failure: E_INVALIDARG, if the source value is invalid.
3266  */
3267 HRESULT WINAPI VarR8FromDec(const DECIMAL* pDecIn, double *pDblOut)
3268 {
3269  BYTE scale = DEC_SCALE(pDecIn);
3270  double divisor = 1.0, highPart;
3271 
3272  if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
3273  return E_INVALIDARG;
3274 
3275  while (scale--)
3276  divisor *= 10;
3277 
3278  if (DEC_SIGN(pDecIn))
3279  divisor = -divisor;
3280 
3281  if (DEC_HI32(pDecIn))
3282  {
3283  highPart = (double)DEC_HI32(pDecIn) / divisor;
3284  highPart *= 4294967296.0F;
3285  highPart *= 4294967296.0F;
3286  }
3287  else
3288  highPart = 0.0;
3289 
3290  *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
3291  return S_OK;
3292 }
3293 
3294 /************************************************************************
3295  * VarR8FromI8 (OLEAUT32.362)
3296  *
3297  * Convert a VT_I8 to a VT_R8.
3298  *
3299  * PARAMS
3300  * ullIn [I] Source
3301  * pDblOut [O] Destination
3302  *
3303  * RETURNS
3304  * S_OK.
3305  */
3306 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3307 {
3308  return _VarR8FromI8(llIn, pDblOut);
3309 }
3310 
3311 /************************************************************************
3312  * VarR8FromUI8 (OLEAUT32.363)
3313  *
3314  * Convert a VT_UI8 to a VT_R8.
3315  *
3316  * PARAMS
3317  * ullIn [I] Source
3318  * pDblOut [O] Destination
3319  *
3320  * RETURNS
3321  * S_OK.
3322  */
3323 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3324 {
3325  return _VarR8FromUI8(ullIn, pDblOut);
3326 }
3327 
3328 /************************************************************************
3329  * VarR8Pow (OLEAUT32.315)
3330  *
3331  * Raise a VT_R8 to a power.
3332  *
3333  * PARAMS
3334  * dblLeft [I] Source
3335  * dblPow [I] Power to raise dblLeft by
3336  * pDblOut [O] Destination
3337  *
3338  * RETURNS
3339  * S_OK. pDblOut contains dblLeft to the power of dblRight.
3340  */
3341 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3342 {
3343  *pDblOut = pow(dblLeft, dblPow);
3344  return S_OK;
3345 }
3346 
3347 /************************************************************************
3348  * VarR8Round (OLEAUT32.317)
3349  *
3350  * Round a VT_R8 to a given number of decimal points.
3351  *
3352  * PARAMS
3353  * dblIn [I] Source
3354  * nDig [I] Number of decimal points to round to
3355  * pDblOut [O] Destination for rounded number
3356  *
3357  * RETURNS
3358  * Success: S_OK. pDblOut is rounded to nDig digits.
3359  * Failure: E_INVALIDARG, if cDecimals is less than 0.
3360  *
3361  * NOTES
3362  * The native version of this function rounds using the internal
3363  * binary representation of the number. Wine uses the dutch rounding
3364  * convention, so therefore small differences can occur in the value returned.
3365  * MSDN says that you should use your own rounding function if you want
3366  * rounding to be predictable in your application.
3367  */
3368 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3369 {
3370  double scale, whole, fract;
3371 
3372  if (nDig < 0)
3373  return E_INVALIDARG;
3374 
3375  scale = pow(10.0, nDig);
3376 
3377  dblIn *= scale;
3378  whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3379  fract = dblIn - whole;
3380 
3381  if (fract > 0.5)
3382  dblIn = whole + 1.0;
3383  else if (fract == 0.5)
3384  dblIn = whole + fmod(whole, 2.0);
3385  else if (fract >= 0.0)
3386  dblIn = whole;
3387  else if (fract == -0.5)
3388  dblIn = whole - fmod(whole, 2.0);
3389  else if (fract > -0.5)
3390  dblIn = whole;
3391  else
3392  dblIn = whole - 1.0;
3393 
3394  *pDblOut = dblIn / scale;
3395  return S_OK;
3396 }
3397 
3398 /* CY
3399  */
3400 
3401 /* Powers of 10 from 0..4 D.P. */
3402 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3404 
3405 /************************************************************************
3406  * VarCyFromUI1 (OLEAUT32.98)
3407  *
3408  * Convert a VT_UI1 to a VT_CY.
3409  *
3410  * PARAMS
3411  * bIn [I] Source
3412  * pCyOut [O] Destination
3413  *
3414  * RETURNS
3415  * Success: S_OK.
3416  * Failure: E_INVALIDARG, if the source value is invalid
3417  * DISP_E_OVERFLOW, if the value will not fit in the destination
3418  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3419  */
3421 {
3422  pCyOut->int64 = (ULONG64)bIn * CY_MULTIPLIER;
3423  return S_OK;
3424 }
3425 
3426 /************************************************************************
3427  * VarCyFromI2 (OLEAUT32.99)
3428  *
3429  * Convert a VT_I2 to a VT_CY.
3430  *
3431  * PARAMS
3432  * sIn [I] Source
3433  * pCyOut [O] Destination
3434  *
3435  * RETURNS
3436  * Success: S_OK.
3437  * Failure: E_INVALIDARG, if the source value is invalid
3438  * DISP_E_OVERFLOW, if the value will not fit in the destination
3439  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3440  */
3442 {
3443  pCyOut->int64 = (LONG64)sIn * CY_MULTIPLIER;
3444  return S_OK;
3445 }
3446 
3447 /************************************************************************
3448  * VarCyFromI4 (OLEAUT32.100)
3449  *
3450  * Convert a VT_I4 to a VT_CY.
3451  *
3452  * PARAMS
3453  * sIn [I] Source
3454  * pCyOut [O] Destination
3455  *
3456  * RETURNS
3457  * Success: S_OK.
3458  * Failure: E_INVALIDARG, if the source value is invalid
3459  * DISP_E_OVERFLOW, if the value will not fit in the destination
3460  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3461  */
3463 {
3464  pCyOut->int64 = (LONG64)lIn * CY_MULTIPLIER;
3465  return S_OK;
3466 }
3467 
3468 /************************************************************************
3469  * VarCyFromR4 (OLEAUT32.101)
3470  *
3471  * Convert a VT_R4 to a VT_CY.
3472  *
3473  * PARAMS
3474  * fltIn [I] Source
3475  * pCyOut [O] Destination
3476  *
3477  * RETURNS
3478  * Success: S_OK.
3479  * Failure: E_INVALIDARG, if the source value is invalid
3480  * DISP_E_OVERFLOW, if the value will not fit in the destination
3481  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3482  */
3484 {
3485  return VarCyFromR8(fltIn, pCyOut);
3486 }
3487 
3488 /************************************************************************
3489  * VarCyFromR8 (OLEAUT32.102)
3490  *
3491  * Convert a VT_R8 to a VT_CY.
3492  *
3493  * PARAMS
3494  * dblIn [I] Source
3495  * pCyOut [O] Destination
3496  *
3497  * RETURNS
3498  * Success: S_OK.
3499  * Failure: E_INVALIDARG, if the source value is invalid
3500  * DISP_E_OVERFLOW, if the value will not fit in the destination
3501  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3502  */
3503 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3504 {
3505 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3506  /* This code gives identical results to Win32 on Intel.
3507  * Here we use fp exceptions to catch overflows when storing the value.
3508  */
3509  static const unsigned short r8_fpcontrol = 0x137f;
3510  static const double r8_multiplier = CY_MULTIPLIER_F;
3511  unsigned short old_fpcontrol, result_fpstatus;
3512 
3513  /* Clear exceptions, save the old fp state and load the new state */
3514  __asm__ __volatile__( "fnclex" );
3515  __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
3516  __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
3517  /* Perform the conversion. */
3518  __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
3519  __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
3520  __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
3521  /* Save the resulting fp state, load the old state and clear exceptions */
3522  __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
3523  __asm__ __volatile__( "fnclex" );
3524  __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
3525 
3526  if (result_fpstatus & 0x9) /* Overflow | Invalid */
3527  return DISP_E_OVERFLOW;
3528 #else
3529  /* This version produces slightly different results for boundary cases */
3530  if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3531  return DISP_E_OVERFLOW;
3532  dblIn *= CY_MULTIPLIER_F;
3533  VARIANT_DutchRound(LONG64, dblIn, pCyOut->int64);
3534 #endif
3535  return S_OK;
3536 }
3537 
3538 /************************************************************************
3539  * VarCyFromDate (OLEAUT32.103)
3540  *
3541  * Convert a VT_DATE to a VT_CY.
3542  *
3543  * PARAMS
3544  * dateIn [I] Source
3545  * pCyOut [O] Destination
3546  *
3547  * RETURNS
3548  * Success: S_OK.
3549  * Failure: E_INVALIDARG, if the source value is invalid
3550  * DISP_E_OVERFLOW, if the value will not fit in the destination
3551  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3552  */
3554 {
3555  return VarCyFromR8(dateIn, pCyOut);
3556 }
3557 
3558 /************************************************************************
3559  * VarCyFromStr (OLEAUT32.104)
3560  *
3561  * Convert a VT_BSTR to a VT_CY.
3562  *
3563  * PARAMS
3564  * strIn [I] Source
3565  * lcid [I] LCID for the conversion
3566  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3567  * pCyOut [O] Destination
3568  *
3569  * RETURNS
3570  * Success: S_OK.
3571  * Failure: E_INVALIDARG, if the source value is invalid
3572  * DISP_E_OVERFLOW, if the value will not fit in the destination
3573  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3574  */
3576 {
3577  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pCyOut, VT_CY);
3578 }
3579 
3580 /************************************************************************
3581  * VarCyFromDisp (OLEAUT32.105)
3582  *
3583  * Convert a VT_DISPATCH to a VT_CY.
3584  *
3585  * PARAMS
3586  * pdispIn [I] Source
3587  * lcid [I] LCID for conversion
3588  * pCyOut [O] Destination
3589  *
3590  * RETURNS
3591  * Success: S_OK.
3592  * Failure: E_INVALIDARG, if the source value is invalid
3593  * DISP_E_OVERFLOW, if the value will not fit in the destination
3594  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3595  */
3596 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
3597 {
3598  return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY, 0);
3599 }
3600 
3601 /************************************************************************
3602  * VarCyFromBool (OLEAUT32.106)
3603  *
3604  * Convert a VT_BOOL to a VT_CY.
3605  *
3606  * PARAMS
3607  * boolIn [I] Source
3608  * pCyOut [O] Destination
3609  *
3610  * RETURNS
3611  * Success: S_OK.
3612  * Failure: E_INVALIDARG, if the source value is invalid
3613  * DISP_E_OVERFLOW, if the value will not fit in the destination
3614  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3615  *
3616  * NOTES
3617  * While the sign of the boolean is stored in the currency, the value is
3618  * converted to either 0 or 1.
3619  */
3621 {
3622  pCyOut->int64 = (LONG64)boolIn * CY_MULTIPLIER;
3623  return S_OK;
3624 }
3625 
3626 /************************************************************************
3627  * VarCyFromI1 (OLEAUT32.225)
3628  *
3629  * Convert a VT_I1 to a VT_CY.
3630  *
3631  * PARAMS
3632  * cIn [I] Source
3633  * pCyOut [O] Destination
3634  *
3635  * RETURNS
3636  * Success: S_OK.
3637  * Failure: E_INVALIDARG, if the source value is invalid
3638  * DISP_E_OVERFLOW, if the value will not fit in the destination
3639  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3640  */
3641 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3642 {
3643  pCyOut->int64 = (LONG64)cIn * CY_MULTIPLIER;
3644  return S_OK;
3645 }
3646 
3647 /************************************************************************
3648  * VarCyFromUI2 (OLEAUT32.226)
3649  *
3650  * Convert a VT_UI2 to a VT_CY.
3651  *
3652  * PARAMS
3653  * usIn [I] Source
3654  * pCyOut [O] Destination
3655  *
3656  * RETURNS
3657  * Success: S_OK.
3658  * Failure: E_INVALIDARG, if the source value is invalid
3659  * DISP_E_OVERFLOW, if the value will not fit in the destination
3660  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3661  */
3663 {
3664  pCyOut->int64 = (ULONG64)usIn * CY_MULTIPLIER;
3665  return S_OK;
3666 }
3667 
3668 /************************************************************************
3669  * VarCyFromUI4 (OLEAUT32.227)
3670  *
3671  * Convert a VT_UI4 to a VT_CY.
3672  *
3673  * PARAMS
3674  * ulIn [I] Source
3675  * pCyOut [O] Destination
3676  *
3677  * RETURNS
3678  * Success: S_OK.
3679  * Failure: E_INVALIDARG, if the source value is invalid
3680  * DISP_E_OVERFLOW, if the value will not fit in the destination
3681  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3682  */
3684 {
3685  pCyOut->int64 = (ULONG64)ulIn * CY_MULTIPLIER;
3686  return S_OK;
3687 }
3688 
3689 /************************************************************************
3690  * VarCyFromDec (OLEAUT32.228)
3691  *
3692  * Convert a VT_DECIMAL to a VT_CY.
3693  *
3694  * PARAMS
3695  * pdecIn [I] Source
3696  * pCyOut [O] Destination
3697  *
3698  * RETURNS
3699  * Success: S_OK.
3700  * Failure: E_INVALIDARG, if the source value is invalid
3701  * DISP_E_OVERFLOW, if the value will not fit in the destination
3702  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3703  */
3705 {
3706  DECIMAL rounded;
3707  HRESULT hRet;
3708 
3709  hRet = VarDecRound(pdecIn, 4, &rounded);
3710 
3711  if (SUCCEEDED(hRet))
3712  {
3713  double d;
3714 
3715  if (DEC_HI32(&rounded))
3716  return DISP_E_OVERFLOW;
3717 
3718  /* Note: Without the casts this promotes to int64 which loses precision */
3719  d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
3720  if (DEC_SIGN(&rounded))
3721  d = -d;
3722  return VarCyFromR8(d, pCyOut);
3723  }
3724  return hRet;
3725 }
3726 
3727 /************************************************************************
3728  * VarCyFromI8 (OLEAUT32.366)
3729  *
3730  * Convert a VT_I8 to a VT_CY.
3731  *
3732  * PARAMS
3733  * ullIn [I] Source
3734  * pCyOut [O] Destination
3735  *
3736  * RETURNS
3737  * Success: S_OK.
3738  * Failure: E_INVALIDARG, if the source value is invalid
3739  * DISP_E_OVERFLOW, if the value will not fit in the destination
3740  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3741  */
3743 {
3744  if (llIn <= (I8_MIN/CY_MULTIPLIER) || llIn >= (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
3745  pCyOut->int64 = llIn * CY_MULTIPLIER;
3746  return S_OK;
3747 }
3748 
3749 /************************************************************************
3750  * VarCyFromUI8 (OLEAUT32.375)
3751  *
3752  * Convert a VT_UI8 to a VT_CY.
3753  *
3754  * PARAMS
3755  * ullIn [I] Source
3756  * pCyOut [O] Destination
3757  *
3758  * RETURNS
3759  * Success: S_OK.
3760  * Failure: E_INVALIDARG, if the source value is invalid
3761  * DISP_E_OVERFLOW, if the value will not fit in the destination
3762  * DISP_E_TYPEMISMATCH, if the type cannot be converted
3763  */
3765 {
3766  if (ullIn > (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
3767  pCyOut->int64 = ullIn * CY_MULTIPLIER;
3768  return S_OK;
3769 }
3770 
3771 /************************************************************************
3772  * VarCyAdd (OLEAUT32.299)
3773  *
3774  * Add one CY to another.
3775  *
3776  * PARAMS
3777  * cyLeft [I] Source
3778  * cyRight [I] Value to add
3779  * pCyOut [O] Destination
3780  *
3781  * RETURNS
3782  * Success: S_OK.
3783  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3784  */
3785 HRESULT WINAPI VarCyAdd(CY cyLeft, CY cyRight, CY* pCyOut)
3786 {
3787  double l,r;
3788  _VarR8FromCy(cyLeft, &l);
3789  _VarR8FromCy(cyRight, &r);
3790  l = l + r;
3791  return VarCyFromR8(l, pCyOut);
3792 }
3793 
3794 /************************************************************************
3795  * VarCyMul (OLEAUT32.303)
3796  *
3797  * Multiply one CY by another.
3798  *
3799  * PARAMS
3800  * cyLeft [I] Source
3801  * cyRight [I] Value to multiply by
3802  * pCyOut [O] Destination
3803  *
3804  * RETURNS
3805  * Success: S_OK.
3806  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3807  */
3808 HRESULT WINAPI VarCyMul(CY cyLeft, CY cyRight, CY* pCyOut)
3809 {
3810  double l,r;
3811  _VarR8FromCy(cyLeft, &l);
3812  _VarR8FromCy(cyRight, &r);
3813  l = l * r;
3814  return VarCyFromR8(l, pCyOut);
3815 }
3816 
3817 /************************************************************************
3818  * VarCyMulI4 (OLEAUT32.304)
3819  *
3820  * Multiply one CY by a VT_I4.
3821  *
3822  * PARAMS
3823  * cyLeft [I] Source
3824  * lRight [I] Value to multiply by
3825  * pCyOut [O] Destination
3826  *
3827  * RETURNS
3828  * Success: S_OK.
3829  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3830  */
3831 HRESULT WINAPI VarCyMulI4(CY cyLeft, LONG lRight, CY* pCyOut)
3832 {
3833  double d;
3834 
3835  _VarR8FromCy(cyLeft, &d);
3836  d = d * lRight;
3837  return VarCyFromR8(d, pCyOut);
3838 }
3839 
3840 /************************************************************************
3841  * VarCySub (OLEAUT32.305)
3842  *
3843  * Subtract one CY from another.
3844  *
3845  * PARAMS
3846  * cyLeft [I] Source
3847  * cyRight [I] Value to subtract
3848  * pCyOut [O] Destination
3849  *
3850  * RETURNS
3851  * Success: S_OK.
3852  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3853  */
3854 HRESULT WINAPI VarCySub(CY cyLeft, CY cyRight, CY* pCyOut)
3855 {
3856  double l,r;
3857  _VarR8FromCy(cyLeft, &l);
3858  _VarR8FromCy(cyRight, &r);
3859  l = l - r;
3860  return VarCyFromR8(l, pCyOut);
3861 }
3862 
3863 /************************************************************************
3864  * VarCyAbs (OLEAUT32.306)
3865  *
3866  * Convert a VT_CY into its absolute value.
3867  *
3868  * PARAMS
3869  * cyIn [I] Source
3870  * pCyOut [O] Destination
3871  *
3872  * RETURNS
3873  * Success: S_OK. pCyOut contains the absolute value.
3874  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3875  */
3876 HRESULT WINAPI VarCyAbs(CY cyIn, CY* pCyOut)
3877 {
3878  if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3879  return DISP_E_OVERFLOW;
3880 
3881  pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3882  return S_OK;
3883 }
3884 
3885 /************************************************************************
3886  * VarCyFix (OLEAUT32.307)
3887  *
3888  * Return the integer part of a VT_CY.
3889  *
3890  * PARAMS
3891  * cyIn [I] Source
3892  * pCyOut [O] Destination
3893  *
3894  * RETURNS
3895  * Success: S_OK.
3896  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3897  *
3898  * NOTES
3899  * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3900  * negative numbers away from 0, while this function rounds them towards zero.
3901  */
3902 HRESULT WINAPI VarCyFix(CY cyIn, CY* pCyOut)
3903 {
3904  pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3905  pCyOut->int64 *= CY_MULTIPLIER;
3906  return S_OK;
3907 }
3908 
3909 /************************************************************************
3910  * VarCyInt (OLEAUT32.308)
3911  *
3912  * Return the integer part of a VT_CY.
3913  *
3914  * PARAMS
3915  * cyIn [I] Source
3916  * pCyOut [O] Destination
3917  *
3918  * RETURNS
3919  * Success: S_OK.
3920  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3921  *
3922  * NOTES
3923  * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3924  * negative numbers towards 0, while this function rounds them away from zero.
3925  */
3926 HRESULT WINAPI VarCyInt(CY cyIn, CY* pCyOut)
3927 {
3928  pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3929  pCyOut->int64 *= CY_MULTIPLIER;
3930 
3931  if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3932  {
3933  pCyOut->int64 -= CY_MULTIPLIER;
3934  }
3935  return S_OK;
3936 }
3937 
3938 /************************************************************************
3939  * VarCyNeg (OLEAUT32.309)
3940  *
3941  * Change the sign of a VT_CY.
3942  *
3943  * PARAMS
3944  * cyIn [I] Source
3945  * pCyOut [O] Destination
3946  *
3947  * RETURNS
3948  * Success: S_OK.
3949  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3950  */
3951 HRESULT WINAPI VarCyNeg(CY cyIn, CY* pCyOut)
3952 {
3953  if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3954  return DISP_E_OVERFLOW;
3955 
3956  pCyOut->int64 = -cyIn.int64;
3957  return S_OK;
3958 }
3959 
3960 /************************************************************************
3961  * VarCyRound (OLEAUT32.310)
3962  *
3963  * Change the precision of a VT_CY.
3964  *
3965  * PARAMS
3966  * cyIn [I] Source
3967  * cDecimals [I] New number of decimals to keep
3968  * pCyOut [O] Destination
3969  *
3970  * RETURNS
3971  * Success: S_OK.
3972  * Failure: E_INVALIDARG, if cDecimals is less than 0.
3973  */
3974 HRESULT WINAPI VarCyRound(CY cyIn, int cDecimals, CY* pCyOut)
3975 {
3976  if (cDecimals < 0)
3977  return E_INVALIDARG;
3978 
3979  if (cDecimals > 3)
3980  {
3981  /* Rounding to more precision than we have */
3982  *pCyOut = cyIn;
3983  return S_OK;
3984  }
3985  else
3986  {
3987  double d, div = CY_Divisors[cDecimals];
3988 
3989  _VarR8FromCy(cyIn, &d);
3990  d = d * div;
3991  VARIANT_DutchRound(LONGLONG, d, pCyOut->int64);
3992  d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3993  VARIANT_DutchRound(LONGLONG, d, pCyOut->int64);
3994  return S_OK;
3995  }
3996 }
3997 
3998 /************************************************************************
3999  * VarCyCmp (OLEAUT32.311)
4000  *
4001  * Compare two VT_CY values.
4002  *
4003  * PARAMS
4004  * cyLeft [I] Source
4005  * cyRight [I] Value to compare
4006  *
4007  * RETURNS
4008  * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
4009  * compare is less, equal or greater than source respectively.
4010  * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4011  */
4012 HRESULT WINAPI VarCyCmp(CY cyLeft, CY cyRight)
4013 {
4014  HRESULT hRet;
4015  CY result;
4016 
4017  /* Subtract right from left, and compare the result to 0 */
4018  hRet = VarCySub(cyLeft, cyRight, &result);
4019 
4020  if (SUCCEEDED(hRet))
4021  {
4022  if (result.int64 < 0)
4023  hRet = (HRESULT)VARCMP_LT;
4024  else if (result.int64 > 0)
4025  hRet = (HRESULT)VARCMP_GT;
4026  else
4027  hRet = (HRESULT)VARCMP_EQ;
4028  }
4029  return hRet;
4030 }
4031 
4032 /************************************************************************
4033  * VarCyCmpR8 (OLEAUT32.312)
4034  *
4035  * Compare a VT_CY to a double
4036  *
4037  * PARAMS
4038  * cyLeft [I] Currency Source
4039  * dblRight [I] double to compare to cyLeft
4040  *
4041  * RETURNS
4042  * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
4043  * less than, equal to or greater than cyLeft respectively.
4044  * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4045  */
4046 HRESULT WINAPI VarCyCmpR8(CY cyLeft, double dblRight)
4047 {
4048  HRESULT hRet;
4049  CY cyRight;
4050 
4051  hRet = VarCyFromR8(dblRight, &cyRight);
4052 
4053  if (SUCCEEDED(hRet))
4054  hRet = VarCyCmp(cyLeft, cyRight);
4055 
4056  return hRet;
4057 }
4058 
4059 /************************************************************************
4060  * VarCyMulI8 (OLEAUT32.329)
4061  *
4062  * Multiply a VT_CY by a VT_I8.
4063  *
4064  * PARAMS
4065  * cyLeft [I] Source
4066  * llRight [I] Value to multiply by
4067  * pCyOut [O] Destination
4068  *
4069  * RETURNS
4070  * Success: S_OK.
4071  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4072  */
4073 HRESULT WINAPI VarCyMulI8(CY cyLeft, LONG64 llRight, CY* pCyOut)
4074 {
4075  double d;
4076 
4077  _VarR8FromCy(cyLeft, &d);
4078  d = d * (double)llRight;
4079  return VarCyFromR8(d, pCyOut);
4080 }
4081 
4082 /* DECIMAL
4083  */
4084 
4085 /************************************************************************
4086  * VarDecFromUI1 (OLEAUT32.190)
4087  *
4088  * Convert a VT_UI1 to a DECIMAL.
4089  *
4090  * PARAMS
4091  * bIn [I] Source
4092  * pDecOut [O] Destination
4093  *
4094  * RETURNS
4095  * S_OK.
4096  */
4098 {
4099  return VarDecFromUI4(bIn, pDecOut);
4100 }
4101 
4102 /************************************************************************
4103  * VarDecFromI2 (OLEAUT32.191)
4104  *
4105  * Convert a VT_I2 to a DECIMAL.
4106  *
4107  * PARAMS
4108  * sIn [I] Source
4109  * pDecOut [O] Destination
4110  *
4111  * RETURNS
4112  * S_OK.
4113  */
4115 {
4116  return VarDecFromI4(sIn, pDecOut);
4117 }
4118 
4119 /************************************************************************
4120  * VarDecFromI4 (OLEAUT32.192)
4121  *
4122  * Convert a VT_I4 to a DECIMAL.
4123  *
4124  * PARAMS
4125  * sIn [I] Source
4126  * pDecOut [O] Destination
4127  *
4128  * RETURNS
4129  * S_OK.
4130  */
4132 {
4133  DEC_HI32(pDecOut) = 0;
4134  DEC_MID32(pDecOut) = 0;
4135 
4136  if (lIn < 0)
4137  {
4138  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4139  DEC_LO32(pDecOut) = -lIn;
4140  }
4141  else
4142  {
4143  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4144  DEC_LO32(pDecOut) = lIn;
4145  }
4146  return S_OK;
4147 }
4148 
4149 /* internal representation of the value stored in a DECIMAL. The bytes are
4150  stored from LSB at index 0 to MSB at index 11
4151  */
4152 typedef struct DECIMAL_internal
4153 {
4154  DWORD bitsnum[3]; /* 96 significant bits, unsigned */
4155  unsigned char scale; /* number scaled * 10 ^ -(scale) */
4156  unsigned int sign : 1; /* 0 - positive, 1 - negative */
4157 } VARIANT_DI;
4158 
4160 static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest);
4161 static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to);
4162 static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to);
4163 static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor);
4164 static BOOL VARIANT_int_iszero(const DWORD * p, unsigned int n);
4165 
4166 /************************************************************************
4167  * VarDecFromR4 (OLEAUT32.193)
4168  *
4169  * Convert a VT_R4 to a DECIMAL.
4170  *
4171  * PARAMS
4172  * fltIn [I] Source
4173  * pDecOut [O] Destination
4174  *
4175  * RETURNS
4176  * S_OK.
4177  */
4179 {
4180  VARIANT_DI di;
4181  HRESULT hres;
4182 
4183  hres = VARIANT_DI_FromR4(fltIn, &di);
4184  if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
4185  return hres;
4186 }
4187 
4188 /************************************************************************
4189  * VarDecFromR8 (OLEAUT32.194)
4190  *
4191  * Convert a VT_R8 to a DECIMAL.
4192  *
4193  * PARAMS
4194  * dblIn [I] Source
4195  * pDecOut [O] Destination
4196  *
4197  * RETURNS
4198  * S_OK.
4199  */
4200 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4201 {
4202  VARIANT_DI di;
4203  HRESULT hres;
4204 
4205  hres = VARIANT_DI_FromR8(dblIn, &di);
4206  if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
4207  return hres;
4208 }
4209 
4210 /************************************************************************
4211  * VarDecFromDate (OLEAUT32.195)
4212  *
4213  * Convert a VT_DATE to a DECIMAL.
4214  *
4215  * PARAMS
4216  * dateIn [I] Source
4217  * pDecOut [O] Destination
4218  *
4219  * RETURNS
4220  * S_OK.
4221  */
4223 {
4224  return VarDecFromR8(dateIn, pDecOut);
4225 }
4226 
4227 /************************************************************************
4228  * VarDecFromCy (OLEAUT32.196)
4229  *
4230  * Convert a VT_CY to a DECIMAL.
4231  *
4232  * PARAMS
4233  * cyIn [I] Source
4234  * pDecOut [O] Destination
4235  *
4236  * RETURNS
4237  * S_OK.
4238  */
4240 {
4241  DEC_HI32(pDecOut) = 0;
4242 
4243  /* Note: This assumes 2s complement integer representation */
4244  if (cyIn.s.Hi & 0x80000000)
4245  {
4246  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4247  DEC_LO64(pDecOut) = -cyIn.int64;
4248  }
4249  else
4250  {
4251  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4252  DEC_MID32(pDecOut) = cyIn.s.Hi;
4253  DEC_LO32(pDecOut) = cyIn.s.Lo;
4254  }
4255  return S_OK;
4256 }
4257 
4258 /************************************************************************
4259  * VarDecFromStr (OLEAUT32.197)
4260  *
4261  * Convert a VT_BSTR to a DECIMAL.
4262  *
4263  * PARAMS
4264  * strIn [I] Source
4265  * lcid [I] LCID for the conversion
4266  * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4267  * pDecOut [O] Destination
4268  *
4269  * RETURNS
4270  * Success: S_OK.
4271  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4272  */
4274 {
4275  return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDecOut, VT_DECIMAL);
4276 }
4277 
4278 /************************************************************************
4279  * VarDecFromDisp (OLEAUT32.198)
4280  *
4281  * Convert a VT_DISPATCH to a DECIMAL.
4282  *
4283  * PARAMS
4284  * pdispIn [I] Source
4285  * lcid [I] LCID for conversion
4286  * pDecOut [O] Destination
4287  *
4288  * RETURNS
4289  * Success: S_OK.
4290  * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4291  */
4293 {
4294  return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL, 0);
4295 }
4296 
4297 /************************************************************************
4298  * VarDecFromBool (OLEAUT32.199)
4299  *
4300  * Convert a VT_BOOL to a DECIMAL.
4301  *
4302  * PARAMS
4303  * bIn [I] Source
4304  * pDecOut [O] Destination
4305  *
4306  * RETURNS
4307  * S_OK.
4308  *
4309  * NOTES
4310  * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4311  */
4313 {
4314  DEC_HI32(pDecOut) = 0;
4315  DEC_MID32(pDecOut) = 0;
4316  if (bIn)
4317  {
4318  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4319  DEC_LO32(pDecOut) = 1;
4320  }
4321  else
4322  {
4323  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4324  DEC_LO32(pDecOut) = 0;
4325  }
4326  return S_OK;
4327 }
4328 
4329 /************************************************************************
4330  * VarDecFromI1 (OLEAUT32.241)
4331  *
4332  * Convert a VT_I1 to a DECIMAL.
4333  *
4334  * PARAMS
4335  * cIn [I] Source
4336  * pDecOut [O] Destination
4337  *
4338  * RETURNS
4339  * S_OK.
4340  */
4341 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4342 {
4343  return VarDecFromI4(cIn, pDecOut);
4344 }
4345 
4346 /************************************************************************
4347  * VarDecFromUI2 (OLEAUT32.242)
4348  *
4349  * Convert a VT_UI2 to a DECIMAL.
4350  *
4351  * PARAMS
4352  * usIn [I] Source
4353  * pDecOut [O] Destination
4354  *
4355  * RETURNS
4356  * S_OK.
4357  */
4359 {
4360  return VarDecFromUI4(usIn, pDecOut);
4361 }
4362 
4363 /************************************************************************
4364  * VarDecFromUI4 (OLEAUT32.243)
4365  *
4366  * Convert a VT_UI4 to a DECIMAL.
4367  *
4368  * PARAMS
4369  * ulIn [I] Source
4370  * pDecOut [O] Destination
4371  *
4372  * RETURNS
4373  * S_OK.
4374  */
4376 {
4377  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4378  DEC_HI32(pDecOut) = 0;
4379  DEC_MID32(pDecOut) = 0;
4380  DEC_LO32(pDecOut) = ulIn;
4381  return S_OK;
4382 }
4383 
4384 /************************************************************************
4385  * VarDecFromI8 (OLEAUT32.374)
4386  *
4387  * Convert a VT_I8 to a DECIMAL.
4388  *
4389  * PARAMS
4390  * llIn [I] Source
4391  * pDecOut [O] Destination
4392  *
4393  * RETURNS
4394  * S_OK.
4395  */
4397 {
4398  PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4399 
4400  DEC_HI32(pDecOut) = 0;
4401 
4402  /* Note: This assumes 2s complement integer representation */
4403  if (pLi->u.HighPart & 0x80000000)
4404  {
4405  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4406  DEC_LO64(pDecOut) = -pLi->QuadPart;
4407  }
4408  else
4409  {
4410  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4411  DEC_MID32(pDecOut) = pLi->u.HighPart;
4412  DEC_LO32(pDecOut) = pLi->u.LowPart;
4413  }
4414  return S_OK;
4415 }
4416 
4417 /************************************************************************
4418  * VarDecFromUI8 (OLEAUT32.375)
4419  *
4420  * Convert a VT_UI8 to a DECIMAL.
4421  *
4422  * PARAMS
4423  * ullIn [I] Source
4424  * pDecOut [O] Destination
4425  *
4426  * RETURNS
4427  * S_OK.
4428  */
4430 {
4431  DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4432  DEC_HI32(pDecOut) = 0;
4433  DEC_LO64(pDecOut) = ullIn;
4434  return S_OK;
4435 }
4436 
4437 /* Make two DECIMALS the same scale; used by math functions below */
4438 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4439  const DECIMAL** ppDecRight,
4440  DECIMAL pDecOut[2])
4441 {
4442  static DECIMAL scaleFactor;
4443  unsigned char remainder;
4444  DECIMAL decTemp;
4445  VARIANT_DI di;
4446  int scaleAmount, i;
4447 
4448  if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4449  return E_INVALIDARG;
4450 
4451  DEC_LO32(&scaleFactor) = 10;
4452 
4453  i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4454 
4455  if (!scaleAmount)
4456  return S_OK; /* Same scale */
4457 
4458  if (scaleAmount > 0)
4459  {
4460  decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4461  *ppDecRight = &pDecOut[0];
4462  }
4463  else
4464  {
4465  decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4466  *ppDecLeft = &pDecOut[0];
4467  i = -scaleAmount;
4468  }
4469 
4470  /* Multiply up the value to be scaled by the correct amount (if possible) */
4471  while (i > 0 && SUCCEEDED(VarDecMul(&decTemp, &scaleFactor, &pDecOut[0])))
4472  {
4473  decTemp = pDecOut[0];
4474  i--;
4475  }
4476 
4477  if (!i)
4478  {
4479  DEC_SCALE(&pDecOut[0]) += (scaleAmount > 0) ? scaleAmount : (-scaleAmount);
4480  return S_OK; /* Same scale */
4481  }
4482 
4483  /* Scaling further not possible, reduce accuracy of other argument */
4484  pDecOut[0] = decTemp;
4485  if (scaleAmount > 0)
4486  {
4487  DEC_SCALE(&pDecOut[0]) += scaleAmount - i;
4488  VARIANT_DIFromDec(*ppDecLeft, &di);
4489  *ppDecLeft = &pDecOut[1];
4490  }
4491  else
4492  {
4493  DEC_SCALE(&pDecOut[0]) += (-scaleAmount) - i;
4494  VARIANT_DIFromDec(*ppDecRight, &di);
4495  *ppDecRight = &pDecOut[1];
4496  }
4497 
4498  di.scale -= i;
4499  remainder = 0;
4500  while (i-- > 0 && !VARIANT_int_iszero(di.bitsnum, ARRAY_SIZE(di.bitsnum)))
4501  {
4503  if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
4504  }
4505 
4506  /* round up the result - native oleaut32 does this */
4507  if (remainder >= 5) {
4508  for (remainder = 1, i = 0; i < ARRAY_SIZE(di.bitsnum) && remainder; i++) {
4509  ULONGLONG digit = di.bitsnum[i] + 1;
4510  remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4511  di.bitsnum[i] = digit & 0xFFFFFFFF;
4512  }
4513  }
4514 
4515  VARIANT_DecFromDI(&di, &pDecOut[1]);
4516  return S_OK;
4517 }
4518 
4519 /* Add two unsigned 32 bit values with overflow */
4520 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4521 {
4522  ULARGE_INTEGER ul64;
4523 
4524  ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4525  *pulHigh = ul64.u.HighPart;
4526  return ul64.u.LowPart;
4527 }
4528 
4529 /* Subtract two unsigned 32 bit values with underflow */
4530 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4531 {
4532  BOOL invert = FALSE;
4533  ULARGE_INTEGER ul64;
4534 
4535  ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4536  if (ulLeft < ulRight)
4537  invert = TRUE;
4538 
4539  if (ul64.QuadPart > (ULONG64)*pulHigh)
4540  ul64.QuadPart -= (ULONG64)*pulHigh;
4541  else
4542  {
4543  ul64.QuadPart -= (ULONG64)*pulHigh;
4544  invert = TRUE;
4545  }
4546  if (invert)
4547  ul64.u.HighPart = -ul64.u.HighPart ;
4548 
4549  *pulHigh = ul64.u.HighPart;
4550  return ul64.u.LowPart;
4551 }
4552 
4553 /* Multiply two unsigned 32 bit values with overflow */
4554 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4555 {
4556  ULARGE_INTEGER ul64;
4557 
4558  ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4559  *pulHigh = ul64.u.HighPart;
4560  return ul64.u.LowPart;
4561 }
4562 
4563 /* Compare two decimals that have the same scale */
4564 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4565 {
4566  if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4567  (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4568  return -1;
4569  else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4570  return 0;
4571  return 1;
4572 }
4573 
4574 /************************************************************************
4575  * VarDecAdd (OLEAUT32.177)
4576  *
4577  * Add one DECIMAL to another.
4578  *
4579  * PARAMS
4580  * pDecLeft [I] Source
4581  * pDecRight [I] Value to add
4582  * pDecOut [O] Destination
4583  *
4584  * RETURNS
4585  * Success: S_OK.
4586  * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4587  */
4588 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4589 {
4590  HRESULT hRet;
4591  DECIMAL scaled[2];
4592 
4593  hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, scaled);
4594 
4595  if (SUCCEEDED(hRet))
4596  {
4597  /* Our decimals now have the same scale, we can add them as 96 bit integers */
4598  ULONG overflow = 0;
4599  BYTE sign = DECIMAL_POS;
4600  int cmp;
4601 
4602  /* Correct for the sign of the result */
4603  if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4604  {
4605  /* -x + -y : Negative */
4606  sign = DECIMAL_NEG;
4607  goto VarDecAdd_AsPositive;
4608  }
4609  else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4610  {
4611  cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4612 
4613  /* -x + y : Negative if x > y */
4614  if (cmp > 0)
4615  {
4616  sign = DECIMAL_NEG;
4617 VarDecAdd_AsNegative:
4618  DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4619  DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4620  DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4621  }
4622  else
4623  {
4624 VarDecAdd_AsInvertedNegative:
4625  DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecRight), DEC_LO32(pDecLeft), &overflow);
4626  DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4627  DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecRight), DEC_HI32(pDecLeft), &overflow);
4628  }
4629  }
4630  else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4631  {
4632  cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4633 
4634  /* x + -y : Negative if x <= y */
4635  if (cmp <= 0)
4636  {
4637  sign = DECIMAL_NEG;
4638  goto VarDecAdd_AsInvertedNegative;
4639  }
4640  goto VarDecAdd_AsNegative;
4641  }
4642  else
4643  {
4644  /* x + y : Positive */
4645 VarDecAdd_AsPositive:
4646  DEC_LO32(pDecOut) = VARIANT_Add(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4647  DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4648  DEC_HI32(pDecOut) = VARIANT_Add(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4649  }
4650 
4651  if (overflow)
4652  return DISP_E_OVERFLOW; /* overflowed */
4653 
4654  DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4655  DEC_SIGN(pDecOut) = sign;
4656  }
4657  return hRet;
4658 }
4659 
4660 /* translate from external DECIMAL format into an internal representation */
4661 static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to)
4662 {
4663  to->scale = DEC_SCALE(from);
4664  to->sign = DEC_SIGN(from) ? 1 : 0;
4665 
4666  to->bitsnum[0] = DEC_LO32(from);
4667  to->bitsnum[1] = DEC_MID32(from);
4668  to->bitsnum[2] = DEC_HI32(from);
4669 }
4670 
4671 static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to)
4672 {
4673  if (from->sign) {
4674  DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_NEG, from->scale);
4675  } else {
4676  DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_POS, from->scale);
4677  }
4678 
4679  DEC_LO32(to) = from->bitsnum[0];
4680  DEC_MID32(to) = from->bitsnum[1];
4681  DEC_HI32(to) = from->bitsnum[2];
4682 }
4683 
4684 /* clear an internal representation of a DECIMAL */
4686 {
4687  memset(i, 0, sizeof(VARIANT_DI));
4688 }
4689 
4690 /* divide the (unsigned) number stored in p (LSB) by a byte value (<= 0xff). Any nonzero
4691  size is supported. The value in p is replaced by the quotient of the division, and
4692  the remainder is returned as a result. This routine is most often used with a divisor
4693  of 10 in order to scale up numbers, and in the DECIMAL->string conversion.
4694  */
4695 static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor)
4696 {
4697  if (divisor == 0) {
4698  /* division by 0 */
4699  return 0xFF;
4700  } else if (divisor == 1) {
4701  /* dividend remains unchanged */
4702  return 0;
4703  } else {
4704  unsigned char remainder = 0;
4705  ULONGLONG iTempDividend;
4706  signed int i;
4707 
4708  for (i = n - 1; i >= 0 && !p[i]; i--); /* skip leading zeros */
4709  for (; i >= 0; i--) {
4710  iTempDividend = ((ULONGLONG)remainder << 32) + p[i];
4711  remainder = iTempDividend % divisor;
4712  p[i] = iTempDividend / divisor;
4713  }
4714 
4715  return remainder;
4716  }
4717 }
4718 
4719 /* check to test if encoded number is a zero. Returns 1 if zero, 0 for nonzero */
4720 static BOOL VARIANT_int_iszero(const DWORD * p, unsigned int n)
4721 {
4722  for (; n > 0; n--) if (*p++ != 0) return FALSE;
4723  return TRUE;
4724 }
4725 
4726 /* multiply two DECIMALS, without changing either one, and place result in third
4727  parameter. Result is normalized when scale is > 0. Attempts to remove significant
4728  digits when scale > 0 in order to fit an overflowing result. Final overflow
4729  flag is returned.
4730  */
4731 static int VARIANT_DI_mul(const VARIANT_DI * a, const VARIANT_DI * b, VARIANT_DI * result)
4732 {
4733  BOOL r_overflow = FALSE;
4734  DWORD running[6];
4735  signed int mulstart;
4736 
4738  result->sign = (a->sign ^ b->sign) ? 1 : 0;
4739 
4740  /* Multiply 128-bit operands into a (max) 256-bit result. The scale
4741  of the result is formed by adding the scales of the operands.
4742  */
4743  result->scale = a->scale + b->scale;
4744  memset(running, 0, sizeof(running));
4745 
4746  /* count number of leading zero-bytes in operand A */
4747  for (mulstart = ARRAY_SIZE(a->bitsnum) - 1; mulstart >= 0 && !a->bitsnum[mulstart]; mulstart--);
4748  if (mulstart < 0) {
4749  /* result is 0, because operand A is 0 */
4750  result->scale = 0;
4751  result->sign = 0;
4752  } else {
4753  unsigned char remainder = 0;
4754  int iA;
4755 
4756  /* perform actual multiplication */
4757  for (iA = 0; iA <= mulstart; iA++) {
4758  ULONG iOverflowMul;
4759  int iB;
4760 
4761  for (iOverflowMul = 0, iB = 0; iB < ARRAY_SIZE(b->bitsnum); iB++) {
4762  ULONG iRV;
4763  int iR;
4764 
4765  iRV = VARIANT_Mul(b->bitsnum[iB], a->bitsnum[iA], &iOverflowMul);
4766  iR = iA + iB;
4767  do {
4768  running[iR] = VARIANT_Add(running[iR], 0, &iRV);
4769  iR++;
4770  } while (iRV);
4771  }
4772  }
4773 
4774 /* Too bad - native oleaut does not do this, so we should not either */
4775 #if 0
4776  /* While the result is divisible by 10, and the scale > 0, divide by 10.
4777  This operation should not lose significant digits, and gives an
4778  opportunity to reduce the possibility of overflows in future
4779  operations issued by the application.
4780  */
4781  while (result->scale > 0) {
4782  memcpy(quotient, running, sizeof(quotient));
4783  remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
4784  if (remainder > 0) break;
4785  memcpy(running, quotient, sizeof(quotient));
4786  result->scale--;
4787  }
4788 #endif
4789  /* While the 256-bit result overflows, and the scale > 0, divide by 10.
4790  This operation *will* lose significant digits of the result because
4791  all the factors of 10 were consumed by the previous operation.
4792  */
4793  while (result->scale > 0 && !VARIANT_int_iszero(running + ARRAY_SIZE(result->bitsnum),
4794  ARRAY_SIZE(running) - ARRAY_SIZE(result->bitsnum))) {
4795 
4796  remainder = VARIANT_int_divbychar(running, ARRAY_SIZE(running), 10);
4797  if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
4798  result->scale--;
4799  }
4800 
4801  /* round up the result - native oleaut32 does this */
4802  if (remainder >= 5) {
4803  unsigned int i;
4804  for (remainder = 1, i = 0; i < ARRAY_SIZE(running) && remainder; i++) {
4805  ULONGLONG digit = running[i] + 1;
4806  remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4807  running[i] = digit & 0xFFFFFFFF;
4808  }
4809  }
4810 
4811  /* Signal overflow if scale == 0 and 256-bit result still overflows,
4812  and copy result bits into result structure
4813  */
4814  r_overflow = !VARIANT_int_iszero(running + ARRAY_SIZE(result->bitsnum),
4815  ARRAY_SIZE(running) - ARRAY_SIZE(result->bitsnum));
4816  memcpy(result->bitsnum, running, sizeof(result->bitsnum));
4817  }
4818  return r_overflow;
4819 }
4820 
4821 /* cast DECIMAL into string. Any scale should be handled properly. en_US locale is
4822  hardcoded (period for decimal separator, dash as negative sign). Returns TRUE for
4823  success, FALSE if insufficient space in output buffer.
4824  */
4825 static BOOL VARIANT_DI_tostringW(const VARIANT_DI * a, WCHAR * s, unsigned int n)
4826 {
4827  BOOL overflow = FALSE;
4828  DWORD quotient[3];
4829  unsigned char remainder;
4830  unsigned int i;
4831 
4832  /* place negative sign */
4833  if (!VARIANT_int_iszero(a->bitsnum, ARRAY_SIZE(a->bitsnum)) && a->sign) {
4834  if (n > 0) {
4835  *s++ = '-';
4836  n--;
4837  }
4838  else overflow = TRUE;
4839  }
4840 
4841  /* prepare initial 0 */
4842  if (!overflow) {
4843  if (n >= 2) {
4844  s[0] = '0';
4845  s[1] = '\0';
4846  } else overflow = TRUE;
4847  }
4848 
4849  i = 0;
4850  memcpy(quotient, a->bitsnum, sizeof(a->bitsnum));
4851  while (!overflow && !VARIANT_int_iszero(quotient, ARRAY_SIZE(quotient))) {
4852  remainder = VARIANT_int_divbychar(quotient, ARRAY_SIZE(quotient), 10);
4853  if (i + 2 > n) {
4854  overflow = TRUE;
4855  } else {
4856  s[i++] = '0' + remainder;
4857  s[i] = '\0';
4858  }
4859  }
4860 
4861  if (!overflow && !VARIANT_int_iszero(a->bitsnum, ARRAY_SIZE(a->bitsnum))) {
4862 
4863  /* reverse order of digits */
4864  WCHAR * x = s; WCHAR * y = s + i - 1;
4865  while (x < y) {
4866  *x ^= *y;
4867  *y ^= *x;
4868  *x++ ^= *y--;
4869  }
4870 
4871  /* check for decimal point. "i" now has string length */
4872  if (i <= a->scale) {
4873  unsigned int numzeroes = a->scale + 1 - i;
4874  if (i + 1 + numzeroes >= n) {
4875  overflow = TRUE;
4876  } else {
4877  memmove(s + numzeroes, s, (i + 1) * sizeof(WCHAR));
4878  i += numzeroes;
4879  while (numzeroes > 0) {
4880  s[--numzeroes] = '0';
4881  }
4882  }
4883  }
4884 
4885  /* place decimal point */
4886  if (a->scale > 0) {
4887  unsigned int periodpos = i - a->scale;
4888  if (i + 2 >= n) {
4889  overflow = TRUE;
4890  } else {
4891  memmove(s + periodpos + 1, s + periodpos, (i + 1 - periodpos) * sizeof(WCHAR));
4892  s[periodpos] = '.'; i++;
4893 
4894  /* remove extra zeros at the end, if any */
4895  while (s[i - 1] == '0') s[--i] = '\0';
4896  if (s[i - 1] == '.') s[--i] = '\0';
4897  }
4898  }
4899  }
4900 
4901  return !overflow;
4902 }
4903 
4904 /* shift the bits of a DWORD array to the left. p[0] is assumed LSB */
4905 static void VARIANT_int_shiftleft(DWORD * p, unsigned int n, unsigned int shift)
4906 {
4907  DWORD shifted;
4908  unsigned int i;
4909 
4910  /* shift whole DWORDs to the left */
4911  while (shift >= 32)
4912  {
4913  memmove(p + 1, p, (n - 1) * sizeof(DWORD));
4914  *p = 0; shift -= 32;
4915  }
4916 
4917  /* shift remainder (1..31 bits) */
4918  shifted = 0;
4919  if (shift > 0) for (i = 0; i < n; i++)
4920  {
4921  DWORD b;
4922  b = p[i] >> (32 - shift);
4923  p[i] = (p[i] << shift) | shifted;
4924  shifted = b;
4925  }
4926 }
4927 
4928 /* add the (unsigned) numbers stored in two DWORD arrays with LSB at index 0.
4929  Value at v is incremented by the value at p. Any size is supported, provided
4930  that v is not shorter than p. Any unapplied carry is returned as a result.
4931  */
4932 static unsigned char VARIANT_int_add(DWORD * v, unsigned int nv, const DWORD * p,
4933  unsigned int np)
4934 {
4935  unsigned char carry = 0;
4936 
4937  if (nv >= np) {
4938  ULONGLONG sum;
4939  unsigned int i;
4940 
4941  for (i = 0; i < np; i++) {
4942  sum = (ULONGLONG)v[i]
4943  + (ULONGLONG)p[i]
4944  + (ULONGLONG)carry;
4945  v[i] = sum & 0xffffffff;
4946  carry = sum >> 32;
4947  }
4948  for (; i < nv && carry; i++) {
4949  sum = (ULONGLONG)v[i]
4950  + (ULONGLONG)carry;
4951  v[i] = sum & 0xffffffff;
4952  carry = sum >> 32;
4953  }
4954  }
4955  return carry;
4956 }
4957 
4958 /* perform integral division with operand p as dividend. Parameter n indicates
4959  number of available DWORDs in divisor p, but available space in p must be
4960  actually at least 2 * n DWORDs, because the remainder of the integral
4961  division is built in the next n DWORDs past the start of the quotient. This
4962  routine replaces the dividend in p with the quotient, and appends n
4963  additional DWORDs for the remainder.
4964 
4965  Thanks to Lee & Mark Atkinson for their book _Using_C_ (my very first book on
4966  C/C++ :-) where the "longhand binary division" algorithm was exposed for the
4967  source code to the VLI (Very Large Integer) division operator. This algorithm
4968  was then heavily modified by me (Alex Villacis Lasso) in order to handle
4969  variably-scaled integers such as the MS DECIMAL representation.
4970  */
4971 static void VARIANT_int_div(DWORD * p, unsigned int n, const DWORD * divisor,
4972  unsigned int dn)
4973 {
4974  unsigned int i;
4975  DWORD tempsub[8];
4976  DWORD * negdivisor = tempsub + n;
4977 
4978  /* build 2s-complement of divisor */
4979  for (i = 0; i < n; i++) negdivisor[i] = (i < dn) ? ~divisor[i] : 0xFFFFFFFF;
4980  p[n] = 1;
4981  VARIANT_int_add(negdivisor, n, p + n, 1);
4982  memset(p + n, 0, n * sizeof(DWORD));
4983 
4984  /* skip all leading zero DWORDs in quotient */
4985  for (i = 0; i < n && !p[n - 1]; i++) VARIANT_int_shiftleft(p, n, 32);
4986  /* i is now number of DWORDs left to process */
4987  for (i <<= 5; i < (n << 5); i++) {
4988  VARIANT_int_shiftleft(p, n << 1, 1); /* shl quotient+remainder */
4989 
4990  /* trial subtraction */
4991  memcpy(tempsub, p + n, n * sizeof(DWORD));
4992  VARIANT_int_add(tempsub, n, negdivisor, n);
4993 
4994  /* check whether result of subtraction was negative */
4995  if ((tempsub[n - 1] & 0x80000000) == 0) {
4996  memcpy(p + n, tempsub, n * sizeof(DWORD));
4997  p[0] |= 1;
4998  }
4999  }
5000 }
5001 
5002 /* perform integral multiplication by a byte operand. Used for scaling by 10 */
5003 static unsigned char VARIANT_int_mulbychar(DWORD * p, unsigned int n, unsigned char m)
5004 {
5005  unsigned int i;
5006  ULONG iOverflowMul;
5007 
5008  for (iOverflowMul = 0, i = 0; i < n; i++)
5009  p[i] = VARIANT_Mul(p[i], m, &iOverflowMul);
5010  return (unsigned char)iOverflowMul;
5011 }
5012 
5013 /* increment value in A by the value indicated in B, with scale adjusting.
5014  Modifies parameters by adjusting scales. Returns 0 if addition was
5015  successful, nonzero if a parameter underflowed before it could be
5016  successfully used in the addition.
5017  */
5019  DWORD * a, int * ascale, unsigned int an,
5020  DWORD * b, int * bscale, unsigned int bn)
5021 {
5022  int underflow = 0;
5023 
5024  if (VARIANT_int_iszero(a, an)) {
5025  /* if A is zero, copy B into A, after removing digits */
5026  while (bn > an && !VARIANT_int_iszero(b + an, bn - an)) {
5027  VARIANT_int_divbychar(b, bn, 10);
5028  (*bscale)--;
5029  }
5030  memcpy(a, b, an * sizeof(DWORD));
5031  *ascale = *bscale;
5032  } else if (!VARIANT_int_iszero(b, bn)) {
5033  unsigned int tn = an + 1;
5034  DWORD t[5];
5035 
5036  if (bn + 1 > tn) tn = bn + 1;
5037  if (*ascale != *bscale) {
5038  /* first (optimistic) try - try to scale down the one with the bigger
5039  scale, while this number is divisible by 10 */
5040  DWORD * digitchosen;
5041  unsigned int nchosen;
5042  int * scalechosen;
5043  int targetscale;
5044 
5045  if (*ascale < *bscale) {
5046  targetscale = *ascale;
5047  scalechosen = bscale;
5048  digitchosen = b;
5049  nchosen = bn;
5050  } else {
5051  targetscale = *bscale;
5052  scalechosen = ascale;
5053  digitchosen = a;
5054  nchosen = an;
5055  }
5056  memset(t, 0, tn * sizeof(DWORD));
5057  memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5058 
5059  /* divide by 10 until target scale is reached */
5060  while (*scalechosen > targetscale) {
5061  unsigned char remainder = VARIANT_int_divbychar(t, tn, 10);
5062  if (!remainder) {
5063  (*scalechosen)--;
5064  memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5065  } else break;
5066  }
5067  }
5068 
5069  if (*ascale != *bscale) {
5070  DWORD * digitchosen;
5071  unsigned int nchosen;
5072  int * scalechosen;
5073  int targetscale;
5074 
5075  /* try to scale up the one with the smaller scale */
5076  if (*ascale > *bscale) {
5077  targetscale = *ascale;
5078  scalechosen = bscale;
5079  digitchosen = b;
5080  nchosen = bn;
5081  } else {
5082  targetscale = *bscale;
5083  scalechosen = ascale;
5084  digitchosen = a;
5085  nchosen = an;
5086  }
5087  memset(t, 0, tn * sizeof(DWORD));
5088  memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5089 
5090  /* multiply by 10 until target scale is reached, or
5091  significant bytes overflow the number
5092  */
5093  while (*scalechosen < targetscale && t[nchosen] == 0) {
5094  VARIANT_int_mulbychar(t, tn, 10);
5095  if (t[nchosen] == 0) {
5096  /* still does not overflow */
5097  (*scalechosen)++;
5098  memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5099  }
5100  }
5101  }
5102 
5103  if (*ascale != *bscale) {
5104  /* still different? try to scale down the one with the bigger scale
5105  (this *will* lose significant digits) */
5106  DWORD * digitchosen;
5107  unsigned int nchosen;
5108  int * scalechosen;
5109  int targetscale;
5110 
5111  if (*ascale < *bscale) {
5112  targetscale = *ascale;
5113  scalechosen = bscale;
5114  digitchosen = b;
5115  nchosen = bn;
5116  } else {
5117  targetscale = *bscale;
5118  scalechosen = ascale;
5119  digitchosen = a;
5120  nchosen = an;
5121  }
5122  memset(t, 0, tn * sizeof(DWORD));
5123  memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5124 
5125  /* divide by 10 until target scale is reached */
5126  while (*scalechosen > targetscale) {
5127  VARIANT_int_divbychar(t, tn, 10);
5128  (*scalechosen)--;
5129  memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5130  }
5131  }
5132 
5133  /* check whether any of the operands still has significant digits
5134  (underflow case 1)
5135  */
5136  if (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn)) {
5137  underflow = 1;
5138  } else {
5139  /* at this step, both numbers have the same scale and can be added
5140  as integers. However, the result might not fit in A, so further
5141  scaling down might be necessary.
5142  */
5143  while (!underflow) {
5144  memset(t, 0, tn * sizeof(DWORD));
5145  memcpy(t, a, an * sizeof(DWORD));
5146 
5147  VARIANT_int_add(t, tn, b, bn);
5148  if (VARIANT_int_iszero(t + an, tn - an)) {
5149  /* addition was successful */
5150  memcpy(a, t, an * sizeof(DWORD));
5151  break;
5152  } else {
5153  /* addition overflowed - remove significant digits
5154  from both operands and try again */
5155  VARIANT_int_divbychar(a, an, 10); (*ascale)--;
5156  VARIANT_int_divbychar(b, bn, 10); (*bscale)--;
5157  /* check whether any operand keeps significant digits after
5158  scaledown (underflow case 2)
5159  */
5160  underflow = (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn));
5161  }
5162  }
5163  }
5164  }
5165  return underflow;
5166 }
5167 
5168 /* perform complete DECIMAL division in the internal representation. Returns
5169  0 if the division was completed (even if quotient is set to 0), or nonzero
5170  in case of quotient overflow.
5171  */
5172 static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * divisor,
5173  VARIANT_DI * quotient, BOOL round_remainder)
5174 {
5175  HRESULT r_overflow = S_OK;
5176 
5177  if (VARIANT_int_iszero(divisor->bitsnum, ARRAY_SIZE(divisor->bitsnum))) {
5178  /* division by 0 */
5179  r_overflow = DISP_E_DIVBYZERO;
5180  } else if (VARIANT_int_iszero(dividend->bitsnum, ARRAY_SIZE(dividend->bitsnum))) {
5181  VARIANT_DI_clear(quotient);
5182  } else {
5183  int quotientscale, remainderscale, tempquotientscale;
5184  DWORD remainderplusquotient[8];
5185  int underflow;
5186 
5187  quotientscale = remainderscale = (int)dividend->scale - (int)divisor->scale;
5188  tempquotientscale = quotientscale;
5189  VARIANT_DI_clear(quotient);
5190  quotient->sign = (dividend->sign ^ divisor->sign) ? 1 : 0;
5191 
5192  /* The following strategy is used for division
5193  1) if there was a nonzero remainder from previous iteration, use it as
5194  dividend for this iteration, else (for first iteration) use intended
5195  dividend
5196  2) perform integer division in temporary buffer, develop quotient in
5197  low-order part, remainder in high-order part
5198  3) add quotient from step 2 to final result, with possible loss of
5199  significant digits
5200  4) multiply integer part of remainder by 10, while incrementing the
5201  scale of the remainder. This operation preserves the intended value
5202  of the remainder.
5203  5) loop to step 1 until one of the following is true:
5204  a) remainder is zero (exact division achieved)
5205  b) addition in step 3 fails to modify bits in quotient (remainder underflow)
5206  */
5207  memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5208  memcpy(remainderplusquotient, dividend->bitsnum, sizeof(dividend->bitsnum));
5209  do {
5210  VARIANT_int_div(remainderplusquotient, 4, divisor->bitsnum, ARRAY_SIZE(divisor->bitsnum));
5211  underflow = VARIANT_int_addlossy( quotient->bitsnum, &quotientscale,
5212  ARRAY_SIZE(quotient->bitsnum), remainderplusquotient, &tempquotientscale, 4);
5213  if (round_remainder) {
5214  if(remainderplusquotient[4] >= 5){
5215  unsigned int i;
5216  unsigned char remainder = 1;
5217  for (i = 0; i < ARRAY_SIZE(quotient->bitsnum) && remainder; i++) {
5218  ULONGLONG digit = quotient->bitsnum[i] + 1;
5219  remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
5220  quotient->bitsnum[i] = digit & 0xFFFFFFFF;
5221  }
5222  }
5223  memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5224  } else {
5225  VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
5226  memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
5227  }
5228  tempquotientscale = ++remainderscale;
5229  } while (!underflow && !VARIANT_int_iszero(remainderplusquotient + 4, 4));
5230 
5231  /* quotient scale might now be negative (extremely big number). If, so, try
5232  to multiply quotient by 10 (without overflowing), while adjusting the scale,
5233  until scale is 0. If this cannot be done, it is a real overflow.
5234  */
5235  while (r_overflow == S_OK && quotientscale < 0) {
5236  memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5237  memcpy(remainderplusquotient, quotient->bitsnum, sizeof(quotient->bitsnum));
5238  VARIANT_int_mulbychar(remainderplusquotient, ARRAY_SIZE(remainderplusquotient), 10);
5239  if (VARIANT_int_iszero(remainderplusquotient + ARRAY_SIZE(quotient->bitsnum),
5240  ARRAY_SIZE(remainderplusquotient) - ARRAY_SIZE(quotient->bitsnum))) {
5241  quotientscale++;
5242  memcpy(quotient->bitsnum, remainderplusquotient, sizeof(quotient->bitsnum));
5243  } else r_overflow = DISP_E_OVERFLOW;
5244  }
5245  if (r_overflow == S_OK) {
5246  if (quotientscale <= 255) quotient->scale = quotientscale;
5247  else VARIANT_DI_clear(quotient);
5248  }
5249  }
5250  return r_overflow;
5251 }
5252 
5253 /* This procedure receives a VARIANT_DI with a defined mantissa and sign, but
5254  with an undefined scale, which will be assigned to (if possible). It also
5255  receives an exponent of 2. This procedure will then manipulate the mantissa
5256  and calculate a corresponding scale, so that the exponent2 value is assimilated
5257  into the VARIANT_DI and is therefore no longer necessary. Returns S_OK if
5258  successful, or DISP_E_OVERFLOW if the represented value is too big to fit into
5259  a DECIMAL. */
5260 static HRESULT VARIANT_DI_normalize(VARIANT_DI * val, int exponent2, BOOL isDouble)
5261 {
5262  HRESULT hres = S_OK;
5263  int exponent5, exponent10;
5264 
5265  /* A factor of 2^exponent2 is equivalent to (10^exponent2)/(5^exponent2), and
5266  thus equal to (5^-exponent2)*(10^exponent2). After all manipulations,
5267  exponent10 might be used to set the VARIANT_DI scale directly. However,
5268  the value of 5^-exponent5 must be assimilated into the VARIANT_DI. */
5269  exponent5 = -exponent2;
5270  exponent10 = exponent2;
5271 
5272  /* Handle exponent5 > 0 */
5273  while (exponent5 > 0) {
5274  char bPrevCarryBit;
5275  char bCurrCarryBit;
5276 
5277  /* In order to multiply the value represented by the VARIANT_DI by 5, it
5278  is best to multiply by 10/2. Therefore, exponent10 is incremented, and
5279  somehow the mantissa should be divided by 2. */
5280  if ((val->bitsnum[0] & 1) == 0) {
5281  /* The mantissa is divisible by 2. Therefore the division can be done
5282  without losing significant digits. */
5283  exponent10++; exponent5--;
5284 
5285  /* Shift right */
5286  bPrevCarryBit = val->bitsnum[2] & 1;
5287  val->bitsnum[2] >>= 1;
5288  bCurrCarryBit = val->bitsnum[1] & 1;
5289  val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
5290  val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
5291  } else {
5292  /* The mantissa is NOT divisible by 2. Therefore the mantissa should
5293  be multiplied by 5, unless the multiplication overflows. */
5294  DWORD temp_bitsnum[3];
5295 
5296  exponent5--;
5297 
5298  memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5299  if (0 == VARIANT_int_mulbychar(temp_bitsnum, 3, 5)) {
5300  /* Multiplication succeeded without overflow, so copy result back
5301  into VARIANT_DI */
5302  memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5303 
5304  /* Mask out 3 extraneous bits introduced by the multiply */
5305  } else {
5306  /* Multiplication by 5 overflows. The mantissa should be divided
5307  by 2, and therefore will lose significant digits. */
5308  exponent10++;
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  }
5317  }
5318  }
5319 
5320  /* Handle exponent5 < 0 */
5321  while (exponent5 < 0) {
5322  /* In order to divide the value represented by the VARIANT_DI by 5, it
5323  is best to multiply by 2/10. Therefore, exponent10 is decremented,
5324  and the mantissa should be multiplied by 2 */
5325  if ((val->bitsnum[2] & 0x80000000) == 0) {
5326  /* The mantissa can withstand a shift-left without overflowing */
5327  exponent10--; exponent5++;
5328  VARIANT_int_shiftleft(val->bitsnum, 3, 1);
5329  } else {
5330  /* The mantissa would overflow if shifted. Therefore it should be
5331  directly divided by 5. This will lose significant digits, unless
5332  by chance the mantissa happens to be divisible by 5 */
5333  exponent5++;
5334  VARIANT_int_divbychar(val->bitsnum, 3, 5);
5335  }
5336  }
5337 
5338  /* At this point, the mantissa has assimilated the exponent5, but the
5339  exponent10 might not be suitable for assignment. The exponent10 must be
5340  in the range [-DEC_MAX_SCALE..0], so the mantissa must be scaled up or
5341  down appropriately. */
5342  while (hres == S_OK && exponent10 > 0) {
5343  /* In order to bring exponent10 down to 0, the mantissa should be
5344  multiplied by 10 to compensate. If the exponent10 is too big, this
5345  will cause the mantissa to overflow. */
5346  if (0 == VARIANT_int_mulbychar(val->bitsnum, 3, 10)) {
5347  exponent10--;
5348  } else {
5350  }
5351  }
5352  while (exponent10 < -DEC_MAX_SCALE) {
5353  int rem10;
5354  /* In order to bring exponent up to -DEC_MAX_SCALE, the mantissa should
5355  be divided by 10 to compensate. If the exponent10 is too small, this
5356  will cause the mantissa to underflow and become 0 */
5357  rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5358  exponent10++;
5359  if (VARIANT_int_iszero(val->bitsnum, 3)) {
5360  /* Underflow, unable to keep dividing */
5361  exponent10 = 0;
5362  } else if (rem10 >= 5) {
5363  DWORD x = 1;
5364  VARIANT_int_add(val->bitsnum, 3, &x, 1);
5365  }
5366  }
5367  /* This step is required in order to remove excess bits of precision from the
5368  end of the bit representation, down to the precision guaranteed by the
5369  floating point number. */
5370  if (isDouble) {
5371  while (exponent10 < 0 && (val->bitsnum[2] != 0 || (val->bitsnum[1] & 0xFFE00000) != 0)) {
5372  int rem10;
5373 
5374  rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5375  exponent10++;
5376  if (rem10 >= 5) {
5377  DWORD x = 1;
5378  VARIANT_int_add(val->bitsnum, 3, &x, 1);
5379  }
5380  }
5381  } else {
5382  while (exponent10 < 0 && (val->bitsnum[2] != 0 || val->bitsnum[1] != 0 ||
5383  (val->bitsnum[2] == 0 && val->bitsnum[1] == 0 && (val->bitsnum[0] & 0xFF000000) != 0))) {
5384  int rem10;
5385 
5386  rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5387  exponent10++;
5388  if (rem10 >= 5) {
5389  DWORD x = 1;
5390  VARIANT_int_add(val->bitsnum, 3, &x, 1);
5391  }
5392  }
5393  }
5394  /* Remove multiples of 10 from the representation */
5395  while (exponent10 < 0) {
5396  DWORD temp_bitsnum[3];
5397 
5398  memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5399  if (0 == VARIANT_int_divbychar(temp_bitsnum, 3, 10)) {
5400  exponent10++;
5401  memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5402  } else break;
5403  }
5404 
5405  /* Scale assignment */
5406  if (hres == S_OK) val->scale = -exponent10;
5407 
5408  return hres;
5409 }
5410 
5411 typedef union
5412 {
5413  struct
5414  {
5415  unsigned int m : 23;
5416  unsigned int exp_bias : 8;
5417  unsigned int sign : 1;
5418  } i;
5419  float f;
5420 } R4_FIELDS;
5421 
5422 /* Convert a 32-bit floating point number into a DECIMAL, without using an
5423  intermediate string step. */
5425 {
5426  HRESULT hres = S_OK;
5427  R4_FIELDS fx;
5428 
5429  fx.f = source;
5430 
5431  /* Detect special cases */
5432  if (fx.i.m == 0 && fx.i.exp_bias == 0) {
5433  /* Floating-point zero */
5435  } else if (fx.i.m == 0 && fx.i.exp_bias == 0xFF) {
5436  /* Floating-point infinity */
5438  } else if (fx.i.exp_bias == 0xFF) {
5439  /* Floating-point NaN */
5441  } else {
5442  int exponent2;
5444 
5445  exponent2 = fx.i.exp_bias - 127; /* Get unbiased exponent */
5446  dest->sign = fx.i.sign; /* Sign is simply copied */
5447 
5448  /* Copy significant bits to VARIANT_DI mantissa */
5449  dest->bitsnum[0] = fx.i.m;
5450  dest->bitsnum[0] &= 0x007FFFFF;
5451  if (fx.i.exp_bias == 0) {
5452  /* Denormalized number - correct exponent */
5453  exponent2++;
5454  } else {
5455  /* Add hidden bit to mantissa */
5456  dest->bitsnum[0] |= 0x00800000;
5457  }
5458 
5459  /* The act of copying a FP mantissa as integer bits is equivalent to
5460  shifting left the mantissa 23 bits. The exponent2 is reduced to
5461  compensate. */
5462  exponent2 -= 23;
5463 
5464  hres = VARIANT_DI_normalize(dest, exponent2, FALSE);
5465  }
5466 
5467  return hres;
5468 }
5469 
5470 typedef union
5471 {
5472  struct
5473  {
5474  unsigned int m_lo : 32; /* 52 bits of precision */
5475  unsigned int m_hi : 20;
5476  unsigned int exp_bias : 11; /* bias == 1023 */
5477  unsigned int sign : 1;
5478  } i;
5479  double d;
5480 } R8_FIELDS;
5481 
5482 /* Convert a 64-bit floating point number into a DECIMAL, without using an
5483  intermediate string step. */
5485 {
5486  HRESULT hres = S_OK;
5487  R8_FIELDS fx;
5488 
5489  fx.d = source;
5490 
5491  /* Detect special cases */
5492  if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0) {
5493  /* Floating-point zero */
5495  } else if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0x7FF) {
5496  /* Floating-point infinit