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