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