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