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