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