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