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