wined3d: Use shader_sm1_read_opcode() in shader_get_registers_used().
[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_I4 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   return VarCyFromR8(bIn, pCyOut);
3424 }
3425
3426 /************************************************************************
3427  * VarCyFromI2 (OLEAUT32.99)
3428  *
3429  * Convert a VT_I2 to a VT_CY.
3430  *
3431  * PARAMS
3432  *  sIn    [I] Source
3433  *  pCyOut [O] Destination
3434  *
3435  * RETURNS
3436  *  Success: S_OK.
3437  *  Failure: E_INVALIDARG, if the source value is invalid
3438  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3439  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3440  */
3441 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
3442 {
3443   return VarCyFromR8(sIn, pCyOut);
3444 }
3445
3446 /************************************************************************
3447  * VarCyFromI4 (OLEAUT32.100)
3448  *
3449  * Convert a VT_I4 to a VT_CY.
3450  *
3451  * PARAMS
3452  *  sIn    [I] Source
3453  *  pCyOut [O] Destination
3454  *
3455  * RETURNS
3456  *  Success: S_OK.
3457  *  Failure: E_INVALIDARG, if the source value is invalid
3458  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3459  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3460  */
3461 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
3462 {
3463   return VarCyFromR8(lIn, pCyOut);
3464 }
3465
3466 /************************************************************************
3467  * VarCyFromR4 (OLEAUT32.101)
3468  *
3469  * Convert a VT_R4 to a VT_CY.
3470  *
3471  * PARAMS
3472  *  fltIn  [I] Source
3473  *  pCyOut [O] Destination
3474  *
3475  * RETURNS
3476  *  Success: S_OK.
3477  *  Failure: E_INVALIDARG, if the source value is invalid
3478  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3479  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3480  */
3481 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
3482 {
3483   return VarCyFromR8(fltIn, pCyOut);
3484 }
3485
3486 /************************************************************************
3487  * VarCyFromR8 (OLEAUT32.102)
3488  *
3489  * Convert a VT_R8 to a VT_CY.
3490  *
3491  * PARAMS
3492  *  dblIn  [I] Source
3493  *  pCyOut [O] Destination
3494  *
3495  * RETURNS
3496  *  Success: S_OK.
3497  *  Failure: E_INVALIDARG, if the source value is invalid
3498  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3499  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3500  */
3501 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3502 {
3503 #if defined(__GNUC__) && defined(__i386__)
3504   /* This code gives identical results to Win32 on Intel.
3505    * Here we use fp exceptions to catch overflows when storing the value.
3506    */
3507   static const unsigned short r8_fpcontrol = 0x137f;
3508   static const double r8_multiplier = CY_MULTIPLIER_F;
3509   unsigned short old_fpcontrol, result_fpstatus;
3510
3511   /* Clear exceptions, save the old fp state and load the new state */
3512   __asm__ __volatile__( "fnclex" );
3513   __asm__ __volatile__( "fstcw %0"   :   "=m" (old_fpcontrol) : );
3514   __asm__ __volatile__( "fldcw %0"   : : "m"  (r8_fpcontrol) );
3515   /* Perform the conversion. */
3516   __asm__ __volatile__( "fldl  %0"   : : "m"  (dblIn) );
3517   __asm__ __volatile__( "fmull %0"   : : "m"  (r8_multiplier) );
3518   __asm__ __volatile__( "fistpll %0" : : "m"  (*pCyOut) );
3519   /* Save the resulting fp state, load the old state and clear exceptions */
3520   __asm__ __volatile__( "fstsw %0"   :   "=m" (result_fpstatus) : );
3521   __asm__ __volatile__( "fnclex" );
3522   __asm__ __volatile__( "fldcw %0"   : : "m"  (old_fpcontrol) );
3523
3524   if (result_fpstatus & 0x9) /* Overflow | Invalid */
3525     return DISP_E_OVERFLOW;
3526 #else
3527   /* This version produces slightly different results for boundary cases */
3528   if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3529     return DISP_E_OVERFLOW;
3530   dblIn *= CY_MULTIPLIER_F;
3531   VARIANT_DutchRound(LONG64, dblIn, pCyOut->int64);
3532 #endif
3533   return S_OK;
3534 }
3535
3536 /************************************************************************
3537  * VarCyFromDate (OLEAUT32.103)
3538  *
3539  * Convert a VT_DATE to a VT_CY.
3540  *
3541  * PARAMS
3542  *  dateIn [I] Source
3543  *  pCyOut [O] Destination
3544  *
3545  * RETURNS
3546  *  Success: S_OK.
3547  *  Failure: E_INVALIDARG, if the source value is invalid
3548  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3549  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3550  */
3551 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
3552 {
3553   return VarCyFromR8(dateIn, pCyOut);
3554 }
3555
3556 /************************************************************************
3557  * VarCyFromStr (OLEAUT32.104)
3558  *
3559  * Convert a VT_BSTR to a VT_CY.
3560  *
3561  * PARAMS
3562  *  strIn   [I] Source
3563  *  lcid    [I] LCID for the conversion
3564  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3565  *  pCyOut  [O] Destination
3566  *
3567  * RETURNS
3568  *  Success: S_OK.
3569  *  Failure: E_INVALIDARG, if the source value is invalid
3570  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3571  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3572  */
3573 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
3574 {
3575   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pCyOut, VT_CY);
3576 }
3577
3578 /************************************************************************
3579  * VarCyFromDisp (OLEAUT32.105)
3580  *
3581  * Convert a VT_DISPATCH to a VT_CY.
3582  *
3583  * PARAMS
3584  *  pdispIn [I] Source
3585  *  lcid    [I] LCID for conversion
3586  *  pCyOut  [O] Destination
3587  *
3588  * RETURNS
3589  *  Success: S_OK.
3590  *  Failure: E_INVALIDARG, if the source value is invalid
3591  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3592  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3593  */
3594 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
3595 {
3596   return VARIANT_FromDisp(pdispIn, lcid, pCyOut, VT_CY, 0);
3597 }
3598
3599 /************************************************************************
3600  * VarCyFromBool (OLEAUT32.106)
3601  *
3602  * Convert a VT_BOOL to a VT_CY.
3603  *
3604  * PARAMS
3605  *  boolIn [I] Source
3606  *  pCyOut [O] Destination
3607  *
3608  * RETURNS
3609  *  Success: S_OK.
3610  *  Failure: E_INVALIDARG, if the source value is invalid
3611  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3612  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3613  *
3614  * NOTES
3615  *  While the sign of the boolean is stored in the currency, the value is
3616  *  converted to either 0 or 1.
3617  */
3618 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
3619 {
3620   return VarCyFromR8(boolIn, pCyOut);
3621 }
3622
3623 /************************************************************************
3624  * VarCyFromI1 (OLEAUT32.225)
3625  *
3626  * Convert a VT_I1 to a VT_CY.
3627  *
3628  * PARAMS
3629  *  cIn    [I] Source
3630  *  pCyOut [O] Destination
3631  *
3632  * RETURNS
3633  *  Success: S_OK.
3634  *  Failure: E_INVALIDARG, if the source value is invalid
3635  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3636  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3637  */
3638 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3639 {
3640   return VarCyFromR8(cIn, pCyOut);
3641 }
3642
3643 /************************************************************************
3644  * VarCyFromUI2 (OLEAUT32.226)
3645  *
3646  * Convert a VT_UI2 to a VT_CY.
3647  *
3648  * PARAMS
3649  *  usIn   [I] Source
3650  *  pCyOut [O] Destination
3651  *
3652  * RETURNS
3653  *  Success: S_OK.
3654  *  Failure: E_INVALIDARG, if the source value is invalid
3655  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3656  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3657  */
3658 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
3659 {
3660   return VarCyFromR8(usIn, pCyOut);
3661 }
3662
3663 /************************************************************************
3664  * VarCyFromUI4 (OLEAUT32.227)
3665  *
3666  * Convert a VT_UI4 to a VT_CY.
3667  *
3668  * PARAMS
3669  *  ulIn   [I] Source
3670  *  pCyOut [O] Destination
3671  *
3672  * RETURNS
3673  *  Success: S_OK.
3674  *  Failure: E_INVALIDARG, if the source value is invalid
3675  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3676  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3677  */
3678 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
3679 {
3680   return VarCyFromR8(ulIn, pCyOut);
3681 }
3682
3683 /************************************************************************
3684  * VarCyFromDec (OLEAUT32.228)
3685  *
3686  * Convert a VT_DECIMAL to a VT_CY.
3687  *
3688  * PARAMS
3689  *  pdecIn  [I] Source
3690  *  pCyOut  [O] Destination
3691  *
3692  * RETURNS
3693  *  Success: S_OK.
3694  *  Failure: E_INVALIDARG, if the source value is invalid
3695  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3696  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3697  */
3698 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
3699 {
3700   DECIMAL rounded;
3701   HRESULT hRet;
3702
3703   hRet = VarDecRound(pdecIn, 4, &rounded);
3704
3705   if (SUCCEEDED(hRet))
3706   {
3707     double d;
3708
3709     if (DEC_HI32(&rounded))
3710       return DISP_E_OVERFLOW;
3711
3712     /* Note: Without the casts this promotes to int64 which loses precision */
3713     d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
3714     if (DEC_SIGN(&rounded))
3715       d = -d;
3716     return VarCyFromR8(d, pCyOut);
3717   }
3718   return hRet;
3719 }
3720
3721 /************************************************************************
3722  * VarCyFromI8 (OLEAUT32.366)
3723  *
3724  * Convert a VT_I8 to a VT_CY.
3725  *
3726  * PARAMS
3727  *  ullIn  [I] Source
3728  *  pCyOut [O] Destination
3729  *
3730  * RETURNS
3731  *  Success: S_OK.
3732  *  Failure: E_INVALIDARG, if the source value is invalid
3733  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3734  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3735  */
3736 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
3737 {
3738   if (llIn <= (I8_MIN/CY_MULTIPLIER) || llIn >= (I8_MAX/CY_MULTIPLIER)) return DISP_E_OVERFLOW;
3739   pCyOut->int64 = llIn * CY_MULTIPLIER;
3740   return S_OK;
3741 }
3742
3743 /************************************************************************
3744  * VarCyFromUI8 (OLEAUT32.375)
3745  *
3746  * Convert a VT_UI8 to a VT_CY.
3747  *
3748  * PARAMS
3749  *  ullIn  [I] Source
3750  *  pCyOut [O] Destination
3751  *
3752  * RETURNS
3753  *  Success: S_OK.
3754  *  Failure: E_INVALIDARG, if the source value is invalid
3755  *           DISP_E_OVERFLOW, if the value will not fit in the destination
3756  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
3757  */
3758 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
3759 {
3760   return VarCyFromR8(ullIn, pCyOut);
3761 }
3762
3763 /************************************************************************
3764  * VarCyAdd (OLEAUT32.299)
3765  *
3766  * Add one CY to another.
3767  *
3768  * PARAMS
3769  *  cyLeft  [I] Source
3770  *  cyRight [I] Value to add
3771  *  pCyOut  [O] Destination
3772  *
3773  * RETURNS
3774  *  Success: S_OK.
3775  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3776  */
3777 HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
3778 {
3779   double l,r;
3780   _VarR8FromCy(cyLeft, &l);
3781   _VarR8FromCy(cyRight, &r);
3782   l = l + r;
3783   return VarCyFromR8(l, pCyOut);
3784 }
3785
3786 /************************************************************************
3787  * VarCyMul (OLEAUT32.303)
3788  *
3789  * Multiply one CY by another.
3790  *
3791  * PARAMS
3792  *  cyLeft  [I] Source
3793  *  cyRight [I] Value to multiply by
3794  *  pCyOut  [O] Destination
3795  *
3796  * RETURNS
3797  *  Success: S_OK.
3798  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3799  */
3800 HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
3801 {
3802   double l,r;
3803   _VarR8FromCy(cyLeft, &l);
3804   _VarR8FromCy(cyRight, &r);
3805   l = l * r;
3806   return VarCyFromR8(l, pCyOut);
3807 }
3808
3809 /************************************************************************
3810  * VarCyMulI4 (OLEAUT32.304)
3811  *
3812  * Multiply one CY by a VT_I4.
3813  *
3814  * PARAMS
3815  *  cyLeft  [I] Source
3816  *  lRight  [I] Value to multiply by
3817  *  pCyOut  [O] Destination
3818  *
3819  * RETURNS
3820  *  Success: S_OK.
3821  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3822  */
3823 HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
3824 {
3825   double d;
3826
3827   _VarR8FromCy(cyLeft, &d);
3828   d = d * lRight;
3829   return VarCyFromR8(d, pCyOut);
3830 }
3831
3832 /************************************************************************
3833  * VarCySub (OLEAUT32.305)
3834  *
3835  * Subtract one CY from another.
3836  *
3837  * PARAMS
3838  *  cyLeft  [I] Source
3839  *  cyRight [I] Value to subtract
3840  *  pCyOut  [O] Destination
3841  *
3842  * RETURNS
3843  *  Success: S_OK.
3844  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3845  */
3846 HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
3847 {
3848   double l,r;
3849   _VarR8FromCy(cyLeft, &l);
3850   _VarR8FromCy(cyRight, &r);
3851   l = l - r;
3852   return VarCyFromR8(l, pCyOut);
3853 }
3854
3855 /************************************************************************
3856  * VarCyAbs (OLEAUT32.306)
3857  *
3858  * Convert a VT_CY into its absolute value.
3859  *
3860  * PARAMS
3861  *  cyIn   [I] Source
3862  *  pCyOut [O] Destination
3863  *
3864  * RETURNS
3865  *  Success: S_OK. pCyOut contains the absolute value.
3866  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3867  */
3868 HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
3869 {
3870   if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3871     return DISP_E_OVERFLOW;
3872
3873   pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3874   return S_OK;
3875 }
3876
3877 /************************************************************************
3878  * VarCyFix (OLEAUT32.307)
3879  *
3880  * Return the integer part of a VT_CY.
3881  *
3882  * PARAMS
3883  *  cyIn   [I] Source
3884  *  pCyOut [O] Destination
3885  *
3886  * RETURNS
3887  *  Success: S_OK.
3888  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3889  *
3890  * NOTES
3891  *  - The difference between this function and VarCyInt() is that VarCyInt() rounds
3892  *    negative numbers away from 0, while this function rounds them towards zero.
3893  */
3894 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
3895 {
3896   pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3897   pCyOut->int64 *= CY_MULTIPLIER;
3898   return S_OK;
3899 }
3900
3901 /************************************************************************
3902  * VarCyInt (OLEAUT32.308)
3903  *
3904  * Return the integer part of a VT_CY.
3905  *
3906  * PARAMS
3907  *  cyIn   [I] Source
3908  *  pCyOut [O] Destination
3909  *
3910  * RETURNS
3911  *  Success: S_OK.
3912  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3913  *
3914  * NOTES
3915  *  - The difference between this function and VarCyFix() is that VarCyFix() rounds
3916  *    negative numbers towards 0, while this function rounds them away from zero.
3917  */
3918 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
3919 {
3920   pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3921   pCyOut->int64 *= CY_MULTIPLIER;
3922
3923   if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3924   {
3925     pCyOut->int64 -= CY_MULTIPLIER;
3926   }
3927   return S_OK;
3928 }
3929
3930 /************************************************************************
3931  * VarCyNeg (OLEAUT32.309)
3932  *
3933  * Change the sign of a VT_CY.
3934  *
3935  * PARAMS
3936  *  cyIn   [I] Source
3937  *  pCyOut [O] Destination
3938  *
3939  * RETURNS
3940  *  Success: S_OK.
3941  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3942  */
3943 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
3944 {
3945   if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3946     return DISP_E_OVERFLOW;
3947
3948   pCyOut->int64 = -cyIn.int64;
3949   return S_OK;
3950 }
3951
3952 /************************************************************************
3953  * VarCyRound (OLEAUT32.310)
3954  *
3955  * Change the precision of a VT_CY.
3956  *
3957  * PARAMS
3958  *  cyIn      [I] Source
3959  *  cDecimals [I] New number of decimals to keep
3960  *  pCyOut    [O] Destination
3961  *
3962  * RETURNS
3963  *  Success: S_OK.
3964  *  Failure: E_INVALIDARG, if cDecimals is less than 0.
3965  */
3966 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
3967 {
3968   if (cDecimals < 0)
3969     return E_INVALIDARG;
3970
3971   if (cDecimals > 3)
3972   {
3973     /* Rounding to more precision than we have */
3974     *pCyOut = cyIn;
3975     return S_OK;
3976   }
3977   else
3978   {
3979     double d, div = CY_Divisors[cDecimals];
3980
3981     _VarR8FromCy(cyIn, &d);
3982     d = d * div;
3983     VARIANT_DutchRound(LONGLONG, d, pCyOut->int64);
3984     d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3985     VARIANT_DutchRound(LONGLONG, d, pCyOut->int64);
3986     return S_OK;
3987   }
3988 }
3989
3990 /************************************************************************
3991  * VarCyCmp (OLEAUT32.311)
3992  *
3993  * Compare two VT_CY values.
3994  *
3995  * PARAMS
3996  *  cyLeft  [I] Source
3997  *  cyRight [I] Value to compare
3998  *
3999  * RETURNS
4000  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
4001  *           compare is less, equal or greater than source respectively.
4002  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4003  */
4004 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
4005 {
4006   HRESULT hRet;
4007   CY result;
4008
4009   /* Subtract right from left, and compare the result to 0 */
4010   hRet = VarCySub(cyLeft, cyRight, &result);
4011
4012   if (SUCCEEDED(hRet))
4013   {
4014     if (result.int64 < 0)
4015       hRet = (HRESULT)VARCMP_LT;
4016     else if (result.int64 > 0)
4017       hRet = (HRESULT)VARCMP_GT;
4018     else
4019       hRet = (HRESULT)VARCMP_EQ;
4020   }
4021   return hRet;
4022 }
4023
4024 /************************************************************************
4025  * VarCyCmpR8 (OLEAUT32.312)
4026  *
4027  * Compare a VT_CY to a double
4028  *
4029  * PARAMS
4030  *  cyLeft   [I] Currency Source
4031  *  dblRight [I] double to compare to cyLeft
4032  *
4033  * RETURNS
4034  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
4035  *           less than, equal to or greater than cyLeft respectively.
4036  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
4037  */
4038 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
4039 {
4040   HRESULT hRet;
4041   CY cyRight;
4042
4043   hRet = VarCyFromR8(dblRight, &cyRight);
4044
4045   if (SUCCEEDED(hRet))
4046     hRet = VarCyCmp(cyLeft, cyRight);
4047
4048   return hRet;
4049 }
4050
4051 /************************************************************************
4052  * VarCyMulI8 (OLEAUT32.329)
4053  *
4054  * Multiply a VT_CY by a VT_I8.
4055  *
4056  * PARAMS
4057  *  cyLeft  [I] Source
4058  *  llRight [I] Value to multiply by
4059  *  pCyOut  [O] Destination
4060  *
4061  * RETURNS
4062  *  Success: S_OK.
4063  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4064  */
4065 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
4066 {
4067   double d;
4068
4069   _VarR8FromCy(cyLeft, &d);
4070   d = d  * (double)llRight;
4071   return VarCyFromR8(d, pCyOut);
4072 }
4073
4074 /* DECIMAL
4075  */
4076
4077 /************************************************************************
4078  * VarDecFromUI1 (OLEAUT32.190)
4079  *
4080  * Convert a VT_UI1 to a DECIMAL.
4081  *
4082  * PARAMS
4083  *  bIn     [I] Source
4084  *  pDecOut [O] Destination
4085  *
4086  * RETURNS
4087  *  S_OK.
4088  */
4089 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
4090 {
4091   return VarDecFromUI4(bIn, pDecOut);
4092 }
4093
4094 /************************************************************************
4095  * VarDecFromI2 (OLEAUT32.191)
4096  *
4097  * Convert a VT_I2 to a DECIMAL.
4098  *
4099  * PARAMS
4100  *  sIn     [I] Source
4101  *  pDecOut [O] Destination
4102  *
4103  * RETURNS
4104  *  S_OK.
4105  */
4106 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
4107 {
4108   return VarDecFromI4(sIn, pDecOut);
4109 }
4110
4111 /************************************************************************
4112  * VarDecFromI4 (OLEAUT32.192)
4113  *
4114  * Convert a VT_I4 to a DECIMAL.
4115  *
4116  * PARAMS
4117  *  sIn     [I] Source
4118  *  pDecOut [O] Destination
4119  *
4120  * RETURNS
4121  *  S_OK.
4122  */
4123 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
4124 {
4125   DEC_HI32(pDecOut) = 0;
4126   DEC_MID32(pDecOut) = 0;
4127
4128   if (lIn < 0)
4129   {
4130     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4131     DEC_LO32(pDecOut) = -lIn;
4132   }
4133   else
4134   {
4135     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4136     DEC_LO32(pDecOut) = lIn;
4137   }
4138   return S_OK;
4139 }
4140
4141 #define LOCALE_EN_US            (MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT))
4142
4143 /* internal representation of the value stored in a DECIMAL. The bytes are
4144    stored from LSB at index 0 to MSB at index 11
4145  */
4146 typedef struct DECIMAL_internal
4147 {
4148     DWORD bitsnum[3];  /* 96 significant bits, unsigned */
4149     unsigned char scale;      /* number scaled * 10 ^ -(scale) */
4150     unsigned int  sign : 1;   /* 0 - positive, 1 - negative */
4151 } VARIANT_DI;
4152
4153 static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI * dest);
4154 static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest);
4155 static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to);
4156 static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to);
4157
4158 /************************************************************************
4159  * VarDecFromR4 (OLEAUT32.193)
4160  *
4161  * Convert a VT_R4 to a DECIMAL.
4162  *
4163  * PARAMS
4164  *  fltIn   [I] Source
4165  *  pDecOut [O] Destination
4166  *
4167  * RETURNS
4168  *  S_OK.
4169  */
4170 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
4171 {
4172   VARIANT_DI di;
4173   HRESULT hres;
4174
4175   hres = VARIANT_DI_FromR4(fltIn, &di);
4176   if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
4177   return hres;
4178 }
4179
4180 /************************************************************************
4181  * VarDecFromR8 (OLEAUT32.194)
4182  *
4183  * Convert a VT_R8 to a DECIMAL.
4184  *
4185  * PARAMS
4186  *  dblIn   [I] Source
4187  *  pDecOut [O] Destination
4188  *
4189  * RETURNS
4190  *  S_OK.
4191  */
4192 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4193 {
4194   VARIANT_DI di;
4195   HRESULT hres;
4196
4197   hres = VARIANT_DI_FromR8(dblIn, &di);
4198   if (hres == S_OK) VARIANT_DecFromDI(&di, pDecOut);
4199   return hres;
4200 }
4201
4202 /************************************************************************
4203  * VarDecFromDate (OLEAUT32.195)
4204  *
4205  * Convert a VT_DATE to a DECIMAL.
4206  *
4207  * PARAMS
4208  *  dateIn  [I] Source
4209  *  pDecOut [O] Destination
4210  *
4211  * RETURNS
4212  *  S_OK.
4213  */
4214 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
4215 {
4216   return VarDecFromR8(dateIn, pDecOut);
4217 }
4218
4219 /************************************************************************
4220  * VarDecFromCy (OLEAUT32.196)
4221  *
4222  * Convert a VT_CY to a DECIMAL.
4223  *
4224  * PARAMS
4225  *  cyIn    [I] Source
4226  *  pDecOut [O] Destination
4227  *
4228  * RETURNS
4229  *  S_OK.
4230  */
4231 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
4232 {
4233   DEC_HI32(pDecOut) = 0;
4234
4235   /* Note: This assumes 2s complement integer representation */
4236   if (cyIn.s.Hi & 0x80000000)
4237   {
4238     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4239     DEC_LO64(pDecOut) = -cyIn.int64;
4240   }
4241   else
4242   {
4243     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4244     DEC_MID32(pDecOut) = cyIn.s.Hi;
4245     DEC_LO32(pDecOut) = cyIn.s.Lo;
4246   }
4247   return S_OK;
4248 }
4249
4250 /************************************************************************
4251  * VarDecFromStr (OLEAUT32.197)
4252  *
4253  * Convert a VT_BSTR to a DECIMAL.
4254  *
4255  * PARAMS
4256  *  strIn   [I] Source
4257  *  lcid    [I] LCID for the conversion
4258  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4259  *  pDecOut [O] Destination
4260  *
4261  * RETURNS
4262  *  Success: S_OK.
4263  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4264  */
4265 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
4266 {
4267   return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDecOut, VT_DECIMAL);
4268 }
4269
4270 /************************************************************************
4271  * VarDecFromDisp (OLEAUT32.198)
4272  *
4273  * Convert a VT_DISPATCH to a DECIMAL.
4274  *
4275  * PARAMS
4276  *  pdispIn  [I] Source
4277  *  lcid     [I] LCID for conversion
4278  *  pDecOut  [O] Destination
4279  *
4280  * RETURNS
4281  *  Success: S_OK.
4282  *  Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4283  */
4284 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
4285 {
4286   return VARIANT_FromDisp(pdispIn, lcid, pDecOut, VT_DECIMAL, 0);
4287 }
4288
4289 /************************************************************************
4290  * VarDecFromBool (OLEAUT32.199)
4291  *
4292  * Convert a VT_BOOL to a DECIMAL.
4293  *
4294  * PARAMS
4295  *  bIn     [I] Source
4296  *  pDecOut [O] Destination
4297  *
4298  * RETURNS
4299  *  S_OK.
4300  *
4301  * NOTES
4302  *  The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4303  */
4304 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
4305 {
4306   DEC_HI32(pDecOut) = 0;
4307   DEC_MID32(pDecOut) = 0;
4308   if (bIn)
4309   {
4310     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4311     DEC_LO32(pDecOut) = 1;
4312   }
4313   else
4314   {
4315     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4316     DEC_LO32(pDecOut) = 0;
4317   }
4318   return S_OK;
4319 }
4320
4321 /************************************************************************
4322  * VarDecFromI1 (OLEAUT32.241)
4323  *
4324  * Convert a VT_I1 to a DECIMAL.
4325  *
4326  * PARAMS
4327  *  cIn     [I] Source
4328  *  pDecOut [O] Destination
4329  *
4330  * RETURNS
4331  *  S_OK.
4332  */
4333 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4334 {
4335   return VarDecFromI4(cIn, pDecOut);
4336 }
4337
4338 /************************************************************************
4339  * VarDecFromUI2 (OLEAUT32.242)
4340  *
4341  * Convert a VT_UI2 to a DECIMAL.
4342  *
4343  * PARAMS
4344  *  usIn    [I] Source
4345  *  pDecOut [O] Destination
4346  *
4347  * RETURNS
4348  *  S_OK.
4349  */
4350 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
4351 {
4352   return VarDecFromUI4(usIn, pDecOut);
4353 }
4354
4355 /************************************************************************
4356  * VarDecFromUI4 (OLEAUT32.243)
4357  *
4358  * Convert a VT_UI4 to a DECIMAL.
4359  *
4360  * PARAMS
4361  *  ulIn    [I] Source
4362  *  pDecOut [O] Destination
4363  *
4364  * RETURNS
4365  *  S_OK.
4366  */
4367 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
4368 {
4369   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4370   DEC_HI32(pDecOut) = 0;
4371   DEC_MID32(pDecOut) = 0;
4372   DEC_LO32(pDecOut) = ulIn;
4373   return S_OK;
4374 }
4375
4376 /************************************************************************
4377  * VarDecFromI8 (OLEAUT32.374)
4378  *
4379  * Convert a VT_I8 to a DECIMAL.
4380  *
4381  * PARAMS
4382  *  llIn    [I] Source
4383  *  pDecOut [O] Destination
4384  *
4385  * RETURNS
4386  *  S_OK.
4387  */
4388 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
4389 {
4390   PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4391
4392   DEC_HI32(pDecOut) = 0;
4393
4394   /* Note: This assumes 2s complement integer representation */
4395   if (pLi->u.HighPart & 0x80000000)
4396   {
4397     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4398     DEC_LO64(pDecOut) = -pLi->QuadPart;
4399   }
4400   else
4401   {
4402     DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4403     DEC_MID32(pDecOut) = pLi->u.HighPart;
4404     DEC_LO32(pDecOut) = pLi->u.LowPart;
4405   }
4406   return S_OK;
4407 }
4408
4409 /************************************************************************
4410  * VarDecFromUI8 (OLEAUT32.375)
4411  *
4412  * Convert a VT_UI8 to a DECIMAL.
4413  *
4414  * PARAMS
4415  *  ullIn   [I] Source
4416  *  pDecOut [O] Destination
4417  *
4418  * RETURNS
4419  *  S_OK.
4420  */
4421 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
4422 {
4423   DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4424   DEC_HI32(pDecOut) = 0;
4425   DEC_LO64(pDecOut) = ullIn;
4426   return S_OK;
4427 }
4428
4429 /* Make two DECIMALS the same scale; used by math functions below */
4430 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4431                                 const DECIMAL** ppDecRight,
4432                                 DECIMAL* pDecOut)
4433 {
4434   static DECIMAL scaleFactor;
4435   DECIMAL decTemp;
4436   int scaleAmount, i;
4437   HRESULT hRet = S_OK;
4438
4439   if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4440     return E_INVALIDARG;
4441
4442   DEC_LO32(&scaleFactor) = 10;
4443
4444   i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4445
4446   if (!scaleAmount)
4447     return S_OK; /* Same scale */
4448
4449   if (scaleAmount > 0)
4450   {
4451     decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4452     *ppDecRight = pDecOut;
4453   }
4454   else
4455   {
4456     decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4457     *ppDecLeft = pDecOut;
4458     i = scaleAmount = -scaleAmount;
4459   }
4460
4461   if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
4462     return DISP_E_OVERFLOW; /* Can't scale up */
4463
4464   /* Multiply up the value to be scaled by the correct amount */
4465   while (SUCCEEDED(hRet) && i--)
4466   {
4467     /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4468     hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
4469     decTemp = *pDecOut;
4470   }
4471   DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
4472   return hRet;
4473 }
4474
4475 /* Add two unsigned 32 bit values with overflow */
4476 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4477 {
4478   ULARGE_INTEGER ul64;
4479
4480   ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4481   *pulHigh = ul64.u.HighPart;
4482   return ul64.u.LowPart;
4483 }
4484
4485 /* Subtract two unsigned 32 bit values with underflow */
4486 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4487 {
4488   int invert = 0;
4489   ULARGE_INTEGER ul64;
4490
4491   ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4492   if (ulLeft < ulRight)
4493     invert = 1;
4494
4495   if (ul64.QuadPart > (ULONG64)*pulHigh)
4496     ul64.QuadPart -= (ULONG64)*pulHigh;
4497   else
4498   {
4499     ul64.QuadPart -= (ULONG64)*pulHigh;
4500     invert = 1;
4501   }
4502   if (invert)
4503     ul64.u.HighPart = -ul64.u.HighPart ;
4504
4505   *pulHigh = ul64.u.HighPart;
4506   return ul64.u.LowPart;
4507 }
4508
4509 /* Multiply two unsigned 32 bit values with overflow */
4510 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4511 {
4512   ULARGE_INTEGER ul64;
4513
4514   ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4515   *pulHigh = ul64.u.HighPart;
4516   return ul64.u.LowPart;
4517 }
4518
4519 /* Compare two decimals that have the same scale */
4520 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4521 {
4522   if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4523       (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4524     return -1;
4525   else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4526     return 0;
4527   return 1;
4528 }
4529
4530 /************************************************************************
4531  * VarDecAdd (OLEAUT32.177)
4532  *
4533  * Add one DECIMAL to another.
4534  *
4535  * PARAMS
4536  *  pDecLeft  [I] Source
4537  *  pDecRight [I] Value to add
4538  *  pDecOut   [O] Destination
4539  *
4540  * RETURNS
4541  *  Success: S_OK.
4542  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4543  */
4544 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4545 {
4546   HRESULT hRet;
4547   DECIMAL scaled;
4548
4549   hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
4550
4551   if (SUCCEEDED(hRet))
4552   {
4553     /* Our decimals now have the same scale, we can add them as 96 bit integers */
4554     ULONG overflow = 0;
4555     BYTE sign = DECIMAL_POS;
4556
4557     /* Correct for the sign of the result */
4558     if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4559     {
4560       /* -x + -y : Negative */
4561       sign = DECIMAL_NEG;
4562       goto VarDecAdd_AsPositive;
4563     }
4564     else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4565     {
4566       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4567
4568       /* -x + y : Negative if x > y */
4569       if (cmp > 0)
4570       {
4571         sign = DECIMAL_NEG;
4572 VarDecAdd_AsNegative:
4573         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
4574         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4575         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
4576       }
4577       else
4578       {
4579 VarDecAdd_AsInvertedNegative:
4580         DEC_LO32(pDecOut)  = VARIANT_Sub(DEC_LO32(pDecRight),  DEC_LO32(pDecLeft),  &overflow);
4581         DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4582         DEC_HI32(pDecOut)  = VARIANT_Sub(DEC_HI32(pDecRight),  DEC_HI32(pDecLeft),  &overflow);
4583       }
4584     }
4585     else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4586     {
4587       int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4588
4589       /* x + -y : Negative if x <= y */
4590       if (cmp <= 0)
4591       {
4592         sign = DECIMAL_NEG;
4593         goto VarDecAdd_AsInvertedNegative;
4594       }
4595       goto VarDecAdd_AsNegative;
4596     }
4597     else
4598     {
4599       /* x + y : Positive */
4600 VarDecAdd_AsPositive:
4601       DEC_LO32(pDecOut)  = VARIANT_Add(DEC_LO32(pDecLeft),  DEC_LO32(pDecRight),  &overflow);
4602       DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4603       DEC_HI32(pDecOut)  = VARIANT_Add(DEC_HI32(pDecLeft),  DEC_HI32(pDecRight),  &overflow);
4604     }
4605
4606     if (overflow)
4607       return DISP_E_OVERFLOW; /* overflowed */
4608
4609     DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4610     DEC_SIGN(pDecOut) = sign;
4611   }
4612   return hRet;
4613 }
4614
4615 /* translate from external DECIMAL format into an internal representation */
4616 static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to)
4617 {
4618     to->scale = DEC_SCALE(from);
4619     to->sign = DEC_SIGN(from) ? 1 : 0;
4620
4621     to->bitsnum[0] = DEC_LO32(from);
4622     to->bitsnum[1] = DEC_MID32(from);
4623     to->bitsnum[2] = DEC_HI32(from);
4624 }
4625
4626 static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to)
4627 {
4628     if (from->sign) {
4629         DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_NEG, from->scale);
4630     } else {
4631         DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_POS, from->scale);
4632     }
4633
4634     DEC_LO32(to) = from->bitsnum[0];
4635     DEC_MID32(to) = from->bitsnum[1];
4636     DEC_HI32(to) = from->bitsnum[2];
4637 }
4638
4639 /* clear an internal representation of a DECIMAL */
4640 static void VARIANT_DI_clear(VARIANT_DI * i)
4641 {
4642     memset(i, 0, sizeof(VARIANT_DI));
4643 }
4644
4645 /* divide the (unsigned) number stored in p (LSB) by a byte value (<= 0xff). Any nonzero
4646    size is supported. The value in p is replaced by the quotient of the division, and
4647    the remainder is returned as a result. This routine is most often used with a divisor
4648    of 10 in order to scale up numbers, and in the DECIMAL->string conversion.
4649  */
4650 static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor)
4651 {
4652     if (divisor == 0) {
4653         /* division by 0 */
4654         return 0xFF;
4655     } else if (divisor == 1) {
4656         /* dividend remains unchanged */
4657         return 0;
4658     } else {
4659         unsigned char remainder = 0;
4660         ULONGLONG iTempDividend;
4661         signed int i;
4662         
4663         for (i = n - 1; i >= 0 && !p[i]; i--);  /* skip leading zeros */
4664         for (; i >= 0; i--) {
4665             iTempDividend = ((ULONGLONG)remainder << 32) + p[i];
4666             remainder = iTempDividend % divisor;
4667             p[i] = iTempDividend / divisor;
4668         }
4669         
4670         return remainder;
4671     }
4672 }
4673
4674 /* check to test if encoded number is a zero. Returns 1 if zero, 0 for nonzero */
4675 static int VARIANT_int_iszero(const DWORD * p, unsigned int n)
4676 {
4677     for (; n > 0; n--) if (*p++ != 0) return 0;
4678     return 1;
4679 }
4680
4681 /* multiply two DECIMALS, without changing either one, and place result in third
4682    parameter. Result is normalized when scale is > 0. Attempts to remove significant
4683    digits when scale > 0 in order to fit an overflowing result. Final overflow
4684    flag is returned.
4685  */
4686 static int VARIANT_DI_mul(const VARIANT_DI * a, const VARIANT_DI * b, VARIANT_DI * result)
4687 {
4688     int r_overflow = 0;
4689     DWORD running[6];
4690     signed int mulstart;
4691
4692     VARIANT_DI_clear(result);
4693     result->sign = (a->sign ^ b->sign) ? 1 : 0;
4694
4695     /* Multiply 128-bit operands into a (max) 256-bit result. The scale
4696        of the result is formed by adding the scales of the operands.
4697      */
4698     result->scale = a->scale + b->scale;
4699     memset(running, 0, sizeof(running));
4700
4701     /* count number of leading zero-bytes in operand A */
4702     for (mulstart = sizeof(a->bitsnum)/sizeof(DWORD) - 1; mulstart >= 0 && !a->bitsnum[mulstart]; mulstart--);
4703     if (mulstart < 0) {
4704         /* result is 0, because operand A is 0 */
4705         result->scale = 0;
4706         result->sign = 0;
4707     } else {
4708         unsigned char remainder = 0;
4709         int iA;        
4710
4711         /* perform actual multiplication */
4712         for (iA = 0; iA <= mulstart; iA++) {
4713             ULONG iOverflowMul;
4714             int iB;
4715             
4716             for (iOverflowMul = 0, iB = 0; iB < sizeof(b->bitsnum)/sizeof(DWORD); iB++) {
4717                 ULONG iRV;
4718                 int iR;
4719                 
4720                 iRV = VARIANT_Mul(b->bitsnum[iB], a->bitsnum[iA], &iOverflowMul);
4721                 iR = iA + iB;
4722                 do {
4723                     running[iR] = VARIANT_Add(running[iR], 0, &iRV);
4724                     iR++;
4725                 } while (iRV);
4726             }
4727         }
4728
4729 /* Too bad - native oleaut does not do this, so we should not either */
4730 #if 0
4731         /* While the result is divisible by 10, and the scale > 0, divide by 10.
4732            This operation should not lose significant digits, and gives an
4733            opportunity to reduce the possibility of overflows in future
4734            operations issued by the application.
4735          */
4736         while (result->scale > 0) {
4737             memcpy(quotient, running, sizeof(quotient));
4738             remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
4739             if (remainder > 0) break;
4740             memcpy(running, quotient, sizeof(quotient));
4741             result->scale--;
4742         }
4743 #endif
4744         /* While the 256-bit result overflows, and the scale > 0, divide by 10.
4745            This operation *will* lose significant digits of the result because
4746            all the factors of 10 were consumed by the previous operation.
4747         */
4748         while (result->scale > 0 && !VARIANT_int_iszero(
4749             running + sizeof(result->bitsnum) / sizeof(DWORD),
4750             (sizeof(running) - sizeof(result->bitsnum)) / sizeof(DWORD))) {
4751             
4752             remainder = VARIANT_int_divbychar(running, sizeof(running) / sizeof(DWORD), 10);
4753             if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder);
4754             result->scale--;
4755         }
4756         
4757         /* round up the result - native oleaut32 does this */
4758         if (remainder >= 5) {
4759             unsigned int i;
4760             for (remainder = 1, i = 0; i < sizeof(running)/sizeof(DWORD) && remainder; i++) {
4761                 ULONGLONG digit = running[i] + 1;
4762                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
4763                 running[i] = digit & 0xFFFFFFFF;
4764             }
4765         }
4766
4767         /* Signal overflow if scale == 0 and 256-bit result still overflows,
4768            and copy result bits into result structure
4769         */
4770         r_overflow = !VARIANT_int_iszero(
4771             running + sizeof(result->bitsnum)/sizeof(DWORD), 
4772             (sizeof(running) - sizeof(result->bitsnum))/sizeof(DWORD));
4773         memcpy(result->bitsnum, running, sizeof(result->bitsnum));
4774     }
4775     return r_overflow;
4776 }
4777
4778 /* cast DECIMAL into string. Any scale should be handled properly. en_US locale is
4779    hardcoded (period for decimal separator, dash as negative sign). Returns 0 for
4780    success, nonzero if insufficient space in output buffer.
4781  */
4782 static int VARIANT_DI_tostringW(const VARIANT_DI * a, WCHAR * s, unsigned int n)
4783 {
4784     int overflow = 0;
4785     DWORD quotient[3];
4786     unsigned char remainder;
4787     unsigned int i;
4788
4789     /* place negative sign */
4790     if (!VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD)) && a->sign) {
4791         if (n > 0) {
4792             *s++ = '-';
4793             n--;
4794         }
4795         else overflow = 1;
4796     }
4797
4798     /* prepare initial 0 */
4799     if (!overflow) {
4800         if (n >= 2) {
4801             s[0] = '0';
4802             s[1] = '\0';
4803         } else overflow = 1;
4804     }
4805
4806     i = 0;
4807     memcpy(quotient, a->bitsnum, sizeof(a->bitsnum));
4808     while (!overflow && !VARIANT_int_iszero(quotient, sizeof(quotient) / sizeof(DWORD))) {
4809         remainder = VARIANT_int_divbychar(quotient, sizeof(quotient) / sizeof(DWORD), 10);
4810         if (i + 2 > n) {
4811             overflow = 1;
4812         } else {
4813             s[i++] = '0' + remainder;
4814             s[i] = '\0';
4815         }
4816     }
4817
4818     if (!overflow && !VARIANT_int_iszero(a->bitsnum, sizeof(a->bitsnum) / sizeof(DWORD))) {
4819
4820         /* reverse order of digits */
4821         WCHAR * x = s; WCHAR * y = s + i - 1;
4822         while (x < y) {
4823             *x ^= *y;
4824             *y ^= *x;
4825             *x++ ^= *y--;
4826         }
4827
4828         /* check for decimal point. "i" now has string length */
4829         if (i <= a->scale) {
4830             unsigned int numzeroes = a->scale + 1 - i;
4831             if (i + 1 + numzeroes >= n) {
4832                 overflow = 1;
4833             } else {
4834                 memmove(s + numzeroes, s, (i + 1) * sizeof(WCHAR));
4835                 i += numzeroes;
4836                 while (numzeroes > 0) {
4837                     s[--numzeroes] = '0';
4838                 }
4839             }
4840         }
4841
4842         /* place decimal point */
4843         if (a->scale > 0) {
4844             unsigned int periodpos = i - a->scale;
4845             if (i + 2 >= n) {
4846                 overflow = 1;
4847             } else {
4848                 memmove(s + periodpos + 1, s + periodpos, (i + 1 - periodpos) * sizeof(WCHAR));
4849                 s[periodpos] = '.'; i++;
4850                 
4851                 /* remove extra zeros at the end, if any */
4852                 while (s[i - 1] == '0') s[--i] = '\0';
4853                 if (s[i - 1] == '.') s[--i] = '\0';
4854             }
4855         }
4856     }
4857
4858     return overflow;
4859 }
4860
4861 /* shift the bits of a DWORD array to the left. p[0] is assumed LSB */
4862 static void VARIANT_int_shiftleft(DWORD * p, unsigned int n, unsigned int shift)
4863 {
4864     DWORD shifted;
4865     unsigned int i;
4866     
4867     /* shift whole DWORDs to the left */
4868     while (shift >= 32)
4869     {
4870         memmove(p + 1, p, (n - 1) * sizeof(DWORD));
4871         *p = 0; shift -= 32;
4872     }
4873     
4874     /* shift remainder (1..31 bits) */
4875     shifted = 0;
4876     if (shift > 0) for (i = 0; i < n; i++)
4877     {
4878         DWORD b;
4879         b = p[i] >> (32 - shift);
4880         p[i] = (p[i] << shift) | shifted;
4881         shifted = b;
4882     }
4883 }
4884
4885 /* add the (unsigned) numbers stored in two DWORD arrays with LSB at index 0.
4886    Value at v is incremented by the value at p. Any size is supported, provided
4887    that v is not shorter than p. Any unapplied carry is returned as a result.
4888  */
4889 static unsigned char VARIANT_int_add(DWORD * v, unsigned int nv, const DWORD * p,
4890     unsigned int np)
4891 {
4892     unsigned char carry = 0;
4893
4894     if (nv >= np) {
4895         ULONGLONG sum;
4896         unsigned int i;
4897
4898         for (i = 0; i < np; i++) {
4899             sum = (ULONGLONG)v[i]
4900                 + (ULONGLONG)p[i]
4901                 + (ULONGLONG)carry;
4902             v[i] = sum & 0xffffffff;
4903             carry = sum >> 32;
4904         }
4905         for (; i < nv && carry; i++) {
4906             sum = (ULONGLONG)v[i]
4907                 + (ULONGLONG)carry;
4908             v[i] = sum & 0xffffffff;
4909             carry = sum >> 32;
4910         }
4911     }
4912     return carry;
4913 }
4914
4915 /* perform integral division with operand p as dividend. Parameter n indicates 
4916    number of available DWORDs in divisor p, but available space in p must be 
4917    actually at least 2 * n DWORDs, because the remainder of the integral 
4918    division is built in the next n DWORDs past the start of the quotient. This 
4919    routine replaces the dividend in p with the quotient, and appends n 
4920    additional DWORDs for the remainder.
4921
4922    Thanks to Lee & Mark Atkinson for their book _Using_C_ (my very first book on
4923    C/C++ :-) where the "longhand binary division" algorithm was exposed for the
4924    source code to the VLI (Very Large Integer) division operator. This algorithm
4925    was then heavily modified by me (Alex Villacis Lasso) in order to handle
4926    variably-scaled integers such as the MS DECIMAL representation.
4927  */
4928 static void VARIANT_int_div(DWORD * p, unsigned int n, const DWORD * divisor,
4929     unsigned int dn)
4930 {
4931     unsigned int i;
4932     DWORD tempsub[8];
4933     DWORD * negdivisor = tempsub + n;
4934
4935     /* build 2s-complement of divisor */
4936     for (i = 0; i < n; i++) negdivisor[i] = (i < dn) ? ~divisor[i] : 0xFFFFFFFF;
4937     p[n] = 1;
4938     VARIANT_int_add(negdivisor, n, p + n, 1);
4939     memset(p + n, 0, n * sizeof(DWORD));
4940
4941     /* skip all leading zero DWORDs in quotient */
4942     for (i = 0; i < n && !p[n - 1]; i++) VARIANT_int_shiftleft(p, n, 32);
4943     /* i is now number of DWORDs left to process */
4944     for (i <<= 5; i < (n << 5); i++) {
4945         VARIANT_int_shiftleft(p, n << 1, 1);    /* shl quotient+remainder */
4946
4947         /* trial subtraction */
4948         memcpy(tempsub, p + n, n * sizeof(DWORD));
4949         VARIANT_int_add(tempsub, n, negdivisor, n);
4950
4951         /* check whether result of subtraction was negative */
4952         if ((tempsub[n - 1] & 0x80000000) == 0) {
4953             memcpy(p + n, tempsub, n * sizeof(DWORD));
4954             p[0] |= 1;
4955         }
4956     }
4957 }
4958
4959 /* perform integral multiplication by a byte operand. Used for scaling by 10 */
4960 static unsigned char VARIANT_int_mulbychar(DWORD * p, unsigned int n, unsigned char m)
4961 {
4962     unsigned int i;
4963     ULONG iOverflowMul;
4964     
4965     for (iOverflowMul = 0, i = 0; i < n; i++)
4966         p[i] = VARIANT_Mul(p[i], m, &iOverflowMul);
4967     return (unsigned char)iOverflowMul;
4968 }
4969
4970 /* increment value in A by the value indicated in B, with scale adjusting. 
4971    Modifies parameters by adjusting scales. Returns 0 if addition was 
4972    successful, nonzero if a parameter underflowed before it could be 
4973    successfully used in the addition.
4974  */
4975 static int VARIANT_int_addlossy(
4976     DWORD * a, int * ascale, unsigned int an,
4977     DWORD * b, int * bscale, unsigned int bn)
4978 {
4979     int underflow = 0;
4980
4981     if (VARIANT_int_iszero(a, an)) {
4982         /* if A is zero, copy B into A, after removing digits */
4983         while (bn > an && !VARIANT_int_iszero(b + an, bn - an)) {
4984             VARIANT_int_divbychar(b, bn, 10);
4985             (*bscale)--;
4986         }
4987         memcpy(a, b, an * sizeof(DWORD));
4988         *ascale = *bscale;
4989     } else if (!VARIANT_int_iszero(b, bn)) {
4990         unsigned int tn = an + 1;
4991         DWORD t[5];
4992
4993         if (bn + 1 > tn) tn = bn + 1;
4994         if (*ascale != *bscale) {
4995             /* first (optimistic) try - try to scale down the one with the bigger
4996                scale, while this number is divisible by 10 */
4997             DWORD * digitchosen;
4998             unsigned int nchosen;
4999             int * scalechosen;
5000             int targetscale;
5001
5002             if (*ascale < *bscale) {
5003                 targetscale = *ascale;
5004                 scalechosen = bscale;
5005                 digitchosen = b;
5006                 nchosen = bn;
5007             } else {
5008                 targetscale = *bscale;
5009                 scalechosen = ascale;
5010                 digitchosen = a;
5011                 nchosen = an;
5012             }
5013             memset(t, 0, tn * sizeof(DWORD));
5014             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5015
5016             /* divide by 10 until target scale is reached */
5017             while (*scalechosen > targetscale) {
5018                 unsigned char remainder = VARIANT_int_divbychar(t, tn, 10);
5019                 if (!remainder) {
5020                     (*scalechosen)--;
5021                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5022                 } else break;
5023             }
5024         }
5025
5026         if (*ascale != *bscale) {
5027             DWORD * digitchosen;
5028             unsigned int nchosen;
5029             int * scalechosen;
5030             int targetscale;
5031
5032             /* try to scale up the one with the smaller scale */
5033             if (*ascale > *bscale) {
5034                 targetscale = *ascale;
5035                 scalechosen = bscale;
5036                 digitchosen = b;
5037                 nchosen = bn;
5038             } else {
5039                 targetscale = *bscale;
5040                 scalechosen = ascale;
5041                 digitchosen = a;
5042                 nchosen = an;
5043             }
5044             memset(t, 0, tn * sizeof(DWORD));
5045             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5046
5047             /* multiply by 10 until target scale is reached, or
5048                significant bytes overflow the number
5049              */
5050             while (*scalechosen < targetscale && t[nchosen] == 0) {
5051                 VARIANT_int_mulbychar(t, tn, 10);
5052                 if (t[nchosen] == 0) {
5053                     /* still does not overflow */
5054                     (*scalechosen)++;
5055                     memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5056                 }
5057             }
5058         }
5059
5060         if (*ascale != *bscale) {
5061             /* still different? try to scale down the one with the bigger scale
5062                (this *will* lose significant digits) */
5063             DWORD * digitchosen;
5064             unsigned int nchosen;
5065             int * scalechosen;
5066             int targetscale;
5067
5068             if (*ascale < *bscale) {
5069                 targetscale = *ascale;
5070                 scalechosen = bscale;
5071                 digitchosen = b;
5072                 nchosen = bn;
5073             } else {
5074                 targetscale = *bscale;
5075                 scalechosen = ascale;
5076                 digitchosen = a;
5077                 nchosen = an;
5078             }
5079             memset(t, 0, tn * sizeof(DWORD));
5080             memcpy(t, digitchosen, nchosen * sizeof(DWORD));
5081
5082             /* divide by 10 until target scale is reached */
5083             while (*scalechosen > targetscale) {
5084                 VARIANT_int_divbychar(t, tn, 10);
5085                 (*scalechosen)--;
5086                 memcpy(digitchosen, t, nchosen * sizeof(DWORD));
5087             }
5088         }
5089
5090         /* check whether any of the operands still has significant digits
5091            (underflow case 1)
5092          */
5093         if (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn)) {
5094             underflow = 1;
5095         } else {
5096             /* at this step, both numbers have the same scale and can be added
5097                as integers. However, the result might not fit in A, so further
5098                scaling down might be necessary.
5099              */
5100             while (!underflow) {
5101                 memset(t, 0, tn * sizeof(DWORD));
5102                 memcpy(t, a, an * sizeof(DWORD));
5103
5104                 VARIANT_int_add(t, tn, b, bn);
5105                 if (VARIANT_int_iszero(t + an, tn - an)) {
5106                     /* addition was successful */
5107                     memcpy(a, t, an * sizeof(DWORD));
5108                     break;
5109                 } else {
5110                     /* addition overflowed - remove significant digits
5111                        from both operands and try again */
5112                     VARIANT_int_divbychar(a, an, 10); (*ascale)--;
5113                     VARIANT_int_divbychar(b, bn, 10); (*bscale)--;
5114                     /* check whether any operand keeps significant digits after
5115                        scaledown (underflow case 2)
5116                      */
5117                     underflow = (VARIANT_int_iszero(a, an) || VARIANT_int_iszero(b, bn));
5118                 }
5119             }
5120         }
5121     }
5122     return underflow;
5123 }
5124
5125 /* perform complete DECIMAL division in the internal representation. Returns
5126    0 if the division was completed (even if quotient is set to 0), or nonzero
5127    in case of quotient overflow.
5128  */
5129 static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * divisor,
5130                               VARIANT_DI * quotient)
5131 {
5132     HRESULT r_overflow = S_OK;
5133
5134     if (VARIANT_int_iszero(divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD))) {
5135         /* division by 0 */
5136         r_overflow = DISP_E_DIVBYZERO;
5137     } else if (VARIANT_int_iszero(dividend->bitsnum, sizeof(dividend->bitsnum)/sizeof(DWORD))) {
5138         VARIANT_DI_clear(quotient);
5139     } else {
5140         int quotientscale, remainderscale, tempquotientscale;
5141         DWORD remainderplusquotient[8];
5142         int underflow;
5143
5144         quotientscale = remainderscale = (int)dividend->scale - (int)divisor->scale;
5145         tempquotientscale = quotientscale;
5146         VARIANT_DI_clear(quotient);
5147         quotient->sign = (dividend->sign ^ divisor->sign) ? 1 : 0;
5148
5149         /*  The following strategy is used for division
5150             1) if there was a nonzero remainder from previous iteration, use it as
5151                dividend for this iteration, else (for first iteration) use intended
5152                dividend
5153             2) perform integer division in temporary buffer, develop quotient in
5154                low-order part, remainder in high-order part
5155             3) add quotient from step 2 to final result, with possible loss of
5156                significant digits
5157             4) multiply integer part of remainder by 10, while incrementing the
5158                scale of the remainder. This operation preserves the intended value
5159                of the remainder.
5160             5) loop to step 1 until one of the following is true:
5161                 a) remainder is zero (exact division achieved)
5162                 b) addition in step 3 fails to modify bits in quotient (remainder underflow)
5163          */
5164         memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5165         memcpy(remainderplusquotient, dividend->bitsnum, sizeof(dividend->bitsnum));
5166         do {
5167             VARIANT_int_div(
5168                 remainderplusquotient, 4,
5169                 divisor->bitsnum, sizeof(divisor->bitsnum)/sizeof(DWORD));
5170             underflow = VARIANT_int_addlossy(
5171                 quotient->bitsnum, &quotientscale, sizeof(quotient->bitsnum) / sizeof(DWORD),
5172                 remainderplusquotient, &tempquotientscale, 4);
5173             VARIANT_int_mulbychar(remainderplusquotient + 4, 4, 10);
5174             memcpy(remainderplusquotient, remainderplusquotient + 4, 4 * sizeof(DWORD));
5175             tempquotientscale = ++remainderscale;
5176         } while (!underflow && !VARIANT_int_iszero(remainderplusquotient + 4, 4));
5177
5178         /* quotient scale might now be negative (extremely big number). If, so, try
5179            to multiply quotient by 10 (without overflowing), while adjusting the scale,
5180            until scale is 0. If this cannot be done, it is a real overflow.
5181          */
5182         while (r_overflow == S_OK && quotientscale < 0) {
5183             memset(remainderplusquotient, 0, sizeof(remainderplusquotient));
5184             memcpy(remainderplusquotient, quotient->bitsnum, sizeof(quotient->bitsnum));
5185             VARIANT_int_mulbychar(remainderplusquotient, sizeof(remainderplusquotient)/sizeof(DWORD), 10);
5186             if (VARIANT_int_iszero(remainderplusquotient + sizeof(quotient->bitsnum)/sizeof(DWORD),
5187                 (sizeof(remainderplusquotient) - sizeof(quotient->bitsnum))/sizeof(DWORD))) {
5188                 quotientscale++;
5189                 memcpy(quotient->bitsnum, remainderplusquotient, sizeof(quotient->bitsnum));
5190             } else r_overflow = DISP_E_OVERFLOW;
5191         }
5192         if (r_overflow == S_OK) {
5193             if (quotientscale <= 255) quotient->scale = quotientscale;
5194             else VARIANT_DI_clear(quotient);
5195         }
5196     }
5197     return r_overflow;
5198 }
5199
5200 /* This procedure receives a VARIANT_DI with a defined mantissa and sign, but
5201    with an undefined scale, which will be assigned to (if possible). It also
5202    receives an exponent of 2. This procedure will then manipulate the mantissa
5203    and calculate a corresponding scale, so that the exponent2 value is assimilated
5204    into the VARIANT_DI and is therefore no longer necessary. Returns S_OK if
5205    successful, or DISP_E_OVERFLOW if the represented value is too big to fit into
5206    a DECIMAL. */
5207 static HRESULT VARIANT_DI_normalize(VARIANT_DI * val, int exponent2, int isDouble)
5208 {
5209     HRESULT hres = S_OK;
5210     int exponent5, exponent10;
5211
5212     /* A factor of 2^exponent2 is equivalent to (10^exponent2)/(5^exponent2), and
5213        thus equal to (5^-exponent2)*(10^exponent2). After all manipulations,
5214        exponent10 might be used to set the VARIANT_DI scale directly. However,
5215        the value of 5^-exponent5 must be assimilated into the VARIANT_DI. */
5216     exponent5 = -exponent2;
5217     exponent10 = exponent2;
5218
5219     /* Handle exponent5 > 0 */
5220     while (exponent5 > 0) {
5221         char bPrevCarryBit;
5222         char bCurrCarryBit;
5223
5224         /* In order to multiply the value represented by the VARIANT_DI by 5, it
5225            is best to multiply by 10/2. Therefore, exponent10 is incremented, and
5226            somehow the mantissa should be divided by 2.  */
5227         if ((val->bitsnum[0] & 1) == 0) {
5228             /* The mantissa is divisible by 2. Therefore the division can be done
5229                without losing significant digits. */
5230             exponent10++; exponent5--;
5231
5232             /* Shift right */
5233             bPrevCarryBit = val->bitsnum[2] & 1;
5234             val->bitsnum[2] >>= 1;
5235             bCurrCarryBit = val->bitsnum[1] & 1;
5236             val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
5237             val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
5238         } else {
5239             /* The mantissa is NOT divisible by 2. Therefore the mantissa should
5240                be multiplied by 5, unless the multiplication overflows. */
5241             DWORD temp_bitsnum[3];
5242
5243             exponent5--;
5244
5245             memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5246             if (0 == VARIANT_int_mulbychar(temp_bitsnum, 3, 5)) {
5247                 /* Multiplication succeeded without overflow, so copy result back
5248                    into VARIANT_DI */
5249                 memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5250
5251                 /* Mask out 3 extraneous bits introduced by the multiply */
5252             } else {
5253                 /* Multiplication by 5 overflows. The mantissa should be divided
5254                    by 2, and therefore will lose significant digits. */
5255                 exponent10++;
5256
5257                 /* Shift right */
5258                 bPrevCarryBit = val->bitsnum[2] & 1;
5259                 val->bitsnum[2] >>= 1;
5260                 bCurrCarryBit = val->bitsnum[1] & 1;
5261                 val->bitsnum[1] = (val->bitsnum[1] >> 1) | (bPrevCarryBit ? 0x80000000 : 0);
5262                 val->bitsnum[0] = (val->bitsnum[0] >> 1) | (bCurrCarryBit ? 0x80000000 : 0);
5263             }
5264         }
5265     }
5266
5267     /* Handle exponent5 < 0 */
5268     while (exponent5 < 0) {
5269         /* In order to divide the value represented by the VARIANT_DI by 5, it
5270            is best to multiply by 2/10. Therefore, exponent10 is decremented,
5271            and the mantissa should be multiplied by 2 */
5272         if ((val->bitsnum[2] & 0x80000000) == 0) {
5273             /* The mantissa can withstand a shift-left without overflowing */
5274             exponent10--; exponent5++;
5275             VARIANT_int_shiftleft(val->bitsnum, 3, 1);
5276         } else {
5277             /* The mantissa would overflow if shifted. Therefore it should be
5278                directly divided by 5. This will lose significant digits, unless
5279                by chance the mantissa happens to be divisible by 5 */
5280             exponent5++;
5281             VARIANT_int_divbychar(val->bitsnum, 3, 5);
5282         }
5283     }
5284
5285     /* At this point, the mantissa has assimilated the exponent5, but the
5286        exponent10 might not be suitable for assignment. The exponent10 must be
5287        in the range [-DEC_MAX_SCALE..0], so the mantissa must be scaled up or
5288        down appropriately. */
5289     while (hres == S_OK && exponent10 > 0) {
5290         /* In order to bring exponent10 down to 0, the mantissa should be
5291            multiplied by 10 to compensate. If the exponent10 is too big, this
5292            will cause the mantissa to overflow. */
5293         if (0 == VARIANT_int_mulbychar(val->bitsnum, 3, 10)) {
5294             exponent10--;
5295         } else {
5296             hres = DISP_E_OVERFLOW;
5297         }
5298     }
5299     while (exponent10 < -DEC_MAX_SCALE) {
5300         int rem10;
5301         /* In order to bring exponent up to -DEC_MAX_SCALE, the mantissa should
5302            be divided by 10 to compensate. If the exponent10 is too small, this
5303            will cause the mantissa to underflow and become 0 */
5304         rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5305         exponent10++;
5306         if (VARIANT_int_iszero(val->bitsnum, 3)) {
5307             /* Underflow, unable to keep dividing */
5308             exponent10 = 0;
5309         } else if (rem10 >= 5) {
5310             DWORD x = 1;
5311             VARIANT_int_add(val->bitsnum, 3, &x, 1);
5312         }
5313     }
5314     /* This step is required in order to remove excess bits of precision from the
5315        end of the bit representation, down to the precision guaranteed by the
5316        floating point number. */
5317     if (isDouble) {
5318         while (exponent10 < 0 && (val->bitsnum[2] != 0 || (val->bitsnum[2] == 0 && (val->bitsnum[1] & 0xFFE00000) != 0))) {
5319             int rem10;
5320
5321             rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5322             exponent10++;
5323             if (rem10 >= 5) {
5324                 DWORD x = 1;
5325                 VARIANT_int_add(val->bitsnum, 3, &x, 1);
5326             }
5327         }
5328     } else {
5329         while (exponent10 < 0 && (val->bitsnum[2] != 0 || val->bitsnum[1] != 0 ||
5330             (val->bitsnum[2] == 0 && val->bitsnum[1] == 0 && (val->bitsnum[0] & 0xFF000000) != 0))) {
5331             int rem10;
5332
5333             rem10 = VARIANT_int_divbychar(val->bitsnum, 3, 10);
5334             exponent10++;
5335             if (rem10 >= 5) {
5336                 DWORD x = 1;
5337                 VARIANT_int_add(val->bitsnum, 3, &x, 1);
5338             }
5339         }
5340     }
5341     /* Remove multiples of 10 from the representation */
5342     while (exponent10 < 0) {
5343         DWORD temp_bitsnum[3];
5344
5345         memcpy(temp_bitsnum, val->bitsnum, 3 * sizeof(DWORD));
5346         if (0 == VARIANT_int_divbychar(temp_bitsnum, 3, 10)) {
5347             exponent10++;
5348             memcpy(val->bitsnum, temp_bitsnum, 3 * sizeof(DWORD));
5349         } else break;
5350     }
5351
5352     /* Scale assignment */
5353     if (hres == S_OK) val->scale = -exponent10;
5354
5355     return hres;
5356 }
5357
5358 typedef union
5359 {
5360     struct
5361     {
5362         unsigned long m : 23;
5363         unsigned int exp_bias : 8;
5364         unsigned int sign : 1;
5365     } i;
5366     float f;
5367 } R4_FIELDS;
5368
5369 /* Convert a 32-bit floating point number into a DECIMAL, without using an
5370    intermediate string step. */
5371 static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI * dest)
5372 {
5373     HRESULT hres = S_OK;
5374     R4_FIELDS fx;
5375
5376     fx.f = source;
5377
5378     /* Detect special cases */
5379     if (fx.i.m == 0 && fx.i.exp_bias == 0) {
5380         /* Floating-point zero */
5381         VARIANT_DI_clear(dest);
5382     } else if (fx.i.m == 0  && fx.i.exp_bias == 0xFF) {
5383         /* Floating-point infinity */
5384         hres = DISP_E_OVERFLOW;
5385     } else if (fx.i.exp_bias == 0xFF) {
5386         /* Floating-point NaN */
5387         hres = DISP_E_BADVARTYPE;
5388     } else {
5389         int exponent2;
5390         VARIANT_DI_clear(dest);
5391
5392         exponent2 = fx.i.exp_bias - 127;   /* Get unbiased exponent */
5393         dest->sign = fx.i.sign;             /* Sign is simply copied */
5394
5395         /* Copy significant bits to VARIANT_DI mantissa */
5396         dest->bitsnum[0] = fx.i.m;
5397         dest->bitsnum[0] &= 0x007FFFFF;
5398         if (fx.i.exp_bias == 0) {
5399             /* Denormalized number - correct exponent */
5400             exponent2++;
5401         } else {
5402             /* Add hidden bit to mantissa */
5403             dest->bitsnum[0] |= 0x00800000;
5404         }
5405
5406         /* The act of copying a FP mantissa as integer bits is equivalent to
5407            shifting left the mantissa 23 bits. The exponent2 is reduced to
5408            compensate. */
5409         exponent2 -= 23;
5410
5411         hres = VARIANT_DI_normalize(dest, exponent2, 0);
5412     }
5413
5414     return hres;
5415 }
5416
5417 typedef union
5418 {
5419     struct
5420     {
5421         unsigned long m_lo : 32;    /* 52 bits of precision */
5422         unsigned int m_hi : 20;
5423         unsigned int exp_bias : 11; /* bias == 1023 */
5424         unsigned int sign : 1;
5425     } i;
5426     double d;
5427 } R8_FIELDS;
5428
5429 /* Convert a 64-bit floating point number into a DECIMAL, without using an
5430    intermediate string step. */
5431 static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest)
5432 {
5433     HRESULT hres = S_OK;
5434     R8_FIELDS fx;
5435
5436     fx.d = source;
5437
5438     /* Detect special cases */
5439     if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0) {
5440         /* Floating-point zero */
5441         VARIANT_DI_clear(dest);
5442     } else if (fx.i.m_lo == 0 && fx.i.m_hi == 0 && fx.i.exp_bias == 0x7FF) {
5443         /* Floating-point infinity */
5444         hres = DISP_E_OVERFLOW;
5445     } else if (fx.i.exp_bias == 0x7FF) {
5446         /* Floating-point NaN */
5447         hres = DISP_E_BADVARTYPE;
5448     } else {
5449         int exponent2;
5450         VARIANT_DI_clear(dest);
5451
5452         exponent2 = fx.i.exp_bias - 1023;   /* Get unbiased exponent */
5453         dest->sign = fx.i.sign;             /* Sign is simply copied */
5454
5455         /* Copy significant bits to VARIANT_DI mantissa */
5456         dest->bitsnum[0] = fx.i.m_lo;
5457         dest->bitsnum[1] = fx.i.m_hi;
5458         dest->bitsnum[1] &= 0x000FFFFF;
5459         if (fx.i.exp_bias == 0) {
5460             /* Denormalized number - correct exponent */
5461             exponent2++;
5462         } else {
5463             /* Add hidden bit to mantissa */
5464             dest->bitsnum[1] |= 0x00100000;
5465         }
5466
5467         /* The act of copying a FP mantissa as integer bits is equivalent to
5468            shifting left the mantissa 52 bits. The exponent2 is reduced to
5469            compensate. */
5470         exponent2 -= 52;
5471
5472         hres = VARIANT_DI_normalize(dest, exponent2, 1);
5473     }
5474
5475     return hres;
5476 }
5477
5478 /************************************************************************
5479  * VarDecDiv (OLEAUT32.178)
5480  *
5481  * Divide one DECIMAL by another.
5482  *
5483  * PARAMS
5484  *  pDecLeft  [I] Source
5485  *  pDecRight [I] Value to divide by
5486  *  pDecOut   [O] Destination
5487  *
5488  * RETURNS
5489  *  Success: S_OK.
5490  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5491  */
5492 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5493 {
5494   HRESULT hRet = S_OK;
5495   VARIANT_DI di_left, di_right, di_result;
5496   HRESULT divresult;
5497
5498   if (!pDecLeft || !pDecRight || !pDecOut) return E_INVALIDARG;
5499
5500   VARIANT_DIFromDec(pDecLeft, &di_left);
5501   VARIANT_DIFromDec(pDecRight, &di_right);
5502   divresult = VARIANT_DI_div(&di_left, &di_right, &di_result);
5503   if (divresult != S_OK)
5504   {
5505       /* division actually overflowed */
5506       hRet = divresult;
5507   }
5508   else
5509   {
5510       hRet = S_OK;
5511
5512       if (di_result.scale > DEC_MAX_SCALE)
5513       {
5514         unsigned char remainder = 0;
5515       
5516         /* division underflowed. In order to comply with the MSDN
5517            specifications for DECIMAL ranges, some significant digits
5518            must be removed
5519          */
5520         WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5521             di_result.scale);
5522         while (di_result.scale > DEC_MAX_SCALE && 
5523                !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD)))
5524         {
5525             remainder = VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum) / sizeof(DWORD), 10);
5526             di_result.scale--;
5527         }
5528         if (di_result.scale > DEC_MAX_SCALE)
5529         {
5530             WARN("result underflowed, setting to 0\n");
5531             di_result.scale = 0;
5532             di_result.sign = 0;
5533         }
5534         else if (remainder >= 5)    /* round up result - native oleaut32 does this */
5535         {
5536             unsigned int i;
5537             for (remainder = 1, i = 0; i < sizeof(di_result.bitsnum) / sizeof(DWORD) && remainder; i++) {
5538                 ULONGLONG digit = di_result.bitsnum[i] + 1;
5539                 remainder = (digit > 0xFFFFFFFF) ? 1 : 0;
5540                 di_result.bitsnum[i] = digit & 0xFFFFFFFF;
5541             }
5542         }
5543       }
5544       VARIANT_DecFromDI(&di_result, pDecOut);
5545   }
5546   return hRet;
5547 }
5548
5549 /************************************************************************
5550  * VarDecMul (OLEAUT32.179)
5551  *
5552  * Multiply one DECIMAL by another.
5553  *
5554  * PARAMS
5555  *  pDecLeft  [I] Source
5556  *  pDecRight [I] Value to multiply by
5557  *  pDecOut   [O] Destination
5558  *
5559  * RETURNS
5560  *  Success: S_OK.
5561  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5562  */
5563 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5564 {
5565   HRESULT hRet = S_OK;
5566   VARIANT_DI di_left, di_right, di_result;
5567   int mulresult;
5568
5569   VARIANT_DIFromDec(pDecLeft, &di_left);
5570   VARIANT_DIFromDec(pDecRight, &di_right);
5571   mulresult = VARIANT_DI_mul(&di_left, &di_right, &di_result);
5572   if (mulresult)
5573   {
5574     /* multiplication actually overflowed */
5575     hRet = DISP_E_OVERFLOW;
5576   }
5577   else
5578   {
5579     if (di_result.scale > DEC_MAX_SCALE)
5580     {
5581       /* multiplication underflowed. In order to comply with the MSDN
5582          specifications for DECIMAL ranges, some significant digits
5583          must be removed
5584        */
5585       WARN("result scale is %u, scaling (with loss of significant digits)...\n",
5586           di_result.scale);
5587       while (di_result.scale > DEC_MAX_SCALE && 
5588             !VARIANT_int_iszero(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD)))
5589       {
5590         VARIANT_int_divbychar(di_result.bitsnum, sizeof(di_result.bitsnum)/sizeof(DWORD), 10);
5591         di_result.scale--;
5592       }
5593       if (di_result.scale > DEC_MAX_SCALE)
5594       {
5595         WARN("result underflowed, setting to 0\n");
5596         di_result.scale = 0;
5597         di_result.sign = 0;
5598       }
5599     }
5600     VARIANT_DecFromDI(&di_result, pDecOut);
5601   }
5602   return hRet;
5603 }
5604
5605 /************************************************************************
5606  * VarDecSub (OLEAUT32.181)
5607  *
5608  * Subtract one DECIMAL from another.
5609  *
5610  * PARAMS
5611  *  pDecLeft  [I] Source
5612  *  pDecRight [I] DECIMAL to subtract from pDecLeft
5613  *  pDecOut   [O] Destination
5614  *
5615  * RETURNS
5616  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5617  */
5618 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
5619 {
5620   DECIMAL decRight;
5621
5622   /* Implement as addition of the negative */
5623   VarDecNeg(pDecRight, &decRight);
5624   return VarDecAdd(pDecLeft, &decRight, pDecOut);
5625 }
5626
5627 /************************************************************************
5628  * VarDecAbs (OLEAUT32.182)
5629  *
5630  * Convert a DECIMAL into its absolute value.
5631  *
5632  * PARAMS
5633  *  pDecIn  [I] Source
5634  *  pDecOut [O] Destination
5635  *
5636  * RETURNS
5637  *  S_OK. This function does not fail.
5638  */
5639 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5640 {
5641   *pDecOut = *pDecIn;
5642   DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
5643   return S_OK;
5644 }
5645
5646 /************************************************************************
5647  * VarDecFix (OLEAUT32.187)
5648  *
5649  * Return the integer portion of a DECIMAL.
5650  *
5651  * PARAMS
5652  *  pDecIn  [I] Source
5653  *  pDecOut [O] Destination
5654  *
5655  * RETURNS
5656  *  Success: S_OK.
5657  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5658  *
5659  * NOTES
5660  *  - The difference between this function and VarDecInt() is that VarDecInt() rounds
5661  *    negative numbers away from 0, while this function rounds them towards zero.
5662  */
5663 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5664 {
5665   double dbl;
5666   HRESULT hr;
5667
5668   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
5669     return E_INVALIDARG;
5670
5671   if (!DEC_SCALE(pDecIn))
5672   {
5673     *pDecOut = *pDecIn; /* Already an integer */
5674     return S_OK;
5675   }
5676
5677   hr = VarR8FromDec(pDecIn, &dbl);
5678   if (SUCCEEDED(hr)) {
5679     LONGLONG rounded = dbl;
5680
5681     hr = VarDecFromI8(rounded, pDecOut);
5682   }
5683   return hr;
5684 }
5685
5686 /************************************************************************
5687  * VarDecInt (OLEAUT32.188)
5688  *
5689  * Return the integer portion of a DECIMAL.
5690  *
5691  * PARAMS
5692  *  pDecIn  [I] Source
5693  *  pDecOut [O] Destination
5694  *
5695  * RETURNS
5696  *  Success: S_OK.
5697  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
5698  *
5699  * NOTES
5700  *  - The difference between this function and VarDecFix() is that VarDecFix() rounds
5701  *    negative numbers towards 0, while this function rounds them away from zero.
5702  */
5703 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5704 {
5705   double dbl;
5706   HRESULT hr;
5707
5708   if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
5709     return E_INVALIDARG;
5710
5711   if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
5712     return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
5713
5714   hr = VarR8FromDec(pDecIn, &dbl);
5715   if (SUCCEEDED(hr)) {
5716     LONGLONG rounded = dbl >= 0.0 ? dbl + 0.5 : dbl - 0.5;
5717
5718     hr = VarDecFromI8(rounded, pDecOut);
5719   }
5720   return hr;
5721 }
5722
5723 /************************************************************************
5724  * VarDecNeg (OLEAUT32.189)
5725  *
5726  * Change the sign of a DECIMAL.
5727  *
5728  * PARAMS
5729  *  pDecIn  [I] Source
5730  *  pDecOut [O] Destination
5731  *
5732  * RETURNS
5733  *  S_OK. This function does not fail.
5734  */
5735 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
5736 {
5737   *pDecOut = *pDecIn;
5738   DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
5739   return S_OK;
5740 }
5741
5742 /************************************************************************
5743  * VarDecRound (OLEAUT32.203)
5744  *
5745  * Change the precision of a DECIMAL.
5746  *
5747  * PARAMS
5748  *  pDecIn    [I] Source
5749  *  cDecimals [I] New number of decimals to keep
5750  *  pDecOut   [O] Destination
5751  *
5752  * RETURNS
5753  *  Success: S_OK. pDecOut contains the rounded value.
5754  *  Failure: E_INVALIDARG if any argument is invalid.
5755  */
5756 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
5757 {
5758   if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
5759     return E_INVALIDARG;
5760
5761   if (cDecimals >= DEC_SCALE(pDecIn))
5762   {
5763     *pDecOut = *pDecIn; /* More precision than we have */
5764     return S_OK;
5765   }
5766
5767   FIXME("semi-stub!\n");
5768
5769   return DISP_E_OVERFLOW;
5770 }
5771
5772 /************************************************************************
5773  * VarDecCmp (OLEAUT32.204)
5774  *
5775  * Compare two DECIMAL values.
5776  *
5777  * PARAMS
5778  *  pDecLeft  [I] Source
5779  *  pDecRight [I] Value to compare
5780  *
5781  * RETURNS
5782  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
5783  *           is less than, equal to or greater than pDecRight respectively.
5784  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5785  */
5786 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
5787 {
5788   HRESULT hRet;
5789   DECIMAL result;
5790
5791   /* Subtract right from left, and compare the result to 0 */
5792   hRet = VarDecSub(pDecLeft, pDecRight, &result);
5793
5794   if (SUCCEEDED(hRet))
5795   {
5796     int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
5797
5798     if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
5799       hRet = (HRESULT)VARCMP_LT;
5800     else if (non_zero)
5801       hRet = (HRESULT)VARCMP_GT;
5802     else
5803       hRet = (HRESULT)VARCMP_EQ;
5804   }
5805   return hRet;
5806 }
5807
5808 /************************************************************************
5809  * VarDecCmpR8 (OLEAUT32.298)
5810  *
5811  * Compare a DECIMAL to a double
5812  *
5813  * PARAMS
5814  *  pDecLeft [I] DECIMAL Source
5815  *  dblRight [I] double to compare to pDecLeft
5816  *
5817  * RETURNS
5818  *  Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
5819  *           is less than, equal to or greater than pDecLeft respectively.
5820  *  Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison
5821  */
5822 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
5823 {
5824   HRESULT hRet;
5825   DECIMAL decRight;
5826
5827   hRet = VarDecFromR8(dblRight, &decRight);
5828
5829   if (SUCCEEDED(hRet))
5830     hRet = VarDecCmp(pDecLeft, &decRight);
5831
5832   return hRet;
5833 }
5834
5835 /* BOOL
5836  */
5837
5838 /************************************************************************
5839  * VarBoolFromUI1 (OLEAUT32.118)
5840  *
5841  * Convert a VT_UI1 to a VT_BOOL.
5842  *
5843  * PARAMS
5844  *  bIn      [I] Source
5845  *  pBoolOut [O] Destination
5846  *
5847  * RETURNS
5848  *  S_OK.
5849  */
5850 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
5851 {
5852   *pBoolOut = bIn ? VARIANT_TRUE : VARIANT_FALSE;
5853   return S_OK;
5854 }
5855
5856 /************************************************************************
5857  * VarBoolFromI2 (OLEAUT32.119)
5858  *
5859  * Convert a VT_I2 to a VT_BOOL.
5860  *
5861  * PARAMS
5862  *  sIn      [I] Source
5863  *  pBoolOut [O] Destination
5864  *
5865  * RETURNS
5866  *  S_OK.
5867  */
5868 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
5869 {
5870   *pBoolOut = sIn ? VARIANT_TRUE : VARIANT_FALSE;
5871   return S_OK;
5872 }
5873
5874 /************************************************************************
5875  * VarBoolFromI4 (OLEAUT32.120)
5876  *
5877  * Convert a VT_I4 to a VT_BOOL.
5878  *
5879  * PARAMS
5880  *  sIn      [I] Source
5881  *  pBoolOut [O] Destination
5882  *
5883  * RETURNS
5884  *  S_OK.
5885  */
5886 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
5887 {
5888   *pBoolOut = lIn ? VARIANT_TRUE : VARIANT_FALSE;
5889   return S_OK;
5890 }
5891
5892 /************************************************************************
5893  * VarBoolFromR4 (OLEAUT32.121)
5894  *
5895  * Convert a VT_R4 to a VT_BOOL.
5896  *
5897  * PARAMS
5898  *  fltIn    [I] Source
5899  *  pBoolOut [O] Destination
5900  *
5901  * RETURNS
5902  *  S_OK.
5903  */
5904 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
5905 {
5906   *pBoolOut = fltIn ? VARIANT_TRUE : VARIANT_FALSE;
5907   return S_OK;
5908 }
5909
5910 /************************************************************************
5911  * VarBoolFromR8 (OLEAUT32.122)
5912  *
5913  * Convert a VT_R8 to a VT_BOOL.
5914  *
5915  * PARAMS
5916  *  dblIn    [I] Source
5917  *  pBoolOut [O] Destination
5918  *
5919  * RETURNS
5920  *  S_OK.
5921  */
5922 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
5923 {
5924   *pBoolOut = dblIn ? VARIANT_TRUE : VARIANT_FALSE;
5925   return S_OK;
5926 }
5927
5928 /************************************************************************
5929  * VarBoolFromDate (OLEAUT32.123)
5930  *
5931  * Convert a VT_DATE to a VT_BOOL.
5932  *
5933  * PARAMS
5934  *  dateIn   [I] Source
5935  *  pBoolOut [O] Destination
5936  *
5937  * RETURNS
5938  *  S_OK.
5939  */
5940 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
5941 {
5942   *pBoolOut = dateIn ? VARIANT_TRUE : VARIANT_FALSE;
5943   return S_OK;
5944 }
5945
5946 /************************************************************************
5947  * VarBoolFromCy (OLEAUT32.124)
5948  *
5949  * Convert a VT_CY to a VT_BOOL.
5950  *
5951  * PARAMS
5952  *  cyIn     [I] Source
5953  *  pBoolOut [O] Destination
5954  *
5955  * RETURNS
5956  *  S_OK.
5957  */
5958 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
5959 {
5960   *pBoolOut = cyIn.int64 ? VARIANT_TRUE : VARIANT_FALSE;
5961   return S_OK;
5962 }
5963
5964 /************************************************************************
5965  * VARIANT_GetLocalisedText [internal]
5966  *
5967  * Get a localized string from the resources
5968  *
5969  */
5970 BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
5971 {
5972   HRSRC hrsrc;
5973
5974   hrsrc = FindResourceExW( hProxyDll, (LPWSTR)RT_STRING,
5975                            MAKEINTRESOURCEW((dwId >> 4) + 1), langId );
5976   if (hrsrc)
5977   {
5978     HGLOBAL hmem = LoadResource( hProxyDll, hrsrc );
5979
5980     if (hmem)
5981     {
5982       const WCHAR *p;
5983       unsigned int i;
5984
5985       p = LockResource( hmem );
5986       for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
5987
5988       memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
5989       lpszDest[*p] = '\0';
5990       TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
5991       return TRUE;
5992     }
5993   }
5994   return FALSE;
5995 }
5996
5997 /************************************************************************
5998  * VarBoolFromStr (OLEAUT32.125)
5999  *
6000  * Convert a VT_BSTR to a VT_BOOL.
6001  *
6002  * PARAMS
6003  *  strIn    [I] Source
6004  *  lcid     [I] LCID for the conversion
6005  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6006  *  pBoolOut [O] Destination
6007  *
6008  * RETURNS
6009  *  Success: S_OK.
6010  *  Failure: E_INVALIDARG, if pBoolOut is invalid.
6011  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
6012  *
6013  * NOTES
6014  *  - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
6015  *  it may contain (in any case mapping) the text "true" or "false".
6016  *  - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
6017  *  localised text of "True" or "False" in the language specified by lcid.
6018  *  - If none of these matches occur, the string is treated as a numeric string
6019  *  and the boolean pBoolOut will be set according to whether the number is zero
6020  *  or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
6021  *  - If the text is not numeric and does not match any of the above, then
6022  *  DISP_E_TYPEMISMATCH is returned.
6023  */
6024 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
6025 {
6026   /* Any VB/VBA programmers out there should recognise these strings... */
6027   static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
6028   static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
6029   WCHAR szBuff[64];
6030   LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6031   HRESULT hRes = S_OK;
6032
6033   if (!strIn || !pBoolOut)
6034     return DISP_E_TYPEMISMATCH;
6035
6036   /* Check if we should be comparing against localised text */
6037   if (dwFlags & VAR_LOCALBOOL)
6038   {
6039     /* Convert our LCID into a usable value */
6040     lcid = ConvertDefaultLocale(lcid);
6041
6042     langId = LANGIDFROMLCID(lcid);
6043
6044     if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
6045       langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6046
6047     /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
6048      * I don't think this is needed unless any of the localised text strings
6049      * contain characters that can be so mapped. In the event that this is
6050      * true for a given language (possibly some Asian languages), then strIn
6051      * should be mapped here _only_ if langId is an Id for which this can occur.
6052      */
6053   }
6054
6055   /* Note that if we are not comparing against localised strings, langId
6056    * will have its default value of LANG_ENGLISH. This allows us to mimic
6057    * the native behaviour of always checking against English strings even
6058    * after we've checked for localised ones.
6059    */
6060 VarBoolFromStr_CheckLocalised:
6061   if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
6062   {
6063     /* Compare against localised strings, ignoring case */
6064     if (!strcmpiW(strIn, szBuff))
6065     {
6066       *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
6067       return hRes;
6068     }
6069     VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
6070     if (!strcmpiW(strIn, szBuff))
6071     {
6072       *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
6073       return hRes;
6074     }
6075   }
6076
6077   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
6078   {
6079     /* We have checked the localised text, now check English */
6080     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6081     goto VarBoolFromStr_CheckLocalised;
6082   }
6083
6084   /* All checks against localised text have failed, try #TRUE#/#FALSE# */
6085   if (!strcmpW(strIn, szFalse))
6086     *pBoolOut = VARIANT_FALSE;
6087   else if (!strcmpW(strIn, szTrue))
6088     *pBoolOut = VARIANT_TRUE;
6089   else
6090   {
6091     double d;
6092
6093     /* If this string is a number, convert it as one */
6094     hRes = VarR8FromStr(strIn, lcid, dwFlags, &d);
6095     if (SUCCEEDED(hRes)) *pBoolOut = d ? VARIANT_TRUE : VARIANT_FALSE;
6096   }
6097   return hRes;
6098 }
6099
6100 /************************************************************************
6101  * VarBoolFromDisp (OLEAUT32.126)
6102  *
6103  * Convert a VT_DISPATCH to a VT_BOOL.
6104  *
6105  * PARAMS
6106  *  pdispIn   [I] Source
6107  *  lcid      [I] LCID for conversion
6108  *  pBoolOut  [O] Destination
6109  *
6110  * RETURNS
6111  *  Success: S_OK.
6112  *  Failure: E_INVALIDARG, if the source value is invalid
6113  *           DISP_E_OVERFLOW, if the value will not fit in the destination
6114  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
6115  */
6116 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
6117 {
6118   return VARIANT_FromDisp(pdispIn, lcid, pBoolOut, VT_BOOL, 0);
6119 }
6120
6121 /************************************************************************
6122  * VarBoolFromI1 (OLEAUT32.233)
6123  *
6124  * Convert a VT_I1 to a VT_BOOL.
6125  *
6126  * PARAMS
6127  *  cIn      [I] Source
6128  *  pBoolOut [O] Destination
6129  *
6130  * RETURNS
6131  *  S_OK.
6132  */
6133 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
6134 {
6135   *pBoolOut = cIn ? VARIANT_TRUE : VARIANT_FALSE;
6136   return S_OK;
6137 }
6138
6139 /************************************************************************
6140  * VarBoolFromUI2 (OLEAUT32.234)
6141  *
6142  * Convert a VT_UI2 to a VT_BOOL.
6143  *
6144  * PARAMS
6145  *  usIn     [I] Source
6146  *  pBoolOut [O] Destination
6147  *
6148  * RETURNS
6149  *  S_OK.
6150  */
6151 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
6152 {
6153   *pBoolOut = usIn ? VARIANT_TRUE : VARIANT_FALSE;
6154   return S_OK;
6155 }
6156
6157 /************************************************************************
6158  * VarBoolFromUI4 (OLEAUT32.235)
6159  *
6160  * Convert a VT_UI4 to a VT_BOOL.
6161  *
6162  * PARAMS
6163  *  ulIn     [I] Source
6164  *  pBoolOut [O] Destination
6165  *
6166  * RETURNS
6167  *  S_OK.
6168  */
6169 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
6170 {
6171   *pBoolOut = ulIn ? VARIANT_TRUE : VARIANT_FALSE;
6172   return S_OK;
6173 }
6174
6175 /************************************************************************
6176  * VarBoolFromDec (OLEAUT32.236)
6177  *
6178  * Convert a VT_DECIMAL to a VT_BOOL.
6179  *
6180  * PARAMS
6181  *  pDecIn   [I] Source
6182  *  pBoolOut [O] Destination
6183  *
6184  * RETURNS
6185  *  Success: S_OK.
6186  *  Failure: E_INVALIDARG, if pDecIn is invalid.
6187  */
6188 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
6189 {
6190   if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
6191     return E_INVALIDARG;
6192
6193   if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
6194     *pBoolOut = VARIANT_TRUE;
6195   else
6196     *pBoolOut = VARIANT_FALSE;
6197   return S_OK;
6198 }
6199
6200 /************************************************************************
6201  * VarBoolFromI8 (OLEAUT32.370)
6202  *
6203  * Convert a VT_I8 to a VT_BOOL.
6204  *
6205  * PARAMS
6206  *  ullIn    [I] Source
6207  *  pBoolOut [O] Destination
6208  *
6209  * RETURNS
6210  *  S_OK.
6211  */
6212 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
6213 {
6214   *pBoolOut = llIn ? VARIANT_TRUE : VARIANT_FALSE;
6215   return S_OK;
6216 }
6217
6218 /************************************************************************
6219  * VarBoolFromUI8 (OLEAUT32.371)
6220  *
6221  * Convert a VT_UI8 to a VT_BOOL.
6222  *
6223  * PARAMS
6224  *  ullIn    [I] Source
6225  *  pBoolOut [O] Destination
6226  *
6227  * RETURNS
6228  *  S_OK.
6229  */
6230 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
6231 {
6232   *pBoolOut = ullIn ? VARIANT_TRUE : VARIANT_FALSE;
6233   return S_OK;
6234 }
6235
6236 /* BSTR
6237  */
6238
6239 /* Write a number from a UI8 and sign */
6240 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
6241 {
6242   do
6243   {
6244     WCHAR ulNextDigit = ulVal % 10;
6245
6246     *szOut-- = '0' + ulNextDigit;
6247     ulVal = (ulVal - ulNextDigit) / 10;
6248   } while (ulVal);
6249
6250   szOut++;
6251   return szOut;
6252 }
6253
6254 /* Create a (possibly localised) BSTR from a UI8 and sign */
6255 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
6256 {
6257   WCHAR szConverted[256];
6258
6259   if (dwFlags & VAR_NEGATIVE)
6260     *--szOut = '-';
6261
6262   if (dwFlags & LOCALE_USE_NLS)
6263   {
6264     /* Format the number for the locale */
6265     szConverted[0] = '\0';
6266     GetNumberFormatW(lcid,
6267                      dwFlags & LOCALE_NOUSEROVERRIDE,
6268                      szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
6269     szOut = szConverted;
6270   }
6271   return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
6272 }
6273
6274 /* Create a (possibly localised) BSTR from a UI8 and sign */
6275 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
6276 {
6277   WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
6278
6279   if (!pbstrOut)
6280     return E_INVALIDARG;
6281
6282   /* Create the basic number string */
6283   *szOut-- = '\0';
6284   szOut = VARIANT_WriteNumber(ulVal, szOut);
6285
6286   *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
6287   TRACE("returning %s\n", debugstr_w(*pbstrOut));
6288   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6289 }
6290
6291 /******************************************************************************
6292  * VarBstrFromUI1 (OLEAUT32.108)
6293  *
6294  * Convert a VT_UI1 to a VT_BSTR.
6295  *
6296  * PARAMS
6297  *  bIn      [I] Source
6298  *  lcid     [I] LCID for the conversion
6299  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6300  *  pbstrOut [O] Destination
6301  *
6302  * RETURNS
6303  *  Success: S_OK.
6304  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6305  *           E_OUTOFMEMORY, if memory allocation fails.
6306  */
6307 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6308 {
6309   return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
6310 }
6311
6312 /******************************************************************************
6313  * VarBstrFromI2 (OLEAUT32.109)
6314  *
6315  * Convert a VT_I2 to a VT_BSTR.
6316  *
6317  * PARAMS
6318  *  sIn      [I] Source
6319  *  lcid     [I] LCID for the conversion
6320  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6321  *  pbstrOut [O] Destination
6322  *
6323  * RETURNS
6324  *  Success: S_OK.
6325  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6326  *           E_OUTOFMEMORY, if memory allocation fails.
6327  */
6328 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6329 {
6330   ULONG64 ul64 = sIn;
6331
6332   if (sIn < 0)
6333   {
6334     ul64 = -sIn;
6335     dwFlags |= VAR_NEGATIVE;
6336   }
6337   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6338 }
6339
6340 /******************************************************************************
6341  * VarBstrFromI4 (OLEAUT32.110)
6342  *
6343  * Convert a VT_I4 to a VT_BSTR.
6344  *
6345  * PARAMS
6346  *  lIn      [I] Source
6347  *  lcid     [I] LCID for the conversion
6348  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6349  *  pbstrOut [O] Destination
6350  *
6351  * RETURNS
6352  *  Success: S_OK.
6353  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6354  *           E_OUTOFMEMORY, if memory allocation fails.
6355  */
6356 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6357 {
6358   ULONG64 ul64 = lIn;
6359
6360   if (lIn < 0)
6361   {
6362     ul64 = (ULONG)-lIn;
6363     dwFlags |= VAR_NEGATIVE;
6364   }
6365   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6366 }
6367
6368 static BSTR VARIANT_BstrReplaceDecimal(const WCHAR * buff, LCID lcid, ULONG dwFlags)
6369 {
6370   BSTR bstrOut;
6371   WCHAR lpDecimalSep[16];
6372
6373   /* Native oleaut32 uses the locale-specific decimal separator even in the
6374      absence of the LOCALE_USE_NLS flag. For example, the Spanish/Latin 
6375      American locales will see "one thousand and one tenth" as "1000,1" 
6376      instead of "1000.1" (notice the comma). The following code checks for
6377      the need to replace the decimal separator, and if so, will prepare an
6378      appropriate NUMBERFMTW structure to do the job via GetNumberFormatW().
6379    */
6380   GetLocaleInfoW(lcid, LOCALE_SDECIMAL | (dwFlags & LOCALE_NOUSEROVERRIDE),
6381                  lpDecimalSep, sizeof(lpDecimalSep) / sizeof(WCHAR));
6382   if (lpDecimalSep[0] == '.' && lpDecimalSep[1] == '\0')
6383   {
6384     /* locale is compatible with English - return original string */
6385     bstrOut = SysAllocString(buff);
6386   }
6387   else
6388   {
6389     WCHAR *p;
6390     WCHAR numbuff[256];
6391     WCHAR empty[1] = {'\0'};
6392     NUMBERFMTW minFormat;
6393
6394     minFormat.NumDigits = 0;
6395     minFormat.LeadingZero = 0;
6396     minFormat.Grouping = 0;
6397     minFormat.lpDecimalSep = lpDecimalSep;
6398     minFormat.lpThousandSep = empty;
6399     minFormat.NegativeOrder = 1; /* NLS_NEG_LEFT */
6400
6401     /* count number of decimal digits in string */
6402     p = strchrW( buff, '.' );
6403     if (p) minFormat.NumDigits = strlenW(p + 1);
6404
6405     numbuff[0] = '\0';
6406     if (!GetNumberFormatW(lcid, 0, buff, &minFormat, numbuff, sizeof(numbuff) / sizeof(WCHAR)))
6407     {
6408       WARN("GetNumberFormatW() failed, returning raw number string instead\n");
6409       bstrOut = SysAllocString(buff);
6410     }
6411     else
6412     {
6413       TRACE("created minimal NLS string %s\n", debugstr_w(numbuff));
6414       bstrOut = SysAllocString(numbuff);
6415     }
6416   }
6417   return bstrOut;
6418 }
6419
6420 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
6421                                     BSTR* pbstrOut, LPCWSTR lpszFormat)
6422 {
6423   WCHAR buff[256];
6424
6425   if (!pbstrOut)
6426     return E_INVALIDARG;
6427
6428   sprintfW( buff, lpszFormat, dblIn );
6429
6430   /* Negative zeroes are disallowed (some applications depend on this).
6431      If buff starts with a minus, and then nothing follows but zeroes
6432      and/or a period, it is a negative zero and is replaced with a
6433      canonical zero. This duplicates native oleaut32 behavior.
6434    */
6435   if (buff[0] == '-')
6436   {
6437     const WCHAR szAccept[] = {'0', '.', '\0'};
6438     if (strlenW(buff + 1) == strspnW(buff + 1, szAccept))
6439     { buff[0] = '0'; buff[1] = '\0'; }
6440   }
6441
6442   TRACE("created string %s\n", debugstr_w(buff));
6443   if (dwFlags & LOCALE_USE_NLS)
6444   {
6445     WCHAR numbuff[256];
6446
6447     /* Format the number for the locale */
6448     numbuff[0] = '\0';
6449     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6450                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
6451     TRACE("created NLS string %s\n", debugstr_w(numbuff));
6452     *pbstrOut = SysAllocString(numbuff);
6453   }
6454   else
6455   {
6456     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
6457   }
6458   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6459 }
6460
6461 /******************************************************************************
6462  * VarBstrFromR4 (OLEAUT32.111)
6463  *
6464  * Convert a VT_R4 to a VT_BSTR.
6465  *
6466  * PARAMS
6467  *  fltIn    [I] Source
6468  *  lcid     [I] LCID for the conversion
6469  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6470  *  pbstrOut [O] Destination
6471  *
6472  * RETURNS
6473  *  Success: S_OK.
6474  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6475  *           E_OUTOFMEMORY, if memory allocation fails.
6476  */
6477 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6478 {
6479   return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
6480 }
6481
6482 /******************************************************************************
6483  * VarBstrFromR8 (OLEAUT32.112)
6484  *
6485  * Convert a VT_R8 to a VT_BSTR.
6486  *
6487  * PARAMS
6488  *  dblIn    [I] Source
6489  *  lcid     [I] LCID for the conversion
6490  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6491  *  pbstrOut [O] Destination
6492  *
6493  * RETURNS
6494  *  Success: S_OK.
6495  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6496  *           E_OUTOFMEMORY, if memory allocation fails.
6497  */
6498 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6499 {
6500   return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
6501 }
6502
6503 /******************************************************************************
6504  *    VarBstrFromCy   [OLEAUT32.113]
6505  *
6506  * Convert a VT_CY to a VT_BSTR.
6507  *
6508  * PARAMS
6509  *  cyIn     [I] Source
6510  *  lcid     [I] LCID for the conversion
6511  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6512  *  pbstrOut [O] Destination
6513  *
6514  * RETURNS
6515  *  Success: S_OK.
6516  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6517  *           E_OUTOFMEMORY, if memory allocation fails.
6518  */
6519 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
6520 {
6521   WCHAR buff[256];
6522   VARIANT_DI decVal;
6523
6524   if (!pbstrOut)
6525     return E_INVALIDARG;
6526
6527   decVal.scale = 4;
6528   decVal.sign = 0;
6529   decVal.bitsnum[0] = cyIn.s.Lo;
6530   decVal.bitsnum[1] = cyIn.s.Hi;
6531   if (cyIn.s.Hi & 0x80000000UL) {
6532     DWORD one = 1;
6533
6534     /* Negative number! */
6535     decVal.sign = 1;
6536     decVal.bitsnum[0] = ~decVal.bitsnum[0];
6537     decVal.bitsnum[1] = ~decVal.bitsnum[1];
6538     VARIANT_int_add(decVal.bitsnum, 3, &one, 1);
6539   }
6540   decVal.bitsnum[2] = 0;
6541   VARIANT_DI_tostringW(&decVal, buff, sizeof(buff)/sizeof(buff[0]));
6542
6543   if (dwFlags & LOCALE_USE_NLS)
6544   {
6545     WCHAR cybuff[256];
6546
6547     /* Format the currency for the locale */
6548     cybuff[0] = '\0';
6549     GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6550                        buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
6551     *pbstrOut = SysAllocString(cybuff);
6552   }
6553   else
6554     *pbstrOut = VARIANT_BstrReplaceDecimal(buff,lcid,dwFlags);
6555
6556   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6557 }
6558
6559 /******************************************************************************
6560  *    VarBstrFromDate    [OLEAUT32.114]
6561  *
6562  * Convert a VT_DATE to a VT_BSTR.
6563  *
6564  * PARAMS
6565  *  dateIn   [I] Source
6566  *  lcid     [I] LCID for the conversion
6567  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6568  *  pbstrOut [O] Destination
6569  *
6570  * RETURNS
6571  *  Success: S_OK.
6572  *  Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
6573  *           E_OUTOFMEMORY, if memory allocation fails.
6574  */
6575 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6576 {
6577   SYSTEMTIME st;
6578   DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
6579   WCHAR date[128], *time;
6580
6581   TRACE("(%g,0x%08x,0x%08x,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
6582
6583   if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
6584     return E_INVALIDARG;
6585
6586   *pbstrOut = NULL;
6587
6588   if (dwFlags & VAR_CALENDAR_THAI)
6589       st.wYear += 553; /* Use the Thai buddhist calendar year */
6590   else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
6591       FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
6592
6593   if (dwFlags & LOCALE_USE_NLS)
6594     dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
6595   else
6596   {
6597     double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
6598     double partial = dateIn - whole;
6599
6600     if (whole == 0.0)
6601       dwFlags |= VAR_TIMEVALUEONLY;
6602     else if (partial < 1e-12)
6603       dwFlags |= VAR_DATEVALUEONLY;
6604   }
6605
6606   if (dwFlags & VAR_TIMEVALUEONLY)
6607     date[0] = '\0';
6608   else
6609     if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
6610                         sizeof(date)/sizeof(WCHAR)))
6611       return E_INVALIDARG;
6612
6613   if (!(dwFlags & VAR_DATEVALUEONLY))
6614   {
6615     time = date + strlenW(date);
6616     if (time != date)
6617       *time++ = ' ';
6618     if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
6619                         sizeof(date)/sizeof(WCHAR)-(time-date)))
6620       return E_INVALIDARG;
6621   }
6622
6623   *pbstrOut = SysAllocString(date);
6624   if (*pbstrOut)
6625     TRACE("returning %s\n", debugstr_w(*pbstrOut));
6626   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6627 }
6628
6629 /******************************************************************************
6630  * VarBstrFromBool (OLEAUT32.116)
6631  *
6632  * Convert a VT_BOOL to a VT_BSTR.
6633  *
6634  * PARAMS
6635  *  boolIn   [I] Source
6636  *  lcid     [I] LCID for the conversion
6637  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6638  *  pbstrOut [O] Destination
6639  *
6640  * RETURNS
6641  *  Success: S_OK.
6642  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6643  *           E_OUTOFMEMORY, if memory allocation fails.
6644  *
6645  * NOTES
6646  *  If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
6647  *  localised text of "True" or "False". To convert a bool into a
6648  *  numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
6649  */
6650 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6651 {
6652   WCHAR szBuff[64];
6653   DWORD dwResId = IDS_TRUE;
6654   LANGID langId;
6655
6656   TRACE("%d,0x%08x,0x%08x,%p\n", boolIn, lcid, dwFlags, pbstrOut);
6657
6658   if (!pbstrOut)
6659     return E_INVALIDARG;
6660
6661   /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
6662    * for variant formatting */
6663   switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
6664   {
6665   case VAR_BOOLONOFF:
6666       dwResId = IDS_ON;
6667       break;
6668   case VAR_BOOLYESNO:
6669       dwResId = IDS_YES;
6670       break;
6671   case VAR_LOCALBOOL:
6672       break;
6673   default:
6674     lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
6675   }
6676
6677   lcid = ConvertDefaultLocale(lcid);
6678   langId = LANGIDFROMLCID(lcid);
6679   if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
6680     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6681
6682   if (boolIn == VARIANT_FALSE)
6683     dwResId++; /* Use negative form */
6684
6685 VarBstrFromBool_GetLocalised:
6686   if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
6687   {
6688     *pbstrOut = SysAllocString(szBuff);
6689     return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6690   }
6691
6692   if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
6693   {
6694     langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
6695     goto VarBstrFromBool_GetLocalised;
6696   }
6697
6698   /* Should never get here */
6699   WARN("Failed to load bool text!\n");
6700   return E_OUTOFMEMORY;
6701 }
6702
6703 /******************************************************************************
6704  * VarBstrFromI1 (OLEAUT32.229)
6705  *
6706  * Convert a VT_I1 to a VT_BSTR.
6707  *
6708  * PARAMS
6709  *  cIn      [I] Source
6710  *  lcid     [I] LCID for the conversion
6711  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6712  *  pbstrOut [O] Destination
6713  *
6714  * RETURNS
6715  *  Success: S_OK.
6716  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6717  *           E_OUTOFMEMORY, if memory allocation fails.
6718  */
6719 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6720 {
6721   ULONG64 ul64 = cIn;
6722
6723   if (cIn < 0)
6724   {
6725     ul64 = -cIn;
6726     dwFlags |= VAR_NEGATIVE;
6727   }
6728   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6729 }
6730
6731 /******************************************************************************
6732  * VarBstrFromUI2 (OLEAUT32.230)
6733  *
6734  * Convert a VT_UI2 to a VT_BSTR.
6735  *
6736  * PARAMS
6737  *  usIn     [I] Source
6738  *  lcid     [I] LCID for the conversion
6739  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6740  *  pbstrOut [O] Destination
6741  *
6742  * RETURNS
6743  *  Success: S_OK.
6744  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6745  *           E_OUTOFMEMORY, if memory allocation fails.
6746  */
6747 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6748 {
6749   return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
6750 }
6751
6752 /******************************************************************************
6753  * VarBstrFromUI4 (OLEAUT32.231)
6754  *
6755  * Convert a VT_UI4 to a VT_BSTR.
6756  *
6757  * PARAMS
6758  *  ulIn     [I] Source
6759  *  lcid     [I] LCID for the conversion
6760  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6761  *  pbstrOut [O] Destination
6762  *
6763  * RETURNS
6764  *  Success: S_OK.
6765  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6766  *           E_OUTOFMEMORY, if memory allocation fails.
6767  */
6768 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6769 {
6770   return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
6771 }
6772
6773 /******************************************************************************
6774  * VarBstrFromDec (OLEAUT32.232)
6775  *
6776  * Convert a VT_DECIMAL to a VT_BSTR.
6777  *
6778  * PARAMS
6779  *  pDecIn   [I] Source
6780  *  lcid     [I] LCID for the conversion
6781  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6782  *  pbstrOut [O] Destination
6783  *
6784  * RETURNS
6785  *  Success: S_OK.
6786  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6787  *           E_OUTOFMEMORY, if memory allocation fails.
6788  */
6789 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6790 {
6791   WCHAR buff[256];
6792   VARIANT_DI temp;
6793
6794   if (!pbstrOut)
6795     return E_INVALIDARG;
6796
6797   VARIANT_DIFromDec(pDecIn, &temp);
6798   VARIANT_DI_tostringW(&temp, buff, 256);
6799
6800   if (dwFlags & LOCALE_USE_NLS)
6801   {
6802     WCHAR numbuff[256];
6803
6804     /* Format the number for the locale */
6805     numbuff[0] = '\0';
6806     GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
6807                      buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
6808     TRACE("created NLS string %s\n", debugstr_w(numbuff));
6809     *pbstrOut = SysAllocString(numbuff);
6810   }
6811   else
6812   {
6813     *pbstrOut = VARIANT_BstrReplaceDecimal(buff, lcid, dwFlags);
6814   }
6815   
6816   TRACE("returning %s\n", debugstr_w(*pbstrOut));
6817   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
6818 }
6819
6820 /************************************************************************
6821  * VarBstrFromI8 (OLEAUT32.370)
6822  *
6823  * Convert a VT_I8 to a VT_BSTR.
6824  *
6825  * PARAMS
6826  *  llIn     [I] Source
6827  *  lcid     [I] LCID for the conversion
6828  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6829  *  pbstrOut [O] Destination
6830  *
6831  * RETURNS
6832  *  Success: S_OK.
6833  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6834  *           E_OUTOFMEMORY, if memory allocation fails.
6835  */
6836 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6837 {
6838   ULONG64 ul64 = llIn;
6839
6840   if (llIn < 0)
6841   {
6842     ul64 = -llIn;
6843     dwFlags |= VAR_NEGATIVE;
6844   }
6845   return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
6846 }
6847
6848 /************************************************************************
6849  * VarBstrFromUI8 (OLEAUT32.371)
6850  *
6851  * Convert a VT_UI8 to a VT_BSTR.
6852  *
6853  * PARAMS
6854  *  ullIn    [I] Source
6855  *  lcid     [I] LCID for the conversion
6856  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6857  *  pbstrOut [O] Destination
6858  *
6859  * RETURNS
6860  *  Success: S_OK.
6861  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6862  *           E_OUTOFMEMORY, if memory allocation fails.
6863  */
6864 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6865 {
6866   return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
6867 }
6868
6869 /************************************************************************
6870  * VarBstrFromDisp (OLEAUT32.115)
6871  *
6872  * Convert a VT_DISPATCH to a BSTR.
6873  *
6874  * PARAMS
6875  *  pdispIn [I] Source
6876  *  lcid    [I] LCID for conversion
6877  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
6878  *  pbstrOut  [O] Destination
6879  *
6880  * RETURNS
6881  *  Success: S_OK.
6882  *  Failure: E_INVALIDARG, if the source value is invalid
6883  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
6884  */
6885 HRESULT WINAPI VarBstrFromDisp(IDispatch* pdispIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
6886 {
6887   return VARIANT_FromDisp(pdispIn, lcid, pbstrOut, VT_BSTR, dwFlags);
6888 }
6889
6890 /**********************************************************************
6891  * VarBstrCat (OLEAUT32.313)
6892  *
6893  * Concatenate two BSTR values.
6894  *
6895  * PARAMS
6896  *  pbstrLeft  [I] Source
6897  *  pbstrRight [I] Value to concatenate
6898  *  pbstrOut   [O] Destination
6899  *
6900  * RETURNS
6901  *  Success: S_OK.
6902  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
6903  *           E_OUTOFMEMORY, if memory allocation fails.
6904  */
6905 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
6906 {
6907   unsigned int lenLeft, lenRight;
6908
6909   TRACE("%s,%s,%p\n",
6910    debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
6911    debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), pbstrOut);
6912
6913   if (!pbstrOut)
6914     return E_INVALIDARG;
6915
6916   lenLeft = pbstrLeft ? SysStringLen(pbstrLeft) : 0;
6917   lenRight = pbstrRight ? SysStringLen(pbstrRight) : 0;
6918
6919   *pbstrOut = SysAllocStringLen(NULL, lenLeft + lenRight);
6920   if (!*pbstrOut)
6921     return E_OUTOFMEMORY;
6922
6923   (*pbstrOut)[0] = '\0';
6924
6925   if (pbstrLeft)
6926     memcpy(*pbstrOut, pbstrLeft, lenLeft * sizeof(WCHAR));
6927
6928   if (pbstrRight)
6929     memcpy(*pbstrOut + lenLeft, pbstrRight, lenRight * sizeof(WCHAR));
6930
6931   TRACE("%s\n", debugstr_wn(*pbstrOut, SysStringLen(*pbstrOut)));
6932   return S_OK;
6933 }
6934
6935 /**********************************************************************
6936  * VarBstrCmp (OLEAUT32.314)
6937  *
6938  * Compare two BSTR values.
6939  *
6940  * PARAMS
6941  *  pbstrLeft  [I] Source
6942  *  pbstrRight [I] Value to compare
6943  *  lcid       [I] LCID for the comparison
6944  *  dwFlags    [I] Flags to pass directly to CompareStringW().
6945  *
6946  * RETURNS
6947  *  VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
6948  *  than, equal to or greater than pbstrRight respectively.
6949  *
6950  * NOTES
6951  *  VARCMP_NULL is NOT returned if either string is NULL unlike MSDN
6952  *  states. A NULL BSTR pointer is equivalent to an empty string.
6953  *  If LCID is equal to 0, a byte by byte comparison is performed.
6954  */
6955 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
6956 {
6957     HRESULT hres;
6958     int ret;
6959
6960     TRACE("%s,%s,%d,%08x\n",
6961      debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
6962      debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), lcid, dwFlags);
6963
6964     if (!pbstrLeft || !*pbstrLeft)
6965     {
6966       if (pbstrRight && *pbstrRight)
6967         return VARCMP_LT;
6968     }
6969     else if (!pbstrRight || !*pbstrRight)
6970         return VARCMP_GT;
6971
6972     if (lcid == 0)
6973     {
6974       unsigned int lenLeft = SysStringByteLen(pbstrLeft);
6975       unsigned int lenRight = SysStringByteLen(pbstrRight);
6976       ret = memcmp(pbstrLeft, pbstrRight, min(lenLeft, lenRight));
6977       if (ret < 0)
6978         return VARCMP_LT;
6979       if (ret > 0)
6980         return VARCMP_GT;
6981       if (lenLeft < lenRight)
6982         return VARCMP_LT;
6983       if (lenLeft > lenRight)
6984         return VARCMP_GT;
6985       return VARCMP_EQ;
6986     }
6987     else
6988     {
6989       unsigned int lenLeft = SysStringLen(pbstrLeft);
6990       unsigned int lenRight = SysStringLen(pbstrRight);
6991
6992       if (lenLeft == 0 || lenRight == 0)
6993       {
6994           if (lenLeft == 0 && lenRight == 0) return VARCMP_EQ;
6995           return lenLeft < lenRight ? VARCMP_LT : VARCMP_GT;
6996       }
6997
6998       hres = CompareStringW(lcid, dwFlags, pbstrLeft, lenLeft,
6999               pbstrRight, lenRight) - 1;
7000       TRACE("%d\n", hres);
7001       return hres;
7002     }
7003 }
7004
7005 /*
7006  * DATE
7007  */
7008
7009 /******************************************************************************
7010  * VarDateFromUI1 (OLEAUT32.88)
7011  *
7012  * Convert a VT_UI1 to a VT_DATE.
7013  *
7014  * PARAMS
7015  *  bIn      [I] Source
7016  *  pdateOut [O] Destination
7017  *
7018  * RETURNS
7019  *  S_OK.
7020  */
7021 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
7022 {
7023   return VarR8FromUI1(bIn, pdateOut);
7024 }
7025
7026 /******************************************************************************
7027  * VarDateFromI2 (OLEAUT32.89)
7028  *
7029  * Convert a VT_I2 to a VT_DATE.
7030  *
7031  * PARAMS
7032  *  sIn      [I] Source
7033  *  pdateOut [O] Destination
7034  *
7035  * RETURNS
7036  *  S_OK.
7037  */
7038 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
7039 {
7040   return VarR8FromI2(sIn, pdateOut);
7041 }
7042
7043 /******************************************************************************
7044  * VarDateFromI4 (OLEAUT32.90)
7045  *
7046  * Convert a VT_I4 to a VT_DATE.
7047  *
7048  * PARAMS
7049  *  lIn      [I] Source
7050  *  pdateOut [O] Destination
7051  *
7052  * RETURNS
7053  *  S_OK.
7054  */
7055 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
7056 {
7057   return VarDateFromR8(lIn, pdateOut);
7058 }
7059
7060 /******************************************************************************
7061  * VarDateFromR4 (OLEAUT32.91)
7062  *
7063  * Convert a VT_R4 to a VT_DATE.
7064  *
7065  * PARAMS
7066  *  fltIn    [I] Source
7067  *  pdateOut [O] Destination
7068  *
7069  * RETURNS
7070  *  S_OK.
7071  */
7072 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
7073 {
7074   return VarR8FromR4(fltIn, pdateOut);
7075 }
7076
7077 /******************************************************************************
7078  * VarDateFromR8 (OLEAUT32.92)
7079  *
7080  * Convert a VT_R8 to a VT_DATE.
7081  *
7082  * PARAMS
7083  *  dblIn    [I] Source
7084  *  pdateOut [O] Destination
7085  *
7086  * RETURNS
7087  *  S_OK.
7088  */
7089 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
7090 {
7091   if (dblIn <= (DATE_MIN - 1.0) || dblIn >= (DATE_MAX + 1.0)) return DISP_E_OVERFLOW;
7092   *pdateOut = (DATE)dblIn;
7093   return S_OK;
7094 }
7095
7096 /**********************************************************************
7097  * VarDateFromDisp (OLEAUT32.95)
7098  *
7099  * Convert a VT_DISPATCH to a VT_DATE.
7100  *
7101  * PARAMS
7102  *  pdispIn  [I] Source
7103  *  lcid     [I] LCID for conversion
7104  *  pdateOut [O] Destination
7105  *
7106  * RETURNS
7107  *  Success: S_OK.
7108  *  Failure: E_INVALIDARG, if the source value is invalid
7109  *           DISP_E_OVERFLOW, if the value will not fit in the destination
7110  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
7111  */
7112 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
7113 {
7114   return VARIANT_FromDisp(pdispIn, lcid, pdateOut, VT_DATE, 0);
7115 }
7116
7117 /******************************************************************************
7118  * VarDateFromBool (OLEAUT32.96)
7119  *
7120  * Convert a VT_BOOL to a VT_DATE.
7121  *
7122  * PARAMS
7123  *  boolIn   [I] Source
7124  *  pdateOut [O] Destination
7125  *
7126  * RETURNS
7127  *  S_OK.
7128  */
7129 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
7130 {
7131   return VarR8FromBool(boolIn, pdateOut);
7132 }
7133
7134 /**********************************************************************
7135  * VarDateFromCy (OLEAUT32.93)
7136  *
7137  * Convert a VT_CY to a VT_DATE.
7138  *
7139  * PARAMS
7140  *  lIn      [I] Source
7141  *  pdateOut [O] Destination
7142  *
7143  * RETURNS
7144  *  S_OK.
7145  */
7146 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
7147 {
7148   return VarR8FromCy(cyIn, pdateOut);
7149 }
7150
7151 /* Date string parsing */
7152 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
7153 #define DP_DATESEP 0x02 /* Date separator */
7154 #define DP_MONTH   0x04 /* Month name */
7155 #define DP_AM      0x08 /* AM */
7156 #define DP_PM      0x10 /* PM */
7157
7158 typedef struct tagDATEPARSE
7159 {
7160     DWORD dwCount;      /* Number of fields found so far (maximum 6) */
7161     DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
7162     DWORD dwFlags[6];   /* Flags for each field */
7163     DWORD dwValues[6];  /* Value of each field */
7164 } DATEPARSE;
7165
7166 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
7167
7168 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
7169
7170 /* Determine if a day is valid in a given month of a given year */
7171 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
7172 {
7173   static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
7174
7175   if (day && month && month < 13)
7176   {
7177     if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
7178       return TRUE;
7179   }
7180   return FALSE;
7181 }
7182
7183 /* Possible orders for 3 numbers making up a date */
7184 #define ORDER_MDY 0x01
7185 #define ORDER_YMD 0x02
7186 #define ORDER_YDM 0x04
7187 #define ORDER_DMY 0x08
7188 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
7189
7190 /* Determine a date for a particular locale, from 3 numbers */
7191 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
7192                                        DWORD offset, SYSTEMTIME *st)
7193 {
7194   DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
7195
7196   if (!dp->dwCount)
7197   {
7198     v1 = 30; /* Default to (Variant) 0 date part */
7199     v2 = 12;
7200     v3 = 1899;
7201     goto VARIANT_MakeDate_OK;
7202   }
7203
7204   v1 = dp->dwValues[offset + 0];
7205   v2 = dp->dwValues[offset + 1];
7206   if (dp->dwCount == 2)
7207   {
7208     SYSTEMTIME current;
7209     GetSystemTime(&current);
7210     v3 = current.wYear;
7211   }
7212   else
7213     v3 = dp->dwValues[offset + 2];
7214
7215   TRACE("(%d,%d,%d,%d,%d)\n", v1, v2, v3, iDate, offset);
7216
7217   /* If one number must be a month (Because a month name was given), then only
7218    * consider orders with the month in that position.
7219    * If we took the current year as 'v3', then only allow a year in that position.
7220    */
7221   if (dp->dwFlags[offset + 0] & DP_MONTH)
7222   {
7223     dwAllOrders = ORDER_MDY;
7224   }
7225   else if (dp->dwFlags[offset + 1] & DP_MONTH)
7226   {
7227     dwAllOrders = ORDER_DMY;
7228     if (dp->dwCount > 2)
7229       dwAllOrders |= ORDER_YMD;
7230   }
7231   else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
7232   {
7233     dwAllOrders = ORDER_YDM;
7234   }
7235   else
7236   {
7237     dwAllOrders = ORDER_MDY|ORDER_DMY;
7238     if (dp->dwCount > 2)
7239       dwAllOrders |= (ORDER_YMD|ORDER_YDM);
7240   }
7241
7242 VARIANT_MakeDate_Start:
7243   TRACE("dwAllOrders is 0x%08x\n", dwAllOrders);
7244
7245   while (dwAllOrders)
7246   {
7247     DWORD dwTemp;
7248
7249     if (dwCount == 0)
7250     {
7251       /* First: Try the order given by iDate */
7252       switch (iDate)
7253       {
7254       case 0:  dwTry = dwAllOrders & ORDER_MDY; break;
7255       case 1:  dwTry = dwAllOrders & ORDER_DMY; break;
7256       default: dwTry = dwAllOrders & ORDER_YMD; break;
7257       }
7258     }
7259     else if (dwCount == 1)
7260     {
7261       /* Second: Try all the orders compatible with iDate */
7262       switch (iDate)
7263       {
7264       case 0:  dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
7265       case 1:  dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
7266       default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
7267       }
7268     }
7269     else
7270     {
7271       /* Finally: Try any remaining orders */
7272       dwTry = dwAllOrders;
7273     }
7274
7275     TRACE("Attempt %d, dwTry is 0x%08x\n", dwCount, dwTry);
7276
7277     dwCount++;
7278     if (!dwTry)
7279       continue;
7280
7281 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
7282
7283     if (dwTry & ORDER_MDY)
7284     {
7285       if (VARIANT_IsValidMonthDay(v2,v1,v3))
7286       {
7287         DATE_SWAP(v1,v2);
7288         goto VARIANT_MakeDate_OK;
7289       }
7290       dwAllOrders &= ~ORDER_MDY;
7291     }
7292     if (dwTry & ORDER_YMD)
7293     {
7294       if (VARIANT_IsValidMonthDay(v3,v2,v1))
7295       {
7296         DATE_SWAP(v1,v3);
7297         goto VARIANT_MakeDate_OK;
7298       }
7299       dwAllOrders &= ~ORDER_YMD;
7300     }
7301     if (dwTry & ORDER_YDM)
7302     {
7303       if (VARIANT_IsValidMonthDay(v2,v3,v1))
7304       {
7305         DATE_SWAP(v1,v2);
7306         DATE_SWAP(v2,v3);
7307         goto VARIANT_MakeDate_OK;
7308       }
7309       dwAllOrders &= ~ORDER_YDM;
7310     }
7311     if (dwTry & ORDER_DMY)
7312     {
7313       if (VARIANT_IsValidMonthDay(v1,v2,v3))
7314         goto VARIANT_MakeDate_OK;
7315       dwAllOrders &= ~ORDER_DMY;
7316     }
7317     if (dwTry & ORDER_MYD)
7318     {
7319       /* Only occurs if we are trying a 2 year date as M/Y not D/M */
7320       if (VARIANT_IsValidMonthDay(v3,v1,v2))
7321       {
7322         DATE_SWAP(v1,v3);
7323         DATE_SWAP(v2,v3);
7324         goto VARIANT_MakeDate_OK;
7325       }
7326       dwAllOrders &= ~ORDER_MYD;
7327     }
7328   }
7329
7330   if (dp->dwCount == 2)
7331   {
7332     /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
7333     v3 = 1; /* 1st of the month */
7334     dwAllOrders = ORDER_YMD|ORDER_MYD;
7335     dp->dwCount = 0; /* Don't return to this code path again */
7336     dwCount = 0;
7337     goto VARIANT_MakeDate_Start;
7338   }
7339
7340   /* No valid dates were able to be constructed */
7341   return DISP_E_TYPEMISMATCH;
7342
7343 VARIANT_MakeDate_OK:
7344
7345   /* Check that the time part is ok */
7346   if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
7347     return DISP_E_TYPEMISMATCH;
7348
7349   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
7350   if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
7351     st->wHour += 12;
7352   else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
7353     st->wHour = 0;
7354   TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
7355
7356   st->wDay = v1;
7357   st->wMonth = v2;
7358   /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
7359    * be retrieved from:
7360    * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
7361    * But Wine doesn't have/use that key as at the time of writing.
7362    */
7363   st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
7364   TRACE("Returning date %d/%d/%d\n", v1, v2, st->wYear);
7365   return S_OK;
7366 }
7367
7368 /******************************************************************************
7369  * VarDateFromStr [OLEAUT32.94]
7370  *
7371  * Convert a VT_BSTR to at VT_DATE.
7372  *
7373  * PARAMS
7374  *  strIn    [I] String to convert
7375  *  lcid     [I] Locale identifier for the conversion
7376  *  dwFlags  [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
7377  *  pdateOut [O] Destination for the converted value
7378  *
7379  * RETURNS
7380  *  Success: S_OK. pdateOut contains the converted value.
7381  *  FAILURE: An HRESULT error code indicating the problem.
7382  *
7383  * NOTES
7384  *  Any date format that can be created using the date formats from lcid
7385  *  (Either from kernel Nls functions, variant conversion or formatting) is a
7386  *  valid input to this function. In addition, a few more esoteric formats are
7387  *  also supported for compatibility with the native version. The date is
7388  *  interpreted according to the date settings in the control panel, unless
7389  *  the date is invalid in that format, in which the most compatible format
7390  *  that produces a valid date will be used.
7391  */
7392 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
7393 {
7394   static const USHORT ParseDateTokens[] =
7395   {
7396     LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
7397     LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
7398     LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
7399     LOCALE_SMONTHNAME13,
7400     LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
7401     LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
7402     LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
7403     LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
7404     LOCALE_SABBREVMONTHNAME13,
7405     LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
7406     LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
7407     LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
7408     LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
7409     LOCALE_SABBREVDAYNAME7,
7410     LOCALE_S1159, LOCALE_S2359
7411   };
7412   static const BYTE ParseDateMonths[] =
7413   {
7414     1,2,3,4,5,6,7,8,9,10,11,12,13,
7415     1,2,3,4,5,6,7,8,9,10,11,12,13
7416   };
7417   unsigned int i;
7418   BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
7419   DATEPARSE dp;
7420   DWORD dwDateSeps = 0, iDate = 0;
7421   HRESULT hRet = S_OK;
7422
7423   if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
7424       (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
7425     return E_INVALIDARG;
7426
7427   if (!strIn)
7428     return DISP_E_TYPEMISMATCH;
7429
7430   *pdateOut = 0.0;
7431
7432   TRACE("(%s,0x%08x,0x%08x,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
7433
7434   memset(&dp, 0, sizeof(dp));
7435
7436   GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
7437                  (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
7438   TRACE("iDate is %d\n", iDate);
7439
7440   /* Get the month/day/am/pm tokens for this locale */
7441   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7442   {
7443     WCHAR buff[128];
7444     LCTYPE lctype =  ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
7445
7446     /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
7447      *        GetAltMonthNames(). We should really cache these strings too.
7448      */
7449     buff[0] = '\0';
7450     GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
7451     tokens[i] = SysAllocString(buff);
7452     TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
7453   }
7454
7455   /* Parse the string into our structure */
7456   while (*strIn)
7457   {
7458     if (dp.dwCount >= 6)
7459       break;
7460
7461     if (isdigitW(*strIn))
7462     {
7463       dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
7464       dp.dwCount++;
7465       strIn--;
7466     }
7467     else if (isalpha(*strIn))
7468     {
7469       BOOL bFound = FALSE;
7470
7471       for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7472       {
7473         DWORD dwLen = strlenW(tokens[i]);
7474         if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
7475         {
7476           if (i <= 25)
7477           {
7478             dp.dwValues[dp.dwCount] = ParseDateMonths[i];
7479             dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
7480             dp.dwCount++;
7481           }
7482           else if (i > 39)
7483           {
7484             if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
7485               hRet = DISP_E_TYPEMISMATCH;
7486             else
7487             {
7488               dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
7489               dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
7490             }
7491           }
7492           strIn += (dwLen - 1);
7493           bFound = TRUE;
7494           break;
7495         }
7496       }
7497
7498       if (!bFound)
7499       {
7500         if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
7501             (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7502         {
7503           /* Special case - 'a' and 'p' are recognised as short for am/pm */
7504           if (*strIn == 'a' || *strIn == 'A')
7505           {
7506             dp.dwFlags[dp.dwCount - 1] |= DP_AM;
7507             dp.dwParseFlags |=  DP_AM;
7508           }
7509           else
7510           {
7511             dp.dwFlags[dp.dwCount - 1] |= DP_PM;
7512             dp.dwParseFlags |=  DP_PM;
7513           }
7514           strIn++;
7515         }
7516         else
7517         {
7518           TRACE("No matching token for %s\n", debugstr_w(strIn));
7519           hRet = DISP_E_TYPEMISMATCH;
7520           break;
7521         }
7522       }
7523     }
7524     else if (*strIn == ':' ||  *strIn == '.')
7525     {
7526       if (!dp.dwCount || !strIn[1])
7527         hRet = DISP_E_TYPEMISMATCH;
7528       else
7529         dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
7530     }
7531     else if (*strIn == '-' || *strIn == '/')
7532     {
7533       dwDateSeps++;
7534       if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
7535         hRet = DISP_E_TYPEMISMATCH;
7536       else
7537         dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
7538     }
7539     else if (*strIn == ',' || isspaceW(*strIn))
7540     {
7541       if (*strIn == ',' && !strIn[1])
7542         hRet = DISP_E_TYPEMISMATCH;
7543     }
7544     else
7545     {
7546       hRet = DISP_E_TYPEMISMATCH;
7547     }
7548     strIn++;
7549   }
7550
7551   if (!dp.dwCount || dp.dwCount > 6 ||
7552       (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
7553     hRet = DISP_E_TYPEMISMATCH;
7554
7555   if (SUCCEEDED(hRet))
7556   {
7557     SYSTEMTIME st;
7558     DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
7559
7560     st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
7561
7562     /* Figure out which numbers correspond to which fields.
7563      *
7564      * This switch statement works based on the fact that native interprets any
7565      * fields that are not joined with a time separator ('.' or ':') as date
7566      * fields. Thus we construct a value from 0-32 where each set bit indicates
7567      * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
7568      * For valid permutations, we set dwOffset to point to the first date field
7569      * and shorten dp.dwCount by the number of time fields found. The real
7570      * magic here occurs in VARIANT_MakeDate() above, where we determine what
7571      * each date number must represent in the context of iDate.
7572      */
7573     TRACE("0x%08x\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
7574
7575     switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
7576     {
7577     case 0x1: /* TT TTDD TTDDD */
7578       if (dp.dwCount > 3 &&
7579           ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
7580           (dp.dwFlags[4] & (DP_AM|DP_PM))))
7581         hRet = DISP_E_TYPEMISMATCH;
7582       else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
7583         hRet = DISP_E_TYPEMISMATCH;
7584       st.wHour = dp.dwValues[0];
7585       st.wMinute  = dp.dwValues[1];
7586       dp.dwCount -= 2;
7587       dwOffset = 2;
7588       break;
7589
7590     case 0x3: /* TTT TTTDD TTTDDD */
7591       if (dp.dwCount > 4 &&
7592           ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
7593           (dp.dwFlags[5] & (DP_AM|DP_PM))))
7594         hRet = DISP_E_TYPEMISMATCH;
7595       else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
7596         hRet = DISP_E_TYPEMISMATCH;
7597       st.wHour   = dp.dwValues[0];
7598       st.wMinute = dp.dwValues[1];
7599       st.wSecond = dp.dwValues[2];
7600       dwOffset = 3;
7601       dp.dwCount -= 3;
7602       break;
7603
7604     case 0x4: /* DDTT */
7605       if (dp.dwCount != 4 ||
7606           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7607         hRet = DISP_E_TYPEMISMATCH;
7608
7609       st.wHour = dp.dwValues[2];
7610       st.wMinute  = dp.dwValues[3];
7611       dp.dwCount -= 2;
7612       break;
7613
7614    case 0x0: /* T DD DDD TDDD TDDD */
7615       if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
7616       {
7617         st.wHour = dp.dwValues[0]; /* T */
7618         dp.dwCount = 0;
7619         break;
7620       }
7621       else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
7622       {
7623         hRet = DISP_E_TYPEMISMATCH;
7624       }
7625       else if (dp.dwCount == 3)
7626       {
7627         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
7628         {
7629           dp.dwCount = 2;
7630           st.wHour = dp.dwValues[0];
7631           dwOffset = 1;
7632           break;
7633         }
7634         if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
7635         {
7636           dp.dwCount = 2;
7637           st.wHour = dp.dwValues[2];
7638           break;
7639         }
7640         else if (dp.dwParseFlags & (DP_AM|DP_PM))
7641           hRet = DISP_E_TYPEMISMATCH;
7642       }
7643       else if (dp.dwCount == 4)
7644       {
7645         dp.dwCount = 3;
7646         if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
7647         {
7648           st.wHour = dp.dwValues[0];
7649           dwOffset = 1;
7650         }
7651         else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
7652         {
7653           st.wHour = dp.dwValues[3];
7654         }
7655         else
7656           hRet = DISP_E_TYPEMISMATCH;
7657         break;
7658       }
7659       /* .. fall through .. */
7660
7661     case 0x8: /* DDDTT */
7662       if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
7663           (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
7664            (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
7665            dp.dwCount == 4 || dp.dwCount == 6)
7666         hRet = DISP_E_TYPEMISMATCH;
7667       st.wHour   = dp.dwValues[3];
7668       st.wMinute = dp.dwValues[4];
7669       if (dp.dwCount == 5)
7670         dp.dwCount -= 2;
7671       break;
7672
7673     case 0xC: /* DDTTT */
7674       if (dp.dwCount != 5 ||
7675           (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
7676         hRet = DISP_E_TYPEMISMATCH;
7677       st.wHour   = dp.dwValues[2];
7678       st.wMinute = dp.dwValues[3];
7679       st.wSecond = dp.dwValues[4];
7680       dp.dwCount -= 3;
7681       break;
7682
7683     case 0x18: /* DDDTTT */
7684       if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
7685           (dp.dwFlags[2] & (DP_AM|DP_PM)))
7686         hRet = DISP_E_TYPEMISMATCH;
7687       st.wHour   = dp.dwValues[3];
7688       st.wMinute = dp.dwValues[4];
7689       st.wSecond = dp.dwValues[5];
7690       dp.dwCount -= 3;
7691       break;
7692
7693     default:
7694       hRet = DISP_E_TYPEMISMATCH;
7695       break;
7696     }
7697
7698     if (SUCCEEDED(hRet))
7699     {
7700       hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
7701
7702       if (dwFlags & VAR_TIMEVALUEONLY)
7703       {
7704         st.wYear = 1899;
7705         st.wMonth = 12;
7706         st.wDay = 30;
7707       }
7708       else if (dwFlags & VAR_DATEVALUEONLY)
7709        st.wHour = st.wMinute = st.wSecond = 0;
7710
7711       /* Finally, convert the value to a VT_DATE */
7712       if (SUCCEEDED(hRet))
7713         hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
7714     }
7715   }
7716
7717   for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
7718     SysFreeString(tokens[i]);
7719   return hRet;
7720 }
7721
7722 /******************************************************************************
7723  * VarDateFromI1 (OLEAUT32.221)
7724  *
7725  * Convert a VT_I1 to a VT_DATE.
7726  *
7727  * PARAMS
7728  *  cIn      [I] Source
7729  *  pdateOut [O] Destination
7730  *
7731  * RETURNS
7732  *  S_OK.
7733  */
7734 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
7735 {
7736   return VarR8FromI1(cIn, pdateOut);
7737 }
7738
7739 /******************************************************************************
7740  * VarDateFromUI2 (OLEAUT32.222)
7741  *
7742  * Convert a VT_UI2 to a VT_DATE.
7743  *
7744  * PARAMS
7745  *  uiIn     [I] Source
7746  *  pdateOut [O] Destination
7747  *
7748  * RETURNS
7749  *  S_OK.
7750  */
7751 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
7752 {
7753   return VarR8FromUI2(uiIn, pdateOut);
7754 }
7755
7756 /******************************************************************************
7757  * VarDateFromUI4 (OLEAUT32.223)
7758  *
7759  * Convert a VT_UI4 to a VT_DATE.
7760  *
7761  * PARAMS
7762  *  ulIn     [I] Source
7763  *  pdateOut [O] Destination
7764  *
7765  * RETURNS
7766  *  S_OK.
7767  */
7768 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
7769 {
7770   return VarDateFromR8(ulIn, pdateOut);
7771 }
7772
7773 /**********************************************************************
7774  * VarDateFromDec (OLEAUT32.224)
7775  *
7776  * Convert a VT_DECIMAL to a VT_DATE.
7777  *
7778  * PARAMS
7779  *  pdecIn   [I] Source
7780  *  pdateOut [O] Destination
7781  *
7782  * RETURNS
7783  *  S_OK.
7784  */
7785 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
7786 {
7787   return VarR8FromDec(pdecIn, pdateOut);
7788 }
7789
7790 /******************************************************************************
7791  * VarDateFromI8 (OLEAUT32.364)
7792  *
7793  * Convert a VT_I8 to a VT_DATE.
7794  *
7795  * PARAMS
7796  *  llIn     [I] Source
7797  *  pdateOut [O] Destination
7798  *
7799  * RETURNS
7800  *  Success: S_OK.
7801  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
7802  */
7803 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
7804 {
7805   if (llIn < DATE_MIN || llIn > DATE_MAX) return DISP_E_OVERFLOW;
7806   *pdateOut = (DATE)llIn;
7807   return S_OK;
7808 }
7809
7810 /******************************************************************************
7811  * VarDateFromUI8 (OLEAUT32.365)
7812  *
7813  * Convert a VT_UI8 to a VT_DATE.
7814  *
7815  * PARAMS
7816  *  ullIn    [I] Source
7817  *  pdateOut [O] Destination
7818  *
7819  * RETURNS
7820  *  Success: S_OK.
7821  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
7822  */
7823 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
7824 {
7825   if (ullIn > DATE_MAX) return DISP_E_OVERFLOW;
7826   *pdateOut = (DATE)ullIn;
7827   return S_OK;
7828 }