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