Also scan HKEY_CURRENT_USER for shell namespace extensions in
[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 *= 4294967296.0F;
2966     highPart *= 4294967296.0F;
2967   }
2968   else
2969     highPart = 0.0;
2970
2971   *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
2972   return S_OK;
2973 }
2974
2975 /************************************************************************
2976  * VarR4FromI8 (OLEAUT32.360)
2977  *
2978  * Convert a VT_I8 to a VT_R4.
2979  *
2980  * PARAMS
2981  *  ullIn   [I] Source
2982  *  pFltOut [O] Destination
2983  *
2984  * RETURNS
2985  *  S_OK.
2986  */
2987 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2988 {
2989   return _VarR4FromI8(llIn, pFltOut);
2990 }
2991
2992 /************************************************************************
2993  * VarR4FromUI8 (OLEAUT32.361)
2994  *
2995  * Convert a VT_UI8 to a VT_R4.
2996  *
2997  * PARAMS
2998  *  ullIn   [I] Source
2999  *  pFltOut [O] Destination
3000  *
3001  * RETURNS
3002  *  S_OK.
3003  */
3004 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
3005 {
3006   return _VarR4FromUI8(ullIn, pFltOut);
3007 }
3008
3009 /************************************************************************
3010  * VarR4CmpR8 (OLEAUT32.316)
3011  *
3012  * Compare a VT_R4 to a VT_R8.
3013  *
3014  * PARAMS
3015  *  fltLeft  [I] Source
3016  *  dblRight [I] Value to compare
3017  *
3018  * RETURNS
3019  *  VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
3020  *  equal to or greater than dblRight respectively.
3021  */
3022 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
3023 {
3024   if (fltLeft < dblRight)
3025     return VARCMP_LT;
3026   else if (fltLeft > dblRight)
3027     return VARCMP_GT;
3028   return VARCMP_EQ;
3029 }
3030
3031 /* R8
3032  */
3033
3034 /************************************************************************
3035  * VarR8FromUI1 (OLEAUT32.78)
3036  *
3037  * Convert a VT_UI1 to a VT_R8.
3038  *
3039  * PARAMS
3040  *  bIn     [I] Source
3041  *  pDblOut [O] Destination
3042  *
3043  * RETURNS
3044  *  S_OK.
3045  */
3046 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
3047 {
3048   return _VarR8FromUI1(bIn, pDblOut);
3049 }
3050
3051 /************************************************************************
3052  * VarR8FromI2 (OLEAUT32.79)
3053  *
3054  * Convert a VT_I2 to a VT_R8.
3055  *
3056  * PARAMS
3057  *  sIn     [I] Source
3058  *  pDblOut [O] Destination
3059  *
3060  * RETURNS
3061  *  S_OK.
3062  */
3063 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
3064 {
3065   return _VarR8FromI2(sIn, pDblOut);
3066 }
3067
3068 /************************************************************************
3069  * VarR8FromI4 (OLEAUT32.80)
3070  *
3071  * Convert a VT_I4 to a VT_R8.
3072  *
3073  * PARAMS
3074  *  sIn     [I] Source
3075  *  pDblOut [O] Destination
3076  *
3077  * RETURNS
3078  *  S_OK.
3079  */
3080 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
3081 {
3082   return _VarR8FromI4(lIn, pDblOut);
3083 }
3084
3085 /************************************************************************
3086  * VarR8FromR4 (OLEAUT32.81)
3087  *
3088  * Convert a VT_R4 to a VT_R8.
3089  *
3090  * PARAMS
3091  *  fltIn   [I] Source
3092  *  pDblOut [O] Destination
3093  *
3094  * RETURNS
3095  *  S_OK.
3096  */
3097 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
3098 {
3099   return _VarR8FromR4(fltIn, pDblOut);
3100 }
3101
3102 /************************************************************************
3103  * VarR8FromCy (OLEAUT32.82)
3104  *
3105  * Convert a VT_CY to a VT_R8.
3106  *
3107  * PARAMS
3108  *  cyIn    [I] Source
3109  *  pDblOut [O] Destination
3110  *
3111  * RETURNS
3112  *  S_OK.
3113  */
3114 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
3115 {
3116   return _VarR8FromCy(cyIn, pDblOut);
3117 }
3118
3119 /************************************************************************
3120  * VarR8FromDate (OLEAUT32.83)
3121  *
3122  * Convert a VT_DATE to a VT_R8.
3123  *
3124  * PARAMS
3125  *  dateIn  [I] Source
3126  *  pDblOut [O] Destination
3127  *
3128  * RETURNS
3129  *  S_OK.
3130  */
3131 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
3132 {
3133   return _VarR8FromDate(dateIn, pDblOut);
3134 }
3135
3136 /************************************************************************
3137  * VarR8FromStr (OLEAUT32.84)
3138  *
3139  * Convert a VT_BSTR to a VT_R8.
3140  *
3141  * PARAMS
3142  *  strIn   [I] Source
3143  *  lcid    [I] LCID for the conversion
3144  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3145  *  pDblOut [O] Destination
3146  *
3147  * RETURNS
3148  *  Success: S_OK.
3149  *  Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3150  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3151  */
3152 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3153 {
3154   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDblOut, VT_R8);
3155 }
3156
3157 /************************************************************************
3158  * VarR8FromDisp (OLEAUT32.85)
3159  *
3160  * Convert a VT_DISPATCH to a VT_R8.
3161  *
3162  * PARAMS
3163  *  pdispIn  [I] Source
3164  *  lcid     [I] LCID for conversion
3165  *  pDblOut  [O] Destination
3166  *
3167  * RETURNS
3168  *  Success: S_OK.
3169  *  Failure: E_INVALIDARG, if the source value is invalid
3170  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3171  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3172  */
3173 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3174 {
3175   return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8);
3176 }
3177
3178 /************************************************************************
3179  * VarR8FromBool (OLEAUT32.86)
3180  *
3181  * Convert a VT_BOOL to a VT_R8.
3182  *
3183  * PARAMS
3184  *  boolIn  [I] Source
3185  *  pDblOut [O] Destination
3186  *
3187  * RETURNS
3188  *  S_OK.
3189  */
3190 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
3191 {
3192   return VarR8FromI2(boolIn, pDblOut);
3193 }
3194
3195 /************************************************************************
3196  * VarR8FromI1 (OLEAUT32.217)
3197  *
3198  * Convert a VT_I1 to a VT_R8.
3199  *
3200  * PARAMS
3201  *  cIn     [I] Source
3202  *  pDblOut [O] Destination
3203  *
3204  * RETURNS
3205  *  Success: S_OK.
3206  *  Failure: E_INVALIDARG, if the source value is invalid
3207  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3208  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3209  */
3210 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3211 {
3212   return _VarR8FromI1(cIn, pDblOut);
3213 }
3214
3215 /************************************************************************
3216  * VarR8FromUI2 (OLEAUT32.218)
3217  *
3218  * Convert a VT_UI2 to a VT_R8.
3219  *
3220  * PARAMS
3221  *  usIn    [I] Source
3222  *  pDblOut [O] Destination
3223  *
3224  * RETURNS
3225  *  Success: S_OK.
3226  *  Failure: E_INVALIDARG, if the source value is invalid
3227  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3228  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3229  */
3230 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3231 {
3232   return _VarR8FromUI2(usIn, pDblOut);
3233 }
3234
3235 /************************************************************************
3236  * VarR8FromUI4 (OLEAUT32.219)
3237  *
3238  * Convert a VT_UI4 to a VT_R8.
3239  *
3240  * PARAMS
3241  *  ulIn    [I] Source
3242  *  pDblOut [O] Destination
3243  *
3244  * RETURNS
3245  *  Success: S_OK.
3246  *  Failure: E_INVALIDARG, if the source value is invalid
3247  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3248  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3249  */
3250 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3251 {
3252   return _VarR8FromUI4(ulIn, pDblOut);
3253 }
3254
3255 /************************************************************************
3256  * VarR8FromDec (OLEAUT32.220)
3257  *
3258  * Convert a VT_DECIMAL to a VT_R8.
3259  *
3260  * PARAMS
3261  *  pDecIn  [I] Source
3262  *  pDblOut [O] Destination
3263  *
3264  * RETURNS
3265  *  Success: S_OK.
3266  *  Failure: E_INVALIDARG, if the source value is invalid.
3267  */
3268 HRESULT WINAPI VarR8FromDec(DECIMAL* pDecIn, double *pDblOut)
3269 {
3270   BYTE scale = DEC_SCALE(pDecIn);
3271   double divisor = 1.0, highPart;
3272
3273   if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
3274     return E_INVALIDARG;
3275
3276   while (scale--)
3277     divisor *= 10;
3278
3279   if (DEC_SIGN(pDecIn))
3280     divisor = -divisor;
3281
3282   if (DEC_HI32(pDecIn))
3283   {
3284     highPart = (double)DEC_HI32(pDecIn) / divisor;
3285     highPart *= 4294967296.0F;
3286     highPart *= 4294967296.0F;
3287   }
3288   else
3289     highPart = 0.0;
3290
3291   *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
3292   return S_OK;
3293 }
3294
3295 /************************************************************************
3296  * VarR8FromI8 (OLEAUT32.362)
3297  *
3298  * Convert a VT_I8 to a VT_R8.
3299  *
3300  * PARAMS
3301  *  ullIn   [I] Source
3302  *  pDblOut [O] Destination
3303  *
3304  * RETURNS
3305  *  S_OK.
3306  */
3307 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3308 {
3309   return _VarR8FromI8(llIn, pDblOut);
3310 }
3311
3312 /************************************************************************
3313  * VarR8FromUI8 (OLEAUT32.363)
3314  *
3315  * Convert a VT_UI8 to a VT_R8.
3316  *
3317  * PARAMS
3318  *  ullIn   [I] Source
3319  *  pDblOut [O] Destination
3320  *
3321  * RETURNS
3322  *  S_OK.
3323  */
3324 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3325 {
3326   return _VarR8FromUI8(ullIn, pDblOut);
3327 }
3328
3329 /************************************************************************
3330  * VarR8Pow (OLEAUT32.315)
3331  *
3332  * Raise a VT_R8 to a power.
3333  *
3334  * PARAMS
3335  *  dblLeft [I] Source
3336  *  dblPow  [I] Power to raise dblLeft by
3337  *  pDblOut [O] Destination
3338  *
3339  * RETURNS
3340  *  S_OK. pDblOut contains dblLeft to the power of dblRight.
3341  */
3342 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3343 {
3344   *pDblOut = pow(dblLeft, dblPow);
3345   return S_OK;
3346 }
3347
3348 /************************************************************************
3349  * VarR8Round (OLEAUT32.317)
3350  *
3351  * Round a VT_R8 to a given number of decimal points.
3352  *
3353  * PARAMS
3354  *  dblIn   [I] Source
3355  *  nDig    [I] Number of decimal points to round to
3356  *  pDblOut [O] Destination for rounded number
3357  *
3358  * RETURNS
3359  *  Success: S_OK. pDblOut is rounded to nDig digits.
3360  *  Failure: E_INVALIDARG, if cDecimals is less than 0.
3361  *
3362  * NOTES
3363  *  The native version of this function rounds using the internal
3364  *  binary representation of the number. Wine uses the dutch rounding
3365  *  convention, so therefore small differences can occur in the value returned.
3366  *  MSDN says that you should use your own rounding function if you want
3367  *  rounding to be predictable in your application.
3368  */
3369 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3370 {
3371   double scale, whole, fract;
3372
3373   if (nDig < 0)
3374     return E_INVALIDARG;
3375
3376   scale = pow(10.0, nDig);
3377
3378   dblIn *= scale;
3379   whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3380   fract = dblIn - whole;
3381
3382   if (fract > 0.5)
3383     dblIn = whole + 1.0;
3384   else if (fract == 0.5)
3385     dblIn = whole + fmod(whole, 2.0);
3386   else if (fract >= 0.0)
3387     dblIn = whole;
3388   else if (fract == -0.5)
3389     dblIn = whole - fmod(whole, 2.0);
3390   else if (fract > -0.5)
3391     dblIn = whole;
3392   else
3393     dblIn = whole - 1.0;
3394
3395   *pDblOut = dblIn / scale;
3396   return S_OK;
3397 }
3398
3399 /* CY
3400  */
3401
3402 /* Powers of 10 from 0..4 D.P. */
3403 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3404   CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
3405
3406 /************************************************************************
3407  * VarCyFromUI1 (OLEAUT32.98)
3408  *
3409  * Convert a VT_UI1 to a VT_CY.
3410  *
3411  * PARAMS
3412  *  bIn    [I] Source
3413  *  pCyOut [O] Destination
3414  *
3415  * RETURNS
3416  *  Success: S_OK.
3417  *  Failure: E_INVALIDARG, if the source value is invalid
3418  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3419  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3420  */
3421 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
3422 {
3423   return VarCyFromR8(bIn, pCyOut);
3424 }
3425
3426 /************************************************************************
3427  * VarCyFromI2 (OLEAUT32.99)
3428  *
3429  * Convert a VT_I2 to a VT_CY.
3430  *
3431  * PARAMS
3432  *  sIn    [I] Source
3433  *  pCyOut [O] Destination
3434  *
3435  * RETURNS
3436  *  Success: S_OK.
3437  *  Failure: E_INVALIDARG, if the source value is invalid
3438  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3439  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3440  */
3441 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
3442 {
3443   return VarCyFromR8(sIn, pCyOut);
3444 }
3445
3446 /************************************************************************
3447  * VarCyFromI4 (OLEAUT32.100)
3448  *
3449  * Convert a VT_I4 to a VT_CY.
3450  *
3451  * PARAMS
3452  *  sIn    [I] Source
3453  *  pCyOut [O] Destination
3454  *
3455  * RETURNS
3456  *  Success: S_OK.
3457  *  Failure: E_INVALIDARG, if the source value is invalid
3458  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3459  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3460  */
3461 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
3462 {
3463   return VarCyFromR8(lIn, pCyOut);
3464 }
3465
3466 /************************************************************************
3467  * VarCyFromR4 (OLEAUT32.101)
3468  *
3469  * Convert a VT_R4 to a VT_CY.
3470  *
3471  * PARAMS
3472  *  fltIn  [I] Source
3473  *  pCyOut [O] Destination
3474  *
3475  * RETURNS
3476  *  Success: S_OK.
3477  *  Failure: E_INVALIDARG, if the source value is invalid
3478  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3479  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3480  */
3481 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
3482 {
3483   return VarCyFromR8(fltIn, pCyOut);
3484 }
3485
3486 /************************************************************************
3487  * VarCyFromR8 (OLEAUT32.102)
3488  *
3489  * Convert a VT_R8 to a VT_CY.
3490  *
3491  * PARAMS
3492  *  dblIn  [I] Source
3493  *  pCyOut [O] Destination
3494  *
3495  * RETURNS
3496  *  Success: S_OK.
3497  *  Failure: E_INVALIDARG, if the source value is invalid
3498  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3499  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3500  */
3501 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3502 {
3503 #if defined(__GNUC__) && defined(__i386__)
3504   /* This code gives identical results to Win32 on Intel.
3505    * Here we use fp exceptions to catch overflows when storing the value.
3506    */
3507   static const unsigned short r8_fpcontrol = 0x137f;
3508   static const double r8_multiplier = CY_MULTIPLIER_F;
3509   unsigned short old_fpcontrol, result_fpstatus;
3510
3511   /* Clear exceptions, save the old fp state and load the new state */
3512   __asm__ __volatile__( "fnclex" );
3513   __asm__ __volatile__( "fstcw %0"   :   "=m" (old_fpcontrol) : );
3514   __asm__ __volatile__( "fldcw %0"   : : "m"  (r8_fpcontrol) );
3515   /* Perform the conversion. */
3516   __asm__ __volatile__( "fldl  %0"   : : "m"  (dblIn) );
3517   __asm__ __volatile__( "fmull %0"   : : "m"  (r8_multiplier) );
3518   __asm__ __volatile__( "fistpll %0" : : "m"  (*pCyOut) );
3519   /* Save the resulting fp state, load the old state and clear exceptions */
3520   __asm__ __volatile__( "fstsw %0"   :   "=m" (result_fpstatus) : );
3521   __asm__ __volatile__( "fnclex" );
3522   __asm__ __volatile__( "fldcw %0"   : : "m"  (old_fpcontrol) );
3523
3524   if (result_fpstatus & 0x9) /* Overflow | Invalid */
3525     return DISP_E_OVERFLOW;
3526   return S_OK;
3527 #else
3528   /* This version produces slightly different results for boundary cases */
3529   if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3530     return DISP_E_OVERFLOW;
3531   dblIn *= CY_MULTIPLIER_F;
3532   VARIANT_DutchRound(LONG64, dblIn, pCyOut->int64);
3533 #endif
3534   return S_OK;
3535 }
3536
3537 /************************************************************************
3538  * VarCyFromDate (OLEAUT32.103)
3539  *
3540  * Convert a VT_DATE to a VT_CY.
3541  *
3542  * PARAMS
3543  *  dateIn [I] Source
3544  *  pCyOut [O] Destination
3545  *
3546  * RETURNS
3547  *  Success: S_OK.
3548  *  Failure: E_INVALIDARG, if the source value is invalid
3549  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3550  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3551  */
3552 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
3553 {
3554   return VarCyFromR8(dateIn, pCyOut);
3555 }
3556
3557 /************************************************************************
3558  * VarCyFromStr (OLEAUT32.104)
3559  *
3560  * Convert a VT_BSTR to a VT_CY.
3561  *
3562  * PARAMS
3563  *  strIn   [I] Source
3564  *  lcid    [I] LCID for the conversion
3565  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3566  *  pCyOut  [O] Destination
3567  *
3568  * RETURNS
3569  *  Success: S_OK.
3570  *  Failure: E_INVALIDARG, if the source value is invalid
3571  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3572  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3573  */
3574 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
3575 {
3576   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pCyOut, VT_CY);
3577 }
3578
3579 /************************************************************************
3580  * VarCyFromDisp (OLEAUT32.105)
3581  *
3582  * Convert a VT_DISPATCH to a VT_CY.
3583  *
3584  * PARAMS
3585  *  pdispIn [I] Source
3586  *  lcid    [I] LCID for conversion
3587  *  pCyOut  [O] Destination
3588  *
3589  * RETURNS
3590  *  Success: S_OK.
3591  *  Failure: E_INVALIDARG, if the source value is invalid
3592  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3593  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3594  */
3595 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
3596 {
3597   return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY);
3598 }
3599
3600 /************************************************************************
3601  * VarCyFromBool (OLEAUT32.106)
3602  *
3603  * Convert a VT_BOOL to a VT_CY.
3604  *
3605  * PARAMS
3606  *  boolIn [I] Source
3607  *  pCyOut [O] Destination
3608  *
3609  * RETURNS
3610  *  Success: S_OK.
3611  *  Failure: E_INVALIDARG, if the source value is invalid
3612  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3613  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3614  *
3615  * NOTES
3616  *  While the sign of the boolean is stored in the currency, the value is
3617  *  converted to either 0 or 1.
3618  */
3619 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
3620 {
3621   return VarCyFromR8(boolIn, pCyOut);
3622 }
3623
3624 /************************************************************************
3625  * VarCyFromI1 (OLEAUT32.225)
3626  *
3627  * Convert a VT_I1 to a VT_CY.
3628  *
3629  * PARAMS
3630  *  cIn    [I] Source
3631  *  pCyOut [O] Destination
3632  *
3633  * RETURNS
3634  *  Success: S_OK.
3635  *  Failure: E_INVALIDARG, if the source value is invalid
3636  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3637  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3638  */
3639 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3640 {
3641   return VarCyFromR8(cIn, pCyOut);
3642 }
3643
3644 /************************************************************************
3645  * VarCyFromUI2 (OLEAUT32.226)
3646  *
3647  * Convert a VT_UI2 to a VT_CY.
3648  *
3649  * PARAMS
3650  *  usIn   [I] Source
3651  *  pCyOut [O] Destination
3652  *
3653  * RETURNS
3654  *  Success: S_OK.
3655  *  Failure: E_INVALIDARG, if the source value is invalid
3656  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3657  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3658  */
3659 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
3660 {
3661   return VarCyFromR8(usIn, pCyOut);
3662 }
3663
3664 /************************************************************************
3665  * VarCyFromUI4 (OLEAUT32.227)
3666  *
3667  * Convert a VT_UI4 to a VT_CY.
3668  *
3669  * PARAMS
3670  *  ulIn   [I] Source
3671  *  pCyOut [O] Destination
3672  *
3673  * RETURNS
3674  *  Success: S_OK.
3675  *  Failure: E_INVALIDARG, if the source value is invalid
3676  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3677  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3678  */
3679 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
3680 {
3681   return VarCyFromR8(ulIn, pCyOut);
3682 }
3683
3684 /************************************************************************
3685  * VarCyFromDec (OLEAUT32.228)
3686  *
3687  * Convert a VT_DECIMAL to a VT_CY.
3688  *
3689  * PARAMS
3690  *  pdecIn  [I] Source
3691  *  pCyOut  [O] Destination
3692  *
3693  * RETURNS
3694  *  Success: S_OK.
3695  *  Failure: E_INVALIDARG, if the source value is invalid
3696  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3697  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3698  */
3699 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
3700 {
3701   DECIMAL rounded;
3702   HRESULT hRet;
3703
3704   hRet = VarDecRound(pdecIn, 4, &rounded);
3705
3706   if (SUCCEEDED(hRet))
3707   {
3708     double d;
3709
3710     if (DEC_HI32(&rounded))
3711       return DISP_E_OVERFLOW;
3712
3713     /* Note: Without the casts this promotes to int64 which loses precision */
3714     d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
3715     if (DEC_SIGN(&rounded))
3716       d = -d;
3717     return VarCyFromR8(d, pCyOut);
3718   }
3719   return hRet;
3720 }
3721
3722 /************************************************************************
3723  * VarCyFromI8 (OLEAUT32.366)
3724  *
3725  * Convert a VT_I8 to a VT_CY.
3726  *
3727  * PARAMS
3728  *  ullIn  [I] Source
3729  *  pCyOut [O] Destination
3730  *
3731  * RETURNS
3732  *  Success: S_OK.
3733  *  Failure: E_INVALIDARG, if the source value is invalid
3734  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3735  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3736  */
3737 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
3738 {
3739   if (llIn <= (I8_MIN/CY_MULTIPLIER) || llIn >= (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
3740   pCyOut->int64 = llIn * CY_MULTIPLIER;
3741   return S_OK;
3742 }
3743
3744 /************************************************************************
3745  * VarCyFromUI8 (OLEAUT32.375)
3746  *
3747  * Convert a VT_UI8 to a VT_CY.
3748  *
3749  * PARAMS
3750  *  ullIn  [I] Source
3751  *  pCyOut [O] Destination
3752  *
3753  * RETURNS
3754  *  Success: S_OK.
3755  *  Failure: E_INVALIDARG, if the source value is invalid
3756  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3757  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3758  */
3759 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
3760 {
3761   return VarCyFromR8(ullIn, pCyOut);
3762 }
3763
3764 /************************************************************************
3765  * VarCyAdd (OLEAUT32.299)
3766  *
3767  * Add one CY to another.
3768  *
3769  * PARAMS
3770  *  cyLeft  [I] Source
3771  *  cyRight [I] Value to add
3772  *  pCyOut  [O] Destination
3773  *
3774  * RETURNS
3775  *  Success: S_OK.
3776  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3777  */
3778 HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
3779 {
3780   double l,r;
3781   _VarR8FromCy(cyLeft, &l);
3782   _VarR8FromCy(cyRight, &r);
3783   l = l + r;
3784   return VarCyFromR8(l, pCyOut);
3785 }
3786
3787 /************************************************************************
3788  * VarCyMul (OLEAUT32.303)
3789  *
3790  * Multiply one CY by another.
3791  *
3792  * PARAMS
3793  *  cyLeft  [I] Source
3794  *  cyRight [I] Value to multiply by
3795  *  pCyOut  [O] Destination
3796  *
3797  * RETURNS
3798  *  Success: S_OK.
3799  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3800  */
3801 HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
3802 {
3803   double l,r;
3804   _VarR8FromCy(cyLeft, &l);
3805   _VarR8FromCy(cyRight, &r);
3806   l = l * r;
3807   return VarCyFromR8(l, pCyOut);
3808 }
3809
3810 /************************************************************************
3811  * VarCyMulI4 (OLEAUT32.304)
3812  *
3813  * Multiply one CY by a VT_I4.
3814  *
3815  * PARAMS
3816  *  cyLeft  [I] Source
3817  *  lRight  [I] Value to multiply by
3818  *  pCyOut  [O] Destination
3819  *
3820  * RETURNS
3821  *  Success: S_OK.
3822  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3823  */
3824 HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
3825 {
3826   double d;
3827
3828   _VarR8FromCy(cyLeft, &d);
3829   d = d * lRight;
3830   return VarCyFromR8(d, pCyOut);
3831 }
3832
3833 /************************************************************************
3834  * VarCySub (OLEAUT32.305)
3835  *
3836  * Subtract one CY from another.
3837  *
3838  * PARAMS
3839  *  cyLeft  [I] Source
3840  *  cyRight [I] Value to subtract
3841  *  pCyOut  [O] Destination
3842  *
3843  * RETURNS
3844  *  Success: S_OK.
3845  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3846  */
3847 HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
3848 {
3849   double l,r;
3850   _VarR8FromCy(cyLeft, &l);
3851   _VarR8FromCy(cyRight, &r);
3852   l = l - r;
3853   return VarCyFromR8(l, pCyOut);
3854 }
3855
3856 /************************************************************************
3857  * VarCyAbs (OLEAUT32.306)
3858  *
3859  * Convert a VT_CY into its absolute value.
3860  *
3861  * PARAMS
3862  *  cyIn   [I] Source
3863  *  pCyOut [O] Destination
3864  *
3865  * RETURNS
3866  *  Success: S_OK. pCyOut contains the absolute value.
3867  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3868  */
3869 HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
3870 {
3871   if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3872     return DISP_E_OVERFLOW;
3873
3874   pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3875   return S_OK;
3876 }
3877
3878 /************************************************************************
3879  * VarCyFix (OLEAUT32.307)
3880  *
3881  * Return the integer part of a VT_CY.
3882  *
3883  * PARAMS
3884  *  cyIn   [I] Source
3885  *  pCyOut [O] Destination
3886  *
3887  * RETURNS
3888  *  Success: S_OK.
3889  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3890  *
3891  * NOTES
3892  *  - The difference between this function and VarCyInt() is that VarCyInt() rounds
3893  *    negative numbers away from 0, while this function rounds them towards zero.
3894  */
3895 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
3896 {
3897   pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3898   pCyOut->int64 *= CY_MULTIPLIER;
3899   return S_OK;
3900 }
3901
3902 /************************************************************************
3903  * VarCyInt (OLEAUT32.308)
3904  *
3905  * Return the integer part of a VT_CY.
3906  *
3907  * PARAMS
3908  *  cyIn   [I] Source
3909  *  pCyOut [O] Destination
3910  *
3911  * RETURNS
3912  *  Success: S_OK.
3913  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3914  *
3915  * NOTES
3916  *  - The difference between this function and VarCyFix() is that VarCyFix() rounds
3917  *    negative numbers towards 0, while this function rounds them away from zero.
3918  */
3919 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
3920 {
3921   pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3922   pCyOut->int64 *= CY_MULTIPLIER;
3923
3924   if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3925   {
3926     pCyOut->int64 -= CY_MULTIPLIER;
3927   }
3928   return S_OK;
3929 }
3930
3931 /************************************************************************
3932  * VarCyNeg (OLEAUT32.309)
3933  *
3934  * Change the sign of a VT_CY.
3935  *
3936  * PARAMS
3937  *  cyIn   [I] Source
3938  *  pCyOut [O] Destination
3939  *
3940  * RETURNS
3941  *  Success: S_OK.
3942  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3943  */
3944 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
3945 {
3946   if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3947     return DISP_E_OVERFLOW;
3948
3949   pCyOut->int64 = -cyIn.int64;
3950   return S_OK;
3951 }
3952
3953 /************************************************************************
3954  * VarCyRound (OLEAUT32.310)
3955  *
3956  * Change the precision of a VT_CY.
3957  *
3958  * PARAMS
3959  *  cyIn      [I] Source
3960  *  cDecimals [I] New number of decimals to keep
3961  *  pCyOut    [O] Destination
3962  *
3963  * RETURNS
3964  *  Success: S_OK.
3965  *  Failure: E_INVALIDARG, if cDecimals is less than 0.
3966  */
3967 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
3968 {
3969   if (cDecimals < 0)
3970     return E_INVALIDARG;
3971
3972   if (cDecimals > 3)
3973   {
3974     /* Rounding to more precision than we have */
3975     *pCyOut = cyIn;
3976     return S_OK;
3977   }
3978   else
3979   {
3980     double d, div = CY_Divisors[cDecimals];
3981
3982     _VarR8FromCy(cyIn, &d);
3983     d = d * div;
3984     VARIANT_DutchRound(LONGLONG, d, pCyOut->int64)
3985     d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3986     VARIANT_DutchRound(LONGLONG, d, pCyOut->int64)
3987     return S_OK;
3988   }
3989 }
3990
3991 /************************************************************************
3992  * VarCyCmp (OLEAUT32.311)
3993  *
3994  * Compare two VT_CY values.
3995  *
3996  * PARAMS
3997  *  cyLeft  [I] Source
3998  *  cyRight [I] Value to compare
3999  *
4000  * RETURNS
4001  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
4002  *           compare is less, equal or greater than source respectively.
4003  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4004  */
4005 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
4006 {
4007   HRESULT hRet;
4008   CY result;
4009
4010   /* Subtract right from left, and compare the result to 0 */
4011   hRet = VarCySub(cyLeft, cyRight, &result);
4012
4013   if (SUCCEEDED(hRet))
4014   {
4015     if (result.int64 < 0)
4016       hRet = (HRESULT)VARCMP_LT;
4017     else if (result.int64 > 0)
4018       hRet = (HRESULT)VARCMP_GT;
4019     else
4020       hRet = (HRESULT)VARCMP_EQ;
4021   }
4022   return hRet;
4023 }
4024
4025 /************************************************************************
4026  * VarCyCmpR8 (OLEAUT32.312)
4027  *
4028  * Compare a VT_CY to a double
4029  *
4030  * PARAMS
4031  *  cyLeft   [I] Currency Source
4032  *  dblRight [I] double to compare to cyLeft
4033  *
4034  * RETURNS
4035  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
4036  *           less than, equal to or greater than cyLeft respectively.
4037  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4038  */
4039 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
4040 {
4041   HRESULT hRet;
4042   CY cyRight;
4043
4044   hRet = VarCyFromR8(dblRight, &cyRight);
4045
4046   if (SUCCEEDED(hRet))
4047     hRet = VarCyCmp(cyLeft, cyRight);
4048
4049   return hRet;
4050 }
4051
4052 /************************************************************************
4053  * VarCyMulI8 (OLEAUT32.329)
4054  *
4055  * Multiply a VT_CY by a VT_I8.
4056  *
4057  * PARAMS
4058  *  cyLeft  [I] Source
4059  *  llRight [I] Value to multiply by
4060  *  pCyOut  [O] Destination
4061  *
4062  * RETURNS
4063  *  Success: S_OK.
4064  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4065  */
4066 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
4067 {
4068   double d;
4069
4070   _VarR8FromCy(cyLeft, &d);
4071   d = d  * (double)llRight;
4072   return VarCyFromR8(d, pCyOut);
4073 }
4074
4075 /* DECIMAL
4076  */
4077
4078 /************************************************************************
4079  * VarDecFromUI1 (OLEAUT32.190)
4080  *
4081  * Convert a VT_UI1 to a DECIMAL.
4082  *
4083  * PARAMS
4084  *  bIn     [I] Source
4085  *  pDecOut [O] Destination
4086  *
4087  * RETURNS
4088  *  S_OK.
4089  */
4090 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
4091 {
4092   return VarDecFromUI4(bIn, pDecOut);
4093 }
4094
4095 /************************************************************************
4096  * VarDecFromI2 (OLEAUT32.191)
4097  *
4098  * Convert a VT_I2 to a DECIMAL.
4099  *
4100  * PARAMS
4101  *  sIn     [I] Source
4102  *  pDecOut [O] Destination
4103  *
4104  * RETURNS
4105  *  S_OK.
4106  */
4107 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
4108 {
4109   return VarDecFromI4(sIn, pDecOut);
4110 }
4111
4112 /************************************************************************
4113  * VarDecFromI4 (OLEAUT32.192)
4114  *
4115  * Convert a VT_I4 to a DECIMAL.
4116  *
4117  * PARAMS
4118  *  sIn     [I] Source
4119  *  pDecOut [O] Destination
4120  *
4121  * RETURNS
4122  *  S_OK.
4123  */
4124 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
4125 {
4126   DEC_HI32(pDecOut) = 0;
4127   DEC_MID32(pDecOut) = 0;
4128
4129   if (lIn < 0)
4130   {
4131     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4132     DEC_LO32(pDecOut) = -lIn;
4133   }
4134   else
4135   {
4136     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4137     DEC_LO32(pDecOut) = lIn;
4138   }
4139   return S_OK;
4140 }
4141
4142 #define LOCALE_EN_US            (MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT))
4143
4144 /************************************************************************
4145  * VarDecFromR4 (OLEAUT32.193)
4146  *
4147  * Convert a VT_R4 to a DECIMAL.
4148  *
4149  * PARAMS
4150  *  fltIn   [I] Source
4151  *  pDecOut [O] Destination
4152  *
4153  * RETURNS
4154  *  S_OK.
4155  */
4156 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
4157 {
4158   WCHAR buff[256];
4159
4160   sprintfW( buff, szFloatFormatW, fltIn );
4161   return VarDecFromStr(buff, LOCALE_EN_US, 0, pDecOut);
4162 }
4163
4164 /************************************************************************
4165  * VarDecFromR8 (OLEAUT32.194)
4166  *
4167  * Convert a VT_R8 to a DECIMAL.
4168  *
4169  * PARAMS
4170  *  dblIn   [I] Source
4171  *  pDecOut [O] Destination
4172  *
4173  * RETURNS
4174  *  S_OK.
4175  */
4176 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4177 {
4178   WCHAR buff[256];
4179
4180   sprintfW( buff, szDoubleFormatW, dblIn );
4181   return VarDecFromStr(buff, LOCALE_EN_US, 0, pDecOut);
4182 }
4183
4184 /************************************************************************
4185  * VarDecFromDate (OLEAUT32.195)
4186  *
4187  * Convert a VT_DATE to a DECIMAL.
4188  *
4189  * PARAMS
4190  *  dateIn  [I] Source
4191  *  pDecOut [O] Destination
4192  *
4193  * RETURNS
4194  *  S_OK.
4195  */
4196 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
4197 {
4198   return VarDecFromR8(dateIn, pDecOut);
4199 }
4200
4201 /************************************************************************
4202  * VarDecFromCy (OLEAUT32.196)
4203  *
4204  * Convert a VT_CY to a DECIMAL.
4205  *
4206  * PARAMS
4207  *  cyIn    [I] Source
4208  *  pDecOut [O] Destination
4209  *
4210  * RETURNS
4211  *  S_OK.
4212  */
4213 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
4214 {
4215   DEC_HI32(pDecOut) = 0;
4216
4217   /* Note: This assumes 2s complement integer representation */
4218   if (cyIn.s.Hi & 0x80000000)
4219   {
4220     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4221     DEC_LO64(pDecOut) = -cyIn.int64;
4222   }
4223   else
4224   {
4225     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4226     DEC_MID32(pDecOut) = cyIn.s.Hi;
4227     DEC_LO32(pDecOut) = cyIn.s.Lo;
4228   }
4229   return S_OK;
4230 }
4231
4232 /************************************************************************
4233  * VarDecFromStr (OLEAUT32.197)
4234  *
4235  * Convert a VT_BSTR to a DECIMAL.
4236  *
4237  * PARAMS
4238  *  strIn   [I] Source
4239  *  lcid    [I] LCID for the conversion
4240  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4241  *  pDecOut [O] Destination
4242  *
4243  * RETURNS
4244  *  Success: S_OK.
4245  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4246  */
4247 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
4248 {
4249   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDecOut, VT_DECIMAL);
4250 }
4251
4252 /************************************************************************
4253  * VarDecFromDisp (OLEAUT32.198)
4254  *
4255  * Convert a VT_DISPATCH to a DECIMAL.
4256  *
4257  * PARAMS
4258  *  pdispIn  [I] Source
4259  *  lcid     [I] LCID for conversion
4260  *  pDecOut  [O] Destination
4261  *
4262  * RETURNS
4263  *  Success: S_OK.
4264  *  Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4265  */
4266 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
4267 {
4268   return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL);
4269 }
4270
4271 /************************************************************************
4272  * VarDecFromBool (OLEAUT32.199)
4273  *
4274  * Convert a VT_BOOL to a DECIMAL.
4275  *
4276  * PARAMS
4277  *  bIn     [I] Source
4278  *  pDecOut [O] Destination
4279  *
4280  * RETURNS
4281  *  S_OK.
4282  *
4283  * NOTES
4284  *  The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4285  */
4286 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
4287 {
4288   DEC_HI32(pDecOut) = 0;
4289   DEC_MID32(pDecOut) = 0;
4290   if (bIn)
4291   {
4292     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4293     DEC_LO32(pDecOut) = 1;
4294   }
4295   else
4296   {
4297     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4298     DEC_LO32(pDecOut) = 0;
4299   }
4300   return S_OK;
4301 }
4302
4303 /************************************************************************
4304  * VarDecFromI1 (OLEAUT32.241)
4305  *
4306  * Convert a VT_I1 to a DECIMAL.
4307  *
4308  * PARAMS
4309  *  cIn     [I] Source
4310  *  pDecOut [O] Destination
4311  *
4312  * RETURNS
4313  *  S_OK.
4314  */
4315 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4316 {
4317   return VarDecFromI4(cIn, pDecOut);
4318 }
4319
4320 /************************************************************************
4321  * VarDecFromUI2 (OLEAUT32.242)
4322  *
4323  * Convert a VT_UI2 to a DECIMAL.
4324  *
4325  * PARAMS
4326  *  usIn    [I] Source
4327  *  pDecOut [O] Destination
4328  *
4329  * RETURNS
4330  *  S_OK.
4331  */
4332 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
4333 {
4334   return VarDecFromUI4(usIn, pDecOut);
4335 }
4336
4337 /************************************************************************
4338  * VarDecFromUI4 (OLEAUT32.243)
4339  *
4340  * Convert a VT_UI4 to a DECIMAL.
4341  *
4342  * PARAMS
4343  *  ulIn    [I] Source
4344  *  pDecOut [O] Destination
4345  *
4346  * RETURNS
4347  *  S_OK.
4348  */
4349 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
4350 {
4351   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4352   DEC_HI32(pDecOut) = 0;
4353   DEC_MID32(pDecOut) = 0;
4354   DEC_LO32(pDecOut) = ulIn;
4355   return S_OK;
4356 }
4357
4358 /************************************************************************
4359  * VarDecFromI8 (OLEAUT32.374)
4360  *
4361  * Convert a VT_I8 to a DECIMAL.
4362  *
4363  * PARAMS
4364  *  llIn    [I] Source
4365  *  pDecOut [O] Destination
4366  *
4367  * RETURNS
4368  *  S_OK.
4369  */
4370 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
4371 {
4372   PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4373
4374   DEC_HI32(pDecOut) = 0;
4375
4376   /* Note: This assumes 2s complement integer representation */
4377   if (pLi->u.HighPart & 0x80000000)
4378   {
4379     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4380     DEC_LO64(pDecOut) = -pLi->QuadPart;
4381   }
4382   else
4383   {
4384     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4385     DEC_MID32(pDecOut) = pLi->u.HighPart;
4386     DEC_LO32(pDecOut) = pLi->u.LowPart;
4387   }
4388   return S_OK;
4389 }
4390
4391 /************************************************************************
4392  * VarDecFromUI8 (OLEAUT32.375)
4393  *
4394  * Convert a VT_UI8 to a DECIMAL.
4395  *
4396  * PARAMS
4397  *  ullIn   [I] Source
4398  *  pDecOut [O] Destination
4399  *
4400  * RETURNS
4401  *  S_OK.
4402  */
4403 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
4404 {
4405   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4406   DEC_HI32(pDecOut) = 0;
4407   DEC_LO64(pDecOut) = ullIn;
4408   return S_OK;
4409 }
4410
4411 /* Make two DECIMALS the same scale; used by math functions below */
4412 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4413                                 const DECIMAL** ppDecRight,
4414                                 DECIMAL* pDecOut)
4415 {
4416   static DECIMAL scaleFactor;
4417   DECIMAL decTemp;
4418   int scaleAmount, i;
4419   HRESULT hRet = S_OK;
4420
4421   if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4422     return E_INVALIDARG;
4423
4424   DEC_LO32(&scaleFactor) = 10;
4425
4426   i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4427
4428   if (!scaleAmount)
4429     return S_OK; /* Same scale */
4430
4431   if (scaleAmount > 0)
4432   {
4433     decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4434     *ppDecRight = pDecOut;
4435   }
4436   else
4437   {
4438     decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4439     *ppDecLeft = pDecOut;
4440     i = scaleAmount = -scaleAmount;
4441   }
4442
4443   if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
4444     return DISP_E_OVERFLOW; /* Can't scale up */
4445
4446   /* Multiply up the value to be scaled by the correct amount */
4447   while (SUCCEEDED(hRet) && i--)
4448   {
4449     /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4450     hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
4451     decTemp = *pDecOut;
4452   }
4453   DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
4454   return hRet;
4455 }
4456
4457 /* Add two unsigned 32 bit values with overflow */
4458 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4459 {
4460   ULARGE_INTEGER ul64;
4461
4462   ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4463   *pulHigh = ul64.u.HighPart;
4464   return ul64.u.LowPart;
4465 }
4466
4467 /* Subtract two unsigned 32 bit values with underflow */
4468 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4469 {
4470   int invert = 0;
4471   ULARGE_INTEGER ul64;
4472
4473   ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4474   if (ulLeft < ulRight)
4475     invert = 1;
4476
4477   if (ul64.QuadPart > (ULONG64)*pulHigh)
4478     ul64.QuadPart -= (ULONG64)*pulHigh;
4479   else
4480   {
4481     ul64.QuadPart -= (ULONG64)*pulHigh;
4482     invert = 1;
4483   }
4484   if (invert)
4485     ul64.u.HighPart = -ul64.u.HighPart ;
4486
4487   *pulHigh = ul64.u.HighPart;
4488   return ul64.u.LowPart;
4489 }
4490
4491 /* Multiply two unsigned 32 bit values with overflow */
4492 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4493 {
4494   ULARGE_INTEGER ul64;
4495
4496   ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4497   *pulHigh = ul64.u.HighPart;
4498   return ul64.u.LowPart;
4499 }
4500
4501 /* Compare two decimals that have the same scale */
4502 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4503 {
4504   if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4505       (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4506     return -1;
4507   else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4508     return 0;
4509   return 1;
4510 }
4511
4512 /************************************************************************
4513  * VarDecAdd (OLEAUT32.177)
4514  *
4515  * Add one DECIMAL to another.
4516  *
4517  * PARAMS
4518  *  pDecLeft  [I] Source
4519  *  pDecRight [I] Value to add
4520  *  pDecOut   [O] Destination
4521  *
4522  * RETURNS
4523  *  Success: S_OK.
4524  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4525  */
4526 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4527 {
4528   HRESULT hRet;
4529   DECIMAL scaled;
4530
4531   hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
4532
4533   if (SUCCEEDED(hRet))
4534   {
4535     /* Our decimals now have the same scale, we can add them as 96 bit integers */
4536     ULONG overflow = 0;
4537     BYTE sign = DECIMAL_POS;
4538
4539     /* Correct for the sign of the result */
4540     if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4541     {
4542       /* -x + -y : Negative */
4543       sign = DECIMAL_NEG;
4544       goto VarDecAdd_AsPositive;
4545     }
4546     else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4547     {
4548       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4549
4550       /* -x + y : Negative if x > y */
4551       if (cmp > 0)
4552       {
4553         sign = DECIMAL_NEG;
4554 VarDecAdd_AsNegative:
4555         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
4556         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4557         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
4558       }
4559       else
4560       {
4561 VarDecAdd_AsInvertedNegative:
4562         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecRight),  DEC_LO32(pDecLeft),  &overflow);
4563         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4564         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecRight),  DEC_HI32(pDecLeft),  &overflow);
4565       }
4566     }
4567     else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4568     {
4569       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4570
4571       /* x + -y : Negative if x <= y */
4572       if (cmp <= 0)
4573       {
4574         sign = DECIMAL_NEG;
4575         goto VarDecAdd_AsInvertedNegative;
4576       }
4577       goto VarDecAdd_AsNegative;
4578     }
4579     else
4580     {
4581       /* x + y : Positive */
4582 VarDecAdd_AsPositive:
4583       DEC_LO32(pDecOut)  = VARIANT_Add(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
4584       DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4585       DEC_HI32(pDecOut)  = VARIANT_Add(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
4586     }
4587
4588     if (overflow)
4589       return DISP_E_OVERFLOW; /* overflowed */
4590
4591     DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4592     DEC_SIGN(pDecOut) = sign;
4593   }
4594   return hRet;
4595 }
4596
4597 /* internal representation of the value stored in a DECIMAL. The bytes are
4598    stored from LSB at index 0 to MSB at index 11
4599  */
4600 typedef struct DECIMAL_internal
4601 {
4602     DWORD bitsnum[3];  /* 96 significant bits, unsigned */
4603     unsigned char scale;      /* number scaled * 10 ^ -(scale) */
4604     unsigned int  sign : 1;   /* 0 - positive, 1 - negative */
4605 } VARIANT_DI;
4606
4607 /* translate from external DECIMAL format into an internal representation */
4608 static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to)
4609 {
4610     to->scale = DEC_SCALE(from);
4611     to->sign = DEC_SIGN(from) ? 1 : 0;
4612
4613     to->bitsnum[0] = DEC_LO32(from);
4614     to->bitsnum[1] = DEC_MID32(from);
4615     to->bitsnum[2] = DEC_HI32(from);
4616 }
4617
4618 static void VARIANT_DecFromDI(VARIANT_DI * from, DECIMAL * to)
4619 {
4620     if (from->sign) {
4621         DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_NEG, from->scale);
4622     } else {
4623         DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_POS, from->scale);
4624     }
4625
4626     DEC_LO32(to) = from->bitsnum[0];
4627     DEC_MID32(to) = from->bitsnum[1];
4628     DEC_HI32(to) = from->bitsnum[2];
4629 }
4630
4631 /* clear an internal representation of a DECIMAL */
4632 static void VARIANT_DI_clear(VARIANT_DI * i)
4633 {
4634     memset(i, 0, sizeof(VARIANT_DI));
4635 }
4636
4637 /* divide the (unsigned) number stored in p (LSB) by a byte value (<= 0xff). Any nonzero
4638    size is supported. The value in p is replaced by the quotient of the division, and
4639    the remainder is returned as a result. This routine is most often used with a divisor
4640    of 10 in order to scale up numbers, and in the DECIMAL->string conversion.
4641  */
4642 static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor)
4643 {
4644     if (divisor == 0) {
4645         /* division by 0 */
4646         return 0xFF;
4647     } else if (divisor == 1) {
4648         /* dividend remains unchanged */
4649         return 0;
4650     } else {
4651         unsigned char remainder = 0;
4652         ULONGLONG iTempDividend;
4653         signed int i;
4654         
4655         for (i = n - 1; i >= 0 && !p[i]; i--);  /* skip leading zeros */
4656         for (; i >= 0; i--) {
4657             iTempDividend = ((ULONGLONG)remainder << 32) + p[i];
4658             remainder = iTempDividend % divisor;
4659             p[i] = iTempDividend / divisor;
4660         }
4661         
4662         return remainder;
4663     }
4664 }
4665
4666 /* check to test if encoded number is a zero. Returns 1 if zero, 0 for nonzero */
4667 static int VARIANT_int_iszero(DWORD * p, unsigned int n)
4668 {
4669     for (; n > 0; n--) if (*p++ != 0) return 0;
4670     return 1;
4671 }
4672
4673 /* multiply two DECIMALS, without changing either one, and place result in third
4674    parameter. Result is normalized when scale is > 0. Attempts to remove significant
4675    digits when scale > 0 in order to fit an overflowing result. Final overflow
4676    flag is returned.
4677  */
4678 static int VARIANT_DI_mul(VARIANT_DI * a, VARIANT_DI * b, VARIANT_DI * result)
4679 {
4680     int r_overflow = 0;
4681     DWORD running[6];
4682     signed int mulstart;
4683
4684     VARIANT_DI_clear(result);
4685     result->sign = (a->sign ^ b->sign) ? 1 : 0;
4686
4687     /* Multiply 128-bit operands into a (max) 256-bit result. The scale
4688        of the result is formed by adding the scales of the operands.
4689      */
4690     result->scale = a->scale + b->scale;
4691     memset(running, 0, sizeof(running));
4692
4693     /* count number of leading zero-bytes in operand A */
4694     for (mulstart = sizeof(a->bitsnum)/sizeof(DWORD) - 1; mulstart >= 0 && !a->bitsnum[mulstart]; mulstart--);
4695     if (mulstart < 0) {
4696         /* result is 0, because operand A is 0 */
4697         result->scale = 0;
4698         result->sign = 0;
4699     } else {
4700         unsigned char remainder = 0;
4701         int iA;        
4702
4703         /* perform actual multiplication */
4704         for (iA = 0; iA <= mulstart; iA++) {
4705             ULONG iOverflowMul;
4706             int iB;
4707             
4708             for (iOverflowMul = 0, iB = 0; iB < sizeof(b->bitsnum)/sizeof(DWORD); iB++) {
4709                 ULONG iRV;
4710                 int iR;
4711                 
4712                 iRV = VARIANT_Mul(b->bitsnum[iB], a->bitsnum[iA], &iOverflowMul);
4713                 iR = iA + iB;
4714                 do {
4715                     running[iR] = VARIANT_Add(running[iR], 0, &iRV);
4716                     iR++;
4717                 } while (iRV);
4718             }
4719         }
4720
4721 /* Too bad - native oleaut does not do this, so we should not either */
4722 #if 0
4723         /* While the result is divisible by 10, and the scale > 0, divide by 10.
4724            This operation should not lose significant digits, and gives an
4725            opportunity to reduce the possibility of overflows in future
4726            operations issued by the application.
4727          */
4728         while (result->scale > 0) {
4729             memcpy(quotient, running, sizeof(quotient));
4730             remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
4731             if (remainder > 0) break;
4732             memcpy(running, quotient, sizeof(quotient));
4733             result->scale--;
4734         }
4735 #endif
4736         /* While the 256-bit result overflows, and the scale > 0, divide by 10.
4737            This operation *will* lose significant digits of the result because
4738            all the factors of 10 were consumed by the previous operation.
4739         */
4740         while (result->scale > 0 && !VARIANT_int_iszero(
4741             running + sizeof(result->bitsnum) / sizeof(DWORD),
4742             (sizeof(running) - sizeof(result->bitsnum)) / sizeof(DWORD))) {
4743             
4744             remainder = VARIANT_int_divbychar(running, sizeof(running) / sizeof(DWORD), 10);
4745             if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
4746             result->scale--;
4747         }
4748         
4749         /* round up the result - native oleaut32 does this */
4750         if (remainder >= 5) {
4751             unsigned int i;
4752             for (remainder = 1, i = 0; i < sizeof(running)/sizeof(DWORD) && remainder; i++) {
4753                 ULONGLONG digit = running[i] + 1;
4754                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4755                 running[i] = digit & 0xFFFFFFFF;
4756             }
4757         }
4758
4759         /* Signal overflow if scale == 0 and 256-bit result still overflows,
4760            and copy result bits into result structure
4761         */
4762         r_overflow = !VARIANT_int_iszero(
4763             running + sizeof(result->bitsnum)/sizeof(DWORD), 
4764             (sizeof(running) - sizeof(result->bitsnum))/sizeof(DWORD));
4765         memcpy(result->bitsnum, running, sizeof(result->bitsnum));
4766     }
4767     return r_overflow;
4768 }
4769
4770 /* cast DECIMAL into string. Any scale should be handled properly. en_US locale is
4771    hardcoded (period for decimal separator, dash as negative sign). Returns 0 for
4772    success, nonzero if insufficient space in output buffer.
4773  */
4774 static int VARIANT_DI_tostringW(VARIANT_DI * a, WCHAR * s, unsigned int n)
4775 {
4776     int overflow = 0;
4777     DWORD quotient[3];
4778     unsigned char remainder;
4779     unsigned int i;
4780
4781     /* place negative sign */
4782     if (!VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD)) && a->sign) {
4783         if (n > 0) {
4784             *s++ = '-';
4785             n--;
4786         }
4787         else overflow = 1;
4788     }
4789
4790     /* prepare initial 0 */
4791     if (!overflow) {
4792         if (n >= 2) {
4793             s[0] = '0';
4794             s[1] = '\0';
4795         } else overflow = 1;
4796     }
4797
4798     i = 0;
4799     memcpy(quotient, a->bitsnum, sizeof(a->bitsnum));
4800     while (!overflow && !VARIANT_int_iszero(quotient, sizeof(quotient) / sizeof(DWORD))) {
4801         remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
4802         if (i + 2 > n) {
4803             overflow = 1;
4804         } else {
4805             s[i++] = '0' + remainder;
4806             s[i] = '\0';
4807         }
4808     }
4809
4810     if (!overflow && !VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD))) {
4811
4812         /* reverse order of digits */
4813         WCHAR * x = s; WCHAR * y = s + i - 1;
4814         while (x < y) {
4815             *x ^= *y;
4816             *y ^= *x;
4817             *x++ ^= *y--;
4818         }
4819
4820         /* check for decimal point. "i" now has string length */
4821         if (i <= a->scale) {
4822             unsigned int numzeroes = a->scale + 1 - i;
4823             if (i + 1 + numzeroes >= n) {
4824                 overflow = 1;
4825             } else {
4826                 memmove(s + numzeroes, s, (i + 1) * sizeof(WCHAR));
4827                 i += numzeroes;
4828                 while (numzeroes > 0) {
4829                     s[--numzeroes] = '0';
4830                 }
4831             }
4832         }
4833
4834         /* place decimal point */
4835         if (a->scale > 0) {
4836             unsigned int periodpos = i - a->scale;
4837             if (i + 2 >= n) {
4838                 overflow = 1;
4839             } else {
4840                 memmove(s + periodpos + 1, s + periodpos, (i + 1 - periodpos) * sizeof(WCHAR));
4841                 s[periodpos] = '.'; i++;
4842                 
4843                 /* remove extra zeros at the end, if any */
4844                 while (s[i - 1] == '0') s[--i] = '\0';
4845                 if (s[i - 1] == '.') s[--i] = '\0';
4846             }
4847         }
4848     }
4849
4850     return overflow;
4851 }
4852
4853 /* shift the bits of a DWORD array to the left. p[0] is assumed LSB */
4854 static void VARIANT_int_shiftleft(DWORD * p, unsigned int n, unsigned int shift)
4855 {
4856     DWORD shifted;
4857     unsigned int i;
4858     
4859     /* shift whole DWORDs to the left */
4860     while (shift >= 32)
4861     {
4862         memmove(p + 1, p, (n - 1) * sizeof(DWORD));
4863         *p = 0; shift -= 32;
4864     }
4865     
4866     /* shift remainder (1..31 bits) */
4867     shifted = 0;
4868     if (shift > 0) for (i = 0; i < n; i++)
4869     {
4870         DWORD b;
4871         b = p[i] >> (32 - shift);
4872         p[i] = (p[i] << shift) | shifted;
4873         shifted = b;
4874     }
4875 }
4876
4877 /* add the (unsigned) numbers stored in two DWORD arrays with LSB at index 0.
4878    Value at v is incremented by the value at p. Any size is supported, provided
4879    that v is not shorter than p. Any unapplied carry is returned as a result.
4880  */
4881 static unsigned char VARIANT_int_add(DWORD * v, unsigned int nv, DWORD * p, 
4882     unsigned int np)
4883 {
4884     unsigned char carry = 0;
4885
4886     if (nv >= np) {
4887         ULONGLONG sum;
4888         unsigned int i;
4889
4890         for (i = 0; i < np; i++) {
4891             sum = (ULONGLONG)v[i]
4892                 + (ULONGLONG)p[i]
4893                 + (ULONGLONG)carry;
4894             v[i] = sum & 0xffffffff;
4895             carry = sum >> 32;
4896         }
4897         for (; i < nv && carry; i++) {
4898             sum = (ULONGLONG)v[i]
4899                 + (ULONGLONG)carry;
4900             v[i] = sum & 0xffffffff;
4901             carry = sum >> 32;
4902         }
4903     }
4904     return carry;
4905 }
4906
4907 /* perform integral division with operand p as dividend. Parameter n indicates 
4908    number of available DWORDs in divisor p, but available space in p must be 
4909    actually at least 2 * n DWORDs, because the remainder of the integral 
4910    division is built in the next n DWORDs past the start of the quotient. This 
4911    routine replaces the dividend in p with the quotient, and appends n 
4912    additional DWORDs for the remainder.
4913
4914    Thanks to Lee & Mark Atkinson for their book _Using_C_ (my very first book on
4915    C/C++ :-) where the "longhand binary division" algorithm was exposed for the
4916    source code to the VLI (Very Large Integer) division operator. This algorithm
4917    was then heavily modified by me (Alex Villacis Lasso) in order to handle
4918    variably-scaled integers such as the MS DECIMAL representation.
4919  */
4920 static void VARIANT_int_div(DWORD * p, unsigned int n, DWORD * divisor,
4921     unsigned int dn)
4922 {
4923     unsigned int i;
4924     DWORD tempsub[8];
4925     DWORD * negdivisor = tempsub + n;
4926
4927     /* build 2s-complement of divisor */
4928     for (i = 0; i < n; i++) negdivisor[i] = (i < dn) ? ~divisor[i] : 0xFFFFFFFF;
4929     p[n] = 1;
4930     VARIANT_int_add(negdivisor, n, p + n, 1);
4931     memset(p + n, 0, n * sizeof(DWORD));
4932
4933     /* skip all leading zero DWORDs in quotient */
4934     for (i = 0; i < n && !p[n - 1]; i++) VARIANT_int_shiftleft(p, n, 32);
4935     /* i is now number of DWORDs left to process */
4936     for (i <<= 5; i < (n << 5); i++) {
4937         VARIANT_int_shiftleft(p, n << 1, 1);    /* shl quotient+remainder */
4938
4939         /* trial subtraction */
4940         memcpy(tempsub, p + n, n * sizeof(DWORD));
4941         VARIANT_int_add(tempsub, n, negdivisor, n);
4942
4943         /* check whether result of subtraction was negative */
4944         if ((tempsub[n - 1] & 0x80000000) == 0) {
4945             memcpy(p + n, tempsub, n * sizeof(DWORD));
4946             p[0] |= 1;
4947         }
4948     }
4949 }
4950
4951 /* perform integral multiplication by a byte operand. Used for scaling by 10 */
4952 static unsigned char VARIANT_int_mulbychar(DWORD * p, unsigned int n, unsigned char m)
4953 {
4954     unsigned int i;
4955     ULONG iOverflowMul;
4956     
4957     for (iOverflowMul = 0, i = 0; i < n; i++)
4958         p[i] = VARIANT_Mul(p[i], m, &iOverflowMul);
4959     return (unsigned char)iOverflowMul;
4960 }
4961
4962 /* increment value in A by the value indicated in B, with scale adjusting. 
4963    Modifies parameters by adjusting scales. Returns 0 if addition was 
4964    successful, nonzero if a parameter underflowed before it could be 
4965    successfully used in the addition.
4966  */
4967 static int VARIANT_int_addlossy(
4968     DWORD * a, int * ascale, unsigned int an,
4969     DWORD * b, int * bscale, unsigned int bn)
4970 {
4971     int underflow = 0;
4972
4973     if (VARIANT_int_iszero(a, an)) {
4974         /* if A is zero, copy B into A, after removing digits */
4975         while (bn > an && !VARIANT_int_iszero(b + an, bn - an)) {
4976             VARIANT_int_divbychar(b, bn, 10);
4977             (*bscale)--;
4978         }
4979         memcpy(a, b, an * sizeof(DWORD));
4980         *ascale = *bscale;
4981     } else if (!VARIANT_int_iszero(b, bn)) {
4982         unsigned int tn = an + 1;
4983         DWORD t[5];
4984
4985         if (bn + 1 > tn) tn = bn + 1;
4986         if (*ascale != *bscale) {
4987             /* first (optimistic) try - try to scale down the one with the bigger
4988                scale, while this number is divisible by 10 */
4989             DWORD * digitchosen;
4990             unsigned int nchosen;
4991             int * scalechosen;
4992             int targetscale;
4993
4994             if (*ascale < *bscale) {
4995                 targetscale = *ascale;
4996                 scalechosen = bscale;
4997                 digitchosen = b;
4998                 nchosen = bn;
4999             } else {
5000                 targetscale = *bscale;
5001                 scalechosen = ascale;
5002                 digitchosen = a;
5003                 nchosen = an;
5004             }
5005             memset(t, 0, tn * sizeof(DWORD));
5006             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5007
5008             /* divide by 10 until target scale is reached */
5009             while (*scalechosen > targetscale) {
5010                 unsigned char remainder = VARIANT_int_divbychar(t, tn, 10);
5011                 if (!remainder) {
5012                     (*scalechosen)--;
5013                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5014                 } else break;
5015             }
5016         }
5017
5018         if (*ascale != *bscale) {
5019             DWORD * digitchosen;
5020             unsigned int nchosen;
5021             int * scalechosen;
5022             int targetscale;
5023
5024             /* try to scale up the one with the smaller scale */
5025             if (*ascale > *bscale) {
5026                 targetscale = *ascale;
5027                 scalechosen = bscale;
5028                 digitchosen = b;
5029                 nchosen = bn;
5030             } else {
5031                 targetscale = *bscale;
5032                 scalechosen = ascale;
5033                 digitchosen = a;
5034                 nchosen = an;
5035             }
5036             memset(t, 0, tn * sizeof(DWORD));
5037             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5038
5039             /* multiply by 10 until target scale is reached, or
5040                significant bytes overflow the number
5041              */
5042             while (*scalechosen < targetscale && t[nchosen] == 0) {
5043                 VARIANT_int_mulbychar(t, tn, 10);
5044                 if (t[nchosen] == 0) {
5045                     /* still does not overflow */
5046                     (*scalechosen)++;
5047                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5048                 }
5049             }
5050         }
5051
5052         if (*ascale != *bscale) {
5053             /* still different? try to scale down the one with the bigger scale
5054                (this *will* lose significant digits) */
5055             DWORD * digitchosen;
5056             unsigned int nchosen;
5057             int * scalechosen;
5058             int targetscale;
5059
5060             if (*ascale < *bscale) {
5061                 targetscale = *ascale;
5062                 scalechosen = bscale;
5063                 digitchosen = b;
5064                 nchosen = bn;
5065             } else {
5066                 targetscale = *bscale;
5067                 scalechosen = ascale;
5068                 digitchosen = a;
5069                 nchosen = an;
5070             }
5071             memset(t, 0, tn * sizeof(DWORD));
5072             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5073
5074             /* divide by 10 until target scale is reached */
5075             while (*scalechosen > targetscale) {
5076                 VARIANT_int_divbychar(t, tn, 10);
5077                 (*scalechosen)--;
5078                 memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5079             }
5080         }
5081
5082         /* check whether any of the operands still has significant digits
5083            (underflow case 1)
5084          */
5085         if (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn)) {
5086             underflow = 1;
5087         } else {
5088             /* at this step, both numbers have the same scale and can be added
5089                as integers. However, the result might not fit in A, so further
5090                scaling down might be necessary.
5091              */
5092             while (!underflow) {
5093                 memset(t, 0, tn * sizeof(DWORD));
5094                 memcpy(t, a, an * sizeof(DWORD));
5095
5096                 VARIANT_int_add(t, tn, b, bn);
5097                 if (VARIANT_int_iszero(t + an, tn - an)) {
5098                     /* addition was successful */
5099                     memcpy(a, t, an * sizeof(DWORD));
5100                     break;
5101                 } else {
5102                     /* addition overflowed - remove significant digits
5103                        from both operands and try again */
5104                     VARIANT_int_divbychar(a, an, 10); (*ascale)--;
5105                     VARIANT_int_divbychar(b, bn, 10); (*bscale)--;
5106                     /* check whether any operand keeps significant digits after
5107                        scaledown (underflow case 2)
5108                      */
5109                     underflow = (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn));
5110                 }
5111             }
5112         }
5113     }
5114     return underflow;
5115 }
5116
5117 /* perform complete DECIMAL division in the internal representation. Returns
5118    0 if the division was completed (even if quotient is set to 0), or nonzero
5119    in case of quotient overflow.
5120  */
5121 static HRESULT VARIANT_DI_div(VARIANT_DI * dividend, VARIANT_DI * divisor, VARIANT_DI * quotient)
5122 {
5123     HRESULT r_overflow = S_OK;
5124
5125     if (VARIANT_int_iszero(divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD))) {
5126         /* division by 0 */
5127         r_overflow = DISP_E_DIVBYZERO;
5128     } else if (VARIANT_int_iszero(dividend->bitsnum, sizeof(dividend->bitsnum)/sizeof(DWORD))) {
5129         VARIANT_DI_clear(quotient);
5130     } else {
5131         int quotientscale, remainderscale, tempquotientscale;
5132         DWORD remainderplusquotient[8];
5133         int underflow;
5134
5135         quotientscale = remainderscale = (int)dividend->scale - (int)divisor->scale;
5136         tempquotientscale = quotientscale;
5137         VARIANT_DI_clear(quotient);
5138         quotient->sign = (dividend->sign ^ divisor->sign) ? 1 : 0;
5139
5140         /*  The following strategy is used for division
5141             1) if there was a nonzero remainder from previous iteration, use it as
5142                dividend for this iteration, else (for first iteration) use intended
5143                dividend
5144             2) perform integer division in temporary buffer, develop quotient in
5145                low-order part, remainder in high-order part
5146             3) add quotient from step 2 to final result, with possible loss of
5147                significant digits
5148             4) multiply integer part of remainder by 10, while incrementing the
5149                scale of the remainder. This operation preserves the intended value
5150                of the remainder.
5151             5) loop to step 1 until one of the following is true:
5152                 a) remainder is zero (exact division achieved)
5153                 b) addition in step 3 fails to modify bits in quotient (remainder underflow)
5154          */
5155         memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5156         memcpy(remainderplusquotient, dividend->bitsnum, sizeof(dividend->bitsnum));
5157         do {
5158             VARIANT_int_div(
5159                 remainderplusquotient, 4,
5160                 divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD));
5161             underflow = VARIANT_int_addlossy(
5162                 quotient->bitsnum, &quotientscale, sizeof(quotient->bitsnum) / sizeof(DWORD),
5163                 remainderplusquotient, &tempquotientscale, 4);
5164             VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
5165             memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
5166             tempquotientscale = ++remainderscale;
5167         } while (!underflow && !VARIANT_int_iszero(remainderplusquotient + 4, 4));
5168
5169         /* quotient scale might now be negative (extremely big number). If, so, try
5170            to multiply quotient by 10 (without overflowing), while adjusting the scale,
5171            until scale is 0. If this cannot be done, it is a real overflow.
5172          */
5173         while (!r_overflow && quotientscale < 0) {
5174             memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5175             memcpy(remainderplusquotient, quotient->bitsnum, sizeof(quotient->bitsnum));
5176             VARIANT_int_mulbychar(remainderplusquotient, sizeof(remainderplusquotient)/sizeof(DWORD), 10);
5177             if (VARIANT_int_iszero(remainderplusquotient + sizeof(quotient->bitsnum)/sizeof(DWORD),
5178                 (sizeof(remainderplusquotient) - sizeof(quotient->bitsnum))/sizeof(DWORD))) {
5179                 quotientscale++;
5180                 memcpy(quotient->bitsnum, remainderplusquotient, sizeof(quotient->bitsnum));
5181             } else r_overflow = DISP_E_OVERFLOW;
5182         }
5183         if (!r_overflow) {
5184             if (quotientscale <= 255) quotient->scale = quotientscale;
5185             else VARIANT_DI_clear(quotient);
5186         }
5187     }
5188     return r_overflow;
5189 }
5190
5191 /************************************************************************
5192  * VarDecDiv (OLEAUT32.178)
5193  *
5194  * Divide one DECIMAL by another.
5195  *
5196  * PARAMS
5197  *  pDecLeft  [I] Source
5198  *  pDecRight [I] Value to divide by
5199  *  pDecOut   [O] Destination
5200  *
5201  * RETURNS
5202  *  Success: S_OK.
5203  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5204  */
5205 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5206 {
5207   HRESULT hRet = S_OK;
5208   VARIANT_DI di_left, di_right, di_result;
5209   HRESULT divresult;
5210
5211   if (!pDecLeft || !pDecRight || !pDecOut) return E_INVALIDARG;
5212
5213   VARIANT_DIFromDec(pDecLeft, &di_left);
5214   VARIANT_DIFromDec(pDecRight, &di_right);
5215   divresult = VARIANT_DI_div(&di_left, &di_right, &di_result);
5216   if (divresult)
5217   {
5218       /* division actually overflowed */
5219       hRet = divresult;
5220   }
5221   else
5222   {
5223       hRet = S_OK;
5224
5225       if (di_result.scale > DEC_MAX_SCALE)
5226       {
5227         unsigned char remainder = 0;
5228       
5229         /* division underflowed. In order to comply with the MSDN
5230            specifications for DECIMAL ranges, some significant digits
5231            must be removed
5232          */
5233         WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5234             di_result.scale);
5235         while (di_result.scale > DEC_MAX_SCALE && 
5236                !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD)))
5237         {
5238             remainder = VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD), 10);
5239             di_result.scale--;
5240         }
5241         if (di_result.scale > DEC_MAX_SCALE)
5242         {
5243             WARN("result underflowed, setting to 0\n");
5244             di_result.scale = 0;
5245             di_result.sign = 0;
5246         }
5247         else if (remainder >= 5)    /* round up result - native oleaut32 does this */
5248         {
5249             unsigned int i;
5250             for (remainder = 1, i = 0; i < sizeof(di_result.bitsnum) / sizeof(DWORD) && remainder; i++) {
5251                 ULONGLONG digit = di_result.bitsnum[i] + 1;
5252                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
5253                 di_result.bitsnum[i] = digit & 0xFFFFFFFF;
5254             }
5255         }
5256       }
5257       VARIANT_DecFromDI(&di_result, pDecOut);
5258   }
5259   return hRet;
5260 }
5261
5262 /************************************************************************
5263  * VarDecMul (OLEAUT32.179)
5264  *
5265  * Multiply one DECIMAL by another.
5266  *
5267  * PARAMS
5268  *  pDecLeft  [I] Source
5269  *  pDecRight [I] Value to multiply by
5270  *  pDecOut   [O] Destination
5271  *
5272  * RETURNS
5273  *  Success: S_OK.
5274  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5275  */
5276 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5277 {
5278   HRESULT hRet = S_OK;
5279   VARIANT_DI di_left, di_right, di_result;
5280   int mulresult;
5281
5282   VARIANT_DIFromDec(pDecLeft, &di_left);
5283   VARIANT_DIFromDec(pDecRight, &di_right);
5284   mulresult = VARIANT_DI_mul(&di_left, &di_right, &di_result);
5285   if (mulresult)
5286   {
5287     /* multiplication actually overflowed */
5288     hRet = DISP_E_OVERFLOW;
5289   }
5290   else
5291   {
5292     if (di_result.scale > DEC_MAX_SCALE)
5293     {
5294       /* multiplication underflowed. In order to comply with the MSDN
5295          specifications for DECIMAL ranges, some significant digits
5296          must be removed
5297        */
5298       WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5299           di_result.scale);
5300       while (di_result.scale > DEC_MAX_SCALE && 
5301             !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD)))
5302       {
5303         VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD), 10);
5304         di_result.scale--;
5305       }
5306       if (di_result.scale > DEC_MAX_SCALE)
5307       {
5308         WARN("result underflowed, setting to 0\n");
5309         di_result.scale = 0;
5310         di_result.sign = 0;
5311       }
5312     }
5313     VARIANT_DecFromDI(&di_result, pDecOut);
5314   }
5315   return hRet;
5316 }
5317
5318 /************************************************************************
5319  * VarDecSub (OLEAUT32.181)
5320  *
5321  * Subtract one DECIMAL from another.
5322  *
5323  * PARAMS
5324  *  pDecLeft  [I] Source
5325  *  pDecRight [I] DECIMAL to subtract from pDecLeft
5326  *  pDecOut   [O] Destination
5327  *
5328  * RETURNS
5329  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5330  */
5331 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5332 {
5333   DECIMAL decRight;
5334
5335   /* Implement as addition of the negative */
5336   VarDecNeg(pDecRight, &decRight);
5337   return VarDecAdd(pDecLeft, &decRight, pDecOut);
5338 }
5339
5340 /************************************************************************
5341  * VarDecAbs (OLEAUT32.182)
5342  *
5343  * Convert a DECIMAL into its absolute value.
5344  *
5345  * PARAMS
5346  *  pDecIn  [I] Source
5347  *  pDecOut [O] Destination
5348  *
5349  * RETURNS
5350  *  S_OK. This function does not fail.
5351  */
5352 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5353 {
5354   *pDecOut = *pDecIn;
5355   DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
5356   return S_OK;
5357 }
5358
5359 /************************************************************************
5360  * VarDecFix (OLEAUT32.187)
5361  *
5362  * Return the integer portion of a DECIMAL.
5363  *
5364  * PARAMS
5365  *  pDecIn  [I] Source
5366  *  pDecOut [O] Destination
5367  *
5368  * RETURNS
5369  *  Success: S_OK.
5370  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5371  *
5372  * NOTES
5373  *  - The difference between this function and VarDecInt() is that VarDecInt() rounds
5374  *    negative numbers away from 0, while this function rounds them towards zero.
5375  */
5376 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5377 {
5378   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
5379     return E_INVALIDARG;
5380
5381   if (!DEC_SCALE(pDecIn))
5382   {
5383     *pDecOut = *pDecIn; /* Already an integer */
5384     return S_OK;
5385   }
5386
5387   FIXME("semi-stub!\n");
5388   return DISP_E_OVERFLOW;
5389 }
5390
5391 /************************************************************************
5392  * VarDecInt (OLEAUT32.188)
5393  *
5394  * Return the integer portion of a DECIMAL.
5395  *
5396  * PARAMS
5397  *  pDecIn  [I] Source
5398  *  pDecOut [O] Destination
5399  *
5400  * RETURNS
5401  *  Success: S_OK.
5402  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5403  *
5404  * NOTES
5405  *  - The difference between this function and VarDecFix() is that VarDecFix() rounds
5406  *    negative numbers towards 0, while this function rounds them away from zero.
5407  */
5408 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5409 {
5410   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
5411     return E_INVALIDARG;
5412
5413   if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
5414     return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
5415
5416   FIXME("semi-stub!\n");
5417   return DISP_E_OVERFLOW;
5418 }
5419
5420 /************************************************************************
5421  * VarDecNeg (OLEAUT32.189)
5422  *
5423  * Change the sign of a DECIMAL.
5424  *
5425  * PARAMS
5426  *  pDecIn  [I] Source
5427  *  pDecOut [O] Destination
5428  *
5429  * RETURNS
5430  *  S_OK. This function does not fail.
5431  */
5432 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5433 {
5434   *pDecOut = *pDecIn;
5435   DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
5436   return S_OK;
5437 }
5438
5439 /************************************************************************
5440  * VarDecRound (OLEAUT32.203)
5441  *
5442  * Change the precision of a DECIMAL.
5443  *
5444  * PARAMS
5445  *  pDecIn    [I] Source
5446  *  cDecimals [I] New number of decimals to keep
5447  *  pDecOut   [O] Destination
5448  *
5449  * RETURNS
5450  *  Success: S_OK. pDecOut contains the rounded value.
5451  *  Failure: E_INVALIDARG if any argument is invalid.
5452  */
5453 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
5454 {
5455   if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
5456     return E_INVALIDARG;
5457
5458   if (cDecimals >= DEC_SCALE(pDecIn))
5459   {
5460     *pDecOut = *pDecIn; /* More precision than we have */
5461     return S_OK;
5462   }
5463
5464   FIXME("semi-stub!\n");
5465
5466   return DISP_E_OVERFLOW;
5467 }
5468
5469 /************************************************************************
5470  * VarDecCmp (OLEAUT32.204)
5471  *
5472  * Compare two DECIMAL values.
5473  *
5474  * PARAMS
5475  *  pDecLeft  [I] Source
5476  *  pDecRight [I] Value to compare
5477  *
5478  * RETURNS
5479  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
5480  *           is less than, equal to or greater than pDecRight respectively.
5481  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5482  */
5483 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
5484 {
5485   HRESULT hRet;
5486   DECIMAL result;
5487
5488   /* Subtract right from left, and compare the result to 0 */
5489   hRet = VarDecSub(pDecLeft, pDecRight, &result);
5490
5491   if (SUCCEEDED(hRet))
5492   {
5493     int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
5494
5495     if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
5496       hRet = (HRESULT)VARCMP_LT;
5497     else if (non_zero)
5498       hRet = (HRESULT)VARCMP_GT;
5499     else
5500       hRet = (HRESULT)VARCMP_EQ;
5501   }
5502   return hRet;
5503 }
5504
5505 /************************************************************************
5506  * VarDecCmpR8 (OLEAUT32.298)
5507  *
5508  * Compare a DECIMAL to a double
5509  *
5510  * PARAMS
5511  *  pDecLeft [I] DECIMAL Source
5512  *  dblRight [I] double to compare to pDecLeft
5513  *
5514  * RETURNS
5515  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
5516  *           is less than, equal to or greater than pDecLeft respectively.
5517  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5518  */
5519 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
5520 {
5521   HRESULT hRet;
5522   DECIMAL decRight;
5523
5524   hRet = VarDecFromR8(dblRight, &decRight);
5525
5526   if (SUCCEEDED(hRet))
5527     hRet = VarDecCmp(pDecLeft, &decRight);
5528
5529   return hRet;
5530 }
5531
5532 /* BOOL
5533  */
5534
5535 /************************************************************************
5536  * VarBoolFromUI1 (OLEAUT32.118)
5537  *
5538  * Convert a VT_UI1 to a VT_BOOL.
5539  *
5540  * PARAMS
5541  *  bIn      [I] Source
5542  *  pBoolOut [O] Destination
5543  *
5544  * RETURNS
5545  *  S_OK.
5546  */
5547 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
5548 {
5549   *pBoolOut = bIn ? VARIANT_TRUE : VARIANT_FALSE;
5550   return S_OK;
5551 }
5552
5553 /************************************************************************
5554  * VarBoolFromI2 (OLEAUT32.119)
5555  *
5556  * Convert a VT_I2 to a VT_BOOL.
5557  *
5558  * PARAMS
5559  *  sIn      [I] Source
5560  *  pBoolOut [O] Destination
5561  *
5562  * RETURNS
5563  *  S_OK.
5564  */
5565 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
5566 {
5567   *pBoolOut = sIn ? VARIANT_TRUE : VARIANT_FALSE;
5568   return S_OK;
5569 }
5570
5571 /************************************************************************
5572  * VarBoolFromI4 (OLEAUT32.120)
5573  *
5574  * Convert a VT_I4 to a VT_BOOL.
5575  *
5576  * PARAMS
5577  *  sIn      [I] Source
5578  *  pBoolOut [O] Destination
5579  *
5580  * RETURNS
5581  *  S_OK.
5582  */
5583 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
5584 {
5585   *pBoolOut = lIn ? VARIANT_TRUE : VARIANT_FALSE;
5586   return S_OK;
5587 }
5588
5589 /************************************************************************
5590  * VarBoolFromR4 (OLEAUT32.121)
5591  *
5592  * Convert a VT_R4 to a VT_BOOL.
5593  *
5594  * PARAMS
5595  *  fltIn    [I] Source
5596  *  pBoolOut [O] Destination
5597  *
5598  * RETURNS
5599  *  S_OK.
5600  */
5601 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
5602 {
5603   *pBoolOut = fltIn ? VARIANT_TRUE : VARIANT_FALSE;
5604   return S_OK;
5605 }
5606
5607 /************************************************************************
5608  * VarBoolFromR8 (OLEAUT32.122)
5609  *
5610  * Convert a VT_R8 to a VT_BOOL.
5611  *
5612  * PARAMS
5613  *  dblIn    [I] Source
5614  *  pBoolOut [O] Destination
5615  *
5616  * RETURNS
5617  *  S_OK.
5618  */
5619 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
5620 {
5621   *pBoolOut = dblIn ? VARIANT_TRUE : VARIANT_FALSE;
5622   return S_OK;
5623 }
5624
5625 /************************************************************************
5626  * VarBoolFromDate (OLEAUT32.123)
5627  *
5628  * Convert a VT_DATE to a VT_BOOL.
5629  *
5630  * PARAMS
5631  *  dateIn   [I] Source
5632  *  pBoolOut [O] Destination
5633  *
5634  * RETURNS
5635  *  S_OK.
5636  */
5637 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
5638 {
5639   *pBoolOut = dateIn ? VARIANT_TRUE : VARIANT_FALSE;
5640   return S_OK;
5641 }
5642
5643 /************************************************************************
5644  * VarBoolFromCy (OLEAUT32.124)
5645  *
5646  * Convert a VT_CY to a VT_BOOL.
5647  *
5648  * PARAMS
5649  *  cyIn     [I] Source
5650  *  pBoolOut [O] Destination
5651  *
5652  * RETURNS
5653  *  S_OK.
5654  */
5655 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
5656 {
5657   *pBoolOut = cyIn.int64 ? VARIANT_TRUE : VARIANT_FALSE;
5658   return S_OK;
5659 }
5660
5661 static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
5662 {
5663   HRSRC hrsrc;
5664
5665   hrsrc = FindResourceExW( OLEAUT32_hModule, (LPWSTR)RT_STRING,
5666                            MAKEINTRESOURCEW((dwId >> 4) + 1), langId );
5667   if (hrsrc)
5668   {
5669     HGLOBAL hmem = LoadResource( OLEAUT32_hModule, hrsrc );
5670
5671     if (hmem)
5672     {
5673       const WCHAR *p;
5674       unsigned int i;
5675
5676       p = LockResource( hmem );
5677       for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
5678
5679       memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
5680       lpszDest[*p] = '\0';
5681       TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
5682       return TRUE;
5683     }
5684   }
5685   return FALSE;
5686 }
5687
5688 /************************************************************************
5689  * VarBoolFromStr (OLEAUT32.125)
5690  *
5691  * Convert a VT_BSTR to a VT_BOOL.
5692  *
5693  * PARAMS
5694  *  strIn    [I] Source
5695  *  lcid     [I] LCID for the conversion
5696  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5697  *  pBoolOut [O] Destination
5698  *
5699  * RETURNS
5700  *  Success: S_OK.
5701  *  Failure: E_INVALIDARG, if pBoolOut is invalid.
5702  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
5703  *
5704  * NOTES
5705  *  - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
5706  *  it may contain (in any case mapping) the text "true" or "false".
5707  *  - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
5708  *  localised text of "True" or "False" in the language specified by lcid.
5709  *  - If none of these matches occur, the string is treated as a numeric string
5710  *  and the boolean pBoolOut will be set according to whether the number is zero
5711  *  or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
5712  *  - If the text is not numeric and does not match any of the above, then
5713  *  DISP_E_TYPEMISMATCH is returned.
5714  */
5715 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
5716 {
5717   /* Any VB/VBA programmers out there should recognise these strings... */
5718   static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
5719   static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
5720   WCHAR szBuff[64];
5721   LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5722   HRESULT hRes = S_OK;
5723
5724   if (!strIn || !pBoolOut)
5725     return DISP_E_TYPEMISMATCH;
5726
5727   /* Check if we should be comparing against localised text */
5728   if (dwFlags & VAR_LOCALBOOL)
5729   {
5730     /* Convert our LCID into a usable value */
5731     lcid = ConvertDefaultLocale(lcid);
5732
5733     langId = LANGIDFROMLCID(lcid);
5734
5735     if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
5736       langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5737
5738     /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
5739      * I don't think this is needed unless any of the localised text strings
5740      * contain characters that can be so mapped. In the event that this is
5741      * true for a given language (possibly some Asian languages), then strIn
5742      * should be mapped here _only_ if langId is an Id for which this can occur.
5743      */
5744   }
5745
5746   /* Note that if we are not comparing against localised strings, langId
5747    * will have its default value of LANG_ENGLISH. This allows us to mimic
5748    * the native behaviour of always checking against English strings even
5749    * after we've checked for localised ones.
5750    */
5751 VarBoolFromStr_CheckLocalised:
5752   if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
5753   {
5754     /* Compare against localised strings, ignoring case */
5755     if (!strcmpiW(strIn, szBuff))
5756     {
5757       *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
5758       return hRes;
5759     }
5760     VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
5761     if (!strcmpiW(strIn, szBuff))
5762     {
5763       *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
5764       return hRes;
5765     }
5766   }
5767
5768   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5769   {
5770     /* We have checked the localised text, now check English */
5771     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5772     goto VarBoolFromStr_CheckLocalised;
5773   }
5774
5775   /* All checks against localised text have failed, try #TRUE#/#FALSE# */
5776   if (!strcmpW(strIn, szFalse))
5777     *pBoolOut = VARIANT_FALSE;
5778   else if (!strcmpW(strIn, szTrue))
5779     *pBoolOut = VARIANT_TRUE;
5780   else
5781   {
5782     double d;
5783
5784     /* If this string is a number, convert it as one */
5785     hRes = VarR8FromStr(strIn, lcid, dwFlags, &d);
5786     if (SUCCEEDED(hRes)) *pBoolOut = d ? VARIANT_TRUE : VARIANT_FALSE;
5787   }
5788   return hRes;
5789 }
5790
5791 /************************************************************************
5792  * VarBoolFromDisp (OLEAUT32.126)
5793  *
5794  * Convert a VT_DISPATCH to a VT_BOOL.
5795  *
5796  * PARAMS
5797  *  pdispIn   [I] Source
5798  *  lcid      [I] LCID for conversion
5799  *  pBoolOut  [O] Destination
5800  *
5801  * RETURNS
5802  *  Success: S_OK.
5803  *  Failure: E_INVALIDARG, if the source value is invalid
5804  *           DISP_E_OVERFLOW, if the value will not fit in the destination
5805  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
5806  */
5807 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
5808 {
5809   return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL);
5810 }
5811
5812 /************************************************************************
5813  * VarBoolFromI1 (OLEAUT32.233)
5814  *
5815  * Convert a VT_I1 to a VT_BOOL.
5816  *
5817  * PARAMS
5818  *  cIn      [I] Source
5819  *  pBoolOut [O] Destination
5820  *
5821  * RETURNS
5822  *  S_OK.
5823  */
5824 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
5825 {
5826   *pBoolOut = cIn ? VARIANT_TRUE : VARIANT_FALSE;
5827   return S_OK;
5828 }
5829
5830 /************************************************************************
5831  * VarBoolFromUI2 (OLEAUT32.234)
5832  *
5833  * Convert a VT_UI2 to a VT_BOOL.
5834  *
5835  * PARAMS
5836  *  usIn     [I] Source
5837  *  pBoolOut [O] Destination
5838  *
5839  * RETURNS
5840  *  S_OK.
5841  */
5842 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
5843 {
5844   *pBoolOut = usIn ? VARIANT_TRUE : VARIANT_FALSE;
5845   return S_OK;
5846 }
5847
5848 /************************************************************************
5849  * VarBoolFromUI4 (OLEAUT32.235)
5850  *
5851  * Convert a VT_UI4 to a VT_BOOL.
5852  *
5853  * PARAMS
5854  *  ulIn     [I] Source
5855  *  pBoolOut [O] Destination
5856  *
5857  * RETURNS
5858  *  S_OK.
5859  */
5860 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
5861 {
5862   *pBoolOut = ulIn ? VARIANT_TRUE : VARIANT_FALSE;
5863   return S_OK;
5864 }
5865
5866 /************************************************************************
5867  * VarBoolFromDec (OLEAUT32.236)
5868  *
5869  * Convert a VT_DECIMAL to a VT_BOOL.
5870  *
5871  * PARAMS
5872  *  pDecIn   [I] Source
5873  *  pBoolOut [O] Destination
5874  *
5875  * RETURNS
5876  *  Success: S_OK.
5877  *  Failure: E_INVALIDARG, if pDecIn is invalid.
5878  */
5879 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
5880 {
5881   if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
5882     return E_INVALIDARG;
5883
5884   if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
5885     *pBoolOut = VARIANT_TRUE;
5886   else
5887     *pBoolOut = VARIANT_FALSE;
5888   return S_OK;
5889 }
5890
5891 /************************************************************************
5892  * VarBoolFromI8 (OLEAUT32.370)
5893  *
5894  * Convert a VT_I8 to a VT_BOOL.
5895  *
5896  * PARAMS
5897  *  ullIn    [I] Source
5898  *  pBoolOut [O] Destination
5899  *
5900  * RETURNS
5901  *  S_OK.
5902  */
5903 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
5904 {
5905   *pBoolOut = llIn ? VARIANT_TRUE : VARIANT_FALSE;
5906   return S_OK;
5907 }
5908
5909 /************************************************************************
5910  * VarBoolFromUI8 (OLEAUT32.371)
5911  *
5912  * Convert a VT_UI8 to a VT_BOOL.
5913  *
5914  * PARAMS
5915  *  ullIn    [I] Source
5916  *  pBoolOut [O] Destination
5917  *
5918  * RETURNS
5919  *  S_OK.
5920  */
5921 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
5922 {
5923   *pBoolOut = ullIn ? VARIANT_TRUE : VARIANT_FALSE;
5924   return S_OK;
5925 }
5926
5927 /* BSTR
5928  */
5929
5930 /* Write a number from a UI8 and sign */
5931 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
5932 {
5933   do
5934   {
5935     WCHAR ulNextDigit = ulVal % 10;
5936
5937     *szOut-- = '0' + ulNextDigit;
5938     ulVal = (ulVal - ulNextDigit) / 10;
5939   } while (ulVal);
5940
5941   szOut++;
5942   return szOut;
5943 }
5944
5945 /* Create a (possibly localised) BSTR from a UI8 and sign */
5946 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
5947 {
5948   WCHAR szConverted[256];
5949
5950   if (dwFlags & VAR_NEGATIVE)
5951     *--szOut = '-';
5952
5953   if (dwFlags & LOCALE_USE_NLS)
5954   {
5955     /* Format the number for the locale */
5956     szConverted[0] = '\0';
5957     GetNumberFormatW(lcid,
5958                      dwFlags & LOCALE_NOUSEROVERRIDE,
5959                      szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
5960     szOut = szConverted;
5961   }
5962   return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
5963 }
5964
5965 /* Create a (possibly localised) BSTR from a UI8 and sign */
5966 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
5967 {
5968   WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5969
5970   if (!pbstrOut)
5971     return E_INVALIDARG;
5972
5973   /* Create the basic number string */
5974   *szOut-- = '\0';
5975   szOut = VARIANT_WriteNumber(ulVal, szOut);
5976
5977   *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5978   TRACE("returning %s\n", debugstr_w(*pbstrOut));
5979   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5980 }
5981
5982 /******************************************************************************
5983  * VarBstrFromUI1 (OLEAUT32.108)
5984  *
5985  * Convert a VT_UI1 to a VT_BSTR.
5986  *
5987  * PARAMS
5988  *  bIn      [I] Source
5989  *  lcid     [I] LCID for the conversion
5990  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5991  *  pbstrOut [O] Destination
5992  *
5993  * RETURNS
5994  *  Success: S_OK.
5995  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5996  *           E_OUTOFMEMORY, if memory allocation fails.
5997  */
5998 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5999 {
6000   return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
6001 }
6002
6003 /******************************************************************************
6004  * VarBstrFromI2 (OLEAUT32.109)
6005  *
6006  * Convert a VT_I2 to a VT_BSTR.
6007  *
6008  * PARAMS
6009  *  sIn      [I] Source
6010  *  lcid     [I] LCID for the conversion
6011  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6012  *  pbstrOut [O] Destination
6013  *
6014  * RETURNS
6015  *  Success: S_OK.
6016  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6017  *           E_OUTOFMEMORY, if memory allocation fails.
6018  */
6019 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6020 {
6021   ULONG64 ul64 = sIn;
6022
6023   if (sIn < 0)
6024   {
6025     ul64 = -sIn;
6026     dwFlags |= VAR_NEGATIVE;
6027   }
6028   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6029 }
6030
6031 /******************************************************************************
6032  * VarBstrFromI4 (OLEAUT32.110)
6033  *
6034  * Convert a VT_I4 to a VT_BSTR.
6035  *
6036  * PARAMS
6037  *  lIn      [I] Source
6038  *  lcid     [I] LCID for the conversion
6039  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6040  *  pbstrOut [O] Destination
6041  *
6042  * RETURNS
6043  *  Success: S_OK.
6044  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6045  *           E_OUTOFMEMORY, if memory allocation fails.
6046  */
6047 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6048 {
6049   ULONG64 ul64 = lIn;
6050
6051   if (lIn < 0)
6052   {
6053     ul64 = (ULONG)-lIn;
6054     dwFlags |= VAR_NEGATIVE;
6055   }
6056   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6057 }
6058
6059 static BSTR VARIANT_BstrReplaceDecimal(WCHAR * buff, LCID lcid, ULONG dwFlags)
6060 {
6061   BSTR bstrOut;
6062   WCHAR lpDecimalSep[16];
6063
6064   /* Native oleaut32 uses the locale-specific decimal separator even in the
6065      absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin 
6066      American locales will see "one thousand and one tenth" as "1000,1" 
6067      instead of "1000.1" (notice the comma). The following code checks for
6068      the need to replace the decimal separator, and if so, will prepare an
6069      appropriate NUMBERFMTW structure to do the job via GetNumberFormatW().
6070    */
6071   GetLocaleInfoW(lcid, LOCALE_SDECIMAL, lpDecimalSep, sizeof(lpDecimalSep) / sizeof(WCHAR));
6072   if (lpDecimalSep[0] == '.' && lpDecimalSep[1] == '\0')
6073   {
6074     /* locale is compatible with English - return original string */
6075     bstrOut = SysAllocString(buff);
6076   }
6077   else
6078   {
6079     WCHAR *p;
6080     WCHAR numbuff[256];
6081     WCHAR empty[1] = {'\0'};
6082     NUMBERFMTW minFormat;
6083
6084     minFormat.NumDigits = 0;
6085     minFormat.LeadingZero = 0;
6086     minFormat.Grouping = 0;
6087     minFormat.lpDecimalSep = lpDecimalSep;
6088     minFormat.lpThousandSep = empty;
6089     minFormat.NegativeOrder = 1; /* NLS_NEG_LEFT */
6090
6091     /* count number of decimal digits in string */
6092     p = strchrW( buff, '.' );
6093     if (p) minFormat.NumDigits = strlenW(p + 1);
6094
6095     numbuff[0] = '\0';
6096     if (!GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6097                    buff, &minFormat, numbuff, sizeof(numbuff) / sizeof(WCHAR)))
6098     {
6099       WARN("GetNumberFormatW() failed, returning raw number string instead\n");
6100       bstrOut = SysAllocString(buff);
6101     }
6102     else
6103     {
6104       TRACE("created minimal NLS string %s\n", debugstr_w(numbuff));
6105       bstrOut = SysAllocString(numbuff);
6106     }
6107   }
6108   return bstrOut;
6109 }
6110
6111 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
6112                                     BSTR* pbstrOut, LPCWSTR lpszFormat)
6113 {
6114   WCHAR buff[256];
6115
6116   if (!pbstrOut)
6117     return E_INVALIDARG;
6118
6119   sprintfW( buff, lpszFormat, dblIn );
6120
6121   /* Negative zeroes are disallowed (some applications depend on this).
6122      If buff starts with a minus, and then nothing follows but zeroes
6123      and/or a period, it is a negative zero and is replaced with a
6124      canonical zero. This duplicates native oleaut32 behavior.
6125    */
6126   if (buff[0] == '-')
6127   {
6128     const WCHAR szAccept[] = {'0', '.', '\0'};
6129     if (strlenW(buff + 1) == strspnW(buff + 1, szAccept))
6130     { buff[0] = '0'; buff[1] = '\0'; }
6131   }
6132
6133   TRACE("created string %s\n", debugstr_w(buff));
6134   if (dwFlags & LOCALE_USE_NLS)
6135   {
6136     WCHAR numbuff[256];
6137
6138     /* Format the number for the locale */
6139     numbuff[0] = '\0';
6140     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6141                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
6142     TRACE("created NLS string %s\n", debugstr_w(numbuff));
6143     *pbstrOut = SysAllocString(numbuff);
6144   }
6145   else
6146   {
6147     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
6148   }
6149   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6150 }
6151
6152 /******************************************************************************
6153  * VarBstrFromR4 (OLEAUT32.111)
6154  *
6155  * Convert a VT_R4 to a VT_BSTR.
6156  *
6157  * PARAMS
6158  *  fltIn    [I] Source
6159  *  lcid     [I] LCID for the conversion
6160  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6161  *  pbstrOut [O] Destination
6162  *
6163  * RETURNS
6164  *  Success: S_OK.
6165  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6166  *           E_OUTOFMEMORY, if memory allocation fails.
6167  */
6168 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6169 {
6170   return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
6171 }
6172
6173 /******************************************************************************
6174  * VarBstrFromR8 (OLEAUT32.112)
6175  *
6176  * Convert a VT_R8 to a VT_BSTR.
6177  *
6178  * PARAMS
6179  *  dblIn    [I] Source
6180  *  lcid     [I] LCID for the conversion
6181  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6182  *  pbstrOut [O] Destination
6183  *
6184  * RETURNS
6185  *  Success: S_OK.
6186  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6187  *           E_OUTOFMEMORY, if memory allocation fails.
6188  */
6189 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6190 {
6191   return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
6192 }
6193
6194 /******************************************************************************
6195  *    VarBstrFromCy   [OLEAUT32.113]
6196  *
6197  * Convert a VT_CY to a VT_BSTR.
6198  *
6199  * PARAMS
6200  *  cyIn     [I] Source
6201  *  lcid     [I] LCID for the conversion
6202  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6203  *  pbstrOut [O] Destination
6204  *
6205  * RETURNS
6206  *  Success: S_OK.
6207  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6208  *           E_OUTOFMEMORY, if memory allocation fails.
6209  */
6210 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
6211 {
6212   WCHAR buff[256];
6213   double dblVal;
6214
6215   if (!pbstrOut)
6216     return E_INVALIDARG;
6217
6218   VarR8FromCy(cyIn, &dblVal);
6219   sprintfW(buff, szDoubleFormatW, dblVal);
6220
6221   if (dwFlags & LOCALE_USE_NLS)
6222   {
6223     WCHAR cybuff[256];
6224
6225     /* Format the currency for the locale */
6226     cybuff[0] = '\0';
6227     GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6228                        buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
6229     *pbstrOut = SysAllocString(cybuff);
6230   }
6231   else
6232     *pbstrOut = SysAllocString(buff);
6233
6234   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6235 }
6236
6237 /******************************************************************************
6238  *    VarBstrFromDate    [OLEAUT32.114]
6239  *
6240  * Convert a VT_DATE to a VT_BSTR.
6241  *
6242  * PARAMS
6243  *  dateIn   [I] Source
6244  *  lcid     [I] LCID for the conversion
6245  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6246  *  pbstrOut [O] Destination
6247  *
6248  * RETURNS
6249  *  Success: S_OK.
6250  *  Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
6251  *           E_OUTOFMEMORY, if memory allocation fails.
6252  */
6253 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6254 {
6255   SYSTEMTIME st;
6256   DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
6257   WCHAR date[128], *time;
6258
6259   TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
6260
6261   if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
6262     return E_INVALIDARG;
6263
6264   *pbstrOut = NULL;
6265
6266   if (dwFlags & VAR_CALENDAR_THAI)
6267       st.wYear += 553; /* Use the Thai buddhist calendar year */
6268   else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
6269       FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
6270
6271   if (dwFlags & LOCALE_USE_NLS)
6272     dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
6273   else
6274   {
6275     double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
6276     double partial = dateIn - whole;
6277
6278     if (whole == 0.0)
6279       dwFlags |= VAR_TIMEVALUEONLY;
6280     else if (partial < 1e-12)
6281       dwFlags |= VAR_DATEVALUEONLY;
6282   }
6283
6284   if (dwFlags & VAR_TIMEVALUEONLY)
6285     date[0] = '\0';
6286   else
6287     if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
6288                         sizeof(date)/sizeof(WCHAR)))
6289       return E_INVALIDARG;
6290
6291   if (!(dwFlags & VAR_DATEVALUEONLY))
6292   {
6293     time = date + strlenW(date);
6294     if (time != date)
6295       *time++ = ' ';
6296     if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
6297                         sizeof(date)/sizeof(WCHAR)-(time-date)))
6298       return E_INVALIDARG;
6299   }
6300
6301   *pbstrOut = SysAllocString(date);
6302   if (*pbstrOut)
6303     TRACE("returning %s\n", debugstr_w(*pbstrOut));
6304   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6305 }
6306
6307 /******************************************************************************
6308  * VarBstrFromBool (OLEAUT32.116)
6309  *
6310  * Convert a VT_BOOL to a VT_BSTR.
6311  *
6312  * PARAMS
6313  *  boolIn   [I] Source
6314  *  lcid     [I] LCID for the conversion
6315  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6316  *  pbstrOut [O] Destination
6317  *
6318  * RETURNS
6319  *  Success: S_OK.
6320  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6321  *           E_OUTOFMEMORY, if memory allocation fails.
6322  *
6323  * NOTES
6324  *  If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
6325  *  localised text of "True" or "False". To convert a bool into a
6326  *  numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
6327  */
6328 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6329 {
6330   WCHAR szBuff[64];
6331   DWORD dwResId = IDS_TRUE;
6332   LANGID langId;
6333
6334   TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn, lcid, dwFlags, pbstrOut);
6335
6336   if (!pbstrOut)
6337     return E_INVALIDARG;
6338
6339   /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
6340    * for variant formatting */
6341   switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
6342   {
6343   case VAR_BOOLONOFF:
6344       dwResId = IDS_ON;
6345       break;
6346   case VAR_BOOLYESNO:
6347       dwResId = IDS_YES;
6348       break;
6349   case VAR_LOCALBOOL:
6350       break;
6351   default:
6352     lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
6353   }
6354
6355   lcid = ConvertDefaultLocale(lcid);
6356   langId = LANGIDFROMLCID(lcid);
6357   if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
6358     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6359
6360   if (boolIn == VARIANT_FALSE)
6361     dwResId++; /* Use negative form */
6362
6363 VarBstrFromBool_GetLocalised:
6364   if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
6365   {
6366     *pbstrOut = SysAllocString(szBuff);
6367     return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6368   }
6369
6370   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
6371   {
6372     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6373     goto VarBstrFromBool_GetLocalised;
6374   }
6375
6376   /* Should never get here */
6377   WARN("Failed to load bool text!\n");
6378   return E_OUTOFMEMORY;
6379 }
6380
6381 /******************************************************************************
6382  * VarBstrFromI1 (OLEAUT32.229)
6383  *
6384  * Convert a VT_I1 to a VT_BSTR.
6385  *
6386  * PARAMS
6387  *  cIn      [I] Source
6388  *  lcid     [I] LCID for the conversion
6389  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6390  *  pbstrOut [O] Destination
6391  *
6392  * RETURNS
6393  *  Success: S_OK.
6394  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6395  *           E_OUTOFMEMORY, if memory allocation fails.
6396  */
6397 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6398 {
6399   ULONG64 ul64 = cIn;
6400
6401   if (cIn < 0)
6402   {
6403     ul64 = -cIn;
6404     dwFlags |= VAR_NEGATIVE;
6405   }
6406   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6407 }
6408
6409 /******************************************************************************
6410  * VarBstrFromUI2 (OLEAUT32.230)
6411  *
6412  * Convert a VT_UI2 to a VT_BSTR.
6413  *
6414  * PARAMS
6415  *  usIn     [I] Source
6416  *  lcid     [I] LCID for the conversion
6417  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6418  *  pbstrOut [O] Destination
6419  *
6420  * RETURNS
6421  *  Success: S_OK.
6422  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6423  *           E_OUTOFMEMORY, if memory allocation fails.
6424  */
6425 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6426 {
6427   return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
6428 }
6429
6430 /******************************************************************************
6431  * VarBstrFromUI4 (OLEAUT32.231)
6432  *
6433  * Convert a VT_UI4 to a VT_BSTR.
6434  *
6435  * PARAMS
6436  *  ulIn     [I] Source
6437  *  lcid     [I] LCID for the conversion
6438  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6439  *  pbstrOut [O] Destination
6440  *
6441  * RETURNS
6442  *  Success: S_OK.
6443  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6444  *           E_OUTOFMEMORY, if memory allocation fails.
6445  */
6446 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6447 {
6448   return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
6449 }
6450
6451 /******************************************************************************
6452  * VarBstrFromDec (OLEAUT32.232)
6453  *
6454  * Convert a VT_DECIMAL to a VT_BSTR.
6455  *
6456  * PARAMS
6457  *  pDecIn   [I] Source
6458  *  lcid     [I] LCID for the conversion
6459  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6460  *  pbstrOut [O] Destination
6461  *
6462  * RETURNS
6463  *  Success: S_OK.
6464  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6465  *           E_OUTOFMEMORY, if memory allocation fails.
6466  */
6467 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6468 {
6469   WCHAR buff[256];
6470   VARIANT_DI temp;
6471
6472   if (!pbstrOut)
6473     return E_INVALIDARG;
6474
6475   VARIANT_DIFromDec(pDecIn, &temp);
6476   VARIANT_DI_tostringW(&temp, buff, 256);
6477
6478   if (dwFlags & LOCALE_USE_NLS)
6479   {
6480     WCHAR numbuff[256];
6481
6482     /* Format the number for the locale */
6483     numbuff[0] = '\0';
6484     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6485                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
6486     TRACE("created NLS string %s\n", debugstr_w(numbuff));
6487     *pbstrOut = SysAllocString(numbuff);
6488   }
6489   else
6490   {
6491     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
6492   }
6493   
6494   TRACE("returning %s\n", debugstr_w(*pbstrOut));
6495   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6496 }
6497
6498 /************************************************************************
6499  * VarBstrFromI8 (OLEAUT32.370)
6500  *
6501  * Convert a VT_I8 to a VT_BSTR.
6502  *
6503  * PARAMS
6504  *  llIn     [I] Source
6505  *  lcid     [I] LCID for the conversion
6506  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6507  *  pbstrOut [O] Destination
6508  *
6509  * RETURNS
6510  *  Success: S_OK.
6511  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6512  *           E_OUTOFMEMORY, if memory allocation fails.
6513  */
6514 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6515 {
6516   ULONG64 ul64 = llIn;
6517
6518   if (llIn < 0)
6519   {
6520     ul64 = -llIn;
6521     dwFlags |= VAR_NEGATIVE;
6522   }
6523   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6524 }
6525
6526 /************************************************************************
6527  * VarBstrFromUI8 (OLEAUT32.371)
6528  *
6529  * Convert a VT_UI8 to a VT_BSTR.
6530  *
6531  * PARAMS
6532  *  ullIn    [I] Source
6533  *  lcid     [I] LCID for the conversion
6534  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6535  *  pbstrOut [O] Destination
6536  *
6537  * RETURNS
6538  *  Success: S_OK.
6539  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6540  *           E_OUTOFMEMORY, if memory allocation fails.
6541  */
6542 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6543 {
6544   return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
6545 }
6546
6547 /**********************************************************************
6548  * VarBstrCat (OLEAUT32.313)
6549  *
6550  * Concatenate two BSTR values.
6551  *
6552  * PARAMS
6553  *  pbstrLeft  [I] Source
6554  *  pbstrRight [I] Value to concatenate
6555  *  pbstrOut   [O] Destination
6556  *
6557  * RETURNS
6558  *  Success: S_OK.
6559  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6560  *           E_OUTOFMEMORY, if memory allocation fails.
6561  */
6562 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
6563 {
6564   unsigned int len;
6565
6566   if (!pbstrOut)
6567     return E_INVALIDARG;
6568
6569   len = pbstrLeft ? strlenW(pbstrLeft) : 0;
6570   if (pbstrRight)
6571     len += strlenW(pbstrRight);
6572
6573   *pbstrOut = SysAllocStringLen(NULL, len);
6574   if (!*pbstrOut)
6575     return E_OUTOFMEMORY;
6576
6577   (*pbstrOut)[0] = '\0';
6578
6579   if (pbstrLeft)
6580     strcpyW(*pbstrOut, pbstrLeft);
6581
6582   if (pbstrRight)
6583     strcatW(*pbstrOut, pbstrRight);
6584
6585   return S_OK;
6586 }
6587
6588 /**********************************************************************
6589  * VarBstrCmp (OLEAUT32.314)
6590  *
6591  * Compare two BSTR values.
6592  *
6593  * PARAMS
6594  *  pbstrLeft  [I] Source
6595  *  pbstrRight [I] Value to compare
6596  *  lcid       [I] LCID for the comparison
6597  *  dwFlags    [I] Flags to pass directly to CompareStringW().
6598  *
6599  * RETURNS
6600  *  VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
6601  *  than, equal to or greater than pbstrRight respectively.
6602  *  VARCMP_NULL is returned if either string is NULL, unless both are NULL
6603  *  in which case VARCMP_EQ is returned.
6604  */
6605 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
6606 {
6607     if (!pbstrLeft)
6608     {
6609       if (!pbstrRight || !*pbstrRight)
6610         return VARCMP_EQ;
6611       return VARCMP_NULL;
6612     }
6613     else if (!pbstrRight)
6614     {
6615       if (!*pbstrLeft)
6616         return VARCMP_EQ;
6617       return VARCMP_NULL;
6618     }
6619
6620     return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
6621 }
6622
6623 /*
6624  * DATE
6625  */
6626
6627 /******************************************************************************
6628  * VarDateFromUI1 (OLEAUT32.88)
6629  *
6630  * Convert a VT_UI1 to a VT_DATE.
6631  *
6632  * PARAMS
6633  *  bIn      [I] Source
6634  *  pdateOut [O] Destination
6635  *
6636  * RETURNS
6637  *  S_OK.
6638  */
6639 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
6640 {
6641   return VarR8FromUI1(bIn, pdateOut);
6642 }
6643
6644 /******************************************************************************
6645  * VarDateFromI2 (OLEAUT32.89)
6646  *
6647  * Convert a VT_I2 to a VT_DATE.
6648  *
6649  * PARAMS
6650  *  sIn      [I] Source
6651  *  pdateOut [O] Destination
6652  *
6653  * RETURNS
6654  *  S_OK.
6655  */
6656 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
6657 {
6658   return VarR8FromI2(sIn, pdateOut);
6659 }
6660
6661 /******************************************************************************
6662  * VarDateFromI4 (OLEAUT32.90)
6663  *
6664  * Convert a VT_I4 to a VT_DATE.
6665  *
6666  * PARAMS
6667  *  lIn      [I] Source
6668  *  pdateOut [O] Destination
6669  *
6670  * RETURNS
6671  *  S_OK.
6672  */
6673 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
6674 {
6675   return VarDateFromR8(lIn, pdateOut);
6676 }
6677
6678 /******************************************************************************
6679  * VarDateFromR4 (OLEAUT32.91)
6680  *
6681  * Convert a VT_R4 to a VT_DATE.
6682  *
6683  * PARAMS
6684  *  fltIn    [I] Source
6685  *  pdateOut [O] Destination
6686  *
6687  * RETURNS
6688  *  S_OK.
6689  */
6690 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
6691 {
6692   return VarR8FromR4(fltIn, pdateOut);
6693 }
6694
6695 /******************************************************************************
6696  * VarDateFromR8 (OLEAUT32.92)
6697  *
6698  * Convert a VT_R8 to a VT_DATE.
6699  *
6700  * PARAMS
6701  *  dblIn    [I] Source
6702  *  pdateOut [O] Destination
6703  *
6704  * RETURNS
6705  *  S_OK.
6706  */
6707 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
6708 {
6709   if (dblIn <= (DATE_MIN - 1.0) || dblIn >= (DATE_MAX + 1.0)) return DISP_E_OVERFLOW;
6710   *pdateOut = (DATE)dblIn;
6711   return S_OK;
6712 }
6713
6714 /**********************************************************************
6715  * VarDateFromDisp (OLEAUT32.95)
6716  *
6717  * Convert a VT_DISPATCH to a VT_DATE.
6718  *
6719  * PARAMS
6720  *  pdispIn  [I] Source
6721  *  lcid     [I] LCID for conversion
6722  *  pdateOut [O] Destination
6723  *
6724  * RETURNS
6725  *  Success: S_OK.
6726  *  Failure: E_INVALIDARG, if the source value is invalid
6727  *           DISP_E_OVERFLOW, if the value will not fit in the destination
6728  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
6729  */
6730 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
6731 {
6732   return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE);
6733 }
6734
6735 /******************************************************************************
6736  * VarDateFromBool (OLEAUT32.96)
6737  *
6738  * Convert a VT_BOOL to a VT_DATE.
6739  *
6740  * PARAMS
6741  *  boolIn   [I] Source
6742  *  pdateOut [O] Destination
6743  *
6744  * RETURNS
6745  *  S_OK.
6746  */
6747 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
6748 {
6749   return VarR8FromBool(boolIn, pdateOut);
6750 }
6751
6752 /**********************************************************************
6753  * VarDateFromCy (OLEAUT32.93)
6754  *
6755  * Convert a VT_CY to a VT_DATE.
6756  *
6757  * PARAMS
6758  *  lIn      [I] Source
6759  *  pdateOut [O] Destination
6760  *
6761  * RETURNS
6762  *  S_OK.
6763  */
6764 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
6765 {
6766   return VarR8FromCy(cyIn, pdateOut);
6767 }
6768
6769 /* Date string parsing */
6770 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
6771 #define DP_DATESEP 0x02 /* Date separator */
6772 #define DP_MONTH   0x04 /* Month name */
6773 #define DP_AM      0x08 /* AM */
6774 #define DP_PM      0x10 /* PM */
6775
6776 typedef struct tagDATEPARSE
6777 {
6778     DWORD dwCount;      /* Number of fields found so far (maximum 6) */
6779     DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
6780     DWORD dwFlags[6];   /* Flags for each field */
6781     DWORD dwValues[6];  /* Value of each field */
6782 } DATEPARSE;
6783
6784 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
6785
6786 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
6787
6788 /* Determine if a day is valid in a given month of a given year */
6789 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
6790 {
6791   static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
6792
6793   if (day && month && month < 13)
6794   {
6795     if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
6796       return TRUE;
6797   }
6798   return FALSE;
6799 }
6800
6801 /* Possible orders for 3 numbers making up a date */
6802 #define ORDER_MDY 0x01
6803 #define ORDER_YMD 0x02
6804 #define ORDER_YDM 0x04
6805 #define ORDER_DMY 0x08
6806 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
6807
6808 /* Determine a date for a particular locale, from 3 numbers */
6809 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
6810                                        DWORD offset, SYSTEMTIME *st)
6811 {
6812   DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
6813
6814   if (!dp->dwCount)
6815   {
6816     v1 = 30; /* Default to (Variant) 0 date part */
6817     v2 = 12;
6818     v3 = 1899;
6819     goto VARIANT_MakeDate_OK;
6820   }
6821
6822   v1 = dp->dwValues[offset + 0];
6823   v2 = dp->dwValues[offset + 1];
6824   if (dp->dwCount == 2)
6825   {
6826     SYSTEMTIME current;
6827     GetSystemTime(&current);
6828     v3 = current.wYear;
6829   }
6830   else
6831     v3 = dp->dwValues[offset + 2];
6832
6833   TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
6834
6835   /* If one number must be a month (Because a month name was given), then only
6836    * consider orders with the month in that position.
6837    * If we took the current year as 'v3', then only allow a year in that position.
6838    */
6839   if (dp->dwFlags[offset + 0] & DP_MONTH)
6840   {
6841     dwAllOrders = ORDER_MDY;
6842   }
6843   else if (dp->dwFlags[offset + 1] & DP_MONTH)
6844   {
6845     dwAllOrders = ORDER_DMY;
6846     if (dp->dwCount > 2)
6847       dwAllOrders |= ORDER_YMD;
6848   }
6849   else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
6850   {
6851     dwAllOrders = ORDER_YDM;
6852   }
6853   else
6854   {
6855     dwAllOrders = ORDER_MDY|ORDER_DMY;
6856     if (dp->dwCount > 2)
6857       dwAllOrders |= (ORDER_YMD|ORDER_YDM);
6858   }
6859
6860 VARIANT_MakeDate_Start:
6861   TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
6862
6863   while (dwAllOrders)
6864   {
6865     DWORD dwTemp;
6866
6867     if (dwCount == 0)
6868     {
6869       /* First: Try the order given by iDate */
6870       switch (iDate)
6871       {
6872       case 0:  dwTry = dwAllOrders & ORDER_MDY; break;
6873       case 1:  dwTry = dwAllOrders & ORDER_DMY; break;
6874       default: dwTry = dwAllOrders & ORDER_YMD; break;
6875       }
6876     }
6877     else if (dwCount == 1)
6878     {
6879       /* Second: Try all the orders compatible with iDate */
6880       switch (iDate)
6881       {
6882       case 0:  dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
6883       case 1:  dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
6884       default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
6885       }
6886     }
6887     else
6888     {
6889       /* Finally: Try any remaining orders */
6890       dwTry = dwAllOrders;
6891     }
6892
6893     TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
6894
6895     dwCount++;
6896     if (!dwTry)
6897       continue;
6898
6899 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6900
6901     if (dwTry & ORDER_MDY)
6902     {
6903       if (VARIANT_IsValidMonthDay(v2,v1,v3))
6904       {
6905         DATE_SWAP(v1,v2);
6906         goto VARIANT_MakeDate_OK;
6907       }
6908       dwAllOrders &= ~ORDER_MDY;
6909     }
6910     if (dwTry & ORDER_YMD)
6911     {
6912       if (VARIANT_IsValidMonthDay(v3,v2,v1))
6913       {
6914         DATE_SWAP(v1,v3);
6915         goto VARIANT_MakeDate_OK;
6916       }
6917       dwAllOrders &= ~ORDER_YMD;
6918     }
6919     if (dwTry & ORDER_YDM)
6920     {
6921       if (VARIANT_IsValidMonthDay(v2,v3,v1))
6922       {
6923         DATE_SWAP(v1,v2);
6924         DATE_SWAP(v2,v3);
6925         goto VARIANT_MakeDate_OK;
6926       }
6927       dwAllOrders &= ~ORDER_YDM;
6928     }
6929     if (dwTry & ORDER_DMY)
6930     {
6931       if (VARIANT_IsValidMonthDay(v1,v2,v3))
6932         goto VARIANT_MakeDate_OK;
6933       dwAllOrders &= ~ORDER_DMY;
6934     }
6935     if (dwTry & ORDER_MYD)
6936     {
6937       /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6938       if (VARIANT_IsValidMonthDay(v3,v1,v2))
6939       {
6940         DATE_SWAP(v1,v3);
6941         DATE_SWAP(v2,v3);
6942         goto VARIANT_MakeDate_OK;
6943       }
6944       dwAllOrders &= ~ORDER_MYD;
6945     }
6946   }
6947
6948   if (dp->dwCount == 2)
6949   {
6950     /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6951     v3 = 1; /* 1st of the month */
6952     dwAllOrders = ORDER_YMD|ORDER_MYD;
6953     dp->dwCount = 0; /* Don't return to this code path again */
6954     dwCount = 0;
6955     goto VARIANT_MakeDate_Start;
6956   }
6957
6958   /* No valid dates were able to be constructed */
6959   return DISP_E_TYPEMISMATCH;
6960
6961 VARIANT_MakeDate_OK:
6962
6963   /* Check that the time part is ok */
6964   if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
6965     return DISP_E_TYPEMISMATCH;
6966
6967   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6968   if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
6969     st->wHour += 12;
6970   else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
6971     st->wHour = 0;
6972   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6973
6974   st->wDay = v1;
6975   st->wMonth = v2;
6976   /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6977    * be retrieved from:
6978    * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6979    * But Wine doesn't have/use that key as at the time of writing.
6980    */
6981   st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
6982   TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
6983   return S_OK;
6984 }
6985
6986 /******************************************************************************
6987  * VarDateFromStr [OLEAUT32.94]
6988  *
6989  * Convert a VT_BSTR to at VT_DATE.
6990  *
6991  * PARAMS
6992  *  strIn    [I] String to convert
6993  *  lcid     [I] Locale identifier for the conversion
6994  *  dwFlags  [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6995  *  pdateOut [O] Destination for the converted value
6996  *
6997  * RETURNS
6998  *  Success: S_OK. pdateOut contains the converted value.
6999  *  FAILURE: An HRESULT error code indicating the prolem.
7000  *
7001  * NOTES
7002  *  Any date format that can be created using the date formats from lcid
7003  *  (Either from kernel Nls functions, variant conversion or formatting) is a
7004  *  valid input to this function. In addition, a few more esoteric formats are
7005  *  also supported for compatibility with the native version. The date is
7006  *  interpreted according to the date settings in the control panel, unless
7007  *  the date is invalid in that format, in which the most compatible format
7008  *  that produces a valid date will be used.
7009  */
7010 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
7011 {
7012   static const USHORT ParseDateTokens[] =
7013   {
7014     LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
7015     LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
7016     LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
7017     LOCALE_SMONTHNAME13,
7018     LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
7019     LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
7020     LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
7021     LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
7022     LOCALE_SABBREVMONTHNAME13,
7023     LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
7024     LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
7025     LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
7026     LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
7027     LOCALE_SABBREVDAYNAME7,
7028     LOCALE_S1159, LOCALE_S2359
7029   };
7030   static const BYTE ParseDateMonths[] =
7031   {
7032     1,2,3,4,5,6,7,8,9,10,11,12,13,
7033     1,2,3,4,5,6,7,8,9,10,11,12,13
7034   };
7035   size_t i;
7036   BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
7037   DATEPARSE dp;
7038   DWORD dwDateSeps = 0, iDate = 0;
7039   HRESULT hRet = S_OK;
7040
7041   if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
7042       (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
7043     return E_INVALIDARG;
7044
7045   if (!strIn)
7046     return DISP_E_TYPEMISMATCH;
7047
7048   *pdateOut = 0.0;
7049
7050   TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
7051
7052   memset(&dp, 0, sizeof(dp));
7053
7054   GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
7055                  (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
7056   TRACE("iDate is %ld\n", iDate);
7057
7058   /* Get the month/day/am/pm tokens for this locale */
7059   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7060   {
7061     WCHAR buff[128];
7062     LCTYPE lctype =  ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
7063
7064     /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
7065      *        GetAltMonthNames(). We should really cache these strings too.
7066      */
7067     buff[0] = '\0';
7068     GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
7069     tokens[i] = SysAllocString(buff);
7070     TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
7071   }
7072
7073   /* Parse the string into our structure */
7074   while (*strIn)
7075   {
7076     if (dp.dwCount > 6)
7077       break;
7078
7079     if (isdigitW(*strIn))
7080     {
7081       dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
7082       dp.dwCount++;
7083       strIn--;
7084     }
7085     else if (isalpha(*strIn))
7086     {
7087       BOOL bFound = FALSE;
7088
7089       for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7090       {
7091         DWORD dwLen = strlenW(tokens[i]);
7092         if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
7093         {
7094           if (i <= 25)
7095           {
7096             dp.dwValues[dp.dwCount] = ParseDateMonths[i];
7097             dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
7098             dp.dwCount++;
7099           }
7100           else if (i > 39)
7101           {
7102             if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
7103               hRet = DISP_E_TYPEMISMATCH;
7104             else
7105             {
7106               dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
7107               dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
7108             }
7109           }
7110           strIn += (dwLen - 1);
7111           bFound = TRUE;
7112           break;
7113         }
7114       }
7115
7116       if (!bFound)
7117       {
7118         if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
7119             (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7120         {
7121           /* Special case - 'a' and 'p' are recognised as short for am/pm */
7122           if (*strIn == 'a' || *strIn == 'A')
7123           {
7124             dp.dwFlags[dp.dwCount - 1] |= DP_AM;
7125             dp.dwParseFlags |=  DP_AM;
7126           }
7127           else
7128           {
7129             dp.dwFlags[dp.dwCount - 1] |= DP_PM;
7130             dp.dwParseFlags |=  DP_PM;
7131           }
7132           strIn++;
7133         }
7134         else
7135         {
7136           TRACE("No matching token for %s\n", debugstr_w(strIn));
7137           hRet = DISP_E_TYPEMISMATCH;
7138           break;
7139         }
7140       }
7141     }
7142     else if (*strIn == ':' ||  *strIn == '.')
7143     {
7144       if (!dp.dwCount || !strIn[1])
7145         hRet = DISP_E_TYPEMISMATCH;
7146       else
7147         dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
7148     }
7149     else if (*strIn == '-' || *strIn == '/')
7150     {
7151       dwDateSeps++;
7152       if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
7153         hRet = DISP_E_TYPEMISMATCH;
7154       else
7155         dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
7156     }
7157     else if (*strIn == ',' || isspaceW(*strIn))
7158     {
7159       if (*strIn == ',' && !strIn[1])
7160         hRet = DISP_E_TYPEMISMATCH;
7161     }
7162     else
7163     {
7164       hRet = DISP_E_TYPEMISMATCH;
7165     }
7166     strIn++;
7167   }
7168
7169   if (!dp.dwCount || dp.dwCount > 6 ||
7170       (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7171     hRet = DISP_E_TYPEMISMATCH;
7172
7173   if (SUCCEEDED(hRet))
7174   {
7175     SYSTEMTIME st;
7176     DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
7177
7178     st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
7179
7180     /* Figure out which numbers correspond to which fields.
7181      *
7182      * This switch statement works based on the fact that native interprets any
7183      * fields that are not joined with a time separator ('.' or ':') as date
7184      * fields. Thus we construct a value from 0-32 where each set bit indicates
7185      * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
7186      * For valid permutations, we set dwOffset to point to the first date field
7187      * and shorten dp.dwCount by the number of time fields found. The real
7188      * magic here occurs in VARIANT_MakeDate() above, where we determine what
7189      * each date number must represent in the context of iDate.
7190      */
7191     TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
7192
7193     switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
7194     {
7195     case 0x1: /* TT TTDD TTDDD */
7196       if (dp.dwCount > 3 &&
7197           ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
7198           (dp.dwFlags[4] & (DP_AM|DP_PM))))
7199         hRet = DISP_E_TYPEMISMATCH;
7200       else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
7201         hRet = DISP_E_TYPEMISMATCH;
7202       st.wHour = dp.dwValues[0];
7203       st.wMinute  = dp.dwValues[1];
7204       dp.dwCount -= 2;
7205       dwOffset = 2;
7206       break;
7207
7208     case 0x3: /* TTT TTTDD TTTDDD */
7209       if (dp.dwCount > 4 &&
7210           ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
7211           (dp.dwFlags[5] & (DP_AM|DP_PM))))
7212         hRet = DISP_E_TYPEMISMATCH;
7213       else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
7214         hRet = DISP_E_TYPEMISMATCH;
7215       st.wHour   = dp.dwValues[0];
7216       st.wMinute = dp.dwValues[1];
7217       st.wSecond = dp.dwValues[2];
7218       dwOffset = 3;
7219       dp.dwCount -= 3;
7220       break;
7221
7222     case 0x4: /* DDTT */
7223       if (dp.dwCount != 4 ||
7224           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7225         hRet = DISP_E_TYPEMISMATCH;
7226
7227       st.wHour = dp.dwValues[2];
7228       st.wMinute  = dp.dwValues[3];
7229       dp.dwCount -= 2;
7230       break;
7231
7232    case 0x0: /* T DD DDD TDDD TDDD */
7233       if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
7234       {
7235         st.wHour = dp.dwValues[0]; /* T */
7236         dp.dwCount = 0;
7237         break;
7238       }
7239       else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
7240       {
7241         hRet = DISP_E_TYPEMISMATCH;
7242       }
7243       else if (dp.dwCount == 3)
7244       {
7245         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
7246         {
7247           dp.dwCount = 2;
7248           st.wHour = dp.dwValues[0];
7249           dwOffset = 1;
7250           break;
7251         }
7252         if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
7253         {
7254           dp.dwCount = 2;
7255           st.wHour = dp.dwValues[2];
7256           break;
7257         }
7258         else if (dp.dwParseFlags & (DP_AM|DP_PM))
7259           hRet = DISP_E_TYPEMISMATCH;
7260       }
7261       else if (dp.dwCount == 4)
7262       {
7263         dp.dwCount = 3;
7264         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
7265         {
7266           st.wHour = dp.dwValues[0];
7267           dwOffset = 1;
7268         }
7269         else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
7270         {
7271           st.wHour = dp.dwValues[3];
7272         }
7273         else
7274           hRet = DISP_E_TYPEMISMATCH;
7275         break;
7276       }
7277       /* .. fall through .. */
7278
7279     case 0x8: /* DDDTT */
7280       if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
7281           (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
7282            (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
7283            dp.dwCount == 4 || dp.dwCount == 6)
7284         hRet = DISP_E_TYPEMISMATCH;
7285       st.wHour   = dp.dwValues[3];
7286       st.wMinute = dp.dwValues[4];
7287       if (dp.dwCount == 5)
7288         dp.dwCount -= 2;
7289       break;
7290
7291     case 0xC: /* DDTTT */
7292       if (dp.dwCount != 5 ||
7293           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7294         hRet = DISP_E_TYPEMISMATCH;
7295       st.wHour   = dp.dwValues[2];
7296       st.wMinute = dp.dwValues[3];
7297       st.wSecond = dp.dwValues[4];
7298       dp.dwCount -= 3;
7299       break;
7300
7301     case 0x18: /* DDDTTT */
7302       if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
7303           (dp.dwFlags[2] & (DP_AM|DP_PM)))
7304         hRet = DISP_E_TYPEMISMATCH;
7305       st.wHour   = dp.dwValues[3];
7306       st.wMinute = dp.dwValues[4];
7307       st.wSecond = dp.dwValues[5];
7308       dp.dwCount -= 3;
7309       break;
7310
7311     default:
7312       hRet = DISP_E_TYPEMISMATCH;
7313       break;
7314     }
7315
7316     if (SUCCEEDED(hRet))
7317     {
7318       hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
7319
7320       if (dwFlags & VAR_TIMEVALUEONLY)
7321       {
7322         st.wYear = 1899;
7323         st.wMonth = 12;
7324         st.wDay = 30;
7325       }
7326       else if (dwFlags & VAR_DATEVALUEONLY)
7327        st.wHour = st.wMinute = st.wSecond = 0;
7328
7329       /* Finally, convert the value to a VT_DATE */
7330       if (SUCCEEDED(hRet))
7331         hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
7332     }
7333   }
7334
7335   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7336     SysFreeString(tokens[i]);
7337   return hRet;
7338 }
7339
7340 /******************************************************************************
7341  * VarDateFromI1 (OLEAUT32.221)
7342  *
7343  * Convert a VT_I1 to a VT_DATE.
7344  *
7345  * PARAMS
7346  *  cIn      [I] Source
7347  *  pdateOut [O] Destination
7348  *
7349  * RETURNS
7350  *  S_OK.
7351  */
7352 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
7353 {
7354   return VarR8FromI1(cIn, pdateOut);
7355 }
7356
7357 /******************************************************************************
7358  * VarDateFromUI2 (OLEAUT32.222)
7359  *
7360  * Convert a VT_UI2 to a VT_DATE.
7361  *
7362  * PARAMS
7363  *  uiIn     [I] Source
7364  *  pdateOut [O] Destination
7365  *
7366  * RETURNS
7367  *  S_OK.
7368  */
7369 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
7370 {
7371   return VarR8FromUI2(uiIn, pdateOut);
7372 }
7373
7374 /******************************************************************************
7375  * VarDateFromUI4 (OLEAUT32.223)
7376  *
7377  * Convert a VT_UI4 to a VT_DATE.
7378  *
7379  * PARAMS
7380  *  ulIn     [I] Source
7381  *  pdateOut [O] Destination
7382  *
7383  * RETURNS
7384  *  S_OK.
7385  */
7386 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
7387 {
7388   return VarDateFromR8(ulIn, pdateOut);
7389 }
7390
7391 /**********************************************************************
7392  * VarDateFromDec (OLEAUT32.224)
7393  *
7394  * Convert a VT_DECIMAL to a VT_DATE.
7395  *
7396  * PARAMS
7397  *  pdecIn   [I] Source
7398  *  pdateOut [O] Destination
7399  *
7400  * RETURNS
7401  *  S_OK.
7402  */
7403 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
7404 {
7405   return VarR8FromDec(pdecIn, pdateOut);
7406 }
7407
7408 /******************************************************************************
7409  * VarDateFromI8 (OLEAUT32.364)
7410  *
7411  * Convert a VT_I8 to a VT_DATE.
7412  *
7413  * PARAMS
7414  *  llIn     [I] Source
7415  *  pdateOut [O] Destination
7416  *
7417  * RETURNS
7418  *  Success: S_OK.
7419  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
7420  */
7421 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
7422 {
7423   if (llIn < DATE_MIN || llIn > DATE_MAX) return DISP_E_OVERFLOW;
7424   *pdateOut = (DATE)llIn;
7425   return S_OK;
7426 }
7427
7428 /******************************************************************************
7429  * VarDateFromUI8 (OLEAUT32.365)
7430  *
7431  * Convert a VT_UI8 to a VT_DATE.
7432  *
7433  * PARAMS
7434  *  ullIn    [I] Source
7435  *  pdateOut [O] Destination
7436  *
7437  * RETURNS
7438  *  Success: S_OK.
7439  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
7440  */
7441 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
7442 {
7443   if (ullIn > DATE_MAX) return DISP_E_OVERFLOW;
7444   *pdateOut = (DATE)ullIn;
7445   return S_OK;
7446 }