xref: /reactos/dll/win32/oleaut32/vartype.c (revision 845faec4)
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 
33 WINE_DEFAULT_DEBUG_CHANNEL(variant);
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 = sizeof(rgb) / sizeof(BYTE);
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,
115                                 VARTYPE vt, DWORD dwFlags)
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 */
175 BOTHTST(BYTE, SHORT, VarUI1FromI2, UI1_MIN, UI1_MAX)
176 SIMPLE(BYTE, VARIANT_BOOL, VarUI1FromBool)
177 NEGTST(BYTE, signed char, VarUI1FromI1)
178 POSTST(BYTE, USHORT, VarUI1FromUI2, UI1_MAX)
179 BOTHTST(BYTE, LONG, VarUI1FromI4, UI1_MIN, UI1_MAX)
180 POSTST(BYTE, ULONG, VarUI1FromUI4, UI1_MAX)
181 BOTHTST(BYTE, LONG64, VarUI1FromI8, UI1_MIN, UI1_MAX)
182 POSTST(BYTE, ULONG64, VarUI1FromUI8, UI1_MAX)
183 
184 /* I2 */
185 SIMPLE(SHORT, BYTE, VarI2FromUI1)
186 BOTHTST(SHORT, LONG, VarI2FromI4, I2_MIN, I2_MAX)
187 SIMPLE(SHORT, VARIANT_BOOL, VarI2FromBool)
188 SIMPLE(SHORT, signed char, VarI2FromI1)
189 POSTST(SHORT, USHORT, VarI2FromUI2, I2_MAX)
190 POSTST(SHORT, ULONG, VarI2FromUI4, I2_MAX)
191 BOTHTST(SHORT, LONG64, VarI2FromI8, I2_MIN, I2_MAX)
192 POSTST(SHORT, ULONG64, VarI2FromUI8, I2_MAX)
193 
194 /* UI2 */
195 SIMPLE(USHORT, BYTE, VarUI2FromUI1)
196 NEGTST(USHORT, SHORT, VarUI2FromI2)
197 BOTHTST(USHORT, LONG, VarUI2FromI4, UI2_MIN, UI2_MAX)
198 SIMPLE(USHORT, VARIANT_BOOL, VarUI2FromBool)
199 NEGTST(USHORT, signed char, VarUI2FromI1)
200 POSTST(USHORT, ULONG, VarUI2FromUI4, UI2_MAX)
201 BOTHTST(USHORT, LONG64, VarUI2FromI8, UI2_MIN, UI2_MAX)
202 POSTST(USHORT, ULONG64, VarUI2FromUI8, UI2_MAX)
203 
204 /* I4 */
205 SIMPLE(LONG, BYTE, VarI4FromUI1)
206 SIMPLE(LONG, SHORT, VarI4FromI2)
207 SIMPLE(LONG, VARIANT_BOOL, VarI4FromBool)
208 SIMPLE(LONG, signed char, VarI4FromI1)
209 SIMPLE(LONG, USHORT, VarI4FromUI2)
210 POSTST(LONG, ULONG, VarI4FromUI4, I4_MAX)
211 BOTHTST(LONG, LONG64, VarI4FromI8, I4_MIN, I4_MAX)
212 POSTST(LONG, ULONG64, VarI4FromUI8, I4_MAX)
213 
214 /* UI4 */
215 SIMPLE(ULONG, BYTE, VarUI4FromUI1)
216 NEGTST(ULONG, SHORT, VarUI4FromI2)
217 NEGTST(ULONG, LONG, VarUI4FromI4)
218 SIMPLE(ULONG, VARIANT_BOOL, VarUI4FromBool)
219 NEGTST(ULONG, signed char, VarUI4FromI1)
220 SIMPLE(ULONG, USHORT, VarUI4FromUI2)
221 BOTHTST(ULONG, LONG64, VarUI4FromI8, UI4_MIN, UI4_MAX)
222 POSTST(ULONG, ULONG64, VarUI4FromUI8, UI4_MAX)
223 
224 /* I8 */
225 SIMPLE(LONG64, BYTE, VarI8FromUI1)
226 SIMPLE(LONG64, SHORT, VarI8FromI2)
227 SIMPLE(LONG64, signed char, VarI8FromI1)
228 SIMPLE(LONG64, USHORT, VarI8FromUI2)
229 SIMPLE(LONG64, ULONG, VarI8FromUI4)
230 POSTST(LONG64, ULONG64, VarI8FromUI8, I8_MAX)
231 
232 /* UI8 */
233 SIMPLE(ULONG64, BYTE, VarUI8FromUI1)
234 NEGTST(ULONG64, SHORT, VarUI8FromI2)
235 NEGTST(ULONG64, signed char, VarUI8FromI1)
236 SIMPLE(ULONG64, USHORT, VarUI8FromUI2)
237 SIMPLE(ULONG64, ULONG, VarUI8FromUI4)
238 NEGTST(ULONG64, LONG64, VarUI8FromI8)
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  */
589 HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
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  */
608 HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
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  */
628 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
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  */
675 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
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  */
697 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
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  */
719 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
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  */
740 HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
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  */
757 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
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  */
795 HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
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  */
814 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
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  */
833 HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
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  */
859 HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
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  */
878 HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
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  */
899 HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
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  */
917 HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
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  */
935 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
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  */
977 HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
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  */
998 HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
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  */
1020 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
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  */
1041 HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
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  */
1058 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
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  */
1093 HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
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  */
1111 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
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  */
1130 HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
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  */
1155 HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
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  */
1173 HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
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  */
1193 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
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  */
1211 HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
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  */
1229 HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
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  */
1247 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
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  */
1289 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
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  */
1310 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
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  */
1334 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
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  */
1355 HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
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  */
1372 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
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  */
1408 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
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  */
1427 HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
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  */
1452 HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
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  */
1470 HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
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  */
1490 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
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  */
1509 HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
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  */
1527 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
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  */
1569 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
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  */
1588 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
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  */
1610 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
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  */
1631 HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
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  */
1648 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
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  */
1682 HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
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  */
1700 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
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  */
1719 HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
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  */
1744 HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
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  */
1762 HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
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  */
1782 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
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  */
1800 HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
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  */
1818 HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
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  */
1836 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
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  */
1878 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
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  */
1896 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
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  */
1919 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
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  */
1940 HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
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  */
1957 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
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  */
1992 HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
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  */
2011 HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
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  */
2036 HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
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  */
2054 HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
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  */
2074 HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
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  */
2092 HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
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  */
2111 HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
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  */
2173 HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
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  */
2204 HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
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  */
2226 HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
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  */
2247 HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
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  */
2264 HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
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  */
2298 HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
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  */
2315 HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
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  */
2334 HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
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  */
2377 HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
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  */
2398 HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
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  */
2415 HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
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  */
2432 HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
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  */
2450 HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
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  */
2497 HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
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  */
2532 HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
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  */
2554 HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
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  */
2575 HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
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  */
2593 HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
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  */
2627 HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
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  */
2644 HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
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  */
2669 HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
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,
3402   CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
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  */
3419 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
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  */
3440 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
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  */
3461 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
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  */
3482 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
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  */
3552 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
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  */
3574 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
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  */
3619 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
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  */
3661 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
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  */
3682 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
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  */
3703 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
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  */
3741 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
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  */
3763 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
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(const CY cyLeft, const 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(const CY cyLeft, const 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(const 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(const CY cyLeft, const 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(const 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(const 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(const 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(const 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(const 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(const CY cyLeft, const 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(const 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(const 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  */
4096 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
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  */
4113 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
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  */
4130 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
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 
4158 static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI * dest);
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  */
4177 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
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  */
4221 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
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  */
4238 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
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  */
4272 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
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  */
4291 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
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  */
4311 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
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  */
4357 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
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  */
4374 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
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  */
4395 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
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  */
4428 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
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, sizeof(di.bitsnum)/sizeof(DWORD)))
4500   {
4501     remainder = VARIANT_int_divbychar(di.bitsnum, sizeof(di.bitsnum)/sizeof(DWORD), 10);
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 < sizeof(di.bitsnum)/sizeof(DWORD) && 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 */
4684 static void VARIANT_DI_clear(VARIANT_DI * i)
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 
4736     VARIANT_DI_clear(result);
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 = sizeof(a->bitsnum)/sizeof(DWORD) - 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 < sizeof(b->bitsnum)/sizeof(DWORD); 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(
4793             running + sizeof(result->bitsnum) / sizeof(DWORD),
4794             (sizeof(running) - sizeof(result->bitsnum)) / sizeof(DWORD))) {
4795 
4796             remainder = VARIANT_int_divbychar(running, sizeof(running) / sizeof(DWORD), 10);
4797             if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
4798             result->scale--;
4799         }
4800 
4801         /* round up the result - native oleaut32 does this */
4802         if (remainder >= 5) {
4803             unsigned int i;
4804             for (remainder = 1, i = 0; i < sizeof(running)/sizeof(DWORD) && remainder; i++) {
4805                 ULONGLONG digit = running[i] + 1;
4806                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4807                 running[i] = digit & 0xFFFFFFFF;
4808             }
4809         }
4810 
4811         /* Signal overflow if scale == 0 and 256-bit result still overflows,
4812            and copy result bits into result structure
4813         */
4814         r_overflow = !VARIANT_int_iszero(
4815             running + sizeof(result->bitsnum)/sizeof(DWORD),
4816             (sizeof(running) - sizeof(result->bitsnum))/sizeof(DWORD));
4817         memcpy(result->bitsnum, running, sizeof(result->bitsnum));
4818     }
4819     return r_overflow;
4820 }
4821 
4822 /* cast DECIMAL into string. Any scale should be handled properly. en_US locale is
4823    hardcoded (period for decimal separator, dash as negative sign). Returns TRUE for
4824    success, FALSE if insufficient space in output buffer.
4825  */
4826 static BOOL VARIANT_DI_tostringW(const VARIANT_DI * a, WCHAR * s, unsigned int n)
4827 {
4828     BOOL overflow = FALSE;
4829     DWORD quotient[3];
4830     unsigned char remainder;
4831     unsigned int i;
4832 
4833     /* place negative sign */
4834     if (!VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD)) && a->sign) {
4835         if (n > 0) {
4836             *s++ = '-';
4837             n--;
4838         }
4839         else overflow = TRUE;
4840     }
4841 
4842     /* prepare initial 0 */
4843     if (!overflow) {
4844         if (n >= 2) {
4845             s[0] = '0';
4846             s[1] = '\0';
4847         } else overflow = TRUE;
4848     }
4849 
4850     i = 0;
4851     memcpy(quotient, a->bitsnum, sizeof(a->bitsnum));
4852     while (!overflow && !VARIANT_int_iszero(quotient, sizeof(quotient) / sizeof(DWORD))) {
4853         remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
4854         if (i + 2 > n) {
4855             overflow = TRUE;
4856         } else {
4857             s[i++] = '0' + remainder;
4858             s[i] = '\0';
4859         }
4860     }
4861 
4862     if (!overflow && !VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD))) {
4863 
4864         /* reverse order of digits */
4865         WCHAR * x = s; WCHAR * y = s + i - 1;
4866         while (x < y) {
4867             *x ^= *y;
4868             *y ^= *x;
4869             *x++ ^= *y--;
4870         }
4871 
4872         /* check for decimal point. "i" now has string length */
4873         if (i <= a->scale) {
4874             unsigned int numzeroes = a->scale + 1 - i;
4875             if (i + 1 + numzeroes >= n) {
4876                 overflow = TRUE;
4877             } else {
4878                 memmove(s + numzeroes, s, (i + 1) * sizeof(WCHAR));
4879                 i += numzeroes;
4880                 while (numzeroes > 0) {
4881                     s[--numzeroes] = '0';
4882                 }
4883             }
4884         }
4885 
4886         /* place decimal point */
4887         if (a->scale > 0) {
4888             unsigned int periodpos = i - a->scale;
4889             if (i + 2 >= n) {
4890                 overflow = TRUE;
4891             } else {
4892                 memmove(s + periodpos + 1, s + periodpos, (i + 1 - periodpos) * sizeof(WCHAR));
4893                 s[periodpos] = '.'; i++;
4894 
4895                 /* remove extra zeros at the end, if any */
4896                 while (s[i - 1] == '0') s[--i] = '\0';
4897                 if (s[i - 1] == '.') s[--i] = '\0';
4898             }
4899         }
4900     }
4901 
4902     return !overflow;
4903 }
4904 
4905 /* shift the bits of a DWORD array to the left. p[0] is assumed LSB */
4906 static void VARIANT_int_shiftleft(DWORD * p, unsigned int n, unsigned int shift)
4907 {
4908     DWORD shifted;
4909     unsigned int i;
4910 
4911     /* shift whole DWORDs to the left */
4912     while (shift >= 32)
4913     {
4914         memmove(p + 1, p, (n - 1) * sizeof(DWORD));
4915         *p = 0; shift -= 32;
4916     }
4917 
4918     /* shift remainder (1..31 bits) */
4919     shifted = 0;
4920     if (shift > 0) for (i = 0; i < n; i++)
4921     {
4922         DWORD b;
4923         b = p[i] >> (32 - shift);
4924         p[i] = (p[i] << shift) | shifted;
4925         shifted = b;
4926     }
4927 }
4928 
4929 /* add the (unsigned) numbers stored in two DWORD arrays with LSB at index 0.
4930    Value at v is incremented by the value at p. Any size is supported, provided
4931    that v is not shorter than p. Any unapplied carry is returned as a result.
4932  */
4933 static unsigned char VARIANT_int_add(DWORD * v, unsigned int nv, const DWORD * p,
4934     unsigned int np)
4935 {
4936     unsigned char carry = 0;
4937 
4938     if (nv >= np) {
4939         ULONGLONG sum;
4940         unsigned int i;
4941 
4942         for (i = 0; i < np; i++) {
4943             sum = (ULONGLONG)v[i]
4944                 + (ULONGLONG)p[i]
4945                 + (ULONGLONG)carry;
4946             v[i] = sum & 0xffffffff;
4947             carry = sum >> 32;
4948         }
4949         for (; i < nv && carry; i++) {
4950             sum = (ULONGLONG)v[i]
4951                 + (ULONGLONG)carry;
4952             v[i] = sum & 0xffffffff;
4953             carry = sum >> 32;
4954         }
4955     }
4956     return carry;
4957 }
4958 
4959 /* perform integral division with operand p as dividend. Parameter n indicates
4960    number of available DWORDs in divisor p, but available space in p must be
4961    actually at least 2 * n DWORDs, because the remainder of the integral
4962    division is built in the next n DWORDs past the start of the quotient. This
4963    routine replaces the dividend in p with the quotient, and appends n
4964    additional DWORDs for the remainder.
4965 
4966    Thanks to Lee & Mark Atkinson for their book _Using_C_ (my very first book on
4967    C/C++ :-) where the "longhand binary division" algorithm was exposed for the
4968    source code to the VLI (Very Large Integer) division operator. This algorithm
4969    was then heavily modified by me (Alex Villacis Lasso) in order to handle
4970    variably-scaled integers such as the MS DECIMAL representation.
4971  */
4972 static void VARIANT_int_div(DWORD * p, unsigned int n, const DWORD * divisor,
4973     unsigned int dn)
4974 {
4975     unsigned int i;
4976     DWORD tempsub[8];
4977     DWORD * negdivisor = tempsub + n;
4978 
4979     /* build 2s-complement of divisor */
4980     for (i = 0; i < n; i++) negdivisor[i] = (i < dn) ? ~divisor[i] : 0xFFFFFFFF;
4981     p[n] = 1;
4982     VARIANT_int_add(negdivisor, n, p + n, 1);
4983     memset(p + n, 0, n * sizeof(DWORD));
4984 
4985     /* skip all leading zero DWORDs in quotient */
4986     for (i = 0; i < n && !p[n - 1]; i++) VARIANT_int_shiftleft(p, n, 32);
4987     /* i is now number of DWORDs left to process */
4988     for (i <<= 5; i < (n << 5); i++) {
4989         VARIANT_int_shiftleft(p, n << 1, 1);    /* shl quotient+remainder */
4990 
4991         /* trial subtraction */
4992         memcpy(tempsub, p + n, n * sizeof(DWORD));
4993         VARIANT_int_add(tempsub, n, negdivisor, n);
4994 
4995         /* check whether result of subtraction was negative */
4996         if ((tempsub[n - 1] & 0x80000000) == 0) {
4997             memcpy(p + n, tempsub, n * sizeof(DWORD));
4998             p[0] |= 1;
4999         }
5000     }
5001 }
5002 
5003 /* perform integral multiplication by a byte operand. Used for scaling by 10 */
5004 static unsigned char VARIANT_int_mulbychar(DWORD * p, unsigned int n, unsigned char m)
5005 {
5006     unsigned int i;
5007     ULONG iOverflowMul;
5008 
5009     for (iOverflowMul = 0, i = 0; i < n; i++)
5010         p[i] = VARIANT_Mul(p[i], m, &iOverflowMul);
5011     return (unsigned char)iOverflowMul;
5012 }
5013 
5014 /* increment value in A by the value indicated in B, with scale adjusting.
5015    Modifies parameters by adjusting scales. Returns 0 if addition was
5016    successful, nonzero if a parameter underflowed before it could be
5017    successfully used in the addition.
5018  */
5019 static int VARIANT_int_addlossy(
5020     DWORD * a, int * ascale, unsigned int an,
5021     DWORD * b, int * bscale, unsigned int bn)
5022 {
5023     int underflow = 0;
5024 
5025     if (VARIANT_int_iszero(a, an)) {
5026         /* if A is zero, copy B into A, after removing digits */
5027         while (bn > an && !VARIANT_int_iszero(b + an, bn - an)) {
5028             VARIANT_int_divbychar(b, bn, 10);
5029             (*bscale)--;
5030         }
5031         memcpy(a, b, an * sizeof(DWORD));
5032         *ascale = *bscale;
5033     } else if (!VARIANT_int_iszero(b, bn)) {
5034         unsigned int tn = an + 1;
5035         DWORD t[5];
5036 
5037         if (bn + 1 > tn) tn = bn + 1;
5038         if (*ascale != *bscale) {
5039             /* first (optimistic) try - try to scale down the one with the bigger
5040                scale, while this number is divisible by 10 */
5041             DWORD * digitchosen;
5042             unsigned int nchosen;
5043             int * scalechosen;
5044             int targetscale;
5045 
5046             if (*ascale < *bscale) {
5047                 targetscale = *ascale;
5048                 scalechosen = bscale;
5049                 digitchosen = b;
5050                 nchosen = bn;
5051             } else {
5052                 targetscale = *bscale;
5053                 scalechosen = ascale;
5054                 digitchosen = a;
5055                 nchosen = an;
5056             }
5057             memset(t, 0, tn * sizeof(DWORD));
5058             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5059 
5060             /* divide by 10 until target scale is reached */
5061             while (*scalechosen > targetscale) {
5062                 unsigned char remainder = VARIANT_int_divbychar(t, tn, 10);
5063                 if (!remainder) {
5064                     (*scalechosen)--;
5065                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5066                 } else break;
5067             }
5068         }
5069 
5070         if (*ascale != *bscale) {
5071             DWORD * digitchosen;
5072             unsigned int nchosen;
5073             int * scalechosen;
5074             int targetscale;
5075 
5076             /* try to scale up the one with the smaller scale */
5077             if (*ascale > *bscale) {
5078                 targetscale = *ascale;
5079                 scalechosen = bscale;
5080                 digitchosen = b;
5081                 nchosen = bn;
5082             } else {
5083                 targetscale = *bscale;
5084                 scalechosen = ascale;
5085                 digitchosen = a;
5086                 nchosen = an;
5087             }
5088             memset(t, 0, tn * sizeof(DWORD));
5089             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5090 
5091             /* multiply by 10 until target scale is reached, or
5092                significant bytes overflow the number
5093              */
5094             while (*scalechosen < targetscale && t[nchosen] == 0) {
5095                 VARIANT_int_mulbychar(t, tn, 10);
5096                 if (t[nchosen] == 0) {
5097                     /* still does not overflow */
5098                     (*scalechosen)++;
5099                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5100                 }
5101             }
5102         }
5103 
5104         if (*ascale != *bscale) {
5105             /* still different? try to scale down the one with the bigger scale
5106                (this *will* lose significant digits) */
5107             DWORD * digitchosen;
5108             unsigned int nchosen;
5109             int * scalechosen;
5110             int targetscale;
5111 
5112             if (*ascale < *bscale) {
5113                 targetscale = *ascale;
5114                 scalechosen = bscale;
5115                 digitchosen = b;
5116                 nchosen = bn;
5117             } else {
5118                 targetscale = *bscale;
5119                 scalechosen = ascale;
5120                 digitchosen = a;
5121                 nchosen = an;
5122             }
5123             memset(t, 0, tn * sizeof(DWORD));
5124             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5125 
5126             /* divide by 10 until target scale is reached */
5127             while (*scalechosen > targetscale) {
5128                 VARIANT_int_divbychar(t, tn, 10);
5129                 (*scalechosen)--;
5130                 memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5131             }
5132         }
5133 
5134         /* check whether any of the operands still has significant digits
5135            (underflow case 1)
5136          */
5137         if (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn)) {
5138             underflow = 1;
5139         } else {
5140             /* at this step, both numbers have the same scale and can be added
5141                as integers. However, the result might not fit in A, so further
5142                scaling down might be necessary.
5143              */
5144             while (!underflow) {
5145                 memset(t, 0, tn * sizeof(DWORD));
5146                 memcpy(t, a, an * sizeof(DWORD));
5147 
5148                 VARIANT_int_add(t, tn, b, bn);
5149                 if (VARIANT_int_iszero(t + an, tn - an)) {
5150                     /* addition was successful */
5151                     memcpy(a, t, an * sizeof(DWORD));
5152                     break;
5153                 } else {
5154                     /* addition overflowed - remove significant digits
5155                        from both operands and try again */
5156                     VARIANT_int_divbychar(a, an, 10); (*ascale)--;
5157                     VARIANT_int_divbychar(b, bn, 10); (*bscale)--;
5158                     /* check whether any operand keeps significant digits after
5159                        scaledown (underflow case 2)
5160                      */
5161                     underflow = (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn));
5162                 }
5163             }
5164         }
5165     }
5166     return underflow;
5167 }
5168 
5169 /* perform complete DECIMAL division in the internal representation. Returns
5170    0 if the division was completed (even if quotient is set to 0), or nonzero
5171    in case of quotient overflow.
5172  */
5173 static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * divisor,
5174                               VARIANT_DI * quotient, BOOL round_remainder)
5175 {
5176     HRESULT r_overflow = S_OK;
5177 
5178     if (VARIANT_int_iszero(divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD))) {
5179         /* division by 0 */
5180         r_overflow = DISP_E_DIVBYZERO;
5181     } else if (VARIANT_int_iszero(dividend->bitsnum, sizeof(dividend->bitsnum)/sizeof(DWORD))) {
5182         VARIANT_DI_clear(quotient);
5183     } else {
5184         int quotientscale, remainderscale, tempquotientscale;
5185         DWORD remainderplusquotient[8];
5186         int underflow;
5187 
5188         quotientscale = remainderscale = (int)dividend->scale - (int)divisor->scale;
5189         tempquotientscale = quotientscale;
5190         VARIANT_DI_clear(quotient);
5191         quotient->sign = (dividend->sign ^ divisor->sign) ? 1 : 0;
5192 
5193         /*  The following strategy is used for division
5194             1) if there was a nonzero remainder from previous iteration, use it as
5195                dividend for this iteration, else (for first iteration) use intended
5196                dividend
5197             2) perform integer division in temporary buffer, develop quotient in
5198                low-order part, remainder in high-order part
5199             3) add quotient from step 2 to final result, with possible loss of
5200                significant digits
5201             4) multiply integer part of remainder by 10, while incrementing the
5202                scale of the remainder. This operation preserves the intended value
5203                of the remainder.
5204             5) loop to step 1 until one of the following is true:
5205                 a) remainder is zero (exact division achieved)
5206                 b) addition in step 3 fails to modify bits in quotient (remainder underflow)
5207          */
5208         memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5209         memcpy(remainderplusquotient, dividend->bitsnum, sizeof(dividend->bitsnum));
5210         do {
5211             VARIANT_int_div(
5212                 remainderplusquotient, 4,
5213                 divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD));
5214             underflow = VARIANT_int_addlossy(
5215                 quotient->bitsnum, &quotientscale, sizeof(quotient->bitsnum) / sizeof(DWORD),
5216                 remainderplusquotient, &tempquotientscale, 4);
5217             if (round_remainder) {
5218                 if(remainderplusquotient[4] >= 5){
5219                     unsigned int i;
5220                     unsigned char remainder = 1;
5221                     for (i = 0; i < sizeof(quotient->bitsnum) / sizeof(DWORD) && remainder; i++) {
5222                         ULONGLONG digit = quotient->bitsnum[i] + 1;
5223                         remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
5224                         quotient->bitsnum[i] = digit & 0xFFFFFFFF;
5225                     }
5226                 }
5227                 memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5228             } else {
5229                 VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
5230                 memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
5231             }
5232             tempquotientscale = ++remainderscale;
5233         } while (!underflow && !VARIANT_int_iszero(remainderplusquotient + 4, 4));
5234 
5235         /* quotient scale might now be negative (extremely big number). If, so, try
5236            to multiply quotient by 10 (without overflowing), while adjusting the scale,
5237            until scale is 0. If this cannot be done, it is a real overflow.
5238          */
5239         while (r_overflow == S_OK && quotientscale < 0) {
5240             memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5241             memcpy(remainderplusquotient, quotient->bitsnum, sizeof(quotient->bitsnum));
5242             VARIANT_int_mulbychar(remainderplusquotient, sizeof(remainderplusquotient)/sizeof(DWORD), 10);
5243             if (VARIANT_int_iszero(remainderplusquotient + sizeof(quotient->bitsnum)/sizeof(DWORD),
5244                 (sizeof(remainderplusquotient) - sizeof(quotient->bitsnum))/sizeof(DWORD))) {
5245                 quotientscale++;
5246                 memcpy(quotient->bitsnum, remainderplusquotient, sizeof(quotient->bitsnum));
5247             } else r_overflow = DISP_E_OVERFLOW;
5248         }
5249         if (r_overflow == S_OK) {
5250             if (quotientscale <= 255) quotient->scale = quotientscale;
5251             else VARIANT_DI_clear(quotient);
5252         }
5253     }
5254     return r_overflow;
5255 }
5256 
5257 /* This procedure receives a VARIANT_DI with a defined mantissa and sign, but
5258    with an undefined scale, which will be assigned to (if possible). It also
5259    receives an exponent of 2. This procedure will then manipulate the mantissa
5260    and calculate a corresponding scale, so that the exponent2 value is assimilated
5261    into the VARIANT_DI and is therefore no longer necessary. Returns S_OK if
5262    successful, or DISP_E_OVERFLOW if the represented value is too big to fit into
5263    a DECIMAL. */
5264 static HRESULT VARIANT_DI_normalize(VARIANT_DI * val, int exponent2, BOOL isDouble)
5265 {
5266     HRESULT hres = S_OK;
5267     int exponent5, exponent10;
5268 
5269     /* A factor of 2^exponent2 is equivalent to (10^exponent2)/(5^exponent2), and
5270        thus equal to (5^-exponent2)*(10^exponent2). After all manipulations,
5271        exponent10 might be used to set the VARIANT_DI scale directly. However,
5272        the value of 5^-exponent5 must be assimilated into the VARIANT_DI. */
5273     exponent5 = -exponent2;
5274     exponent10 = exponent2;
5275 
5276     /* Handle exponent5 > 0 */
5277     while (exponent5 > 0) {
5278         char bPrevCarryBit;
5279         char bCurrCarryBit;
5280 
5281         /* In order to multiply the value represented by the VARIANT_DI by 5, it
5282            is best to multiply by 10/2. Therefore, exponent10 is incremented, and
5283            somehow the mantissa should be divided by 2.  */
5284         if ((val->bitsnum[0] & 1) == 0) {
5285             /* The mantissa is divisible by 2. Therefore the division can be done
5286                without losing significant digits. */
5287             exponent10++; exponent5--;
5288 
5289             /* Shift right */
5290             bPrevCarryBit = val->bitsnum[2] & 1;
5291             val->bitsnum[2] >>= 1;
5292             bCurrCarryBit = val->bitsnum[1] & 1;
5293             val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
5294             val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
5295         } else {
5296             /* The mantissa is NOT divisible by 2. Therefore the mantissa should
5297                be multiplied by 5, unless the multiplication overflows. */
5298             DWORD temp_bitsnum[3];
5299 
5300             exponent5--;
5301 
5302             memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5303             if (0 == VARIANT_int_mulbychar(temp_bitsnum, 3, 5)) {
5304                 /* Multiplication succeeded without overflow, so copy result back
5305                    into VARIANT_DI */
5306                 memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5307 
5308                 /* Mask out 3 extraneous bits introduced by the multiply */
5309             } else {
5310                 /* Multiplication by 5 overflows. The mantissa should be divided
5311                    by 2, and therefore will lose significant digits. */
5312                 exponent10++;
5313 
5314                 /* Shift right */
5315                 bPrevCarryBit = val->bitsnum[2] & 1;
5316                 val->bitsnum[2] >>= 1;
5317                 bCurrCarryBit = val->bitsnum[1] & 1;
5318                 val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
5319                 val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
5320             }
5321         }
5322     }
5323 
5324     /* Handle exponent5 < 0 */
5325     while (exponent5 < 0) {
5326         /* In order to divide the value represented by the VARIANT_DI by 5, it
5327            is best to multiply by 2/10. Therefore, exponent10 is decremented,
5328            and the mantissa should be multiplied by 2 */
5329         if ((val->bitsnum[2] & 0x80000000) == 0) {
5330             /* The mantissa can withstand a shift-left without overflowing */
5331             exponent10--; exponent5++;
5332             VARIANT_int_shiftleft(val->bitsnum, 3, 1);
5333         } else {
5334             /* The mantissa would overflow if shifted. Therefore it should be
5335                directly divided by 5. This will lose significant digits, unless
5336                by chance the mantissa happens to be divisible by 5 */
5337             exponent5++;
5338             VARIANT_int_divbychar(val->bitsnum, 3, 5);
5339         }
5340     }
5341 
5342     /* At this point, the mantissa has assimilated the exponent5, but the
5343        exponent10 might not be suitable for assignment. The exponent10 must be
5344        in the range [-DEC_MAX_SCALE..0], so the mantissa must be scaled up or
5345        down appropriately. */
5346     while (hres == S_OK && exponent10 > 0) {
5347         /* In order to bring exponent10 down to 0, the mantissa should be
5348            multiplied by 10 to compensate. If the exponent10 is too big, this
5349            will cause the mantissa to overflow. */
5350         if (0 == VARIANT_int_mulbychar(val->bitsnum, 3, 10)) {
5351             exponent10--;
5352         } else {
5353             hres = DISP_E_OVERFLOW;
5354         }
5355     }
5356     while (exponent10 < -DEC_MAX_SCALE) {
5357         int rem10;
5358         /* In order to bring exponent up to -DEC_MAX_SCALE, the mantissa should
5359            be divided by 10 to compensate. If the exponent10 is too small, this
5360            will cause the mantissa to underflow and become 0 */
5361         rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5362         exponent10++;
5363         if (VARIANT_int_iszero(val->bitsnum, 3)) {
5364             /* Underflow, unable to keep dividing */
5365             exponent10 = 0;
5366         } else if (rem10 >= 5) {
5367             DWORD x = 1;
5368             VARIANT_int_add(val->bitsnum, 3, &x, 1);
5369         }
5370     }
5371     /* This step is required in order to remove excess bits of precision from the
5372        end of the bit representation, down to the precision guaranteed by the
5373        floating point number. */
5374     if (isDouble) {
5375         while (exponent10 < 0 && (val->bitsnum[2] != 0 || (val->bitsnum[1] & 0xFFE00000) != 0)) {
5376             int rem10;
5377 
5378             rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5379             exponent10++;
5380             if (rem10 >= 5) {
5381                 DWORD x = 1;
5382                 VARIANT_int_add(val->bitsnum, 3, &x, 1);
5383             }
5384         }
5385     } else {
5386         while (exponent10 < 0 && (val->bitsnum[2] != 0 || val->bitsnum[1] != 0 ||
5387             (val->bitsnum[2] == 0 && val->bitsnum[1] == 0 && (val->bitsnum[0] & 0xFF000000) != 0))) {
5388             int rem10;
5389 
5390             rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5391             exponent10++;
5392             if (rem10 >= 5) {
5393                 DWORD x = 1;
5394                 VARIANT_int_add(val->bitsnum, 3, &x, 1);
5395             }
5396         }
5397     }
5398     /* Remove multiples of 10 from the representation */
5399     while (exponent10 < 0) {
5400         DWORD temp_bitsnum[3];
5401 
5402         memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5403         if (0 == VARIANT_int_divbychar(temp_bitsnum, 3, 10)) {
5404             exponent10++;
5405             memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5406         } else break;
5407     }
5408 
5409     /* Scale assignment */
5410     if (hres == S_OK) val->scale = -exponent10;
5411 
5412     return hres;
5413 }
5414 
5415 typedef union
5416 {
5417     struct
5418     {
5419         unsigned int m : 23;
5420         unsigned int exp_bias : 8;
5421         unsigned int sign : 1;
5422     } i;
5423     float f;
5424 } R4_FIELDS;
5425 
5426 /* Convert a 32-bit floating point number into a DECIMAL, without using an
5427    intermediate string step. */
5428 static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI * dest)
5429 {
5430     HRESULT hres = S_OK;
5431     R4_FIELDS fx;
5432 
5433     fx.f = source;
5434 
5435     /* Detect special cases */
5436     if (fx.i.m == 0 && fx.i.exp_bias == 0) {
5437         /* Floating-point zero */
5438         VARIANT_DI_clear(dest);
5439     } else if (fx.i.m == 0  && fx.i.exp_bias == 0xFF) {
5440         /* Floating-point infinity */
5441         hres = DISP_E_OVERFLOW;
5442     } else if (fx.i.exp_bias == 0xFF) {
5443         /* Floating-point NaN */
5444         hres = DISP_E_BADVARTYPE;
5445     } else {
5446         int exponent2;
5447         VARIANT_DI_clear(dest);
5448 
5449         exponent2 = fx.i.exp_bias - 127;   /* Get unbiased exponent */
5450         dest->sign = fx.i.sign;             /* Sign is simply copied */
5451 
5452         /* Copy significant bits to VARIANT_DI mantissa */
5453         dest->bitsnum[0] = fx.i.m;
5454         dest->bitsnum[0] &= 0x007FFFFF;
5455         if (fx.i.exp_bias == 0) {
5456             /* Denormalized number - correct exponent */
5457             exponent2++;
5458         } else {
5459             /* Add hidden bit to mantissa */
5460             dest->bitsnum[0] |= 0x00800000;
5461         }
5462 
5463         /* The act of copying a FP mantissa as integer bits is equivalent to
5464            shifting left the mantissa 23 bits. The exponent2 is reduced to
5465            compensate. */
5466         exponent2 -= 23;
5467 
5468         hres = VARIANT_DI_normalize(dest, exponent2, FALSE);
5469     }
5470 
5471     return hres;
5472 }
5473 
5474 typedef union
5475 {
5476     struct
5477     {
5478         unsigned int m_lo : 32;     /* 52 bits of precision */
5479         unsigned int m_hi : 20;
5480         unsigned int exp_bias : 11; /* bias == 1023 */
5481         unsigned int sign : 1;
5482     } i;
5483     double d;
5484 } R8_FIELDS;
5485 
5486 /* Convert a 64-bit floating point number into a DECIMAL, without using an
5487    intermediate string step. */
5488 static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest)
5489 {
5490     HRESULT hres = S_OK;
5491     R8_FIELDS fx;
5492 
5493     fx.d = source;
5494 
5495     /* Detect special cases */
5496     if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0) {
5497         /* Floating-point zero */
5498         VARIANT_DI_clear(dest);
5499     } else if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0x7FF) {
5500         /* Floating-point infinity */
5501         hres = DISP_E_OVERFLOW;
5502     } else if (fx.i.exp_bias == 0x7FF) {
5503         /* Floating-point NaN */
5504         hres = DISP_E_BADVARTYPE;
5505     } else {
5506         int exponent2;
5507         VARIANT_DI_clear(dest);
5508 
5509         exponent2 = fx.i.exp_bias - 1023;   /* Get unbiased exponent */
5510         dest->sign = fx.i.sign;             /* Sign is simply copied */
5511 
5512         /* Copy significant bits to VARIANT_DI mantissa */
5513         dest->bitsnum[0] = fx.i.m_lo;
5514         dest->bitsnum[1] = fx.i.m_hi;
5515         dest->bitsnum[1] &= 0x000FFFFF;
5516         if (fx.i.exp_bias == 0) {
5517             /* Denormalized number - correct exponent */
5518             exponent2++;
5519         } else {
5520             /* Add hidden bit to mantissa */
5521             dest->bitsnum[1] |= 0x00100000;
5522         }
5523 
5524         /* The act of copying a FP mantissa as integer bits is equivalent to
5525            shifting left the mantissa 52 bits. The exponent2 is reduced to
5526            compensate. */
5527         exponent2 -= 52;
5528 
5529         hres = VARIANT_DI_normalize(dest, exponent2, TRUE);
5530     }
5531 
5532     return hres;
5533 }
5534 
5535 static HRESULT VARIANT_do_division(const DECIMAL *pDecLeft, const DECIMAL *pDecRight, DECIMAL *pDecOut,
5536         BOOL round)
5537 {
5538   HRESULT hRet = S_OK;
5539   VARIANT_DI di_left, di_right, di_result;
5540   HRESULT divresult;
5541 
5542   VARIANT_DIFromDec(pDecLeft, &di_left);
5543   VARIANT_DIFromDec(pDecRight, &di_right);
5544   divresult = VARIANT_DI_div(&di_left, &di_right, &di_result, round);
5545   if (divresult != S_OK)
5546   {
5547       /* division actually overflowed */
5548       hRet = divresult;
5549   }
5550   else
5551   {
5552       hRet = S_OK;
5553 
5554       if (di_result.scale > DEC_MAX_SCALE)
5555       {
5556         unsigned char remainder = 0;
5557 
5558         /* division underflowed. In order to comply with the MSDN
5559            specifications for DECIMAL ranges, some significant digits
5560            must be removed
5561          */
5562         WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5563             di_result.scale);
5564         while (di_result.scale > DEC_MAX_SCALE &&
5565                !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD)))
5566         {
5567             remainder = VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD), 10);
5568             di_result.scale--;
5569         }
5570         if (di_result.scale > DEC_MAX_SCALE)
5571         {
5572             WARN("result underflowed, setting to 0\n");
5573             di_result.scale = 0;
5574             di_result.sign = 0;
5575         }
5576         else if (remainder >= 5)    /* round up result - native oleaut32 does this */
5577         {
5578             unsigned int i;
5579             for (remainder = 1, i = 0; i < sizeof(di_result.bitsnum) / sizeof(DWORD) && remainder; i++) {
5580                 ULONGLONG digit = di_result.bitsnum[i] + 1;
5581                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
5582                 di_result.bitsnum[i] = digit & 0xFFFFFFFF;
5583             }
5584         }
5585       }
5586       VARIANT_DecFromDI(&di_result, pDecOut);
5587   }
5588   return hRet;
5589 }
5590 
5591 /************************************************************************
5592  * VarDecDiv (OLEAUT32.178)
5593  *
5594  * Divide one DECIMAL by another.
5595  *
5596  * PARAMS
5597  *  pDecLeft  [I] Source
5598  *  pDecRight [I] Value to divide by
5599  *  pDecOut   [O] Destination
5600  *
5601  * RETURNS
5602  *  Success: S_OK.
5603  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5604  */
5605 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5606 {
5607   if (!pDecLeft || !pDecRight || !pDecOut) return E_INVALIDARG;
5608 
5609   return VARIANT_do_division(pDecLeft, pDecRight, pDecOut, FALSE);
5610 }
5611 
5612 /************************************************************************
5613  * VarDecMul (OLEAUT32.179)
5614  *
5615  * Multiply one DECIMAL by another.
5616  *
5617  * PARAMS
5618  *  pDecLeft  [I] Source
5619  *  pDecRight [I] Value to multiply by
5620  *  pDecOut   [O] Destination
5621  *
5622  * RETURNS
5623  *  Success: S_OK.
5624  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5625  */
5626 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5627 {
5628   HRESULT hRet = S_OK;
5629   VARIANT_DI di_left, di_right, di_result;
5630   int mulresult;
5631 
5632   VARIANT_DIFromDec(pDecLeft, &di_left);
5633   VARIANT_DIFromDec(pDecRight, &di_right);
5634   mulresult = VARIANT_DI_mul(&di_left, &di_right, &di_result);
5635   if (mulresult)
5636   {
5637     /* multiplication actually overflowed */
5638     hRet = DISP_E_OVERFLOW;
5639   }
5640   else
5641   {
5642     if (di_result.scale > DEC_MAX_SCALE)
5643     {
5644       /* multiplication underflowed. In order to comply with the MSDN
5645          specifications for DECIMAL ranges, some significant digits
5646          must be removed
5647        */
5648       WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5649           di_result.scale);
5650       while (di_result.scale > DEC_MAX_SCALE &&
5651             !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD)))
5652       {
5653         VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD), 10);
5654         di_result.scale--;
5655       }
5656       if (di_result.scale > DEC_MAX_SCALE)
5657       {
5658         WARN("result underflowed, setting to 0\n");
5659         di_result.scale = 0;
5660         di_result.sign = 0;
5661       }
5662     }
5663     VARIANT_DecFromDI(&di_result, pDecOut);
5664   }
5665   return hRet;
5666 }
5667 
5668 /************************************************************************
5669  * VarDecSub (OLEAUT32.181)
5670  *
5671  * Subtract one DECIMAL from another.
5672  *
5673  * PARAMS
5674  *  pDecLeft  [I] Source
5675  *  pDecRight [I] DECIMAL to subtract from pDecLeft
5676  *  pDecOut   [O] Destination
5677  *
5678  * RETURNS
5679  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5680  */
5681 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5682 {
5683   DECIMAL decRight;
5684 
5685   /* Implement as addition of the negative */
5686   VarDecNeg(pDecRight, &decRight);
5687   return VarDecAdd(pDecLeft, &decRight, pDecOut);
5688 }
5689 
5690 /************************************************************************
5691  * VarDecAbs (OLEAUT32.182)
5692  *
5693  * Convert a DECIMAL into its absolute value.
5694  *
5695  * PARAMS
5696  *  pDecIn  [I] Source
5697  *  pDecOut [O] Destination
5698  *
5699  * RETURNS
5700  *  S_OK. This function does not fail.
5701  */
5702 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5703 {
5704   *pDecOut = *pDecIn;
5705   DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
5706   return S_OK;
5707 }
5708 
5709 /************************************************************************
5710  * VarDecFix (OLEAUT32.187)
5711  *
5712  * Return the integer portion of a DECIMAL.
5713  *
5714  * PARAMS
5715  *  pDecIn  [I] Source
5716  *  pDecOut [O] Destination
5717  *
5718  * RETURNS
5719  *  Success: S_OK.
5720  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5721  *
5722  * NOTES
5723  *  - The difference between this function and VarDecInt() is that VarDecInt() rounds
5724  *    negative numbers away from 0, while this function rounds them towards zero.
5725  */
5726 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5727 {
5728   double dbl;
5729   HRESULT hr;
5730 
5731   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
5732     return E_INVALIDARG;
5733 
5734   if (!DEC_SCALE(pDecIn))
5735   {
5736     *pDecOut = *pDecIn; /* Already an integer */
5737     return S_OK;
5738   }
5739 
5740   hr = VarR8FromDec(pDecIn, &dbl);
5741   if (SUCCEEDED(hr)) {
5742     LONGLONG rounded = dbl;
5743 
5744     hr = VarDecFromI8(rounded, pDecOut);
5745   }
5746   return hr;
5747 }
5748 
5749 /************************************************************************
5750  * VarDecInt (OLEAUT32.188)
5751  *
5752  * Return the integer portion of a DECIMAL.
5753  *
5754  * PARAMS
5755  *  pDecIn  [I] Source
5756  *  pDecOut [O] Destination
5757  *
5758  * RETURNS
5759  *  Success: S_OK.
5760  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5761  *
5762  * NOTES
5763  *  - The difference between this function and VarDecFix() is that VarDecFix() rounds
5764  *    negative numbers towards 0, while this function rounds them away from zero.
5765  */
5766 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5767 {
5768   double dbl;
5769   HRESULT hr;
5770 
5771   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
5772     return E_INVALIDARG;
5773 
5774   if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
5775     return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
5776 
5777   hr = VarR8FromDec(pDecIn, &dbl);
5778   if (SUCCEEDED(hr)) {
5779     LONGLONG rounded = dbl >= 0.0 ? dbl + 0.5 : dbl - 0.5;
5780 
5781     hr = VarDecFromI8(rounded, pDecOut);
5782   }
5783   return hr;
5784 }
5785 
5786 /************************************************************************
5787  * VarDecNeg (OLEAUT32.189)
5788  *
5789  * Change the sign of a DECIMAL.
5790  *
5791  * PARAMS
5792  *  pDecIn  [I] Source
5793  *  pDecOut [O] Destination
5794  *
5795  * RETURNS
5796  *  S_OK. This function does not fail.
5797  */
5798 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5799 {
5800   *pDecOut = *pDecIn;
5801   DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
5802   return S_OK;
5803 }
5804 
5805 /************************************************************************
5806  * VarDecRound (OLEAUT32.203)
5807  *
5808  * Change the precision of a DECIMAL.
5809  *
5810  * PARAMS
5811  *  pDecIn    [I] Source
5812  *  cDecimals [I] New number of decimals to keep
5813  *  pDecOut   [O] Destination
5814  *
5815  * RETURNS
5816  *  Success: S_OK. pDecOut contains the rounded value.
5817  *  Failure: E_INVALIDARG if any argument is invalid.
5818  */
5819 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
5820 {
5821   DECIMAL divisor, tmp;
5822   HRESULT hr;
5823   unsigned int i;
5824 
5825   if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
5826     return E_INVALIDARG;
5827 
5828   if (cDecimals >= DEC_SCALE(pDecIn))
5829   {
5830     *pDecOut = *pDecIn; /* More precision than we have */
5831     return S_OK;
5832   }
5833 
5834   /* truncate significant digits and rescale */
5835   memset(&divisor, 0, sizeof(divisor));
5836   DEC_LO64(&divisor) = 1;
5837 
5838   memset(&tmp, 0, sizeof(tmp));
5839   DEC_LO64(&tmp) = 10;
5840   for (i = 0; i < DEC_SCALE(pDecIn) - cDecimals; ++i)
5841   {
5842     hr = VarDecMul(&divisor, &tmp, &divisor);
5843     if (FAILED(hr))
5844       return hr;
5845   }
5846 
5847   hr = VARIANT_do_division(pDecIn, &divisor, pDecOut, TRUE);
5848   if (FAILED(hr))
5849     return hr;
5850 
5851   DEC_SCALE(pDecOut) = cDecimals;
5852 
5853   return S_OK;
5854 }
5855 
5856 /************************************************************************
5857  * VarDecCmp (OLEAUT32.204)
5858  *
5859  * Compare two DECIMAL values.
5860  *
5861  * PARAMS
5862  *  pDecLeft  [I] Source
5863  *  pDecRight [I] Value to compare
5864  *
5865  * RETURNS
5866  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
5867  *           is less than, equal to or greater than pDecRight respectively.
5868  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5869  */
5870 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
5871 {
5872   HRESULT hRet;
5873   DECIMAL result;
5874 
5875   if (!pDecLeft || !pDecRight)
5876     return VARCMP_NULL;
5877 
5878   if ((!(DEC_SIGN(pDecLeft) & DECIMAL_NEG)) && (DEC_SIGN(pDecRight) & DECIMAL_NEG) &&
5879       (DEC_HI32(pDecLeft) | DEC_MID32(pDecLeft) | DEC_LO32(pDecLeft)))
5880     return VARCMP_GT;
5881   else if ((DEC_SIGN(pDecLeft) & DECIMAL_NEG) && (!(DEC_SIGN(pDecRight) & DECIMAL_NEG)) &&
5882       (DEC_HI32(pDecLeft) | DEC_MID32(pDecLeft) | DEC_LO32(pDecLeft)))
5883     return VARCMP_LT;
5884 
5885   /* Subtract right from left, and compare the result to 0 */
5886   hRet = VarDecSub(pDecLeft, pDecRight, &result);
5887 
5888   if (SUCCEEDED(hRet))
5889   {
5890     int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
5891 
5892     if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
5893       hRet = (HRESULT)VARCMP_LT;
5894     else if (non_zero)
5895       hRet = (HRESULT)VARCMP_GT;
5896     else
5897       hRet = (HRESULT)VARCMP_EQ;
5898   }
5899   return hRet;
5900 }
5901 
5902 /************************************************************************
5903  * VarDecCmpR8 (OLEAUT32.298)
5904  *
5905  * Compare a DECIMAL to a double
5906  *
5907  * PARAMS
5908  *  pDecLeft [I] DECIMAL Source
5909  *  dblRight [I] double to compare to pDecLeft
5910  *
5911  * RETURNS
5912  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
5913  *           is less than, equal to or greater than pDecLeft respectively.
5914  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5915  */
5916 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
5917 {
5918   HRESULT hRet;
5919   DECIMAL decRight;
5920 
5921   hRet = VarDecFromR8(dblRight, &decRight);
5922 
5923   if (SUCCEEDED(hRet))
5924     hRet = VarDecCmp(pDecLeft, &decRight);
5925 
5926   return hRet;
5927 }
5928 
5929 /* BOOL
5930  */
5931 
5932 /************************************************************************
5933  * VarBoolFromUI1 (OLEAUT32.118)
5934  *
5935  * Convert a VT_UI1 to a VT_BOOL.
5936  *
5937  * PARAMS
5938  *  bIn      [I] Source
5939  *  pBoolOut [O] Destination
5940  *
5941  * RETURNS
5942  *  S_OK.
5943  */
5944 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
5945 {
5946   *pBoolOut = bIn ? VARIANT_TRUE : VARIANT_FALSE;
5947   return S_OK;
5948 }
5949 
5950 /************************************************************************
5951  * VarBoolFromI2 (OLEAUT32.119)
5952  *
5953  * Convert a VT_I2 to a VT_BOOL.
5954  *
5955  * PARAMS
5956  *  sIn      [I] Source
5957  *  pBoolOut [O] Destination
5958  *
5959  * RETURNS
5960  *  S_OK.
5961  */
5962 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
5963 {
5964   *pBoolOut = sIn ? VARIANT_TRUE : VARIANT_FALSE;
5965   return S_OK;
5966 }
5967 
5968 /************************************************************************
5969  * VarBoolFromI4 (OLEAUT32.120)
5970  *
5971  * Convert a VT_I4 to a VT_BOOL.
5972  *
5973  * PARAMS
5974  *  sIn      [I] Source
5975  *  pBoolOut [O] Destination
5976  *
5977  * RETURNS
5978  *  S_OK.
5979  */
5980 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
5981 {
5982   *pBoolOut = lIn ? VARIANT_TRUE : VARIANT_FALSE;
5983   return S_OK;
5984 }
5985 
5986 /************************************************************************
5987  * VarBoolFromR4 (OLEAUT32.121)
5988  *
5989  * Convert a VT_R4 to a VT_BOOL.
5990  *
5991  * PARAMS
5992  *  fltIn    [I] Source
5993  *  pBoolOut [O] Destination
5994  *
5995  * RETURNS
5996  *  S_OK.
5997  */
5998 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
5999 {
6000   *pBoolOut = fltIn ? VARIANT_TRUE : VARIANT_FALSE;
6001   return S_OK;
6002 }
6003 
6004 /************************************************************************
6005  * VarBoolFromR8 (OLEAUT32.122)
6006  *
6007  * Convert a VT_R8 to a VT_BOOL.
6008  *
6009  * PARAMS
6010  *  dblIn    [I] Source
6011  *  pBoolOut [O] Destination
6012  *
6013  * RETURNS
6014  *  S_OK.
6015  */
6016 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
6017 {
6018   *pBoolOut = dblIn ? VARIANT_TRUE : VARIANT_FALSE;
6019   return S_OK;
6020 }
6021 
6022 /************************************************************************
6023  * VarBoolFromDate (OLEAUT32.123)
6024  *
6025  * Convert a VT_DATE to a VT_BOOL.
6026  *
6027  * PARAMS
6028  *  dateIn   [I] Source
6029  *  pBoolOut [O] Destination
6030  *
6031  * RETURNS
6032  *  S_OK.
6033  */
6034 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
6035 {
6036   *pBoolOut = dateIn ? VARIANT_TRUE : VARIANT_FALSE;
6037   return S_OK;
6038 }
6039 
6040 /************************************************************************
6041  * VarBoolFromCy (OLEAUT32.124)
6042  *
6043  * Convert a VT_CY to a VT_BOOL.
6044  *
6045  * PARAMS
6046  *  cyIn     [I] Source
6047  *  pBoolOut [O] Destination
6048  *
6049  * RETURNS
6050  *  S_OK.
6051  */
6052 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
6053 {
6054   *pBoolOut = cyIn.int64 ? VARIANT_TRUE : VARIANT_FALSE;
6055   return S_OK;
6056 }
6057 
6058 /************************************************************************
6059  * VARIANT_GetLocalisedText [internal]
6060  *
6061  * Get a localized string from the resources
6062  *
6063  */
6064 static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
6065 {
6066   HRSRC hrsrc;
6067 
6068   hrsrc = FindResourceExW( hProxyDll, (LPWSTR)RT_STRING,
6069                            MAKEINTRESOURCEW((dwId >> 4) + 1), langId );
6070   if (hrsrc)
6071   {
6072     HGLOBAL hmem = LoadResource( hProxyDll, hrsrc );
6073 
6074     if (hmem)
6075     {
6076       const WCHAR *p;
6077       unsigned int i;
6078 
6079       p = LockResource( hmem );
6080       for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
6081 
6082       memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
6083       lpszDest[*p] = '\0';
6084       TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
6085       return TRUE;
6086     }
6087   }
6088   return FALSE;
6089 }
6090 
6091 /************************************************************************
6092  * VarBoolFromStr (OLEAUT32.125)
6093  *
6094  * Convert a VT_BSTR to a VT_BOOL.
6095  *
6096  * PARAMS
6097  *  strIn    [I] Source
6098  *  lcid     [I] LCID for the conversion
6099  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6100  *  pBoolOut [O] Destination
6101  *
6102  * RETURNS
6103  *  Success: S_OK.
6104  *  Failure: E_INVALIDARG, if pBoolOut is invalid.
6105  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
6106  *
6107  * NOTES
6108  *  - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
6109  *  it may contain (in any case mapping) the text "true" or "false".
6110  *  - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
6111  *  localised text of "True" or "False" in the language specified by lcid.
6112  *  - If none of these matches occur, the string is treated as a numeric string
6113  *  and the boolean pBoolOut will be set according to whether the number is zero
6114  *  or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
6115  *  - If the text is not numeric and does not match any of the above, then
6116  *  DISP_E_TYPEMISMATCH is returned.
6117  */
6118 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
6119 {
6120   /* Any VB/VBA programmers out there should recognise these strings... */
6121   static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
6122   static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
6123   WCHAR szBuff[64];
6124   LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6125   HRESULT hRes = S_OK;
6126 
6127   if (!strIn || !pBoolOut)
6128     return DISP_E_TYPEMISMATCH;
6129 
6130   /* Check if we should be comparing against localised text */
6131   if (dwFlags & VAR_LOCALBOOL)
6132   {
6133     /* Convert our LCID into a usable value */
6134     lcid = ConvertDefaultLocale(lcid);
6135 
6136     langId = LANGIDFROMLCID(lcid);
6137 
6138     if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
6139       langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6140 
6141     /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
6142      * I don't think this is needed unless any of the localised text strings
6143      * contain characters that can be so mapped. In the event that this is
6144      * true for a given language (possibly some Asian languages), then strIn
6145      * should be mapped here _only_ if langId is an Id for which this can occur.
6146      */
6147   }
6148 
6149   /* Note that if we are not comparing against localised strings, langId
6150    * will have its default value of LANG_ENGLISH. This allows us to mimic
6151    * the native behaviour of always checking against English strings even
6152    * after we've checked for localised ones.
6153    */
6154 VarBoolFromStr_CheckLocalised:
6155   if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
6156   {
6157     /* Compare against localised strings, ignoring case */
6158     if (!strcmpiW(strIn, szBuff))
6159     {
6160       *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
6161       return hRes;
6162     }
6163     VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
6164     if (!strcmpiW(strIn, szBuff))
6165     {
6166       *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
6167       return hRes;
6168     }
6169   }
6170 
6171   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
6172   {
6173     /* We have checked the localised text, now check English */
6174     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6175     goto VarBoolFromStr_CheckLocalised;
6176   }
6177 
6178   /* All checks against localised text have failed, try #TRUE#/#FALSE# */
6179   if (!strcmpW(strIn, szFalse))
6180     *pBoolOut = VARIANT_FALSE;
6181   else if (!strcmpW(strIn, szTrue))
6182     *pBoolOut = VARIANT_TRUE;
6183   else
6184   {
6185     double d;
6186 
6187     /* If this string is a number, convert it as one */
6188     hRes = VarR8FromStr(strIn, lcid, dwFlags, &d);
6189     if (SUCCEEDED(hRes)) *pBoolOut = d ? VARIANT_TRUE : VARIANT_FALSE;
6190   }
6191   return hRes;
6192 }
6193 
6194 /************************************************************************
6195  * VarBoolFromDisp (OLEAUT32.126)
6196  *
6197  * Convert a VT_DISPATCH to a VT_BOOL.
6198  *
6199  * PARAMS
6200  *  pdispIn   [I] Source
6201  *  lcid      [I] LCID for conversion
6202  *  pBoolOut  [O] Destination
6203  *
6204  * RETURNS
6205  *  Success: S_OK.
6206  *  Failure: E_INVALIDARG, if the source value is invalid
6207  *           DISP_E_OVERFLOW, if the value will not fit in the destination
6208  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
6209  */
6210 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
6211 {
6212   return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL, 0);
6213 }
6214 
6215 /************************************************************************
6216  * VarBoolFromI1 (OLEAUT32.233)
6217  *
6218  * Convert a VT_I1 to a VT_BOOL.
6219  *
6220  * PARAMS
6221  *  cIn      [I] Source
6222  *  pBoolOut [O] Destination
6223  *
6224  * RETURNS
6225  *  S_OK.
6226  */
6227 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
6228 {
6229   *pBoolOut = cIn ? VARIANT_TRUE : VARIANT_FALSE;
6230   return S_OK;
6231 }
6232 
6233 /************************************************************************
6234  * VarBoolFromUI2 (OLEAUT32.234)
6235  *
6236  * Convert a VT_UI2 to a VT_BOOL.
6237  *
6238  * PARAMS
6239  *  usIn     [I] Source
6240  *  pBoolOut [O] Destination
6241  *
6242  * RETURNS
6243  *  S_OK.
6244  */
6245 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
6246 {
6247   *pBoolOut = usIn ? VARIANT_TRUE : VARIANT_FALSE;
6248   return S_OK;
6249 }
6250 
6251 /************************************************************************
6252  * VarBoolFromUI4 (OLEAUT32.235)
6253  *
6254  * Convert a VT_UI4 to a VT_BOOL.
6255  *
6256  * PARAMS
6257  *  ulIn     [I] Source
6258  *  pBoolOut [O] Destination
6259  *
6260  * RETURNS
6261  *  S_OK.
6262  */
6263 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
6264 {
6265   *pBoolOut = ulIn ? VARIANT_TRUE : VARIANT_FALSE;
6266   return S_OK;
6267 }
6268 
6269 /************************************************************************
6270  * VarBoolFromDec (OLEAUT32.236)
6271  *
6272  * Convert a VT_DECIMAL to a VT_BOOL.
6273  *
6274  * PARAMS
6275  *  pDecIn   [I] Source
6276  *  pBoolOut [O] Destination
6277  *
6278  * RETURNS
6279  *  Success: S_OK.
6280  *  Failure: E_INVALIDARG, if pDecIn is invalid.
6281  */
6282 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
6283 {
6284   if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
6285     return E_INVALIDARG;
6286 
6287   if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
6288     *pBoolOut = VARIANT_TRUE;
6289   else
6290     *pBoolOut = VARIANT_FALSE;
6291   return S_OK;
6292 }
6293 
6294 /************************************************************************
6295  * VarBoolFromI8 (OLEAUT32.370)
6296  *
6297  * Convert a VT_I8 to a VT_BOOL.
6298  *
6299  * PARAMS
6300  *  ullIn    [I] Source
6301  *  pBoolOut [O] Destination
6302  *
6303  * RETURNS
6304  *  S_OK.
6305  */
6306 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
6307 {
6308   *pBoolOut = llIn ? VARIANT_TRUE : VARIANT_FALSE;
6309   return S_OK;
6310 }
6311 
6312 /************************************************************************
6313  * VarBoolFromUI8 (OLEAUT32.371)
6314  *
6315  * Convert a VT_UI8 to a VT_BOOL.
6316  *
6317  * PARAMS
6318  *  ullIn    [I] Source
6319  *  pBoolOut [O] Destination
6320  *
6321  * RETURNS
6322  *  S_OK.
6323  */
6324 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
6325 {
6326   *pBoolOut = ullIn ? VARIANT_TRUE : VARIANT_FALSE;
6327   return S_OK;
6328 }
6329 
6330 /* BSTR
6331  */
6332 
6333 /* Write a number from a UI8 and sign */
6334 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
6335 {
6336   do
6337   {
6338     WCHAR ulNextDigit = ulVal % 10;
6339 
6340     *szOut-- = '0' + ulNextDigit;
6341     ulVal = (ulVal - ulNextDigit) / 10;
6342   } while (ulVal);
6343 
6344   szOut++;
6345   return szOut;
6346 }
6347 
6348 /* Create a (possibly localised) BSTR from a UI8 and sign */
6349 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
6350 {
6351   WCHAR szConverted[256];
6352 
6353   if (dwFlags & VAR_NEGATIVE)
6354     *--szOut = '-';
6355 
6356   if (dwFlags & LOCALE_USE_NLS)
6357   {
6358     /* Format the number for the locale */
6359     szConverted[0] = '\0';
6360     GetNumberFormatW(lcid,
6361                      dwFlags & LOCALE_NOUSEROVERRIDE,
6362                      szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
6363     szOut = szConverted;
6364   }
6365   return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
6366 }
6367 
6368 /* Create a (possibly localised) BSTR from a UI8 and sign */
6369 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
6370 {
6371   WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
6372 
6373   if (!pbstrOut)
6374     return E_INVALIDARG;
6375 
6376   /* Create the basic number string */
6377   *szOut-- = '\0';
6378   szOut = VARIANT_WriteNumber(ulVal, szOut);
6379 
6380   *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
6381   TRACE("returning %s\n", debugstr_w(*pbstrOut));
6382   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6383 }
6384 
6385 /******************************************************************************
6386  * VarBstrFromUI1 (OLEAUT32.108)
6387  *
6388  * Convert a VT_UI1 to a VT_BSTR.
6389  *
6390  * PARAMS
6391  *  bIn      [I] Source
6392  *  lcid     [I] LCID for the conversion
6393  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6394  *  pbstrOut [O] Destination
6395  *
6396  * RETURNS
6397  *  Success: S_OK.
6398  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6399  *           E_OUTOFMEMORY, if memory allocation fails.
6400  */
6401 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6402 {
6403   return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
6404 }
6405 
6406 /******************************************************************************
6407  * VarBstrFromI2 (OLEAUT32.109)
6408  *
6409  * Convert a VT_I2 to a VT_BSTR.
6410  *
6411  * PARAMS
6412  *  sIn      [I] Source
6413  *  lcid     [I] LCID for the conversion
6414  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6415  *  pbstrOut [O] Destination
6416  *
6417  * RETURNS
6418  *  Success: S_OK.
6419  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6420  *           E_OUTOFMEMORY, if memory allocation fails.
6421  */
6422 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6423 {
6424   ULONG64 ul64 = sIn;
6425 
6426   if (sIn < 0)
6427   {
6428     ul64 = -sIn;
6429     dwFlags |= VAR_NEGATIVE;
6430   }
6431   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6432 }
6433 
6434 /******************************************************************************
6435  * VarBstrFromI4 (OLEAUT32.110)
6436  *
6437  * Convert a VT_I4 to a VT_BSTR.
6438  *
6439  * PARAMS
6440  *  lIn      [I] Source
6441  *  lcid     [I] LCID for the conversion
6442  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6443  *  pbstrOut [O] Destination
6444  *
6445  * RETURNS
6446  *  Success: S_OK.
6447  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6448  *           E_OUTOFMEMORY, if memory allocation fails.
6449  */
6450 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6451 {
6452   ULONG64 ul64 = lIn;
6453 
6454   if (lIn < 0)
6455   {
6456     ul64 = (ULONG)-lIn;
6457     dwFlags |= VAR_NEGATIVE;
6458   }
6459   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6460 }
6461 
6462 static BSTR VARIANT_BstrReplaceDecimal(const WCHAR * buff, LCID lcid, ULONG dwFlags)
6463 {
6464   BSTR bstrOut;
6465   WCHAR lpDecimalSep[16];
6466 
6467   /* Native oleaut32 uses the locale-specific decimal separator even in the
6468      absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin
6469      American locales will see "one thousand and one tenth" as "1000,1"
6470      instead of "1000.1" (notice the comma). The following code checks for
6471      the need to replace the decimal separator, and if so, will prepare an
6472      appropriate NUMBERFMTW structure to do the job via GetNumberFormatW().
6473    */
6474   GetLocaleInfoW(lcid, LOCALE_SDECIMAL | (dwFlags & LOCALE_NOUSEROVERRIDE),
6475                  lpDecimalSep, sizeof(lpDecimalSep) / sizeof(WCHAR));
6476   if (lpDecimalSep[0] == '.' && lpDecimalSep[1] == '\0')
6477   {
6478     /* locale is compatible with English - return original string */
6479     bstrOut = SysAllocString(buff);
6480   }
6481   else
6482   {
6483     WCHAR *p;
6484     WCHAR numbuff[256];
6485     WCHAR empty[] = {'\0'};
6486     NUMBERFMTW minFormat;
6487 
6488     minFormat.NumDigits = 0;
6489     minFormat.LeadingZero = 0;
6490     minFormat.Grouping = 0;
6491     minFormat.lpDecimalSep = lpDecimalSep;
6492     minFormat.lpThousandSep = empty;
6493     minFormat.NegativeOrder = 1; /* NLS_NEG_LEFT */
6494 
6495     /* count number of decimal digits in string */
6496     p = strchrW( buff, '.' );
6497     if (p) minFormat.NumDigits = strlenW(p + 1);
6498 
6499     numbuff[0] = '\0';
6500     if (!GetNumberFormatW(lcid, 0, buff, &minFormat, numbuff, sizeof(numbuff) / sizeof(WCHAR)))
6501     {
6502       WARN("GetNumberFormatW() failed, returning raw number string instead\n");
6503       bstrOut = SysAllocString(buff);
6504     }
6505     else
6506     {
6507       TRACE("created minimal NLS string %s\n", debugstr_w(numbuff));
6508       bstrOut = SysAllocString(numbuff);
6509     }
6510   }
6511   return bstrOut;
6512 }
6513 
6514 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
6515                                     BSTR* pbstrOut, LPCWSTR lpszFormat)
6516 {
6517   WCHAR buff[256];
6518 
6519   if (!pbstrOut)
6520     return E_INVALIDARG;
6521 
6522   sprintfW( buff, lpszFormat, dblIn );
6523 
6524   /* Negative zeroes are disallowed (some applications depend on this).
6525      If buff starts with a minus, and then nothing follows but zeroes
6526      and/or a period, it is a negative zero and is replaced with a
6527      canonical zero. This duplicates native oleaut32 behavior.
6528    */
6529   if (buff[0] == '-')
6530   {
6531     const WCHAR szAccept[] = {'0', '.', '\0'};
6532     if (strlenW(buff + 1) == strspnW(buff + 1, szAccept))
6533     { buff[0] = '0'; buff[1] = '\0'; }
6534   }
6535 
6536   TRACE("created string %s\n", debugstr_w(buff));
6537   if (dwFlags & LOCALE_USE_NLS)
6538   {
6539     WCHAR numbuff[256];
6540 
6541     /* Format the number for the locale */
6542     numbuff[0] = '\0';
6543     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6544                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
6545     TRACE("created NLS string %s\n", debugstr_w(numbuff));
6546     *pbstrOut = SysAllocString(numbuff);
6547   }
6548   else
6549   {
6550     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
6551   }
6552   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6553 }
6554 
6555 /******************************************************************************
6556  * VarBstrFromR4 (OLEAUT32.111)
6557  *
6558  * Convert a VT_R4 to a VT_BSTR.
6559  *
6560  * PARAMS
6561  *  fltIn    [I] Source
6562  *  lcid     [I] LCID for the conversion
6563  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6564  *  pbstrOut [O] Destination
6565  *
6566  * RETURNS
6567  *  Success: S_OK.
6568  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6569  *           E_OUTOFMEMORY, if memory allocation fails.
6570  */
6571 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6572 {
6573   return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
6574 }
6575 
6576 /******************************************************************************
6577  * VarBstrFromR8 (OLEAUT32.112)
6578  *
6579  * Convert a VT_R8 to a VT_BSTR.
6580  *
6581  * PARAMS
6582  *  dblIn    [I] Source
6583  *  lcid     [I] LCID for the conversion
6584  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6585  *  pbstrOut [O] Destination
6586  *
6587  * RETURNS
6588  *  Success: S_OK.
6589  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6590  *           E_OUTOFMEMORY, if memory allocation fails.
6591  */
6592 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6593 {
6594   return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
6595 }
6596 
6597 /******************************************************************************
6598  *    VarBstrFromCy   [OLEAUT32.113]
6599  *
6600  * Convert a VT_CY to a VT_BSTR.
6601  *
6602  * PARAMS
6603  *  cyIn     [I] Source
6604  *  lcid     [I] LCID for the conversion
6605  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6606  *  pbstrOut [O] Destination
6607  *
6608  * RETURNS
6609  *  Success: S_OK.
6610  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6611  *           E_OUTOFMEMORY, if memory allocation fails.
6612  */
6613 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
6614 {
6615   WCHAR buff[256];
6616   VARIANT_DI decVal;
6617 
6618   if (!pbstrOut)
6619     return E_INVALIDARG;
6620 
6621   decVal.scale = 4;
6622   decVal.sign = 0;
6623   decVal.bitsnum[0] = cyIn.s.Lo;
6624   decVal.bitsnum[1] = cyIn.s.Hi;
6625   if (cyIn.s.Hi & 0x80000000UL) {
6626     DWORD one = 1;
6627 
6628     /* Negative number! */
6629     decVal.sign = 1;
6630     decVal.bitsnum[0] = ~decVal.bitsnum[0];
6631     decVal.bitsnum[1] = ~decVal.bitsnum[1];
6632     VARIANT_int_add(decVal.bitsnum, 3, &one, 1);
6633   }
6634   decVal.bitsnum[2] = 0;
6635   VARIANT_DI_tostringW(&decVal, buff, sizeof(buff)/sizeof(buff[0]));
6636 
6637   if (dwFlags & LOCALE_USE_NLS)
6638   {
6639     WCHAR cybuff[256];
6640 
6641     /* Format the currency for the locale */
6642     cybuff[0] = '\0';
6643     GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6644                        buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
6645     *pbstrOut = SysAllocString(cybuff);
6646   }
6647   else
6648     *pbstrOut = VARIANT_BstrReplaceDecimal(buff,lcid,dwFlags);
6649 
6650   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6651 }
6652 
6653 static inline int output_int_len(int o, int min_len, WCHAR *date, int date_len)
6654 {
6655     int len, tmp;
6656 
6657     if(min_len >= date_len)
6658         return -1;
6659 
6660     for(len=0, tmp=o; tmp; tmp/=10) len++;
6661     if(!len) len++;
6662     if(len >= date_len)
6663         return -1;
6664 
6665     for(tmp=min_len-len; tmp>0; tmp--)
6666         *date++ = '0';
6667     for(tmp=len; tmp>0; tmp--, o/=10)
6668         date[tmp-1] = '0' + o%10;
6669     return min_len>len ? min_len : len;
6670 }
6671 
6672 /* format date string, similar to GetDateFormatW function but works on bigger range of dates */
6673 BOOL get_date_format(LCID lcid, DWORD flags, const SYSTEMTIME *st,
6674         const WCHAR *fmt, WCHAR *date, int date_len)
6675 {
6676     static const LCTYPE dayname[] = {
6677         LOCALE_SDAYNAME7, LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3,
6678         LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, LOCALE_SDAYNAME6
6679     };
6680     static const LCTYPE sdayname[] = {
6681         LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
6682         LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
6683         LOCALE_SABBREVDAYNAME6
6684     };
6685     static const LCTYPE monthname[] = {
6686         LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
6687         LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
6688         LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12
6689     };
6690     static const LCTYPE smonthname[] = {
6691         LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
6692         LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
6693         LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
6694         LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12
6695     };
6696 
6697     if(flags & ~(LOCALE_NOUSEROVERRIDE|VAR_DATEVALUEONLY))
6698         FIXME("ignoring flags %x\n", flags);
6699     flags &= LOCALE_NOUSEROVERRIDE;
6700 
6701     while(*fmt && date_len) {
6702         int count = 1;
6703 
6704         switch(*fmt) {
6705             case 'd':
6706             case 'M':
6707             case 'y':
6708             case 'g':
6709                 while(*fmt == *(fmt+count))
6710                     count++;
6711                 fmt += count-1;
6712         }
6713 
6714         switch(*fmt) {
6715         case 'd':
6716             if(count >= 4)
6717                 count = GetLocaleInfoW(lcid, dayname[st->wDayOfWeek] | flags, date, date_len)-1;
6718             else if(count == 3)
6719                 count = GetLocaleInfoW(lcid, sdayname[st->wDayOfWeek] | flags, date, date_len)-1;
6720             else
6721                 count = output_int_len(st->wDay, count, date, date_len);
6722             break;
6723         case 'M':
6724             if(count >= 4)
6725                 count = GetLocaleInfoW(lcid, monthname[st->wMonth-1] | flags, date, date_len)-1;
6726             else if(count == 3)
6727                 count = GetLocaleInfoW(lcid, smonthname[st->wMonth-1] | flags, date, date_len)-1;
6728             else
6729                 count = output_int_len(st->wMonth, count, date, date_len);
6730             break;
6731         case 'y':
6732             if(count >= 3)
6733                 count = output_int_len(st->wYear, 0, date, date_len);
6734             else
6735                 count = output_int_len(st->wYear%100, count, date, date_len);
6736             break;
6737         case 'g':
6738             if(count == 2) {
6739                 FIXME("Should be using GetCalendarInfo(CAL_SERASTRING), defaulting to 'AD'\n");
6740 
6741                 *date++ = 'A';
6742                 date_len--;
6743                 if(date_len)
6744                     *date = 'D';
6745                 else
6746                     count = -1;
6747                 break;
6748             }
6749         /* fall through */
6750         default:
6751             *date = *fmt;
6752         }
6753 
6754         if(count < 0)
6755             break;
6756         fmt++;
6757         date += count;
6758         date_len -= count;
6759     }
6760 
6761     if(!date_len)
6762         return FALSE;
6763     *date++ = 0;
6764     return TRUE;
6765 }
6766 
6767 /******************************************************************************
6768  *    VarBstrFromDate    [OLEAUT32.114]
6769  *
6770  * Convert a VT_DATE to a VT_BSTR.
6771  *
6772  * PARAMS
6773  *  dateIn   [I] Source
6774  *  lcid     [I] LCID for the conversion
6775  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6776  *  pbstrOut [O] Destination
6777  *
6778  * RETURNS
6779  *  Success: S_OK.
6780  *  Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
6781  *           E_OUTOFMEMORY, if memory allocation fails.
6782  */
6783 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6784 {
6785   SYSTEMTIME st;
6786   DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
6787   WCHAR date[128], fmt_buff[80], *time;
6788 
6789   TRACE("(%g,0x%08x,0x%08x,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
6790 
6791   if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
6792     return E_INVALIDARG;
6793 
6794   *pbstrOut = NULL;
6795 
6796   if (dwFlags & VAR_CALENDAR_THAI)
6797       st.wYear += 553; /* Use the Thai buddhist calendar year */
6798   else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
6799       FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
6800 
6801   if (dwFlags & LOCALE_USE_NLS)
6802     dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
6803   else
6804   {
6805     double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
6806     double partial = dateIn - whole;
6807 
6808     if (whole == 0.0)
6809       dwFlags |= VAR_TIMEVALUEONLY;
6810     else if (partial > -1e-12 && partial < 1e-12)
6811       dwFlags |= VAR_DATEVALUEONLY;
6812   }
6813 
6814   if (dwFlags & VAR_TIMEVALUEONLY)
6815     date[0] = '\0';
6816   else
6817     if (!GetLocaleInfoW(lcid, LOCALE_SSHORTDATE, fmt_buff, sizeof(fmt_buff)/sizeof(WCHAR)) ||
6818         !get_date_format(lcid, dwFlags, &st, fmt_buff, date, sizeof(date)/sizeof(WCHAR)))
6819       return E_INVALIDARG;
6820 
6821   if (!(dwFlags & VAR_DATEVALUEONLY))
6822   {
6823     time = date + strlenW(date);
6824     if (time != date)
6825       *time++ = ' ';
6826     if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
6827                         sizeof(date)/sizeof(WCHAR)-(time-date)))
6828       return E_INVALIDARG;
6829   }
6830 
6831   *pbstrOut = SysAllocString(date);
6832   if (*pbstrOut)
6833     TRACE("returning %s\n", debugstr_w(*pbstrOut));
6834   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6835 }
6836 
6837 /******************************************************************************
6838  * VarBstrFromBool (OLEAUT32.116)
6839  *
6840  * Convert a VT_BOOL to a VT_BSTR.
6841  *
6842  * PARAMS
6843  *  boolIn   [I] Source
6844  *  lcid     [I] LCID for the conversion
6845  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6846  *  pbstrOut [O] Destination
6847  *
6848  * RETURNS
6849  *  Success: S_OK.
6850  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6851  *           E_OUTOFMEMORY, if memory allocation fails.
6852  *
6853  * NOTES
6854  *  If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
6855  *  localised text of "True" or "False". To convert a bool into a
6856  *  numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
6857  */
6858 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6859 {
6860   WCHAR szBuff[64];
6861   DWORD dwResId = IDS_TRUE;
6862   LANGID langId;
6863 
6864   TRACE("%d,0x%08x,0x%08x,%p\n", boolIn, lcid, dwFlags, pbstrOut);
6865 
6866   if (!pbstrOut)
6867     return E_INVALIDARG;
6868 
6869   /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
6870    * for variant formatting */
6871   switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
6872   {
6873   case VAR_BOOLONOFF:
6874       dwResId = IDS_ON;
6875       break;
6876   case VAR_BOOLYESNO:
6877       dwResId = IDS_YES;
6878       break;
6879   case VAR_LOCALBOOL:
6880       break;
6881   default:
6882     lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
6883   }
6884 
6885   lcid = ConvertDefaultLocale(lcid);
6886   langId = LANGIDFROMLCID(lcid);
6887   if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
6888     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6889 
6890   if (boolIn == VARIANT_FALSE)
6891     dwResId++; /* Use negative form */
6892 
6893 VarBstrFromBool_GetLocalised:
6894   if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
6895   {
6896     *pbstrOut = SysAllocString(szBuff);
6897     return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6898   }
6899 
6900   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
6901   {
6902     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6903     goto VarBstrFromBool_GetLocalised;
6904   }
6905 
6906   /* Should never get here */
6907   WARN("Failed to load bool text!\n");
6908   return E_OUTOFMEMORY;
6909 }
6910 
6911 /******************************************************************************
6912  * VarBstrFromI1 (OLEAUT32.229)
6913  *
6914  * Convert a VT_I1 to a VT_BSTR.
6915  *
6916  * PARAMS
6917  *  cIn      [I] Source
6918  *  lcid     [I] LCID for the conversion
6919  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6920  *  pbstrOut [O] Destination
6921  *
6922  * RETURNS
6923  *  Success: S_OK.
6924  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6925  *           E_OUTOFMEMORY, if memory allocation fails.
6926  */
6927 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6928 {
6929   ULONG64 ul64 = cIn;
6930 
6931   if (cIn < 0)
6932   {
6933     ul64 = -cIn;
6934     dwFlags |= VAR_NEGATIVE;
6935   }
6936   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6937 }
6938 
6939 /******************************************************************************
6940  * VarBstrFromUI2 (OLEAUT32.230)
6941  *
6942  * Convert a VT_UI2 to a VT_BSTR.
6943  *
6944  * PARAMS
6945  *  usIn     [I] Source
6946  *  lcid     [I] LCID for the conversion
6947  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6948  *  pbstrOut [O] Destination
6949  *
6950  * RETURNS
6951  *  Success: S_OK.
6952  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6953  *           E_OUTOFMEMORY, if memory allocation fails.
6954  */
6955 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6956 {
6957   return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
6958 }
6959 
6960 /******************************************************************************
6961  * VarBstrFromUI4 (OLEAUT32.231)
6962  *
6963  * Convert a VT_UI4 to a VT_BSTR.
6964  *
6965  * PARAMS
6966  *  ulIn     [I] Source
6967  *  lcid     [I] LCID for the conversion
6968  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6969  *  pbstrOut [O] Destination
6970  *
6971  * RETURNS
6972  *  Success: S_OK.
6973  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6974  *           E_OUTOFMEMORY, if memory allocation fails.
6975  */
6976 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6977 {
6978   return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
6979 }
6980 
6981 /******************************************************************************
6982  * VarBstrFromDec (OLEAUT32.232)
6983  *
6984  * Convert a VT_DECIMAL to a VT_BSTR.
6985  *
6986  * PARAMS
6987  *  pDecIn   [I] Source
6988  *  lcid     [I] LCID for the conversion
6989  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6990  *  pbstrOut [O] Destination
6991  *
6992  * RETURNS
6993  *  Success: S_OK.
6994  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6995  *           E_OUTOFMEMORY, if memory allocation fails.
6996  */
6997 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6998 {
6999   WCHAR buff[256];
7000   VARIANT_DI temp;
7001 
7002   if (!pbstrOut)
7003     return E_INVALIDARG;
7004 
7005   VARIANT_DIFromDec(pDecIn, &temp);
7006   VARIANT_DI_tostringW(&temp, buff, 256);
7007 
7008   if (dwFlags & LOCALE_USE_NLS)
7009   {
7010     WCHAR numbuff[256];
7011 
7012     /* Format the number for the locale */
7013     numbuff[0] = '\0';
7014     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
7015                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
7016     TRACE("created NLS string %s\n", debugstr_w(numbuff));
7017     *pbstrOut = SysAllocString(numbuff);
7018   }
7019   else
7020   {
7021     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
7022   }
7023 
7024   TRACE("returning %s\n", debugstr_w(*pbstrOut));
7025   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
7026 }
7027 
7028 /************************************************************************
7029  * VarBstrFromI8 (OLEAUT32.370)
7030  *
7031  * Convert a VT_I8 to a VT_BSTR.
7032  *
7033  * PARAMS
7034  *  llIn     [I] Source
7035  *  lcid     [I] LCID for the conversion
7036  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7037  *  pbstrOut [O] Destination
7038  *
7039  * RETURNS
7040  *  Success: S_OK.
7041  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
7042  *           E_OUTOFMEMORY, if memory allocation fails.
7043  */
7044 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
7045 {
7046   ULONG64 ul64 = llIn;
7047 
7048   if (llIn < 0)
7049   {
7050     ul64 = -llIn;
7051     dwFlags |= VAR_NEGATIVE;
7052   }
7053   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
7054 }
7055 
7056 /************************************************************************
7057  * VarBstrFromUI8 (OLEAUT32.371)
7058  *
7059  * Convert a VT_UI8 to a VT_BSTR.
7060  *
7061  * PARAMS
7062  *  ullIn    [I] Source
7063  *  lcid     [I] LCID for the conversion
7064  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7065  *  pbstrOut [O] Destination
7066  *
7067  * RETURNS
7068  *  Success: S_OK.
7069  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
7070  *           E_OUTOFMEMORY, if memory allocation fails.
7071  */
7072 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
7073 {
7074   return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
7075 }
7076 
7077 /************************************************************************
7078  * VarBstrFromDisp (OLEAUT32.115)
7079  *
7080  * Convert a VT_DISPATCH to a BSTR.
7081  *
7082  * PARAMS
7083  *  pdispIn [I] Source
7084  *  lcid    [I] LCID for conversion
7085  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
7086  *  pbstrOut  [O] Destination
7087  *
7088  * RETURNS
7089  *  Success: S_OK.
7090  *  Failure: E_INVALIDARG, if the source value is invalid
7091  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
7092  */
7093 HRESULT WINAPI VarBstrFromDisp(IDispatch* pdispIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
7094 {
7095   return VARIANT_FromDisp(pdispIn, lcid, pbstrOut, VT_BSTR, dwFlags);
7096 }
7097 
7098 /**********************************************************************
7099  * VarBstrCat (OLEAUT32.313)
7100  *
7101  * Concatenate two BSTR values.
7102  *
7103  * PARAMS
7104  *  pbstrLeft  [I] Source
7105  *  pbstrRight [I] Value to concatenate
7106  *  pbstrOut   [O] Destination
7107  *
7108  * RETURNS
7109  *  Success: S_OK.
7110  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
7111  *           E_OUTOFMEMORY, if memory allocation fails.
7112  */
7113 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
7114 {
7115   unsigned int lenLeft, lenRight;
7116 
7117   TRACE("%s,%s,%p\n",
7118    debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
7119    debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), pbstrOut);
7120 
7121   if (!pbstrOut)
7122     return E_INVALIDARG;
7123 
7124   /* use byte length here to properly handle ansi-allocated BSTRs */
7125   lenLeft = pbstrLeft ? SysStringByteLen(pbstrLeft) : 0;
7126   lenRight = pbstrRight ? SysStringByteLen(pbstrRight) : 0;
7127 
7128   *pbstrOut = SysAllocStringByteLen(NULL, lenLeft + lenRight);
7129   if (!*pbstrOut)
7130     return E_OUTOFMEMORY;
7131 
7132   (*pbstrOut)[0] = '\0';
7133 
7134   if (pbstrLeft)
7135     memcpy(*pbstrOut, pbstrLeft, lenLeft);
7136 
7137   if (pbstrRight)
7138     memcpy((CHAR*)*pbstrOut + lenLeft, pbstrRight, lenRight);
7139 
7140   TRACE("%s\n", debugstr_wn(*pbstrOut, SysStringLen(*pbstrOut)));
7141   return S_OK;
7142 }
7143 
7144 /**********************************************************************
7145  * VarBstrCmp (OLEAUT32.314)
7146  *
7147  * Compare two BSTR values.
7148  *
7149  * PARAMS
7150  *  pbstrLeft  [I] Source
7151  *  pbstrRight [I] Value to compare
7152  *  lcid       [I] LCID for the comparison
7153  *  dwFlags    [I] Flags to pass directly to CompareStringW().
7154  *
7155  * RETURNS
7156  *  VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
7157  *  than, equal to or greater than pbstrRight respectively.
7158  *
7159  * NOTES
7160  *  VARCMP_NULL is NOT returned if either string is NULL unlike MSDN
7161  *  states. A NULL BSTR pointer is equivalent to an empty string.
7162  *  If LCID is equal to 0, a byte by byte comparison is performed.
7163  */
7164 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
7165 {
7166     HRESULT hres;
7167     int ret;
7168 
7169     TRACE("%s,%s,%d,%08x\n",
7170      debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
7171      debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), lcid, dwFlags);
7172 
7173     if (!pbstrLeft || !*pbstrLeft)
7174     {
7175       if (pbstrRight && *pbstrRight)
7176         return VARCMP_LT;
7177     }
7178     else if (!pbstrRight || !*pbstrRight)
7179         return VARCMP_GT;
7180 
7181     if (lcid == 0)
7182     {
7183       unsigned int lenLeft = SysStringByteLen(pbstrLeft);
7184       unsigned int lenRight = SysStringByteLen(pbstrRight);
7185       ret = memcmp(pbstrLeft, pbstrRight, min(lenLeft, lenRight));
7186       if (ret < 0)
7187         return VARCMP_LT;
7188       if (ret > 0)
7189         return VARCMP_GT;
7190       if (lenLeft < lenRight)
7191         return VARCMP_LT;
7192       if (lenLeft > lenRight)
7193         return VARCMP_GT;
7194       return VARCMP_EQ;
7195     }
7196     else
7197     {
7198       unsigned int lenLeft = SysStringLen(pbstrLeft);
7199       unsigned int lenRight = SysStringLen(pbstrRight);
7200 
7201       if (lenLeft == 0 || lenRight == 0)
7202       {
7203           if (lenLeft == 0 && lenRight == 0) return VARCMP_EQ;
7204           return lenLeft < lenRight ? VARCMP_LT : VARCMP_GT;
7205       }
7206 
7207       hres = CompareStringW(lcid, dwFlags, pbstrLeft, lenLeft,
7208               pbstrRight, lenRight) - CSTR_LESS_THAN;
7209       TRACE("%d\n", hres);
7210       return hres;
7211     }
7212 }
7213 
7214 /*
7215  * DATE
7216  */
7217 
7218 /******************************************************************************
7219  * VarDateFromUI1 (OLEAUT32.88)
7220  *
7221  * Convert a VT_UI1 to a VT_DATE.
7222  *
7223  * PARAMS
7224  *  bIn      [I] Source
7225  *  pdateOut [O] Destination
7226  *
7227  * RETURNS
7228  *  S_OK.
7229  */
7230 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
7231 {
7232   return VarR8FromUI1(bIn, pdateOut);
7233 }
7234 
7235 /******************************************************************************
7236  * VarDateFromI2 (OLEAUT32.89)
7237  *
7238  * Convert a VT_I2 to a VT_DATE.
7239  *
7240  * PARAMS
7241  *  sIn      [I] Source
7242  *  pdateOut [O] Destination
7243  *
7244  * RETURNS
7245  *  S_OK.
7246  */
7247 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
7248 {
7249   return VarR8FromI2(sIn, pdateOut);
7250 }
7251 
7252 /******************************************************************************
7253  * VarDateFromI4 (OLEAUT32.90)
7254  *
7255  * Convert a VT_I4 to a VT_DATE.
7256  *
7257  * PARAMS
7258  *  lIn      [I] Source
7259  *  pdateOut [O] Destination
7260  *
7261  * RETURNS
7262  *  S_OK.
7263  */
7264 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
7265 {
7266   return VarDateFromR8(lIn, pdateOut);
7267 }
7268 
7269 /******************************************************************************
7270  * VarDateFromR4 (OLEAUT32.91)
7271  *
7272  * Convert a VT_R4 to a VT_DATE.
7273  *
7274  * PARAMS
7275  *  fltIn    [I] Source
7276  *  pdateOut [O] Destination
7277  *
7278  * RETURNS
7279  *  S_OK.
7280  */
7281 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
7282 {
7283   return VarR8FromR4(fltIn, pdateOut);
7284 }
7285 
7286 /******************************************************************************
7287  * VarDateFromR8 (OLEAUT32.92)
7288  *
7289  * Convert a VT_R8 to a VT_DATE.
7290  *
7291  * PARAMS
7292  *  dblIn    [I] Source
7293  *  pdateOut [O] Destination
7294  *
7295  * RETURNS
7296  *  S_OK.
7297  */
7298 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
7299 {
7300   if (dblIn <= (DATE_MIN - 1.0) || dblIn >= (DATE_MAX + 1.0)) return DISP_E_OVERFLOW;
7301   *pdateOut = (DATE)dblIn;
7302   return S_OK;
7303 }
7304 
7305 /**********************************************************************
7306  * VarDateFromDisp (OLEAUT32.95)
7307  *
7308  * Convert a VT_DISPATCH to a VT_DATE.
7309  *
7310  * PARAMS
7311  *  pdispIn  [I] Source
7312  *  lcid     [I] LCID for conversion
7313  *  pdateOut [O] Destination
7314  *
7315  * RETURNS
7316  *  Success: S_OK.
7317  *  Failure: E_INVALIDARG, if the source value is invalid
7318  *           DISP_E_OVERFLOW, if the value will not fit in the destination
7319  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
7320  */
7321 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
7322 {
7323   return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE, 0);
7324 }
7325 
7326 /******************************************************************************
7327  * VarDateFromBool (OLEAUT32.96)
7328  *
7329  * Convert a VT_BOOL to a VT_DATE.
7330  *
7331  * PARAMS
7332  *  boolIn   [I] Source
7333  *  pdateOut [O] Destination
7334  *
7335  * RETURNS
7336  *  S_OK.
7337  */
7338 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
7339 {
7340   return VarR8FromBool(boolIn, pdateOut);
7341 }
7342 
7343 /**********************************************************************
7344  * VarDateFromCy (OLEAUT32.93)
7345  *
7346  * Convert a VT_CY to a VT_DATE.
7347  *
7348  * PARAMS
7349  *  lIn      [I] Source
7350  *  pdateOut [O] Destination
7351  *
7352  * RETURNS
7353  *  S_OK.
7354  */
7355 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
7356 {
7357   return VarR8FromCy(cyIn, pdateOut);
7358 }
7359 
7360 /* Date string parsing */
7361 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
7362 #define DP_DATESEP 0x02 /* Date separator */
7363 #define DP_MONTH   0x04 /* Month name */
7364 #define DP_AM      0x08 /* AM */
7365 #define DP_PM      0x10 /* PM */
7366 
7367 typedef struct tagDATEPARSE
7368 {
7369     DWORD dwCount;      /* Number of fields found so far (maximum 6) */
7370     DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
7371     DWORD dwFlags[6];   /* Flags for each field */
7372     DWORD dwValues[6];  /* Value of each field */
7373 } DATEPARSE;
7374 
7375 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
7376 
7377 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
7378 
7379 /* Determine if a day is valid in a given month of a given year */
7380 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
7381 {
7382   static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
7383 
7384   if (day && month && month < 13)
7385   {
7386     if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
7387       return TRUE;
7388   }
7389   return FALSE;
7390 }
7391 
7392 /* Possible orders for 3 numbers making up a date */
7393 #define ORDER_MDY 0x01
7394 #define ORDER_YMD 0x02
7395 #define ORDER_YDM 0x04
7396 #define ORDER_DMY 0x08
7397 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
7398 
7399 /* Determine a date for a particular locale, from 3 numbers */
7400 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
7401                                        DWORD offset, SYSTEMTIME *st)
7402 {
7403   DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
7404 
7405   if (!dp->dwCount)
7406   {
7407     v1 = 30; /* Default to (Variant) 0 date part */
7408     v2 = 12;
7409     v3 = 1899;
7410     goto VARIANT_MakeDate_OK;
7411   }
7412 
7413   v1 = dp->dwValues[offset + 0];
7414   v2 = dp->dwValues[offset + 1];
7415   if (dp->dwCount == 2)
7416   {
7417     SYSTEMTIME current;
7418     GetSystemTime(&current);
7419     v3 = current.wYear;
7420   }
7421   else
7422     v3 = dp->dwValues[offset + 2];
7423 
7424   TRACE("(%d,%d,%d,%d,%d)\n", v1, v2, v3, iDate, offset);
7425 
7426   /* If one number must be a month (Because a month name was given), then only
7427    * consider orders with the month in that position.
7428    * If we took the current year as 'v3', then only allow a year in that position.
7429    */
7430   if (dp->dwFlags[offset + 0] & DP_MONTH)
7431   {
7432     dwAllOrders = ORDER_MDY;
7433   }
7434   else if (dp->dwFlags[offset + 1] & DP_MONTH)
7435   {
7436     dwAllOrders = ORDER_DMY;
7437     if (dp->dwCount > 2)
7438       dwAllOrders |= ORDER_YMD;
7439   }
7440   else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
7441   {
7442     dwAllOrders = ORDER_YDM;
7443   }
7444   else
7445   {
7446     dwAllOrders = ORDER_MDY|ORDER_DMY;
7447     if (dp->dwCount > 2)
7448       dwAllOrders |= (ORDER_YMD|ORDER_YDM);
7449   }
7450 
7451 VARIANT_MakeDate_Start:
7452   TRACE("dwAllOrders is 0x%08x\n", dwAllOrders);
7453 
7454   while (dwAllOrders)
7455   {
7456     DWORD dwTemp;
7457 
7458     if (dwCount == 0)
7459     {
7460       /* First: Try the order given by iDate */
7461       switch (iDate)
7462       {
7463       case 0:  dwTry = dwAllOrders & ORDER_MDY; break;
7464       case 1:  dwTry = dwAllOrders & ORDER_DMY; break;
7465       default: dwTry = dwAllOrders & ORDER_YMD; break;
7466       }
7467     }
7468     else if (dwCount == 1)
7469     {
7470       /* Second: Try all the orders compatible with iDate */
7471       switch (iDate)
7472       {
7473       case 0:  dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
7474       case 1:  dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YDM|ORDER_MYD); break;
7475       default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
7476       }
7477     }
7478     else
7479     {
7480       /* Finally: Try any remaining orders */
7481       dwTry = dwAllOrders;
7482     }
7483 
7484     TRACE("Attempt %d, dwTry is 0x%08x\n", dwCount, dwTry);
7485 
7486     dwCount++;
7487     if (!dwTry)
7488       continue;
7489 
7490 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
7491 
7492     if (dwTry & ORDER_MDY)
7493     {
7494       if (VARIANT_IsValidMonthDay(v2,v1,v3))
7495       {
7496         DATE_SWAP(v1,v2);
7497         goto VARIANT_MakeDate_OK;
7498       }
7499       dwAllOrders &= ~ORDER_MDY;
7500     }
7501     if (dwTry & ORDER_YMD)
7502     {
7503       if (VARIANT_IsValidMonthDay(v3,v2,v1))
7504       {
7505         DATE_SWAP(v1,v3);
7506         goto VARIANT_MakeDate_OK;
7507       }
7508       dwAllOrders &= ~ORDER_YMD;
7509     }
7510     if (dwTry & ORDER_YDM)
7511     {
7512       if (VARIANT_IsValidMonthDay(v2,v3,v1))
7513       {
7514         DATE_SWAP(v1,v2);
7515         DATE_SWAP(v2,v3);
7516         goto VARIANT_MakeDate_OK;
7517       }
7518       dwAllOrders &= ~ORDER_YDM;
7519     }
7520     if (dwTry & ORDER_DMY)
7521     {
7522       if (VARIANT_IsValidMonthDay(v1,v2,v3))
7523         goto VARIANT_MakeDate_OK;
7524       dwAllOrders &= ~ORDER_DMY;
7525     }
7526     if (dwTry & ORDER_MYD)
7527     {
7528       /* Only occurs if we are trying a 2 year date as M/Y not D/M */
7529       if (VARIANT_IsValidMonthDay(v3,v1,v2))
7530       {
7531         DATE_SWAP(v1,v3);
7532         DATE_SWAP(v2,v3);
7533         goto VARIANT_MakeDate_OK;
7534       }
7535       dwAllOrders &= ~ORDER_MYD;
7536     }
7537   }
7538 
7539   if (dp->dwCount == 2)
7540   {
7541     /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
7542     v3 = 1; /* 1st of the month */
7543     dwAllOrders = ORDER_YMD|ORDER_MYD;
7544     dp->dwCount = 0; /* Don't return to this code path again */
7545     dwCount = 0;
7546     goto VARIANT_MakeDate_Start;
7547   }
7548 
7549   /* No valid dates were able to be constructed */
7550   return DISP_E_TYPEMISMATCH;
7551 
7552 VARIANT_MakeDate_OK:
7553 
7554   /* Check that the time part is ok */
7555   if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
7556     return DISP_E_TYPEMISMATCH;
7557 
7558   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
7559   if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
7560     st->wHour += 12;
7561   else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
7562     st->wHour = 0;
7563   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
7564 
7565   st->wDay = v1;
7566   st->wMonth = v2;
7567   /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
7568    * be retrieved from:
7569    * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
7570    * But Wine doesn't have/use that key as at the time of writing.
7571    */
7572   st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
7573   TRACE("Returning date %d/%d/%d\n", v1, v2, st->wYear);
7574   return S_OK;
7575 }
7576 
7577 /******************************************************************************
7578  * VarDateFromStr [OLEAUT32.94]
7579  *
7580  * Convert a VT_BSTR to at VT_DATE.
7581  *
7582  * PARAMS
7583  *  strIn    [I] String to convert
7584  *  lcid     [I] Locale identifier for the conversion
7585  *  dwFlags  [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
7586  *  pdateOut [O] Destination for the converted value
7587  *
7588  * RETURNS
7589  *  Success: S_OK. pdateOut contains the converted value.
7590  *  FAILURE: An HRESULT error code indicating the problem.
7591  *
7592  * NOTES
7593  *  Any date format that can be created using the date formats from lcid
7594  *  (Either from kernel Nls functions, variant conversion or formatting) is a
7595  *  valid input to this function. In addition, a few more esoteric formats are
7596  *  also supported for compatibility with the native version. The date is
7597  *  interpreted according to the date settings in the control panel, unless
7598  *  the date is invalid in that format, in which the most compatible format
7599  *  that produces a valid date will be used.
7600  */
7601 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
7602 {
7603   static const USHORT ParseDateTokens[] =
7604   {
7605     LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
7606     LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
7607     LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
7608     LOCALE_SMONTHNAME13,
7609     LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
7610     LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
7611     LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
7612     LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
7613     LOCALE_SABBREVMONTHNAME13,
7614     LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
7615     LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
7616     LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
7617     LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
7618     LOCALE_SABBREVDAYNAME7,
7619     LOCALE_S1159, LOCALE_S2359,
7620     LOCALE_SDATE
7621   };
7622   static const BYTE ParseDateMonths[] =
7623   {
7624     1,2,3,4,5,6,7,8,9,10,11,12,13,
7625     1,2,3,4,5,6,7,8,9,10,11,12,13
7626   };
7627   unsigned int i;
7628   BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
7629   DATEPARSE dp;
7630   DWORD dwDateSeps = 0, iDate = 0;
7631   HRESULT hRet = S_OK;
7632 
7633   if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
7634       (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
7635     return E_INVALIDARG;
7636 
7637   if (!strIn)
7638     return DISP_E_TYPEMISMATCH;
7639 
7640   *pdateOut = 0.0;
7641 
7642   TRACE("(%s,0x%08x,0x%08x,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
7643 
7644   memset(&dp, 0, sizeof(dp));
7645 
7646   GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
7647                  (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
7648   TRACE("iDate is %d\n", iDate);
7649 
7650   /* Get the month/day/am/pm tokens for this locale */
7651   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7652   {
7653     WCHAR buff[128];
7654     LCTYPE lctype =  ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
7655 
7656     /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
7657      *        GetAltMonthNames(). We should really cache these strings too.
7658      */
7659     buff[0] = '\0';
7660     GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
7661     tokens[i] = SysAllocString(buff);
7662     TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
7663   }
7664 
7665   /* Parse the string into our structure */
7666   while (*strIn)
7667   {
7668     if (isdigitW(*strIn))
7669     {
7670       if (dp.dwCount >= 6)
7671       {
7672         hRet = DISP_E_TYPEMISMATCH;
7673         break;
7674       }
7675       dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
7676       dp.dwCount++;
7677       strIn--;
7678     }
7679     else if (isalphaW(*strIn))
7680     {
7681       BOOL bFound = FALSE;
7682 
7683       for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7684       {
7685         DWORD dwLen = strlenW(tokens[i]);
7686         if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
7687         {
7688           if (i <= 25)
7689           {
7690             if (dp.dwCount >= 6)
7691               hRet = DISP_E_TYPEMISMATCH;
7692             else
7693             {
7694               dp.dwValues[dp.dwCount] = ParseDateMonths[i];
7695               dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
7696               dp.dwCount++;
7697             }
7698           }
7699           else if (i > 39 && i < 42)
7700           {
7701             if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
7702               hRet = DISP_E_TYPEMISMATCH;
7703             else
7704             {
7705               dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
7706               dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
7707             }
7708           }
7709           strIn += (dwLen - 1);
7710           bFound = TRUE;
7711           break;
7712         }
7713       }
7714 
7715       if (!bFound)
7716       {
7717         if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
7718             (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7719         {
7720           /* Special case - 'a' and 'p' are recognised as short for am/pm */
7721           if (*strIn == 'a' || *strIn == 'A')
7722           {
7723             dp.dwFlags[dp.dwCount - 1] |= DP_AM;
7724             dp.dwParseFlags |=  DP_AM;
7725           }
7726           else
7727           {
7728             dp.dwFlags[dp.dwCount - 1] |= DP_PM;
7729             dp.dwParseFlags |=  DP_PM;
7730           }
7731           strIn++;
7732         }
7733         else
7734         {
7735           TRACE("No matching token for %s\n", debugstr_w(strIn));
7736           hRet = DISP_E_TYPEMISMATCH;
7737           break;
7738         }
7739       }
7740     }
7741     else if (*strIn == ':' ||  *strIn == '.')
7742     {
7743       if (!dp.dwCount || !strIn[1])
7744         hRet = DISP_E_TYPEMISMATCH;
7745       else
7746         if (tokens[42][0] == *strIn)
7747         {
7748           dwDateSeps++;
7749           if (dwDateSeps > 2)
7750             hRet = DISP_E_TYPEMISMATCH;
7751           else
7752             dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
7753         }
7754         else
7755           dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
7756     }
7757     else if (*strIn == '-' || *strIn == '/')
7758     {
7759       dwDateSeps++;
7760       if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
7761         hRet = DISP_E_TYPEMISMATCH;
7762       else
7763         dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
7764     }
7765     else if (*strIn == ',' || isspaceW(*strIn))
7766     {
7767       if (*strIn == ',' && !strIn[1])
7768         hRet = DISP_E_TYPEMISMATCH;
7769     }
7770     else
7771     {
7772       hRet = DISP_E_TYPEMISMATCH;
7773     }
7774     strIn++;
7775   }
7776 
7777   if (!dp.dwCount || dp.dwCount > 6 ||
7778       (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7779     hRet = DISP_E_TYPEMISMATCH;
7780 
7781   if (SUCCEEDED(hRet))
7782   {
7783     SYSTEMTIME st;
7784     DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
7785 
7786     st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
7787 
7788     /* Figure out which numbers correspond to which fields.
7789      *
7790      * This switch statement works based on the fact that native interprets any
7791      * fields that are not joined with a time separator ('.' or ':') as date
7792      * fields. Thus we construct a value from 0-32 where each set bit indicates
7793      * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
7794      * For valid permutations, we set dwOffset to point to the first date field
7795      * and shorten dp.dwCount by the number of time fields found. The real
7796      * magic here occurs in VARIANT_MakeDate() above, where we determine what
7797      * each date number must represent in the context of iDate.
7798      */
7799     TRACE("0x%08x\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
7800 
7801     switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
7802     {
7803     case 0x1: /* TT TTDD TTDDD */
7804       if (dp.dwCount > 3 &&
7805           ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
7806           (dp.dwFlags[4] & (DP_AM|DP_PM))))
7807         hRet = DISP_E_TYPEMISMATCH;
7808       else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
7809         hRet = DISP_E_TYPEMISMATCH;
7810       st.wHour = dp.dwValues[0];
7811       st.wMinute  = dp.dwValues[1];
7812       dp.dwCount -= 2;
7813       dwOffset = 2;
7814       break;
7815 
7816     case 0x3: /* TTT TTTDD TTTDDD */
7817       if (dp.dwCount > 4 &&
7818           ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
7819           (dp.dwFlags[5] & (DP_AM|DP_PM))))
7820         hRet = DISP_E_TYPEMISMATCH;
7821       else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
7822         hRet = DISP_E_TYPEMISMATCH;
7823       st.wHour   = dp.dwValues[0];
7824       st.wMinute = dp.dwValues[1];
7825       st.wSecond = dp.dwValues[2];
7826       dwOffset = 3;
7827       dp.dwCount -= 3;
7828       break;
7829 
7830     case 0x4: /* DDTT */
7831       if (dp.dwCount != 4 ||
7832           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7833         hRet = DISP_E_TYPEMISMATCH;
7834 
7835       st.wHour = dp.dwValues[2];
7836       st.wMinute  = dp.dwValues[3];
7837       dp.dwCount -= 2;
7838       break;
7839 
7840    case 0x0: /* T DD DDD TDDD TDDD */
7841       if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
7842       {
7843         st.wHour = dp.dwValues[0]; /* T */
7844         dp.dwCount = 0;
7845         break;
7846       }
7847       else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
7848       {
7849         hRet = DISP_E_TYPEMISMATCH;
7850       }
7851       else if (dp.dwCount == 3)
7852       {
7853         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
7854         {
7855           dp.dwCount = 2;
7856           st.wHour = dp.dwValues[0];
7857           dwOffset = 1;
7858           break;
7859         }
7860         if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
7861         {
7862           dp.dwCount = 2;
7863           st.wHour = dp.dwValues[2];
7864           break;
7865         }
7866         else if (dp.dwParseFlags & (DP_AM|DP_PM))
7867           hRet = DISP_E_TYPEMISMATCH;
7868       }
7869       else if (dp.dwCount == 4)
7870       {
7871         dp.dwCount = 3;
7872         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
7873         {
7874           st.wHour = dp.dwValues[0];
7875           dwOffset = 1;
7876         }
7877         else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
7878         {
7879           st.wHour = dp.dwValues[3];
7880         }
7881         else
7882           hRet = DISP_E_TYPEMISMATCH;
7883         break;
7884       }
7885       /* .. fall through .. */
7886 
7887     case 0x8: /* DDDTT */
7888       if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
7889           (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
7890            (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
7891            dp.dwCount == 4 || dp.dwCount == 6)
7892         hRet = DISP_E_TYPEMISMATCH;
7893       st.wHour   = dp.dwValues[3];
7894       st.wMinute = dp.dwValues[4];
7895       if (dp.dwCount == 5)
7896         dp.dwCount -= 2;
7897       break;
7898 
7899     case 0xC: /* DDTTT */
7900       if (dp.dwCount != 5 ||
7901           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7902         hRet = DISP_E_TYPEMISMATCH;
7903       st.wHour   = dp.dwValues[2];
7904       st.wMinute = dp.dwValues[3];
7905       st.wSecond = dp.dwValues[4];
7906       dp.dwCount -= 3;
7907       break;
7908 
7909     case 0x18: /* DDDTTT */
7910       if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
7911           (dp.dwFlags[2] & (DP_AM|DP_PM)))
7912         hRet = DISP_E_TYPEMISMATCH;
7913       st.wHour   = dp.dwValues[3];
7914       st.wMinute = dp.dwValues[4];
7915       st.wSecond = dp.dwValues[5];
7916       dp.dwCount -= 3;
7917       break;
7918 
7919     default:
7920       hRet = DISP_E_TYPEMISMATCH;
7921       break;
7922     }
7923 
7924     if (SUCCEEDED(hRet))
7925     {
7926       hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
7927 
7928       if (dwFlags & VAR_TIMEVALUEONLY)
7929       {
7930         st.wYear = 1899;
7931         st.wMonth = 12;
7932         st.wDay = 30;
7933       }
7934       else if (dwFlags & VAR_DATEVALUEONLY)
7935        st.wHour = st.wMinute = st.wSecond = 0;
7936 
7937       /* Finally, convert the value to a VT_DATE */
7938       if (SUCCEEDED(hRet))
7939         hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
7940     }
7941   }
7942 
7943   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7944     SysFreeString(tokens[i]);
7945   return hRet;
7946 }
7947 
7948 /******************************************************************************
7949  * VarDateFromI1 (OLEAUT32.221)
7950  *
7951  * Convert a VT_I1 to a VT_DATE.
7952  *
7953  * PARAMS
7954  *  cIn      [I] Source
7955  *  pdateOut [O] Destination
7956  *
7957  * RETURNS
7958  *  S_OK.
7959  */
7960 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
7961 {
7962   return VarR8FromI1(cIn, pdateOut);
7963 }
7964 
7965 /******************************************************************************
7966  * VarDateFromUI2 (OLEAUT32.222)
7967  *
7968  * Convert a VT_UI2 to a VT_DATE.
7969  *
7970  * PARAMS
7971  *  uiIn     [I] Source
7972  *  pdateOut [O] Destination
7973  *
7974  * RETURNS
7975  *  S_OK.
7976  */
7977 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
7978 {
7979   return VarR8FromUI2(uiIn, pdateOut);
7980 }
7981 
7982 /******************************************************************************
7983  * VarDateFromUI4 (OLEAUT32.223)
7984  *
7985  * Convert a VT_UI4 to a VT_DATE.
7986  *
7987  * PARAMS
7988  *  ulIn     [I] Source
7989  *  pdateOut [O] Destination
7990  *
7991  * RETURNS
7992  *  S_OK.
7993  */
7994 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
7995 {
7996   return VarDateFromR8(ulIn, pdateOut);
7997 }
7998 
7999 /**********************************************************************
8000  * VarDateFromDec (OLEAUT32.224)
8001  *
8002  * Convert a VT_DECIMAL to a VT_DATE.
8003  *
8004  * PARAMS
8005  *  pdecIn   [I] Source
8006  *  pdateOut [O] Destination
8007  *
8008  * RETURNS
8009  *  S_OK.
8010  */
8011 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
8012 {
8013   return VarR8FromDec(pdecIn, pdateOut);
8014 }
8015 
8016 /******************************************************************************
8017  * VarDateFromI8 (OLEAUT32.364)
8018  *
8019  * Convert a VT_I8 to a VT_DATE.
8020  *
8021  * PARAMS
8022  *  llIn     [I] Source
8023  *  pdateOut [O] Destination
8024  *
8025  * RETURNS
8026  *  Success: S_OK.
8027  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
8028  */
8029 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
8030 {
8031   if (llIn < DATE_MIN || llIn > DATE_MAX) return DISP_E_OVERFLOW;
8032   *pdateOut = (DATE)llIn;
8033   return S_OK;
8034 }
8035 
8036 /******************************************************************************
8037  * VarDateFromUI8 (OLEAUT32.365)
8038  *
8039  * Convert a VT_UI8 to a VT_DATE.
8040  *
8041  * PARAMS
8042  *  ullIn    [I] Source
8043  *  pdateOut [O] Destination
8044  *
8045  * RETURNS
8046  *  Success: S_OK.
8047  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
8048  */
8049 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
8050 {
8051   if (ullIn > DATE_MAX) return DISP_E_OVERFLOW;
8052   *pdateOut = (DATE)ullIn;
8053   return S_OK;
8054 }
8055