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