~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/oleaut32/vartype.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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)