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