remove FIXMEs and enable now compiling functions
[reactos.git] / reactos / lib / 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #define NONAMELESSUNION
21 #define NONAMELESSSTRUCT
22 #include "wine/debug.h"
23 #include "wine/unicode.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "winnt.h"
27 #include "variant.h"
28 #include "resource.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(ole);
31
32
33 #ifdef __REACTOS__ /*FIXME*/
34 /* problems with decVal member of VARIANT union in MinGW headers */
35 #undef V_DECIMAL
36 #define V_DECIMAL(X) (X->__VARIANT_NAME_1.decVal)
37 #endif
38
39
40 extern HMODULE OLEAUT32_hModule;
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 #ifndef __REACTOS__ /*FIXME*/
55 case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT));
56 #endif
57 break;
58 case VT_R4:
59 case VT_INT:
60 case VT_I4:
61 case VT_UINT:
62 #ifndef __REACTOS__ /*FIXME*/
63 case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG));
64 #endif
65 break;
66 case VT_R8:
67 case VT_DATE:
68 case VT_CY:
69 case VT_I8:
70 #ifndef __REACTOS__ /*FIXME*/
71 case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64));
72 #endif
73 break;
74 case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
75 case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
76 default:
77 FIXME("VT_ type %d unhandled, please report!\n", vt);
78 }
79 }
80
81
82 /* Coerce VT_BSTR to a numeric type */
83 HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
84 void* pOut, VARTYPE vt)
85 {
86 VARIANTARG dstVar;
87 HRESULT hRet;
88 NUMPARSE np;
89 BYTE rgb[1024];
90
91 /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
92 np.cDig = sizeof(rgb) / sizeof(BYTE);
93 np.dwInFlags = NUMPRS_STD;
94
95 hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
96
97 if (SUCCEEDED(hRet))
98 {
99 /* 1 << vt gives us the VTBIT constant for the destination number type */
100 hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
101 if (SUCCEEDED(hRet))
102 VARIANT_CopyData(&dstVar, vt, pOut);
103 }
104 return hRet;
105 }
106
107 /* Coerce VT_DISPATCH to another type */
108 HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, VARTYPE vt)
109 {
110 static const DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
111 VARIANTARG srcVar, dstVar;
112 HRESULT hRet;
113
114 if (!pdispIn)
115 return DISP_E_BADVARTYPE;
116
117 /* Get the default 'value' property from the IDispatch */
118 hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
119 (DISPPARAMS*)&emptyParams, &srcVar, NULL, NULL);
120
121 if (SUCCEEDED(hRet))
122 {
123 /* Convert the property to the requested type */
124 V_VT(&dstVar) = VT_EMPTY;
125 hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, 0, vt);
126 VariantClear(&srcVar);
127
128 if (SUCCEEDED(hRet))
129 {
130 VARIANT_CopyData(&dstVar, vt, pOut);
131 VariantClear(&srcVar);
132 }
133 }
134 else
135 hRet = DISP_E_TYPEMISMATCH;
136 return hRet;
137 }
138
139 /* I1
140 */
141
142 /************************************************************************
143 * VarI1FromUI1 (OLEAUT32.244)
144 *
145 * Convert a VT_UI1 to a VT_I1.
146 *
147 * PARAMS
148 * bIn [I] Source
149 * pcOut [O] Destination
150 *
151 * RETURNS
152 * Success: S_OK.
153 * Failure: E_INVALIDARG, if the source value is invalid
154 * DISP_E_OVERFLOW, if the value will not fit in the destination
155 */
156 HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
157 {
158 return _VarI1FromUI1(bIn, pcOut);
159 }
160
161 /************************************************************************
162 * VarI1FromI2 (OLEAUT32.245)
163 *
164 * Convert a VT_I2 to a VT_I1.
165 *
166 * PARAMS
167 * sIn [I] Source
168 * pcOut [O] Destination
169 *
170 * RETURNS
171 * Success: S_OK.
172 * Failure: E_INVALIDARG, if the source value is invalid
173 * DISP_E_OVERFLOW, if the value will not fit in the destination
174 */
175 HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
176 {
177 return _VarI1FromI2(sIn, pcOut);
178 }
179
180 /************************************************************************
181 * VarI1FromI4 (OLEAUT32.246)
182 *
183 * Convert a VT_I4 to a VT_I1.
184 *
185 * PARAMS
186 * iIn [I] Source
187 * pcOut [O] Destination
188 *
189 * RETURNS
190 * Success: S_OK.
191 * Failure: E_INVALIDARG, if the source value is invalid
192 * DISP_E_OVERFLOW, if the value will not fit in the destination
193 */
194 HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
195 {
196 return _VarI1FromI4(iIn, pcOut);
197 }
198
199 /************************************************************************
200 * VarI1FromR4 (OLEAUT32.247)
201 *
202 * Convert a VT_R4 to a VT_I1.
203 *
204 * PARAMS
205 * fltIn [I] Source
206 * pcOut [O] Destination
207 *
208 * RETURNS
209 * Success: S_OK.
210 * Failure: E_INVALIDARG, if the source value is invalid
211 * DISP_E_OVERFLOW, if the value will not fit in the destination
212 */
213 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
214 {
215 return _VarI1FromR4(fltIn, pcOut);
216 }
217
218 /************************************************************************
219 * VarI1FromR8 (OLEAUT32.248)
220 *
221 * Convert a VT_R8 to a VT_I1.
222 *
223 * PARAMS
224 * dblIn [I] Source
225 * pcOut [O] Destination
226 *
227 * RETURNS
228 * Success: S_OK.
229 * Failure: E_INVALIDARG, if the source value is invalid
230 * DISP_E_OVERFLOW, if the value will not fit in the destination
231 *
232 * NOTES
233 * See VarI8FromR8() for details concerning rounding.
234 */
235 HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
236 {
237 if (dblIn < (double)I1_MIN || dblIn > (double)I1_MAX)
238 return DISP_E_OVERFLOW;
239 OLEAUT32_DutchRound(CHAR, dblIn, *pcOut);
240 return S_OK;
241 }
242
243 /************************************************************************
244 * VarI1FromDate (OLEAUT32.249)
245 *
246 * Convert a VT_DATE to a VT_I1.
247 *
248 * PARAMS
249 * dateIn [I] Source
250 * pcOut [O] Destination
251 *
252 * RETURNS
253 * Success: S_OK.
254 * Failure: E_INVALIDARG, if the source value is invalid
255 * DISP_E_OVERFLOW, if the value will not fit in the destination
256 */
257 HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
258 {
259 return _VarI1FromDate(dateIn, pcOut);
260 }
261
262 /************************************************************************
263 * VarI1FromCy (OLEAUT32.250)
264 *
265 * Convert a VT_CY to a VT_I1.
266 *
267 * PARAMS
268 * cyIn [I] Source
269 * pcOut [O] Destination
270 *
271 * RETURNS
272 * Success: S_OK.
273 * Failure: E_INVALIDARG, if the source value is invalid
274 * DISP_E_OVERFLOW, if the value will not fit in the destination
275 */
276 HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
277 {
278 LONG i = I1_MAX + 1;
279
280 _VarI4FromCy(cyIn, &i);
281 return _VarI1FromI4(i, pcOut);
282 }
283
284 /************************************************************************
285 * VarI1FromStr (OLEAUT32.251)
286 *
287 * Convert a VT_BSTR to a VT_I1.
288 *
289 * PARAMS
290 * strIn [I] Source
291 * lcid [I] LCID for the conversion
292 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
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 * DISP_E_TYPEMISMATCH, if the type cannot be converted
300 */
301 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
302 {
303 return _VarI1FromStr(strIn, lcid, dwFlags, pcOut);
304 }
305
306 /************************************************************************
307 * VarI1FromDisp (OLEAUT32.252)
308 *
309 * Convert a VT_DISPATCH to a VT_I1.
310 *
311 * PARAMS
312 * pdispIn [I] Source
313 * lcid [I] LCID for conversion
314 * pcOut [O] Destination
315 *
316 * RETURNS
317 * Success: S_OK.
318 * Failure: E_INVALIDARG, if the source value is invalid
319 * DISP_E_OVERFLOW, if the value will not fit in the destination
320 * DISP_E_TYPEMISMATCH, if the type cannot be converted
321 */
322 HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
323 {
324 return _VarI1FromDisp(pdispIn, lcid, pcOut);
325 }
326
327 /************************************************************************
328 * VarI1FromBool (OLEAUT32.253)
329 *
330 * Convert a VT_BOOL to a VT_I1.
331 *
332 * PARAMS
333 * boolIn [I] Source
334 * pcOut [O] Destination
335 *
336 * RETURNS
337 * S_OK.
338 */
339 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
340 {
341 return _VarI1FromBool(boolIn, pcOut);
342 }
343
344 /************************************************************************
345 * VarI1FromUI2 (OLEAUT32.254)
346 *
347 * Convert a VT_UI2 to a VT_I1.
348 *
349 * PARAMS
350 * usIn [I] Source
351 * pcOut [O] Destination
352 *
353 * RETURNS
354 * Success: S_OK.
355 * Failure: E_INVALIDARG, if the source value is invalid
356 * DISP_E_OVERFLOW, if the value will not fit in the destination
357 */
358 HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
359 {
360 return _VarI1FromUI2(usIn, pcOut);
361 }
362
363 /************************************************************************
364 * VarI1FromUI4 (OLEAUT32.255)
365 *
366 * Convert a VT_UI4 to a VT_I1.
367 *
368 * PARAMS
369 * ulIn [I] Source
370 * pcOut [O] Destination
371 *
372 * RETURNS
373 * Success: S_OK.
374 * Failure: E_INVALIDARG, if the source value is invalid
375 * DISP_E_OVERFLOW, if the value will not fit in the destination
376 * DISP_E_TYPEMISMATCH, if the type cannot be converted
377 */
378 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
379 {
380 return _VarI1FromUI4(ulIn, pcOut);
381 }
382
383 /************************************************************************
384 * VarI1FromDec (OLEAUT32.256)
385 *
386 * Convert a VT_DECIMAL to a VT_I1.
387 *
388 * PARAMS
389 * pDecIn [I] Source
390 * pcOut [O] Destination
391 *
392 * RETURNS
393 * Success: S_OK.
394 * Failure: E_INVALIDARG, if the source value is invalid
395 * DISP_E_OVERFLOW, if the value will not fit in the destination
396 */
397 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
398 HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
399 {
400 LONG64 i64;
401 HRESULT hRet;
402
403 hRet = _VarI8FromDec(pdecIn, &i64);
404
405 if (SUCCEEDED(hRet))
406 hRet = _VarI1FromI8(i64, pcOut);
407 return hRet;
408 }
409 #endif
410
411 /************************************************************************
412 * VarI1FromI8 (OLEAUT32.376)
413 *
414 * Convert a VT_I8 to a VT_I1.
415 *
416 * PARAMS
417 * llIn [I] Source
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 */
425 HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
426 {
427 return _VarI1FromI8(llIn, pcOut);
428 }
429
430 /************************************************************************
431 * VarI1FromUI8 (OLEAUT32.377)
432 *
433 * Convert a VT_UI8 to a VT_I1.
434 *
435 * PARAMS
436 * ullIn [I] Source
437 * pcOut [O] Destination
438 *
439 * RETURNS
440 * Success: S_OK.
441 * Failure: E_INVALIDARG, if the source value is invalid
442 * DISP_E_OVERFLOW, if the value will not fit in the destination
443 */
444 HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
445 {
446 return _VarI1FromUI8(ullIn, pcOut);
447 }
448
449 /* UI1
450 */
451
452 /************************************************************************
453 * VarUI1FromI2 (OLEAUT32.130)
454 *
455 * Convert a VT_I2 to a VT_UI1.
456 *
457 * PARAMS
458 * sIn [I] Source
459 * pbOut [O] Destination
460 *
461 * RETURNS
462 * Success: S_OK.
463 * Failure: E_INVALIDARG, if the source value is invalid
464 * DISP_E_OVERFLOW, if the value will not fit in the destination
465 */
466 HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
467 {
468 return _VarUI1FromI2(sIn, pbOut);
469 }
470
471 /************************************************************************
472 * VarUI1FromI4 (OLEAUT32.131)
473 *
474 * Convert a VT_I4 to a VT_UI1.
475 *
476 * PARAMS
477 * iIn [I] Source
478 * pbOut [O] Destination
479 *
480 * RETURNS
481 * Success: S_OK.
482 * Failure: E_INVALIDARG, if the source value is invalid
483 * DISP_E_OVERFLOW, if the value will not fit in the destination
484 */
485 HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
486 {
487 return _VarUI1FromI4(iIn, pbOut);
488 }
489
490 /************************************************************************
491 * VarUI1FromR4 (OLEAUT32.132)
492 *
493 * Convert a VT_R4 to a VT_UI1.
494 *
495 * PARAMS
496 * fltIn [I] Source
497 * pbOut [O] Destination
498 *
499 * RETURNS
500 * Success: S_OK.
501 * Failure: E_INVALIDARG, if the source value is invalid
502 * DISP_E_OVERFLOW, if the value will not fit in the destination
503 * DISP_E_TYPEMISMATCH, if the type cannot be converted
504 */
505 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
506 {
507 return _VarUI1FromR4(fltIn, pbOut);
508 }
509
510 /************************************************************************
511 * VarUI1FromR8 (OLEAUT32.133)
512 *
513 * Convert a VT_R8 to a VT_UI1.
514 *
515 * PARAMS
516 * dblIn [I] Source
517 * pbOut [O] Destination
518 *
519 * RETURNS
520 * Success: S_OK.
521 * Failure: E_INVALIDARG, if the source value is invalid
522 * DISP_E_OVERFLOW, if the value will not fit in the destination
523 *
524 * NOTES
525 * See VarI8FromR8() for details concerning rounding.
526 */
527 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
528 {
529 if (dblIn < -0.5 || dblIn > (double)UI1_MAX)
530 return DISP_E_OVERFLOW;
531 OLEAUT32_DutchRound(BYTE, dblIn, *pbOut);
532 return S_OK;
533 }
534
535 /************************************************************************
536 * VarUI1FromCy (OLEAUT32.134)
537 *
538 * Convert a VT_CY to a VT_UI1.
539 *
540 * PARAMS
541 * cyIn [I] Source
542 * pbOut [O] Destination
543 *
544 * RETURNS
545 * Success: S_OK.
546 * Failure: E_INVALIDARG, if the source value is invalid
547 * DISP_E_OVERFLOW, if the value will not fit in the destination
548 *
549 * NOTES
550 * Negative values >= -5000 will be converted to 0.
551 */
552 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
553 {
554 ULONG i = UI1_MAX + 1;
555
556 _VarUI4FromCy(cyIn, &i);
557 return _VarUI1FromUI4(i, pbOut);
558 }
559
560 /************************************************************************
561 * VarUI1FromDate (OLEAUT32.135)
562 *
563 * Convert a VT_DATE to a VT_UI1.
564 *
565 * PARAMS
566 * dateIn [I] Source
567 * pbOut [O] Destination
568 *
569 * RETURNS
570 * Success: S_OK.
571 * Failure: E_INVALIDARG, if the source value is invalid
572 * DISP_E_OVERFLOW, if the value will not fit in the destination
573 */
574 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
575 {
576 return _VarUI1FromDate(dateIn, pbOut);
577 }
578
579 /************************************************************************
580 * VarUI1FromStr (OLEAUT32.136)
581 *
582 * Convert a VT_BSTR to a VT_UI1.
583 *
584 * PARAMS
585 * strIn [I] Source
586 * lcid [I] LCID for the conversion
587 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
588 * pbOut [O] Destination
589 *
590 * RETURNS
591 * Success: S_OK.
592 * Failure: E_INVALIDARG, if the source value is invalid
593 * DISP_E_OVERFLOW, if the value will not fit in the destination
594 * DISP_E_TYPEMISMATCH, if the type cannot be converted
595 */
596 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
597 {
598 return _VarUI1FromStr(strIn, lcid, dwFlags, pbOut);
599 }
600
601 /************************************************************************
602 * VarUI1FromDisp (OLEAUT32.137)
603 *
604 * Convert a VT_DISPATCH to a VT_UI1.
605 *
606 * PARAMS
607 * pdispIn [I] Source
608 * lcid [I] LCID for conversion
609 * pbOut [O] Destination
610 *
611 * RETURNS
612 * Success: S_OK.
613 * Failure: E_INVALIDARG, if the source value is invalid
614 * DISP_E_OVERFLOW, if the value will not fit in the destination
615 * DISP_E_TYPEMISMATCH, if the type cannot be converted
616 */
617 HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
618 {
619 return _VarUI1FromDisp(pdispIn, lcid, pbOut);
620 }
621
622 /************************************************************************
623 * VarUI1FromBool (OLEAUT32.138)
624 *
625 * Convert a VT_BOOL to a VT_UI1.
626 *
627 * PARAMS
628 * boolIn [I] Source
629 * pbOut [O] Destination
630 *
631 * RETURNS
632 * S_OK.
633 */
634 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
635 {
636 return _VarUI1FromBool(boolIn, pbOut);
637 }
638
639 /************************************************************************
640 * VarUI1FromI1 (OLEAUT32.237)
641 *
642 * Convert a VT_I1 to a VT_UI1.
643 *
644 * PARAMS
645 * cIn [I] Source
646 * pbOut [O] Destination
647 *
648 * RETURNS
649 * Success: S_OK.
650 * Failure: E_INVALIDARG, if the source value is invalid
651 * DISP_E_OVERFLOW, if the value will not fit in the destination
652 */
653 HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
654 {
655 return _VarUI1FromI1(cIn, pbOut);
656 }
657
658 /************************************************************************
659 * VarUI1FromUI2 (OLEAUT32.238)
660 *
661 * Convert a VT_UI2 to a VT_UI1.
662 *
663 * PARAMS
664 * usIn [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 HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
673 {
674 return _VarUI1FromUI2(usIn, pbOut);
675 }
676
677 /************************************************************************
678 * VarUI1FromUI4 (OLEAUT32.239)
679 *
680 * Convert a VT_UI4 to a VT_UI1.
681 *
682 * PARAMS
683 * ulIn [I] Source
684 * pbOut [O] Destination
685 *
686 * RETURNS
687 * Success: S_OK.
688 * Failure: E_INVALIDARG, if the source value is invalid
689 * DISP_E_OVERFLOW, if the value will not fit in the destination
690 */
691 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
692 {
693 return _VarUI1FromUI4(ulIn, pbOut);
694 }
695
696 /************************************************************************
697 * VarUI1FromDec (OLEAUT32.240)
698 *
699 * Convert a VT_DECIMAL to a VT_UI1.
700 *
701 * PARAMS
702 * pDecIn [I] Source
703 * pbOut [O] Destination
704 *
705 * RETURNS
706 * Success: S_OK.
707 * Failure: E_INVALIDARG, if the source value is invalid
708 * DISP_E_OVERFLOW, if the value will not fit in the destination
709 */
710 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
711 HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
712 {
713 LONG64 i64;
714 HRESULT hRet;
715
716 hRet = _VarI8FromDec(pdecIn, &i64);
717
718 if (SUCCEEDED(hRet))
719 hRet = _VarUI1FromI8(i64, pbOut);
720 return hRet;
721 }
722 #endif
723
724 /************************************************************************
725 * VarUI1FromI8 (OLEAUT32.372)
726 *
727 * Convert a VT_I8 to a VT_UI1.
728 *
729 * PARAMS
730 * llIn [I] Source
731 * pbOut [O] Destination
732 *
733 * RETURNS
734 * Success: S_OK.
735 * Failure: E_INVALIDARG, if the source value is invalid
736 * DISP_E_OVERFLOW, if the value will not fit in the destination
737 */
738 HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
739 {
740 return _VarUI1FromI8(llIn, pbOut);
741 }
742
743 /************************************************************************
744 * VarUI1FromUI8 (OLEAUT32.373)
745 *
746 * Convert a VT_UI8 to a VT_UI1.
747 *
748 * PARAMS
749 * ullIn [I] Source
750 * pbOut [O] Destination
751 *
752 * RETURNS
753 * Success: S_OK.
754 * Failure: E_INVALIDARG, if the source value is invalid
755 * DISP_E_OVERFLOW, if the value will not fit in the destination
756 */
757 HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
758 {
759 return _VarUI1FromUI8(ullIn, pbOut);
760 }
761
762
763 /* I2
764 */
765
766 /************************************************************************
767 * VarI2FromUI1 (OLEAUT32.48)
768 *
769 * Convert a VT_UI2 to a VT_I2.
770 *
771 * PARAMS
772 * bIn [I] Source
773 * psOut [O] Destination
774 *
775 * RETURNS
776 * S_OK.
777 */
778 HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
779 {
780 return _VarI2FromUI1(bIn, psOut);
781 }
782
783 /************************************************************************
784 * VarI2FromI4 (OLEAUT32.49)
785 *
786 * Convert a VT_I4 to a VT_I2.
787 *
788 * PARAMS
789 * iIn [I] Source
790 * psOut [O] Destination
791 *
792 * RETURNS
793 * Success: S_OK.
794 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
795 */
796 HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
797 {
798 return _VarI2FromI4(iIn, psOut);
799 }
800
801 /************************************************************************
802 * VarI2FromR4 (OLEAUT32.50)
803 *
804 * Convert a VT_R4 to a VT_I2.
805 *
806 * PARAMS
807 * fltIn [I] Source
808 * psOut [O] Destination
809 *
810 * RETURNS
811 * Success: S_OK.
812 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
813 */
814 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
815 {
816 return _VarI2FromR4(fltIn, psOut);
817 }
818
819 /************************************************************************
820 * VarI2FromR8 (OLEAUT32.51)
821 *
822 * Convert a VT_R8 to a VT_I2.
823 *
824 * PARAMS
825 * dblIn [I] Source
826 * psOut [O] Destination
827 *
828 * RETURNS
829 * Success: S_OK.
830 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
831 *
832 * NOTES
833 * See VarI8FromR8() for details concerning rounding.
834 */
835 HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
836 {
837 if (dblIn < (double)I2_MIN || dblIn > (double)I2_MAX)
838 return DISP_E_OVERFLOW;
839 OLEAUT32_DutchRound(SHORT, dblIn, *psOut);
840 return S_OK;
841 }
842
843 /************************************************************************
844 * VarI2FromCy (OLEAUT32.52)
845 *
846 * Convert a VT_CY to a VT_I2.
847 *
848 * PARAMS
849 * cyIn [I] Source
850 * psOut [O] Destination
851 *
852 * RETURNS
853 * Success: S_OK.
854 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
855 */
856 HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
857 {
858 LONG i = I2_MAX + 1;
859
860 _VarI4FromCy(cyIn, &i);
861 return _VarI2FromI4(i, psOut);
862 }
863
864 /************************************************************************
865 * VarI2FromDate (OLEAUT32.53)
866 *
867 * Convert a VT_DATE to a VT_I2.
868 *
869 * PARAMS
870 * dateIn [I] Source
871 * psOut [O] Destination
872 *
873 * RETURNS
874 * Success: S_OK.
875 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
876 */
877 HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
878 {
879 return _VarI2FromDate(dateIn, psOut);
880 }
881
882 /************************************************************************
883 * VarI2FromStr (OLEAUT32.54)
884 *
885 * Convert a VT_BSTR to a VT_I2.
886 *
887 * PARAMS
888 * strIn [I] Source
889 * lcid [I] LCID for the conversion
890 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
891 * psOut [O] Destination
892 *
893 * RETURNS
894 * Success: S_OK.
895 * Failure: E_INVALIDARG, if any parameter is invalid
896 * DISP_E_OVERFLOW, if the value will not fit in the destination
897 * DISP_E_TYPEMISMATCH, if the type cannot be converted
898 */
899 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
900 {
901 return _VarI2FromStr(strIn, lcid, dwFlags, psOut);
902 }
903
904 /************************************************************************
905 * VarI2FromDisp (OLEAUT32.55)
906 *
907 * Convert a VT_DISPATCH to a VT_I2.
908 *
909 * PARAMS
910 * pdispIn [I] Source
911 * lcid [I] LCID for conversion
912 * psOut [O] Destination
913 *
914 * RETURNS
915 * Success: S_OK.
916 * Failure: E_INVALIDARG, if pdispIn is invalid,
917 * DISP_E_OVERFLOW, if the value will not fit in the destination,
918 * DISP_E_TYPEMISMATCH, if the type cannot be converted
919 */
920 HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
921 {
922 return _VarI2FromDisp(pdispIn, lcid, psOut);
923 }
924
925 /************************************************************************
926 * VarI2FromBool (OLEAUT32.56)
927 *
928 * Convert a VT_BOOL to a VT_I2.
929 *
930 * PARAMS
931 * boolIn [I] Source
932 * psOut [O] Destination
933 *
934 * RETURNS
935 * S_OK.
936 */
937 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
938 {
939 return _VarI2FromBool(boolIn, psOut);
940 }
941
942 /************************************************************************
943 * VarI2FromI1 (OLEAUT32.205)
944 *
945 * Convert a VT_I1 to a VT_I2.
946 *
947 * PARAMS
948 * cIn [I] Source
949 * psOut [O] Destination
950 *
951 * RETURNS
952 * S_OK.
953 */
954 HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
955 {
956 return _VarI2FromI1(cIn, psOut);
957 }
958
959 /************************************************************************
960 * VarI2FromUI2 (OLEAUT32.206)
961 *
962 * Convert a VT_UI2 to a VT_I2.
963 *
964 * PARAMS
965 * usIn [I] Source
966 * psOut [O] Destination
967 *
968 * RETURNS
969 * Success: S_OK.
970 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
971 */
972 HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
973 {
974 return _VarI2FromUI2(usIn, psOut);
975 }
976
977 /************************************************************************
978 * VarI2FromUI4 (OLEAUT32.207)
979 *
980 * Convert a VT_UI4 to a VT_I2.
981 *
982 * PARAMS
983 * ulIn [I] Source
984 * psOut [O] Destination
985 *
986 * RETURNS
987 * Success: S_OK.
988 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
989 */
990 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
991 {
992 return _VarI2FromUI4(ulIn, psOut);
993 }
994
995 /************************************************************************
996 * VarI2FromDec (OLEAUT32.208)
997 *
998 * Convert a VT_DECIMAL to a VT_I2.
999 *
1000 * PARAMS
1001 * pDecIn [I] Source
1002 * psOut [O] Destination
1003 *
1004 * RETURNS
1005 * Success: S_OK.
1006 * Failure: E_INVALIDARG, if the source value is invalid
1007 * DISP_E_OVERFLOW, if the value will not fit in the destination
1008 */
1009 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
1010 HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
1011 {
1012 LONG64 i64;
1013 HRESULT hRet;
1014
1015 hRet = _VarI8FromDec(pdecIn, &i64);
1016
1017 if (SUCCEEDED(hRet))
1018 hRet = _VarI2FromI8(i64, psOut);
1019 return hRet;
1020 }
1021 #endif
1022
1023 /************************************************************************
1024 * VarI2FromI8 (OLEAUT32.346)
1025 *
1026 * Convert a VT_I8 to a VT_I2.
1027 *
1028 * PARAMS
1029 * llIn [I] Source
1030 * psOut [O] Destination
1031 *
1032 * RETURNS
1033 * Success: S_OK.
1034 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1035 */
1036 HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
1037 {
1038 return _VarI2FromI8(llIn, psOut);
1039 }
1040
1041 /************************************************************************
1042 * VarI2FromUI8 (OLEAUT32.347)
1043 *
1044 * Convert a VT_UI8 to a VT_I2.
1045 *
1046 * PARAMS
1047 * ullIn [I] Source
1048 * psOut [O] Destination
1049 *
1050 * RETURNS
1051 * Success: S_OK.
1052 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1053 */
1054 HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
1055 {
1056 return _VarI2FromUI8(ullIn, psOut);
1057 }
1058
1059 /* UI2
1060 */
1061
1062 /************************************************************************
1063 * VarUI2FromUI1 (OLEAUT32.257)
1064 *
1065 * Convert a VT_UI1 to a VT_UI2.
1066 *
1067 * PARAMS
1068 * bIn [I] Source
1069 * pusOut [O] Destination
1070 *
1071 * RETURNS
1072 * S_OK.
1073 */
1074 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
1075 {
1076 return _VarUI2FromUI1(bIn, pusOut);
1077 }
1078
1079 /************************************************************************
1080 * VarUI2FromI2 (OLEAUT32.258)
1081 *
1082 * Convert a VT_I2 to a VT_UI2.
1083 *
1084 * PARAMS
1085 * sIn [I] Source
1086 * pusOut [O] Destination
1087 *
1088 * RETURNS
1089 * Success: S_OK.
1090 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1091 */
1092 HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
1093 {
1094 return _VarUI2FromI2(sIn, pusOut);
1095 }
1096
1097 /************************************************************************
1098 * VarUI2FromI4 (OLEAUT32.259)
1099 *
1100 * Convert a VT_I4 to a VT_UI2.
1101 *
1102 * PARAMS
1103 * iIn [I] Source
1104 * pusOut [O] Destination
1105 *
1106 * RETURNS
1107 * Success: S_OK.
1108 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1109 */
1110 HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
1111 {
1112 return _VarUI2FromI4(iIn, pusOut);
1113 }
1114
1115 /************************************************************************
1116 * VarUI2FromR4 (OLEAUT32.260)
1117 *
1118 * Convert a VT_R4 to a VT_UI2.
1119 *
1120 * PARAMS
1121 * fltIn [I] Source
1122 * pusOut [O] Destination
1123 *
1124 * RETURNS
1125 * Success: S_OK.
1126 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1127 */
1128 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
1129 {
1130 return _VarUI2FromR4(fltIn, pusOut);
1131 }
1132
1133 /************************************************************************
1134 * VarUI2FromR8 (OLEAUT32.261)
1135 *
1136 * Convert a VT_R8 to a VT_UI2.
1137 *
1138 * PARAMS
1139 * dblIn [I] Source
1140 * pusOut [O] Destination
1141 *
1142 * RETURNS
1143 * Success: S_OK.
1144 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1145 *
1146 * NOTES
1147 * See VarI8FromR8() for details concerning rounding.
1148 */
1149 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
1150 {
1151 if (dblIn < -0.5 || dblIn > (double)UI2_MAX)
1152 return DISP_E_OVERFLOW;
1153 OLEAUT32_DutchRound(USHORT, dblIn, *pusOut);
1154 return S_OK;
1155 }
1156
1157 /************************************************************************
1158 * VarUI2FromDate (OLEAUT32.262)
1159 *
1160 * Convert a VT_DATE to a VT_UI2.
1161 *
1162 * PARAMS
1163 * dateIn [I] Source
1164 * pusOut [O] Destination
1165 *
1166 * RETURNS
1167 * Success: S_OK.
1168 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1169 */
1170 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
1171 {
1172 return _VarUI2FromDate(dateIn, pusOut);
1173 }
1174
1175 /************************************************************************
1176 * VarUI2FromCy (OLEAUT32.263)
1177 *
1178 * Convert a VT_CY to a VT_UI2.
1179 *
1180 * PARAMS
1181 * cyIn [I] Source
1182 * pusOut [O] Destination
1183 *
1184 * RETURNS
1185 * Success: S_OK.
1186 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1187 *
1188 * NOTES
1189 * Negative values >= -5000 will be converted to 0.
1190 */
1191 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
1192 {
1193 ULONG i = UI2_MAX + 1;
1194
1195 _VarUI4FromCy(cyIn, &i);
1196 return _VarUI2FromUI4(i, pusOut);
1197 }
1198
1199 /************************************************************************
1200 * VarUI2FromStr (OLEAUT32.264)
1201 *
1202 * Convert a VT_BSTR to a VT_UI2.
1203 *
1204 * PARAMS
1205 * strIn [I] Source
1206 * lcid [I] LCID for the conversion
1207 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1208 * pusOut [O] Destination
1209 *
1210 * RETURNS
1211 * Success: S_OK.
1212 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1213 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1214 */
1215 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
1216 {
1217 return _VarUI2FromStr(strIn, lcid, dwFlags, pusOut);
1218 }
1219
1220 /************************************************************************
1221 * VarUI2FromDisp (OLEAUT32.265)
1222 *
1223 * Convert a VT_DISPATCH to a VT_UI2.
1224 *
1225 * PARAMS
1226 * pdispIn [I] Source
1227 * lcid [I] LCID for conversion
1228 * pusOut [O] Destination
1229 *
1230 * RETURNS
1231 * Success: S_OK.
1232 * Failure: E_INVALIDARG, if the source value is invalid
1233 * DISP_E_OVERFLOW, if the value will not fit in the destination
1234 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1235 */
1236 HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
1237 {
1238 return _VarUI2FromDisp(pdispIn, lcid, pusOut);
1239 }
1240
1241 /************************************************************************
1242 * VarUI2FromBool (OLEAUT32.266)
1243 *
1244 * Convert a VT_BOOL to a VT_UI2.
1245 *
1246 * PARAMS
1247 * boolIn [I] Source
1248 * pusOut [O] Destination
1249 *
1250 * RETURNS
1251 * S_OK.
1252 */
1253 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
1254 {
1255 return _VarUI2FromBool(boolIn, pusOut);
1256 }
1257
1258 /************************************************************************
1259 * VarUI2FromI1 (OLEAUT32.267)
1260 *
1261 * Convert a VT_I1 to a VT_UI2.
1262 *
1263 * PARAMS
1264 * cIn [I] Source
1265 * pusOut [O] Destination
1266 *
1267 * RETURNS
1268 * Success: S_OK.
1269 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1270 */
1271 HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
1272 {
1273 return _VarUI2FromI1(cIn, pusOut);
1274 }
1275
1276 /************************************************************************
1277 * VarUI2FromUI4 (OLEAUT32.268)
1278 *
1279 * Convert a VT_UI4 to a VT_UI2.
1280 *
1281 * PARAMS
1282 * ulIn [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 VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
1290 {
1291 return _VarUI2FromUI4(ulIn, pusOut);
1292 }
1293
1294 /************************************************************************
1295 * VarUI2FromDec (OLEAUT32.269)
1296 *
1297 * Convert a VT_DECIMAL to a VT_UI2.
1298 *
1299 * PARAMS
1300 * pDecIn [I] Source
1301 * pusOut [O] Destination
1302 *
1303 * RETURNS
1304 * Success: S_OK.
1305 * Failure: E_INVALIDARG, if the source value is invalid
1306 * DISP_E_OVERFLOW, if the value will not fit in the destination
1307 */
1308 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
1309 HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
1310 {
1311 LONG64 i64;
1312 HRESULT hRet;
1313
1314 hRet = _VarI8FromDec(pdecIn, &i64);
1315
1316 if (SUCCEEDED(hRet))
1317 hRet = _VarUI2FromI8(i64, pusOut);
1318 return hRet;
1319 }
1320 #endif
1321
1322 /************************************************************************
1323 * VarUI2FromI8 (OLEAUT32.378)
1324 *
1325 * Convert a VT_I8 to a VT_UI2.
1326 *
1327 * PARAMS
1328 * llIn [I] Source
1329 * pusOut [O] Destination
1330 *
1331 * RETURNS
1332 * Success: S_OK.
1333 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1334 */
1335 HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
1336 {
1337 return _VarUI2FromI8(llIn, pusOut);
1338 }
1339
1340 /************************************************************************
1341 * VarUI2FromUI8 (OLEAUT32.379)
1342 *
1343 * Convert a VT_UI8 to a VT_UI2.
1344 *
1345 * PARAMS
1346 * ullIn [I] Source
1347 * pusOut [O] Destination
1348 *
1349 * RETURNS
1350 * Success: S_OK.
1351 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1352 */
1353 HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
1354 {
1355 return _VarUI2FromUI8(ullIn, pusOut);
1356 }
1357
1358 /* I4
1359 */
1360
1361 /************************************************************************
1362 * VarI4FromUI1 (OLEAUT32.58)
1363 *
1364 * Convert a VT_UI1 to a VT_I4.
1365 *
1366 * PARAMS
1367 * bIn [I] Source
1368 * piOut [O] Destination
1369 *
1370 * RETURNS
1371 * S_OK.
1372 */
1373 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
1374 {
1375 return _VarI4FromUI1(bIn, piOut);
1376 }
1377
1378 /************************************************************************
1379 * VarI4FromI2 (OLEAUT32.59)
1380 *
1381 * Convert a VT_I2 to a VT_I4.
1382 *
1383 * PARAMS
1384 * iIn [I] Source
1385 * piOut [O] Destination
1386 *
1387 * RETURNS
1388 * Success: S_OK.
1389 * Failure: E_INVALIDARG, if the source value is invalid
1390 * DISP_E_OVERFLOW, if the value will not fit in the destination
1391 */
1392 HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
1393 {
1394 return _VarI4FromI2(sIn, piOut);
1395 }
1396
1397 /************************************************************************
1398 * VarI4FromR4 (OLEAUT32.60)
1399 *
1400 * Convert a VT_R4 to a VT_I4.
1401 *
1402 * PARAMS
1403 * fltIn [I] Source
1404 * piOut [O] Destination
1405 *
1406 * RETURNS
1407 * Success: S_OK.
1408 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1409 */
1410 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
1411 {
1412 return _VarI4FromR4(fltIn, piOut);
1413 }
1414
1415 /************************************************************************
1416 * VarI4FromR8 (OLEAUT32.61)
1417 *
1418 * Convert a VT_R8 to a VT_I4.
1419 *
1420 * PARAMS
1421 * dblIn [I] Source
1422 * piOut [O] Destination
1423 *
1424 * RETURNS
1425 * Success: S_OK.
1426 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1427 *
1428 * NOTES
1429 * See VarI8FromR8() for details concerning rounding.
1430 */
1431 HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
1432 {
1433 if (dblIn < (double)I4_MIN || dblIn > (double)I4_MAX)
1434 return DISP_E_OVERFLOW;
1435 OLEAUT32_DutchRound(LONG, dblIn, *piOut);
1436 return S_OK;
1437 }
1438
1439 /************************************************************************
1440 * VarI4FromCy (OLEAUT32.62)
1441 *
1442 * Convert a VT_CY to a VT_I4.
1443 *
1444 * PARAMS
1445 * cyIn [I] Source
1446 * piOut [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 VarI4FromCy(CY cyIn, LONG *piOut)
1453 {
1454 double d = cyIn.int64 / CY_MULTIPLIER_F;
1455 return _VarI4FromR8(d, piOut);
1456 }
1457
1458 /************************************************************************
1459 * VarI4FromDate (OLEAUT32.63)
1460 *
1461 * Convert a VT_DATE to a VT_I4.
1462 *
1463 * PARAMS
1464 * dateIn [I] Source
1465 * piOut [O] Destination
1466 *
1467 * RETURNS
1468 * Success: S_OK.
1469 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1470 */
1471 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
1472 {
1473 return _VarI4FromDate(dateIn, piOut);
1474 }
1475
1476 /************************************************************************
1477 * VarI4FromStr (OLEAUT32.64)
1478 *
1479 * Convert a VT_BSTR to a VT_I4.
1480 *
1481 * PARAMS
1482 * strIn [I] Source
1483 * lcid [I] LCID for the conversion
1484 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1485 * piOut [O] Destination
1486 *
1487 * RETURNS
1488 * Success: S_OK.
1489 * Failure: E_INVALIDARG, if any parameter is invalid
1490 * DISP_E_OVERFLOW, if the value will not fit in the destination
1491 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1492 */
1493 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
1494 {
1495 return _VarI4FromStr(strIn, lcid, dwFlags, piOut);
1496 }
1497
1498 /************************************************************************
1499 * VarI4FromDisp (OLEAUT32.65)
1500 *
1501 * Convert a VT_DISPATCH to a VT_I4.
1502 *
1503 * PARAMS
1504 * pdispIn [I] Source
1505 * lcid [I] LCID for conversion
1506 * piOut [O] Destination
1507 *
1508 * RETURNS
1509 * Success: S_OK.
1510 * Failure: E_INVALIDARG, if the source value is invalid
1511 * DISP_E_OVERFLOW, if the value will not fit in the destination
1512 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1513 */
1514 HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
1515 {
1516 return _VarI4FromDisp(pdispIn, lcid, piOut);
1517 }
1518
1519 /************************************************************************
1520 * VarI4FromBool (OLEAUT32.66)
1521 *
1522 * Convert a VT_BOOL to a VT_I4.
1523 *
1524 * PARAMS
1525 * boolIn [I] Source
1526 * piOut [O] Destination
1527 *
1528 * RETURNS
1529 * S_OK.
1530 */
1531 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
1532 {
1533 return _VarI4FromBool(boolIn, piOut);
1534 }
1535
1536 /************************************************************************
1537 * VarI4FromI1 (OLEAUT32.209)
1538 *
1539 * Convert a VT_I4 to a VT_I4.
1540 *
1541 * PARAMS
1542 * cIn [I] Source
1543 * piOut [O] Destination
1544 *
1545 * RETURNS
1546 * S_OK.
1547 */
1548 HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
1549 {
1550 return _VarI4FromI1(cIn, piOut);
1551 }
1552
1553 /************************************************************************
1554 * VarI4FromUI2 (OLEAUT32.210)
1555 *
1556 * Convert a VT_UI2 to a VT_I4.
1557 *
1558 * PARAMS
1559 * usIn [I] Source
1560 * piOut [O] Destination
1561 *
1562 * RETURNS
1563 * S_OK.
1564 */
1565 HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
1566 {
1567 return _VarI4FromUI2(usIn, piOut);
1568 }
1569
1570 /************************************************************************
1571 * VarI4FromUI4 (OLEAUT32.211)
1572 *
1573 * Convert a VT_UI4 to a VT_I4.
1574 *
1575 * PARAMS
1576 * ulIn [I] Source
1577 * piOut [O] Destination
1578 *
1579 * RETURNS
1580 * Success: S_OK.
1581 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1582 */
1583 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
1584 {
1585 return _VarI4FromUI4(ulIn, piOut);
1586 }
1587
1588 /************************************************************************
1589 * VarI4FromDec (OLEAUT32.212)
1590 *
1591 * Convert a VT_DECIMAL to a VT_I4.
1592 *
1593 * PARAMS
1594 * pDecIn [I] Source
1595 * piOut [O] Destination
1596 *
1597 * RETURNS
1598 * Success: S_OK.
1599 * Failure: E_INVALIDARG, if pdecIn is invalid
1600 * DISP_E_OVERFLOW, if the value will not fit in the destination
1601 */
1602 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
1603 HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
1604 {
1605 LONG64 i64;
1606 HRESULT hRet;
1607
1608 hRet = _VarI8FromDec(pdecIn, &i64);
1609
1610 if (SUCCEEDED(hRet))
1611 hRet = _VarI4FromI8(i64, piOut);
1612 return hRet;
1613 }
1614 #endif
1615
1616 /************************************************************************
1617 * VarI4FromI8 (OLEAUT32.348)
1618 *
1619 * Convert a VT_I8 to a VT_I4.
1620 *
1621 * PARAMS
1622 * llIn [I] Source
1623 * piOut [O] Destination
1624 *
1625 * RETURNS
1626 * Success: S_OK.
1627 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1628 */
1629 HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
1630 {
1631 return _VarI4FromI8(llIn, piOut);
1632 }
1633
1634 /************************************************************************
1635 * VarI4FromUI8 (OLEAUT32.349)
1636 *
1637 * Convert a VT_UI8 to a VT_I4.
1638 *
1639 * PARAMS
1640 * ullIn [I] Source
1641 * piOut [O] Destination
1642 *
1643 * RETURNS
1644 * Success: S_OK.
1645 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1646 */
1647 HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
1648 {
1649 return _VarI4FromUI8(ullIn, piOut);
1650 }
1651
1652 /* UI4
1653 */
1654
1655 /************************************************************************
1656 * VarUI4FromUI1 (OLEAUT32.270)
1657 *
1658 * Convert a VT_UI1 to a VT_UI4.
1659 *
1660 * PARAMS
1661 * bIn [I] Source
1662 * pulOut [O] Destination
1663 *
1664 * RETURNS
1665 * S_OK.
1666 */
1667 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
1668 {
1669 return _VarUI4FromUI1(bIn, pulOut);
1670 }
1671
1672 /************************************************************************
1673 * VarUI4FromI2 (OLEAUT32.271)
1674 *
1675 * Convert a VT_I2 to a VT_UI4.
1676 *
1677 * PARAMS
1678 * sIn [I] Source
1679 * pulOut [O] Destination
1680 *
1681 * RETURNS
1682 * Success: S_OK.
1683 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1684 */
1685 HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
1686 {
1687 return _VarUI4FromI2(sIn, pulOut);
1688 }
1689
1690 /************************************************************************
1691 * VarUI4FromI4 (OLEAUT32.272)
1692 *
1693 * Convert a VT_I4 to a VT_UI4.
1694 *
1695 * PARAMS
1696 * iIn [I] Source
1697 * pulOut [O] Destination
1698 *
1699 * RETURNS
1700 * Success: S_OK.
1701 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1702 */
1703 HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
1704 {
1705 return _VarUI4FromI4(iIn, pulOut);
1706 }
1707
1708 /************************************************************************
1709 * VarUI4FromR4 (OLEAUT32.273)
1710 *
1711 * Convert a VT_R4 to a VT_UI4.
1712 *
1713 * PARAMS
1714 * fltIn [I] Source
1715 * pulOut [O] Destination
1716 *
1717 * RETURNS
1718 * Success: S_OK.
1719 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1720 */
1721 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
1722 {
1723 return _VarUI4FromR4(fltIn, pulOut);
1724 }
1725
1726 /************************************************************************
1727 * VarUI4FromR8 (OLEAUT32.274)
1728 *
1729 * Convert a VT_R8 to a VT_UI4.
1730 *
1731 * PARAMS
1732 * dblIn [I] Source
1733 * pulOut [O] Destination
1734 *
1735 * RETURNS
1736 * Success: S_OK.
1737 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1738 *
1739 * NOTES
1740 * See VarI8FromR8() for details concerning rounding.
1741 */
1742 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
1743 {
1744 if (dblIn < -0.5 || dblIn > (double)UI4_MAX)
1745 return DISP_E_OVERFLOW;
1746 OLEAUT32_DutchRound(ULONG, dblIn, *pulOut);
1747 return S_OK;
1748 }
1749
1750 /************************************************************************
1751 * VarUI4FromDate (OLEAUT32.275)
1752 *
1753 * Convert a VT_DATE to a VT_UI4.
1754 *
1755 * PARAMS
1756 * dateIn [I] Source
1757 * pulOut [O] Destination
1758 *
1759 * RETURNS
1760 * Success: S_OK.
1761 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1762 */
1763 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
1764 {
1765 return _VarUI4FromDate(dateIn, pulOut);
1766 }
1767
1768 /************************************************************************
1769 * VarUI4FromCy (OLEAUT32.276)
1770 *
1771 * Convert a VT_CY to a VT_UI4.
1772 *
1773 * PARAMS
1774 * cyIn [I] Source
1775 * pulOut [O] Destination
1776 *
1777 * RETURNS
1778 * Success: S_OK.
1779 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1780 */
1781 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
1782 {
1783 double d = cyIn.int64 / CY_MULTIPLIER_F;
1784 return _VarUI4FromR8(d, pulOut);
1785 }
1786
1787
1788 /************************************************************************
1789 * VarUI4FromStr (OLEAUT32.277)
1790 *
1791 * Convert a VT_BSTR to a VT_UI4.
1792 *
1793 * PARAMS
1794 * strIn [I] Source
1795 * lcid [I] LCID for the conversion
1796 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1797 * pulOut [O] Destination
1798 *
1799 * RETURNS
1800 * Success: S_OK.
1801 * Failure: E_INVALIDARG, if any parameter is invalid
1802 * DISP_E_OVERFLOW, if the value will not fit in the destination
1803 * DISP_E_TYPEMISMATCH, if strIn cannot be converted
1804 */
1805 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
1806 {
1807 return _VarUI4FromStr(strIn, lcid, dwFlags, pulOut);
1808 }
1809
1810 /************************************************************************
1811 * VarUI4FromDisp (OLEAUT32.278)
1812 *
1813 * Convert a VT_DISPATCH to a VT_UI4.
1814 *
1815 * PARAMS
1816 * pdispIn [I] Source
1817 * lcid [I] LCID for conversion
1818 * pulOut [O] Destination
1819 *
1820 * RETURNS
1821 * Success: S_OK.
1822 * Failure: E_INVALIDARG, if the source value is invalid
1823 * DISP_E_OVERFLOW, if the value will not fit in the destination
1824 * DISP_E_TYPEMISMATCH, if the type cannot be converted
1825 */
1826 HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
1827 {
1828 return _VarUI4FromDisp(pdispIn, lcid, pulOut);
1829 }
1830
1831 /************************************************************************
1832 * VarUI4FromBool (OLEAUT32.279)
1833 *
1834 * Convert a VT_BOOL to a VT_UI4.
1835 *
1836 * PARAMS
1837 * boolIn [I] Source
1838 * pulOut [O] Destination
1839 *
1840 * RETURNS
1841 * S_OK.
1842 */
1843 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
1844 {
1845 return _VarUI4FromBool(boolIn, pulOut);
1846 }
1847
1848 /************************************************************************
1849 * VarUI4FromI1 (OLEAUT32.280)
1850 *
1851 * Convert a VT_I1 to a VT_UI4.
1852 *
1853 * PARAMS
1854 * cIn [I] Source
1855 * pulOut [O] Destination
1856 *
1857 * RETURNS
1858 * Success: S_OK.
1859 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1860 */
1861 HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
1862 {
1863 return _VarUI4FromI1(cIn, pulOut);
1864 }
1865
1866 /************************************************************************
1867 * VarUI4FromUI2 (OLEAUT32.281)
1868 *
1869 * Convert a VT_UI2 to a VT_UI4.
1870 *
1871 * PARAMS
1872 * usIn [I] Source
1873 * pulOut [O] Destination
1874 *
1875 * RETURNS
1876 * S_OK.
1877 */
1878 HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
1879 {
1880 return _VarUI4FromUI2(usIn, pulOut);
1881 }
1882
1883 /************************************************************************
1884 * VarUI4FromDec (OLEAUT32.282)
1885 *
1886 * Convert a VT_DECIMAL to a VT_UI4.
1887 *
1888 * PARAMS
1889 * pDecIn [I] Source
1890 * pulOut [O] Destination
1891 *
1892 * RETURNS
1893 * Success: S_OK.
1894 * Failure: E_INVALIDARG, if pdecIn is invalid
1895 * DISP_E_OVERFLOW, if the value will not fit in the destination
1896 */
1897 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
1898 HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
1899 {
1900 LONG64 i64;
1901 HRESULT hRet;
1902
1903 hRet = _VarI8FromDec(pdecIn, &i64);
1904
1905 if (SUCCEEDED(hRet))
1906 hRet = _VarUI4FromI8(i64, pulOut);
1907 return hRet;
1908 }
1909 #endif
1910
1911 /************************************************************************
1912 * VarUI4FromI8 (OLEAUT32.425)
1913 *
1914 * Convert a VT_I8 to a VT_UI4.
1915 *
1916 * PARAMS
1917 * llIn [I] Source
1918 * pulOut [O] Destination
1919 *
1920 * RETURNS
1921 * Success: S_OK.
1922 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1923 */
1924 HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
1925 {
1926 return _VarUI4FromI8(llIn, pulOut);
1927 }
1928
1929 /************************************************************************
1930 * VarUI4FromUI8 (OLEAUT32.426)
1931 *
1932 * Convert a VT_UI8 to a VT_UI4.
1933 *
1934 * PARAMS
1935 * ullIn [I] Source
1936 * pulOut [O] Destination
1937 *
1938 * RETURNS
1939 * Success: S_OK.
1940 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
1941 */
1942 HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
1943 {
1944 return _VarUI4FromUI8(ullIn, pulOut);
1945 }
1946
1947 /* I8
1948 */
1949
1950 /************************************************************************
1951 * VarI8FromUI1 (OLEAUT32.333)
1952 *
1953 * Convert a VT_UI1 to a VT_I8.
1954 *
1955 * PARAMS
1956 * bIn [I] Source
1957 * pi64Out [O] Destination
1958 *
1959 * RETURNS
1960 * S_OK.
1961 */
1962 HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
1963 {
1964 return _VarI8FromUI1(bIn, pi64Out);
1965 }
1966
1967
1968 /************************************************************************
1969 * VarI8FromI2 (OLEAUT32.334)
1970 *
1971 * Convert a VT_I2 to a VT_I8.
1972 *
1973 * PARAMS
1974 * sIn [I] Source
1975 * pi64Out [O] Destination
1976 *
1977 * RETURNS
1978 * S_OK.
1979 */
1980 HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
1981 {
1982 return _VarI8FromI2(sIn, pi64Out);
1983 }
1984
1985 /************************************************************************
1986 * VarI8FromR4 (OLEAUT32.335)
1987 *
1988 * Convert a VT_R4 to a VT_I8.
1989 *
1990 * PARAMS
1991 * fltIn [I] Source
1992 * pi64Out [O] Destination
1993 *
1994 * RETURNS
1995 * Success: S_OK.
1996 * Failure: E_INVALIDARG, if the source value is invalid
1997 * DISP_E_OVERFLOW, if the value will not fit in the destination
1998 */
1999 HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
2000 {
2001 return _VarI8FromR4(fltIn, pi64Out);
2002 }
2003
2004 /************************************************************************
2005 * VarI8FromR8 (OLEAUT32.336)
2006 *
2007 * Convert a VT_R8 to a VT_I8.
2008 *
2009 * PARAMS
2010 * dblIn [I] Source
2011 * pi64Out [O] Destination
2012 *
2013 * RETURNS
2014 * Success: S_OK.
2015 * Failure: E_INVALIDARG, if the source value is invalid
2016 * DISP_E_OVERFLOW, if the value will not fit in the destination
2017 *
2018 * NOTES
2019 * Only values that fit into 63 bits are accepted. Due to rounding issues,
2020 * very high or low values will not be accurately converted.
2021 *
2022 * Numbers are rounded using Dutch rounding, as follows:
2023 *
2024 *| Fractional Part Sign Direction Example
2025 *| --------------- ---- --------- -------
2026 *| < 0.5 + Down 0.4 -> 0.0
2027 *| < 0.5 - Up -0.4 -> 0.0
2028 *| > 0.5 + Up 0.6 -> 1.0
2029 *| < 0.5 - Up -0.6 -> -1.0
2030 *| = 0.5 + Up/Down Down if even, Up if odd
2031 *| = 0.5 - Up/Down Up if even, Down if odd
2032 *
2033 * This system is often used in supermarkets.
2034 */
2035 HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
2036 {
2037 if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
2038 return DISP_E_OVERFLOW;
2039 OLEAUT32_DutchRound(LONG64, dblIn, *pi64Out);
2040 return S_OK;
2041 }
2042
2043
2044 /************************************************************************
2045 * VarI8FromCy (OLEAUT32.337)
2046 *
2047 * Convert a VT_CY to a VT_I8.
2048 *
2049 * PARAMS
2050 * cyIn [I] Source
2051 * pi64Out [O] Destination
2052 *
2053 * RETURNS
2054 * S_OK.
2055 *
2056 * NOTES
2057 * All negative numbers are rounded down by 1, including those that are
2058 * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
2059 * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
2060 * for details.
2061 */
2062 HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
2063 {
2064 *pi64Out = cyIn.int64 / CY_MULTIPLIER;
2065
2066 if (cyIn.int64 < 0)
2067 (*pi64Out)--; /* Mimic Win32 bug */
2068 else
2069 {
2070 cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2071
2072 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
2073 (*pi64Out)++;
2074 }
2075 return S_OK;
2076 }
2077
2078 /************************************************************************
2079 * VarI8FromDate (OLEAUT32.338)
2080 *
2081 * Convert a VT_DATE to a VT_I8.
2082 *
2083 * PARAMS
2084 * dateIn [I] Source
2085 * pi64Out [O] Destination
2086 *
2087 * RETURNS
2088 * Success: S_OK.
2089 * Failure: E_INVALIDARG, if the source value is invalid
2090 * DISP_E_OVERFLOW, if the value will not fit in the destination
2091 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2092 */
2093 HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
2094 {
2095 return _VarI8FromDate(dateIn, pi64Out);
2096 }
2097
2098 /************************************************************************
2099 * VarI8FromStr (OLEAUT32.339)
2100 *
2101 * Convert a VT_BSTR to a VT_I8.
2102 *
2103 * PARAMS
2104 * strIn [I] Source
2105 * lcid [I] LCID for the conversion
2106 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2107 * pi64Out [O] Destination
2108 *
2109 * RETURNS
2110 * Success: S_OK.
2111 * Failure: E_INVALIDARG, if the source value is invalid
2112 * DISP_E_OVERFLOW, if the value will not fit in the destination
2113 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2114 */
2115 HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
2116 {
2117 return _VarI8FromStr(strIn, lcid, dwFlags, pi64Out);
2118 }
2119
2120 /************************************************************************
2121 * VarI8FromDisp (OLEAUT32.340)
2122 *
2123 * Convert a VT_DISPATCH to a VT_I8.
2124 *
2125 * PARAMS
2126 * pdispIn [I] Source
2127 * lcid [I] LCID for conversion
2128 * pi64Out [O] Destination
2129 *
2130 * RETURNS
2131 * Success: S_OK.
2132 * Failure: E_INVALIDARG, if the source value is invalid
2133 * DISP_E_OVERFLOW, if the value will not fit in the destination
2134 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2135 */
2136 HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
2137 {
2138 return _VarI8FromDisp(pdispIn, lcid, pi64Out);
2139 }
2140
2141 /************************************************************************
2142 * VarI8FromBool (OLEAUT32.341)
2143 *
2144 * Convert a VT_BOOL to a VT_I8.
2145 *
2146 * PARAMS
2147 * boolIn [I] Source
2148 * pi64Out [O] Destination
2149 *
2150 * RETURNS
2151 * S_OK.
2152 */
2153 HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
2154 {
2155 return _VarI8FromBool(boolIn, pi64Out);
2156 }
2157
2158 /************************************************************************
2159 * VarI8FromI1 (OLEAUT32.342)
2160 *
2161 * Convert a VT_I1 to a VT_I8.
2162 *
2163 * PARAMS
2164 * cIn [I] Source
2165 * pi64Out [O] Destination
2166 *
2167 * RETURNS
2168 * S_OK.
2169 */
2170 HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
2171 {
2172 return _VarI8FromI1(cIn, pi64Out);
2173 }
2174
2175 /************************************************************************
2176 * VarI8FromUI2 (OLEAUT32.343)
2177 *
2178 * Convert a VT_UI2 to a VT_I8.
2179 *
2180 * PARAMS
2181 * usIn [I] Source
2182 * pi64Out [O] Destination
2183 *
2184 * RETURNS
2185 * S_OK.
2186 */
2187 HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
2188 {
2189 return _VarI8FromUI2(usIn, pi64Out);
2190 }
2191
2192 /************************************************************************
2193 * VarI8FromUI4 (OLEAUT32.344)
2194 *
2195 * Convert a VT_UI4 to a VT_I8.
2196 *
2197 * PARAMS
2198 * ulIn [I] Source
2199 * pi64Out [O] Destination
2200 *
2201 * RETURNS
2202 * S_OK.
2203 */
2204 HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
2205 {
2206 return _VarI8FromUI4(ulIn, pi64Out);
2207 }
2208
2209 /************************************************************************
2210 * VarI8FromDec (OLEAUT32.345)
2211 *
2212 * Convert a VT_DECIMAL to a VT_I8.
2213 *
2214 * PARAMS
2215 * pDecIn [I] Source
2216 * pi64Out [O] Destination
2217 *
2218 * RETURNS
2219 * Success: S_OK.
2220 * Failure: E_INVALIDARG, if the source value is invalid
2221 * DISP_E_OVERFLOW, if the value will not fit in the destination
2222 */
2223 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
2224 HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
2225 {
2226 if (!DEC_SCALE(pdecIn))
2227 {
2228 /* This decimal is just a 96 bit integer */
2229 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2230 return E_INVALIDARG;
2231
2232 if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
2233 return DISP_E_OVERFLOW;
2234
2235 if (DEC_SIGN(pdecIn))
2236 *pi64Out = -DEC_LO64(pdecIn);
2237 else
2238 *pi64Out = DEC_LO64(pdecIn);
2239 return S_OK;
2240 }
2241 else
2242 {
2243 /* Decimal contains a floating point number */
2244 HRESULT hRet;
2245 double dbl;
2246
2247 hRet = _VarR8FromDec(pdecIn, &dbl);
2248 if (SUCCEEDED(hRet))
2249 hRet = VarI8FromR8(dbl, pi64Out);
2250 return hRet;
2251 }
2252 }
2253 #endif
2254
2255 /************************************************************************
2256 * VarI8FromUI8 (OLEAUT32.427)
2257 *
2258 * Convert a VT_UI8 to a VT_I8.
2259 *
2260 * PARAMS
2261 * ullIn [I] Source
2262 * pi64Out [O] Destination
2263 *
2264 * RETURNS
2265 * Success: S_OK.
2266 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2267 */
2268 HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
2269 {
2270 return _VarI8FromUI8(ullIn, pi64Out);
2271 }
2272
2273 /* UI8
2274 */
2275
2276 /************************************************************************
2277 * VarUI8FromI8 (OLEAUT32.428)
2278 *
2279 * Convert a VT_I8 to a VT_UI8.
2280 *
2281 * PARAMS
2282 * ulIn [I] Source
2283 * pui64Out [O] Destination
2284 *
2285 * RETURNS
2286 * Success: S_OK.
2287 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2288 */
2289 HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
2290 {
2291 return _VarUI8FromI8(llIn, pui64Out);
2292 }
2293
2294 /************************************************************************
2295 * VarUI8FromUI1 (OLEAUT32.429)
2296 *
2297 * Convert a VT_UI1 to a VT_UI8.
2298 *
2299 * PARAMS
2300 * bIn [I] Source
2301 * pui64Out [O] Destination
2302 *
2303 * RETURNS
2304 * S_OK.
2305 */
2306 HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
2307 {
2308 return _VarUI8FromUI1(bIn, pui64Out);
2309 }
2310
2311 /************************************************************************
2312 * VarUI8FromI2 (OLEAUT32.430)
2313 *
2314 * Convert a VT_I2 to a VT_UI8.
2315 *
2316 * PARAMS
2317 * sIn [I] Source
2318 * pui64Out [O] Destination
2319 *
2320 * RETURNS
2321 * S_OK.
2322 */
2323 HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
2324 {
2325 return _VarUI8FromI2(sIn, pui64Out);
2326 }
2327
2328 /************************************************************************
2329 * VarUI8FromR4 (OLEAUT32.431)
2330 *
2331 * Convert a VT_R4 to a VT_UI8.
2332 *
2333 * PARAMS
2334 * fltIn [I] Source
2335 * pui64Out [O] Destination
2336 *
2337 * RETURNS
2338 * Success: S_OK.
2339 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2340 */
2341 HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
2342 {
2343 return _VarUI8FromR4(fltIn, pui64Out);
2344 }
2345
2346 /************************************************************************
2347 * VarUI8FromR8 (OLEAUT32.432)
2348 *
2349 * Convert a VT_R8 to a VT_UI8.
2350 *
2351 * PARAMS
2352 * dblIn [I] Source
2353 * pui64Out [O] Destination
2354 *
2355 * RETURNS
2356 * Success: S_OK.
2357 * Failure: E_INVALIDARG, if the source value is invalid
2358 * DISP_E_OVERFLOW, if the value will not fit in the destination
2359 *
2360 * NOTES
2361 * See VarI8FromR8() for details concerning rounding.
2362 */
2363 HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
2364 {
2365 if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
2366 return DISP_E_OVERFLOW;
2367 OLEAUT32_DutchRound(ULONG64, dblIn, *pui64Out);
2368 return S_OK;
2369 }
2370
2371 /************************************************************************
2372 * VarUI8FromCy (OLEAUT32.433)
2373 *
2374 * Convert a VT_CY to a VT_UI8.
2375 *
2376 * PARAMS
2377 * cyIn [I] Source
2378 * pui64Out [O] Destination
2379 *
2380 * RETURNS
2381 * Success: S_OK.
2382 * Failure: E_INVALIDARG, if the source value is invalid
2383 * DISP_E_OVERFLOW, if the value will not fit in the destination
2384 *
2385 * NOTES
2386 * Negative values >= -5000 will be converted to 0.
2387 */
2388 HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
2389 {
2390 if (cyIn.int64 < 0)
2391 {
2392 if (cyIn.int64 < -CY_HALF)
2393 return DISP_E_OVERFLOW;
2394 *pui64Out = 0;
2395 }
2396 else
2397 {
2398 *pui64Out = cyIn.int64 / CY_MULTIPLIER;
2399
2400 cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
2401
2402 if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
2403 (*pui64Out)++;
2404 }
2405 return S_OK;
2406 }
2407
2408 /************************************************************************
2409 * VarUI8FromDate (OLEAUT32.434)
2410 *
2411 * Convert a VT_DATE to a VT_UI8.
2412 *
2413 * PARAMS
2414 * dateIn [I] Source
2415 * pui64Out [O] Destination
2416 *
2417 * RETURNS
2418 * Success: S_OK.
2419 * Failure: E_INVALIDARG, if the source value is invalid
2420 * DISP_E_OVERFLOW, if the value will not fit in the destination
2421 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2422 */
2423 HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
2424 {
2425 return _VarUI8FromDate(dateIn, pui64Out);
2426 }
2427
2428 /************************************************************************
2429 * VarUI8FromStr (OLEAUT32.435)
2430 *
2431 * Convert a VT_BSTR to a VT_UI8.
2432 *
2433 * PARAMS
2434 * strIn [I] Source
2435 * lcid [I] LCID for the conversion
2436 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2437 * pui64Out [O] Destination
2438 *
2439 * RETURNS
2440 * Success: S_OK.
2441 * Failure: E_INVALIDARG, if the source value is invalid
2442 * DISP_E_OVERFLOW, if the value will not fit in the destination
2443 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2444 */
2445 HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
2446 {
2447 return _VarUI8FromStr(strIn, lcid, dwFlags, pui64Out);
2448 }
2449
2450 /************************************************************************
2451 * VarUI8FromDisp (OLEAUT32.436)
2452 *
2453 * Convert a VT_DISPATCH to a VT_UI8.
2454 *
2455 * PARAMS
2456 * pdispIn [I] Source
2457 * lcid [I] LCID for conversion
2458 * pui64Out [O] Destination
2459 *
2460 * RETURNS
2461 * Success: S_OK.
2462 * Failure: E_INVALIDARG, if the source value is invalid
2463 * DISP_E_OVERFLOW, if the value will not fit in the destination
2464 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2465 */
2466 HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
2467 {
2468 return _VarUI8FromDisp(pdispIn, lcid, pui64Out);
2469 }
2470
2471 /************************************************************************
2472 * VarUI8FromBool (OLEAUT32.437)
2473 *
2474 * Convert a VT_BOOL to a VT_UI8.
2475 *
2476 * PARAMS
2477 * boolIn [I] Source
2478 * pui64Out [O] Destination
2479 *
2480 * RETURNS
2481 * Success: S_OK.
2482 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2483 */
2484 HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
2485 {
2486 return _VarUI8FromBool(boolIn, pui64Out);
2487 }
2488 /************************************************************************
2489 * VarUI8FromI1 (OLEAUT32.438)
2490 *
2491 * Convert a VT_I1 to a VT_UI8.
2492 *
2493 * PARAMS
2494 * cIn [I] Source
2495 * pui64Out [O] Destination
2496 *
2497 * RETURNS
2498 * Success: S_OK.
2499 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
2500 */
2501 HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
2502 {
2503 return _VarUI8FromI1(cIn, pui64Out);
2504 }
2505
2506 /************************************************************************
2507 * VarUI8FromUI2 (OLEAUT32.439)
2508 *
2509 * Convert a VT_UI2 to a VT_UI8.
2510 *
2511 * PARAMS
2512 * usIn [I] Source
2513 * pui64Out [O] Destination
2514 *
2515 * RETURNS
2516 * S_OK.
2517 */
2518 HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
2519 {
2520 return _VarUI8FromUI2(usIn, pui64Out);
2521 }
2522
2523 /************************************************************************
2524 * VarUI8FromUI4 (OLEAUT32.440)
2525 *
2526 * Convert a VT_UI4 to a VT_UI8.
2527 *
2528 * PARAMS
2529 * ulIn [I] Source
2530 * pui64Out [O] Destination
2531 *
2532 * RETURNS
2533 * S_OK.
2534 */
2535 HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
2536 {
2537 return _VarUI8FromUI4(ulIn, pui64Out);
2538 }
2539
2540 /************************************************************************
2541 * VarUI8FromDec (OLEAUT32.441)
2542 *
2543 * Convert a VT_DECIMAL to a VT_UI8.
2544 *
2545 * PARAMS
2546 * pDecIn [I] Source
2547 * pui64Out [O] Destination
2548 *
2549 * RETURNS
2550 * Success: S_OK.
2551 * Failure: E_INVALIDARG, if the source value is invalid
2552 * DISP_E_OVERFLOW, if the value will not fit in the destination
2553 *
2554 * NOTES
2555 * Under native Win32, if the source value has a scale of 0, its sign is
2556 * ignored, i.e. this function takes the absolute value rather than fail
2557 * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
2558 * (use VarAbs() on pDecIn first if you really want this behaviour).
2559 */
2560 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
2561 HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
2562 {
2563 if (!DEC_SCALE(pdecIn))
2564 {
2565 /* This decimal is just a 96 bit integer */
2566 if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
2567 return E_INVALIDARG;
2568
2569 if (DEC_HI32(pdecIn))
2570 return DISP_E_OVERFLOW;
2571
2572 if (DEC_SIGN(pdecIn))
2573 {
2574 WARN("Sign would be ignored under Win32!\n");
2575 return DISP_E_OVERFLOW;
2576 }
2577
2578 *pui64Out = DEC_LO64(pdecIn);
2579 return S_OK;
2580 }
2581 else
2582 {
2583 /* Decimal contains a floating point number */
2584 HRESULT hRet;
2585 double dbl;
2586
2587 hRet = _VarR8FromDec(pdecIn, &dbl);
2588 if (SUCCEEDED(hRet))
2589 hRet = VarUI8FromR8(dbl, pui64Out);
2590 return hRet;
2591 }
2592 }
2593 #endif
2594
2595 /* R4
2596 */
2597
2598 /************************************************************************
2599 * VarR4FromUI1 (OLEAUT32.68)
2600 *
2601 * Convert a VT_UI1 to a VT_R4.
2602 *
2603 * PARAMS
2604 * bIn [I] Source
2605 * pFltOut [O] Destination
2606 *
2607 * RETURNS
2608 * S_OK.
2609 */
2610 HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
2611 {
2612 return _VarR4FromUI1(bIn, pFltOut);
2613 }
2614
2615 /************************************************************************
2616 * VarR4FromI2 (OLEAUT32.69)
2617 *
2618 * Convert a VT_I2 to a VT_R4.
2619 *
2620 * PARAMS
2621 * sIn [I] Source
2622 * pFltOut [O] Destination
2623 *
2624 * RETURNS
2625 * S_OK.
2626 */
2627 HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
2628 {
2629 return _VarR4FromI2(sIn, pFltOut);
2630 }
2631
2632 /************************************************************************
2633 * VarR4FromI4 (OLEAUT32.70)
2634 *
2635 * Convert a VT_I4 to a VT_R4.
2636 *
2637 * PARAMS
2638 * sIn [I] Source
2639 * pFltOut [O] Destination
2640 *
2641 * RETURNS
2642 * S_OK.
2643 */
2644 HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
2645 {
2646 return _VarR4FromI4(lIn, pFltOut);
2647 }
2648
2649 /************************************************************************
2650 * VarR4FromR8 (OLEAUT32.71)
2651 *
2652 * Convert a VT_R8 to a VT_R4.
2653 *
2654 * PARAMS
2655 * dblIn [I] Source
2656 * pFltOut [O] Destination
2657 *
2658 * RETURNS
2659 * Success: S_OK.
2660 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2661 */
2662 HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
2663 {
2664 return _VarR4FromR8(dblIn, pFltOut);
2665 }
2666
2667 /************************************************************************
2668 * VarR4FromCy (OLEAUT32.72)
2669 *
2670 * Convert a VT_CY to a VT_R4.
2671 *
2672 * PARAMS
2673 * cyIn [I] Source
2674 * pFltOut [O] Destination
2675 *
2676 * RETURNS
2677 * S_OK.
2678 */
2679 HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
2680 {
2681 return _VarR4FromCy(cyIn, pFltOut);
2682 }
2683
2684 /************************************************************************
2685 * VarR4FromDate (OLEAUT32.73)
2686 *
2687 * Convert a VT_DATE to a VT_R4.
2688 *
2689 * PARAMS
2690 * dateIn [I] Source
2691 * pFltOut [O] Destination
2692 *
2693 * RETURNS
2694 * Success: S_OK.
2695 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
2696 */
2697 HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
2698 {
2699 return _VarR4FromDate(dateIn, pFltOut);
2700 }
2701
2702 /************************************************************************
2703 * VarR4FromStr (OLEAUT32.74)
2704 *
2705 * Convert a VT_BSTR to a VT_R4.
2706 *
2707 * PARAMS
2708 * strIn [I] Source
2709 * lcid [I] LCID for the conversion
2710 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
2711 * pFltOut [O] Destination
2712 *
2713 * RETURNS
2714 * Success: S_OK.
2715 * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
2716 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2717 */
2718 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
2719 {
2720 return _VarR4FromStr(strIn, lcid, dwFlags, pFltOut);
2721 }
2722
2723 /************************************************************************
2724 * VarR4FromDisp (OLEAUT32.75)
2725 *
2726 * Convert a VT_DISPATCH to a VT_R4.
2727 *
2728 * PARAMS
2729 * pdispIn [I] Source
2730 * lcid [I] LCID for conversion
2731 * pFltOut [O] Destination
2732 *
2733 * RETURNS
2734 * Success: S_OK.
2735 * Failure: E_INVALIDARG, if the source value is invalid
2736 * DISP_E_OVERFLOW, if the value will not fit in the destination
2737 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2738 */
2739 HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
2740 {
2741 return _VarR4FromDisp(pdispIn, lcid, pFltOut);
2742 }
2743
2744 /************************************************************************
2745 * VarR4FromBool (OLEAUT32.76)
2746 *
2747 * Convert a VT_BOOL to a VT_R4.
2748 *
2749 * PARAMS
2750 * boolIn [I] Source
2751 * pFltOut [O] Destination
2752 *
2753 * RETURNS
2754 * S_OK.
2755 */
2756 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
2757 {
2758 return _VarR4FromBool(boolIn, pFltOut);
2759 }
2760
2761 /************************************************************************
2762 * VarR4FromI1 (OLEAUT32.213)
2763 *
2764 * Convert a VT_I1 to a VT_R4.
2765 *
2766 * PARAMS
2767 * cIn [I] Source
2768 * pFltOut [O] Destination
2769 *
2770 * RETURNS
2771 * Success: S_OK.
2772 * Failure: E_INVALIDARG, if the source value is invalid
2773 * DISP_E_OVERFLOW, if the value will not fit in the destination
2774 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2775 */
2776 HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
2777 {
2778 return _VarR4FromI1(cIn, pFltOut);
2779 }
2780
2781 /************************************************************************
2782 * VarR4FromUI2 (OLEAUT32.214)
2783 *
2784 * Convert a VT_UI2 to a VT_R4.
2785 *
2786 * PARAMS
2787 * usIn [I] Source
2788 * pFltOut [O] Destination
2789 *
2790 * RETURNS
2791 * Success: S_OK.
2792 * Failure: E_INVALIDARG, if the source value is invalid
2793 * DISP_E_OVERFLOW, if the value will not fit in the destination
2794 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2795 */
2796 HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
2797 {
2798 return _VarR4FromUI2(usIn, pFltOut);
2799 }
2800
2801 /************************************************************************
2802 * VarR4FromUI4 (OLEAUT32.215)
2803 *
2804 * Convert a VT_UI4 to a VT_R4.
2805 *
2806 * PARAMS
2807 * ulIn [I] Source
2808 * pFltOut [O] Destination
2809 *
2810 * RETURNS
2811 * Success: S_OK.
2812 * Failure: E_INVALIDARG, if the source value is invalid
2813 * DISP_E_OVERFLOW, if the value will not fit in the destination
2814 * DISP_E_TYPEMISMATCH, if the type cannot be converted
2815 */
2816 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
2817 {
2818 return _VarR4FromUI4(ulIn, pFltOut);
2819 }
2820
2821 /************************************************************************
2822 * VarR4FromDec (OLEAUT32.216)
2823 *
2824 * Convert a VT_DECIMAL to a VT_R4.
2825 *
2826 * PARAMS
2827 * pDecIn [I] Source
2828 * pFltOut [O] Destination
2829 *
2830 * RETURNS
2831 * Success: S_OK.
2832 * Failure: E_INVALIDARG, if the source value is invalid.
2833 */
2834 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
2835 HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
2836 {
2837 BYTE scale = DEC_SCALE(pDecIn);
2838 int divisor = 1;
2839 double highPart;
2840
2841 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
2842 return E_INVALIDARG;
2843
2844 while (scale--)
2845 divisor *= 10;
2846
2847 if (DEC_SIGN(pDecIn))
2848 divisor = -divisor;
2849
2850 if (DEC_HI32(pDecIn))
2851 {
2852 highPart = (double)DEC_HI32(pDecIn) / (double)divisor;
2853 highPart *= 1.0e64;
2854 }
2855 else
2856 highPart = 0.0;
2857
2858 *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
2859 return S_OK;
2860 }
2861 #endif
2862
2863
2864 /************************************************************************
2865 * VarR4FromI8 (OLEAUT32.360)
2866 *
2867 * Convert a VT_I8 to a VT_R4.
2868 *
2869 * PARAMS
2870 * ullIn [I] Source
2871 * pFltOut [O] Destination
2872 *
2873 * RETURNS
2874 * S_OK.
2875 */
2876 HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
2877 {
2878 return _VarR4FromI8(llIn, pFltOut);
2879 }
2880
2881 /************************************************************************
2882 * VarR4FromUI8 (OLEAUT32.361)
2883 *
2884 * Convert a VT_UI8 to a VT_R4.
2885 *
2886 * PARAMS
2887 * ullIn [I] Source
2888 * pFltOut [O] Destination
2889 *
2890 * RETURNS
2891 * S_OK.
2892 */
2893 HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
2894 {
2895 return _VarR4FromUI8(ullIn, pFltOut);
2896 }
2897
2898 /************************************************************************
2899 * VarR4CmpR8 (OLEAUT32.316)
2900 *
2901 * Compare a VT_R4 to a VT_R8.
2902 *
2903 * PARAMS
2904 * fltLeft [I] Source
2905 * dblRight [I] Value to compare
2906 *
2907 * RETURNS
2908 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
2909 * equal to or greater than dblRight respectively.
2910 */
2911 HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
2912 {
2913 if (fltLeft < dblRight)
2914 return VARCMP_LT;
2915 else if (fltLeft > dblRight)
2916 return VARCMP_GT;
2917 return VARCMP_EQ;
2918 }
2919
2920 /* R8
2921 */
2922
2923 /************************************************************************
2924 * VarR8FromUI1 (OLEAUT32.78)
2925 *
2926 * Convert a VT_UI1 to a VT_R8.
2927 *
2928 * PARAMS
2929 * bIn [I] Source
2930 * pDblOut [O] Destination
2931 *
2932 * RETURNS
2933 * S_OK.
2934 */
2935 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
2936 {
2937 return _VarR8FromUI1(bIn, pDblOut);
2938 }
2939
2940 /************************************************************************
2941 * VarR8FromI2 (OLEAUT32.79)
2942 *
2943 * Convert a VT_I2 to a VT_R8.
2944 *
2945 * PARAMS
2946 * sIn [I] Source
2947 * pDblOut [O] Destination
2948 *
2949 * RETURNS
2950 * S_OK.
2951 */
2952 HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
2953 {
2954 return _VarR8FromI2(sIn, pDblOut);
2955 }
2956
2957 /************************************************************************
2958 * VarR8FromI4 (OLEAUT32.80)
2959 *
2960 * Convert a VT_I4 to a VT_R8.
2961 *
2962 * PARAMS
2963 * sIn [I] Source
2964 * pDblOut [O] Destination
2965 *
2966 * RETURNS
2967 * S_OK.
2968 */
2969 HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
2970 {
2971 return _VarR8FromI4(lIn, pDblOut);
2972 }
2973
2974 /************************************************************************
2975 * VarR8FromR4 (OLEAUT32.81)
2976 *
2977 * Convert a VT_R4 to a VT_R8.
2978 *
2979 * PARAMS
2980 * fltIn [I] Source
2981 * pDblOut [O] Destination
2982 *
2983 * RETURNS
2984 * S_OK.
2985 */
2986 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
2987 {
2988 return _VarR8FromR4(fltIn, pDblOut);
2989 }
2990
2991 /************************************************************************
2992 * VarR8FromCy (OLEAUT32.82)
2993 *
2994 * Convert a VT_CY to a VT_R8.
2995 *
2996 * PARAMS
2997 * cyIn [I] Source
2998 * pDblOut [O] Destination
2999 *
3000 * RETURNS
3001 * S_OK.
3002 */
3003 HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
3004 {
3005 return _VarR8FromCy(cyIn, pDblOut);
3006 }
3007
3008 /************************************************************************
3009 * VarR8FromDate (OLEAUT32.83)
3010 *
3011 * Convert a VT_DATE to a VT_R8.
3012 *
3013 * PARAMS
3014 * dateIn [I] Source
3015 * pDblOut [O] Destination
3016 *
3017 * RETURNS
3018 * S_OK.
3019 */
3020 HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
3021 {
3022 return _VarR8FromDate(dateIn, pDblOut);
3023 }
3024
3025 /************************************************************************
3026 * VarR8FromStr (OLEAUT32.84)
3027 *
3028 * Convert a VT_BSTR to a VT_R8.
3029 *
3030 * PARAMS
3031 * strIn [I] Source
3032 * lcid [I] LCID for the conversion
3033 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3034 * pDblOut [O] Destination
3035 *
3036 * RETURNS
3037 * Success: S_OK.
3038 * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
3039 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3040 */
3041 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
3042 {
3043 return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
3044 }
3045
3046 /************************************************************************
3047 * VarR8FromDisp (OLEAUT32.85)
3048 *
3049 * Convert a VT_DISPATCH to a VT_R8.
3050 *
3051 * PARAMS
3052 * pdispIn [I] Source
3053 * lcid [I] LCID for conversion
3054 * pDblOut [O] Destination
3055 *
3056 * RETURNS
3057 * Success: S_OK.
3058 * Failure: E_INVALIDARG, if the source value is invalid
3059 * DISP_E_OVERFLOW, if the value will not fit in the destination
3060 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3061 */
3062 HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
3063 {
3064 return _VarR8FromDisp(pdispIn, lcid, pDblOut);
3065 }
3066
3067 /************************************************************************
3068 * VarR8FromBool (OLEAUT32.86)
3069 *
3070 * Convert a VT_BOOL to a VT_R8.
3071 *
3072 * PARAMS
3073 * boolIn [I] Source
3074 * pDblOut [O] Destination
3075 *
3076 * RETURNS
3077 * S_OK.
3078 */
3079 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
3080 {
3081 return _VarR8FromBool(boolIn, pDblOut);
3082 }
3083
3084 /************************************************************************
3085 * VarR8FromI1 (OLEAUT32.217)
3086 *
3087 * Convert a VT_I1 to a VT_R8.
3088 *
3089 * PARAMS
3090 * cIn [I] Source
3091 * pDblOut [O] Destination
3092 *
3093 * RETURNS
3094 * Success: S_OK.
3095 * Failure: E_INVALIDARG, if the source value is invalid
3096 * DISP_E_OVERFLOW, if the value will not fit in the destination
3097 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3098 */
3099 HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
3100 {
3101 return _VarR8FromI1(cIn, pDblOut);
3102 }
3103
3104 /************************************************************************
3105 * VarR8FromUI2 (OLEAUT32.218)
3106 *
3107 * Convert a VT_UI2 to a VT_R8.
3108 *
3109 * PARAMS
3110 * usIn [I] Source
3111 * pDblOut [O] Destination
3112 *
3113 * RETURNS
3114 * Success: S_OK.
3115 * Failure: E_INVALIDARG, if the source value is invalid
3116 * DISP_E_OVERFLOW, if the value will not fit in the destination
3117 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3118 */
3119 HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
3120 {
3121 return _VarR8FromUI2(usIn, pDblOut);
3122 }
3123
3124 /************************************************************************
3125 * VarR8FromUI4 (OLEAUT32.219)
3126 *
3127 * Convert a VT_UI4 to a VT_R8.
3128 *
3129 * PARAMS
3130 * ulIn [I] Source
3131 * pDblOut [O] Destination
3132 *
3133 * RETURNS
3134 * Success: S_OK.
3135 * Failure: E_INVALIDARG, if the source value is invalid
3136 * DISP_E_OVERFLOW, if the value will not fit in the destination
3137 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3138 */
3139 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
3140 {
3141 return _VarR8FromUI4(ulIn, pDblOut);
3142 }
3143
3144 /************************************************************************
3145 * VarR8FromDec (OLEAUT32.220)
3146 *
3147 * Convert a VT_DECIMAL to a VT_R8.
3148 *
3149 * PARAMS
3150 * pDecIn [I] Source
3151 * pDblOut [O] Destination
3152 *
3153 * RETURNS
3154 * Success: S_OK.
3155 * Failure: E_INVALIDARG, if the source value is invalid.
3156 */
3157 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
3158 HRESULT WINAPI VarR8FromDec(DECIMAL* pDecIn, double *pDblOut)
3159 {
3160 BYTE scale = DEC_SCALE(pDecIn);
3161 double divisor = 1.0, highPart;
3162
3163 if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
3164 return E_INVALIDARG;
3165
3166 while (scale--)
3167 divisor *= 10;
3168
3169 if (DEC_SIGN(pDecIn))
3170 divisor = -divisor;
3171
3172 if (DEC_HI32(pDecIn))
3173 {
3174 highPart = (double)DEC_HI32(pDecIn) / divisor;
3175 highPart *= 1.0e64;
3176 }
3177 else
3178 highPart = 0.0;
3179
3180 *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
3181 return S_OK;
3182 }
3183 #endif
3184
3185 /************************************************************************
3186 * VarR8FromI8 (OLEAUT32.362)
3187 *
3188 * Convert a VT_I8 to a VT_R8.
3189 *
3190 * PARAMS
3191 * ullIn [I] Source
3192 * pDblOut [O] Destination
3193 *
3194 * RETURNS
3195 * S_OK.
3196 */
3197 HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
3198 {
3199 return _VarR8FromI8(llIn, pDblOut);
3200 }
3201
3202 /************************************************************************
3203 * VarR8FromUI8 (OLEAUT32.363)
3204 *
3205 * Convert a VT_UI8 to a VT_R8.
3206 *
3207 * PARAMS
3208 * ullIn [I] Source
3209 * pDblOut [O] Destination
3210 *
3211 * RETURNS
3212 * S_OK.
3213 */
3214 HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
3215 {
3216 return _VarR8FromUI8(ullIn, pDblOut);
3217 }
3218
3219 /************************************************************************
3220 * VarR8Pow (OLEAUT32.315)
3221 *
3222 * Raise a VT_R8 to a power.
3223 *
3224 * PARAMS
3225 * dblLeft [I] Source
3226 * dblPow [I] Power to raise dblLeft by
3227 * pDblOut [O] Destination
3228 *
3229 * RETURNS
3230 * S_OK. pDblOut contains dblLeft to the power of dblRight.
3231 */
3232 HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
3233 {
3234 *pDblOut = pow(dblLeft, dblPow);
3235 return S_OK;
3236 }
3237
3238 /************************************************************************
3239 * VarR8Round (OLEAUT32.317)
3240 *
3241 * Round a VT_R8 to a given number of decimal points.
3242 *
3243 * PARAMS
3244 * dblIn [I] Source
3245 * nDig [I] Number of decimal points to round to
3246 * pDblOut [O] Destination for rounded number
3247 *
3248 * RETURNS
3249 * Success: S_OK. pDblOut is rounded to nDig digits.
3250 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3251 *
3252 * NOTES
3253 * The native version of this function rounds using the internal
3254 * binary representation of the number. Wine uses the dutch rounding
3255 * convention, so therefore small differences can occur in the value returned.
3256 * MSDN says that you should use your own rounding function if you want
3257 * rounding to be predictable in your application.
3258 */
3259 HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
3260 {
3261 double scale, whole, fract;
3262
3263 if (nDig < 0)
3264 return E_INVALIDARG;
3265
3266 scale = pow(10.0, nDig);
3267
3268 dblIn *= scale;
3269 whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
3270 fract = dblIn - whole;
3271
3272 if (fract > 0.5)
3273 dblIn = whole + 1.0;
3274 else if (fract == 0.5)
3275 dblIn = whole + fmod(whole, 2.0);
3276 else if (fract >= 0.0)
3277 dblIn = whole;
3278 else if (fract == -0.5)
3279 dblIn = whole - fmod(whole, 2.0);
3280 else if (fract > -0.5)
3281 dblIn = whole;
3282 else
3283 dblIn = whole - 1.0;
3284
3285 *pDblOut = dblIn / scale;
3286 return S_OK;
3287 }
3288
3289 /* CY
3290 */
3291
3292 /* Powers of 10 from 0..4 D.P. */
3293 static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
3294 CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
3295
3296 /************************************************************************
3297 * VarCyFromUI1 (OLEAUT32.98)
3298 *
3299 * Convert a VT_UI1 to a VT_CY.
3300 *
3301 * PARAMS
3302 * bIn [I] Source
3303 * pCyOut [O] Destination
3304 *
3305 * RETURNS
3306 * Success: S_OK.
3307 * Failure: E_INVALIDARG, if the source value is invalid
3308 * DISP_E_OVERFLOW, if the value will not fit in the destination
3309 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3310 */
3311 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
3312 {
3313 return _VarCyFromUI1(bIn, pCyOut);
3314 }
3315
3316 /************************************************************************
3317 * VarCyFromI2 (OLEAUT32.99)
3318 *
3319 * Convert a VT_I2 to a VT_CY.
3320 *
3321 * PARAMS
3322 * sIn [I] Source
3323 * pCyOut [O] Destination
3324 *
3325 * RETURNS
3326 * Success: S_OK.
3327 * Failure: E_INVALIDARG, if the source value is invalid
3328 * DISP_E_OVERFLOW, if the value will not fit in the destination
3329 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3330 */
3331 HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
3332 {
3333 return _VarCyFromI2(sIn, pCyOut);
3334 }
3335
3336 /************************************************************************
3337 * VarCyFromI4 (OLEAUT32.100)
3338 *
3339 * Convert a VT_I4 to a VT_CY.
3340 *
3341 * PARAMS
3342 * sIn [I] Source
3343 * pCyOut [O] Destination
3344 *
3345 * RETURNS
3346 * Success: S_OK.
3347 * Failure: E_INVALIDARG, if the source value is invalid
3348 * DISP_E_OVERFLOW, if the value will not fit in the destination
3349 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3350 */
3351 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
3352 {
3353 return _VarCyFromI4(lIn, pCyOut);
3354 }
3355
3356 /************************************************************************
3357 * VarCyFromR4 (OLEAUT32.101)
3358 *
3359 * Convert a VT_R4 to a VT_CY.
3360 *
3361 * PARAMS
3362 * fltIn [I] Source
3363 * pCyOut [O] Destination
3364 *
3365 * RETURNS
3366 * Success: S_OK.
3367 * Failure: E_INVALIDARG, if the source value is invalid
3368 * DISP_E_OVERFLOW, if the value will not fit in the destination
3369 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3370 */
3371 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
3372 {
3373 return _VarCyFromR4(fltIn, pCyOut);
3374 }
3375
3376 /************************************************************************
3377 * VarCyFromR8 (OLEAUT32.102)
3378 *
3379 * Convert a VT_R8 to a VT_CY.
3380 *
3381 * PARAMS
3382 * dblIn [I] Source
3383 * pCyOut [O] Destination
3384 *
3385 * RETURNS
3386 * Success: S_OK.
3387 * Failure: E_INVALIDARG, if the source value is invalid
3388 * DISP_E_OVERFLOW, if the value will not fit in the destination
3389 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3390 */
3391 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
3392 {
3393 #if defined(__GNUC__) && defined(__i386__)
3394 /* This code gives identical results to Win32 on Intel.
3395 * Here we use fp exceptions to catch overflows when storing the value.
3396 */
3397 static const unsigned short r8_fpcontrol = 0x137f;
3398 static const double r8_multiplier = CY_MULTIPLIER_F;
3399 unsigned short old_fpcontrol, result_fpstatus;
3400
3401 /* Clear exceptions, save the old fp state and load the new state */
3402 __asm__ __volatile__( "fnclex" );
3403 __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
3404 __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
3405 /* Perform the conversion. */
3406 __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
3407 __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
3408 __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
3409 /* Save the resulting fp state, load the old state and clear exceptions */
3410 __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
3411 __asm__ __volatile__( "fnclex" );
3412 __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
3413
3414 if (result_fpstatus & 0x9) /* Overflow | Invalid */
3415 return DISP_E_OVERFLOW;
3416 return S_OK;
3417 #else
3418 /* This version produces slightly different results for boundary cases */
3419 if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
3420 return DISP_E_OVERFLOW;
3421 dblIn *= CY_MULTIPLIER_F;
3422 OLEAUT32_DutchRound(LONG64, dblIn, pCyOut->int64);
3423 #endif
3424 return S_OK;
3425 }
3426
3427 /************************************************************************
3428 * VarCyFromDate (OLEAUT32.103)
3429 *
3430 * Convert a VT_DATE to a VT_CY.
3431 *
3432 * PARAMS
3433 * dateIn [I] Source
3434 * pCyOut [O] Destination
3435 *
3436 * RETURNS
3437 * Success: S_OK.
3438 * Failure: E_INVALIDARG, if the source value is invalid
3439 * DISP_E_OVERFLOW, if the value will not fit in the destination
3440 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3441 */
3442 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
3443 {
3444 return _VarCyFromDate(dateIn, pCyOut);
3445 }
3446
3447 /************************************************************************
3448 * VarCyFromStr (OLEAUT32.104)
3449 *
3450 * Convert a VT_BSTR to a VT_CY.
3451 *
3452 * PARAMS
3453 * strIn [I] Source
3454 * lcid [I] LCID for the conversion
3455 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
3456 * pCyOut [O] Destination
3457 *
3458 * RETURNS
3459 * Success: S_OK.
3460 * Failure: E_INVALIDARG, if the source value is invalid
3461 * DISP_E_OVERFLOW, if the value will not fit in the destination
3462 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3463 */
3464 HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
3465 {
3466 return _VarCyFromStr(strIn, lcid, dwFlags, pCyOut);
3467 }
3468
3469 /************************************************************************
3470 * VarCyFromDisp (OLEAUT32.105)
3471 *
3472 * Convert a VT_DISPATCH to a VT_CY.
3473 *
3474 * PARAMS
3475 * pdispIn [I] Source
3476 * lcid [I] LCID for conversion
3477 * pCyOut [O] Destination
3478 *
3479 * RETURNS
3480 * Success: S_OK.
3481 * Failure: E_INVALIDARG, if the source value is invalid
3482 * DISP_E_OVERFLOW, if the value will not fit in the destination
3483 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3484 */
3485 HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
3486 {
3487 return _VarCyFromDisp(pdispIn, lcid, pCyOut);
3488 }
3489
3490
3491 /************************************************************************
3492 * VarCyFromBool (OLEAUT32.106)
3493 *
3494 * Convert a VT_BOOL to a VT_CY.
3495 *
3496 * PARAMS
3497 * boolIn [I] Source
3498 * pCyOut [O] Destination
3499 *
3500 * RETURNS
3501 * Success: S_OK.
3502 * Failure: E_INVALIDARG, if the source value is invalid
3503 * DISP_E_OVERFLOW, if the value will not fit in the destination
3504 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3505 *
3506 * NOTES
3507 * While the sign of the boolean is stored in the currency, the value is
3508 * converted to either 0 or 1.
3509 */
3510 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
3511 {
3512 return _VarCyFromBool(boolIn, pCyOut);
3513 }
3514
3515 /************************************************************************
3516 * VarCyFromI1 (OLEAUT32.225)
3517 *
3518 * Convert a VT_I1 to a VT_CY.
3519 *
3520 * PARAMS
3521 * cIn [I] Source
3522 * pCyOut [O] Destination
3523 *
3524 * RETURNS
3525 * Success: S_OK.
3526 * Failure: E_INVALIDARG, if the source value is invalid
3527 * DISP_E_OVERFLOW, if the value will not fit in the destination
3528 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3529 */
3530 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
3531 {
3532 return _VarCyFromI1(cIn, pCyOut);
3533 }
3534
3535 /************************************************************************
3536 * VarCyFromUI2 (OLEAUT32.226)
3537 *
3538 * Convert a VT_UI2 to a VT_CY.
3539 *
3540 * PARAMS
3541 * usIn [I] Source
3542 * pCyOut [O] Destination
3543 *
3544 * RETURNS
3545 * Success: S_OK.
3546 * Failure: E_INVALIDARG, if the source value is invalid
3547 * DISP_E_OVERFLOW, if the value will not fit in the destination
3548 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3549 */
3550 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
3551 {
3552 return _VarCyFromUI2(usIn, pCyOut);
3553 }
3554
3555 /************************************************************************
3556 * VarCyFromUI4 (OLEAUT32.227)
3557 *
3558 * Convert a VT_UI4 to a VT_CY.
3559 *
3560 * PARAMS
3561 * ulIn [I] Source
3562 * pCyOut [O] Destination
3563 *
3564 * RETURNS
3565 * Success: S_OK.
3566 * Failure: E_INVALIDARG, if the source value is invalid
3567 * DISP_E_OVERFLOW, if the value will not fit in the destination
3568 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3569 */
3570 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
3571 {
3572 return _VarCyFromUI4(ulIn, pCyOut);
3573 }
3574
3575 /************************************************************************
3576 * VarCyFromDec (OLEAUT32.228)
3577 *
3578 * Convert a VT_DECIMAL to a VT_CY.
3579 *
3580 * PARAMS
3581 * pdecIn [I] Source
3582 * pCyOut [O] Destination
3583 *
3584 * RETURNS
3585 * Success: S_OK.
3586 * Failure: E_INVALIDARG, if the source value is invalid
3587 * DISP_E_OVERFLOW, if the value will not fit in the destination
3588 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3589 */
3590 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
3591 HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
3592 {
3593 DECIMAL rounded;
3594 HRESULT hRet;
3595
3596 hRet = VarDecRound(pdecIn, 4, &rounded);
3597
3598 if (SUCCEEDED(hRet))
3599 {
3600 double d;
3601
3602 if (DEC_HI32(&rounded))
3603 return DISP_E_OVERFLOW;
3604
3605 /* Note: Without the casts this promotes to int64 which loses precision */
3606 d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
3607 if (DEC_SIGN(&rounded))
3608 d = -d;
3609 return _VarCyFromR8(d, pCyOut);
3610 }
3611 return hRet;
3612 }
3613 #endif
3614
3615 /************************************************************************
3616 * VarCyFromI8 (OLEAUT32.366)
3617 *
3618 * Convert a VT_I8 to a VT_CY.
3619 *
3620 * PARAMS
3621 * ullIn [I] Source
3622 * pCyOut [O] Destination
3623 *
3624 * RETURNS
3625 * Success: S_OK.
3626 * Failure: E_INVALIDARG, if the source value is invalid
3627 * DISP_E_OVERFLOW, if the value will not fit in the destination
3628 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3629 */
3630 HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
3631 {
3632 return _VarCyFromI8(llIn, pCyOut);
3633 }
3634
3635 /************************************************************************
3636 * VarCyFromUI8 (OLEAUT32.375)
3637 *
3638 * Convert a VT_UI8 to a VT_CY.
3639 *
3640 * PARAMS
3641 * ullIn [I] Source
3642 * pCyOut [O] Destination
3643 *
3644 * RETURNS
3645 * Success: S_OK.
3646 * Failure: E_INVALIDARG, if the source value is invalid
3647 * DISP_E_OVERFLOW, if the value will not fit in the destination
3648 * DISP_E_TYPEMISMATCH, if the type cannot be converted
3649 */
3650 HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
3651 {
3652 return _VarCyFromUI8(ullIn, pCyOut);
3653 }
3654
3655 /************************************************************************
3656 * VarCyAdd (OLEAUT32.299)
3657 *
3658 * Add one CY to another.
3659 *
3660 * PARAMS
3661 * cyLeft [I] Source
3662 * cyRight [I] Value to add
3663 * pCyOut [O] Destination
3664 *
3665 * RETURNS
3666 * Success: S_OK.
3667 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3668 */
3669 HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
3670 {
3671 double l,r;
3672 _VarR8FromCy(cyLeft, &l);
3673 _VarR8FromCy(cyRight, &r);
3674 l = l + r;
3675 return _VarCyFromR8(l, pCyOut);
3676 }
3677
3678 /************************************************************************
3679 * VarCyMul (OLEAUT32.303)
3680 *
3681 * Multiply one CY by another.
3682 *
3683 * PARAMS
3684 * cyLeft [I] Source
3685 * cyRight [I] Value to multiply by
3686 * pCyOut [O] Destination
3687 *
3688 * RETURNS
3689 * Success: S_OK.
3690 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3691 */
3692 HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
3693 {
3694 double l,r;
3695 _VarR8FromCy(cyLeft, &l);
3696 _VarR8FromCy(cyRight, &r);
3697 l = l * r;
3698 return _VarCyFromR8(l, pCyOut);
3699 }
3700
3701 /************************************************************************
3702 * VarCyMulI4 (OLEAUT32.304)
3703 *
3704 * Multiply one CY by a VT_I4.
3705 *
3706 * PARAMS
3707 * cyLeft [I] Source
3708 * lRight [I] Value to multiply by
3709 * pCyOut [O] Destination
3710 *
3711 * RETURNS
3712 * Success: S_OK.
3713 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3714 */
3715 HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
3716 {
3717 double d;
3718
3719 _VarR8FromCy(cyLeft, &d);
3720 d = d * lRight;
3721 return _VarCyFromR8(d, pCyOut);
3722 }
3723
3724 /************************************************************************
3725 * VarCySub (OLEAUT32.305)
3726 *
3727 * Subtract one CY from another.
3728 *
3729 * PARAMS
3730 * cyLeft [I] Source
3731 * cyRight [I] Value to subtract
3732 * pCyOut [O] Destination
3733 *
3734 * RETURNS
3735 * Success: S_OK.
3736 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3737 */
3738 HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
3739 {
3740 double l,r;
3741 _VarR8FromCy(cyLeft, &l);
3742 _VarR8FromCy(cyRight, &r);
3743 l = l - r;
3744 return _VarCyFromR8(l, pCyOut);
3745 }
3746
3747 /************************************************************************
3748 * VarCyAbs (OLEAUT32.306)
3749 *
3750 * Convert a VT_CY into its absolute value.
3751 *
3752 * PARAMS
3753 * cyIn [I] Source
3754 * pCyOut [O] Destination
3755 *
3756 * RETURNS
3757 * Success: S_OK. pCyOut contains the absolute value.
3758 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3759 */
3760 HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
3761 {
3762 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3763 return DISP_E_OVERFLOW;
3764
3765 pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
3766 return S_OK;
3767 }
3768
3769 /************************************************************************
3770 * VarCyFix (OLEAUT32.307)
3771 *
3772 * Return the integer part of a VT_CY.
3773 *
3774 * PARAMS
3775 * cyIn [I] Source
3776 * pCyOut [O] Destination
3777 *
3778 * RETURNS
3779 * Success: S_OK.
3780 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3781 *
3782 * NOTES
3783 * - The difference between this function and VarCyInt() is that VarCyInt() rounds
3784 * negative numbers away from 0, while this function rounds them towards zero.
3785 */
3786 HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
3787 {
3788 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3789 pCyOut->int64 *= CY_MULTIPLIER;
3790 return S_OK;
3791 }
3792
3793 /************************************************************************
3794 * VarCyInt (OLEAUT32.308)
3795 *
3796 * Return the integer part of a VT_CY.
3797 *
3798 * PARAMS
3799 * cyIn [I] Source
3800 * pCyOut [O] Destination
3801 *
3802 * RETURNS
3803 * Success: S_OK.
3804 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3805 *
3806 * NOTES
3807 * - The difference between this function and VarCyFix() is that VarCyFix() rounds
3808 * negative numbers towards 0, while this function rounds them away from zero.
3809 */
3810 HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
3811 {
3812 pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
3813 pCyOut->int64 *= CY_MULTIPLIER;
3814
3815 if (cyIn.int64 < 0 && cyIn.int64 % CY_MULTIPLIER != 0)
3816 {
3817 pCyOut->int64 -= CY_MULTIPLIER;
3818 }
3819 return S_OK;
3820 }
3821
3822 /************************************************************************
3823 * VarCyNeg (OLEAUT32.309)
3824 *
3825 * Change the sign of a VT_CY.
3826 *
3827 * PARAMS
3828 * cyIn [I] Source
3829 * pCyOut [O] Destination
3830 *
3831 * RETURNS
3832 * Success: S_OK.
3833 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3834 */
3835 HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
3836 {
3837 if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
3838 return DISP_E_OVERFLOW;
3839
3840 pCyOut->int64 = -cyIn.int64;
3841 return S_OK;
3842 }
3843
3844 /************************************************************************
3845 * VarCyRound (OLEAUT32.310)
3846 *
3847 * Change the precision of a VT_CY.
3848 *
3849 * PARAMS
3850 * cyIn [I] Source
3851 * cDecimals [I] New number of decimals to keep
3852 * pCyOut [O] Destination
3853 *
3854 * RETURNS
3855 * Success: S_OK.
3856 * Failure: E_INVALIDARG, if cDecimals is less than 0.
3857 */
3858 HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
3859 {
3860 if (cDecimals < 0)
3861 return E_INVALIDARG;
3862
3863 if (cDecimals > 3)
3864 {
3865 /* Rounding to more precision than we have */
3866 *pCyOut = cyIn;
3867 return S_OK;
3868 }
3869 else
3870 {
3871 double d, div = CY_Divisors[cDecimals];
3872
3873 _VarR8FromCy(cyIn, &d);
3874 d = d * div;
3875 OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3876 d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
3877 OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
3878 return S_OK;
3879 }
3880 }
3881
3882 /************************************************************************
3883 * VarCyCmp (OLEAUT32.311)
3884 *
3885 * Compare two VT_CY values.
3886 *
3887 * PARAMS
3888 * cyLeft [I] Source
3889 * cyRight [I] Value to compare
3890 *
3891 * RETURNS
3892 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
3893 * compare is less, equal or greater than source respectively.
3894 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3895 */
3896 HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
3897 {
3898 HRESULT hRet;
3899 CY result;
3900
3901 /* Subtract right from left, and compare the result to 0 */
3902 hRet = VarCySub(cyLeft, cyRight, &result);
3903
3904 if (SUCCEEDED(hRet))
3905 {
3906 if (result.int64 < 0)
3907 hRet = (HRESULT)VARCMP_LT;
3908 else if (result.int64 > 0)
3909 hRet = (HRESULT)VARCMP_GT;
3910 else
3911 hRet = (HRESULT)VARCMP_EQ;
3912 }
3913 return hRet;
3914 }
3915
3916 /************************************************************************
3917 * VarCyCmpR8 (OLEAUT32.312)
3918 *
3919 * Compare a VT_CY to a double
3920 *
3921 * PARAMS
3922 * cyLeft [I] Currency Source
3923 * dblRight [I] double to compare to cyLeft
3924 *
3925 * RETURNS
3926 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
3927 * less than, equal to or greater than cyLeft respectively.
3928 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
3929 */
3930 HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
3931 {
3932 HRESULT hRet;
3933 CY cyRight;
3934
3935 hRet = _VarCyFromR8(dblRight, &cyRight);
3936
3937 if (SUCCEEDED(hRet))
3938 hRet = VarCyCmp(cyLeft, cyRight);
3939
3940 return hRet;
3941 }
3942
3943 /************************************************************************
3944 * VarCyMulI8 (OLEAUT32.329)
3945 *
3946 * Multiply a VT_CY by a VT_I8.
3947 *
3948 * PARAMS
3949 * cyLeft [I] Source
3950 * llRight [I] Value to multiply by
3951 * pCyOut [O] Destination
3952 *
3953 * RETURNS
3954 * Success: S_OK.
3955 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
3956 */
3957 HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
3958 {
3959 double d;
3960
3961 _VarR8FromCy(cyLeft, &d);
3962 d = d * (double)llRight;
3963 return _VarCyFromR8(d, pCyOut);
3964 }
3965
3966 /* DECIMAL
3967 */
3968
3969 /************************************************************************
3970 * VarDecFromUI1 (OLEAUT32.190)
3971 *
3972 * Convert a VT_UI1 to a DECIMAL.
3973 *
3974 * PARAMS
3975 * bIn [I] Source
3976 * pDecOut [O] Destination
3977 *
3978 * RETURNS
3979 * S_OK.
3980 */
3981 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
3982 HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
3983 {
3984 return _VarDecFromUI1(bIn, pDecOut);
3985 }
3986
3987 /************************************************************************
3988 * VarDecFromI2 (OLEAUT32.191)
3989 *
3990 * Convert a VT_I2 to a DECIMAL.
3991 *
3992 * PARAMS
3993 * sIn [I] Source
3994 * pDecOut [O] Destination
3995 *
3996 * RETURNS
3997 * S_OK.
3998 */
3999 HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
4000 {
4001 return _VarDecFromI2(sIn, pDecOut);
4002 }
4003 #endif
4004
4005 /************************************************************************
4006 * VarDecFromI4 (OLEAUT32.192)
4007 *
4008 * Convert a VT_I4 to a DECIMAL.
4009 *
4010 * PARAMS
4011 * sIn [I] Source
4012 * pDecOut [O] Destination
4013 *
4014 * RETURNS
4015 * S_OK.
4016 */
4017 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
4018 HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
4019 {
4020 DEC_HI32(pDecOut) = 0;
4021 DEC_MID32(pDecOut) = 0;
4022
4023 if (lIn < 0)
4024 {
4025 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4026 DEC_LO32(pDecOut) = -lIn;
4027 }
4028 else
4029 {
4030 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4031 DEC_LO32(pDecOut) = lIn;
4032 }
4033 return S_OK;
4034 }
4035 #endif
4036
4037 /************************************************************************
4038 * VarDecFromR4 (OLEAUT32.193)
4039 *
4040 * Convert a VT_R4 to a DECIMAL.
4041 *
4042 * PARAMS
4043 * fltIn [I] Source
4044 * pDecOut [O] Destination
4045 *
4046 * RETURNS
4047 * S_OK.
4048 */
4049 HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
4050 {
4051 WCHAR buff[256];
4052
4053 sprintfW( buff, szFloatFormatW, fltIn );
4054 return _VarDecFromStr(buff, LOCALE_SYSTEM_DEFAULT, 0, pDecOut);
4055 }
4056
4057 /************************************************************************
4058 * VarDecFromR8 (OLEAUT32.194)
4059 *
4060 * Convert a VT_R8 to a DECIMAL.
4061 *
4062 * PARAMS
4063 * dblIn [I] Source
4064 * pDecOut [O] Destination
4065 *
4066 * RETURNS
4067 * S_OK.
4068 */
4069 HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
4070 {
4071 WCHAR buff[256];
4072
4073 sprintfW( buff, szDoubleFormatW, dblIn );
4074 return _VarDecFromStr(buff, LOCALE_USER_DEFAULT, 0, pDecOut);
4075 }
4076
4077 /************************************************************************
4078 * VarDecFromDate (OLEAUT32.195)
4079 *
4080 * Convert a VT_DATE to a DECIMAL.
4081 *
4082 * PARAMS
4083 * dateIn [I] Source
4084 * pDecOut [O] Destination
4085 *
4086 * RETURNS
4087 * S_OK.
4088 */
4089 HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
4090 {
4091 return _VarDecFromDate(dateIn, pDecOut);
4092 }
4093
4094 /************************************************************************
4095 * VarDecFromCy (OLEAUT32.196)
4096 *
4097 * Convert a VT_CY to a DECIMAL.
4098 *
4099 * PARAMS
4100 * cyIn [I] Source
4101 * pDecOut [O] Destination
4102 *
4103 * RETURNS
4104 * S_OK.
4105 */
4106 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4107 HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
4108 {
4109 DEC_HI32(pDecOut) = 0;
4110
4111 /* Note: This assumes 2s complement integer representation */
4112 if (cyIn.s.Hi & 0x80000000)
4113 {
4114 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
4115 DEC_LO64(pDecOut) = -cyIn.int64;
4116 }
4117 else
4118 {
4119 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
4120 DEC_MID32(pDecOut) = cyIn.s.Hi;
4121 DEC_LO32(pDecOut) = cyIn.s.Lo;
4122 }
4123 return S_OK;
4124 }
4125 #endif
4126
4127
4128 /************************************************************************
4129 * VarDecFromStr (OLEAUT32.197)
4130 *
4131 * Convert a VT_BSTR to a DECIMAL.
4132 *
4133 * PARAMS
4134 * strIn [I] Source
4135 * lcid [I] LCID for the conversion
4136 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4137 * pDecOut [O] Destination
4138 *
4139 * RETURNS
4140 * Success: S_OK.
4141 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4142 */
4143 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
4144 {
4145 return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
4146 }
4147
4148 /************************************************************************
4149 * VarDecFromDisp (OLEAUT32.198)
4150 *
4151 * Convert a VT_DISPATCH to a DECIMAL.
4152 *
4153 * PARAMS
4154 * pdispIn [I] Source
4155 * lcid [I] LCID for conversion
4156 * pDecOut [O] Destination
4157 *
4158 * RETURNS
4159 * Success: S_OK.
4160 * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
4161 */
4162 HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
4163 {
4164 return _VarDecFromDisp(pdispIn, lcid, pDecOut);
4165 }
4166
4167 /************************************************************************
4168 * VarDecFromBool (OLEAUT32.199)
4169 *
4170 * Convert a VT_BOOL to a DECIMAL.
4171 *
4172 * PARAMS
4173 * bIn [I] Source
4174 * pDecOut [O] Destination
4175 *
4176 * RETURNS
4177 * S_OK.
4178 *
4179 * NOTES
4180 * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
4181 */
4182 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
4183 HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
4184 {
4185 DEC_HI32(pDecOut) = 0;
4186 DEC_MID32(pDecOut) = 0;
4187 if (bIn)
4188 {
4189 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4190 DEC_LO32(pDecOut) = 1;
4191 }
4192 else
4193 {
4194 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4195 DEC_LO32(pDecOut) = 0;
4196 }
4197 return S_OK;
4198 }
4199
4200 /************************************************************************
4201 * VarDecFromI1 (OLEAUT32.241)
4202 *
4203 * Convert a VT_I1 to a DECIMAL.
4204 *
4205 * PARAMS
4206 * cIn [I] Source
4207 * pDecOut [O] Destination
4208 *
4209 * RETURNS
4210 * S_OK.
4211 */
4212 HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
4213 {
4214 return _VarDecFromI1(cIn, pDecOut);
4215 }
4216
4217 /************************************************************************
4218 * VarDecFromUI2 (OLEAUT32.242)
4219 *
4220 * Convert a VT_UI2 to a DECIMAL.
4221 *
4222 * PARAMS
4223 * usIn [I] Source
4224 * pDecOut [O] Destination
4225 *
4226 * RETURNS
4227 * S_OK.
4228 */
4229 HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
4230 {
4231 return _VarDecFromUI2(usIn, pDecOut);
4232 }
4233 #endif
4234
4235 /************************************************************************
4236 * VarDecFromUI4 (OLEAUT32.243)
4237 *
4238 * Convert a VT_UI4 to a DECIMAL.
4239 *
4240 * PARAMS
4241 * ulIn [I] Source
4242 * pDecOut [O] Destination
4243 *
4244 * RETURNS
4245 * S_OK.
4246 */
4247 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
4248 HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
4249 {
4250 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4251 DEC_HI32(pDecOut) = 0;
4252 DEC_MID32(pDecOut) = 0;
4253 DEC_LO32(pDecOut) = ulIn;
4254 return S_OK;
4255 }
4256 #endif
4257
4258 /************************************************************************
4259 * VarDecFromI8 (OLEAUT32.374)
4260 *
4261 * Convert a VT_I8 to a DECIMAL.
4262 *
4263 * PARAMS
4264 * llIn [I] Source
4265 * pDecOut [O] Destination
4266 *
4267 * RETURNS
4268 * S_OK.
4269 */
4270 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4271 HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
4272 {
4273 PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
4274
4275 DEC_HI32(pDecOut) = 0;
4276
4277 /* Note: This assumes 2s complement integer representation */
4278 if (pLi->u.HighPart & 0x80000000)
4279 {
4280 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
4281 DEC_LO64(pDecOut) = -pLi->QuadPart;
4282 }
4283 else
4284 {
4285 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4286 DEC_MID32(pDecOut) = pLi->u.HighPart;
4287 DEC_LO32(pDecOut) = pLi->u.LowPart;
4288 }
4289 return S_OK;
4290 }
4291 #endif
4292
4293 /************************************************************************
4294 * VarDecFromUI8 (OLEAUT32.375)
4295 *
4296 * Convert a VT_UI8 to a DECIMAL.
4297 *
4298 * PARAMS
4299 * ullIn [I] Source
4300 * pDecOut [O] Destination
4301 *
4302 * RETURNS
4303 * S_OK.
4304 */
4305 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4306 HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
4307 {
4308 DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
4309 DEC_HI32(pDecOut) = 0;
4310 DEC_LO64(pDecOut) = ullIn;
4311 return S_OK;
4312 }
4313 #endif
4314
4315 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4316 /* Make two DECIMALS the same scale; used by math functions below */
4317 static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
4318 const DECIMAL** ppDecRight,
4319 DECIMAL* pDecOut)
4320 {
4321 static DECIMAL scaleFactor;
4322 DECIMAL decTemp;
4323 int scaleAmount, i;
4324 HRESULT hRet = S_OK;
4325
4326 if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
4327 return E_INVALIDARG;
4328
4329 DEC_LO32(&scaleFactor) = 10;
4330
4331 i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
4332
4333 if (!scaleAmount)
4334 return S_OK; /* Same scale */
4335
4336 if (scaleAmount > 0)
4337 {
4338 decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
4339 *ppDecRight = pDecOut;
4340 }
4341 else
4342 {
4343 decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
4344 *ppDecLeft = pDecOut;
4345 i = scaleAmount = -scaleAmount;
4346 }
4347
4348 if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
4349 return DISP_E_OVERFLOW; /* Can't scale up */
4350
4351 /* Multiply up the value to be scaled by the correct amount */
4352 while (SUCCEEDED(hRet) && i--)
4353 {
4354 /* Note we are multiplying by a value with a scale of 0, so we don't recurse */
4355 hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
4356 decTemp = *pDecOut;
4357 }
4358 DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
4359 return hRet;
4360 }
4361 #endif
4362
4363 /* Add two unsigned 32 bit values with overflow */
4364 static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4365 {
4366 ULARGE_INTEGER ul64;
4367
4368 ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
4369 *pulHigh = ul64.u.HighPart;
4370 return ul64.u.LowPart;
4371 }
4372
4373 /* Subtract two unsigned 32 bit values with underflow */
4374 static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4375 {
4376 int invert = 0;
4377 ULARGE_INTEGER ul64;
4378
4379 ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
4380 if (ulLeft < ulRight)
4381 invert = 1;
4382
4383 if (ul64.QuadPart > (ULONG64)*pulHigh)
4384 ul64.QuadPart -= (ULONG64)*pulHigh;
4385 else
4386 {
4387 ul64.QuadPart -= (ULONG64)*pulHigh;
4388 invert = 1;
4389 }
4390 if (invert)
4391 ul64.u.HighPart = -ul64.u.HighPart ;
4392
4393 *pulHigh = ul64.u.HighPart;
4394 return ul64.u.LowPart;
4395 }
4396
4397 /* Multiply two unsigned 32 bit values with overflow */
4398 static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
4399 {
4400 ULARGE_INTEGER ul64;
4401
4402 ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
4403 *pulHigh = ul64.u.HighPart;
4404 return ul64.u.LowPart;
4405 }
4406
4407 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
4408 /* Compare two decimals that have the same scale */
4409 static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
4410 {
4411 if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
4412 (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
4413 return -1;
4414 else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
4415 return 0;
4416 return 1;
4417 }
4418 #endif
4419
4420 /************************************************************************
4421 * VarDecAdd (OLEAUT32.177)
4422 *
4423 * Add one DECIMAL to another.
4424 *
4425 * PARAMS
4426 * pDecLeft [I] Source
4427 * pDecRight [I] Value to add
4428 * pDecOut [O] Destination
4429 *
4430 * RETURNS
4431 * Success: S_OK.
4432 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4433 */
4434 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4435 HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4436 {
4437 HRESULT hRet;
4438 DECIMAL scaled;
4439
4440 hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
4441
4442 if (SUCCEEDED(hRet))
4443 {
4444 /* Our decimals now have the same scale, we can add them as 96 bit integers */
4445 ULONG overflow = 0;
4446 BYTE sign = DECIMAL_POS;
4447
4448 /* Correct for the sign of the result */
4449 if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4450 {
4451 /* -x + -y : Negative */
4452 sign = DECIMAL_NEG;
4453 goto VarDecAdd_AsPositive;
4454 }
4455 else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
4456 {
4457 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4458
4459 /* -x + y : Negative if x > y */
4460 if (cmp > 0)
4461 {
4462 sign = DECIMAL_NEG;
4463 VarDecAdd_AsNegative:
4464 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4465 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4466 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4467 }
4468 else
4469 {
4470 VarDecAdd_AsInvertedNegative:
4471 DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecRight), DEC_LO32(pDecLeft), &overflow);
4472 DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
4473 DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecRight), DEC_HI32(pDecLeft), &overflow);
4474 }
4475 }
4476 else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
4477 {
4478 int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
4479
4480 /* x + -y : Negative if x <= y */
4481 if (cmp <= 0)
4482 {
4483 sign = DECIMAL_NEG;
4484 goto VarDecAdd_AsInvertedNegative;
4485 }
4486 goto VarDecAdd_AsNegative;
4487 }
4488 else
4489 {
4490 /* x + y : Positive */
4491 VarDecAdd_AsPositive:
4492 DEC_LO32(pDecOut) = VARIANT_Add(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
4493 DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
4494 DEC_HI32(pDecOut) = VARIANT_Add(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
4495 }
4496
4497 if (overflow)
4498 return DISP_E_OVERFLOW; /* overflowed */
4499
4500 DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
4501 DEC_SIGN(pDecOut) = sign;
4502 }
4503 return hRet;
4504 }
4505 #endif
4506
4507 /************************************************************************
4508 * VarDecDiv (OLEAUT32.178)
4509 *
4510 * Divide one DECIMAL by another.
4511 *
4512 * PARAMS
4513 * pDecLeft [I] Source
4514 * pDecRight [I] Value to divide by
4515 * pDecOut [O] Destination
4516 *
4517 * RETURNS
4518 * Success: S_OK.
4519 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4520 */
4521 HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4522 {
4523 FIXME("(%p,%p,%p)-stub!\n",pDecLeft,pDecRight,pDecOut);
4524 return DISP_E_OVERFLOW;
4525 }
4526
4527 /************************************************************************
4528 * VarDecMul (OLEAUT32.179)
4529 *
4530 * Multiply one DECIMAL by another.
4531 *
4532 * PARAMS
4533 * pDecLeft [I] Source
4534 * pDecRight [I] Value to multiply by
4535 * pDecOut [O] Destination
4536 *
4537 * RETURNS
4538 * Success: S_OK.
4539 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4540 */
4541 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4542 HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4543 {
4544 /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
4545
4546 if (!DEC_SCALE(pDecLeft) || !DEC_SCALE(pDecRight))
4547 {
4548 /* At least one term is an integer */
4549 const DECIMAL* pDecInteger = DEC_SCALE(pDecLeft) ? pDecRight : pDecLeft;
4550 const DECIMAL* pDecOperand = DEC_SCALE(pDecLeft) ? pDecLeft : pDecRight;
4551 HRESULT hRet = S_OK;
4552 unsigned int multiplier = DEC_LO32(pDecInteger);
4553 ULONG overflow = 0;
4554
4555 if (DEC_HI32(pDecInteger) || DEC_MID32(pDecInteger))
4556 {
4557 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4558 return DISP_E_OVERFLOW;
4559 }
4560
4561 DEC_LO32(pDecOut) = VARIANT_Mul(DEC_LO32(pDecOperand), multiplier, &overflow);
4562 DEC_MID32(pDecOut) = VARIANT_Mul(DEC_MID32(pDecOperand), multiplier, &overflow);
4563 DEC_HI32(pDecOut) = VARIANT_Mul(DEC_HI32(pDecOperand), multiplier, &overflow);
4564
4565 if (overflow)
4566 hRet = DISP_E_OVERFLOW;
4567 else
4568 {
4569 BYTE sign = DECIMAL_POS;
4570
4571 if (DEC_SIGN(pDecLeft) != DEC_SIGN(pDecRight))
4572 sign = DECIMAL_NEG; /* pos * neg => negative */
4573 DEC_SIGN(pDecOut) = sign;
4574 DEC_SCALE(pDecOut) = DEC_SCALE(pDecOperand);
4575 }
4576 return hRet;
4577 }
4578 FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
4579 return DISP_E_OVERFLOW;
4580 }
4581
4582 /************************************************************************
4583 * VarDecSub (OLEAUT32.181)
4584 *
4585 * Subtract one DECIMAL from another.
4586 *
4587 * PARAMS
4588 * pDecLeft [I] Source
4589 * pDecRight [I] DECIMAL to subtract from pDecLeft
4590 * pDecOut [O] Destination
4591 *
4592 * RETURNS
4593 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4594 */
4595 HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
4596 {
4597 DECIMAL decRight;
4598
4599 /* Implement as addition of the negative */
4600 VarDecNeg(pDecRight, &decRight);
4601 return VarDecAdd(pDecLeft, &decRight, pDecOut);
4602 }
4603 #endif
4604
4605 /************************************************************************
4606 * VarDecAbs (OLEAUT32.182)
4607 *
4608 * Convert a DECIMAL into its absolute value.
4609 *
4610 * PARAMS
4611 * pDecIn [I] Source
4612 * pDecOut [O] Destination
4613 *
4614 * RETURNS
4615 * S_OK. This function does not fail.
4616 */
4617 HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4618 {
4619 *pDecOut = *pDecIn;
4620 DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
4621 return S_OK;
4622 }
4623
4624 /************************************************************************
4625 * VarDecFix (OLEAUT32.187)
4626 *
4627 * Return the integer portion of a DECIMAL.
4628 *
4629 * PARAMS
4630 * pDecIn [I] Source
4631 * pDecOut [O] Destination
4632 *
4633 * RETURNS
4634 * Success: S_OK.
4635 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4636 *
4637 * NOTES
4638 * - The difference between this function and VarDecInt() is that VarDecInt() rounds
4639 * negative numbers away from 0, while this function rounds them towards zero.
4640 */
4641 HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4642 {
4643 if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
4644 return E_INVALIDARG;
4645
4646 if (!DEC_SCALE(pDecIn))
4647 {
4648 *pDecOut = *pDecIn; /* Already an integer */
4649 return S_OK;
4650 }
4651
4652 FIXME("semi-stub!\n");
4653 return DISP_E_OVERFLOW;
4654 }
4655
4656 /************************************************************************
4657 * VarDecInt (OLEAUT32.188)
4658 *
4659 * Return the integer portion of a DECIMAL.
4660 *
4661 * PARAMS
4662 * pDecIn [I] Source
4663 * pDecOut [O] Destination
4664 *
4665 * RETURNS
4666 * Success: S_OK.
4667 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
4668 *
4669 * NOTES
4670 * - The difference between this function and VarDecFix() is that VarDecFix() rounds
4671 * negative numbers towards 0, while this function rounds them away from zero.
4672 */
4673 HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4674 {
4675 if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
4676 return E_INVALIDARG;
4677
4678 if (!(DEC_SIGN(pDecOut) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
4679 return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
4680
4681 FIXME("semi-stub!\n");
4682 return DISP_E_OVERFLOW;
4683 }
4684
4685 /************************************************************************
4686 * VarDecNeg (OLEAUT32.189)
4687 *
4688 * Change the sign of a DECIMAL.
4689 *
4690 * PARAMS
4691 * pDecIn [I] Source
4692 * pDecOut [O] Destination
4693 *
4694 * RETURNS
4695 * S_OK. This function does not fail.
4696 */
4697 HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
4698 {
4699 *pDecOut = *pDecIn;
4700 DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
4701 return S_OK;
4702 }
4703
4704 /************************************************************************
4705 * VarDecRound (OLEAUT32.203)
4706 *
4707 * Change the precision of a DECIMAL.
4708 *
4709 * PARAMS
4710 * pDecIn [I] Source
4711 * cDecimals [I] New number of decimals to keep
4712 * pDecOut [O] Destination
4713 *
4714 * RETURNS
4715 * Success: S_OK. pDecOut contains the rounded value.
4716 * Failure: E_INVALIDARG if any argument is invalid.
4717 */
4718 HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
4719 {
4720 if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
4721 return E_INVALIDARG;
4722
4723 if (cDecimals >= DEC_SCALE(pDecIn))
4724 {
4725 *pDecOut = *pDecIn; /* More precision than we have */
4726 return S_OK;
4727 }
4728
4729 FIXME("semi-stub!\n");
4730
4731 return DISP_E_OVERFLOW;
4732 }
4733
4734 /************************************************************************
4735 * VarDecCmp (OLEAUT32.204)
4736 *
4737 * Compare two DECIMAL values.
4738 *
4739 * PARAMS
4740 * pDecLeft [I] Source
4741 * pDecRight [I] Value to compare
4742 *
4743 * RETURNS
4744 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
4745 * is less than, equal to or greater than pDecRight respectively.
4746 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4747 */
4748 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
4749 HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
4750 {
4751 HRESULT hRet;
4752 DECIMAL result;
4753
4754 /* Subtract right from left, and compare the result to 0 */
4755 hRet = VarDecSub(pDecLeft, pDecRight, &result);
4756
4757 if (SUCCEEDED(hRet))
4758 {
4759 int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
4760
4761 if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
4762 hRet = (HRESULT)VARCMP_LT;
4763 else if (non_zero)
4764 hRet = (HRESULT)VARCMP_GT;
4765 else
4766 hRet = (HRESULT)VARCMP_EQ;
4767 }
4768 return hRet;
4769 }
4770
4771
4772 /************************************************************************
4773 * VarDecCmpR8 (OLEAUT32.298)
4774 *
4775 * Compare a DECIMAL to a double
4776 *
4777 * PARAMS
4778 * pDecLeft [I] DECIMAL Source
4779 * dblRight [I] double to compare to pDecLeft
4780 *
4781 * RETURNS
4782 * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
4783 * is less than, equal to or greater than pDecLeft respectively.
4784 * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
4785 */
4786 HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
4787 {
4788 HRESULT hRet;
4789 DECIMAL decRight;
4790
4791 hRet = VarDecFromR8(dblRight, &decRight);
4792
4793 if (SUCCEEDED(hRet))
4794 hRet = VarDecCmp(pDecLeft, &decRight);
4795
4796 return hRet;
4797 }
4798 #endif
4799
4800 /* BOOL
4801 */
4802
4803 /************************************************************************
4804 * VarBoolFromUI1 (OLEAUT32.118)
4805 *
4806 * Convert a VT_UI1 to a VT_BOOL.
4807 *
4808 * PARAMS
4809 * bIn [I] Source
4810 * pBoolOut [O] Destination
4811 *
4812 * RETURNS
4813 * S_OK.
4814 */
4815 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
4816 {
4817 return _VarBoolFromUI1(bIn, pBoolOut);
4818 }
4819
4820 /************************************************************************
4821 * VarBoolFromI2 (OLEAUT32.119)
4822 *
4823 * Convert a VT_I2 to a VT_BOOL.
4824 *
4825 * PARAMS
4826 * sIn [I] Source
4827 * pBoolOut [O] Destination
4828 *
4829 * RETURNS
4830 * S_OK.
4831 */
4832 HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
4833 {
4834 return _VarBoolFromI2(sIn, pBoolOut);
4835 }
4836
4837 /************************************************************************
4838 * VarBoolFromI4 (OLEAUT32.120)
4839 *
4840 * Convert a VT_I4 to a VT_BOOL.
4841 *
4842 * PARAMS
4843 * sIn [I] Source
4844 * pBoolOut [O] Destination
4845 *
4846 * RETURNS
4847 * S_OK.
4848 */
4849 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
4850 {
4851 return _VarBoolFromI4(lIn, pBoolOut);
4852 }
4853
4854 /************************************************************************
4855 * VarBoolFromR4 (OLEAUT32.121)
4856 *
4857 * Convert a VT_R4 to a VT_BOOL.
4858 *
4859 * PARAMS
4860 * fltIn [I] Source
4861 * pBoolOut [O] Destination
4862 *
4863 * RETURNS
4864 * S_OK.
4865 */
4866 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
4867 {
4868 return _VarBoolFromR4(fltIn, pBoolOut);
4869 }
4870
4871 /************************************************************************
4872 * VarBoolFromR8 (OLEAUT32.122)
4873 *
4874 * Convert a VT_R8 to a VT_BOOL.
4875 *
4876 * PARAMS
4877 * dblIn [I] Source
4878 * pBoolOut [O] Destination
4879 *
4880 * RETURNS
4881 * S_OK.
4882 */
4883 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
4884 {
4885 return _VarBoolFromR8(dblIn, pBoolOut);
4886 }
4887
4888 /************************************************************************
4889 * VarBoolFromDate (OLEAUT32.123)
4890 *
4891 * Convert a VT_DATE to a VT_BOOL.
4892 *
4893 * PARAMS
4894 * dateIn [I] Source
4895 * pBoolOut [O] Destination
4896 *
4897 * RETURNS
4898 * S_OK.
4899 */
4900 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
4901 {
4902 return _VarBoolFromDate(dateIn, pBoolOut);
4903 }
4904
4905 /************************************************************************
4906 * VarBoolFromCy (OLEAUT32.124)
4907 *
4908 * Convert a VT_CY to a VT_BOOL.
4909 *
4910 * PARAMS
4911 * cyIn [I] Source
4912 * pBoolOut [O] Destination
4913 *
4914 * RETURNS
4915 * S_OK.
4916 */
4917 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
4918 {
4919 return _VarBoolFromCy(cyIn, pBoolOut);
4920 }
4921
4922 static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
4923 {
4924 HRSRC hrsrc;
4925
4926 hrsrc = FindResourceExW( OLEAUT32_hModule, (LPWSTR)RT_STRING,
4927 (LPCWSTR)((dwId >> 4) + 1), langId );
4928 if (hrsrc)
4929 {
4930 HGLOBAL hmem = LoadResource( OLEAUT32_hModule, hrsrc );
4931
4932 if (hmem)
4933 {
4934 const WCHAR *p;
4935 unsigned int i;
4936
4937 p = LockResource( hmem );
4938 for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
4939
4940 memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
4941 lpszDest[*p] = '\0';
4942 TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
4943 return TRUE;
4944 }
4945 }
4946 return FALSE;
4947 }
4948
4949 /************************************************************************
4950 * VarBoolFromStr (OLEAUT32.125)
4951 *
4952 * Convert a VT_BSTR to a VT_BOOL.
4953 *
4954 * PARAMS
4955 * strIn [I] Source
4956 * lcid [I] LCID for the conversion
4957 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
4958 * pBoolOut [O] Destination
4959 *
4960 * RETURNS
4961 * Success: S_OK.
4962 * Failure: E_INVALIDARG, if pBoolOut is invalid.
4963 * DISP_E_TYPEMISMATCH, if the type cannot be converted
4964 *
4965 * NOTES
4966 * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
4967 * it may contain (in any case mapping) the text "true" or "false".
4968 * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
4969 * localised text of "True" or "False" in the language specified by lcid.
4970 * - If none of these matches occur, the string is treated as a numeric string
4971 * and the boolean pBoolOut will be set according to whether the number is zero
4972 * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
4973 * - If the text is not numeric and does not match any of the above, then
4974 * DISP_E_TYPEMISMATCH is returned.
4975 */
4976 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
4977 {
4978 /* Any VB/VBA programmers out there should recognise these strings... */
4979 static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
4980 static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
4981 WCHAR szBuff[64];
4982 LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4983 HRESULT hRes = S_OK;
4984
4985 if (!strIn || !pBoolOut)
4986 return DISP_E_TYPEMISMATCH;
4987
4988 /* Check if we should be comparing against localised text */
4989 if (dwFlags & VAR_LOCALBOOL)
4990 {
4991 /* Convert our LCID into a usable value */
4992 lcid = ConvertDefaultLocale(lcid);
4993
4994 langId = LANGIDFROMLCID(lcid);
4995
4996 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
4997 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4998
4999 /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
5000 * I don't think this is needed unless any of the localised text strings
5001 * contain characters that can be so mapped. In the event that this is
5002 * true for a given language (possibly some Asian languages), then strIn
5003 * should be mapped here _only_ if langId is an Id for which this can occur.
5004 */
5005 }
5006
5007 /* Note that if we are not comparing against localised strings, langId
5008 * will have its default value of LANG_ENGLISH. This allows us to mimic
5009 * the native behaviour of always checking against English strings even
5010 * after we've checked for localised ones.
5011 */
5012 VarBoolFromStr_CheckLocalised:
5013 if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
5014 {
5015 /* Compare against localised strings, ignoring case */
5016 if (!strcmpiW(strIn, szBuff))
5017 {
5018 *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
5019 return hRes;
5020 }
5021 VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
5022 if (!strcmpiW(strIn, szBuff))
5023 {
5024 *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
5025 return hRes;
5026 }
5027 }
5028
5029 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5030 {
5031 /* We have checked the localised text, now check English */
5032 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5033 goto VarBoolFromStr_CheckLocalised;
5034 }
5035
5036 /* All checks against localised text have failed, try #TRUE#/#FALSE# */
5037 if (!strcmpW(strIn, szFalse))
5038 *pBoolOut = VARIANT_FALSE;
5039 else if (!strcmpW(strIn, szTrue))
5040 *pBoolOut = VARIANT_TRUE;
5041 else
5042 {
5043 double d;
5044
5045 /* If this string is a number, convert it as one */
5046 hRes = _VarR8FromStr(strIn, lcid, dwFlags, &d);
5047 if (SUCCEEDED(hRes))
5048 hRes = _VarBoolFromR8(d, pBoolOut);
5049 }
5050 return hRes;
5051 }
5052
5053 /************************************************************************
5054 * VarBoolFromDisp (OLEAUT32.126)
5055 *
5056 * Convert a VT_DISPATCH to a VT_BOOL.
5057 *
5058 * PARAMS
5059 * pdispIn [I] Source
5060 * lcid [I] LCID for conversion
5061 * pBoolOut [O] Destination
5062 *
5063 * RETURNS
5064 * Success: S_OK.
5065 * Failure: E_INVALIDARG, if the source value is invalid
5066 * DISP_E_OVERFLOW, if the value will not fit in the destination
5067 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5068 */
5069 HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
5070 {
5071 return _VarBoolFromDisp(pdispIn, lcid, pBoolOut);
5072 }
5073
5074 /************************************************************************
5075 * VarBoolFromI1 (OLEAUT32.233)
5076 *
5077 * Convert a VT_I1 to a VT_BOOL.
5078 *
5079 * PARAMS
5080 * cIn [I] Source
5081 * pBoolOut [O] Destination
5082 *
5083 * RETURNS
5084 * S_OK.
5085 */
5086 HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
5087 {
5088 return _VarBoolFromI1(cIn, pBoolOut);
5089 }
5090
5091 /************************************************************************
5092 * VarBoolFromUI2 (OLEAUT32.234)
5093 *
5094 * Convert a VT_UI2 to a VT_BOOL.
5095 *
5096 * PARAMS
5097 * usIn [I] Source
5098 * pBoolOut [O] Destination
5099 *
5100 * RETURNS
5101 * S_OK.
5102 */
5103 HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
5104 {
5105 return _VarBoolFromUI2(usIn, pBoolOut);
5106 }
5107
5108 /************************************************************************
5109 * VarBoolFromUI4 (OLEAUT32.235)
5110 *
5111 * Convert a VT_UI4 to a VT_BOOL.
5112 *
5113 * PARAMS
5114 * ulIn [I] Source
5115 * pBoolOut [O] Destination
5116 *
5117 * RETURNS
5118 * S_OK.
5119 */
5120 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
5121 {
5122 return _VarBoolFromUI4(ulIn, pBoolOut);
5123 }
5124
5125 /************************************************************************
5126 * VarBoolFromDec (OLEAUT32.236)
5127 *
5128 * Convert a VT_DECIMAL to a VT_BOOL.
5129 *
5130 * PARAMS
5131 * pDecIn [I] Source
5132 * pBoolOut [O] Destination
5133 *
5134 * RETURNS
5135 * Success: S_OK.
5136 * Failure: E_INVALIDARG, if pDecIn is invalid.
5137 */
5138 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO32 */
5139 HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
5140 {
5141 if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
5142 return E_INVALIDARG;
5143
5144 if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
5145 *pBoolOut = VARIANT_TRUE;
5146 else
5147 *pBoolOut = VARIANT_FALSE;
5148 return S_OK;
5149 }
5150 #endif
5151
5152 /************************************************************************
5153 * VarBoolFromI8 (OLEAUT32.370)
5154 *
5155 * Convert a VT_I8 to a VT_BOOL.
5156 *
5157 * PARAMS
5158 * ullIn [I] Source
5159 * pBoolOut [O] Destination
5160 *
5161 * RETURNS
5162 * S_OK.
5163 */
5164 HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
5165 {
5166 return _VarBoolFromI8(llIn, pBoolOut);
5167 }
5168
5169 /************************************************************************
5170 * VarBoolFromUI8 (OLEAUT32.371)
5171 *
5172 * Convert a VT_UI8 to a VT_BOOL.
5173 *
5174 * PARAMS
5175 * ullIn [I] Source
5176 * pBoolOut [O] Destination
5177 *
5178 * RETURNS
5179 * S_OK.
5180 */
5181 HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
5182 {
5183 return _VarBoolFromUI8(ullIn, pBoolOut);
5184 }
5185
5186 /* BSTR
5187 */
5188
5189 /* Write a number from a UI8 and sign */
5190 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
5191 {
5192 do
5193 {
5194 WCHAR ulNextDigit = ulVal % 10;
5195
5196 *szOut-- = '0' + ulNextDigit;
5197 ulVal = (ulVal - ulNextDigit) / 10;
5198 } while (ulVal);
5199
5200 szOut++;
5201 return szOut;
5202 }
5203
5204 /* Create a (possibly localised) BSTR from a UI8 and sign */
5205 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
5206 {
5207 WCHAR szConverted[256];
5208
5209 if (dwFlags & VAR_NEGATIVE)
5210 *--szOut = '-';
5211
5212 if (dwFlags & LOCALE_USE_NLS)
5213 {
5214 /* Format the number for the locale */
5215 szConverted[0] = '\0';
5216 GetNumberFormatW(lcid,
5217 dwFlags & LOCALE_NOUSEROVERRIDE,
5218 szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
5219 szOut = szConverted;
5220 }
5221 return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
5222 }
5223
5224 /* Create a (possibly localised) BSTR from a UI8 and sign */
5225 static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
5226 {
5227 WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5228
5229 if (!pbstrOut)
5230 return E_INVALIDARG;
5231
5232 /* Create the basic number string */
5233 *szOut-- = '\0';
5234 szOut = VARIANT_WriteNumber(ulVal, szOut);
5235
5236 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5237 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5238 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5239 }
5240
5241 /******************************************************************************
5242 * VarBstrFromUI1 (OLEAUT32.108)
5243 *
5244 * Convert a VT_UI1 to a VT_BSTR.
5245 *
5246 * PARAMS
5247 * bIn [I] Source
5248 * lcid [I] LCID for the conversion
5249 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5250 * pbstrOut [O] Destination
5251 *
5252 * RETURNS
5253 * Success: S_OK.
5254 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5255 * E_OUTOFMEMORY, if memory allocation fails.
5256 */
5257 HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5258 {
5259 return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
5260 }
5261
5262 /******************************************************************************
5263 * VarBstrFromI2 (OLEAUT32.109)
5264 *
5265 * Convert a VT_I2 to a VT_BSTR.
5266 *
5267 * PARAMS
5268 * sIn [I] Source
5269 * lcid [I] LCID for the conversion
5270 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5271 * pbstrOut [O] Destination
5272 *
5273 * RETURNS
5274 * Success: S_OK.
5275 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5276 * E_OUTOFMEMORY, if memory allocation fails.
5277 */
5278 HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5279 {
5280 ULONG64 ul64 = sIn;
5281
5282 if (sIn < 0)
5283 {
5284 ul64 = -sIn;
5285 dwFlags |= VAR_NEGATIVE;
5286 }
5287 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5288 }
5289
5290 /******************************************************************************
5291 * VarBstrFromI4 (OLEAUT32.110)
5292 *
5293 * Convert a VT_I4 to a VT_BSTR.
5294 *
5295 * PARAMS
5296 * lIn [I] Source
5297 * lcid [I] LCID for the conversion
5298 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5299 * pbstrOut [O] Destination
5300 *
5301 * RETURNS
5302 * Success: S_OK.
5303 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5304 * E_OUTOFMEMORY, if memory allocation fails.
5305 */
5306 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5307 {
5308 ULONG64 ul64 = lIn;
5309
5310 if (lIn < 0)
5311 {
5312 ul64 = -lIn;
5313 dwFlags |= VAR_NEGATIVE;
5314 }
5315 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5316 }
5317
5318 static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
5319 BSTR* pbstrOut, LPCWSTR lpszFormat)
5320 {
5321 WCHAR buff[256];
5322
5323 if (!pbstrOut)
5324 return E_INVALIDARG;
5325
5326 sprintfW( buff, lpszFormat, dblIn );
5327 TRACE("created string %s\n", debugstr_w(buff));
5328 if (dwFlags & LOCALE_USE_NLS)
5329 {
5330 WCHAR numbuff[256];
5331
5332 /* Format the number for the locale */
5333 numbuff[0] = '\0';
5334 GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5335 buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
5336 TRACE("created NLS string %s\n", debugstr_w(numbuff));
5337 *pbstrOut = SysAllocString(numbuff);
5338 }
5339 else
5340 *pbstrOut = SysAllocString(buff);
5341 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5342 }
5343
5344 /******************************************************************************
5345 * VarBstrFromR4 (OLEAUT32.111)
5346 *
5347 * Convert a VT_R4 to a VT_BSTR.
5348 *
5349 * PARAMS
5350 * fltIn [I] Source
5351 * lcid [I] LCID for the conversion
5352 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5353 * pbstrOut [O] Destination
5354 *
5355 * RETURNS
5356 * Success: S_OK.
5357 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5358 * E_OUTOFMEMORY, if memory allocation fails.
5359 */
5360 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5361 {
5362 return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
5363 }
5364
5365 /******************************************************************************
5366 * VarBstrFromR8 (OLEAUT32.112)
5367 *
5368 * Convert a VT_R8 to a VT_BSTR.
5369 *
5370 * PARAMS
5371 * dblIn [I] Source
5372 * lcid [I] LCID for the conversion
5373 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5374 * pbstrOut [O] Destination
5375 *
5376 * RETURNS
5377 * Success: S_OK.
5378 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5379 * E_OUTOFMEMORY, if memory allocation fails.
5380 */
5381 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5382 {
5383 return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
5384 }
5385
5386 /******************************************************************************
5387 * VarBstrFromCy [OLEAUT32.113]
5388 *
5389 * Convert a VT_CY to a VT_BSTR.
5390 *
5391 * PARAMS
5392 * cyIn [I] Source
5393 * lcid [I] LCID for the conversion
5394 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5395 * pbstrOut [O] Destination
5396 *
5397 * RETURNS
5398 * Success: S_OK.
5399 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5400 * E_OUTOFMEMORY, if memory allocation fails.
5401 */
5402 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
5403 {
5404 WCHAR buff[256];
5405 double dblVal;
5406
5407 if (!pbstrOut)
5408 return E_INVALIDARG;
5409
5410 VarR8FromCy(cyIn, &dblVal);
5411 sprintfW(buff, szDoubleFormatW, dblVal);
5412
5413 if (dwFlags & LOCALE_USE_NLS)
5414 {
5415 WCHAR cybuff[256];
5416
5417 /* Format the currency for the locale */
5418 cybuff[0] = '\0';
5419 GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
5420 buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
5421 *pbstrOut = SysAllocString(cybuff);
5422 }
5423 else
5424 *pbstrOut = SysAllocString(buff);
5425
5426 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5427 }
5428
5429 /******************************************************************************
5430 * VarBstrFromDate [OLEAUT32.114]
5431 *
5432 * Convert a VT_DATE to a VT_BSTR.
5433 *
5434 * PARAMS
5435 * dateIn [I] Source
5436 * lcid [I] LCID for the conversion
5437 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5438 * pbstrOut [O] Destination
5439 *
5440 * RETURNS
5441 * Success: S_OK.
5442 * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
5443 * E_OUTOFMEMORY, if memory allocation fails.
5444 */
5445 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5446 {
5447 SYSTEMTIME st;
5448 DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
5449 WCHAR date[128], *time;
5450
5451 TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
5452
5453 #ifndef __REACTOS__ /*FIXME: no VariantTimeToSystemTime() yet */
5454 if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
5455 #else
5456 if (!pbstrOut)
5457 #endif
5458 return E_INVALIDARG;
5459
5460 *pbstrOut = NULL;
5461
5462 if (dwFlags & VAR_CALENDAR_THAI)
5463 st.wYear += 553; /* Use the Thai buddhist calendar year */
5464 else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
5465 FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
5466
5467 if (dwFlags & LOCALE_USE_NLS)
5468 dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
5469 else
5470 {
5471 double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
5472 double partial = dateIn - whole;
5473
5474 if (whole == 0.0)
5475 dwFlags |= VAR_TIMEVALUEONLY;
5476 else if (partial < 1e-12)
5477 dwFlags |= VAR_DATEVALUEONLY;
5478 }
5479
5480 if (dwFlags & VAR_TIMEVALUEONLY)
5481 date[0] = '\0';
5482 else
5483 if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
5484 sizeof(date)/sizeof(WCHAR)))
5485 return E_INVALIDARG;
5486
5487 if (!(dwFlags & VAR_DATEVALUEONLY))
5488 {
5489 time = date + strlenW(date);
5490 if (time != date)
5491 *time++ = ' ';
5492 if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
5493 sizeof(date)/sizeof(WCHAR)-(time-date)))
5494 return E_INVALIDARG;
5495 }
5496
5497 *pbstrOut = SysAllocString(date);
5498 if (*pbstrOut)
5499 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5500 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5501 }
5502
5503 /******************************************************************************
5504 * VarBstrFromBool (OLEAUT32.116)
5505 *
5506 * Convert a VT_BOOL to a VT_BSTR.
5507 *
5508 * PARAMS
5509 * boolIn [I] Source
5510 * lcid [I] LCID for the conversion
5511 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5512 * pbstrOut [O] Destination
5513 *
5514 * RETURNS
5515 * Success: S_OK.
5516 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5517 * E_OUTOFMEMORY, if memory allocation fails.
5518 *
5519 * NOTES
5520 * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
5521 * localised text of "True" or "False". To convert a bool into a
5522 * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
5523 */
5524 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5525 {
5526 WCHAR szBuff[64];
5527 DWORD dwResId = IDS_TRUE;
5528 LANGID langId;
5529
5530 TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn, lcid, dwFlags, pbstrOut);
5531
5532 if (!pbstrOut)
5533 return E_INVALIDARG;
5534
5535 /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
5536 * for variant formatting */
5537 switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
5538 {
5539 case VAR_BOOLONOFF:
5540 dwResId = IDS_ON;
5541 break;
5542 case VAR_BOOLYESNO:
5543 dwResId = IDS_YES;
5544 break;
5545 case VAR_LOCALBOOL:
5546 break;
5547 default:
5548 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
5549 }
5550
5551 lcid = ConvertDefaultLocale(lcid);
5552 langId = LANGIDFROMLCID(lcid);
5553 if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
5554 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5555
5556 if (boolIn == VARIANT_FALSE)
5557 dwResId++; /* Use negative form */
5558
5559 VarBstrFromBool_GetLocalised:
5560 if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
5561 {
5562 *pbstrOut = SysAllocString(szBuff);
5563 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5564 }
5565
5566 if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
5567 {
5568 langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
5569 goto VarBstrFromBool_GetLocalised;
5570 }
5571
5572 /* Should never get here */
5573 WARN("Failed to load bool text!\n");
5574 return E_OUTOFMEMORY;
5575 }
5576
5577 /******************************************************************************
5578 * VarBstrFromI1 (OLEAUT32.229)
5579 *
5580 * Convert a VT_I1 to a VT_BSTR.
5581 *
5582 * PARAMS
5583 * cIn [I] Source
5584 * lcid [I] LCID for the conversion
5585 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5586 * pbstrOut [O] Destination
5587 *
5588 * RETURNS
5589 * Success: S_OK.
5590 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5591 * E_OUTOFMEMORY, if memory allocation fails.
5592 */
5593 HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5594 {
5595 ULONG64 ul64 = cIn;
5596
5597 if (cIn < 0)
5598 {
5599 ul64 = -cIn;
5600 dwFlags |= VAR_NEGATIVE;
5601 }
5602 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5603 }
5604
5605 /******************************************************************************
5606 * VarBstrFromUI2 (OLEAUT32.230)
5607 *
5608 * Convert a VT_UI2 to a VT_BSTR.
5609 *
5610 * PARAMS
5611 * usIn [I] Source
5612 * lcid [I] LCID for the conversion
5613 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5614 * pbstrOut [O] Destination
5615 *
5616 * RETURNS
5617 * Success: S_OK.
5618 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5619 * E_OUTOFMEMORY, if memory allocation fails.
5620 */
5621 HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5622 {
5623 return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
5624 }
5625
5626 /******************************************************************************
5627 * VarBstrFromUI4 (OLEAUT32.231)
5628 *
5629 * Convert a VT_UI4 to a VT_BSTR.
5630 *
5631 * PARAMS
5632 * ulIn [I] Source
5633 * lcid [I] LCID for the conversion
5634 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5635 * pbstrOut [O] Destination
5636 *
5637 * RETURNS
5638 * Success: S_OK.
5639 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5640 * E_OUTOFMEMORY, if memory allocation fails.
5641 */
5642 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5643 {
5644 return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
5645 }
5646
5647 /******************************************************************************
5648 * VarBstrFromDec (OLEAUT32.232)
5649 *
5650 * Convert a VT_DECIMAL to a VT_BSTR.
5651 *
5652 * PARAMS
5653 * pDecIn [I] Source
5654 * lcid [I] LCID for the conversion
5655 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5656 * pbstrOut [O] Destination
5657 *
5658 * RETURNS
5659 * Success: S_OK.
5660 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5661 * E_OUTOFMEMORY, if memory allocation fails.
5662 */
5663 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_LO64 */
5664 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5665 {
5666 if (!pbstrOut)
5667 return E_INVALIDARG;
5668
5669 if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
5670 {
5671 WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
5672
5673 /* Create the basic number string */
5674 *szOut-- = '\0';
5675 szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
5676 if (DEC_SIGN(pDecIn))
5677 dwFlags |= VAR_NEGATIVE;
5678
5679 *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
5680 TRACE("returning %s\n", debugstr_w(*pbstrOut));
5681 return *pbstrOut ? S_OK : E_OUTOFMEMORY;
5682 }
5683 FIXME("semi-stub\n");
5684 return E_INVALIDARG;
5685 }
5686 #endif
5687
5688 /************************************************************************
5689 * VarBstrFromI8 (OLEAUT32.370)
5690 *
5691 * Convert a VT_I8 to a VT_BSTR.
5692 *
5693 * PARAMS
5694 * llIn [I] Source
5695 * lcid [I] LCID for the conversion
5696 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5697 * pbstrOut [O] Destination
5698 *
5699 * RETURNS
5700 * Success: S_OK.
5701 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5702 * E_OUTOFMEMORY, if memory allocation fails.
5703 */
5704 HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5705 {
5706 ULONG64 ul64 = llIn;
5707
5708 if (llIn < 0)
5709 {
5710 ul64 = -llIn;
5711 dwFlags |= VAR_NEGATIVE;
5712 }
5713 return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
5714 }
5715
5716 /************************************************************************
5717 * VarBstrFromUI8 (OLEAUT32.371)
5718 *
5719 * Convert a VT_UI8 to a VT_BSTR.
5720 *
5721 * PARAMS
5722 * ullIn [I] Source
5723 * lcid [I] LCID for the conversion
5724 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
5725 * pbstrOut [O] Destination
5726 *
5727 * RETURNS
5728 * Success: S_OK.
5729 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5730 * E_OUTOFMEMORY, if memory allocation fails.
5731 */
5732 HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
5733 {
5734 return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
5735 }
5736
5737 /**********************************************************************
5738 * VarBstrCat (OLEAUT32.313)
5739 *
5740 * Concatenate two BSTR values.
5741 *
5742 * PARAMS
5743 * pbstrLeft [I] Source
5744 * pbstrRight [I] Value to concatenate
5745 * pbstrOut [O] Destination
5746 *
5747 * RETURNS
5748 * Success: S_OK.
5749 * Failure: E_INVALIDARG, if pbstrOut is invalid.
5750 * E_OUTOFMEMORY, if memory allocation fails.
5751 */
5752 HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
5753 {
5754 unsigned int len;
5755
5756 if (!pbstrOut)
5757 return E_INVALIDARG;
5758
5759 len = pbstrLeft ? strlenW(pbstrLeft) : 0;
5760 if (pbstrRight)
5761 len += strlenW(pbstrRight);
5762
5763 *pbstrOut = SysAllocStringLen(NULL, len);
5764 if (!*pbstrOut)
5765 return E_OUTOFMEMORY;
5766
5767 (*pbstrOut)[0] = '\0';
5768
5769 if (pbstrLeft)
5770 strcpyW(*pbstrOut, pbstrLeft);
5771
5772 if (pbstrRight)
5773 strcatW(*pbstrOut, pbstrRight);
5774
5775 return S_OK;
5776 }
5777
5778 /**********************************************************************
5779 * VarBstrCmp (OLEAUT32.314)
5780 *
5781 * Compare two BSTR values.
5782 *
5783 * PARAMS
5784 * pbstrLeft [I] Source
5785 * pbstrRight [I] Value to compare
5786 * lcid [I] LCID for the comparason
5787 * dwFlags [I] Flags to pass directly to CompareStringW().
5788 *
5789 * RETURNS
5790 * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
5791 * than, equal to or greater than pbstrRight respectively.
5792 * VARCMP_NULL is returned if either string is NULL, unless both are NULL
5793 * in which case VARCMP_EQ is returned.
5794 */
5795 HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
5796 {
5797 if (!pbstrLeft)
5798 {
5799 if (!pbstrRight || !*pbstrRight)
5800 return VARCMP_EQ;
5801 return VARCMP_NULL;
5802 }
5803 else if (!pbstrRight)
5804 {
5805 if (!*pbstrLeft)
5806 return VARCMP_EQ;
5807 return VARCMP_NULL;
5808 }
5809
5810 return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
5811 }
5812
5813 /*
5814 * DATE
5815 */
5816
5817 /******************************************************************************
5818 * VarDateFromUI1 (OLEAUT32.88)
5819 *
5820 * Convert a VT_UI1 to a VT_DATE.
5821 *
5822 * PARAMS
5823 * bIn [I] Source
5824 * pdateOut [O] Destination
5825 *
5826 * RETURNS
5827 * S_OK.
5828 */
5829 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
5830 {
5831 return _VarDateFromUI1(bIn, pdateOut);
5832 }
5833
5834 /******************************************************************************
5835 * VarDateFromI2 (OLEAUT32.89)
5836 *
5837 * Convert a VT_I2 to a VT_DATE.
5838 *
5839 * PARAMS
5840 * sIn [I] Source
5841 * pdateOut [O] Destination
5842 *
5843 * RETURNS
5844 * S_OK.
5845 */
5846 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
5847 {
5848 return _VarDateFromI2(sIn, pdateOut);
5849 }
5850
5851 /******************************************************************************
5852 * VarDateFromI4 (OLEAUT32.90)
5853 *
5854 * Convert a VT_I4 to a VT_DATE.
5855 *
5856 * PARAMS
5857 * lIn [I] Source
5858 * pdateOut [O] Destination
5859 *
5860 * RETURNS
5861 * S_OK.
5862 */
5863 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
5864 {
5865 return _VarDateFromI4(lIn, pdateOut);
5866 }
5867
5868 /******************************************************************************
5869 * VarDateFromR4 (OLEAUT32.91)
5870 *
5871 * Convert a VT_R4 to a VT_DATE.
5872 *
5873 * PARAMS
5874 * fltIn [I] Source
5875 * pdateOut [O] Destination
5876 *
5877 * RETURNS
5878 * S_OK.
5879 */
5880 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
5881 {
5882 return _VarDateFromR4(fltIn, pdateOut);
5883 }
5884
5885 /******************************************************************************
5886 * VarDateFromR8 (OLEAUT32.92)
5887 *
5888 * Convert a VT_R8 to a VT_DATE.
5889 *
5890 * PARAMS
5891 * dblIn [I] Source
5892 * pdateOut [O] Destination
5893 *
5894 * RETURNS
5895 * S_OK.
5896 */
5897 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
5898 {
5899 return _VarDateFromR8(dblIn, pdateOut);
5900 }
5901
5902 /**********************************************************************
5903 * VarDateFromDisp (OLEAUT32.95)
5904 *
5905 * Convert a VT_DISPATCH to a VT_DATE.
5906 *
5907 * PARAMS
5908 * pdispIn [I] Source
5909 * lcid [I] LCID for conversion
5910 * pdateOut [O] Destination
5911 *
5912 * RETURNS
5913 * Success: S_OK.
5914 * Failure: E_INVALIDARG, if the source value is invalid
5915 * DISP_E_OVERFLOW, if the value will not fit in the destination
5916 * DISP_E_TYPEMISMATCH, if the type cannot be converted
5917 */
5918 HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
5919 {
5920 return _VarDateFromDisp(pdispIn, lcid, pdateOut);
5921 }
5922
5923 /******************************************************************************
5924 * VarDateFromBool (OLEAUT32.96)
5925 *
5926 * Convert a VT_BOOL to a VT_DATE.
5927 *
5928 * PARAMS
5929 * boolIn [I] Source
5930 * pdateOut [O] Destination
5931 *
5932 * RETURNS
5933 * S_OK.
5934 */
5935 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
5936 {
5937 return _VarDateFromBool(boolIn, pdateOut);
5938 }
5939
5940 /**********************************************************************
5941 * VarDateFromCy (OLEAUT32.93)
5942 *
5943 * Convert a VT_CY to a VT_DATE.
5944 *
5945 * PARAMS
5946 * lIn [I] Source
5947 * pdateOut [O] Destination
5948 *
5949 * RETURNS
5950 * S_OK.
5951 */
5952 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
5953 {
5954 return _VarDateFromCy(cyIn, pdateOut);
5955 }
5956
5957 /* Date string parsing */
5958 #define DP_TIMESEP 0x01 /* Time separator ( _must_ remain 0x1, used as a bitmask) */
5959 #define DP_DATESEP 0x02 /* Date separator */
5960 #define DP_MONTH 0x04 /* Month name */
5961 #define DP_AM 0x08 /* AM */
5962 #define DP_PM 0x10 /* PM */
5963
5964 typedef struct tagDATEPARSE
5965 {
5966 DWORD dwCount; /* Number of fields found so far (maximum 6) */
5967 DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
5968 DWORD dwFlags[6]; /* Flags for each field */
5969 DWORD dwValues[6]; /* Value of each field */
5970 } DATEPARSE;
5971
5972 #define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
5973
5974 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5975
5976 /* Determine if a day is valid in a given month of a given year */
5977 static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
5978 {
5979 static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
5980
5981 if (day && month && month < 13)
5982 {
5983 if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
5984 return TRUE;
5985 }
5986 return FALSE;
5987 }
5988
5989 /* Possible orders for 3 numbers making up a date */
5990 #define ORDER_MDY 0x01
5991 #define ORDER_YMD 0x02
5992 #define ORDER_YDM 0x04
5993 #define ORDER_DMY 0x08
5994 #define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
5995
5996 /* Determine a date for a particular locale, from 3 numbers */
5997 static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
5998 DWORD offset, SYSTEMTIME *st)
5999 {
6000 DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
6001
6002 if (!dp->dwCount)
6003 {
6004 v1 = 30; /* Default to (Variant) 0 date part */
6005 v2 = 12;
6006 v3 = 1899;
6007 goto VARIANT_MakeDate_OK;
6008 }
6009
6010 v1 = dp->dwValues[offset + 0];
6011 v2 = dp->dwValues[offset + 1];
6012 if (dp->dwCount == 2)
6013 {
6014 SYSTEMTIME current;
6015 GetSystemTime(&current);
6016 v3 = current.wYear;
6017 }
6018 else
6019 v3 = dp->dwValues[offset + 2];
6020
6021 TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
6022
6023 /* If one number must be a month (Because a month name was given), then only
6024 * consider orders with the month in that position.
6025 * If we took the current year as 'v3', then only allow a year in that position.
6026 */
6027 if (dp->dwFlags[offset + 0] & DP_MONTH)
6028 {
6029 dwAllOrders = ORDER_MDY;
6030 }
6031 else if (dp->dwFlags[offset + 1] & DP_MONTH)
6032 {
6033 dwAllOrders = ORDER_DMY;
6034 if (dp->dwCount > 2)
6035 dwAllOrders |= ORDER_YMD;
6036 }
6037 else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
6038 {
6039 dwAllOrders = ORDER_YDM;
6040 }
6041 else
6042 {
6043 dwAllOrders = ORDER_MDY|ORDER_DMY;
6044 if (dp->dwCount > 2)
6045 dwAllOrders |= (ORDER_YMD|ORDER_YDM);
6046 }
6047
6048 VARIANT_MakeDate_Start:
6049 TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
6050
6051 while (dwAllOrders)
6052 {
6053 DWORD dwTemp;
6054
6055 if (dwCount == 0)
6056 {
6057 /* First: Try the order given by iDate */
6058 switch (iDate)
6059 {
6060 case 0: dwTry = dwAllOrders & ORDER_MDY; break;
6061 case 1: dwTry = dwAllOrders & ORDER_DMY; break;
6062 default: dwTry = dwAllOrders & ORDER_YMD; break;
6063 }
6064 }
6065 else if (dwCount == 1)
6066 {
6067 /* Second: Try all the orders compatible with iDate */
6068 switch (iDate)
6069 {
6070 case 0: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
6071 case 1: dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
6072 default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
6073 }
6074 }
6075 else
6076 {
6077 /* Finally: Try any remaining orders */
6078 dwTry = dwAllOrders;
6079 }
6080
6081 TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
6082
6083 dwCount++;
6084 if (!dwTry)
6085 continue;
6086
6087 #define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
6088
6089 if (dwTry & ORDER_MDY)
6090 {
6091 if (VARIANT_IsValidMonthDay(v2,v1,v3))
6092 {
6093 DATE_SWAP(v1,v2);
6094 goto VARIANT_MakeDate_OK;
6095 }
6096 dwAllOrders &= ~ORDER_MDY;
6097 }
6098 if (dwTry & ORDER_YMD)
6099 {
6100 if (VARIANT_IsValidMonthDay(v3,v2,v1))
6101 {
6102 DATE_SWAP(v1,v3);
6103 goto VARIANT_MakeDate_OK;
6104 }
6105 dwAllOrders &= ~ORDER_YMD;
6106 }
6107 if (dwTry & ORDER_YDM)
6108 {
6109 if (VARIANT_IsValidMonthDay(v2,v3,v1))
6110 {
6111 DATE_SWAP(v1,v2);
6112 DATE_SWAP(v2,v3);
6113 goto VARIANT_MakeDate_OK;
6114 }
6115 dwAllOrders &= ~ORDER_YDM;
6116 }
6117 if (dwTry & ORDER_DMY)
6118 {
6119 if (VARIANT_IsValidMonthDay(v1,v2,v3))
6120 goto VARIANT_MakeDate_OK;
6121 dwAllOrders &= ~ORDER_DMY;
6122 }
6123 if (dwTry & ORDER_MYD)
6124 {
6125 /* Only occurs if we are trying a 2 year date as M/Y not D/M */
6126 if (VARIANT_IsValidMonthDay(v3,v1,v2))
6127 {
6128 DATE_SWAP(v1,v3);
6129 DATE_SWAP(v2,v3);
6130 goto VARIANT_MakeDate_OK;
6131 }
6132 dwAllOrders &= ~ORDER_MYD;
6133 }
6134 }
6135
6136 if (dp->dwCount == 2)
6137 {
6138 /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
6139 v3 = 1; /* 1st of the month */
6140 dwAllOrders = ORDER_YMD|ORDER_MYD;
6141 dp->dwCount = 0; /* Don't return to this code path again */
6142 dwCount = 0;
6143 goto VARIANT_MakeDate_Start;
6144 }
6145
6146 /* No valid dates were able to be constructed */
6147 return DISP_E_TYPEMISMATCH;
6148
6149 VARIANT_MakeDate_OK:
6150
6151 /* Check that the time part is ok */
6152 if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
6153 return DISP_E_TYPEMISMATCH;
6154
6155 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6156 if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
6157 st->wHour += 12;
6158 else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
6159 st->wHour = 0;
6160 TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
6161
6162 st->wDay = v1;
6163 st->wMonth = v2;
6164 /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
6165 * be retrieved from:
6166 * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
6167 * But Wine doesn't have/use that key as at the time of writing.
6168 */
6169 st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
6170 TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
6171 return S_OK;
6172 }
6173
6174 /******************************************************************************
6175 * VarDateFromStr [OLEAUT32.94]
6176 *
6177 * Convert a VT_BSTR to at VT_DATE.
6178 *
6179 * PARAMS
6180 * strIn [I] String to convert
6181 * lcid [I] Locale identifier for the conversion
6182 * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
6183 * pdateOut [O] Destination for the converted value
6184 *
6185 * RETURNS
6186 * Success: S_OK. pdateOut contains the converted value.
6187 * FAILURE: An HRESULT error code indicating the prolem.
6188 *
6189 * NOTES
6190 * Any date format that can be created using the date formats from lcid
6191 * (Either from kernel Nls functions, variant conversion or formatting) is a
6192 * valid input to this function. In addition, a few more esoteric formats are
6193 * also supported for compatibility with the native version. The date is
6194 * interpreted according to the date settings in the control panel, unless
6195 * the date is invalid in that format, in which the most compatible format
6196 * that produces a valid date will be used.
6197 */
6198 #ifndef __REACTOS__ /*FIXME: no SystemTimeToVariantTime() yet */
6199 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
6200 {
6201 static const USHORT ParseDateTokens[] =
6202 {
6203 LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
6204 LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
6205 LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
6206 LOCALE_SMONTHNAME13,
6207 LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
6208 LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
6209 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
6210 LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
6211 LOCALE_SABBREVMONTHNAME13,
6212 LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
6213 LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
6214 LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
6215 LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
6216 LOCALE_SABBREVDAYNAME7,
6217 LOCALE_S1159, LOCALE_S2359
6218 };
6219 static const BYTE ParseDateMonths[] =
6220 {
6221 1,2,3,4,5,6,7,8,9,10,11,12,13,
6222 1,2,3,4,5,6,7,8,9,10,11,12,13
6223 };
6224 size_t i;
6225 BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
6226 DATEPARSE dp;
6227 DWORD dwDateSeps = 0, iDate = 0;
6228 HRESULT hRet = S_OK;
6229
6230 if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
6231 (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
6232 return E_INVALIDARG;
6233
6234 if (!strIn)
6235 return DISP_E_TYPEMISMATCH;
6236
6237 *pdateOut = 0.0;
6238
6239 TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
6240
6241 memset(&dp, 0, sizeof(dp));
6242
6243 GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
6244 (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
6245 TRACE("iDate is %ld\n", iDate);
6246
6247 /* Get the month/day/am/pm tokens for this locale */
6248 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6249 {
6250 WCHAR buff[128];
6251 LCTYPE lctype = ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
6252
6253 /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
6254 * GetAltMonthNames(). We should really cache these strings too.
6255 */
6256 buff[0] = '\0';
6257 GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
6258 tokens[i] = SysAllocString(buff);
6259 TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
6260 }
6261
6262 /* Parse the string into our structure */
6263 while (*strIn)
6264 {
6265 if (dp.dwCount > 6)
6266 break;
6267
6268 if (isdigitW(*strIn))
6269 {
6270 dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
6271 dp.dwCount++;
6272 strIn--;
6273 }
6274 else if (isalpha(*strIn))
6275 {
6276 BOOL bFound = FALSE;
6277
6278 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6279 {
6280 DWORD dwLen = strlenW(tokens[i]);
6281 if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
6282 {
6283 if (i <= 25)
6284 {
6285 dp.dwValues[dp.dwCount] = ParseDateMonths[i];
6286 dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
6287 dp.dwCount++;
6288 }
6289 else if (i > 39)
6290 {
6291 if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
6292 hRet = DISP_E_TYPEMISMATCH;
6293 else
6294 {
6295 dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
6296 dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
6297 }
6298 }
6299 strIn += (dwLen - 1);
6300 bFound = TRUE;
6301 break;
6302 }
6303 }
6304
6305 if (!bFound)
6306 {
6307 if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
6308 (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6309 {
6310 /* Special case - 'a' and 'p' are recognised as short for am/pm */
6311 if (*strIn == 'a' || *strIn == 'A')
6312 {
6313 dp.dwFlags[dp.dwCount - 1] |= DP_AM;
6314 dp.dwParseFlags |= DP_AM;
6315 }
6316 else
6317 {
6318 dp.dwFlags[dp.dwCount - 1] |= DP_PM;
6319 dp.dwParseFlags |= DP_PM;
6320 }
6321 strIn++;
6322 }
6323 else
6324 {
6325 TRACE("No matching token for %s\n", debugstr_w(strIn));
6326 hRet = DISP_E_TYPEMISMATCH;
6327 break;
6328 }
6329 }
6330 }
6331 else if (*strIn == ':' || *strIn == '.')
6332 {
6333 if (!dp.dwCount || !strIn[1])
6334 hRet = DISP_E_TYPEMISMATCH;
6335 else
6336 dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
6337 }
6338 else if (*strIn == '-' || *strIn == '/')
6339 {
6340 dwDateSeps++;
6341 if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
6342 hRet = DISP_E_TYPEMISMATCH;
6343 else
6344 dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
6345 }
6346 else if (*strIn == ',' || isspaceW(*strIn))
6347 {
6348 if (*strIn == ',' && !strIn[1])
6349 hRet = DISP_E_TYPEMISMATCH;
6350 }
6351 else
6352 {
6353 hRet = DISP_E_TYPEMISMATCH;
6354 }
6355 strIn++;
6356 }
6357
6358 if (!dp.dwCount || dp.dwCount > 6 ||
6359 (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
6360 hRet = DISP_E_TYPEMISMATCH;
6361
6362 if (SUCCEEDED(hRet))
6363 {
6364 SYSTEMTIME st;
6365 DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
6366
6367 st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
6368
6369 /* Figure out which numbers correspond to which fields.
6370 *
6371 * This switch statement works based on the fact that native interprets any
6372 * fields that are not joined with a time separator ('.' or ':') as date
6373 * fields. Thus we construct a value from 0-32 where each set bit indicates
6374 * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
6375 * For valid permutations, we set dwOffset to point to the first date field
6376 * and shorten dp.dwCount by the number of time fields found. The real
6377 * magic here occurs in VARIANT_MakeDate() above, where we determine what
6378 * each date number must represent in the context of iDate.
6379 */
6380 TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
6381
6382 switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
6383 {
6384 case 0x1: /* TT TTDD TTDDD */
6385 if (dp.dwCount > 3 &&
6386 ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
6387 (dp.dwFlags[4] & (DP_AM|DP_PM))))
6388 hRet = DISP_E_TYPEMISMATCH;
6389 else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
6390 hRet = DISP_E_TYPEMISMATCH;
6391 st.wHour = dp.dwValues[0];
6392 st.wMinute = dp.dwValues[1];
6393 dp.dwCount -= 2;
6394 dwOffset = 2;
6395 break;
6396
6397 case 0x3: /* TTT TTTDD TTTDDD */
6398 if (dp.dwCount > 4 &&
6399 ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
6400 (dp.dwFlags[5] & (DP_AM|DP_PM))))
6401 hRet = DISP_E_TYPEMISMATCH;
6402 else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
6403 hRet = DISP_E_TYPEMISMATCH;
6404 st.wHour = dp.dwValues[0];
6405 st.wMinute = dp.dwValues[1];
6406 st.wSecond = dp.dwValues[2];
6407 dwOffset = 3;
6408 dp.dwCount -= 3;
6409 break;
6410
6411 case 0x4: /* DDTT */
6412 if (dp.dwCount != 4 ||
6413 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6414 hRet = DISP_E_TYPEMISMATCH;
6415
6416 st.wHour = dp.dwValues[2];
6417 st.wMinute = dp.dwValues[3];
6418 dp.dwCount -= 2;
6419 break;
6420
6421 case 0x0: /* T DD DDD TDDD TDDD */
6422 if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
6423 {
6424 st.wHour = dp.dwValues[0]; /* T */
6425 dp.dwCount = 0;
6426 break;
6427 }
6428 else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
6429 {
6430 hRet = DISP_E_TYPEMISMATCH;
6431 }
6432 else if (dp.dwCount == 3)
6433 {
6434 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
6435 {
6436 dp.dwCount = 2;
6437 st.wHour = dp.dwValues[0];
6438 dwOffset = 1;
6439 break;
6440 }
6441 if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
6442 {
6443 dp.dwCount = 2;
6444 st.wHour = dp.dwValues[2];
6445 break;
6446 }
6447 else if (dp.dwParseFlags & (DP_AM|DP_PM))
6448 hRet = DISP_E_TYPEMISMATCH;
6449 }
6450 else if (dp.dwCount == 4)
6451 {
6452 dp.dwCount = 3;
6453 if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
6454 {
6455 st.wHour = dp.dwValues[0];
6456 dwOffset = 1;
6457 }
6458 else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
6459 {
6460 st.wHour = dp.dwValues[3];
6461 }
6462 else
6463 hRet = DISP_E_TYPEMISMATCH;
6464 break;
6465 }
6466 /* .. fall through .. */
6467
6468 case 0x8: /* DDDTT */
6469 if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
6470 (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
6471 (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
6472 dp.dwCount == 4 || dp.dwCount == 6)
6473 hRet = DISP_E_TYPEMISMATCH;
6474 st.wHour = dp.dwValues[3];
6475 st.wMinute = dp.dwValues[4];
6476 if (dp.dwCount == 5)
6477 dp.dwCount -= 2;
6478 break;
6479
6480 case 0xC: /* DDTTT */
6481 if (dp.dwCount != 5 ||
6482 (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
6483 hRet = DISP_E_TYPEMISMATCH;
6484 st.wHour = dp.dwValues[2];
6485 st.wMinute = dp.dwValues[3];
6486 st.wSecond = dp.dwValues[4];
6487 dp.dwCount -= 3;
6488 break;
6489
6490 case 0x18: /* DDDTTT */
6491 if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
6492 (dp.dwFlags[2] & (DP_AM|DP_PM)))
6493 hRet = DISP_E_TYPEMISMATCH;
6494 st.wHour = dp.dwValues[3];
6495 st.wMinute = dp.dwValues[4];
6496 st.wSecond = dp.dwValues[5];
6497 dp.dwCount -= 3;
6498 break;
6499
6500 default:
6501 hRet = DISP_E_TYPEMISMATCH;
6502 break;
6503 }
6504
6505 if (SUCCEEDED(hRet))
6506 {
6507 hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
6508
6509 if (dwFlags & VAR_TIMEVALUEONLY)
6510 {
6511 st.wYear = 1899;
6512 st.wMonth = 12;
6513 st.wDay = 30;
6514 }
6515 else if (dwFlags & VAR_DATEVALUEONLY)
6516 st.wHour = st.wMinute = st.wSecond = 0;
6517
6518 /* Finally, convert the value to a VT_DATE */
6519 if (SUCCEEDED(hRet))
6520 hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
6521 }
6522 }
6523
6524 for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
6525 SysFreeString(tokens[i]);
6526 return hRet;
6527 }
6528 #endif
6529
6530 /******************************************************************************
6531 * VarDateFromI1 (OLEAUT32.221)
6532 *
6533 * Convert a VT_I1 to a VT_DATE.
6534 *
6535 * PARAMS
6536 * cIn [I] Source
6537 * pdateOut [O] Destination
6538 *
6539 * RETURNS
6540 * S_OK.
6541 */
6542 HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
6543 {
6544 return _VarDateFromI1(cIn, pdateOut);
6545 }
6546
6547 /******************************************************************************
6548 * VarDateFromUI2 (OLEAUT32.222)
6549 *
6550 * Convert a VT_UI2 to a VT_DATE.
6551 *
6552 * PARAMS
6553 * uiIn [I] Source
6554 * pdateOut [O] Destination
6555 *
6556 * RETURNS
6557 * S_OK.
6558 */
6559 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
6560 {
6561 return _VarDateFromUI2(uiIn, pdateOut);
6562 }
6563
6564 /******************************************************************************
6565 * VarDateFromUI4 (OLEAUT32.223)
6566 *
6567 * Convert a VT_UI4 to a VT_DATE.
6568 *
6569 * PARAMS
6570 * ulIn [I] Source
6571 * pdateOut [O] Destination
6572 *
6573 * RETURNS
6574 * S_OK.
6575 */
6576 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
6577 {
6578 return _VarDateFromUI4(ulIn, pdateOut);
6579 }
6580
6581 /**********************************************************************
6582 * VarDateFromDec (OLEAUT32.224)
6583 *
6584 * Convert a VT_DECIMAL to a VT_DATE.
6585 *
6586 * PARAMS
6587 * pdecIn [I] Source
6588 * pdateOut [O] Destination
6589 *
6590 * RETURNS
6591 * S_OK.
6592 */
6593 #ifndef __REACTOS__ /*FIXME: problems with MinGW and DEC_MID32 */
6594 HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
6595 {
6596 return _VarDateFromDec(pdecIn, pdateOut);
6597 }
6598 #endif
6599
6600 /******************************************************************************
6601 * VarDateFromI8 (OLEAUT32.364)
6602 *
6603 * Convert a VT_I8 to a VT_DATE.
6604 *
6605 * PARAMS
6606 * llIn [I] Source
6607 * pdateOut [O] Destination
6608 *
6609 * RETURNS
6610 * Success: S_OK.
6611 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6612 */
6613 HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
6614 {
6615 return _VarDateFromI8(llIn, pdateOut);
6616 }
6617
6618 /******************************************************************************
6619 * VarDateFromUI8 (OLEAUT32.365)
6620 *
6621 * Convert a VT_UI8 to a VT_DATE.
6622 *
6623 * PARAMS
6624 * ullIn [I] Source
6625 * pdateOut [O] Destination
6626 *
6627 * RETURNS
6628 * Success: S_OK.
6629 * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
6630 */
6631 HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
6632 {
6633 return _VarDateFromUI8(ullIn, pdateOut);
6634 }