[OLEAUT32]
[reactos.git] / reactos / dll / win32 / oleaut32 / vartype.c
1 /*
2 * Low level variant functions
3 *
4 * Copyright 2003 Jon Griffiths
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "precomp.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(variant);
24
25 extern HMODULE hProxyDll DECLSPEC_HIDDEN;
26
27 #define CY_MULTIPLIER 10000 /* 4 dp of precision */
28 #define CY_MULTIPLIER_F 10000.0
29 #define CY_HALF (CY_MULTIPLIER/2) /* 0.5 */
30 #define CY_HALF_F (CY_MULTIPLIER_F/2.0)
31
32 static const WCHAR szFloatFormatW[] = { '%','.','7','G','\0' };
33 static const WCHAR szDoubleFormatW[] = { '%','.','1','5','G','\0' };
34
35 /* Copy data from one variant to another. */
36 static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
37 {
38 switch (vt)
39 {
40 case VT_I1:
41 case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
42 case VT_BOOL:
43 case VT_I2:
44 case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
45 case VT_R4:
46 case VT_INT:
47 case VT_I4:
48 case VT_UINT:
49 case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
50 case VT_R8:
51 case VT_DATE:
52 case VT_CY:
53 case VT_I8:
54 case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
55 case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
56 case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
57 case VT_BSTR: memcpy(pOut, &V_BSTR(srcVar), sizeof(BSTR)); break;
58 default:
59 FIXME("VT_ type %d unhandled, please report!\n", vt);
60 }
61 }
62
63 /* Macro to inline conversion from a float or double to any integer type,
64 * rounding according to the 'dutch' convention.
65 */
66 #define VARIANT_DutchRound(typ, value, res) do { \
67 double whole = value < 0 ? ceil(value) : floor(value); \
68 double fract = value - whole; \
69 if (fract > 0.5) res = (typ)whole + (typ)1; \
70 else if (fract == 0.5) { typ is_odd = (typ)whole & 1; res = whole + is_odd; } \
71 else if (fract >= 0.0) res = (typ)whole; \
72 else if (fract == -0.5) { typ is_odd = (typ)whole & 1; res = whole - is_odd; } \
73 else if (fract > -0.5) res = (typ)whole; \
74 else res = (typ)whole - (typ)1; \
75 } while(0)
76
77
78 /* Coerce VT_BSTR to a numeric type */
79 static HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
80 void* pOut, VARTYPE vt)
81 {
82 VARIANTARG dstVar;
83 HRESULT hRet;
84 NUMPARSE np;
85 BYTE rgb[1024];
86
87 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
88 np.cDig = sizeof(rgb) / sizeof(BYTE);
89 np.dwInFlags = NUMPRS_STD;
90
91 hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
92
93 if (SUCCEEDED(hRet))
94 {
95 /* 1 << vt gives us the VTBIT constant for the destination number type */
96 hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
97 if (SUCCEEDED(hRet))
98 VARIANT_CopyData(&dstVar, vt, pOut);
99 }
100 return hRet;
101 }
102
103 /* Coerce VT_DISPATCH to another type */
104 static HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut,
105 VARTYPE vt, DWORD dwFlags)
106 {
107 static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
108 VARIANTARG srcVar, dstVar;
109 HRESULT hRet;
110
111 if (!pdispIn)
112 return DISP_E_BADVARTYPE;
113
114 /* Get the default 'value' property from the IDispatch */
115 VariantInit(&srcVar);
116 hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
117 &emptyParams, &srcVar, NULL, NULL);
118
119 if (SUCCEEDED(hRet))
120 {
121 /* Convert the property to the requested type */
122 V_VT(&dstVar) = VT_EMPTY;
123 hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, dwFlags, vt);
124 VariantClear(&srcVar);
125
126 if (SUCCEEDED(hRet))
127 {
128 VARIANT_CopyData(&dstVar, vt, pOut);
129 VariantClear(&srcVar);
130 }
131 }
132 else
133 hRet = DISP_E_TYPEMISMATCH;
134 return hRet;
135 }
136
137 /* Inline return type */
138 #define RETTYP static inline HRESULT
139
140
141 /* Simple compiler cast from one type to another */
142 #define SIMPLE(dest, src, func) RETTYP _##func(src in, dest* out) { \
143 *out = in; return S_OK; }
144
145 /* Compiler cast where input cannot be negative */
146 #define NEGTST(dest, src, func) RETTYP _##func(src in, dest* out) { \
147 if (in < 0) return DISP_E_OVERFLOW; *out = in; return S_OK; }
148
149 /* Compiler cast where input cannot be > some number */
150 #define POSTST(dest, src, func, tst) RETTYP _##func(src in, dest* out) { \
151 if (in > (dest)tst) return DISP_E_OVERFLOW; *out = in; return S_OK; }
152
153 /* Compiler cast where input cannot be < some number or >= some other number */
154 #define BOTHTST(dest, src, func, lo, hi) RETTYP _##func(src in, dest* out) { \
155 if (in < (dest)lo || in > hi) return DISP_E_OVERFLOW; *out = in; return S_OK; }
156
157 /* I1 */
158 POSTST(signed char, BYTE, VarI1FromUI1, I1_MAX)
159 BOTHTST(signed char, SHORT, VarI1FromI2, I1_MIN, I1_MAX)
160 BOTHTST(signed char, LONG, VarI1FromI4, I1_MIN, I1_MAX)
161 SIMPLE(signed char, VARIANT_BOOL, VarI1FromBool)
162 POSTST(signed char, USHORT, VarI1FromUI2, I1_MAX)
163 POSTST(signed char, ULONG, VarI1FromUI4, I1_MAX)
164 BOTHTST(signed char, LONG64, VarI1FromI8, I1_MIN, I1_MAX)
165 POSTST(signed char, ULONG64, VarI1FromUI8, I1_MAX)
166
167 /* UI1 */
168 BOTHTST(BYTE, SHORT, VarUI1FromI2, UI1_MIN, UI1_MAX)
169 SIMPLE(BYTE, VARIANT_BOOL, VarUI1FromBool)
170 NEGTST(BYTE, signed char, VarUI1FromI1)
171 POSTST(BYTE, USHORT, VarUI1FromUI2, UI1_MAX)
172 BOTHTST(BYTE, LONG, VarUI1FromI4, UI1_MIN, UI1_MAX)
173 POSTST(BYTE, ULONG, VarUI1FromUI4, UI1_MAX)
174 BOTHTST(BYTE, LONG64, VarUI1FromI8, UI1_MIN, UI1_MAX)
175 POSTST(BYTE, ULONG64, VarUI1FromUI8, UI1_MAX)
176
177 /* I2 */
178 SIMPLE(SHORT, BYTE, VarI2FromUI1)
179 BOTHTST(SHORT, LONG, VarI2FromI4, I2_MIN, I2_MAX)
180 SIMPLE(SHORT, VARIANT_BOOL, VarI2FromBool)
181 SIMPLE(SHORT, signed char, VarI2FromI1)
182 POSTST(SHORT, USHORT, VarI2FromUI2, I2_MAX)
183 POSTST(SHORT, ULONG, VarI2FromUI4, I2_MAX)
184 BOTHTST(SHORT, LONG64, VarI2FromI8, I2_MIN, I2_MAX)
185 POSTST(SHORT, ULONG64, VarI2FromUI8, I2_MAX)
186
187 /* UI2 */
188 SIMPLE(USHORT, BYTE, VarUI2FromUI1)
189 NEGTST(USHORT, SHORT, VarUI2FromI2)
190 BOTHTST(USHORT, LONG, VarUI2FromI4, UI2_MIN, UI2_MAX)
191 SIMPLE(USHORT, VARIANT_BOOL, VarUI2FromBool)
192 NEGTST(USHORT, signed char, VarUI2FromI1)
193 POSTST(USHORT, ULONG, VarUI2FromUI4, UI2_MAX)
194 BOTHTST(USHORT, LONG64, VarUI2FromI8, UI2_MIN, UI2_MAX)
195 POSTST(USHORT, ULONG64, VarUI2FromUI8, UI2_MAX)
196
197 /* I4 */
198 SIMPLE(LONG, BYTE, VarI4FromUI1)
199 SIMPLE(LONG, SHORT, VarI4FromI2)
200 SIMPLE(LONG, VARIANT_BOOL, VarI4FromBool)
201 SIMPLE(LONG, signed char, VarI4FromI1)
202 SIMPLE(LONG, USHORT, VarI4FromUI2)
203 POSTST(LONG, ULONG, VarI4FromUI4, I4_MAX)
204 BOTHTST(LONG, LONG64, VarI4FromI8, I4_MIN, I4_MAX)
205 POSTST(LONG, ULONG64, VarI4FromUI8, I4_MAX)
206
207 /* UI4 */
208 SIMPLE(ULONG, BYTE, VarUI4FromUI1)
209 NEGTST(ULONG, SHORT, VarUI4FromI2)
210 NEGTST(ULONG, LONG, VarUI4FromI4)
211 SIMPLE(ULONG, VARIANT_BOOL, VarUI4FromBool)
212 NEGTST(ULONG, signed char, VarUI4FromI1)
213 SIMPLE(ULONG, USHORT, VarUI4FromUI2)
214 BOTHTST(ULONG, LONG64, VarUI4FromI8, UI4_MIN, UI4_MAX)
215 POSTST(ULONG, ULONG64, VarUI4FromUI8, UI4_MAX)
216
217 /* I8 */
218 SIMPLE(LONG64, BYTE, VarI8FromUI1)
219 SIMPLE(LONG64, SHORT, VarI8FromI2)
220 SIMPLE(LONG64, signed char, VarI8FromI1)
221 SIMPLE(LONG64, USHORT, VarI8FromUI2)
222 SIMPLE(LONG64, ULONG, VarI8FromUI4)
223 POSTST(LONG64, ULONG64, VarI8FromUI8, I8_MAX)
224
225 /* UI8 */
226 SIMPLE(ULONG64, BYTE, VarUI8FromUI1)
227 NEGTST(ULONG64, SHORT, VarUI8FromI2)
228 NEGTST(ULONG64, signed char, VarUI8FromI1)
229 SIMPLE(ULONG64, USHORT, VarUI8FromUI2)
230 SIMPLE(ULONG64, ULONG, VarUI8FromUI4)
231 NEGTST(ULONG64, LONG64, VarUI8FromI8)
232
233 /* R4 (float) */
234 SIMPLE(float, BYTE, VarR4FromUI1)
235 SIMPLE(float, SHORT, VarR4FromI2)
236 SIMPLE(float, signed char, VarR4FromI1)
237 SIMPLE(float, USHORT, VarR4FromUI2)
238 SIMPLE(float, LONG, VarR4FromI4)
239 SIMPLE(float, ULONG, VarR4FromUI4)
240 SIMPLE(float, LONG64, VarR4FromI8)
241 SIMPLE(float, ULONG64, VarR4FromUI8)
242
243 /* R8 (double) */
244 SIMPLE(double, BYTE, VarR8FromUI1)
245 SIMPLE(double, SHORT, VarR8FromI2)
246 SIMPLE(double, float, VarR8FromR4)
247 RETTYP _VarR8FromCy(CY i, double* o) { *o = (double)i.int64 / CY_MULTIPLIER_F; return S_OK; }
248 SIMPLE(double, DATE, VarR8FromDate)
249 SIMPLE(double, signed char, VarR8FromI1)
250 SIMPLE(double, USHORT, VarR8FromUI2)
251 SIMPLE(double, LONG, VarR8FromI4)
252 SIMPLE(double, ULONG, VarR8FromUI4)
253 SIMPLE(double, LONG64, VarR8FromI8)
254 SIMPLE(double, ULONG64, VarR8FromUI8)
255
256
257 /* I1
258 */
259
260 /************************************************************************
261 * VarI1FromUI1 (OLEAUT32.244)
262 *
263 * Convert a VT_UI1 to a VT_I1.
264 *
265 * PARAMS
266 * bIn [I] Source
267 * pcOut [O] Destination
268 *
269 * RETURNS
270 * Success: S_OK.
271 * Failure: E_INVALIDARG, if the source value is invalid
272 * DISP_E_OVERFLOW, if the value will not fit in the destination
273 */
274 HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
275 {
276 return _VarI1FromUI1(bIn, pcOut);
277 }
278
279 /************************************************************************
280 * VarI1FromI2 (OLEAUT32.245)
281 *
282 * Convert a VT_I2 to a VT_I1.
283 *
284 * PARAMS
285 * sIn [I] Source
286 * pcOut [O] Destination
287 *
288 * RETURNS
289 * Success: S_OK.
290 * Failure: E_INVALIDARG, if the source value is invalid
291 * DISP_E_OVERFLOW, if the value will not fit in the destination
292 */
293 HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
294 {
295 return _VarI1FromI2(sIn, pcOut);
296 }
297
298 /************************************************************************
299 * VarI1FromI4 (OLEAUT32.246)
300 *
301 * Convert a VT_I4 to a VT_I1.
302 *
303 * PARAMS
304 * iIn [I] Source
305 * pcOut [O] Destination
306 *
307 * RETURNS
308 * Success: S_OK.
309 * Failure: E_INVALIDARG, if the source value is invalid
310 * DISP_E_OVERFLOW, if the value will not fit in the destination
311 */
312 HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
313 {
314 return _VarI1FromI4(iIn, pcOut);
315 }
316
317 /************************************************************************
318 * VarI1FromR4 (OLEAUT32.247)
319 *
320 * Convert a VT_R4 to a VT_I1.
321 *
322 * PARAMS
323 * fltIn [I] Source
324 * pcOut [O] Destination
325 *
326 * RETURNS
327 * Success: S_OK.
328 * Failure: E_INVALIDARG, if the source value is invalid
329 * DISP_E_OVERFLOW, if the value will not fit in the destination
330 */
331 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
332 {
333 return VarI1FromR8(fltIn, pcOut);
334 }
335
336 /************************************************************************
337 * VarI1FromR8 (OLEAUT32.248)
338 *
339 * Convert a VT_R8 to a VT_I1.
340 *
341 * PARAMS
342 * dblIn [I] Source
343 * pcOut [O] Destination
344 *
345 * RETURNS
346 * Success: S_OK.
347 * Failure: E_INVALIDARG, if the source value is invalid
348 * DISP_E_OVERFLOW, if the value will not fit in the destination
349 *
350 * NOTES
351 * See VarI8FromR8() for details concerning rounding.
352 */
353 HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
354 {
355 if (dblIn < I1_MIN - 0.5 || dblIn >= I1_MAX + 0.5)
356 return DISP_E_OVERFLOW;
357 VARIANT_DutchRound(CHAR, dblIn, *pcOut);
358 return S_OK;
359 }
360
361 /************************************************************************
362 * VarI1FromDate (OLEAUT32.249)
363 *
364 * Convert a VT_DATE to a VT_I1.
365 *
366 * PARAMS
367 * dateIn [I] Source
368 * pcOut [O] Destination
369 *
370 * RETURNS
371 * Success: S_OK.
372 * Failure: E_INVALIDARG, if the source value is invalid
373 * DISP_E_OVERFLOW, if the value will not fit in the destination
374 */
375 HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
376 {
377 return VarI1FromR8(dateIn, pcOut);
378 }
379
380 /************************************************************************
381 * VarI1FromCy (OLEAUT32.250)
382 *
383 * Convert a VT_CY to a VT_I1.
384 *
385 * PARAMS
386 * cyIn [I] Source
387 * pcOut [O] Destination
388 *
389 * RETURNS
390 * Success: S_OK.
391 * Failure: E_INVALIDARG, if the source value is invalid
392 * DISP_E_OVERFLOW, if the value will not fit in the destination
393 */
394 HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
395 {
396 LONG i = I1_MAX + 1;
397
398 VarI4FromCy(cyIn, &i);
399 return _VarI1FromI4(i, pcOut);
400 }
401
402 /************************************************************************
403 * VarI1FromStr (OLEAUT32.251)
404 *
405 * Convert a VT_BSTR to a VT_I1.
406 *
407 * PARAMS
408 * strIn [I] Source
409 * lcid [I] LCID for the conversion
410 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
411 * pcOut [O] Destination
412 *
413 * RETURNS
414 * Success: S_OK.
415 * Failure: E_INVALIDARG, if the source value is invalid
416 * DISP_E_OVERFLOW, if the value will not fit in the destination
417 * DISP_E_TYPEMISMATCH, if the type cannot be converted
418 */
419 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
420 {
421 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pcOut, VT_I1);
422 }
423
424 /************************************************************************
425 * VarI1FromDisp (OLEAUT32.252)
426 *
427 * Convert a VT_DISPATCH to a VT_I1.
428 *
429 * PARAMS
430 * pdispIn [I] Source
431 * lcid [I] LCID for conversion
432 * pcOut [O] Destination
433 *
434 * RETURNS
435 * Success: S_OK.
436 * Failure: E_INVALIDARG, if the source value is invalid
437 * DISP_E_OVERFLOW, if the value will not fit in the destination
438 * DISP_E_TYPEMISMATCH, if the type cannot be converted
439 */
440 HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
441 {
442 return VARIANT_FromDisp(pdispIn, lcid, pcOut, VT_I1, 0);
443 }
444
445 /************************************************************************
446 * VarI1FromBool (OLEAUT32.253)
447 *
448 * Convert a VT_BOOL to a VT_I1.
449 *
450 * PARAMS
451 * boolIn [I] Source
452 * pcOut [O] Destination
453 *
454 * RETURNS
455 * S_OK.
456 */
457 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
458 {
459 return _VarI1FromBool(boolIn, pcOut);
460 }
461
462 /************************************************************************
463 * VarI1FromUI2 (OLEAUT32.254)
464 *
465 * Convert a VT_UI2 to a VT_I1.
466 *
467 * PARAMS
468 * usIn [I] Source
469 * pcOut [O] Destination
470 *
471 * RETURNS
472 * Success: S_OK.
473 * Failure: E_INVALIDARG, if the source value is invalid
474 * DISP_E_OVERFLOW, if the value will not fit in the destination
475 */
476 HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
477 {
478 return _VarI1FromUI2(usIn, pcOut);
479 }
480
481 /************************************************************************
482 * VarI1FromUI4 (OLEAUT32.255)
483 *
484 * Convert a VT_UI4 to a VT_I1.
485 *
486 * PARAMS
487 * ulIn [I] Source
488 * pcOut [O] Destination
489 *
490 * RETURNS
491 * Success: S_OK.
492 * Failure: E_INVALIDARG, if the source value is invalid
493 * DISP_E_OVERFLOW, if the value will not fit in the destination
494 * DISP_E_TYPEMISMATCH, if the type cannot be converted
495 */
496 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
497 {
498 return _VarI1FromUI4(ulIn, pcOut);
499 }
500
501 /************************************************************************
502 * VarI1FromDec (OLEAUT32.256)
503 *
504 * Convert a VT_DECIMAL to a VT_I1.
505 *
506 * PARAMS
507 * pDecIn [I] Source
508 * pcOut [O] Destination
509 *
510 * RETURNS
511 * Success: S_OK.
512 * Failure: E_INVALIDARG, if the source value is invalid
513 * DISP_E_OVERFLOW, if the value will not fit in the destination
514 */
515 HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
516 {
517 LONG64 i64;
518 HRESULT hRet;
519
520 hRet = VarI8FromDec(pdecIn, &i64);
521
522 if (SUCCEEDED(hRet))
523 hRet = _VarI1FromI8(i64, pcOut);
524 return hRet;
525 }
526
527 /************************************************************************
528 * VarI1FromI8 (OLEAUT32.376)
529 *
530 * Convert a VT_I8 to a VT_I1.
531 *
532 * PARAMS
533 * llIn [I] Source
534 * pcOut [O] Destination
535 *
536 * RETURNS
537 * Success: S_OK.
538 * Failure: E_INVALIDARG, if the source value is invalid
539 * DISP_E_OVERFLOW, if the value will not fit in the destination
540 */
541 HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
542 {
543 return _VarI1FromI8(llIn, pcOut);
544 }
545
546 /************************************************************************
547 * VarI1FromUI8 (OLEAUT32.377)
548 *
549 * Convert a VT_UI8 to a VT_I1.
550 *
551 * PARAMS
552 * ullIn [I] Source
553 * pcOut [O] Destination
554 *
555 * RETURNS
556 * Success: S_OK.
557 * Failure: E_INVALIDARG, if the source value is invalid
558 * DISP_E_OVERFLOW, if the value will not fit in the destination
559 */
560 HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
561 {
562 return _VarI1FromUI8(ullIn, pcOut);
563 }
564
565 /* UI1
566 */
567
568 /************************************************************************
569 * VarUI1FromI2 (OLEAUT32.130)
570 *
571 * Convert a VT_I2 to a VT_UI1.
572 *
573 * PARAMS
574 * sIn [I] Source
575 * pbOut [O] Destination
576 *
577 * RETURNS
578 * Success: S_OK.
579 * Failure: E_INVALIDARG, if the source value is invalid
580 * DISP_E_OVERFLOW, if the value will not fit in the destination
581 */
582 HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
583 {
584 return _VarUI1FromI2(sIn, pbOut);
585 }
586
587 /************************************************************************
588 * VarUI1FromI4 (OLEAUT32.131)
589 *
590 * Convert a VT_I4 to a VT_UI1.
591 *
592 * PARAMS
593 * iIn [I] Source
594 * pbOut [O] Destination
595 *
596 * RETURNS
597 * Success: S_OK.
598 * Failure: E_INVALIDARG, if the source value is invalid
599 * DISP_E_OVERFLOW, if the value will not fit in the destination
600 */
601 HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
602 {
603 return _VarUI1FromI4(iIn, pbOut);
604 }
605
606 /************************************************************************
607 * VarUI1FromR4 (OLEAUT32.132)
608 *
609 * Convert a VT_R4 to a VT_UI1.
610 *
611 * PARAMS
612 * fltIn [I] Source
613 * pbOut [O] Destination
614 *
615 * RETURNS
616 * Success: S_OK.
617 * Failure: E_INVALIDARG, if the source value is invalid
618 * DISP_E_OVERFLOW, if the value will not fit in the destination
619 * DISP_E_TYPEMISMATCH, if the type cannot be converted
620 */
621 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
622 {
623 return VarUI1FromR8(fltIn, pbOut);
624 }
625
626 /************************************************************************
627 * VarUI1FromR8 (OLEAUT32.133)
628 *
629 * Convert a VT_R8 to a VT_UI1.
630 *
631 * PARAMS
632 * dblIn [I] Source
633 * pbOut [O] Destination
634 *
635 * RETURNS
636 * Success: S_OK.
637 * Failure: E_INVALIDARG, if the source value is invalid
638 * DISP_E_OVERFLOW, if the value will not fit in the destination
639 *
640 * NOTES
641 * See VarI8FromR8() for details concerning rounding.
642 */
643 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
644 {
645 if (dblIn < -0.5 || dblIn >= UI1_MAX + 0.5)
646 return DISP_E_OVERFLOW;
647 VARIANT_DutchRound(BYTE, dblIn, *pbOut);
648 return S_OK;
649 }
650
651 /************************************************************************
652 * VarUI1FromCy (OLEAUT32.134)
653 *
654 * Convert a VT_CY to a VT_UI1.
655 *
656 * PARAMS
657 * cyIn [I] Source
658 * pbOut [O] Destination
659 *
660 * RETURNS
661 * Success: S_OK.
662 * Failure: E_INVALIDARG, if the source value is invalid
663 * DISP_E_OVERFLOW, if the value will not fit in the destination
664 *
665 * NOTES
666 * Negative values >= -5000 will be converted to 0.
667 */
668 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
669 {
670 ULONG i = UI1_MAX + 1;
671
672 VarUI4FromCy(cyIn, &i);
673 return _VarUI1FromUI4(i, pbOut);
674 }
675
676 /************************************************************************
677 * VarUI1FromDate (OLEAUT32.135)
678 *
679 * Convert a VT_DATE to a VT_UI1.
680 *
681 * PARAMS
682 * dateIn [I] Source
683 * pbOut [O] Destination
684 *
685 * RETURNS
686 * Success: S_OK.
687 * Failure: E_INVALIDARG, if the source value is invalid
688 * DISP_E_OVERFLOW, if the value will not fit in the destination
689 */
690 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
691 {
692 return VarUI1FromR8(dateIn, pbOut);
693 }
694
695 /************************************************************************
696 * VarUI1FromStr (OLEAUT32.136)
697 *
698 * Convert a VT_BSTR to a VT_UI1.
699 *
700 * PARAMS
701 * strIn [I] Source
702 * lcid [I] LCID for the conversion
703 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
704 * pbOut [O] Destination
705 *
706 * RETURNS
707 * Success: S_OK.
708 * Failure: E_INVALIDARG, if the source value is invalid
709 * DISP_E_OVERFLOW, if the value will not fit in the destination
710 * DISP_E_TYPEMISMATCH, if the type cannot be converted
711 */
712 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
713 {
714 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pbOut, VT_UI1);
715 }
716
717 /************************************************************************
718 * VarUI1FromDisp (OLEAUT32.137)
719 *
720 * Convert a VT_DISPATCH to a VT_UI1.
721 *
722 * PARAMS
723 * pdispIn [I] Source
724 * lcid [I] LCID for conversion
725 * pbOut [O] Destination
726 *
727 * RETURNS
728 * Success: S_OK.
729 * Failure: E_INVALIDARG, if the source value is invalid
730 * DISP_E_OVERFLOW, if the value will not fit in the destination
731 * DISP_E_TYPEMISMATCH, if the type cannot be converted
732 */
733 HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
734 {
735 return VARIANT_FromDisp(pdispIn, lcid, pbOut, VT_UI1, 0);
736 }
737
738 /************************************************************************
739 * VarUI1FromBool (OLEAUT32.138)
740 *
741 * Convert a VT_BOOL to a VT_UI1.
742 *
743 * PARAMS
744 * boolIn [I] Source
745 * pbOut [O] Destination
746 *
747 * RETURNS
748 * S_OK.
749 */
750 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
751 {
752 return _VarUI1FromBool(boolIn, pbOut);
753 }
754
755 /************************************************************************
756 * VarUI1FromI1 (OLEAUT32.237)
757 *
758 * Convert a VT_I1 to a VT_UI1.
759 *
760 * PARAMS
761 * cIn [I] Source
762 * pbOut [O] Destination
763 *
764 * RETURNS
765 * Success: S_OK.
766 * Failure: E_INVALIDARG, if the source value is invalid
767 * DISP_E_OVERFLOW, if the value will not fit in the destination
768 */
769 HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
770 {
771 return _VarUI1FromI1(cIn, pbOut);
772 }
773
774 /************************************************************************
775 * VarUI1FromUI2 (OLEAUT32.238)
776 *
777 * Convert a VT_UI2 to a VT_UI1.
778 *
779 * PARAMS
780 * usIn [I] Source
781 * pbOut [O] Destination
782 *
783 * RETURNS
784 * Success: S_OK.
785 * Failure: E_INVALIDARG, if the source value is invalid
786 * DISP_E_OVERFLOW, if the value will not fit in the destination
787 */
788 HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
789 {
790 return _VarUI1FromUI2(usIn, pbOut);
791 }
792
793 /************************************************************************
794 * VarUI1FromUI4 (OLEAUT32.239)
795 *
796 * Convert a VT_UI4 to a VT_UI1.
797 *
798 * PARAMS
799 * ulIn [I] Source
800 * pbOut [O] Destination
801 *
802 * RETURNS
803 * Success: S_OK.
804 * Failure: E_INVALIDARG, if the source value is invalid
805 * DISP_E_OVERFLOW, if the value will not fit in the destination
806 */
807 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
808 {
809 return _VarUI1FromUI4(ulIn, pbOut);
810 }
811
812 /************************************************************************
813 * VarUI1FromDec (OLEAUT32.240)
814 *
815 * Convert a VT_DECIMAL to a VT_UI1.
816 *
817 * PARAMS
818 * pDecIn [I] Source
819 * pbOut [O] Destination
820 *
821 * RETURNS
822 * Success: S_OK.
823 * Failure: E_INVALIDARG, if the source value is invalid
824 * DISP_E_OVERFLOW, if the value will not fit in the destination
825 */
826 HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
827 {
828 LONG64 i64;
829 HRESULT hRet;
830
831 hRet = VarI8FromDec(pdecIn, &i64);
832
833 if (SUCCEEDED(hRet))
834 hRet = _VarUI1FromI8(i64, pbOut);
835 return hRet;
836 }
837
838 /************************************************************************
839 * VarUI1FromI8 (OLEAUT32.372)
840 *
841 * Convert a VT_I8 to a VT_UI1.
842 *
843 * PARAMS
844 * llIn [I] Source
845 * pbOut [O] Destination
846 *
847 * RETURNS
848 * Success: S_OK.
849 * Failure: E_INVALIDARG, if the source value is invalid
850 * DISP_E_OVERFLOW, if the value will not fit in the destination
851 */
852 HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
853 {
854 return _VarUI1FromI8(llIn, pbOut);
855 }
856
857 /************************************************************************
858 * VarUI1FromUI8 (OLEAUT32.373)
859 *
860 * Convert a VT_UI8 to a VT_UI1.
861 *
862 * PARAMS
863 * ullIn [I] Source
864 * pbOut [O] Destination
865 *
866 * RETURNS
867 * Success: S_OK.
868 * Failure: E_INVALIDARG, if the source value is invalid
869 * DISP_E_OVERFLOW, if the value will not fit in the destination
870 */
871 HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
872 {
873 return _VarUI1FromUI8(ullIn, pbOut);
874 }
875
876
877 /* I2
878 */
879
880 /************************************************************************
881 * VarI2FromUI1 (OLEAUT32.48)
882 *
883 * Convert a VT_UI2 to a VT_I2.
884 *
885 * PARAMS
886 * bIn [I] Source
887 * psOut [O] Destination
888 *
889 * RETURNS
890 * S_OK.
891 */
892 HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
893 {
894 return _VarI2FromUI1(bIn, psOut);
895 }
896
897 /************************************************************************
898 * VarI2FromI4 (OLEAUT32.49)
899 *
900 * Convert a VT_I4 to a VT_I2.
901 *
902 * PARAMS
903 * iIn [I] Source
904 * psOut [O] Destination
905 *
906 * RETURNS
907 * Success: S_OK.
908 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
909 */
910 HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
911 {
912 return _VarI2FromI4(iIn, psOut);
913 }
914
915 /************************************************************************
916 * VarI2FromR4 (OLEAUT32.50)
917 *
918 * Convert a VT_R4 to a VT_I2.
919 *
920 * PARAMS
921 * fltIn [I] Source
922 * psOut [O] Destination
923 *
924 * RETURNS
925 * Success: S_OK.
926 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
927 */
928 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
929 {
930 return VarI2FromR8(fltIn, psOut);
931 }
932
933 /************************************************************************
934 * VarI2FromR8 (OLEAUT32.51)
935 *
936 * Convert a VT_R8 to a VT_I2.
937 *
938 * PARAMS
939 * dblIn [I] Source
940 * psOut [O] Destination
941 *
942 * RETURNS
943 * Success: S_OK.
944 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
945 *
946 * NOTES
947 * See VarI8FromR8() for details concerning rounding.
948 */
949 HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
950 {
951 if (dblIn < I2_MIN - 0.5 || dblIn >= I2_MAX + 0.5)
952 return DISP_E_OVERFLOW;
953 VARIANT_DutchRound(SHORT, dblIn, *psOut);
954 return S_OK;
955 }
956
957 /************************************************************************
958 * VarI2FromCy (OLEAUT32.52)
959 *
960 * Convert a VT_CY to a VT_I2.
961 *
962 * PARAMS
963 * cyIn [I] Source
964 * psOut [O] Destination
965 *
966 * RETURNS
967 * Success: S_OK.
968 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
969 */
970 HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
971 {
972 LONG i = I2_MAX + 1;
973
974 VarI4FromCy(cyIn, &i);
975 return _VarI2FromI4(i, psOut);
976 }
977
978 /************************************************************************
979 * VarI2FromDate (OLEAUT32.53)
980 *
981 * Convert a VT_DATE to a VT_I2.
982 *
983 * PARAMS
984 * dateIn [I] Source
985 * psOut [O] Destination
986 *
987 * RETURNS
988 * Success: S_OK.
989 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
990 */
991 HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
992 {
993 return VarI2FromR8(dateIn, psOut);
994 }
995
996 /************************************************************************
997 * VarI2FromStr (OLEAUT32.54)
998 *
999 * Convert a VT_BSTR to a VT_I2.
1000 *
1001 * PARAMS
1002 * strIn [I] Source
1003 * lcid [I] LCID for the conversion
1004 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1005 * psOut [O] Destination
1006 *
1007 * RETURNS
1008 * Success: S_OK.
1009 * Failure: E_INVALIDARG, if any parameter is invalid
1010 * DISP_E_OVERFLOW, if the value will not fit in the destination
1011 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1012 */
1013 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
1014 {
1015 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, psOut, VT_I2);
1016 }
1017
1018 /************************************************************************
1019 * VarI2FromDisp (OLEAUT32.55)
1020 *
1021 * Convert a VT_DISPATCH to a VT_I2.
1022 *
1023 * PARAMS
1024 * pdispIn [I] Source
1025 * lcid [I] LCID for conversion
1026 * psOut [O] Destination
1027 *
1028 * RETURNS
1029 * Success: S_OK.
1030 * Failure: E_INVALIDARG, if pdispIn is invalid,
1031 * DISP_E_OVERFLOW, if the value will not fit in the destination,
1032 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1033 */
1034 HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
1035 {
1036 return VARIANT_FromDisp(pdispIn, lcid, psOut, VT_I2, 0);
1037 }
1038
1039 /************************************************************************
1040 * VarI2FromBool (OLEAUT32.56)
1041 *
1042 * Convert a VT_BOOL to a VT_I2.
1043 *
1044 * PARAMS
1045 * boolIn [I] Source
1046 * psOut [O] Destination
1047 *
1048 * RETURNS
1049 * S_OK.
1050 */
1051 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
1052 {
1053 return _VarI2FromBool(boolIn, psOut);
1054 }
1055
1056 /************************************************************************
1057 * VarI2FromI1 (OLEAUT32.205)
1058 *
1059 * Convert a VT_I1 to a VT_I2.
1060 *
1061 * PARAMS
1062 * cIn [I] Source
1063 * psOut [O] Destination
1064 *
1065 * RETURNS
1066 * S_OK.
1067 */
1068 HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
1069 {
1070 return _VarI2FromI1(cIn, psOut);
1071 }
1072
1073 /************************************************************************
1074 * VarI2FromUI2 (OLEAUT32.206)
1075 *
1076 * Convert a VT_UI2 to a VT_I2.
1077 *
1078 * PARAMS
1079 * usIn [I] Source
1080 * psOut [O] Destination
1081 *
1082 * RETURNS
1083 * Success: S_OK.
1084 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1085 */
1086 HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
1087 {
1088 return _VarI2FromUI2(usIn, psOut);
1089 }
1090
1091 /************************************************************************
1092 * VarI2FromUI4 (OLEAUT32.207)
1093 *
1094 * Convert a VT_UI4 to a VT_I2.
1095 *
1096 * PARAMS
1097 * ulIn [I] Source
1098 * psOut [O] Destination
1099 *
1100 * RETURNS
1101 * Success: S_OK.
1102 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1103 */
1104 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
1105 {
1106 return _VarI2FromUI4(ulIn, psOut);
1107 }
1108
1109 /************************************************************************
1110 * VarI2FromDec (OLEAUT32.208)
1111 *
1112 * Convert a VT_DECIMAL to a VT_I2.
1113 *
1114 * PARAMS
1115 * pDecIn [I] Source
1116 * psOut [O] Destination
1117 *
1118 * RETURNS
1119 * Success: S_OK.
1120 * Failure: E_INVALIDARG, if the source value is invalid
1121 * DISP_E_OVERFLOW, if the value will not fit in the destination
1122 */
1123 HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
1124 {
1125 LONG64 i64;
1126 HRESULT hRet;
1127
1128 hRet = VarI8FromDec(pdecIn, &i64);
1129
1130 if (SUCCEEDED(hRet))
1131 hRet = _VarI2FromI8(i64, psOut);
1132 return hRet;
1133 }
1134
1135 /************************************************************************
1136 * VarI2FromI8 (OLEAUT32.346)
1137 *
1138 * Convert a VT_I8 to a VT_I2.
1139 *
1140 * PARAMS
1141 * llIn [I] Source
1142 * psOut [O] Destination
1143 *
1144 * RETURNS
1145 * Success: S_OK.
1146 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1147 */
1148 HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
1149 {
1150 return _VarI2FromI8(llIn, psOut);
1151 }
1152
1153 /************************************************************************
1154 * VarI2FromUI8 (OLEAUT32.347)
1155 *
1156 * Convert a VT_UI8 to a VT_I2.
1157 *
1158 * PARAMS
1159 * ullIn [I] Source
1160 * psOut [O] Destination
1161 *
1162 * RETURNS
1163 * Success: S_OK.
1164 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1165 */
1166 HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
1167 {
1168 return _VarI2FromUI8(ullIn, psOut);
1169 }
1170
1171 /* UI2
1172 */
1173
1174 /************************************************************************
1175 * VarUI2FromUI1 (OLEAUT32.257)
1176 *
1177 * Convert a VT_UI1 to a VT_UI2.
1178 *
1179 * PARAMS
1180 * bIn [I] Source
1181 * pusOut [O] Destination
1182 *
1183 * RETURNS
1184 * S_OK.
1185 */
1186 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
1187 {
1188 return _VarUI2FromUI1(bIn, pusOut);
1189 }
1190
1191 /************************************************************************
1192 * VarUI2FromI2 (OLEAUT32.258)
1193 *
1194 * Convert a VT_I2 to a VT_UI2.
1195 *
1196 * PARAMS
1197 * sIn [I] Source
1198 * pusOut [O] Destination
1199 *
1200 * RETURNS
1201 * Success: S_OK.
1202 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1203 */
1204 HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
1205 {
1206 return _VarUI2FromI2(sIn, pusOut);
1207 }
1208
1209 /************************************************************************
1210 * VarUI2FromI4 (OLEAUT32.259)
1211 *
1212 * Convert a VT_I4 to a VT_UI2.
1213 *
1214 * PARAMS
1215 * iIn [I] Source
1216 * pusOut [O] Destination
1217 *
1218 * RETURNS
1219 * Success: S_OK.
1220 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1221 */
1222 HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
1223 {
1224 return _VarUI2FromI4(iIn, pusOut);
1225 }
1226
1227 /************************************************************************
1228 * VarUI2FromR4 (OLEAUT32.260)
1229 *
1230 * Convert a VT_R4 to a VT_UI2.
1231 *
1232 * PARAMS
1233 * fltIn [I] Source
1234 * pusOut [O] Destination
1235 *
1236 * RETURNS
1237 * Success: S_OK.
1238 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1239 */
1240 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
1241 {
1242 return VarUI2FromR8(fltIn, pusOut);
1243 }
1244
1245 /************************************************************************
1246 * VarUI2FromR8 (OLEAUT32.261)
1247 *
1248 * Convert a VT_R8 to a VT_UI2.
1249 *
1250 * PARAMS
1251 * dblIn [I] Source
1252 * pusOut [O] Destination
1253 *
1254 * RETURNS
1255 * Success: S_OK.
1256 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1257 *
1258 * NOTES
1259 * See VarI8FromR8() for details concerning rounding.
1260 */
1261 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
1262 {
1263 if (dblIn < -0.5 || dblIn >= UI2_MAX + 0.5)
1264 return DISP_E_OVERFLOW;
1265 VARIANT_DutchRound(USHORT, dblIn, *pusOut);
1266 return S_OK;
1267 }
1268
1269 /************************************************************************
1270 * VarUI2FromDate (OLEAUT32.262)
1271 *
1272 * Convert a VT_DATE to a VT_UI2.
1273 *
1274 * PARAMS
1275 * dateIn [I] Source
1276 * pusOut [O] Destination
1277 *
1278 * RETURNS
1279 * Success: S_OK.
1280 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1281 */
1282 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
1283 {
1284 return VarUI2FromR8(dateIn, pusOut);
1285 }
1286
1287 /************************************************************************
1288 * VarUI2FromCy (OLEAUT32.263)
1289 *
1290 * Convert a VT_CY to a VT_UI2.
1291 *
1292 * PARAMS
1293 * cyIn [I] Source
1294 * pusOut [O] Destination
1295 *
1296 * RETURNS
1297 * Success: S_OK.
1298 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1299 *
1300 * NOTES
1301 * Negative values >= -5000 will be converted to 0.
1302 */
1303 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
1304 {
1305 ULONG i = UI2_MAX + 1;
1306
1307 VarUI4FromCy(cyIn, &i);
1308 return _VarUI2FromUI4(i, pusOut);
1309 }
1310
1311 /************************************************************************
1312 * VarUI2FromStr (OLEAUT32.264)
1313 *
1314 * Convert a VT_BSTR to a VT_UI2.
1315 *
1316 * PARAMS
1317 * strIn [I] Source
1318 * lcid [I] LCID for the conversion
1319 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1320 * pusOut [O] Destination
1321 *
1322 * RETURNS
1323 * Success: S_OK.
1324 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1325 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1326 */
1327 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
1328 {
1329 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pusOut, VT_UI2);
1330 }
1331
1332 /************************************************************************
1333 * VarUI2FromDisp (OLEAUT32.265)
1334 *
1335 * Convert a VT_DISPATCH to a VT_UI2.
1336 *
1337 * PARAMS
1338 * pdispIn [I] Source
1339 * lcid [I] LCID for conversion
1340 * pusOut [O] Destination
1341 *
1342 * RETURNS
1343 * Success: S_OK.
1344 * Failure: E_INVALIDARG, if the source value is invalid
1345 * DISP_E_OVERFLOW, if the value will not fit in the destination
1346 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1347 */
1348 HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
1349 {
1350 return VARIANT_FromDisp(pdispIn, lcid, pusOut, VT_UI2, 0);
1351 }
1352
1353 /************************************************************************
1354 * VarUI2FromBool (OLEAUT32.266)
1355 *
1356 * Convert a VT_BOOL to a VT_UI2.
1357 *
1358 * PARAMS
1359 * boolIn [I] Source
1360 * pusOut [O] Destination
1361 *
1362 * RETURNS
1363 * S_OK.
1364 */
1365 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
1366 {
1367 return _VarUI2FromBool(boolIn, pusOut);
1368 }
1369
1370 /************************************************************************
1371 * VarUI2FromI1 (OLEAUT32.267)
1372 *
1373 * Convert a VT_I1 to a VT_UI2.
1374 *
1375 * PARAMS
1376 * cIn [I] Source
1377 * pusOut [O] Destination
1378 *
1379 * RETURNS
1380 * Success: S_OK.
1381 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1382 */
1383 HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
1384 {
1385 return _VarUI2FromI1(cIn, pusOut);
1386 }
1387
1388 /************************************************************************
1389 * VarUI2FromUI4 (OLEAUT32.268)
1390 *
1391 * Convert a VT_UI4 to a VT_UI2.
1392 *
1393 * PARAMS
1394 * ulIn [I] Source
1395 * pusOut [O] Destination
1396 *
1397 * RETURNS
1398 * Success: S_OK.
1399 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1400 */
1401 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
1402 {
1403 return _VarUI2FromUI4(ulIn, pusOut);
1404 }
1405
1406 /************************************************************************
1407 * VarUI2FromDec (OLEAUT32.269)
1408 *
1409 * Convert a VT_DECIMAL to a VT_UI2.
1410 *
1411 * PARAMS
1412 * pDecIn [I] Source
1413 * pusOut [O] Destination
1414 *
1415 * RETURNS
1416 * Success: S_OK.
1417 * Failure: E_INVALIDARG, if the source value is invalid
1418 * DISP_E_OVERFLOW, if the value will not fit in the destination
1419 */
1420 HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
1421 {
1422 LONG64 i64;
1423 HRESULT hRet;
1424
1425 hRet = VarI8FromDec(pdecIn, &i64);
1426
1427 if (SUCCEEDED(hRet))
1428 hRet = _VarUI2FromI8(i64, pusOut);
1429 return hRet;
1430 }
1431
1432 /************************************************************************
1433 * VarUI2FromI8 (OLEAUT32.378)
1434 *
1435 * Convert a VT_I8 to a VT_UI2.
1436 *
1437 * PARAMS
1438 * llIn [I] Source
1439 * pusOut [O] Destination
1440 *
1441 * RETURNS
1442 * Success: S_OK.
1443 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1444 */
1445 HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
1446 {
1447 return _VarUI2FromI8(llIn, pusOut);
1448 }
1449
1450 /************************************************************************
1451 * VarUI2FromUI8 (OLEAUT32.379)
1452 *
1453 * Convert a VT_UI8 to a VT_UI2.
1454 *
1455 * PARAMS
1456 * ullIn [I] Source
1457 * pusOut [O] Destination
1458 *
1459 * RETURNS
1460 * Success: S_OK.
1461 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1462 */
1463 HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
1464 {
1465 return _VarUI2FromUI8(ullIn, pusOut);
1466 }
1467
1468 /* I4
1469 */
1470
1471 /************************************************************************
1472 * VarI4FromUI1 (OLEAUT32.58)
1473 *
1474 * Convert a VT_UI1 to a VT_I4.
1475 *
1476 * PARAMS
1477 * bIn [I] Source
1478 * piOut [O] Destination
1479 *
1480 * RETURNS
1481 * S_OK.
1482 */
1483 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
1484 {
1485 return _VarI4FromUI1(bIn, piOut);
1486 }
1487
1488 /************************************************************************
1489 * VarI4FromI2 (OLEAUT32.59)
1490 *
1491 * Convert a VT_I2 to a VT_I4.
1492 *
1493 * PARAMS
1494 * sIn [I] Source
1495 * piOut [O] Destination
1496 *
1497 * RETURNS
1498 * Success: S_OK.
1499 * Failure: E_INVALIDARG, if the source value is invalid
1500 * DISP_E_OVERFLOW, if the value will not fit in the destination
1501 */
1502 HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
1503 {
1504 return _VarI4FromI2(sIn, piOut);
1505 }
1506
1507 /************************************************************************
1508 * VarI4FromR4 (OLEAUT32.60)
1509 *
1510 * Convert a VT_R4 to a VT_I4.
1511 *
1512 * PARAMS
1513 * fltIn [I] Source
1514 * piOut [O] Destination
1515 *
1516 * RETURNS
1517 * Success: S_OK.
1518 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1519 */
1520 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
1521 {
1522 return VarI4FromR8(fltIn, piOut);
1523 }
1524
1525 /************************************************************************
1526 * VarI4FromR8 (OLEAUT32.61)
1527 *
1528 * Convert a VT_R8 to a VT_I4.
1529 *
1530 * PARAMS
1531 * dblIn [I] Source
1532 * piOut [O] Destination
1533 *
1534 * RETURNS
1535 * Success: S_OK.
1536 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1537 *
1538 * NOTES
1539 * See VarI8FromR8() for details concerning rounding.
1540 */
1541 HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
1542 {
1543 if (dblIn < I4_MIN - 0.5 || dblIn >= I4_MAX + 0.5)
1544 return DISP_E_OVERFLOW;
1545 VARIANT_DutchRound(LONG, dblIn, *piOut);
1546 return S_OK;
1547 }
1548
1549 /************************************************************************
1550 * VarI4FromCy (OLEAUT32.62)
1551 *
1552 * Convert a VT_CY to a VT_I4.
1553 *
1554 * PARAMS
1555 * cyIn [I] Source
1556 * piOut [O] Destination
1557 *
1558 * RETURNS
1559 * Success: S_OK.
1560 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1561 */
1562 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
1563 {
1564 double d = cyIn.int64 / CY_MULTIPLIER_F;
1565 return VarI4FromR8(d, piOut);
1566 }
1567
1568 /************************************************************************
1569 * VarI4FromDate (OLEAUT32.63)
1570 *
1571 * Convert a VT_DATE to a VT_I4.
1572 *
1573 * PARAMS
1574 * dateIn [I] Source
1575 * piOut [O] Destination
1576 *
1577 * RETURNS
1578 * Success: S_OK.
1579 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1580 */
1581 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
1582 {
1583 return VarI4FromR8(dateIn, piOut);
1584 }
1585
1586 /************************************************************************
1587 * VarI4FromStr (OLEAUT32.64)
1588 *
1589 * Convert a VT_BSTR to a VT_I4.
1590 *
1591 * PARAMS
1592 * strIn [I] Source
1593 * lcid [I] LCID for the conversion
1594 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1595 * piOut [O] Destination
1596 *
1597 * RETURNS
1598 * Success: S_OK.
1599 * Failure: E_INVALIDARG, if any parameter is invalid
1600 * DISP_E_OVERFLOW, if the value will not fit in the destination
1601 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1602 */
1603 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
1604 {
1605 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, piOut, VT_I4);
1606 }
1607
1608 /************************************************************************
1609 * VarI4FromDisp (OLEAUT32.65)
1610 *
1611 * Convert a VT_DISPATCH to a VT_I4.
1612 *
1613 * PARAMS
1614 * pdispIn [I] Source
1615 * lcid [I] LCID for conversion
1616 * piOut [O] Destination
1617 *
1618 * RETURNS
1619 * Success: S_OK.
1620 * Failure: E_INVALIDARG, if the source value is invalid
1621 * DISP_E_OVERFLOW, if the value will not fit in the destination
1622 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1623 */
1624 HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
1625 {
1626 return VARIANT_FromDisp(pdispIn, lcid, piOut, VT_I4, 0);
1627 }
1628
1629 /************************************************************************
1630 * VarI4FromBool (OLEAUT32.66)
1631 *
1632 * Convert a VT_BOOL to a VT_I4.
1633 *
1634 * PARAMS
1635 * boolIn [I] Source
1636 * piOut [O] Destination
1637 *
1638 * RETURNS
1639 * S_OK.
1640 */
1641 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
1642 {
1643 return _VarI4FromBool(boolIn, piOut);
1644 }
1645
1646 /************************************************************************
1647 * VarI4FromI1 (OLEAUT32.209)
1648 *
1649 * Convert a VT_I1 to a VT_I4.
1650 *
1651 * PARAMS
1652 * cIn [I] Source
1653 * piOut [O] Destination
1654 *
1655 * RETURNS
1656 * S_OK.
1657 */
1658 HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
1659 {
1660 return _VarI4FromI1(cIn, piOut);
1661 }
1662
1663 /************************************************************************
1664 * VarI4FromUI2 (OLEAUT32.210)
1665 *
1666 * Convert a VT_UI2 to a VT_I4.
1667 *
1668 * PARAMS
1669 * usIn [I] Source
1670 * piOut [O] Destination
1671 *
1672 * RETURNS
1673 * S_OK.
1674 */
1675 HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
1676 {
1677 return _VarI4FromUI2(usIn, piOut);
1678 }
1679
1680 /************************************************************************
1681 * VarI4FromUI4 (OLEAUT32.211)
1682 *
1683 * Convert a VT_UI4 to a VT_I4.
1684 *
1685 * PARAMS
1686 * ulIn [I] Source
1687 * piOut [O] Destination
1688 *
1689 * RETURNS
1690 * Success: S_OK.
1691 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1692 */
1693 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
1694 {
1695 return _VarI4FromUI4(ulIn, piOut);
1696 }
1697
1698 /************************************************************************
1699 * VarI4FromDec (OLEAUT32.212)
1700 *
1701 * Convert a VT_DECIMAL to a VT_I4.
1702 *
1703 * PARAMS
1704 * pDecIn [I] Source
1705 * piOut [O] Destination
1706 *
1707 * RETURNS
1708 * Success: S_OK.
1709 * Failure: E_INVALIDARG, if pdecIn is invalid
1710 * DISP_E_OVERFLOW, if the value will not fit in the destination
1711 */
1712 HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
1713 {
1714 LONG64 i64;
1715 HRESULT hRet;
1716
1717 hRet = VarI8FromDec(pdecIn, &i64);
1718
1719 if (SUCCEEDED(hRet))
1720 hRet = _VarI4FromI8(i64, piOut);
1721 return hRet;
1722 }
1723
1724 /************************************************************************
1725 * VarI4FromI8 (OLEAUT32.348)
1726 *
1727 * Convert a VT_I8 to a VT_I4.
1728 *
1729 * PARAMS
1730 * llIn [I] Source
1731 * piOut [O] Destination
1732 *
1733 * RETURNS
1734 * Success: S_OK.
1735 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1736 */
1737 HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
1738 {
1739 return _VarI4FromI8(llIn, piOut);
1740 }
1741
1742 /************************************************************************
1743 * VarI4FromUI8 (OLEAUT32.349)
1744 *
1745 * Convert a VT_UI8 to a VT_I4.
1746 *
1747 * PARAMS
1748 * ullIn [I] Source
1749 * piOut [O] Destination
1750 *
1751 * RETURNS
1752 * Success: S_OK.
1753 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1754 */
1755 HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
1756 {
1757 return _VarI4FromUI8(ullIn, piOut);
1758 }
1759
1760 /* UI4
1761 */
1762
1763 /************************************************************************
1764 * VarUI4FromUI1 (OLEAUT32.270)
1765 *
1766 * Convert a VT_UI1 to a VT_UI4.
1767 *
1768 * PARAMS
1769 * bIn [I] Source
1770 * pulOut [O] Destination
1771 *
1772 * RETURNS
1773 * S_OK.
1774 */
1775 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
1776 {
1777 return _VarUI4FromUI1(bIn, pulOut);
1778 }
1779
1780 /************************************************************************
1781 * VarUI4FromI2 (OLEAUT32.271)
1782 *
1783 * Convert a VT_I2 to a VT_UI4.
1784 *
1785 * PARAMS
1786 * sIn [I] Source
1787 * pulOut [O] Destination
1788 *
1789 * RETURNS
1790 * Success: S_OK.
1791 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1792 */
1793 HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
1794 {
1795 return _VarUI4FromI2(sIn, pulOut);
1796 }
1797
1798 /************************************************************************
1799 * VarUI4FromI4 (OLEAUT32.272)
1800 *
1801 * Convert a VT_I4 to a VT_UI4.
1802 *
1803 * PARAMS
1804 * iIn [I] Source
1805 * pulOut [O] Destination
1806 *
1807 * RETURNS
1808 * Success: S_OK.
1809 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1810 */
1811 HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
1812 {
1813 return _VarUI4FromI4(iIn, pulOut);
1814 }
1815
1816 /************************************************************************
1817 * VarUI4FromR4 (OLEAUT32.273)
1818 *
1819 * Convert a VT_R4 to a VT_UI4.
1820 *
1821 * PARAMS
1822 * fltIn [I] Source
1823 * pulOut [O] Destination
1824 *
1825 * RETURNS
1826 * Success: S_OK.
1827 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1828 */
1829 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
1830 {
1831 return VarUI4FromR8(fltIn, pulOut);
1832 }
1833
1834 /************************************************************************
1835 * VarUI4FromR8 (OLEAUT32.274)
1836 *
1837 * Convert a VT_R8 to a VT_UI4.
1838 *
1839 * PARAMS
1840 * dblIn [I] Source
1841 * pulOut [O] Destination
1842 *
1843 * RETURNS
1844 * Success: S_OK.
1845 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1846 *
1847 * NOTES
1848 * See VarI8FromR8() for details concerning rounding.
1849 */
1850 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
1851 {
1852 if (dblIn < -0.5 || dblIn >= UI4_MAX + 0.5)
1853 return DISP_E_OVERFLOW;
1854 VARIANT_DutchRound(ULONG, dblIn, *pulOut);
1855 return S_OK;
1856 }
1857
1858 /************************************************************************
1859 * VarUI4FromDate (OLEAUT32.275)
1860 *
1861 * Convert a VT_DATE to a VT_UI4.
1862 *
1863 * PARAMS
1864 * dateIn [I] Source
1865 * pulOut [O] Destination
1866 *
1867 * RETURNS
1868 * Success: S_OK.
1869 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1870 */
1871 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
1872 {
1873 return VarUI4FromR8(dateIn, pulOut);
1874 }
1875
1876 /************************************************************************
1877 * VarUI4FromCy (OLEAUT32.276)
1878 *
1879 * Convert a VT_CY to a VT_UI4.
1880 *
1881 * PARAMS
1882 * cyIn [I] Source
1883 * pulOut [O] Destination
1884 *
1885 * RETURNS
1886 * Success: S_OK.
1887 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1888 */
1889 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
1890 {
1891 double d = cyIn.int64 / CY_MULTIPLIER_F;
1892 return VarUI4FromR8(d, pulOut);
1893 }
1894
1895 /************************************************************************
1896 * VarUI4FromStr (OLEAUT32.277)
1897 *
1898 * Convert a VT_BSTR to a VT_UI4.
1899 *
1900 * PARAMS
1901 * strIn [I] Source
1902 * lcid [I] LCID for the conversion
1903 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1904 * pulOut [O] Destination
1905 *
1906 * RETURNS
1907 * Success: S_OK.
1908 * Failure: E_INVALIDARG, if any parameter is invalid
1909 * DISP_E_OVERFLOW, if the value will not fit in the destination
1910 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1911 */
1912 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
1913 {
1914 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pulOut, VT_UI4);
1915 }
1916
1917 /************************************************************************
1918 * VarUI4FromDisp (OLEAUT32.278)
1919 *
1920 * Convert a VT_DISPATCH to a VT_UI4.
1921 *
1922 * PARAMS
1923 * pdispIn [I] Source
1924 * lcid [I] LCID for conversion
1925 * pulOut [O] Destination
1926 *
1927 * RETURNS
1928 * Success: S_OK.
1929 * Failure: E_INVALIDARG, if the source value is invalid
1930 * DISP_E_OVERFLOW, if the value will not fit in the destination
1931 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1932 */
1933 HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
1934 {
1935 return VARIANT_FromDisp(pdispIn, lcid, pulOut, VT_UI4, 0);
1936 }
1937
1938 /************************************************************************
1939 * VarUI4FromBool (OLEAUT32.279)
1940 *
1941 * Convert a VT_BOOL to a VT_UI4.
1942 *
1943 * PARAMS
1944 * boolIn [I] Source
1945 * pulOut [O] Destination
1946 *
1947 * RETURNS
1948 * S_OK.
1949 */
1950 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
1951 {
1952 return _VarUI4FromBool(boolIn, pulOut);
1953 }
1954
1955 /************************************************************************
1956 * VarUI4FromI1 (OLEAUT32.280)
1957 *
1958 * Convert a VT_I1 to a VT_UI4.
1959 *
1960 * PARAMS
1961 * cIn [I] Source
1962 * pulOut [O] Destination
1963 *
1964 * RETURNS
1965 * Success: S_OK.
1966 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1967 */
1968 HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
1969 {
1970 return _VarUI4FromI1(cIn, pulOut);
1971 }
1972
1973 /************************************************************************
1974 * VarUI4FromUI2 (OLEAUT32.281)
1975 *
1976 * Convert a VT_UI2 to a VT_UI4.
1977 *
1978 * PARAMS
1979 * usIn [I] Source
1980 * pulOut [O] Destination
1981 *
1982 * RETURNS
1983 * S_OK.
1984 */
1985 HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
1986 {
1987 return _VarUI4FromUI2(usIn, pulOut);
1988 }
1989
1990 /************************************************************************
1991 * VarUI4FromDec (OLEAUT32.282)
1992 *
1993 * Convert a VT_DECIMAL to a VT_UI4.
1994 *
1995 * PARAMS
1996 * pDecIn [I] Source
1997 * pulOut [O] Destination
1998 *
1999 * RETURNS
2000 * Success: S_OK.
2001 * Failure: E_INVALIDARG, if pdecIn is invalid
2002 * DISP_E_OVERFLOW, if the value will not fit in the destination
2003 */
2004 HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
2005 {
2006 LONG64 i64;
2007 HRESULT hRet;
2008
2009 hRet = VarI8FromDec(pdecIn, &i64);
2010
2011 if (SUCCEEDED(hRet))
2012 hRet = _VarUI4FromI8(i64, pulOut);
2013 return hRet;
2014 }
2015
2016 /************************************************************************
2017 * VarUI4FromI8 (OLEAUT32.425)
2018 *
2019 * Convert a VT_I8 to a VT_UI4.
2020 *
2021 * PARAMS
2022 * llIn [I] Source
2023 * pulOut [O] Destination
2024 *
2025 * RETURNS
2026 * Success: S_OK.
2027 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2028 */
2029 HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
2030 {
2031 return _VarUI4FromI8(llIn, pulOut);
2032 }
2033
2034 /************************************************************************
2035 * VarUI4FromUI8 (OLEAUT32.426)
2036 *
2037 * Convert a VT_UI8 to a VT_UI4.
2038 *
2039 * PARAMS
2040 * ullIn [I] Source
2041 * pulOut [O] Destination
2042 *
2043 * RETURNS
2044 * Success: S_OK.
2045 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2046 */
2047 HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
2048 {
2049 return _VarUI4FromUI8(ullIn, pulOut);
2050 }
2051
2052 /* I8
2053 */
2054
2055 /************************************************************************
2056 * VarI8FromUI1 (OLEAUT32.333)
2057 *
2058 * Convert a VT_UI1 to a VT_I8.
2059 *
2060 * PARAMS
2061 * bIn [I] Source
2062 * pi64Out [O] Destination
2063 *
2064 * RETURNS
2065 * S_OK.
2066 */
2067 HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
2068 {
2069 return _VarI8FromUI1(bIn, pi64Out);
2070 }
2071
2072
2073 /************************************************************************
2074 * VarI8FromI2 (OLEAUT32.334)
2075 *
2076 * Convert a VT_I2 to a VT_I8.
2077 *
2078 * PARAMS
2079 * sIn [I] Source
2080 * pi64Out [O] Destination
2081 *
2082 * RETURNS
2083 * S_OK.
2084 */
2085 HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
2086 {
2087 return _VarI8FromI2(sIn, pi64Out);
2088 }
2089
2090 /************************************************************************
2091 * VarI8FromR4 (OLEAUT32.335)
2092 *
2093 * Convert a VT_R4 to a VT_I8.
2094 *
2095 * PARAMS
2096 * fltIn [I] Source
2097 * pi64Out [O] Destination
2098 *
2099 * RETURNS
2100 * Success: S_OK.
2101 * Failure: E_INVALIDARG, if the source value is invalid
2102 * DISP_E_OVERFLOW, if the value will not fit in the destination
2103 */
2104 HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
2105 {
2106 return VarI8FromR8(fltIn, pi64Out);
2107 }
2108
2109 /************************************************************************
2110 * VarI8FromR8 (OLEAUT32.336)
2111 *
2112 * Convert a VT_R8 to a VT_I8.
2113 *
2114 * PARAMS
2115 * dblIn [I] Source
2116 * pi64Out [O] Destination
2117 *
2118 * RETURNS
2119 * Success: S_OK.
2120 * Failure: E_INVALIDARG, if the source value is invalid
2121 * DISP_E_OVERFLOW, if the value will not fit in the destination
2122 *
2123 * NOTES
2124 * Only values that fit into 63 bits are accepted. Due to rounding issues,
2125 * very high or low values will not be accurately converted.
2126 *
2127 * Numbers are rounded using Dutch rounding, as follows:
2128 *
2129 *| Fractional Part Sign Direction Example
2130 *| --------------- ---- --------- -------
2131 *| < 0.5 + Down 0.4 -> 0.0
2132 *| < 0.5 - Up -0.4 -> 0.0
2133 *| > 0.5 + Up 0.6 -> 1.0
2134 *| < 0.5 - Up -0.6 -> -1.0
2135 *| = 0.5 + Up/Down Down if even, Up if odd
2136 *| = 0.5 - Up/Down Up if even, Down if odd
2137 *
2138 * This system is often used in supermarkets.
2139 */
2140 HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
2141 {
2142 if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
2143 return DISP_E_OVERFLOW;
2144 VARIANT_DutchRound(LONG64, dblIn, *pi64Out);
2145 return S_OK;
2146 }
2147
2148 /************************************************************************
2149 * VarI8FromCy (OLEAUT32.337)
2150 *
2151 * Convert a VT_CY to a VT_I8.
2152 *
2153 * PARAMS
2154 * cyIn [I] Source
2155 * pi64Out [O] Destination
2156 *
2157 * RETURNS
2158 * S_OK.
2159 *
2160 * NOTES
2161 * All negative numbers are rounded down by 1, including those that are
2162 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2163 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2164 * for details.
2165 */
2166 HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
2167 {
2168 *pi64Out = cyIn.int64 / CY_MULTIPLIER;
2169
2170 if (cyIn.int64 < 0)
2171 (*pi64Out)--; /* Mimic Win32 bug */
2172 else
2173 {
2174 cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2175
2176 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
2177 (*pi64Out)++;
2178 }
2179 return S_OK;
2180 }
2181
2182 /************************************************************************
2183 * VarI8FromDate (OLEAUT32.338)
2184 *
2185 * Convert a VT_DATE to a VT_I8.
2186 *
2187 * PARAMS
2188 * dateIn [I] Source
2189 * pi64Out [O] Destination
2190 *
2191 * RETURNS
2192 * Success: S_OK.
2193 * Failure: E_INVALIDARG, if the source value is invalid
2194 * DISP_E_OVERFLOW, if the value will not fit in the destination
2195 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2196 */
2197 HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
2198 {
2199 return VarI8FromR8(dateIn, pi64Out);
2200 }
2201
2202 /************************************************************************
2203 * VarI8FromStr (OLEAUT32.339)
2204 *
2205 * Convert a VT_BSTR to a VT_I8.
2206 *
2207 * PARAMS
2208 * strIn [I] Source
2209 * lcid [I] LCID for the conversion
2210 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2211 * pi64Out [O] Destination
2212 *
2213 * RETURNS
2214 * Success: S_OK.
2215 * Failure: E_INVALIDARG, if the source value is invalid
2216 * DISP_E_OVERFLOW, if the value will not fit in the destination
2217 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2218 */
2219 HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
2220 {
2221 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pi64Out, VT_I8);
2222 }
2223
2224 /************************************************************************
2225 * VarI8FromDisp (OLEAUT32.340)
2226 *
2227 * Convert a VT_DISPATCH to a VT_I8.
2228 *
2229 * PARAMS
2230 * pdispIn [I] Source
2231 * lcid [I] LCID for conversion
2232 * pi64Out [O] Destination
2233 *
2234 * RETURNS
2235 * Success: S_OK.
2236 * Failure: E_INVALIDARG, if the source value is invalid
2237 * DISP_E_OVERFLOW, if the value will not fit in the destination
2238 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2239 */
2240 HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
2241 {
2242 return VARIANT_FromDisp(pdispIn, lcid, pi64Out, VT_I8, 0);
2243 }
2244
2245 /************************************************************************
2246 * VarI8FromBool (OLEAUT32.341)
2247 *
2248 * Convert a VT_BOOL to a VT_I8.
2249 *
2250 * PARAMS
2251 * boolIn [I] Source
2252 * pi64Out [O] Destination
2253 *
2254 * RETURNS
2255 * S_OK.
2256 */
2257 HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
2258 {
2259 return VarI8FromI2(boolIn, pi64Out);
2260 }
2261
2262 /************************************************************************
2263 * VarI8FromI1 (OLEAUT32.342)
2264 *
2265 * Convert a VT_I1 to a VT_I8.
2266 *
2267 * PARAMS
2268 * cIn [I] Source
2269 * pi64Out [O] Destination
2270 *
2271 * RETURNS
2272 * S_OK.
2273 */
2274 HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
2275 {
2276 return _VarI8FromI1(cIn, pi64Out);
2277 }
2278
2279 /************************************************************************
2280 * VarI8FromUI2 (OLEAUT32.343)
2281 *
2282 * Convert a VT_UI2 to a VT_I8.
2283 *
2284 * PARAMS
2285 * usIn [I] Source
2286 * pi64Out [O] Destination
2287 *
2288 * RETURNS
2289 * S_OK.
2290 */
2291 HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
2292 {
2293 return _VarI8FromUI2(usIn, pi64Out);
2294 }
2295
2296 /************************************************************************
2297 * VarI8FromUI4 (OLEAUT32.344)
2298 *
2299 * Convert a VT_UI4 to a VT_I8.
2300 *
2301 * PARAMS
2302 * ulIn [I] Source
2303 * pi64Out [O] Destination
2304 *
2305 * RETURNS
2306 * S_OK.
2307 */
2308 HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
2309 {
2310 return _VarI8FromUI4(ulIn, pi64Out);
2311 }
2312
2313 /************************************************************************
2314 * VarI8FromDec (OLEAUT32.345)
2315 *
2316 * Convert a VT_DECIMAL to a VT_I8.
2317 *
2318 * PARAMS
2319 * pDecIn [I] Source
2320 * pi64Out [O] Destination
2321 *
2322 * RETURNS
2323 * Success: S_OK.
2324 * Failure: E_INVALIDARG, if the source value is invalid
2325 * DISP_E_OVERFLOW, if the value will not fit in the destination
2326 */
2327 HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
2328 {
2329 if (!DEC_SCALE(pdecIn))
2330 {
2331 /* This decimal is just a 96 bit integer */
2332 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2333 return E_INVALIDARG;
2334
2335 if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
2336 return DISP_E_OVERFLOW;
2337
2338 if (DEC_SIGN(pdecIn))
2339 *pi64Out = -DEC_LO64(pdecIn);
2340 else
2341 *pi64Out = DEC_LO64(pdecIn);
2342 return S_OK;
2343 }
2344 else
2345 {
2346 /* Decimal contains a floating point number */
2347 HRESULT hRet;
2348 double dbl;
2349
2350 hRet = VarR8FromDec(pdecIn, &dbl);
2351 if (SUCCEEDED(hRet))
2352 hRet = VarI8FromR8(dbl, pi64Out);
2353 return hRet;
2354 }
2355 }
2356
2357 /************************************************************************
2358 * VarI8FromUI8 (OLEAUT32.427)
2359 *
2360 * Convert a VT_UI8 to a VT_I8.
2361 *
2362 * PARAMS
2363 * ullIn [I] Source
2364 * pi64Out [O] Destination
2365 *
2366 * RETURNS
2367 * Success: S_OK.
2368 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2369 */
2370 HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
2371 {
2372 return _VarI8FromUI8(ullIn, pi64Out);
2373 }
2374
2375 /* UI8
2376 */
2377
2378 /************************************************************************
2379 * VarUI8FromI8 (OLEAUT32.428)
2380 *
2381 * Convert a VT_I8 to a VT_UI8.
2382 *
2383 * PARAMS
2384 * ulIn [I] Source
2385 * pui64Out [O] Destination
2386 *
2387 * RETURNS
2388 * Success: S_OK.
2389 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2390 */
2391 HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
2392 {
2393 return _VarUI8FromI8(llIn, pui64Out);
2394 }
2395
2396 /************************************************************************
2397 * VarUI8FromUI1 (OLEAUT32.429)
2398 *
2399 * Convert a VT_UI1 to a VT_UI8.
2400 *
2401 * PARAMS
2402 * bIn [I] Source
2403 * pui64Out [O] Destination
2404 *
2405 * RETURNS
2406 * S_OK.
2407 */
2408 HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
2409 {
2410 return _VarUI8FromUI1(bIn, pui64Out);
2411 }
2412
2413 /************************************************************************
2414 * VarUI8FromI2 (OLEAUT32.430)
2415 *
2416 * Convert a VT_I2 to a VT_UI8.
2417 *
2418 * PARAMS
2419 * sIn [I] Source
2420 * pui64Out [O] Destination
2421 *
2422 * RETURNS
2423 * S_OK.
2424 */
2425 HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
2426 {
2427 return _VarUI8FromI2(sIn, pui64Out);
2428 }
2429
2430 /************************************************************************
2431 * VarUI8FromR4 (OLEAUT32.431)
2432 *
2433 * Convert a VT_R4 to a VT_UI8.
2434 *
2435 * PARAMS
2436 * fltIn [I] Source
2437 * pui64Out [O] Destination
2438 *
2439 * RETURNS
2440 * Success: S_OK.
2441 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2442 */
2443 HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
2444 {
2445 return VarUI8FromR8(fltIn, pui64Out);
2446 }
2447
2448 /************************************************************************
2449 * VarUI8FromR8 (OLEAUT32.432)
2450 *
2451 * Convert a VT_R8 to a VT_UI8.
2452 *
2453 * PARAMS
2454 * dblIn [I] Source
2455 * pui64Out [O] Destination
2456 *
2457 * RETURNS
2458 * Success: S_OK.
2459 * Failure: E_INVALIDARG, if the source value is invalid
2460 * DISP_E_OVERFLOW, if the value will not fit in the destination
2461 *
2462 * NOTES
2463 * See VarI8FromR8() for details concerning rounding.
2464 */
2465 HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
2466 {
2467 if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
2468 return DISP_E_OVERFLOW;
2469 VARIANT_DutchRound(ULONG64, dblIn, *pui64Out);
2470 return S_OK;
2471 }
2472
2473 /************************************************************************
2474 * VarUI8FromCy (OLEAUT32.433)
2475 *
2476 * Convert a VT_CY to a VT_UI8.
2477 *
2478 * PARAMS
2479 * cyIn [I] Source
2480 * pui64Out [O] Destination
2481 *
2482 * RETURNS
2483 * Success: S_OK.
2484 * Failure: E_INVALIDARG, if the source value is invalid
2485 * DISP_E_OVERFLOW, if the value will not fit in the destination
2486 *
2487 * NOTES
2488 * Negative values >= -5000 will be converted to 0.
2489 */
2490 HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
2491 {
2492 if (cyIn.int64 < 0)
2493 {
2494 if (cyIn.int64 < -CY_HALF)
2495 return DISP_E_OVERFLOW;
2496 *pui64Out = 0;
2497 }
2498 else
2499 {
2500 *pui64Out = cyIn.int64 / CY_MULTIPLIER;
2501
2502 cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2503
2504 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
2505 (*pui64Out)++;
2506 }
2507 return S_OK;
2508 }
2509
2510 /************************************************************************
2511 * VarUI8FromDate (OLEAUT32.434)
2512 *
2513 * Convert a VT_DATE to a VT_UI8.
2514 *
2515 * PARAMS
2516 * dateIn [I] Source
2517 * pui64Out [O] Destination
2518 *
2519 * RETURNS
2520 * Success: S_OK.
2521 * Failure: E_INVALIDARG, if the source value is invalid
2522 * DISP_E_OVERFLOW, if the value will not fit in the destination
2523 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2524 */
2525 HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
2526 {
2527 return VarUI8FromR8(dateIn, pui64Out);
2528 }
2529
2530 /************************************************************************
2531 * VarUI8FromStr (OLEAUT32.435)
2532 *
2533 * Convert a VT_BSTR to a VT_UI8.
2534 *
2535 * PARAMS
2536 * strIn [I] Source
2537 * lcid [I] LCID for the conversion
2538 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2539 * pui64Out [O] Destination
2540 *
2541 * RETURNS
2542 * Success: S_OK.
2543 * Failure: E_INVALIDARG, if the source value is invalid
2544 * DISP_E_OVERFLOW, if the value will not fit in the destination
2545 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2546 */
2547 HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
2548 {
2549 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pui64Out, VT_UI8);
2550 }
2551
2552 /************************************************************************
2553 * VarUI8FromDisp (OLEAUT32.436)
2554 *
2555 * Convert a VT_DISPATCH to a VT_UI8.
2556 *
2557 * PARAMS
2558 * pdispIn [I] Source
2559 * lcid [I] LCID for conversion
2560 * pui64Out [O] Destination
2561 *
2562 * RETURNS
2563 * Success: S_OK.
2564 * Failure: E_INVALIDARG, if the source value is invalid
2565 * DISP_E_OVERFLOW, if the value will not fit in the destination
2566 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2567 */
2568 HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
2569 {
2570 return VARIANT_FromDisp(pdispIn, lcid, pui64Out, VT_UI8, 0);
2571 }
2572
2573 /************************************************************************
2574 * VarUI8FromBool (OLEAUT32.437)
2575 *
2576 * Convert a VT_BOOL to a VT_UI8.
2577 *
2578 * PARAMS
2579 * boolIn [I] Source
2580 * pui64Out [O] Destination
2581 *
2582 * RETURNS
2583 * Success: S_OK.
2584 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2585 */
2586 HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
2587 {
2588 return VarI8FromI2(boolIn, (LONG64 *)pui64Out);
2589 }
2590 /************************************************************************
2591 * VarUI8FromI1 (OLEAUT32.438)
2592 *
2593 * Convert a VT_I1 to a VT_UI8.
2594 *
2595 * PARAMS
2596 * cIn [I] Source
2597 * pui64Out [O] Destination
2598 *
2599 * RETURNS
2600 * Success: S_OK.
2601 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2602 */
2603 HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
2604 {
2605 return _VarUI8FromI1(cIn, pui64Out);
2606 }
2607
2608 /************************************************************************
2609 * VarUI8FromUI2 (OLEAUT32.439)
2610 *
2611 * Convert a VT_UI2 to a VT_UI8.
2612 *
2613 * PARAMS
2614 * usIn [I] Source
2615 * pui64Out [O] Destination
2616 *
2617 * RETURNS
2618 * S_OK.
2619 */
2620 HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
2621 {
2622 return _VarUI8FromUI2(usIn, pui64Out);
2623 }
2624
2625 /************************************************************************
2626 * VarUI8FromUI4 (OLEAUT32.440)
2627 *
2628 * Convert a VT_UI4 to a VT_UI8.
2629 *
2630 * PARAMS
2631 * ulIn [I] Source
2632 * pui64Out [O] Destination
2633 *
2634 * RETURNS
2635 * S_OK.
2636 */
2637 HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
2638 {
2639 return _VarUI8FromUI4(ulIn, pui64Out);
2640 }
2641
2642 /************************************************************************
2643 * VarUI8FromDec (OLEAUT32.441)
2644 *
2645 * Convert a VT_DECIMAL to a VT_UI8.
2646 *
2647 * PARAMS
2648 * pDecIn [I] Source
2649 * pui64Out [O] Destination
2650 *
2651 * RETURNS
2652 * Success: S_OK.
2653 * Failure: E_INVALIDARG, if the source value is invalid
2654 * DISP_E_OVERFLOW, if the value will not fit in the destination
2655 *
2656 * NOTES
2657 * Under native Win32, if the source value has a scale of 0, its sign is
2658 * ignored, i.e. this function takes the absolute value rather than fail
2659 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2660 * (use VarAbs() on pDecIn first if you really want this behaviour).
2661 */
2662 HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
2663 {
2664 if (!DEC_SCALE(pdecIn))
2665 {
2666 /* This decimal is just a 96 bit integer */
2667 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2668 return E_INVALIDARG;
2669
2670 if (DEC_HI32(pdecIn))
2671 return DISP_E_OVERFLOW;
2672
2673 if (DEC_SIGN(pdecIn))
2674 {
2675 WARN("Sign would be ignored under Win32!\n");
2676 return DISP_E_OVERFLOW;
2677 }
2678
2679 *pui64Out = DEC_LO64(pdecIn);
2680 return S_OK;
2681 }
2682 else
2683 {
2684 /* Decimal contains a floating point number */
2685 HRESULT hRet;
2686 double dbl;
2687
2688 hRet = VarR8FromDec(pdecIn, &dbl);
2689 if (SUCCEEDED(hRet))
2690 hRet = VarUI8FromR8(dbl, pui64Out);
2691 return hRet;
2692 }
2693 }
2694
2695 /* R4
2696 */
2697
2698 /************************************************************************
2699 * VarR4FromUI1 (OLEAUT32.68)
2700 *
2701 * Convert a VT_UI1 to a VT_R4.
2702 *
2703 * PARAMS
2704 * bIn [I] Source
2705 * pFltOut [O] Destination
2706 *
2707 * RETURNS
2708 * S_OK.
2709 */
2710 HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
2711 {
2712 return _VarR4FromUI1(bIn, pFltOut);
2713 }
2714
2715 /************************************************************************
2716 * VarR4FromI2 (OLEAUT32.69)
2717 *
2718 * Convert a VT_I2 to a VT_R4.
2719 *
2720 * PARAMS
2721 * sIn [I] Source
2722 * pFltOut [O] Destination
2723 *
2724 * RETURNS
2725 * S_OK.
2726 */
2727 HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
2728 {
2729 return _VarR4FromI2(sIn, pFltOut);
2730 }
2731
2732 /************************************************************************
2733 * VarR4FromI4 (OLEAUT32.70)
2734 *
2735 * Convert a VT_I4 to a VT_R4.
2736 *
2737 * PARAMS
2738 * sIn [I] Source
2739 * pFltOut [O] Destination
2740 *
2741 * RETURNS
2742 * S_OK.
2743 */
2744 HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
2745 {
2746 return _VarR4FromI4(lIn, pFltOut);
2747 }
2748
2749 /************************************************************************
2750 * VarR4FromR8 (OLEAUT32.71)
2751 *
2752 * Convert a VT_R8 to a VT_R4.
2753 *
2754 * PARAMS
2755 * dblIn [I] Source
2756 * pFltOut [O] Destination
2757 *
2758 * RETURNS
2759 * Success: S_OK.
2760 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2761 */
2762 HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
2763 {
2764 double d = dblIn < 0.0 ? -dblIn : dblIn;
2765 if (d > R4_MAX) return DISP_E_OVERFLOW;
2766 *pFltOut = dblIn;
2767 return S_OK;
2768 }
2769
2770 /************************************************************************
2771 * VarR4FromCy (OLEAUT32.72)
2772 *
2773 * Convert a VT_CY to a VT_R4.
2774 *
2775 * PARAMS
2776 * cyIn [I] Source
2777 * pFltOut [O] Destination
2778 *
2779 * RETURNS
2780 * S_OK.
2781 */
2782 HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
2783 {
2784 *pFltOut = (double)cyIn.int64 / CY_MULTIPLIER_F;
2785 return S_OK;
2786 }
2787
2788 /************************************************************************
2789 * VarR4FromDate (OLEAUT32.73)
2790 *
2791 * Convert a VT_DATE to a VT_R4.
2792 *
2793 * PARAMS
2794 * dateIn [I] Source
2795 * pFltOut [O] Destination
2796 *
2797 * RETURNS
2798 * Success: S_OK.
2799 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2800 */
2801 HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
2802 {
2803 return VarR4FromR8(dateIn, pFltOut);
2804 }
2805
2806 /************************************************************************
2807 * VarR4FromStr (OLEAUT32.74)
2808 *
2809 * Convert a VT_BSTR to a VT_R4.
2810 *
2811 * PARAMS
2812 * strIn [I] Source
2813 * lcid [I] LCID for the conversion
2814 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2815 * pFltOut [O] Destination
2816 *
2817 * RETURNS
2818 * Success: S_OK.
2819 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2820 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2821 */
2822 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
2823 {
2824 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pFltOut, VT_R4);
2825 }
2826
2827 /************************************************************************
2828 * VarR4FromDisp (OLEAUT32.75)
2829 *
2830 * Convert a VT_DISPATCH to a VT_R4.
2831 *
2832 * PARAMS
2833 * pdispIn [I] Source
2834 * lcid [I] LCID for conversion
2835 * pFltOut [O] Destination
2836 *
2837 * RETURNS
2838 * Success: S_OK.
2839 * Failure: E_INVALIDARG, if the source value is invalid
2840 * DISP_E_OVERFLOW, if the value will not fit in the destination
2841 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2842 */
2843 HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
2844 {
2845 return VARIANT_FromDisp(pdispIn, lcid, pFltOut, VT_R4, 0);
2846 }
2847
2848 /************************************************************************
2849 * VarR4FromBool (OLEAUT32.76)
2850 *
2851 * Convert a VT_BOOL to a VT_R4.
2852 *
2853 * PARAMS
2854 * boolIn [I] Source
2855 * pFltOut [O] Destination
2856 *
2857 * RETURNS
2858 * S_OK.
2859 */
2860 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
2861 {
2862 return VarR4FromI2(boolIn, pFltOut);
2863 }
2864
2865 /************************************************************************
2866 * VarR4FromI1 (OLEAUT32.213)
2867 *
2868 * Convert a VT_I1 to a VT_R4.
2869 *
2870 * PARAMS
2871 * cIn [I] Source
2872 * pFltOut [O] Destination
2873 *
2874 * RETURNS
2875 * Success: S_OK.
2876 * Failure: E_INVALIDARG, if the source value is invalid
2877 * DISP_E_OVERFLOW, if the value will not fit in the destination
2878 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2879 */
2880 HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
2881 {
2882 return _VarR4FromI1(cIn, pFltOut);
2883 }
2884
2885 /************************************************************************
2886 * VarR4FromUI2 (OLEAUT32.214)
2887 *
2888 * Convert a VT_UI2 to a VT_R4.
2889 *
2890 * PARAMS
2891 * usIn [I] Source
2892 * pFltOut [O] Destination
2893 *
2894 * RETURNS
2895 * Success: S_OK.
2896 * Failure: E_INVALIDARG, if the source value is invalid
2897 * DISP_E_OVERFLOW, if the value will not fit in the destination
2898 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2899 */
2900 HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
2901 {
2902 return _VarR4FromUI2(usIn, pFltOut);
2903 }
2904
2905 /************************************************************************
2906 * VarR4FromUI4 (OLEAUT32.215)
2907 *
2908 * Convert a VT_UI4 to a VT_R4.
2909 *
2910 * PARAMS
2911 * ulIn [I] Source
2912 * pFltOut [O] Destination
2913 *
2914 * RETURNS
2915 * Success: S_OK.
2916 * Failure: E_INVALIDARG, if the source value is invalid
2917 * DISP_E_OVERFLOW, if the value will not fit in the destination
2918 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2919 */
2920 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
2921 {
2922 return _VarR4FromUI4(ulIn, pFltOut);
2923 }
2924
2925 /************************************************************************
2926 * VarR4FromDec (OLEAUT32.216)
2927 *
2928 * Convert a VT_DECIMAL to a VT_R4.
2929 *
2930 * PARAMS
2931 * pDecIn [I] Source
2932 * pFltOut [O] Destination
2933 *
2934 * RETURNS
2935 * Success: S_OK.
2936 * Failure: E_INVALIDARG, if the source value is invalid.
2937 */
2938 HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
2939 {
2940 BYTE scale = DEC_SCALE(pDecIn);
2941 int divisor = 1;
2942 double highPart;
2943
2944 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
2945 return E_INVALIDARG;
2946
2947 while (scale--)
2948 divisor *= 10;
2949
2950 if (DEC_SIGN(pDecIn))
2951 divisor = -divisor;
2952
2953 if (DEC_HI32(pDecIn))
2954 {
2955 highPart = (double)DEC_HI32(pDecIn) / (double)divisor;
2956 highPart *= 4294967296.0F;
2957 highPart *= 4294967296.0F;
2958 }
2959 else
2960 highPart = 0.0;
2961
2962 *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
2963 return S_OK;
2964 }
2965
2966 /************************************************************************
2967 * VarR4FromI8 (OLEAUT32.360)
2968 *
2969 * Convert a VT_I8 to a VT_R4.
2970 *
2971 * PARAMS
2972 * ullIn [I] Source
2973 * pFltOut [O] Destination
2974 *
2975 * RETURNS
2976 * S_OK.
2977 */
2978 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2979 {
2980 return _VarR4FromI8(llIn, pFltOut);
2981 }
2982
2983 /************************************************************************
2984 * VarR4FromUI8 (OLEAUT32.361)
2985 *
2986 * Convert a VT_UI8 to a VT_R4.
2987 *
2988 * PARAMS
2989 * ullIn [I] Source
2990 * pFltOut [O] Destination
2991 *
2992 * RETURNS
2993 * S_OK.
2994 */
2995 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
2996 {
2997 return _VarR4FromUI8(ullIn, pFltOut);
2998 }
2999
3000 /************************************************************************
3001 * VarR4CmpR8 (OLEAUT32.316)
3002 *
3003 * Compare a VT_R4 to a VT_R8.
3004 *
3005 * PARAMS
3006 * fltLeft [I] Source
3007 * dblRight [I] Value to compare
3008 *
3009 * RETURNS
3010 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
3011 * equal to or greater than dblRight respectively.
3012 */
3013 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
3014 {
3015 if (fltLeft < dblRight)
3016 return VARCMP_LT;
3017 else if (fltLeft > dblRight)
3018 return VARCMP_GT;
3019 return VARCMP_EQ;
3020 }
3021
3022 /* R8
3023 */
3024
3025 /************************************************************************
3026 * VarR8FromUI1 (OLEAUT32.78)
3027 *
3028 * Convert a VT_UI1 to a VT_R8.
3029 *
3030 * PARAMS
3031 * bIn [I] Source
3032 * pDblOut [O] Destination
3033 *
3034 * RETURNS
3035 * S_OK.
3036 */
3037 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
3038 {
3039 return _VarR8FromUI1(bIn, pDblOut);
3040 }
3041
3042 /************************************************************************
3043 * VarR8FromI2 (OLEAUT32.79)
3044 *
3045 * Convert a VT_I2 to a VT_R8.
3046 *
3047 * PARAMS
3048 * sIn [I] Source
3049 * pDblOut [O] Destination
3050 *
3051 * RETURNS
3052 * S_OK.
3053 */
3054 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
3055 {
3056 return _VarR8FromI2(sIn, pDblOut);
3057 }
3058
3059 /************************************************************************
3060 * VarR8FromI4 (OLEAUT32.80)
3061 *
3062 * Convert a VT_I4 to a VT_R8.
3063 *
3064 * PARAMS
3065 * sIn [I] Source
3066 * pDblOut [O] Destination
3067 *
3068 * RETURNS
3069 * S_OK.
3070 */
3071 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
3072 {
3073 return _VarR8FromI4(lIn, pDblOut);
3074 }
3075
3076 /************************************************************************
3077 * VarR8FromR4 (OLEAUT32.81)
3078 *
3079 * Convert a VT_R4 to a VT_R8.
3080 *
3081 * PARAMS
3082 * fltIn [I] Source
3083 * pDblOut [O] Destination
3084 *
3085 * RETURNS
3086 * S_OK.
3087 */
3088 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
3089 {
3090 return _VarR8FromR4(fltIn, pDblOut);
3091 }
3092
3093 /************************************************************************
3094 * VarR8FromCy (OLEAUT32.82)
3095 *
3096 * Convert a VT_CY to a VT_R8.
3097 *
3098 * PARAMS
3099 * cyIn [I] Source
3100 * pDblOut [O] Destination
3101 *
3102 * RETURNS
3103 * S_OK.
3104 */
3105 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
3106 {
3107 return _VarR8FromCy(cyIn, pDblOut);
3108 }
3109
3110 /************************************************************************
3111 * VarR8FromDate (OLEAUT32.83)
3112 *
3113 * Convert a VT_DATE to a VT_R8.
3114 *
3115 * PARAMS
3116 * dateIn [I] Source
3117 * pDblOut [O] Destination
3118 *
3119 * RETURNS
3120 * S_OK.
3121 */
3122 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
3123 {
3124 return _VarR8FromDate(dateIn, pDblOut);
3125 }
3126
3127 /************************************************************************
3128 * VarR8FromStr (OLEAUT32.84)
3129 *
3130 * Convert a VT_BSTR to a VT_R8.
3131 *
3132 * PARAMS
3133 * strIn [I] Source
3134 * lcid [I] LCID for the conversion
3135 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3136 * pDblOut [O] Destination
3137 *
3138 * RETURNS
3139 * Success: S_OK.
3140 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3141 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3142 */
3143 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3144 {
3145 return VARIANT_NumberFromBstr(strIn, lcid, dwFlags, pDblOut, VT_R8);
3146 }
3147
3148 /************************************************************************
3149 * VarR8FromDisp (OLEAUT32.85)
3150 *
3151 * Convert a VT_DISPATCH to a VT_R8.
3152 *
3153 * PARAMS
3154 * pdispIn [I] Source
3155 * lcid [I] LCID for conversion
3156 * pDblOut [O] Destination
3157 *
3158 * RETURNS
3159 * Success: S_OK.
3160 * Failure: E_INVALIDARG, if the source value is invalid
3161 * DISP_E_OVERFLOW, if the value will not fit in the destination
3162 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3163 */
3164 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3165 {
3166 return VARIANT_FromDisp(pdispIn, lcid, pDblOut, VT_R8, 0);
3167 }
3168
3169 /************************************************************************
3170 * VarR8FromBool (OLEAUT32.86)
3171 *
3172 * Convert a VT_BOOL to a VT_R8.
3173 *
3174 * PARAMS
3175 * boolIn [I] Source
3176 * pDblOut [O] Destination
3177 *
3178 * RETURNS
3179 * S_OK.
3180 */
3181 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
3182 {
3183 return VarR8FromI2(boolIn, pDblOut);
3184 }
3185
3186 /************************************************************************
3187 * VarR8FromI1 (OLEAUT32.217)
3188 *
3189 * Convert a VT_I1 to a VT_R8.
3190 *
3191 * PARAMS
3192 * cIn [I] Source
3193 * pDblOut [O] Destination
3194 *
3195 * RETURNS
3196 * Success: S_OK.
3197 * Failure: E_INVALIDARG, if the source value is invalid
3198 * DISP_E_OVERFLOW, if the value will not fit in the destination
3199 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3200 */
3201 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3202 {
3203 return _VarR8FromI1(cIn, pDblOut);
3204 }
3205
3206 /************************************************************************
3207 * VarR8FromUI2 (OLEAUT32.218)
3208 *
3209 * Convert a VT_UI2 to a VT_R8.
3210 *
3211 * PARAMS
3212 * usIn [I] Source
3213 * pDblOut [O] Destination
3214 *
3215 * RETURNS
3216 * Success: S_OK.
3217 * Failure: E_INVALIDARG, if the source value is invalid
3218 * DISP_E_OVERFLOW, if the value will not fit in the destination
3219 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3220 */
3221 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3222 {
3223 return _VarR8FromUI2(usIn, pDblOut);
3224 }
3225
3226 /************************************************************************
3227 * VarR8FromUI4 (OLEAUT32.219)
3228 *
3229 * Convert a VT_UI4 to a VT_R8.
3230 *
3231 * PARAMS
3232 * ulIn [I] Source
3233 * pDblOut [O] Destination
3234 *
3235 * RETURNS
3236 * Success: S_OK.
3237 * Failure: E_INVALIDARG, if the source value is invalid
3238 * DISP_E_OVERFLOW, if the value will not fit in the destination
3239 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3240 */
3241 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3242 {
3243 return _VarR8FromUI4(ulIn, pDblOut);
3244 }
3245
3246 /************************************************************************
3247 * VarR8FromDec (OLEAUT32.220)
3248 *
3249 * Convert a VT_DECIMAL to a VT_R8.
3250 *
3251 * PARAMS
3252 * pDecIn [I] Source
3253 * pDblOut [O] Destination
3254 *
3255 * RETURNS
3256 * Success: S_OK.
3257 * Failure: E_INVALIDARG, if the source value is invalid.
3258 */
3259 HRESULT WINAPI VarR8FromDec(const DECIMAL* pDecIn, double *pDblOut)
3260 {
3261 BYTE scale = DEC_SCALE(pDecIn);
3262 double divisor = 1.0, highPart;
3263
3264 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
3265 return E_INVALIDARG;
3266
3267 while (scale--)
3268 divisor *= 10;
3269
3270 if (DEC_SIGN(pDecIn))
3271 divisor = -divisor;
3272
3273 if (DEC_HI32(pDecIn))
3274 {
3275 highPart = (double)DEC_HI32(pDecIn) / divisor;
3276 highPart *= 4294967296.0F;
3277 highPart *= 4294967296.0F;
3278 }
3279 else
3280 highPart = 0.0;
3281
3282 *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
3283 return S_OK;
3284 }
3285
3286 /************************************************************************
3287 * VarR8FromI8 (OLEAUT32.362)
3288 *
3289 * Convert a VT_I8 to a VT_R8.
3290 *
3291 * PARAMS
3292 * ullIn [I] Source
3293 * pDblOut [O] Destination
3294 *
3295 * RETURNS
3296 * S_OK.
3297 */
3298 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3299 {
3300 return _VarR8FromI8(llIn, pDblOut);
3301 }
3302
3303 /************************************************************************
3304 * VarR8FromUI8 (OLEAUT32.363)
3305 *
3306 * Convert a VT_UI8 to a VT_R8.
3307 *
3308 * PARAMS
3309 * ullIn [I] Source
3310 * pDblOut [O] Destination
3311 *
3312 * RETURNS
3313 * S_OK.
3314 */
3315 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3316 {
3317 return _VarR8FromUI8(ullIn, pDblOut);
3318 }
3319
3320 /************************************************************************
3321 * VarR8Pow (OLEAUT32.315)
3322 *
3323 * Raise a VT_R8 to a power.
3324 *
3325 * PARAMS
3326 * dblLeft [I] Source
3327 * dblPow [I] Power to raise dblLeft by
3328 * pDblOut [O] Destination
3329 *
3330 * RETURNS
3331 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3332 */
3333 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3334 {
3335 *pDblOut = pow(dblLeft, dblPow);
3336 return S_OK;
3337 }
3338
3339 /************************************************************************
3340 * VarR8Round (OLEAUT32.317)
3341 *
3342 * Round a VT_R8 to a given number of decimal points.
3343 *
3344 * PARAMS
3345 * dblIn [I] Source
3346 * nDig [I] Number of decimal points to round to
3347 * pDblOut [O] Destination for rounded number
3348 *
3349 * RETURNS
3350 * Success: S_OK. pDblOut is rounded to nDig digits.
3351 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3352 *
3353 * NOTES
3354 * The native version of this function rounds using the internal
3355 * binary representation of the number. Wine uses the dutch rounding
3356 * convention, so therefore small differences can occur in the value returned.
3357 * MSDN says that you should use your own rounding function if you want
3358 * rounding to be predictable in your application.
3359 */
3360 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3361 {
3362 double scale, whole, fract;
3363
3364 if (nDig < 0)
3365 return E_INVALIDARG;
3366
3367 scale = pow(10.0, nDig);
3368
3369 dblIn *= scale;
3370 whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3371 fract = dblIn - whole;
3372
3373 if (fract > 0.5)
3374 dblIn = whole + 1.0;
3375 else if (fract == 0.5)
3376 dblIn = whole + fmod(whole, 2.0);
3377 else if (fract >= 0.0)
3378 dblIn = whole;
3379 else if (fract == -0.5)
3380 dblIn = whole - fmod(whole, 2.0);
3381 else if (fract > -0.5)
3382 dblIn = whole;
3383 else
3384 dblIn = whole - 1.0;
3385
3386 *pDblOut = dblIn / scale;
3387 return S_OK;
3388 }
3389
3390 /* CY
3391 */
3392
3393 /* Powers of 10 from 0..4 D.P. */
3394 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3395 CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
3396
3397 /************************************************************************
3398 * VarCyFromUI1 (OLEAUT32.98)
3399 *
3400 * Convert a VT_UI1 to a VT_CY.
3401 *
3402 * PARAMS
3403 * bIn [I] Source
3404 * pCyOut [O] Destination
3405 *
3406 * RETURNS
3407 * Success: S_OK.
3408 * Failure: E_INVALIDARG, if the source value is invalid
3409 * DISP_E_OVERFLOW, if the value will not fit in the destination
3410 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3411 */
3412 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
3413 {
3414 pCyOut->int64 = (ULONG64)bIn * CY_MULTIPLIER;
3415 return S_OK;
3416 }
3417
3418 /************************************************************************
3419 * VarCyFromI2 (OLEAUT32.99)
3420 *
3421 * Convert a VT_I2 to a VT_CY.
3422 *
3423 * PARAMS
3424 * sIn [I] Source
3425 * pCyOut [O] Destination
3426 *
3427 * RETURNS
3428 * Success: S_OK.
3429 * Failure: E_INVALIDARG, if the source value is invalid
3430 * DISP_E_OVERFLOW, if the value will not fit in the destination
3431 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3432 */
3433 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
3434 {
3435 pCyOut->int64 = (LONG64)sIn * CY_MULTIPLIER;
3436 return S_OK;
3437 }
3438
3439 /************************************************************************
3440 * VarCyFromI4 (OLEAUT32.100)
3441 *
3442 * Convert a VT_I4 to a VT_CY.
3443 *
3444 * PARAMS
3445 * sIn [I] Source
3446 * pCyOut [O] Destination
3447 *
3448 * RETURNS
3449 * Success: S_OK.
3450 * Failure: E_INVALIDARG, if the source value is invalid
3451 * DISP_E_OVERFLOW, if the value will not fit in the destination
3452 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3453 */
3454 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
3455 {
3456 pCyOut->int64 = (LONG64)lIn * CY_MULTIPLIER;
3457 return S_OK;
3458 }
3459
3460 /************************************************************************
3461 * VarCyFromR4 (OLEAUT32.101)
3462 *
3463 * Convert a VT_R4 to a VT_CY.
3464 *
3465 * PARAMS
3466 * fltIn [I] Source
3467 * pCyOut [O] Destination
3468 *
3469 * RETURNS
3470 * Success: S_OK.
3471 * Failure: E_INVALIDARG, if the source value is invalid
3472 * DISP_E_OVERFLOW, if the value will not fit in the destination
3473 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3474 */
3475 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
3476 {
3477 return VarCyFromR8(fltIn, pCyOut);
3478 }
3479
3480 /************************************************************************
3481 * VarCyFromR8 (OLEAUT32.102)
3482 *
3483 * Convert a VT_R8 to a VT_CY.
3484 *
3485 * PARAMS
3486 * dblIn [I] Source
3487 * pCyOut [O] Destination
3488 *
3489 * RETURNS
3490 * Success: S_OK.
3491 * Failure: E_INVALIDARG, if the source value is invalid
3492 * DISP_E_OVERFLOW, if the value will not fit in the destination
3493 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3494 */
3495 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3496 {
3497 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3498 /* This code gives identical results to Win32 on Intel.
3499 * Here we use fp exceptions to catch overflows when storing the value.
3500 */
3501 static const unsigned short r8_fpcontrol = 0x137f;
3502 static const double r8_multiplier = CY_MULTIPLIER_F;
3503 unsigned short old_fpcontrol, result_fpstatus;
3504
3505 /* Clear exceptions, save the old fp state and load the new state */
3506 __asm__ __volatile__( "fnclex" );
3507 __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
3508 __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
3509 /* Perform the conversion. */
3510 __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
3511 __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
3512 __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
3513 /* Save the resulting fp state, load the old state and clear exceptions */
3514 __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
3515 __asm__ __volatile__( "fnclex" );
3516 __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
3517
3518 if (result_fpstatus & 0x9) /* Overflow | Invalid */
3519 return DISP_E_OVERFLOW;
3520 #else
3521 /* This version produces slightly different results for boundary cases */
3522 if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3523 return DISP_E_OVERFLOW;
3524 dblIn *= CY_MULTIPLIER_F;
3525 VARIANT_DutchRound(LONG64, dblIn, pCyOut->int64);
3526 #endif
3527 return S_OK;
3528 }
3529
3530 /************************************************************************
3531 * VarCyFromDate (OLEAUT32.103)
3532 *
3533 * Convert a VT_DATE to a VT_CY.
3534 *
3535 * PARAMS
3536 * dateIn [I] Source
3537 * pCyOut [O] Destination
3538 *
3539 * RETURNS
3540 * Success: S_OK.