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