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