Commented out tests that assume that the current year is 2003.
[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 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
3740 {
3741   pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3742   pCyOut->int64 *= CY_MULTIPLIER;
3743   return S_OK;
3744 }
3745
3746 /************************************************************************
3747  * VarCyInt (OLEAUT32.308)
3748  *
3749  * Return the integer part of a VT_CY.
3750  *
3751  * PARAMS
3752  *  cyIn   [I] Source
3753  *  pCyOut [O] Destination
3754  *
3755  * RETURNS
3756  *  Success: S_OK.
3757  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3758  */
3759 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
3760 {
3761   double d;
3762
3763   _VarR8FromCy(cyIn, &d);
3764   d = floor(d) * CY_MULTIPLIER_F;
3765   OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64);
3766   return S_OK;
3767 }
3768
3769 /************************************************************************
3770  * VarCyNeg (OLEAUT32.309)
3771  *
3772  * Change the sign of a VT_CY.
3773  *
3774  * PARAMS
3775  *  cyIn   [I] Source
3776  *  pCyOut [O] Destination
3777  *
3778  * RETURNS
3779  *  Success: S_OK.
3780  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3781  */
3782 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
3783 {
3784   if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3785     return DISP_E_OVERFLOW;
3786
3787   pCyOut->int64 = -cyIn.int64;
3788   return S_OK;
3789 }
3790
3791 /************************************************************************
3792  * VarCyRound (OLEAUT32.310)
3793  *
3794  * Change the precision of a VT_CY.
3795  *
3796  * PARAMS
3797  *  cyIn      [I] Source
3798  *  cDecimals [I] New number of decimals to keep
3799  *  pCyOut    [O] Destination
3800  *
3801  * RETURNS
3802  *  Success: S_OK.
3803  *  Failure: E_INVALIDARG, if cDecimals is less than 0.
3804  */
3805 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
3806 {
3807   if (cDecimals < 0)
3808     return E_INVALIDARG;
3809
3810   if (cDecimals > 3)
3811   {
3812     /* Rounding to more precision than we have */
3813     *pCyOut = cyIn;
3814     return S_OK;
3815   }
3816   else
3817   {
3818     double d, div = CY_Divisors[cDecimals];
3819
3820     _VarR8FromCy(cyIn, &d);
3821     d = d * div;
3822     OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3823     d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3824     OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3825     return S_OK;
3826   }
3827 }
3828
3829 /************************************************************************
3830  * VarCyCmp (OLEAUT32.311)
3831  *
3832  * Compare two VT_CY values.
3833  *
3834  * PARAMS
3835  *  cyLeft  [I] Source
3836  *  cyRight [I] Value to compare
3837  *
3838  * RETURNS
3839  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
3840  *           compare is less, equal or greater than source respectively.
3841  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3842  */
3843 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
3844 {
3845   HRESULT hRet;
3846   CY result;
3847
3848   /* Subtract right from left, and compare the result to 0 */
3849   hRet = VarCySub(cyLeft, cyRight, &result);
3850
3851   if (SUCCEEDED(hRet))
3852   {
3853     if (result.int64 < 0)
3854       hRet = (HRESULT)VARCMP_LT;
3855     else if (result.int64 > 0)
3856       hRet = (HRESULT)VARCMP_GT;
3857     else
3858       hRet = (HRESULT)VARCMP_EQ;
3859   }
3860   return hRet;
3861 }
3862
3863 /************************************************************************
3864  * VarCyCmpR8 (OLEAUT32.312)
3865  *
3866  * Compare a VT_CY to a double
3867  *
3868  * PARAMS
3869  *  cyLeft   [I] Currency Source
3870  *  dblRight [I] double to compare to cyLeft
3871  *
3872  * RETURNS
3873  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
3874  *           less than, equal to or greater than cyLeft respectively.
3875  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3876  */
3877 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
3878 {
3879   HRESULT hRet;
3880   CY cyRight;
3881
3882   hRet = _VarCyFromR8(dblRight, &cyRight);
3883
3884   if (SUCCEEDED(hRet))
3885     hRet = VarCyCmp(cyLeft, cyRight);
3886
3887   return hRet;
3888 }
3889
3890 /************************************************************************
3891  * VarCyMulI8 (OLEAUT32.329)
3892  *
3893  * Multiply a VT_CY by a VT_I8.
3894  *
3895  * PARAMS
3896  *  cyLeft  [I] Source
3897  *  llRight [I] Value to multiply by
3898  *  pCyOut  [O] Destination
3899  *
3900  * RETURNS
3901  *  Success: S_OK.
3902  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3903  */
3904 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
3905 {
3906   double d;
3907
3908   _VarR8FromCy(cyLeft, &d);
3909   d = d  * (double)llRight;
3910   return _VarCyFromR8(d, pCyOut);
3911 }
3912
3913 /* DECIMAL
3914  */
3915
3916 /************************************************************************
3917  * VarDecFromUI1 (OLEAUT32.190)
3918  *
3919  * Convert a VT_UI1 to a DECIMAL.
3920  *
3921  * PARAMS
3922  *  bIn     [I] Source
3923  *  pDecOut [O] Destination
3924  *
3925  * RETURNS
3926  *  S_OK.
3927  */
3928 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
3929 {
3930   return _VarDecFromUI1(bIn, pDecOut);
3931 }
3932
3933 /************************************************************************
3934  * VarDecFromI2 (OLEAUT32.191)
3935  *
3936  * Convert a VT_I2 to a DECIMAL.
3937  *
3938  * PARAMS
3939  *  sIn     [I] Source
3940  *  pDecOut [O] Destination
3941  *
3942  * RETURNS
3943  *  S_OK.
3944  */
3945 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
3946 {
3947   return _VarDecFromI2(sIn, pDecOut);
3948 }
3949
3950 /************************************************************************
3951  * VarDecFromI4 (OLEAUT32.192)
3952  *
3953  * Convert a VT_I4 to a DECIMAL.
3954  *
3955  * PARAMS
3956  *  sIn     [I] Source
3957  *  pDecOut [O] Destination
3958  *
3959  * RETURNS
3960  *  S_OK.
3961  */
3962 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
3963 {
3964   DEC_HI32(pDecOut) = 0;
3965   DEC_MID32(pDecOut) = 0;
3966
3967   if (lIn < 0)
3968   {
3969     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
3970     DEC_LO32(pDecOut) = -lIn;
3971   }
3972   else
3973   {
3974     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
3975     DEC_LO32(pDecOut) = lIn;
3976   }
3977   return S_OK;
3978 }
3979
3980 /************************************************************************
3981  * VarDecFromR4 (OLEAUT32.193)
3982  *
3983  * Convert a VT_R4 to a DECIMAL.
3984  *
3985  * PARAMS
3986  *  fltIn   [I] Source
3987  *  pDecOut [O] Destination
3988  *
3989  * RETURNS
3990  *  S_OK.
3991  */
3992 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
3993 {
3994   WCHAR buff[256];
3995
3996   sprintfW( buff, szFloatFormatW, fltIn );
3997   return _VarDecFromStr(buff, LOCALE_SYSTEM_DEFAULT, 0, pDecOut);
3998 }
3999
4000 /************************************************************************
4001  * VarDecFromR8 (OLEAUT32.194)
4002  *
4003  * Convert a VT_R8 to a DECIMAL.
4004  *
4005  * PARAMS
4006  *  dblIn   [I] Source
4007  *  pDecOut [O] Destination
4008  *
4009  * RETURNS
4010  *  S_OK.
4011  */
4012 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4013 {
4014   WCHAR buff[256];
4015
4016   sprintfW( buff, szDoubleFormatW, dblIn );
4017   return _VarDecFromStr(buff, LOCALE_USER_DEFAULT, 0, pDecOut);
4018 }
4019
4020 /************************************************************************
4021  * VarDecFromDate (OLEAUT32.195)
4022  *
4023  * Convert a VT_DATE to a DECIMAL.
4024  *
4025  * PARAMS
4026  *  dateIn  [I] Source
4027  *  pDecOut [O] Destination
4028  *
4029  * RETURNS
4030  *  S_OK.
4031  */
4032 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
4033 {
4034   return _VarDecFromDate(dateIn, pDecOut);
4035 }
4036
4037 /************************************************************************
4038  * VarDecFromCy (OLEAUT32.196)
4039  *
4040  * Convert a VT_CY to a DECIMAL.
4041  *
4042  * PARAMS
4043  *  cyIn    [I] Source
4044  *  pDecOut [O] Destination
4045  *
4046  * RETURNS
4047  *  S_OK.
4048  */
4049 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
4050 {
4051   DEC_HI32(pDecOut) = 0;
4052
4053   /* Note: This assumes 2s complement integer representation */
4054   if (cyIn.s.Hi & 0x80000000)
4055   {
4056     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4057     DEC_LO64(pDecOut) = -cyIn.int64;
4058   }
4059   else
4060   {
4061     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4062     DEC_MID32(pDecOut) = cyIn.s.Hi;
4063     DEC_LO32(pDecOut) = cyIn.s.Lo;
4064   }
4065   return S_OK;
4066 }
4067
4068 /************************************************************************
4069  * VarDecFromStr (OLEAUT32.197)
4070  *
4071  * Convert a VT_BSTR to a DECIMAL.
4072  *
4073  * PARAMS
4074  *  strIn   [I] Source
4075  *  lcid    [I] LCID for the conversion
4076  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4077  *  pDecOut [O] Destination
4078  *
4079  * RETURNS
4080  *  Success: S_OK.
4081  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4082  */
4083 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
4084 {
4085   return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
4086 }
4087
4088 /************************************************************************
4089  * VarDecFromDisp (OLEAUT32.198)
4090  *
4091  * Convert a VT_DISPATCH to a DECIMAL.
4092  *
4093  * PARAMS
4094  *  pdispIn  [I] Source
4095  *  lcid     [I] LCID for conversion
4096  *  pDecOut  [O] Destination
4097  *
4098  * RETURNS
4099  *  Success: S_OK.
4100  *  Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4101  */
4102 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
4103 {
4104   return _VarDecFromDisp(pdispIn, lcid, pDecOut);
4105 }
4106
4107 /************************************************************************
4108  * VarDecFromBool (OLEAUT32.199)
4109  *
4110  * Convert a VT_BOOL to a DECIMAL.
4111  *
4112  * PARAMS
4113  *  bIn     [I] Source
4114  *  pDecOut [O] Destination
4115  *
4116  * RETURNS
4117  *  S_OK.
4118  *
4119  * NOTES
4120  *  The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4121  */
4122 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
4123 {
4124   DEC_HI32(pDecOut) = 0;
4125   DEC_MID32(pDecOut) = 0;
4126   if (bIn)
4127   {
4128     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4129     DEC_LO32(pDecOut) = 1;
4130   }
4131   else
4132   {
4133     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4134     DEC_LO32(pDecOut) = 0;
4135   }
4136   return S_OK;
4137 }
4138
4139 /************************************************************************
4140  * VarDecFromI1 (OLEAUT32.241)
4141  *
4142  * Convert a VT_I1 to a DECIMAL.
4143  *
4144  * PARAMS
4145  *  cIn     [I] Source
4146  *  pDecOut [O] Destination
4147  *
4148  * RETURNS
4149  *  S_OK.
4150  */
4151 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4152 {
4153   return _VarDecFromI1(cIn, pDecOut);
4154 }
4155
4156 /************************************************************************
4157  * VarDecFromUI2 (OLEAUT32.242)
4158  *
4159  * Convert a VT_UI2 to a DECIMAL.
4160  *
4161  * PARAMS
4162  *  usIn    [I] Source
4163  *  pDecOut [O] Destination
4164  *
4165  * RETURNS
4166  *  S_OK.
4167  */
4168 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
4169 {
4170   return _VarDecFromUI2(usIn, pDecOut);
4171 }
4172
4173 /************************************************************************
4174  * VarDecFromUI4 (OLEAUT32.243)
4175  *
4176  * Convert a VT_UI4 to a DECIMAL.
4177  *
4178  * PARAMS
4179  *  ulIn    [I] Source
4180  *  pDecOut [O] Destination
4181  *
4182  * RETURNS
4183  *  S_OK.
4184  */
4185 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
4186 {
4187   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4188   DEC_HI32(pDecOut) = 0;
4189   DEC_MID32(pDecOut) = 0;
4190   DEC_LO32(pDecOut) = ulIn;
4191   return S_OK;
4192 }
4193
4194 /************************************************************************
4195  * VarDecFromI8 (OLEAUT32.374)
4196  *
4197  * Convert a VT_I8 to a DECIMAL.
4198  *
4199  * PARAMS
4200  *  llIn    [I] Source
4201  *  pDecOut [O] Destination
4202  *
4203  * RETURNS
4204  *  S_OK.
4205  */
4206 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
4207 {
4208   PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4209
4210   DEC_HI32(pDecOut) = 0;
4211
4212   /* Note: This assumes 2s complement integer representation */
4213   if (pLi->s.HighPart & 0x80000000)
4214   {
4215     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4216     DEC_LO64(pDecOut) = -pLi->QuadPart;
4217   }
4218   else
4219   {
4220     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4221     DEC_MID32(pDecOut) = pLi->s.HighPart;
4222     DEC_LO32(pDecOut) = pLi->s.LowPart;
4223   }
4224   return S_OK;
4225 }
4226
4227 /************************************************************************
4228  * VarDecFromUI8 (OLEAUT32.375)
4229  *
4230  * Convert a VT_UI8 to a DECIMAL.
4231  *
4232  * PARAMS
4233  *  ullIn   [I] Source
4234  *  pDecOut [O] Destination
4235  *
4236  * RETURNS
4237  *  S_OK.
4238  */
4239 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
4240 {
4241   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4242   DEC_HI32(pDecOut) = 0;
4243   DEC_LO64(pDecOut) = ullIn;
4244   return S_OK;
4245 }
4246
4247 /* Make two DECIMALS the same scale; used by math functions below */
4248 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4249                                 const DECIMAL** ppDecRight,
4250                                 DECIMAL* pDecOut)
4251 {
4252   static DECIMAL scaleFactor;
4253   DECIMAL decTemp;
4254   int scaleAmount, i;
4255   HRESULT hRet = S_OK;
4256
4257   if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4258     return E_INVALIDARG;
4259
4260   DEC_LO32(&scaleFactor) = 10;
4261
4262   i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4263
4264   if (!scaleAmount)
4265     return S_OK; /* Same scale */
4266
4267   if (scaleAmount > 0)
4268   {
4269     decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4270     *ppDecRight = pDecOut;
4271   }
4272   else
4273   {
4274     decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4275     *ppDecLeft = pDecOut;
4276     i = scaleAmount = -scaleAmount;
4277   }
4278
4279   if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
4280     return DISP_E_OVERFLOW; /* Can't scale up */
4281
4282   /* Multiply up the value to be scaled by the correct amount */
4283   while (SUCCEEDED(hRet) && i--)
4284   {
4285     /* Note we are multiplying by a value with a scale of 0, so we dont recurse */
4286     hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
4287     decTemp = *pDecOut;
4288   }
4289   DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
4290   return hRet;
4291 }
4292
4293 /* Add two unsigned 32 bit values with overflow */
4294 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4295 {
4296   ULARGE_INTEGER ul64;
4297
4298   ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4299   *pulHigh = ul64.s.HighPart;
4300   return ul64.s.LowPart;
4301 }
4302
4303 /* Subtract two unsigned 32 bit values with underflow */
4304 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4305 {
4306   int invert = 0;
4307   ULARGE_INTEGER ul64;
4308
4309   ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4310   if (ulLeft < ulRight)
4311     invert = 1;
4312
4313   if (ul64.QuadPart > (ULONG64)*pulHigh)
4314     ul64.QuadPart -= (ULONG64)*pulHigh;
4315   else
4316   {
4317     ul64.QuadPart -= (ULONG64)*pulHigh;
4318     invert = 1;
4319   }
4320   if (invert)
4321     ul64.s.HighPart = -ul64.s.HighPart ;
4322
4323   *pulHigh = ul64.s.HighPart;
4324   return ul64.s.LowPart;
4325 }
4326
4327 /* Multiply two unsigned 32 bit values with overflow */
4328 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4329 {
4330   ULARGE_INTEGER ul64;
4331
4332   ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4333   *pulHigh = ul64.s.HighPart;
4334   return ul64.s.LowPart;
4335 }
4336
4337 /* Compare two decimals that have the same scale */
4338 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4339 {
4340   if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4341       (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4342     return -1;
4343   else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4344     return 0;
4345   return 1;
4346 }
4347
4348 /************************************************************************
4349  * VarDecAdd (OLEAUT32.177)
4350  *
4351  * Add one DECIMAL to another.
4352  *
4353  * PARAMS
4354  *  pDecLeft  [I] Source
4355  *  pDecRight [I] Value to add
4356  *  pDecOut   [O] Destination
4357  *
4358  * RETURNS
4359  *  Success: S_OK.
4360  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4361  */
4362 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4363 {
4364   HRESULT hRet;
4365   DECIMAL scaled;
4366
4367   hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
4368
4369   if (SUCCEEDED(hRet))
4370   {
4371     /* Our decimals now have the same scale, we can add them as 96 bit integers */
4372     ULONG overflow = 0;
4373     BYTE sign = DECIMAL_POS;
4374
4375     /* Correct for the sign of the result */
4376     if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4377     {
4378       /* -x + -y : Negative */
4379       sign = DECIMAL_NEG;
4380       goto VarDecAdd_AsPositive;
4381     }
4382     else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4383     {
4384       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4385
4386       /* -x + y : Negative if x > y */
4387       if (cmp > 0)
4388       {
4389         sign = DECIMAL_NEG;
4390 VarDecAdd_AsNegative:
4391         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
4392         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4393         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
4394       }
4395       else
4396       {
4397 VarDecAdd_AsInvertedNegative:
4398         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecRight),  DEC_LO32(pDecLeft),  &overflow);
4399         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4400         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecRight),  DEC_HI32(pDecLeft),  &overflow);
4401       }
4402     }
4403     else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4404     {
4405       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4406
4407       /* x + -y : Negative if x <= y */
4408       if (cmp <= 0)
4409       {
4410         sign = DECIMAL_NEG;
4411         goto VarDecAdd_AsInvertedNegative;
4412       }
4413       goto VarDecAdd_AsNegative;
4414     }
4415     else
4416     {
4417       /* x + y : Positive */
4418 VarDecAdd_AsPositive:
4419       DEC_LO32(pDecOut)  = VARIANT_Add(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
4420       DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4421       DEC_HI32(pDecOut)  = VARIANT_Add(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
4422     }
4423
4424     if (overflow)
4425       return DISP_E_OVERFLOW; /* overflowed */
4426
4427     DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4428     DEC_SIGN(pDecOut) = sign;
4429   }
4430   return hRet;
4431 }
4432
4433 /************************************************************************
4434  * VarDecDiv (OLEAUT32.178)
4435  *
4436  * Divide one DECIMAL by another.
4437  *
4438  * PARAMS
4439  *  pDecLeft  [I] Source
4440  *  pDecRight [I] Value to divide by
4441  *  pDecOut   [O] Destination
4442  *
4443  * RETURNS
4444  *  Success: S_OK.
4445  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4446  */
4447 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4448 {
4449   FIXME("(%p,%p,%p)-stub!\n",pDecLeft,pDecRight,pDecOut);
4450   return DISP_E_OVERFLOW;
4451 }
4452
4453 /************************************************************************
4454  * VarDecMul (OLEAUT32.179)
4455  *
4456  * Multiply one DECIMAL by another.
4457  *
4458  * PARAMS
4459  *  pDecLeft  [I] Source
4460  *  pDecRight [I] Value to multiply by
4461  *  pDecOut   [O] Destination
4462  *
4463  * RETURNS
4464  *  Success: S_OK.
4465  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4466  */
4467 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4468 {
4469   /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4470
4471   if (!DEC_SCALE(pDecLeft) || !DEC_SCALE(pDecRight))
4472   {
4473     /* At least one term is an integer */
4474     const DECIMAL* pDecInteger = DEC_SCALE(pDecLeft) ? pDecRight : pDecLeft;
4475     const DECIMAL* pDecOperand = DEC_SCALE(pDecLeft) ? pDecLeft  : pDecRight;
4476     HRESULT hRet = S_OK;
4477     unsigned int multiplier = DEC_LO32(pDecInteger);
4478     ULONG overflow = 0;
4479
4480     if (DEC_HI32(pDecInteger) || DEC_MID32(pDecInteger))
4481     {
4482       FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4483       return DISP_E_OVERFLOW;
4484     }
4485
4486     DEC_LO32(pDecOut)  = VARIANT_Mul(DEC_LO32(pDecOperand),  multiplier, &overflow);
4487     DEC_MID32(pDecOut) = VARIANT_Mul(DEC_MID32(pDecOperand), multiplier, &overflow);
4488     DEC_HI32(pDecOut)  = VARIANT_Mul(DEC_HI32(pDecOperand),  multiplier, &overflow);
4489
4490     if (overflow)
4491        hRet = DISP_E_OVERFLOW;
4492     else
4493     {
4494       BYTE sign = DECIMAL_POS;
4495
4496       if (DEC_SIGN(pDecLeft) != DEC_SIGN(pDecRight))
4497         sign = DECIMAL_NEG; /* pos * neg => negative */
4498       DEC_SIGN(pDecOut) = sign;
4499       DEC_SCALE(pDecOut) = DEC_SCALE(pDecOperand);
4500     }
4501     return hRet;
4502   }
4503   FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4504   return DISP_E_OVERFLOW;
4505 }
4506
4507 /************************************************************************
4508  * VarDecSub (OLEAUT32.181)
4509  *
4510  * Subtract one DECIMAL from another.
4511  *
4512  * PARAMS
4513  *  pDecLeft  [I] Source
4514  *  pDecRight [I] DECIMAL to subtract from pDecLeft
4515  *  pDecOut   [O] Destination
4516  *
4517  * RETURNS
4518  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4519  */
4520 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4521 {
4522   DECIMAL decRight;
4523
4524   /* Implement as addition of the negative */
4525   VarDecNeg(pDecRight, &decRight);
4526   return VarDecAdd(pDecLeft, &decRight, pDecOut);
4527 }
4528
4529 /************************************************************************
4530  * VarDecAbs (OLEAUT32.182)
4531  *
4532  * Convert a DECIMAL into its absolute value.
4533  *
4534  * PARAMS
4535  *  pDecIn  [I] Source
4536  *  pDecOut [O] Destination
4537  *
4538  * RETURNS
4539  *  S_OK. This function does not fail.
4540  */
4541 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4542 {
4543   *pDecOut = *pDecIn;
4544   DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
4545   return S_OK;
4546 }
4547
4548 /************************************************************************
4549  * VarDecFix (OLEAUT32.187)
4550  *
4551  * Return the integer portion of a DECIMAL.
4552  *
4553  * PARAMS
4554  *  pDecIn  [I] Source
4555  *  pDecOut [O] Destination
4556  *
4557  * RETURNS
4558  *  Success: S_OK.
4559  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4560  */
4561 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4562 {
4563   if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
4564     return E_INVALIDARG;
4565
4566   if (!DEC_SCALE(pDecIn))
4567   {
4568     *pDecOut = *pDecIn; /* Already an integer */
4569     return S_OK;
4570   }
4571
4572   FIXME("semi-stub!\n");
4573   return DISP_E_OVERFLOW;
4574 }
4575
4576 /************************************************************************
4577  * VarDecInt (OLEAUT32.188)
4578  *
4579  * Return the integer portion of a DECIMAL.
4580  *
4581  * PARAMS
4582  *  pDecIn  [I] Source
4583  *  pDecOut [O] Destination
4584  *
4585  * RETURNS
4586  *  Success: S_OK.
4587  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4588  */
4589 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4590 {
4591   if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
4592     return E_INVALIDARG;
4593
4594   if (!DEC_SCALE(pDecIn))
4595   {
4596     *pDecOut = *pDecIn; /* Already an integer */
4597     return S_OK;
4598   }
4599
4600   FIXME("semi-stub!\n");
4601   return DISP_E_OVERFLOW;
4602 }
4603
4604 /************************************************************************
4605  * VarDecNeg (OLEAUT32.189)
4606  *
4607  * Change the sign of a DECIMAL.
4608  *
4609  * PARAMS
4610  *  pDecIn  [I] Source
4611  *  pDecOut [O] Destination
4612  *
4613  * RETURNS
4614  *  S_OK. This function does not fail.
4615  */
4616 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4617 {
4618   *pDecOut = *pDecIn;
4619   DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
4620   return S_OK;
4621 }
4622
4623 /************************************************************************
4624  * VarDecRound (OLEAUT32.203)
4625  *
4626  * Change the precision of a DECIMAL.
4627  *
4628  * PARAMS
4629  *  pDecIn    [I] Source
4630  *  cDecimals [I] New number of decimals to keep
4631  *  pDecOut   [O] Destination
4632  *
4633  * RETURNS
4634  *  Success: S_OK. pDecOut contains the rounded value.
4635  *  Failure: E_INVALIDARG if any argument is invalid.
4636  */
4637 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
4638 {
4639   if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
4640     return E_INVALIDARG;
4641
4642   if (cDecimals >= DEC_SCALE(pDecIn))
4643   {
4644     *pDecOut = *pDecIn; /* More precision than we have */
4645     return S_OK;
4646   }
4647
4648   FIXME("semi-stub!\n");
4649
4650   return DISP_E_OVERFLOW;
4651 }
4652
4653 /************************************************************************
4654  * VarDecCmp (OLEAUT32.204)
4655  *
4656  * Compare two DECIMAL values.
4657  *
4658  * PARAMS
4659  *  pDecLeft  [I] Source
4660  *  pDecRight [I] Value to compare
4661  *
4662  * RETURNS
4663  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4664  *           is less than, equal to or greater than pDecRight respectively.
4665  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4666  */
4667 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
4668 {
4669   HRESULT hRet;
4670   DECIMAL result;
4671
4672   /* Subtract right from left, and compare the result to 0 */
4673   hRet = VarDecSub(pDecLeft, pDecRight, &result);
4674
4675   if (SUCCEEDED(hRet))
4676   {
4677     int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
4678
4679     if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
4680       hRet = (HRESULT)VARCMP_LT;
4681     else if (non_zero)
4682       hRet = (HRESULT)VARCMP_GT;
4683     else
4684       hRet = (HRESULT)VARCMP_EQ;
4685   }
4686   return hRet;
4687 }
4688
4689 /************************************************************************
4690  * VarDecCmpR8 (OLEAUT32.298)
4691  *
4692  * Compare a DECIMAL to a double
4693  *
4694  * PARAMS
4695  *  pDecLeft [I] DECIMAL Source
4696  *  dblRight [I] double to compare to pDecLeft
4697  *
4698  * RETURNS
4699  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4700  *           is less than, equal to or greater than pDecLeft respectively.
4701  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4702  */
4703 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
4704 {
4705   HRESULT hRet;
4706   DECIMAL decRight;
4707
4708   hRet = VarDecFromR8(dblRight, &decRight);
4709
4710   if (SUCCEEDED(hRet))
4711     hRet = VarDecCmp(pDecLeft, &decRight);
4712
4713   return hRet;
4714 }
4715
4716 /* BOOL
4717  */
4718
4719 /************************************************************************
4720  * VarBoolFromUI1 (OLEAUT32.118)
4721  *
4722  * Convert a VT_UI1 to a VT_BOOL.
4723  *
4724  * PARAMS
4725  *  bIn      [I] Source
4726  *  pBoolOut [O] Destination
4727  *
4728  * RETURNS
4729  *  S_OK.
4730  */
4731 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
4732 {
4733   return _VarBoolFromUI1(bIn, pBoolOut);
4734 }
4735
4736 /************************************************************************
4737  * VarBoolFromI2 (OLEAUT32.119)
4738  *
4739  * Convert a VT_I2 to a VT_BOOL.
4740  *
4741  * PARAMS
4742  *  sIn      [I] Source
4743  *  pBoolOut [O] Destination
4744  *
4745  * RETURNS
4746  *  S_OK.
4747  */
4748 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
4749 {
4750   return _VarBoolFromI2(sIn, pBoolOut);
4751 }
4752
4753 /************************************************************************
4754  * VarBoolFromI4 (OLEAUT32.120)
4755  *
4756  * Convert a VT_I4 to a VT_BOOL.
4757  *
4758  * PARAMS
4759  *  sIn      [I] Source
4760  *  pBoolOut [O] Destination
4761  *
4762  * RETURNS
4763  *  S_OK.
4764  */
4765 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
4766 {
4767   return _VarBoolFromI4(lIn, pBoolOut);
4768 }
4769
4770 /************************************************************************
4771  * VarBoolFromR4 (OLEAUT32.121)
4772  *
4773  * Convert a VT_R4 to a VT_BOOL.
4774  *
4775  * PARAMS
4776  *  fltIn    [I] Source
4777  *  pBoolOut [O] Destination
4778  *
4779  * RETURNS
4780  *  S_OK.
4781  */
4782 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
4783 {
4784   return _VarBoolFromR4(fltIn, pBoolOut);
4785 }
4786
4787 /************************************************************************
4788  * VarBoolFromR8 (OLEAUT32.122)
4789  *
4790  * Convert a VT_R8 to a VT_BOOL.
4791  *
4792  * PARAMS
4793  *  dblIn    [I] Source
4794  *  pBoolOut [O] Destination
4795  *
4796  * RETURNS
4797  *  S_OK.
4798  */
4799 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
4800 {
4801   return _VarBoolFromR8(dblIn, pBoolOut);
4802 }
4803
4804 /************************************************************************
4805  * VarBoolFromDate (OLEAUT32.123)
4806  *
4807  * Convert a VT_DATE to a VT_BOOL.
4808  *
4809  * PARAMS
4810  *  dateIn   [I] Source
4811  *  pBoolOut [O] Destination
4812  *
4813  * RETURNS
4814  *  S_OK.
4815  */
4816 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
4817 {
4818   return _VarBoolFromDate(dateIn, pBoolOut);
4819 }
4820
4821 /************************************************************************
4822  * VarBoolFromCy (OLEAUT32.124)
4823  *
4824  * Convert a VT_CY to a VT_BOOL.
4825  *
4826  * PARAMS
4827  *  cyIn     [I] Source
4828  *  pBoolOut [O] Destination
4829  *
4830  * RETURNS
4831  *  S_OK.
4832  */
4833 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
4834 {
4835   return _VarBoolFromCy(cyIn, pBoolOut);
4836 }
4837
4838 static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
4839 {
4840   HRSRC hrsrc;
4841
4842   hrsrc = FindResourceExW( OLEAUT32_hModule, (LPWSTR)RT_STRING,
4843                            (LPCWSTR)((dwId >> 4) + 1), langId );
4844   if (hrsrc)
4845   {
4846     HGLOBAL hmem = LoadResource( OLEAUT32_hModule, hrsrc );
4847
4848     if (hmem)
4849     {
4850       const WCHAR *p;
4851       unsigned int i;
4852
4853       p = LockResource( hmem );
4854       for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
4855
4856       memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
4857       lpszDest[*p] = '\0';
4858       TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
4859       return TRUE;
4860     }
4861   }
4862   return FALSE;
4863 }
4864
4865 /************************************************************************
4866  * VarBoolFromStr (OLEAUT32.125)
4867  *
4868  * Convert a VT_BSTR to a VT_BOOL.
4869  *
4870  * PARAMS
4871  *  strIn    [I] Source
4872  *  lcid     [I] LCID for the conversion
4873  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4874  *  pBoolOut [O] Destination
4875  *
4876  * RETURNS
4877  *  Success: S_OK.
4878  *  Failure: E_INVALIDARG, if pBoolOut is invalid.
4879  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
4880  *
4881  * NOTES
4882  *  - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
4883  *  it may contain (in any case mapping) the text "true" or "false".
4884  *  - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
4885  *  localised text of "True" or "False" in the language specified by lcid.
4886  *  - If none of these matches occur, the string is treated as a numeric string
4887  *  and the boolean pBoolOut will be set according to whether the number is zero
4888  *  or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
4889  *  - If the text is not numeric and does not match any of the above, then
4890  *  DISP_E_TYPEMISMATCH is returned.
4891  */
4892 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
4893 {
4894   /* Any VB/VBA programmers out there should recognise these strings... */
4895   static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
4896   static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
4897   WCHAR szBuff[64];
4898   LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4899   HRESULT hRes = S_OK;
4900
4901   if (!strIn || !pBoolOut)
4902     return DISP_E_TYPEMISMATCH;
4903
4904   /* Check if we should be comparing against localised text */
4905   if (dwFlags & VAR_LOCALBOOL)
4906   {
4907     /* Convert our LCID into a usable value */
4908     lcid = ConvertDefaultLocale(lcid);
4909
4910     langId = LANGIDFROMLCID(lcid);
4911
4912     if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
4913       langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4914
4915     /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
4916      * I don't think this is needed unless any of the localised text strings
4917      * contain characters that can be so mapped. In the event that this is
4918      * true for a given language (possibly some Asian languages), then strIn
4919      * should be mapped here _only_ if langId is an Id for which this can occur.
4920      */
4921   }
4922
4923   /* Note that if we are not comparing against localised strings, langId
4924    * will have its default value of LANG_ENGLISH. This allows us to mimic
4925    * the native behaviour of always checking against English strings even
4926    * after we've checked for localised ones.
4927    */
4928 VarBoolFromStr_CheckLocalised:
4929   if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
4930   {
4931     /* Compare against localised strings, ignoring case */
4932     if (!strcmpiW(strIn, szBuff))
4933     {
4934       *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
4935       return hRes;
4936     }
4937     VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
4938     if (!strcmpiW(strIn, szBuff))
4939     {
4940       *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
4941       return hRes;
4942     }
4943   }
4944
4945   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
4946   {
4947     /* We have checked the localised text, now check English */
4948     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4949     goto VarBoolFromStr_CheckLocalised;
4950   }
4951
4952   /* All checks against localised text have failed, try #TRUE#/#FALSE# */
4953   if (!strcmpW(strIn, szFalse))
4954     *pBoolOut = VARIANT_FALSE;
4955   else if (!strcmpW(strIn, szTrue))
4956     *pBoolOut = VARIANT_TRUE;
4957   else
4958   {
4959     double d;
4960
4961     /* If this string is a number, convert it as one */
4962     hRes = _VarR8FromStr(strIn, lcid, dwFlags, &d);
4963     if (SUCCEEDED(hRes))
4964       hRes = _VarBoolFromR8(d, pBoolOut);
4965   }
4966   return hRes;
4967 }
4968
4969 /************************************************************************
4970  * VarBoolFromDisp (OLEAUT32.126)
4971  *
4972  * Convert a VT_DISPATCH to a VT_BOOL.
4973  *
4974  * PARAMS
4975  *  pdispIn   [I] Source
4976  *  lcid      [I] LCID for conversion
4977  *  pBoolOut  [O] Destination
4978  *
4979  * RETURNS
4980  *  Success: S_OK.
4981  *  Failure: E_INVALIDARG, if the source value is invalid
4982  *           DISP_E_OVERFLOW, if the value will not fit in the destination
4983  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
4984  */
4985 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
4986 {
4987   return _VarBoolFromDisp(pdispIn, lcid, pBoolOut);
4988 }
4989
4990 /************************************************************************
4991  * VarBoolFromI1 (OLEAUT32.233)
4992  *
4993  * Convert a VT_I1 to a VT_BOOL.
4994  *
4995  * PARAMS
4996  *  cIn      [I] Source
4997  *  pBoolOut [O] Destination
4998  *
4999  * RETURNS
5000  *  S_OK.
5001  */
5002 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
5003 {
5004   return _VarBoolFromI1(cIn, pBoolOut);
5005 }
5006
5007 /************************************************************************
5008  * VarBoolFromUI2 (OLEAUT32.234)
5009  *
5010  * Convert a VT_UI2 to a VT_BOOL.
5011  *
5012  * PARAMS
5013  *  usIn     [I] Source
5014  *  pBoolOut [O] Destination
5015  *
5016  * RETURNS
5017  *  S_OK.
5018  */
5019 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
5020 {
5021   return _VarBoolFromUI2(usIn, pBoolOut);
5022 }
5023
5024 /************************************************************************
5025  * VarBoolFromUI4 (OLEAUT32.235)
5026  *
5027  * Convert a VT_UI4 to a VT_BOOL.
5028  *
5029  * PARAMS
5030  *  ulIn     [I] Source
5031  *  pBoolOut [O] Destination
5032  *
5033  * RETURNS
5034  *  S_OK.
5035  */
5036 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
5037 {
5038   return _VarBoolFromUI4(ulIn, pBoolOut);
5039 }
5040
5041 /************************************************************************
5042  * VarBoolFromDec (OLEAUT32.236)
5043  *
5044  * Convert a VT_DECIMAL to a VT_BOOL.
5045  *
5046  * PARAMS
5047  *  pDecIn   [I] Source
5048  *  pBoolOut [O] Destination
5049  *
5050  * RETURNS
5051  *  Success: S_OK.
5052  *  Failure: E_INVALIDARG, if pDecIn is invalid.
5053  */
5054 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
5055 {
5056   if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
5057     return E_INVALIDARG;
5058
5059   if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
5060     *pBoolOut = VARIANT_TRUE;
5061   else
5062     *pBoolOut = VARIANT_FALSE;
5063   return S_OK;
5064 }
5065
5066 /************************************************************************
5067  * VarBoolFromI8 (OLEAUT32.370)
5068  *
5069  * Convert a VT_I8 to a VT_BOOL.
5070  *
5071  * PARAMS
5072  *  ullIn    [I] Source
5073  *  pBoolOut [O] Destination
5074  *
5075  * RETURNS
5076  *  S_OK.
5077  */
5078 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
5079 {
5080   return _VarBoolFromI8(llIn, pBoolOut);
5081 }
5082
5083 /************************************************************************
5084  * VarBoolFromUI8 (OLEAUT32.371)
5085  *
5086  * Convert a VT_UI8 to a VT_BOOL.
5087  *
5088  * PARAMS
5089  *  ullIn    [I] Source
5090  *  pBoolOut [O] Destination
5091  *
5092  * RETURNS
5093  *  S_OK.
5094  */
5095 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
5096 {
5097   return _VarBoolFromUI8(ullIn, pBoolOut);
5098 }
5099
5100 /* BSTR
5101  */
5102
5103 /* Write a number from a UI8 and sign */
5104 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
5105 {
5106   do
5107   {
5108     WCHAR ulNextDigit = ulVal % 10;
5109
5110     *szOut-- = '0' + ulNextDigit;
5111     ulVal = (ulVal - ulNextDigit) / 10;
5112   } while (ulVal);
5113
5114   szOut++;
5115   return szOut;
5116 }
5117
5118 /* Create a (possibly localised) BSTR from a UI8 and sign */
5119 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
5120 {
5121   WCHAR szConverted[256];
5122
5123   if (dwFlags & VAR_NEGATIVE)
5124     *--szOut = '-';
5125
5126   if (dwFlags & LOCALE_USE_NLS)
5127   {
5128     /* Format the number for the locale */
5129     szConverted[0] = '\0';
5130     GetNumberFormatW(lcid,
5131                      dwFlags & LOCALE_NOUSEROVERRIDE,
5132                      szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
5133     szOut = szConverted;
5134   }
5135   return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
5136 }
5137
5138 /* Create a (possibly localised) BSTR from a UI8 and sign */
5139 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
5140 {
5141   WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5142
5143   if (!pbstrOut)
5144     return E_INVALIDARG;
5145
5146   /* Create the basic number string */
5147   *szOut-- = '\0';
5148   szOut = VARIANT_WriteNumber(ulVal, szOut);
5149
5150   *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5151   TRACE("returning %s\n", debugstr_w(*pbstrOut));
5152   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5153 }
5154
5155 /******************************************************************************
5156  * VarBstrFromUI1 (OLEAUT32.108)
5157  *
5158  * Convert a VT_UI1 to a VT_BSTR.
5159  *
5160  * PARAMS
5161  *  bIn      [I] Source
5162  *  lcid     [I] LCID for the conversion
5163  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5164  *  pbstrOut [O] Destination
5165  *
5166  * RETURNS
5167  *  Success: S_OK.
5168  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5169  *           E_OUTOFMEMORY, if memory allocation fails.
5170  */
5171 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5172 {
5173   return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
5174 }
5175
5176 /******************************************************************************
5177  * VarBstrFromI2 (OLEAUT32.109)
5178  *
5179  * Convert a VT_I2 to a VT_BSTR.
5180  *
5181  * PARAMS
5182  *  sIn      [I] Source
5183  *  lcid     [I] LCID for the conversion
5184  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5185  *  pbstrOut [O] Destination
5186  *
5187  * RETURNS
5188  *  Success: S_OK.
5189  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5190  *           E_OUTOFMEMORY, if memory allocation fails.
5191  */
5192 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5193 {
5194   ULONG64 ul64 = sIn;
5195
5196   if (sIn < 0)
5197   {
5198     ul64 = -sIn;
5199     dwFlags |= VAR_NEGATIVE;
5200   }
5201   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5202 }
5203
5204 /******************************************************************************
5205  * VarBstrFromI4 (OLEAUT32.110)
5206  *
5207  * Convert a VT_I4 to a VT_BSTR.
5208  *
5209  * PARAMS
5210  *  lIn      [I] Source
5211  *  lcid     [I] LCID for the conversion
5212  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5213  *  pbstrOut [O] Destination
5214  *
5215  * RETURNS
5216  *  Success: S_OK.
5217  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5218  *           E_OUTOFMEMORY, if memory allocation fails.
5219  */
5220 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5221 {
5222   ULONG64 ul64 = lIn;
5223
5224   if (lIn < 0)
5225   {
5226     ul64 = -lIn;
5227     dwFlags |= VAR_NEGATIVE;
5228   }
5229   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5230 }
5231
5232 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
5233                                     BSTR* pbstrOut, LPCWSTR lpszFormat)
5234 {
5235   WCHAR buff[256];
5236
5237   if (!pbstrOut)
5238     return E_INVALIDARG;
5239
5240   sprintfW( buff, lpszFormat, dblIn );
5241   TRACE("created string %s\n", debugstr_w(buff));
5242   if (dwFlags & LOCALE_USE_NLS)
5243   {
5244     WCHAR numbuff[256];
5245
5246     /* Format the number for the locale */
5247     numbuff[0] = '\0';
5248     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5249                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
5250     TRACE("created NLS string %s\n", debugstr_w(numbuff));
5251     *pbstrOut = SysAllocString(numbuff);
5252   }
5253   else
5254     *pbstrOut = SysAllocString(buff);
5255   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5256 }
5257
5258 /******************************************************************************
5259  * VarBstrFromR4 (OLEAUT32.111)
5260  *
5261  * Convert a VT_R4 to a VT_BSTR.
5262  *
5263  * PARAMS
5264  *  fltIn    [I] Source
5265  *  lcid     [I] LCID for the conversion
5266  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5267  *  pbstrOut [O] Destination
5268  *
5269  * RETURNS
5270  *  Success: S_OK.
5271  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5272  *           E_OUTOFMEMORY, if memory allocation fails.
5273  */
5274 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5275 {
5276   return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
5277 }
5278
5279 /******************************************************************************
5280  * VarBstrFromR8 (OLEAUT32.112)
5281  *
5282  * Convert a VT_R8 to a VT_BSTR.
5283  *
5284  * PARAMS
5285  *  dblIn    [I] Source
5286  *  lcid     [I] LCID for the conversion
5287  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5288  *  pbstrOut [O] Destination
5289  *
5290  * RETURNS
5291  *  Success: S_OK.
5292  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5293  *           E_OUTOFMEMORY, if memory allocation fails.
5294  */
5295 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5296 {
5297   return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
5298 }
5299
5300 /******************************************************************************
5301  *    VarBstrFromCy   [OLEAUT32.113]
5302  *
5303  * Convert a VT_CY to a VT_BSTR.
5304  *
5305  * PARAMS
5306  *  cyIn     [I] Source
5307  *  lcid     [I] LCID for the conversion
5308  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5309  *  pbstrOut [O] Destination
5310  *
5311  * RETURNS
5312  *  Success: S_OK.
5313  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5314  *           E_OUTOFMEMORY, if memory allocation fails.
5315  */
5316 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
5317 {
5318   WCHAR buff[256];
5319   double dblVal;
5320
5321   if (!pbstrOut)
5322     return E_INVALIDARG;
5323
5324   VarR8FromCy(cyIn, &dblVal);
5325   sprintfW(buff, szDoubleFormatW, dblVal);
5326
5327   if (dwFlags & LOCALE_USE_NLS)
5328   {
5329     WCHAR cybuff[256];
5330
5331     /* Format the currency for the locale */
5332     cybuff[0] = '\0';
5333     GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5334                        buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
5335     *pbstrOut = SysAllocString(cybuff);
5336   }
5337   else
5338     *pbstrOut = SysAllocString(buff);
5339
5340   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5341 }
5342
5343 /******************************************************************************
5344  *    VarBstrFromDate    [OLEAUT32.114]
5345  *
5346  * Convert a VT_DATE to a VT_BSTR.
5347  *
5348  * PARAMS
5349  *  dateIn   [I] Source
5350  *  lcid     [I] LCID for the conversion
5351  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5352  *  pbstrOut [O] Destination
5353  *
5354  * RETURNS
5355  *  Success: S_OK.
5356  *  Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5357  *           E_OUTOFMEMORY, if memory allocation fails.
5358  */
5359 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5360 {
5361   SYSTEMTIME st;
5362   DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
5363   WCHAR date[128], *time;
5364
5365   TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
5366
5367   if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
5368     return E_INVALIDARG;
5369
5370   *pbstrOut = NULL;
5371
5372   if (dwFlags & VAR_CALENDAR_THAI)
5373       st.wYear += 553; /* Use the Thai buddhist calendar year */
5374   else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
5375       FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5376
5377   if (dwFlags & LOCALE_USE_NLS)
5378     dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
5379   else
5380   {
5381     double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
5382     double partial = dateIn - whole;
5383
5384     if (whole == 0.0)
5385       dwFlags |= VAR_TIMEVALUEONLY;
5386     else if (partial < 1e-12)
5387       dwFlags |= VAR_DATEVALUEONLY;
5388   }
5389
5390   if (dwFlags & VAR_TIMEVALUEONLY)
5391     date[0] = '\0';
5392   else
5393     if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
5394                         sizeof(date)/sizeof(WCHAR)))
5395       return E_INVALIDARG;
5396
5397   if (!(dwFlags & VAR_DATEVALUEONLY))
5398   {
5399     time = date + strlenW(date);
5400     if (time != date)
5401       *time++ = ' ';
5402     if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
5403                         sizeof(date)/sizeof(WCHAR)-(time-date)))
5404       return E_INVALIDARG;
5405   }
5406
5407   *pbstrOut = SysAllocString(date);
5408   if (*pbstrOut)
5409     TRACE("returning %s\n", debugstr_w(*pbstrOut));
5410   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5411 }
5412
5413 /******************************************************************************
5414  * VarBstrFromBool (OLEAUT32.116)
5415  *
5416  * Convert a VT_BOOL to a VT_BSTR.
5417  *
5418  * PARAMS
5419  *  boolIn   [I] Source
5420  *  lcid     [I] LCID for the conversion
5421  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5422  *  pbstrOut [O] Destination
5423  *
5424  * RETURNS
5425  *  Success: S_OK.
5426  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5427  *           E_OUTOFMEMORY, if memory allocation fails.
5428  *
5429  * NOTES
5430  *  If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5431  *  localised text of "True" or "False". To convert a bool into a
5432  *  numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5433  */
5434 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5435 {
5436   WCHAR szBuff[64];
5437   DWORD dwResId = IDS_TRUE;
5438   LANGID langId;
5439
5440   TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn, lcid, dwFlags, pbstrOut);
5441
5442   if (!pbstrOut)
5443     return E_INVALIDARG;
5444
5445   /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5446    * for variant formatting */
5447   switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
5448   {
5449   case VAR_BOOLONOFF:
5450       dwResId = IDS_ON;
5451       break;
5452   case VAR_BOOLYESNO:
5453       dwResId = IDS_YES;
5454       break;
5455   case VAR_LOCALBOOL:
5456       break;
5457   default:
5458     lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
5459   }
5460
5461   lcid = ConvertDefaultLocale(lcid);
5462   langId = LANGIDFROMLCID(lcid);
5463   if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
5464     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5465
5466   if (boolIn == VARIANT_FALSE)
5467     dwResId++; /* Use negative form */
5468
5469 VarBstrFromBool_GetLocalised:
5470   if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
5471   {
5472     *pbstrOut = SysAllocString(szBuff);
5473     return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5474   }
5475
5476   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5477   {
5478     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5479     goto VarBstrFromBool_GetLocalised;
5480   }
5481
5482   /* Should never get here */
5483   WARN("Failed to load bool text!\n");
5484   return E_OUTOFMEMORY;
5485 }
5486
5487 /******************************************************************************
5488  * VarBstrFromI1 (OLEAUT32.229)
5489  *
5490  * Convert a VT_I1 to a VT_BSTR.
5491  *
5492  * PARAMS
5493  *  cIn      [I] Source
5494  *  lcid     [I] LCID for the conversion
5495  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5496  *  pbstrOut [O] Destination
5497  *
5498  * RETURNS
5499  *  Success: S_OK.
5500  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5501  *           E_OUTOFMEMORY, if memory allocation fails.
5502  */
5503 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5504 {
5505   ULONG64 ul64 = cIn;
5506
5507   if (cIn < 0)
5508   {
5509     ul64 = -cIn;
5510     dwFlags |= VAR_NEGATIVE;
5511   }
5512   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5513 }
5514
5515 /******************************************************************************
5516  * VarBstrFromUI2 (OLEAUT32.230)
5517  *
5518  * Convert a VT_UI2 to a VT_BSTR.
5519  *
5520  * PARAMS
5521  *  usIn     [I] Source
5522  *  lcid     [I] LCID for the conversion
5523  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5524  *  pbstrOut [O] Destination
5525  *
5526  * RETURNS
5527  *  Success: S_OK.
5528  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5529  *           E_OUTOFMEMORY, if memory allocation fails.
5530  */
5531 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5532 {
5533   return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
5534 }
5535
5536 /******************************************************************************
5537  * VarBstrFromUI4 (OLEAUT32.231)
5538  *
5539  * Convert a VT_UI4 to a VT_BSTR.
5540  *
5541  * PARAMS
5542  *  ulIn     [I] Source
5543  *  lcid     [I] LCID for the conversion
5544  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5545  *  pbstrOut [O] Destination
5546  *
5547  * RETURNS
5548  *  Success: S_OK.
5549  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5550  *           E_OUTOFMEMORY, if memory allocation fails.
5551  */
5552 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5553 {
5554   return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
5555 }
5556
5557 /******************************************************************************
5558  * VarBstrFromDec (OLEAUT32.232)
5559  *
5560  * Convert a VT_DECIMAL to a VT_BSTR.
5561  *
5562  * PARAMS
5563  *  pDecIn   [I] Source
5564  *  lcid     [I] LCID for the conversion
5565  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5566  *  pbstrOut [O] Destination
5567  *
5568  * RETURNS
5569  *  Success: S_OK.
5570  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5571  *           E_OUTOFMEMORY, if memory allocation fails.
5572  */
5573 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5574 {
5575   if (!pbstrOut)
5576     return E_INVALIDARG;
5577
5578   if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
5579   {
5580     WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5581
5582     /* Create the basic number string */
5583     *szOut-- = '\0';
5584     szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
5585     if (DEC_SIGN(pDecIn))
5586       dwFlags |= VAR_NEGATIVE;
5587
5588     *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5589     TRACE("returning %s\n", debugstr_w(*pbstrOut));
5590     return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5591   }
5592   FIXME("semi-stub\n");
5593   return E_INVALIDARG;
5594 }
5595
5596 /************************************************************************
5597  * VarBstrFromI8 (OLEAUT32.370)
5598  *
5599  * Convert a VT_I8 to a VT_BSTR.
5600  *
5601  * PARAMS
5602  *  llIn     [I] Source
5603  *  lcid     [I] LCID for the conversion
5604  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5605  *  pbstrOut [O] Destination
5606  *
5607  * RETURNS
5608  *  Success: S_OK.
5609  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5610  *           E_OUTOFMEMORY, if memory allocation fails.
5611  */
5612 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5613 {
5614   ULONG64 ul64 = llIn;
5615
5616   if (llIn < 0)
5617   {
5618     ul64 = -llIn;
5619     dwFlags |= VAR_NEGATIVE;
5620   }
5621   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5622 }
5623
5624 /************************************************************************
5625  * VarBstrFromUI8 (OLEAUT32.371)
5626  *
5627  * Convert a VT_UI8 to a VT_BSTR.
5628  *
5629  * PARAMS
5630  *  ullIn    [I] Source
5631  *  lcid     [I] LCID for the conversion
5632  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5633  *  pbstrOut [O] Destination
5634  *
5635  * RETURNS
5636  *  Success: S_OK.
5637  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5638  *           E_OUTOFMEMORY, if memory allocation fails.
5639  */
5640 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5641 {
5642   return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
5643 }
5644
5645 /**********************************************************************
5646  * VarBstrCat (OLEAUT32.313)
5647  *
5648  * Concatenate two BSTR values.
5649  *
5650  * PARAMS
5651  *  pbstrLeft  [I] Source
5652  *  pbstrRight [I] Value to concatenate
5653  *  pbstrOut   [O] Destination
5654  *
5655  * RETURNS
5656  *  Success: S_OK.
5657  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
5658  *           E_OUTOFMEMORY, if memory allocation fails.
5659  */
5660 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
5661 {
5662   unsigned int len;
5663
5664   if (!pbstrOut)
5665     return E_INVALIDARG;
5666
5667   len = pbstrLeft ? strlenW(pbstrLeft) : 0;
5668   if (pbstrRight)
5669     len += strlenW(pbstrRight);
5670
5671   *pbstrOut = SysAllocStringLen(NULL, len);
5672   if (!*pbstrOut)
5673     return E_OUTOFMEMORY;
5674
5675   (*pbstrOut)[0] = '\0';
5676
5677   if (pbstrLeft)
5678     strcpyW(*pbstrOut, pbstrLeft);
5679
5680   if (pbstrRight)
5681     strcatW(*pbstrOut, pbstrRight);
5682
5683   return S_OK;
5684 }
5685
5686 /**********************************************************************
5687  * VarBstrCmp (OLEAUT32.314)
5688  *
5689  * Compare two BSTR values.
5690  *
5691  * PARAMS
5692  *  pbstrLeft  [I] Source
5693  *  pbstrRight [I] Value to compare
5694  *  lcid       [I] LCID for the comparason
5695  *  dwFlags    [I] Flags to pass directly to CompareStringW().
5696  *
5697  * RETURNS
5698  *  VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5699  *  than, equal to or greater than pbstrRight respectively.
5700  *  VARCMP_NULL is returned if either string is NULL, unless both are NULL
5701  *  in which case VARCMP_EQ is returned.
5702  */
5703 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
5704 {
5705     if (!pbstrLeft)
5706     {
5707       if (!pbstrRight || !*pbstrRight)
5708         return VARCMP_EQ;
5709       return VARCMP_NULL;
5710     }
5711     else if (!pbstrRight)
5712     {
5713       if (!*pbstrLeft)
5714         return VARCMP_EQ;
5715       return VARCMP_NULL;
5716     }
5717
5718     return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
5719 }
5720
5721 /*
5722  * DATE
5723  */
5724
5725 /******************************************************************************
5726  * VarDateFromUI1 (OLEAUT32.88)
5727  *
5728  * Convert a VT_UI1 to a VT_DATE.
5729  *
5730  * PARAMS
5731  *  bIn      [I] Source
5732  *  pdateOut [O] Destination
5733  *
5734  * RETURNS
5735  *  S_OK.
5736  */
5737 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
5738 {
5739   return _VarDateFromUI1(bIn, pdateOut);
5740 }
5741
5742 /******************************************************************************
5743  * VarDateFromI2 (OLEAUT32.89)
5744  *
5745  * Convert a VT_I2 to a VT_DATE.
5746  *
5747  * PARAMS
5748  *  sIn      [I] Source
5749  *  pdateOut [O] Destination
5750  *
5751  * RETURNS
5752  *  S_OK.
5753  */
5754 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
5755 {
5756   return _VarDateFromI2(sIn, pdateOut);
5757 }
5758
5759 /******************************************************************************
5760  * VarDateFromI4 (OLEAUT32.90)
5761  *
5762  * Convert a VT_I4 to a VT_DATE.
5763  *
5764  * PARAMS
5765  *  lIn      [I] Source
5766  *  pdateOut [O] Destination
5767  *
5768  * RETURNS
5769  *  S_OK.
5770  */
5771 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
5772 {
5773   return _VarDateFromI4(lIn, pdateOut);
5774 }
5775
5776 /******************************************************************************
5777  * VarDateFromR4 (OLEAUT32.91)
5778  *
5779  * Convert a VT_R4 to a VT_DATE.
5780  *
5781  * PARAMS
5782  *  fltIn    [I] Source
5783  *  pdateOut [O] Destination
5784  *
5785  * RETURNS
5786  *  S_OK.
5787  */
5788 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
5789 {
5790   return _VarDateFromR4(fltIn, pdateOut);
5791 }
5792
5793 /******************************************************************************
5794  * VarDateFromR8 (OLEAUT32.92)
5795  *
5796  * Convert a VT_R8 to a VT_DATE.
5797  *
5798  * PARAMS
5799  *  dblIn    [I] Source
5800  *  pdateOut [O] Destination
5801  *
5802  * RETURNS
5803  *  S_OK.
5804  */
5805 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
5806 {
5807   return _VarDateFromR8(dblIn, pdateOut);
5808 }
5809
5810 /**********************************************************************
5811  * VarDateFromDisp (OLEAUT32.95)
5812  *
5813  * Convert a VT_DISPATCH to a VT_DATE.
5814  *
5815  * PARAMS
5816  *  pdispIn  [I] Source
5817  *  lcid     [I] LCID for conversion
5818  *  pdateOut [O] Destination
5819  *
5820  * RETURNS
5821  *  Success: S_OK.
5822  *  Failure: E_INVALIDARG, if the source value is invalid
5823  *           DISP_E_OVERFLOW, if the value will not fit in the destination
5824  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
5825  */
5826 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
5827 {
5828   return _VarDateFromDisp(pdispIn, lcid, pdateOut);
5829 }
5830
5831 /******************************************************************************
5832  * VarDateFromBool (OLEAUT32.96)
5833  *
5834  * Convert a VT_BOOL to a VT_DATE.
5835  *
5836  * PARAMS
5837  *  boolIn   [I] Source
5838  *  pdateOut [O] Destination
5839  *
5840  * RETURNS
5841  *  S_OK.
5842  */
5843 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
5844 {
5845   return _VarDateFromBool(boolIn, pdateOut);
5846 }
5847
5848 /**********************************************************************
5849  * VarDateFromCy (OLEAUT32.93)
5850  *
5851  * Convert a VT_CY to a VT_DATE.
5852  *
5853  * PARAMS
5854  *  lIn      [I] Source
5855  *  pdateOut [O] Destination
5856  *
5857  * RETURNS
5858  *  S_OK.
5859  */
5860 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
5861 {
5862   return _VarDateFromCy(cyIn, pdateOut);
5863 }
5864
5865 /* Date string parsing */
5866 #define DP_TIMESEP 0x01 /* Time seperator ( _must_ remain 0x1, used as a bitmask) */
5867 #define DP_DATESEP 0x02 /* Date seperator */
5868 #define DP_MONTH   0x04 /* Month name */
5869 #define DP_AM      0x08 /* AM */
5870 #define DP_PM      0x10 /* PM */
5871
5872 typedef struct tagDATEPARSE
5873 {
5874     DWORD dwCount;      /* Number of fields found so far (maximum 6) */
5875     DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
5876     DWORD dwFlags[6];   /* Flags for each field */
5877     DWORD dwValues[6];  /* Value of each field */
5878 } DATEPARSE;
5879
5880 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
5881
5882 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5883
5884 /* Determine if a day is valid in a given month of a given year */
5885 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
5886 {
5887   static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
5888
5889   if (day && month && month < 13)
5890   {
5891     if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
5892       return TRUE;
5893   }
5894   return FALSE;
5895 }
5896
5897 /* Possible orders for 3 numbers making up a date */
5898 #define ORDER_MDY 0x01
5899 #define ORDER_YMD 0x02
5900 #define ORDER_YDM 0x04
5901 #define ORDER_DMY 0x08
5902 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
5903
5904 /* Determine a date for a particular locale, from 3 numbers */
5905 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
5906                                        DWORD offset, SYSTEMTIME *st)
5907 {
5908   DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
5909
5910   if (!dp->dwCount)
5911   {
5912     v1 = 30; /* Default to (Variant) 0 date part */
5913     v2 = 12;
5914     v3 = 1899;
5915     goto VARIANT_MakeDate_OK;
5916   }
5917
5918   v1 = dp->dwValues[offset + 0];
5919   v2 = dp->dwValues[offset + 1];
5920   if (dp->dwCount == 2)
5921   {
5922     SYSTEMTIME current;
5923     GetSystemTime(&current);
5924     v3 = current.wYear;
5925   }
5926   else
5927     v3 = dp->dwValues[offset + 2];
5928
5929   TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
5930
5931   /* If one number must be a month (Because a month name was given), then only
5932    * consider orders with the month in that position.
5933    * If we took the current year as 'v3', then only allow a year in that position.
5934    */
5935   if (dp->dwFlags[offset + 0] & DP_MONTH)
5936   {
5937     dwAllOrders = ORDER_MDY;
5938   }
5939   else if (dp->dwFlags[offset + 1] & DP_MONTH)
5940   {
5941     dwAllOrders = ORDER_DMY;
5942     if (dp->dwCount > 2)
5943       dwAllOrders |= ORDER_YMD;
5944   }
5945   else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
5946   {
5947     dwAllOrders = ORDER_YDM;
5948   }
5949   else
5950   {
5951     dwAllOrders = ORDER_MDY|ORDER_DMY;
5952     if (dp->dwCount > 2)
5953       dwAllOrders |= (ORDER_YMD|ORDER_YDM);
5954   }
5955
5956 VARIANT_MakeDate_Start:
5957   TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
5958
5959   while (dwAllOrders)
5960   {
5961     DWORD dwTemp;
5962
5963     if (dwCount == 0)
5964     {
5965       /* First: Try the order given by iDate */
5966       switch (iDate)
5967       {
5968       case 0:  dwTry = dwAllOrders & ORDER_MDY; break;
5969       case 1:  dwTry = dwAllOrders & ORDER_DMY; break;
5970       default: dwTry = dwAllOrders & ORDER_YMD; break;
5971       }
5972     }
5973     else if (dwCount == 1)
5974     {
5975       /* Second: Try all the orders compatable with iDate */
5976       switch (iDate)
5977       {
5978       case 0:  dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
5979       case 1:  dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
5980       default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
5981       }
5982     }
5983     else
5984     {
5985       /* Finally: Try any remaining orders */
5986       dwTry = dwAllOrders;
5987     }
5988
5989     TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
5990
5991     dwCount++;
5992     if (!dwTry)
5993       continue;
5994
5995 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
5996
5997     if (dwTry & ORDER_MDY)
5998     {
5999       if (VARIANT_IsValidMonthDay(v2,v1,v3))
6000       {
6001         DATE_SWAP(v1,v2);
6002         goto VARIANT_MakeDate_OK;
6003       }
6004       dwAllOrders &= ~ORDER_MDY;
6005     }
6006     if (dwTry & ORDER_YMD)
6007     {
6008       if (VARIANT_IsValidMonthDay(v3,v2,v1))
6009       {
6010         DATE_SWAP(v1,v3);
6011         goto VARIANT_MakeDate_OK;
6012       }
6013       dwAllOrders &= ~ORDER_YMD;
6014     }
6015     if (dwTry & ORDER_YDM)
6016     {
6017       if (VARIANT_IsValidMonthDay(v2,v3,v1))
6018       {
6019         DATE_SWAP(v1,v2);
6020         DATE_SWAP(v2,v3);
6021         goto VARIANT_MakeDate_OK;
6022       }
6023       dwAllOrders &= ~ORDER_YDM;
6024     }
6025     if (dwTry & ORDER_DMY)
6026     {
6027       if (VARIANT_IsValidMonthDay(v1,v2,v3))
6028         goto VARIANT_MakeDate_OK;
6029       dwAllOrders &= ~ORDER_DMY;
6030     }
6031     if (dwTry & ORDER_MYD)
6032     {
6033       /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6034       if (VARIANT_IsValidMonthDay(v3,v1,v2))
6035       {
6036         DATE_SWAP(v1,v3);
6037         DATE_SWAP(v2,v3);
6038         goto VARIANT_MakeDate_OK;
6039       }
6040       dwAllOrders &= ~ORDER_MYD;
6041     }
6042   }
6043
6044   if (dp->dwCount == 2)
6045   {
6046     /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6047     v3 = 1; /* 1st of the month */
6048     dwAllOrders = ORDER_YMD|ORDER_MYD;
6049     dp->dwCount = 0; /* Don't return to this code path again */
6050     dwCount = 0;
6051     goto VARIANT_MakeDate_Start;
6052   }
6053
6054   /* No valid dates were able to be constructed */
6055   return DISP_E_TYPEMISMATCH;
6056
6057 VARIANT_MakeDate_OK:
6058
6059   /* Check that the time part is ok */
6060   if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
6061     return DISP_E_TYPEMISMATCH;
6062
6063   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6064   if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
6065     st->wHour += 12;
6066   else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
6067     st->wHour = 0;
6068   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6069
6070   st->wDay = v1;
6071   st->wMonth = v2;
6072   /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6073    * be retrieved from:
6074    * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6075    * But Wine doesn't have/use that key as at the time of writing.
6076    */
6077   st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
6078   TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
6079   return S_OK;
6080 }
6081
6082 /******************************************************************************
6083  * VarDateFromStr [OLEAUT32.94]
6084  *
6085  * Convert a VT_BSTR to at VT_DATE.
6086  *
6087  * PARAMS
6088  *  strIn    [I] String to convert
6089  *  lcid     [I] Locale identifier for the conversion
6090  *  dwFlags  [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6091  *  pdateOut [O] Destination for the converted value
6092  *
6093  * RETURNS
6094  *  Success: S_OK. pdateOut contains the converted value.
6095  *  FAILURE: An HRESULT error code indicating the prolem.
6096  *
6097  * NOTES
6098  *  Any date format that can be created using the date formats from lcid
6099  *  (Either from kernel Nls functions, variant conversion or formatting) is a
6100  *  valid input to this function. In addition, a few more esoteric formats are
6101  *  also supported for compatability with the native version. The date is
6102  *  interpreted according to the date settings in the control panel, unless
6103  *  the date is invalid in that format, in which the most compatable format
6104  *  that produces a valid date will be used.
6105  */
6106 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
6107 {
6108   static const USHORT ParseDateTokens[] =
6109   {
6110     LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
6111     LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
6112     LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
6113     LOCALE_SMONTHNAME13,
6114     LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
6115     LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
6116     LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
6117     LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
6118     LOCALE_SABBREVMONTHNAME13,
6119     LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
6120     LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
6121     LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
6122     LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
6123     LOCALE_SABBREVDAYNAME7,
6124     LOCALE_S1159, LOCALE_S2359
6125   };
6126   static const BYTE ParseDateMonths[] =
6127   {
6128     1,2,3,4,5,6,7,8,9,10,11,12,13,
6129     1,2,3,4,5,6,7,8,9,10,11,12,13
6130   };
6131   size_t i;
6132   BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
6133   DATEPARSE dp;
6134   DWORD dwDateSeps = 0, iDate = 0;
6135   HRESULT hRet = S_OK;
6136
6137   if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
6138       (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
6139     return E_INVALIDARG;
6140
6141   if (!strIn)
6142     return DISP_E_TYPEMISMATCH;
6143
6144   *pdateOut = 0.0;
6145
6146   TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
6147
6148   memset(&dp, 0, sizeof(dp));
6149
6150   GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
6151                  (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
6152   TRACE("iDate is %ld\n", iDate);
6153
6154   /* Get the month/day/am/pm tokens for this locale */
6155   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6156   {
6157     WCHAR buff[128];
6158     LCTYPE lctype =  ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
6159
6160     /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6161      *        GetAltMonthNames(). We should really cache these strings too.
6162      */
6163     buff[0] = '\0';
6164     GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
6165     tokens[i] = SysAllocString(buff);
6166     TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
6167   }
6168
6169   /* Parse the string into our structure */
6170   while (*strIn)
6171   {
6172     if (dp.dwCount > 6)
6173       break;
6174
6175     if (isdigitW(*strIn))
6176     {
6177       dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
6178       dp.dwCount++;
6179       strIn--;
6180     }
6181     else if (isalpha(*strIn))
6182     {
6183       BOOL bFound = FALSE;
6184
6185       for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6186       {
6187         DWORD dwLen = strlenW(tokens[i]);
6188         if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
6189         {
6190           if (i <= 25)
6191           {
6192             dp.dwValues[dp.dwCount] = ParseDateMonths[i];
6193             dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
6194             dp.dwCount++;
6195           }
6196           else if (i > 39)
6197           {
6198             if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
6199               hRet = DISP_E_TYPEMISMATCH;
6200             else
6201             {
6202               dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
6203               dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
6204             }
6205           }
6206           strIn += (dwLen - 1);
6207           bFound = TRUE;
6208           break;
6209         }
6210       }
6211
6212       if (!bFound)
6213       {
6214         if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
6215             (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6216         {
6217           /* Special case - 'a' and 'p' are recognised as short for am/pm */
6218           if (*strIn == 'a' || *strIn == 'A')
6219           {
6220             dp.dwFlags[dp.dwCount - 1] |= DP_AM;
6221             dp.dwParseFlags |=  DP_AM;
6222           }
6223           else
6224           {
6225             dp.dwFlags[dp.dwCount - 1] |= DP_PM;
6226             dp.dwParseFlags |=  DP_PM;
6227           }
6228           strIn++;
6229         }
6230         else
6231         {
6232           TRACE("No matching token for %s\n", debugstr_w(strIn));
6233           hRet = DISP_E_TYPEMISMATCH;
6234           break;
6235         }
6236       }
6237     }
6238     else if (*strIn == ':' ||  *strIn == '.')
6239     {
6240       if (!dp.dwCount || !strIn[1])
6241         hRet = DISP_E_TYPEMISMATCH;
6242       else
6243         dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
6244     }
6245     else if (*strIn == '-' || *strIn == '/')
6246     {
6247       dwDateSeps++;
6248       if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
6249         hRet = DISP_E_TYPEMISMATCH;
6250       else
6251         dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
6252     }
6253     else if (*strIn == ',' || isspaceW(*strIn))
6254     {
6255       if (*strIn == ',' && !strIn[1])
6256         hRet = DISP_E_TYPEMISMATCH;
6257     }
6258     else
6259     {
6260       hRet = DISP_E_TYPEMISMATCH;
6261     }
6262     strIn++;
6263   }
6264
6265   if (!dp.dwCount || dp.dwCount > 6 ||
6266       (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6267     hRet = DISP_E_TYPEMISMATCH;
6268
6269   if (SUCCEEDED(hRet))
6270   {
6271     SYSTEMTIME st;
6272     DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
6273
6274     st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
6275
6276     /* Figure out which numbers correspond to which fields.
6277      *
6278      * This switch statement works based on the fact that native interprets any
6279      * fields that are not joined with a time seperator ('.' or ':') as date
6280      * fields. Thus we construct a value from 0-32 where each set bit indicates
6281      * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6282      * For valid permutations, we set dwOffset to point to the first date field
6283      * and shorten dp.dwCount by the number of time fields found. The real
6284      * magic here occurs in VARIANT_MakeDate() above, where we determine what
6285      * each date number must represent in the context of iDate.
6286      */
6287     TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6288
6289     switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6290     {
6291     case 0x1: /* TT TTDD TTDDD */
6292       if (dp.dwCount > 3 &&
6293           ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
6294           (dp.dwFlags[4] & (DP_AM|DP_PM))))
6295         hRet = DISP_E_TYPEMISMATCH;
6296       else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
6297         hRet = DISP_E_TYPEMISMATCH;
6298       st.wHour = dp.dwValues[0];
6299       st.wMinute  = dp.dwValues[1];
6300       dp.dwCount -= 2;
6301       dwOffset = 2;
6302       break;
6303
6304     case 0x3: /* TTT TTTDD TTTDDD */
6305       if (dp.dwCount > 4 &&
6306           ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
6307           (dp.dwFlags[5] & (DP_AM|DP_PM))))
6308         hRet = DISP_E_TYPEMISMATCH;
6309       else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
6310         hRet = DISP_E_TYPEMISMATCH;
6311       st.wHour   = dp.dwValues[0];
6312       st.wMinute = dp.dwValues[1];
6313       st.wSecond = dp.dwValues[2];
6314       dwOffset = 3;
6315       dp.dwCount -= 3;
6316       break;
6317
6318     case 0x4: /* DDTT */
6319       if (dp.dwCount != 4 ||
6320           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6321         hRet = DISP_E_TYPEMISMATCH;
6322
6323       st.wHour = dp.dwValues[2];
6324       st.wMinute  = dp.dwValues[3];
6325       dp.dwCount -= 2;
6326       break;
6327
6328    case 0x0: /* T DD DDD TDDD TDDD */
6329       if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
6330       {
6331         st.wHour = dp.dwValues[0]; /* T */
6332         dp.dwCount = 0;
6333         break;
6334       }
6335       else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
6336       {
6337         hRet = DISP_E_TYPEMISMATCH;
6338       }
6339       else if (dp.dwCount == 3)
6340       {
6341         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
6342         {
6343           dp.dwCount = 2;
6344           st.wHour = dp.dwValues[0];
6345           dwOffset = 1;
6346           break;
6347         }
6348         if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
6349         {
6350           dp.dwCount = 2;
6351           st.wHour = dp.dwValues[2];
6352           break;
6353         }
6354         else if (dp.dwParseFlags & (DP_AM|DP_PM))
6355           hRet = DISP_E_TYPEMISMATCH;
6356       }
6357       else if (dp.dwCount == 4)
6358       {
6359         dp.dwCount = 3;
6360         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
6361         {
6362           st.wHour = dp.dwValues[0];
6363           dwOffset = 1;
6364         }
6365         else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
6366         {
6367           st.wHour = dp.dwValues[3];
6368         }
6369         else
6370           hRet = DISP_E_TYPEMISMATCH;
6371         break;
6372       }
6373       /* .. fall through .. */
6374
6375     case 0x8: /* DDDTT */
6376       if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
6377           (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
6378            (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
6379            dp.dwCount == 4 || dp.dwCount == 6)
6380         hRet = DISP_E_TYPEMISMATCH;
6381       st.wHour   = dp.dwValues[3];
6382       st.wMinute = dp.dwValues[4];
6383       if (dp.dwCount == 5)
6384         dp.dwCount -= 2;
6385       break;
6386
6387     case 0xC: /* DDTTT */
6388       if (dp.dwCount != 5 ||
6389           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6390         hRet = DISP_E_TYPEMISMATCH;
6391       st.wHour   = dp.dwValues[2];
6392       st.wMinute = dp.dwValues[3];
6393       st.wSecond = dp.dwValues[4];
6394       dp.dwCount -= 3;
6395       break;
6396
6397     case 0x18: /* DDDTTT */
6398       if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
6399           (dp.dwFlags[2] & (DP_AM|DP_PM)))
6400         hRet = DISP_E_TYPEMISMATCH;
6401       st.wHour   = dp.dwValues[3];
6402       st.wMinute = dp.dwValues[4];
6403       st.wSecond = dp.dwValues[5];
6404       dp.dwCount -= 3;
6405       break;
6406
6407     default:
6408       hRet = DISP_E_TYPEMISMATCH;
6409       break;
6410     }
6411
6412     if (SUCCEEDED(hRet))
6413     {
6414       hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
6415
6416       if (dwFlags & VAR_TIMEVALUEONLY)
6417       {
6418         st.wYear = 1899;
6419         st.wMonth = 12;
6420         st.wDay = 30;
6421       }
6422       else if (dwFlags & VAR_DATEVALUEONLY)
6423        st.wHour = st.wMinute = st.wSecond = 0;
6424
6425       /* Finally, convert the value to a VT_DATE */
6426       if (SUCCEEDED(hRet))
6427         hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
6428     }
6429   }
6430
6431   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6432     SysFreeString(tokens[i]);
6433   return hRet;
6434 }
6435
6436 /******************************************************************************
6437  * VarDateFromI1 (OLEAUT32.221)
6438  *
6439  * Convert a VT_I1 to a VT_DATE.
6440  *
6441  * PARAMS
6442  *  cIn      [I] Source
6443  *  pdateOut [O] Destination
6444  *
6445  * RETURNS
6446  *  S_OK.
6447  */
6448 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
6449 {
6450   return _VarDateFromI1(cIn, pdateOut);
6451 }
6452
6453 /******************************************************************************
6454  * VarDateFromUI2 (OLEAUT32.222)
6455  *
6456  * Convert a VT_UI2 to a VT_DATE.
6457  *
6458  * PARAMS
6459  *  uiIn     [I] Source
6460  *  pdateOut [O] Destination
6461  *
6462  * RETURNS
6463  *  S_OK.
6464  */
6465 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
6466 {
6467   return _VarDateFromUI2(uiIn, pdateOut);
6468 }
6469
6470 /******************************************************************************
6471  * VarDateFromUI4 (OLEAUT32.223)
6472  *
6473  * Convert a VT_UI4 to a VT_DATE.
6474  *
6475  * PARAMS
6476  *  ulIn     [I] Source
6477  *  pdateOut [O] Destination
6478  *
6479  * RETURNS
6480  *  S_OK.
6481  */
6482 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
6483 {
6484   return _VarDateFromUI4(ulIn, pdateOut);
6485 }
6486
6487 /**********************************************************************
6488  * VarDateFromDec (OLEAUT32.224)
6489  *
6490  * Convert a VT_DECIMAL to a VT_DATE.
6491  *
6492  * PARAMS
6493  *  pdecIn   [I] Source
6494  *  pdateOut [O] Destination
6495  *
6496  * RETURNS
6497  *  S_OK.
6498  */
6499 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
6500 {
6501   return _VarDateFromDec(pdecIn, pdateOut);
6502 }
6503
6504 /******************************************************************************
6505  * VarDateFromI8 (OLEAUT32.364)
6506  *
6507  * Convert a VT_I8 to a VT_DATE.
6508  *
6509  * PARAMS
6510  *  llIn     [I] Source
6511  *  pdateOut [O] Destination
6512  *
6513  * RETURNS
6514  *  Success: S_OK.
6515  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6516  */
6517 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
6518 {
6519   return _VarDateFromI8(llIn, pdateOut);
6520 }
6521
6522 /******************************************************************************
6523  * VarDateFromUI8 (OLEAUT32.365)
6524  *
6525  * Convert a VT_UI8 to a VT_DATE.
6526  *
6527  * PARAMS
6528  *  ullIn    [I] Source
6529  *  pdateOut [O] Destination
6530  *
6531  * RETURNS
6532  *  Success: S_OK.
6533  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6534  */
6535 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
6536 {
6537   return _VarDateFromUI8(ullIn, pdateOut);
6538 }