source: trunk/src/oleaut32/variant.cpp@ 4278

Last change on this file since 4278 was 4278, checked in by davidr, 25 years ago

Updates from Wine

File size: 103.5 KB
Line 
1/* $Id: variant.cpp,v 1.3 2000-09-17 22:31:42 davidr Exp $ */
2/*
3 * VARIANT
4 *
5 * Copyright 1998 Jean-Claude Cote
6 *
7 * Copyright 1999 Sander van Leeuwen (WINE OS/2 Port 990815)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 * NOTES
12 * This implements the low-level and hi-level APIs for manipulating VARIANTs.
13 * The low-level APIs are used to do data coercion between different data types.
14 * The hi-level APIs are built on top of these low-level APIs and handle
15 * initialization, copying, destroying and changing the type of VARIANTs.
16 *
17 * TODO:
18 * - The Variant APIs are do not support international languages, currency
19 * types, number formating and calendar. They only support U.S. English format.
20 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
21 * The prototypes for these are commented out in the oleauto.h file. They need
22 * to be implemented and cases need to be added to the switches of the existing APIs.
23 * - The parsing of date for the VarDateFromStr is not complete.
24 * - The date manipulations do not support date prior to 1900.
25 * - The parsing does not accept has many formats has the Windows implementation.
26 */
27
28#include "oleaut32.h"
29#include "windef.h"
30#include "oleauto.h"
31#include "heap.h"
32#include "debugtools.h"
33#include "winerror.h"
34#include "parsedt.h"
35
36DEFAULT_DEBUG_CHANNEL(ole)
37
38#include <string.h>
39#include <stdlib.h>
40#include <math.h>
41#include <time.h>
42
43//#ifdef HAVE_FLOAT_H
44# include <float.h>
45//#endif
46
47#ifndef FLT_MAX
48# ifdef MAXFLOAT
49# define FLT_MAX MAXFLOAT
50# else
51# error "Can't find #define for MAXFLOAT/FLT_MAX"
52# endif
53#endif
54
55#undef CHAR_MAX
56#undef CHAR_MIN
57static const char CHAR_MAX = 127;
58static const char CHAR_MIN = -128;
59static const BYTE UI1_MAX = 255;
60static const BYTE UI1_MIN = 0;
61static const unsigned short UI2_MAX = 65535;
62static const unsigned short UI2_MIN = 0;
63static const short I2_MAX = 32767;
64static const short I2_MIN = -32768;
65static const unsigned long UI4_MAX = 4294967295U;
66static const unsigned long UI4_MIN = 0;
67static const long I4_MAX = 2147483647;
68static const long I4_MIN = -(2147483648U);
69static const DATE DATE_MIN = -657434;
70static const DATE DATE_MAX = 2958465;
71
72
73/* This mask is used to set a flag in wReserved1 of
74 * the VARIANTARG structure. The flag indicates if
75 * the API function is using an inner variant or not.
76 */
77#define PROCESSING_INNER_VARIANT 0x0001
78
79/* General use buffer.
80 */
81#define BUFFER_MAX 1024
82static char pBuffer[BUFFER_MAX];
83
84/*
85 * Note a leap year is one that is a multiple of 4
86 * but not of a 100. Except if it is a multiple of
87 * 400 then it is a leap year.
88 */
89/* According to postgeSQL date parsing functions there is
90 * a leap year when this expression is true.
91 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
92 * So according to this there is 365.2515 days in one year.
93 * One + every four years: 1/4 -> 365.25
94 * One - every 100 years: 1/100 -> 365.001
95 * One + every 400 years: 1/400 -> 365.0025
96 */
97static const double DAYS_IN_ONE_YEAR = 365.2515;
98
99
100
101/******************************************************************************
102 * DateTimeStringToTm [INTERNAL]
103 *
104 * Converts a string representation of a date and/or time to a tm structure.
105 *
106 * Note this function uses the postgresql date parsing functions found
107 * in the parsedt.c file.
108 *
109 * Returns TRUE if successfull.
110 *
111 * Note: This function does not parse the day of the week,
112 * daylight savings time. It will only fill the followin fields in
113 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
114 *
115 ******************************************************************************/
116static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
117{
118 BOOL res = FALSE;
119 double fsec;
120 int tzp;
121 int dtype;
122 int nf;
123 char *field[MAXDATEFIELDS];
124 int ftype[MAXDATEFIELDS];
125 char lowstr[MAXDATELEN + 1];
126 char* strDateTime = NULL;
127
128 /* Convert the string to ASCII since this is the only format
129 * postgesql can handle.
130 */
131 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
132
133 if( strDateTime != NULL )
134 {
135 /* Make sure we don't go over the maximum length
136 * accepted by postgesql.
137 */
138 if( strlen( strDateTime ) <= MAXDATELEN )
139 {
140 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
141 {
142 if( lcid & VAR_DATEVALUEONLY )
143 {
144 /* Get the date information.
145 * It returns 0 if date information was
146 * present and 1 if only time information was present.
147 * -1 if an error occures.
148 */
149 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
150 {
151 /* Eliminate the time information since we
152 * were asked to get date information only.
153 */
154 pTm->tm_sec = 0;
155 pTm->tm_min = 0;
156 pTm->tm_hour = 0;
157 res = TRUE;
158 }
159 }
160 if( lcid & VAR_TIMEVALUEONLY )
161 {
162 /* Get time information only.
163 */
164 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
165 {
166 res = TRUE;
167 }
168 }
169 else
170 {
171 /* Get both date and time information.
172 * It returns 0 if date information was
173 * present and 1 if only time information was present.
174 * -1 if an error occures.
175 */
176 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
177 {
178 res = TRUE;
179 }
180 }
181 }
182 }
183 HeapFree( GetProcessHeap(), 0, strDateTime );
184 }
185
186 return res;
187}
188
189
190
191
192
193
194/******************************************************************************
195 * TmToDATE [INTERNAL]
196 *
197 * The date is implemented using an 8 byte floating-point number.
198 * Days are represented by whole numbers increments starting with 0.00 has
199 * being December 30 1899, midnight.
200 * The hours are expressed as the fractional part of the number.
201 * December 30 1899 at midnight = 0.00
202 * January 1 1900 at midnight = 2.00
203 * January 4 1900 at 6 AM = 5.25
204 * January 4 1900 at noon = 5.50
205 * December 29 1899 at midnight = -1.00
206 * December 18 1899 at midnight = -12.00
207 * December 18 1899 at 6AM = -12.25
208 * December 18 1899 at 6PM = -12.75
209 * December 19 1899 at midnight = -11.00
210 * The tm structure is as follows:
211 * struct tm {
212 * int tm_sec; seconds after the minute - [0,59]
213 * int tm_min; minutes after the hour - [0,59]
214 * int tm_hour; hours since midnight - [0,23]
215 * int tm_mday; day of the month - [1,31]
216 * int tm_mon; months since January - [0,11]
217 * int tm_year; years
218 * int tm_wday; days since Sunday - [0,6]
219 * int tm_yday; days since January 1 - [0,365]
220 * int tm_isdst; daylight savings time flag
221 * };
222 *
223 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
224 * and tm_isdst fields of the tm structure. And only converts years
225 * after 1900.
226 *
227 * Returns TRUE if successfull.
228 */
229static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
230{
231 if( (pTm->tm_year - 1900) >= 0 )
232 {
233 int leapYear = 0;
234
235 /* Start at 1. This is the way DATE is defined.
236 * January 1, 1900 at Midnight is 1.00.
237 * January 1, 1900 at 6AM is 1.25.
238 * and so on.
239 */
240 *pDateOut = 1;
241
242 /* Add the number of days corresponding to
243 * tm_year.
244 */
245 *pDateOut += (pTm->tm_year - 1900) * 365;
246
247 /* Add the leap days in the previous years between now and 1900.
248 * Note a leap year is one that is a multiple of 4
249 * but not of a 100. Except if it is a multiple of
250 * 400 then it is a leap year.
251 */
252 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
253 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
254 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
255
256 /* Set the leap year flag if the
257 * current year specified by tm_year is a
258 * leap year. This will be used to add a day
259 * to the day count.
260 */
261 if( isleap( pTm->tm_year ) )
262 leapYear = 1;
263
264 /* Add the number of days corresponding to
265 * the month.
266 */
267 switch( pTm->tm_mon )
268 {
269 case 2:
270 *pDateOut += 31;
271 break;
272 case 3:
273 *pDateOut += (59 + leapYear);
274 break;
275 case 4:
276 *pDateOut += (90 + leapYear);
277 break;
278 case 5:
279 *pDateOut += (120 + leapYear);
280 break;
281 case 6:
282 *pDateOut += (151 + leapYear);
283 break;
284 case 7:
285 *pDateOut += (181 + leapYear);
286 break;
287 case 8:
288 *pDateOut += (212 + leapYear);
289 break;
290 case 9:
291 *pDateOut += (243 + leapYear);
292 break;
293 case 10:
294 *pDateOut += (273 + leapYear);
295 break;
296 case 11:
297 *pDateOut += (304 + leapYear);
298 break;
299 case 12:
300 *pDateOut += (334 + leapYear);
301 break;
302 }
303 /* Add the number of days in this month.
304 */
305 *pDateOut += pTm->tm_mday;
306
307 /* Add the number of seconds, minutes, and hours
308 * to the DATE. Note these are the fracionnal part
309 * of the DATE so seconds / number of seconds in a day.
310 */
311 *pDateOut += pTm->tm_hour / 24.0;
312 *pDateOut += pTm->tm_min / 1440.0;
313 *pDateOut += pTm->tm_sec / 86400.0;
314 return TRUE;
315 }
316 return FALSE;
317}
318
319/******************************************************************************
320 * DateToTm [INTERNAL]
321 *
322 * This function converst a windows DATE to a tm structure.
323 *
324 * It does not fill all the fields of the tm structure.
325 * Here is a list of the fields that are filled:
326 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
327 *
328 * Note this function does not support dates before the January 1, 1900
329 * or ( dateIn < 2.0 ).
330 *
331 * Returns TRUE if successfull.
332 */
333static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
334{
335 /* Do not process dates smaller than January 1, 1900.
336 * Which corresponds to 2.0 in the windows DATE format.
337 */
338 if( dateIn >= 2.0 )
339 {
340 double decimalPart = 0.0;
341 double wholePart = 0.0;
342
343 memset(pTm,0,sizeof(*pTm));
344
345 /* Because of the nature of DATE format witch
346 * associates 2.0 to January 1, 1900. We will
347 * remove 1.0 from the whole part of the DATE
348 * so that in the following code 1.0
349 * will correspond to January 1, 1900.
350 * This simplyfies the processing of the DATE value.
351 */
352 dateIn -= 1.0;
353
354 wholePart = (double) floor( dateIn );
355 decimalPart = fmod( dateIn, wholePart );
356
357 if( !(lcid & VAR_TIMEVALUEONLY) )
358 {
359 int nDay = 0;
360 int leapYear = 0;
361 double yearsSince1900 = 0;
362 /* Start at 1900, this where the DATE time 0.0 starts.
363 */
364 pTm->tm_year = 1900;
365 /* find in what year the day in the "wholePart" falls into.
366 * add the value to the year field.
367 */
368 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
369 pTm->tm_year += yearsSince1900;
370 /* determine if this is a leap year.
371 */
372 if( isleap( pTm->tm_year ) )
373 {
374 leapYear = 1;
375 wholePart++;
376 }
377
378 /* find what day of that year does the "wholePart" corresponds to.
379 * Note: nDay is in [1-366] format
380 */
381 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
382 /* Set the tm_yday value.
383 * Note: The day is must be converted from [1-366] to [0-365]
384 */
385 /*pTm->tm_yday = nDay - 1;*/
386 /* find which mount this day corresponds to.
387 */
388 if( nDay <= 31 )
389 {
390 pTm->tm_mday = nDay;
391 pTm->tm_mon = 0;
392 }
393 else if( nDay <= ( 59 + leapYear ) )
394 {
395 pTm->tm_mday = nDay - 31;
396 pTm->tm_mon = 1;
397 }
398 else if( nDay <= ( 90 + leapYear ) )
399 {
400 pTm->tm_mday = nDay - ( 59 + leapYear );
401 pTm->tm_mon = 2;
402 }
403 else if( nDay <= ( 120 + leapYear ) )
404 {
405 pTm->tm_mday = nDay - ( 90 + leapYear );
406 pTm->tm_mon = 3;
407 }
408 else if( nDay <= ( 151 + leapYear ) )
409 {
410 pTm->tm_mday = nDay - ( 120 + leapYear );
411 pTm->tm_mon = 4;
412 }
413 else if( nDay <= ( 181 + leapYear ) )
414 {
415 pTm->tm_mday = nDay - ( 151 + leapYear );
416 pTm->tm_mon = 5;
417 }
418 else if( nDay <= ( 212 + leapYear ) )
419 {
420 pTm->tm_mday = nDay - ( 181 + leapYear );
421 pTm->tm_mon = 6;
422 }
423 else if( nDay <= ( 243 + leapYear ) )
424 {
425 pTm->tm_mday = nDay - ( 212 + leapYear );
426 pTm->tm_mon = 7;
427 }
428 else if( nDay <= ( 273 + leapYear ) )
429 {
430 pTm->tm_mday = nDay - ( 243 + leapYear );
431 pTm->tm_mon = 8;
432 }
433 else if( nDay <= ( 304 + leapYear ) )
434 {
435 pTm->tm_mday = nDay - ( 273 + leapYear );
436 pTm->tm_mon = 9;
437 }
438 else if( nDay <= ( 334 + leapYear ) )
439 {
440 pTm->tm_mday = nDay - ( 304 + leapYear );
441 pTm->tm_mon = 10;
442 }
443 else if( nDay <= ( 365 + leapYear ) )
444 {
445 pTm->tm_mday = nDay - ( 334 + leapYear );
446 pTm->tm_mon = 11;
447 }
448 }
449 if( !(lcid & VAR_DATEVALUEONLY) )
450 {
451 /* find the number of seconds in this day.
452 * fractional part times, hours, minutes, seconds.
453 */
454 pTm->tm_hour = (int) ( decimalPart * 24 );
455 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
456 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
457 }
458 return TRUE;
459 }
460 return FALSE;
461}
462
463
464
465/******************************************************************************
466 * SizeOfVariantData [INTERNAL]
467 *
468 * This function finds the size of the data referenced by a Variant based
469 * the type "vt" of the Variant.
470 */
471static int SizeOfVariantData( VARIANT* parg )
472{
473 int size = 0;
474 switch( parg->vt & VT_TYPEMASK )
475 {
476 case( VT_I2 ):
477 size = sizeof(short);
478 break;
479 case( VT_INT ):
480 size = sizeof(int);
481 break;
482 case( VT_I4 ):
483 size = sizeof(long);
484 break;
485 case( VT_UI1 ):
486 size = sizeof(BYTE);
487 break;
488 case( VT_UI2 ):
489 size = sizeof(unsigned short);
490 break;
491 case( VT_UINT ):
492 size = sizeof(unsigned int);
493 break;
494 case( VT_UI4 ):
495 size = sizeof(unsigned long);
496 break;
497 case( VT_R4 ):
498 size = sizeof(float);
499 break;
500 case( VT_R8 ):
501 size = sizeof(double);
502 break;
503 case( VT_DATE ):
504 size = sizeof(DATE);
505 break;
506 case( VT_BOOL ):
507 size = sizeof(VARIANT_BOOL);
508 break;
509 case( VT_BSTR ):
510 size = sizeof(void*);
511 break;
512 case( VT_CY ):
513 case( VT_DISPATCH ):
514 case( VT_UNKNOWN ):
515 case( VT_DECIMAL ):
516 default:
517 FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
518 break;
519 }
520
521 return size;
522}
523/******************************************************************************
524 * StringDupAtoBstr [INTERNAL]
525 *
526 */
527static BSTR StringDupAtoBstr( char* strIn )
528{
529 BSTR bstr = NULL;
530 OLECHAR* pNewString = NULL;
531 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
532 bstr = SysAllocString( pNewString );
533 HeapFree( GetProcessHeap(), 0, pNewString );
534 return bstr;
535}
536
537/******************************************************************************
538 * round [INTERNAL]
539 *
540 * Round the double value to the nearest integer value.
541 */
542static double round( double d )
543{
544 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
545 BOOL bEvenNumber = FALSE;
546 int nSign = 0;
547
548 /* Save the sign of the number
549 */
550 nSign = (d >= 0.0) ? 1 : -1;
551 d = fabs( d );
552
553 /* Remove the decimals.
554 */
555 integerValue = floor( d );
556
557 /* Set the Even flag. This is used to round the number when
558 * the decimals are exactly 1/2. If the integer part is
559 * odd the number is rounded up. If the integer part
560 * is even the number is rounded down. Using this method
561 * numbers are rounded up|down half the time.
562 */
563 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
564
565 /* Remove the integral part of the number.
566 */
567 decimals = d - integerValue;
568
569 /* Note: Ceil returns the smallest integer that is greater that x.
570 * and floor returns the largest integer that is less than or equal to x.
571 */
572 if( decimals > 0.5 )
573 {
574 /* If the decimal part is greater than 1/2
575 */
576 roundedValue = ceil( d );
577 }
578 else if( decimals < 0.5 )
579 {
580 /* If the decimal part is smaller than 1/2
581 */
582 roundedValue = floor( d );
583 }
584 else
585 {
586 /* the decimals are exactly 1/2 so round according to
587 * the bEvenNumber flag.
588 */
589 if( bEvenNumber )
590 {
591 roundedValue = floor( d );
592 }
593 else
594 {
595 roundedValue = ceil( d );
596 }
597 }
598
599 return roundedValue * nSign;
600}
601
602/******************************************************************************
603 * RemoveCharacterFromString [INTERNAL]
604 *
605 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
606 */
607static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
608{
609 LPSTR pNewString = NULL;
610 LPSTR strToken = NULL;
611
612
613 /* Check if we have a valid argument
614 */
615 if( str != NULL )
616 {
617 pNewString = strdup( str );
618 str[0] = '\0';
619 strToken = strtok( pNewString, strOfCharToRemove );
620 while( strToken != NULL ) {
621 strcat( str, strToken );
622 strToken = strtok( NULL, strOfCharToRemove );
623 }
624 free( pNewString );
625 }
626 return;
627}
628
629/******************************************************************************
630 * GetValidRealString [INTERNAL]
631 *
632 * Checks if the string is of proper format to be converted to a real value.
633 */
634static BOOL IsValidRealString( LPSTR strRealString )
635{
636 /* Real values that have a decimal point are required to either have
637 * digits before or after the decimal point. We will assume that
638 * we do not have any digits at either position. If we do encounter
639 * some we will disable this flag.
640 */
641 BOOL bDigitsRequired = TRUE;
642 /* Processed fields in the string representation of the real number.
643 */
644 BOOL bWhiteSpaceProcessed = FALSE;
645 BOOL bFirstSignProcessed = FALSE;
646 BOOL bFirstDigitsProcessed = FALSE;
647 BOOL bDecimalPointProcessed = FALSE;
648 BOOL bSecondDigitsProcessed = FALSE;
649 BOOL bExponentProcessed = FALSE;
650 BOOL bSecondSignProcessed = FALSE;
651 BOOL bThirdDigitsProcessed = FALSE;
652 /* Assume string parameter "strRealString" is valid and try to disprove it.
653 */
654 BOOL bValidRealString = TRUE;
655
656 /* Used to count the number of tokens in the "strRealString".
657 */
658 LPSTR strToken = NULL;
659 int nTokens = 0;
660 LPSTR pChar = NULL;
661
662 /* Check if we have a valid argument
663 */
664 if( strRealString == NULL )
665 {
666 bValidRealString = FALSE;
667 }
668
669 if( bValidRealString == TRUE )
670 {
671 /* Make sure we only have ONE token in the string.
672 */
673 strToken = strtok( strRealString, " " );
674 while( strToken != NULL ) {
675 nTokens++;
676 strToken = strtok( NULL, " " );
677 }
678
679 if( nTokens != 1 )
680 {
681 bValidRealString = FALSE;
682 }
683 }
684
685
686 /* Make sure this token contains only valid characters.
687 * The string argument to atof has the following form:
688 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
689 * Whitespace consists of space and|or <TAB> characters, which are ignored.
690 * Sign is either plus '+' or minus '-'.
691 * Digits are one or more decimal digits.
692 * Note: If no digits appear before the decimal point, at least one must
693 * appear after the decimal point.
694 * The decimal digits may be followed by an exponent.
695 * An Exponent consists of an introductory letter ( D, d, E, or e) and
696 * an optionally signed decimal integer.
697 */
698 pChar = strRealString;
699 while( bValidRealString == TRUE && *pChar != '\0' )
700 {
701 switch( *pChar )
702 {
703 /* If whitespace...
704 */
705 case ' ':
706 case '\t':
707 if( bWhiteSpaceProcessed ||
708 bFirstSignProcessed ||
709 bFirstDigitsProcessed ||
710 bDecimalPointProcessed ||
711 bSecondDigitsProcessed ||
712 bExponentProcessed ||
713 bSecondSignProcessed ||
714 bThirdDigitsProcessed )
715 {
716 bValidRealString = FALSE;
717 }
718 break;
719 /* If sign...
720 */
721 case '+':
722 case '-':
723 if( bFirstSignProcessed == FALSE )
724 {
725 if( bFirstDigitsProcessed ||
726 bDecimalPointProcessed ||
727 bSecondDigitsProcessed ||
728 bExponentProcessed ||
729 bSecondSignProcessed ||
730 bThirdDigitsProcessed )
731 {
732 bValidRealString = FALSE;
733 }
734 bWhiteSpaceProcessed = TRUE;
735 bFirstSignProcessed = TRUE;
736 }
737 else if( bSecondSignProcessed == FALSE )
738 {
739 /* Note: The exponent must be present in
740 * order to accept the second sign...
741 */
742 if( bExponentProcessed == FALSE ||
743 bThirdDigitsProcessed ||
744 bDigitsRequired )
745 {
746 bValidRealString = FALSE;
747 }
748 bFirstSignProcessed = TRUE;
749 bWhiteSpaceProcessed = TRUE;
750 bFirstDigitsProcessed = TRUE;
751 bDecimalPointProcessed = TRUE;
752 bSecondDigitsProcessed = TRUE;
753 bSecondSignProcessed = TRUE;
754 }
755 break;
756
757 /* If decimals...
758 */
759 case '0':
760 case '1':
761 case '2':
762 case '3':
763 case '4':
764 case '5':
765 case '6':
766 case '7':
767 case '8':
768 case '9':
769 if( bFirstDigitsProcessed == FALSE )
770 {
771 if( bDecimalPointProcessed ||
772 bSecondDigitsProcessed ||
773 bExponentProcessed ||
774 bSecondSignProcessed ||
775 bThirdDigitsProcessed )
776 {
777 bValidRealString = FALSE;
778 }
779 bFirstSignProcessed = TRUE;
780 bWhiteSpaceProcessed = TRUE;
781 /* We have found some digits before the decimal point
782 * so disable the "Digits required" flag.
783 */
784 bDigitsRequired = FALSE;
785 }
786 else if( bSecondDigitsProcessed == FALSE )
787 {
788 if( bExponentProcessed ||
789 bSecondSignProcessed ||
790 bThirdDigitsProcessed )
791 {
792 bValidRealString = FALSE;
793 }
794 bFirstSignProcessed = TRUE;
795 bWhiteSpaceProcessed = TRUE;
796 bFirstDigitsProcessed = TRUE;
797 bDecimalPointProcessed = TRUE;
798 /* We have found some digits after the decimal point
799 * so disable the "Digits required" flag.
800 */
801 bDigitsRequired = FALSE;
802 }
803 else if( bThirdDigitsProcessed == FALSE )
804 {
805 /* Getting here means everything else should be processed.
806 * If we get anything else than a decimal following this
807 * digit it will be flagged by the other cases, so
808 * we do not really need to do anything in here.
809 */
810 }
811 break;
812 /* If DecimalPoint...
813 */
814 case '.':
815 if( bDecimalPointProcessed ||
816 bSecondDigitsProcessed ||
817 bExponentProcessed ||
818 bSecondSignProcessed ||
819 bThirdDigitsProcessed )
820 {
821 bValidRealString = FALSE;
822 }
823 bFirstSignProcessed = TRUE;
824 bWhiteSpaceProcessed = TRUE;
825 bFirstDigitsProcessed = TRUE;
826 bDecimalPointProcessed = TRUE;
827 break;
828 /* If Exponent...
829 */
830 case 'e':
831 case 'E':
832 case 'd':
833 case 'D':
834 if( bExponentProcessed ||
835 bSecondSignProcessed ||
836 bThirdDigitsProcessed ||
837 bDigitsRequired )
838 {
839 bValidRealString = FALSE;
840 }
841 bFirstSignProcessed = TRUE;
842 bWhiteSpaceProcessed = TRUE;
843 bFirstDigitsProcessed = TRUE;
844 bDecimalPointProcessed = TRUE;
845 bSecondDigitsProcessed = TRUE;
846 bExponentProcessed = TRUE;
847 break;
848 default:
849 bValidRealString = FALSE;
850 break;
851 }
852 /* Process next character.
853 */
854 pChar++;
855 }
856
857 /* If the required digits were not present we have an invalid
858 * string representation of a real number.
859 */
860 if( bDigitsRequired == TRUE )
861 {
862 bValidRealString = FALSE;
863 }
864
865 return bValidRealString;
866}
867
868
869/******************************************************************************
870 * Coerce [INTERNAL]
871 *
872 * This function dispatches execution to the proper conversion API
873 * to do the necessary coercion.
874 */
875static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
876{
877 HRESULT res = S_OK;
878 unsigned short vtFrom = 0;
879 vtFrom = ps->vt & VT_TYPEMASK;
880
881 /* Note: Since "long" and "int" values both have 4 bytes and are
882 * both signed integers "int" will be treated as "long" in the
883 * following code.
884 * The same goes for their unsigned versions.
885 */
886
887 /* Trivial Case: If the coercion is from two types that are
888 * identical then we can blindly copy from one argument to another.*/
889 if ((vt==vtFrom))
890 {
891 return VariantCopy(pd,ps);
892 }
893
894 /* Cases requiring thought*/
895 switch( vt )
896 {
897
898 case( VT_EMPTY ):
899 res = VariantClear( pd );
900 break;
901 case( VT_NULL ):
902 res = VariantClear( pd );
903 if( res == S_OK )
904 {
905 pd->vt = VT_NULL;
906 }
907 break;
908 case( VT_I1 ):
909 switch( vtFrom )
910 {
911 case( VT_I1 ):
912 res = VariantCopy( pd, ps );
913 break;
914 case( VT_I2 ):
915 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
916 break;
917 case( VT_INT ):
918 case( VT_I4 ):
919 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
920 break;
921 case( VT_UI1 ):
922 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
923 break;
924 case( VT_UI2 ):
925 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
926 break;
927 case( VT_UINT ):
928 case( VT_UI4 ):
929 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
930 break;
931 case( VT_R4 ):
932 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
933 break;
934 case( VT_R8 ):
935 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
936 break;
937 case( VT_DATE ):
938 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
939 break;
940 case( VT_BOOL ):
941 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
942 break;
943 case( VT_BSTR ):
944 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
945 break;
946 case( VT_CY ):
947 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
948 case( VT_DISPATCH ):
949 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
950 case( VT_UNKNOWN ):
951 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
952 case( VT_DECIMAL ):
953 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
954 default:
955 res = DISP_E_TYPEMISMATCH;
956 FIXME("Coercion from %d to %d\n", vtFrom, vt );
957 break;
958 }
959 break;
960
961 case( VT_I2 ):
962 switch( vtFrom )
963 {
964 case( VT_I1 ):
965 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
966 break;
967 case( VT_I2 ):
968 res = VariantCopy( pd, ps );
969 break;
970 case( VT_INT ):
971 case( VT_I4 ):
972 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
973 break;
974 case( VT_UI1 ):
975 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
976 break;
977 case( VT_UI2 ):
978 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
979 break;
980 case( VT_UINT ):
981 case( VT_UI4 ):
982 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
983 break;
984 case( VT_R4 ):
985 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
986 break;
987 case( VT_R8 ):
988 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
989 break;
990 case( VT_DATE ):
991 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
992 break;
993 case( VT_BOOL ):
994 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
995 break;
996 case( VT_BSTR ):
997 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
998 break;
999 case( VT_CY ):
1000 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
1001 case( VT_DISPATCH ):
1002 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1003 case( VT_UNKNOWN ):
1004 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
1005 case( VT_DECIMAL ):
1006 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
1007 default:
1008 res = DISP_E_TYPEMISMATCH;
1009 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1010 break;
1011 }
1012 break;
1013
1014 case( VT_INT ):
1015 case( VT_I4 ):
1016 switch( vtFrom )
1017 {
1018 case( VT_I1 ):
1019 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1020 break;
1021 case( VT_I2 ):
1022 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1023 break;
1024 case( VT_INT ):
1025 case( VT_I4 ):
1026 res = VariantCopy( pd, ps );
1027 break;
1028 case( VT_UI1 ):
1029 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1030 break;
1031 case( VT_UI2 ):
1032 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1033 break;
1034 case( VT_UINT ):
1035 case( VT_UI4 ):
1036 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1037 break;
1038 case( VT_R4 ):
1039 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1040 break;
1041 case( VT_R8 ):
1042 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1043 break;
1044 case( VT_DATE ):
1045 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1046 break;
1047 case( VT_BOOL ):
1048 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1049 break;
1050 case( VT_BSTR ):
1051 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1052 break;
1053 case( VT_CY ):
1054 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1055 case( VT_DISPATCH ):
1056 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1057 case( VT_UNKNOWN ):
1058 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1059 case( VT_DECIMAL ):
1060 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1061 default:
1062 res = DISP_E_TYPEMISMATCH;
1063 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1064 break;
1065 }
1066 break;
1067
1068 case( VT_UI1 ):
1069 switch( vtFrom )
1070 {
1071 case( VT_I1 ):
1072 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1073 break;
1074 case( VT_I2 ):
1075 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1076 break;
1077 case( VT_INT ):
1078 case( VT_I4 ):
1079 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1080 break;
1081 case( VT_UI1 ):
1082 res = VariantCopy( pd, ps );
1083 break;
1084 case( VT_UI2 ):
1085 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1086 break;
1087 case( VT_UINT ):
1088 case( VT_UI4 ):
1089 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1090 break;
1091 case( VT_R4 ):
1092 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1093 break;
1094 case( VT_R8 ):
1095 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1096 break;
1097 case( VT_DATE ):
1098 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1099 break;
1100 case( VT_BOOL ):
1101 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1102 break;
1103 case( VT_BSTR ):
1104 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1105 break;
1106 case( VT_CY ):
1107 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1108 case( VT_DISPATCH ):
1109 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1110 case( VT_UNKNOWN ):
1111 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1112 case( VT_DECIMAL ):
1113 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1114 default:
1115 res = DISP_E_TYPEMISMATCH;
1116 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1117 break;
1118 }
1119 break;
1120
1121 case( VT_UI2 ):
1122 switch( vtFrom )
1123 {
1124 case( VT_I1 ):
1125 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1126 break;
1127 case( VT_I2 ):
1128 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1129 break;
1130 case( VT_INT ):
1131 case( VT_I4 ):
1132 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1133 break;
1134 case( VT_UI1 ):
1135 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1136 break;
1137 case( VT_UI2 ):
1138 res = VariantCopy( pd, ps );
1139 break;
1140 case( VT_UINT ):
1141 case( VT_UI4 ):
1142 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1143 break;
1144 case( VT_R4 ):
1145 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1146 break;
1147 case( VT_R8 ):
1148 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1149 break;
1150 case( VT_DATE ):
1151 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1152 break;
1153 case( VT_BOOL ):
1154 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1155 break;
1156 case( VT_BSTR ):
1157 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1158 break;
1159 case( VT_CY ):
1160 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1161 case( VT_DISPATCH ):
1162 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1163 case( VT_UNKNOWN ):
1164 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1165 case( VT_DECIMAL ):
1166 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1167 default:
1168 res = DISP_E_TYPEMISMATCH;
1169 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1170 break;
1171 }
1172 break;
1173
1174 case( VT_UINT ):
1175 case( VT_UI4 ):
1176 switch( vtFrom )
1177 {
1178 case( VT_I1 ):
1179 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1180 break;
1181 case( VT_I2 ):
1182 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1183 break;
1184 case( VT_INT ):
1185 case( VT_I4 ):
1186 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1187 break;
1188 case( VT_UI1 ):
1189 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1190 break;
1191 case( VT_UI2 ):
1192 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1193 break;
1194 case( VT_UI4 ):
1195 res = VariantCopy( pd, ps );
1196 break;
1197 case( VT_R4 ):
1198 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1199 break;
1200 case( VT_R8 ):
1201 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1202 break;
1203 case( VT_DATE ):
1204 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1205 break;
1206 case( VT_BOOL ):
1207 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1208 break;
1209 case( VT_BSTR ):
1210 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1211 break;
1212 case( VT_CY ):
1213 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1214 case( VT_DISPATCH ):
1215 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1216 case( VT_UNKNOWN ):
1217 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1218 case( VT_DECIMAL ):
1219 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1220 default:
1221 res = DISP_E_TYPEMISMATCH;
1222 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1223 break;
1224 }
1225 break;
1226
1227 case( VT_R4 ):
1228 switch( vtFrom )
1229 {
1230 case( VT_I1 ):
1231 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1232 break;
1233 case( VT_I2 ):
1234 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1235 break;
1236 case( VT_INT ):
1237 case( VT_I4 ):
1238 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1239 break;
1240 case( VT_UI1 ):
1241 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1242 break;
1243 case( VT_UI2 ):
1244 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1245 break;
1246 case( VT_UINT ):
1247 case( VT_UI4 ):
1248 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1249 break;
1250 case( VT_R4 ):
1251 res = VariantCopy( pd, ps );
1252 break;
1253 case( VT_R8 ):
1254 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1255 break;
1256 case( VT_DATE ):
1257 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1258 break;
1259 case( VT_BOOL ):
1260 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1261 break;
1262 case( VT_BSTR ):
1263 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1264 break;
1265 case( VT_CY ):
1266 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1267 case( VT_DISPATCH ):
1268 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1269 case( VT_UNKNOWN ):
1270 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1271 case( VT_DECIMAL ):
1272 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1273 default:
1274 res = DISP_E_TYPEMISMATCH;
1275 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1276 break;
1277 }
1278 break;
1279
1280 case( VT_R8 ):
1281 switch( vtFrom )
1282 {
1283 case( VT_I1 ):
1284 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1285 break;
1286 case( VT_I2 ):
1287 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1288 break;
1289 case( VT_INT ):
1290 case( VT_I4 ):
1291 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1292 break;
1293 case( VT_UI1 ):
1294 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1295 break;
1296 case( VT_UI2 ):
1297 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1298 break;
1299 case( VT_UINT ):
1300 case( VT_UI4 ):
1301 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1302 break;
1303 case( VT_R4 ):
1304 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1305 break;
1306 case( VT_R8 ):
1307 res = VariantCopy( pd, ps );
1308 break;
1309 case( VT_DATE ):
1310 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1311 break;
1312 case( VT_BOOL ):
1313 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1314 break;
1315 case( VT_BSTR ):
1316 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1317 break;
1318 case( VT_CY ):
1319 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1320 case( VT_DISPATCH ):
1321 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1322 case( VT_UNKNOWN ):
1323 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1324 case( VT_DECIMAL ):
1325 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1326 default:
1327 res = DISP_E_TYPEMISMATCH;
1328 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1329 break;
1330 }
1331 break;
1332
1333 case( VT_DATE ):
1334 switch( vtFrom )
1335 {
1336 case( VT_I1 ):
1337 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1338 break;
1339 case( VT_I2 ):
1340 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1341 break;
1342 case( VT_INT ):
1343 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1344 break;
1345 case( VT_I4 ):
1346 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1347 break;
1348 case( VT_UI1 ):
1349 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1350 break;
1351 case( VT_UI2 ):
1352 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1353 break;
1354 case( VT_UINT ):
1355 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1356 break;
1357 case( VT_UI4 ):
1358 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1359 break;
1360 case( VT_R4 ):
1361 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1362 break;
1363 case( VT_R8 ):
1364 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1365 break;
1366 case( VT_DATE ):
1367 res = VariantCopy( pd, ps );
1368 break;
1369 case( VT_BOOL ):
1370 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1371 break;
1372 case( VT_BSTR ):
1373 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1374 break;
1375 case( VT_CY ):
1376 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1377 case( VT_DISPATCH ):
1378 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1379 case( VT_UNKNOWN ):
1380 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1381 case( VT_DECIMAL ):
1382 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1383 default:
1384 res = DISP_E_TYPEMISMATCH;
1385 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1386 break;
1387 }
1388 break;
1389
1390 case( VT_BOOL ):
1391 switch( vtFrom )
1392 {
1393 case( VT_I1 ):
1394 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1395 break;
1396 case( VT_I2 ):
1397 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1398 break;
1399 case( VT_INT ):
1400 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1401 break;
1402 case( VT_I4 ):
1403 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1404 break;
1405 case( VT_UI1 ):
1406 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1407 break;
1408 case( VT_UI2 ):
1409 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1410 break;
1411 case( VT_UINT ):
1412 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1413 break;
1414 case( VT_UI4 ):
1415 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1416 break;
1417 case( VT_R4 ):
1418 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1419 break;
1420 case( VT_R8 ):
1421 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1422 break;
1423 case( VT_DATE ):
1424 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1425 break;
1426 case( VT_BOOL ):
1427 res = VariantCopy( pd, ps );
1428 break;
1429 case( VT_BSTR ):
1430 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1431 break;
1432 case( VT_CY ):
1433 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1434 case( VT_DISPATCH ):
1435 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1436 case( VT_UNKNOWN ):
1437 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1438 case( VT_DECIMAL ):
1439 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1440 default:
1441 res = DISP_E_TYPEMISMATCH;
1442 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1443 break;
1444 }
1445 break;
1446
1447 case( VT_BSTR ):
1448 switch( vtFrom )
1449 {
1450 case( VT_I1 ):
1451 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1452 break;
1453 case( VT_I2 ):
1454 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1455 break;
1456 case( VT_INT ):
1457 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1458 break;
1459 case( VT_I4 ):
1460 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1461 break;
1462 case( VT_UI1 ):
1463 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1464 break;
1465 case( VT_UI2 ):
1466 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1467 break;
1468 case( VT_UINT ):
1469 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1470 break;
1471 case( VT_UI4 ):
1472 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1473 break;
1474 case( VT_R4 ):
1475 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1476 break;
1477 case( VT_R8 ):
1478 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1479 break;
1480 case( VT_DATE ):
1481 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1482 break;
1483 case( VT_BOOL ):
1484 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1485 break;
1486 case( VT_BSTR ):
1487 res = VariantCopy( pd, ps );
1488 break;
1489 case( VT_CY ):
1490 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1491 case( VT_DISPATCH ):
1492 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1493 case( VT_UNKNOWN ):
1494 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1495 case( VT_DECIMAL ):
1496 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1497 default:
1498 res = DISP_E_TYPEMISMATCH;
1499 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1500 break;
1501 }
1502 break;
1503
1504 case( VT_CY ):
1505 switch( vtFrom )
1506 {
1507 case( VT_I1 ):
1508 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1509 break;
1510 case( VT_I2 ):
1511 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1512 break;
1513 case( VT_INT ):
1514 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1515 break;
1516 case( VT_I4 ):
1517 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1518 break;
1519 case( VT_UI1 ):
1520 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1521 break;
1522 case( VT_UI2 ):
1523 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1524 break;
1525 case( VT_UINT ):
1526 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1527 break;
1528 case( VT_UI4 ):
1529 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1530 break;
1531 case( VT_R4 ):
1532 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1533 break;
1534 case( VT_R8 ):
1535 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1536 break;
1537 case( VT_DATE ):
1538 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1539 break;
1540 case( VT_BOOL ):
1541 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1542 break;
1543 case( VT_CY ):
1544 res = VariantCopy( pd, ps );
1545 break;
1546 case( VT_BSTR ):
1547 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1548 case( VT_DISPATCH ):
1549 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1550 case( VT_UNKNOWN ):
1551 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1552 case( VT_DECIMAL ):
1553 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1554 default:
1555 res = DISP_E_TYPEMISMATCH;
1556 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1557 break;
1558 }
1559 break;
1560
1561 default:
1562 res = DISP_E_TYPEMISMATCH;
1563 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1564 break;
1565 }
1566
1567 return res;
1568}
1569
1570/******************************************************************************
1571 * ValidateVtRange [INTERNAL]
1572 *
1573 * Used internally by the hi-level Variant API to determine
1574 * if the vartypes are valid.
1575 */
1576static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1577{
1578 /* if by value we must make sure it is in the
1579 * range of the valid types.
1580 */
1581 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1582 {
1583 return DISP_E_BADVARTYPE;
1584 }
1585 return S_OK;
1586}
1587
1588
1589/******************************************************************************
1590 * ValidateVartype [INTERNAL]
1591 *
1592 * Used internally by the hi-level Variant API to determine
1593 * if the vartypes are valid.
1594 */
1595static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1596{
1597 HRESULT res = S_OK;
1598
1599 /* check if we have a valid argument.
1600 */
1601 if( vt & VT_BYREF )
1602 {
1603 /* if by reference check that the type is in
1604 * the valid range and that it is not of empty or null type
1605 */
1606 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1607 ( vt & VT_TYPEMASK ) == VT_NULL ||
1608 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1609 {
1610 res = E_INVALIDARG;
1611 }
1612
1613 }
1614 else
1615 {
1616 res = ValidateVtRange( vt );
1617 }
1618
1619 return res;
1620}
1621
1622/******************************************************************************
1623 * ValidateVt [INTERNAL]
1624 *
1625 * Used internally by the hi-level Variant API to determine
1626 * if the vartypes are valid.
1627 */
1628static HRESULT WINAPI ValidateVt( VARTYPE vt )
1629{
1630 HRESULT res = S_OK;
1631
1632 /* check if we have a valid argument.
1633 */
1634 if( vt & VT_BYREF )
1635 {
1636 /* if by reference check that the type is in
1637 * the valid range and that it is not of empty or null type
1638 */
1639 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1640 ( vt & VT_TYPEMASK ) == VT_NULL ||
1641 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1642 {
1643 res = DISP_E_BADVARTYPE;
1644 }
1645
1646 }
1647 else
1648 {
1649 res = ValidateVtRange( vt );
1650 }
1651
1652 return res;
1653}
1654
1655
1656
1657
1658
1659/******************************************************************************
1660 * VariantInit32 [OLEAUT32.8]
1661 *
1662 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1663 * contents of the Variant.
1664 */
1665void WINAPI VariantInit(VARIANTARG* pvarg)
1666{
1667 TRACE("(%p),stub\n",pvarg);
1668
1669 memset(pvarg, 0, sizeof (VARIANTARG));
1670 pvarg->vt = VT_EMPTY;
1671
1672 return;
1673}
1674
1675/******************************************************************************
1676 * VariantClear32 [OLEAUT32.9]
1677 *
1678 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1679 * sets the wReservedX field to 0. The current contents of the VARIANT are
1680 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1681 * released. If VT_ARRAY the array is freed.
1682 */
1683HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1684{
1685 HRESULT res = S_OK;
1686 TRACE("(%p)\n",pvarg);
1687
1688 res = ValidateVariantType( pvarg->vt );
1689 if( res == S_OK )
1690 {
1691 if( !( pvarg->vt & VT_BYREF ) )
1692 {
1693 /*
1694 * The VT_ARRAY flag is a special case of a safe array.
1695 */
1696 if ( (pvarg->vt & VT_ARRAY) != 0)
1697 {
1698 SafeArrayDestroy(pvarg->u.parray);
1699 }
1700 else
1701 {
1702 switch( pvarg->vt & VT_TYPEMASK )
1703 {
1704 case( VT_BSTR ):
1705 SysFreeString( pvarg->u.bstrVal );
1706 break;
1707 case( VT_DISPATCH ):
1708 if(pvarg->u.pdispVal!=NULL)
1709 ICOM_CALL(Release,pvarg->u.pdispVal);
1710 break;
1711 case( VT_VARIANT ):
1712 VariantClear(pvarg->u.pvarVal);
1713 break;
1714 case( VT_UNKNOWN ):
1715 if(pvarg->u.punkVal!=NULL)
1716 ICOM_CALL(Release,pvarg->u.punkVal);
1717 break;
1718 case( VT_SAFEARRAY ):
1719 SafeArrayDestroy(pvarg->u.parray);
1720 break;
1721 default:
1722 break;
1723 }
1724 }
1725 }
1726
1727 /*
1728 * Empty all the fields and mark the type as empty.
1729 */
1730 memset(pvarg, 0, sizeof (VARIANTARG));
1731 pvarg->vt = VT_EMPTY;
1732 }
1733
1734 return res;
1735}
1736
1737/******************************************************************************
1738 * VariantCopy32 [OLEAUT32.10]
1739 *
1740 * Frees up the designation variant and makes a copy of the source.
1741 */
1742HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1743{
1744 HRESULT res = S_OK;
1745
1746 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1747
1748 res = ValidateVariantType( pvargSrc->vt );
1749
1750 /* If the pointer are to the same variant we don't need
1751 * to do anything.
1752 */
1753 if( pvargDest != pvargSrc && res == S_OK )
1754 {
1755 res = VariantClear( pvargDest );
1756
1757 if( res == S_OK )
1758 {
1759 if( pvargSrc->vt & VT_BYREF )
1760 {
1761 /* In the case of byreference we only need
1762 * to copy the pointer.
1763 */
1764 pvargDest->u = pvargSrc->u;
1765 pvargDest->vt = pvargSrc->vt;
1766 }
1767 else
1768 {
1769 /*
1770 * The VT_ARRAY flag is another way to designate a safe array.
1771 */
1772 if (pvargSrc->vt & VT_ARRAY)
1773 {
1774 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1775 }
1776 else
1777 {
1778 /* In the case of by value we need to
1779 * copy the actuall value. In the case of
1780 * VT_BSTR a copy of the string is made,
1781 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1782 * called to increment the object's reference count.
1783 */
1784 switch( pvargSrc->vt & VT_TYPEMASK )
1785 {
1786 case( VT_BSTR ):
1787 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1788 break;
1789 case( VT_DISPATCH ):
1790 pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1791 if (pvargDest->u.pdispVal!=NULL)
1792 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1793 break;
1794 case( VT_VARIANT ):
1795 VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1796 break;
1797 case( VT_UNKNOWN ):
1798 pvargDest->u.punkVal = pvargSrc->u.punkVal;
1799 if (pvargDest->u.pdispVal!=NULL)
1800 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1801 break;
1802 case( VT_SAFEARRAY ):
1803 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1804 break;
1805 default:
1806 pvargDest->u = pvargSrc->u;
1807 break;
1808 }
1809 }
1810
1811 pvargDest->vt = pvargSrc->vt;
1812 }
1813 }
1814 }
1815
1816 return res;
1817}
1818
1819
1820/******************************************************************************
1821 * VariantCopyInd32 [OLEAUT32.11]
1822 *
1823 * Frees up the destination variant and makes a copy of the source. If
1824 * the source is of type VT_BYREF it performs the necessary indirections.
1825 */
1826HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1827{
1828 HRESULT res = S_OK;
1829
1830 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1831
1832 res = ValidateVariantType( pvargSrc->vt );
1833
1834 if( res != S_OK )
1835 return res;
1836
1837 if( pvargSrc->vt & VT_BYREF )
1838 {
1839 VARIANTARG varg;
1840 VariantInit( &varg );
1841
1842 /* handle the in place copy.
1843 */
1844 if( pvargDest == pvargSrc )
1845 {
1846 /* we will use a copy of the source instead.
1847 */
1848 res = VariantCopy( &varg, pvargSrc );
1849 pvargSrc = &varg;
1850 }
1851
1852 if( res == S_OK )
1853 {
1854 res = VariantClear( pvargDest );
1855
1856 if( res == S_OK )
1857 {
1858 /*
1859 * The VT_ARRAY flag is another way to designate a safearray variant.
1860 */
1861 if ( pvargSrc->vt & VT_ARRAY)
1862 {
1863 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1864 }
1865 else
1866 {
1867 /* In the case of by reference we need
1868 * to copy the date pointed to by the variant.
1869 */
1870
1871 /* Get the variant type.
1872 */
1873 switch( pvargSrc->vt & VT_TYPEMASK )
1874 {
1875 case( VT_BSTR ):
1876 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1877 break;
1878 case( VT_DISPATCH ):
1879 break;
1880 case( VT_VARIANT ):
1881 {
1882 /* Prevent from cycling. According to tests on
1883 * VariantCopyInd in Windows and the documentation
1884 * this API dereferences the inner Variants to only one depth.
1885 * If the inner Variant itself contains an
1886 * other inner variant the E_INVALIDARG error is
1887 * returned.
1888 */
1889 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1890 {
1891 /* If we get here we are attempting to deference
1892 * an inner variant that that is itself contained
1893 * in an inner variant so report E_INVALIDARG error.
1894 */
1895 res = E_INVALIDARG;
1896 }
1897 else
1898 {
1899 /* Set the processing inner variant flag.
1900 * We will set this flag in the inner variant
1901 * that will be passed to the VariantCopyInd function.
1902 */
1903 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1904
1905 /* Dereference the inner variant.
1906 */
1907 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1908 }
1909 }
1910 break;
1911 case( VT_UNKNOWN ):
1912 break;
1913 case( VT_SAFEARRAY ):
1914 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1915 break;
1916 default:
1917 /* This is a by reference Variant which means that the union
1918 * part of the Variant contains a pointer to some data of
1919 * type "pvargSrc->vt & VT_TYPEMASK".
1920 * We will deference this data in a generic fashion using
1921 * the void pointer "Variant.u.byref".
1922 * We will copy this data into the union of the destination
1923 * Variant.
1924 */
1925 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1926 break;
1927 }
1928 }
1929
1930 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1931 }
1932 }
1933
1934 /* this should not fail.
1935 */
1936 VariantClear( &varg );
1937 }
1938 else
1939 {
1940 res = VariantCopy( pvargDest, pvargSrc );
1941 }
1942
1943 return res;
1944}
1945
1946/******************************************************************************
1947 * VariantChangeType32 [OLEAUT32.12]
1948 */
1949HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1950 USHORT wFlags, VARTYPE vt)
1951{
1952 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1953}
1954
1955/******************************************************************************
1956 * VariantChangeTypeEx32 [OLEAUT32.147]
1957 */
1958HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1959 LCID lcid, USHORT wFlags, VARTYPE vt)
1960{
1961 HRESULT res = S_OK;
1962 VARIANTARG varg;
1963 VariantInit( &varg );
1964
1965 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1966
1967 /* validate our source argument.
1968 */
1969 res = ValidateVariantType( pvargSrc->vt );
1970
1971 /* validate the vartype.
1972 */
1973 if( res == S_OK )
1974 {
1975 res = ValidateVt( vt );
1976 }
1977
1978 /* if we are doing an in-place conversion make a copy of the source.
1979 */
1980 if( res == S_OK && pvargDest == pvargSrc )
1981 {
1982 res = VariantCopy( &varg, pvargSrc );
1983 pvargSrc = &varg;
1984 }
1985
1986 if( res == S_OK )
1987 {
1988 /* free up the destination variant.
1989 */
1990 res = VariantClear( pvargDest );
1991 }
1992
1993 if( res == S_OK )
1994 {
1995 if( pvargSrc->vt & VT_BYREF )
1996 {
1997 /* Convert the source variant to a "byvalue" variant.
1998 */
1999 VARIANTARG Variant;
2000 VariantInit( &Variant );
2001 res = VariantCopyInd( &Variant, pvargSrc );
2002 if( res == S_OK )
2003 {
2004 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2005 /* this should not fail.
2006 */
2007 VariantClear( &Variant );
2008 }
2009
2010 }
2011 else
2012 {
2013 /* Use the current "byvalue" source variant.
2014 */
2015 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2016 }
2017 }
2018 /* this should not fail.
2019 */
2020 VariantClear( &varg );
2021
2022 /* set the type of the destination
2023 */
2024 if ( res == S_OK )
2025 pvargDest->vt = vt;
2026
2027 return res;
2028}
2029
2030
2031
2032
2033/******************************************************************************
2034 * VarUI1FromI232 [OLEAUT32.130]
2035 */
2036HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2037{
2038 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2039
2040 /* Check range of value.
2041 */
2042 if( sIn < UI1_MIN || sIn > UI1_MAX )
2043 {
2044 return DISP_E_OVERFLOW;
2045 }
2046
2047 *pbOut = (BYTE) sIn;
2048
2049 return S_OK;
2050}
2051
2052/******************************************************************************
2053 * VarUI1FromI432 [OLEAUT32.131]
2054 */
2055HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2056{
2057 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2058
2059 /* Check range of value.
2060 */
2061 if( lIn < UI1_MIN || lIn > UI1_MAX )
2062 {
2063 return DISP_E_OVERFLOW;
2064 }
2065
2066 *pbOut = (BYTE) lIn;
2067
2068 return S_OK;
2069}
2070
2071
2072/******************************************************************************
2073 * VarUI1FromR432 [OLEAUT32.132]
2074 */
2075HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2076{
2077 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2078
2079 /* Check range of value.
2080 */
2081 fltIn = round( fltIn );
2082 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2083 {
2084 return DISP_E_OVERFLOW;
2085 }
2086
2087 *pbOut = (BYTE) fltIn;
2088
2089 return S_OK;
2090}
2091
2092/******************************************************************************
2093 * VarUI1FromR832 [OLEAUT32.133]
2094 */
2095HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2096{
2097 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2098
2099 /* Check range of value.
2100 */
2101 dblIn = round( dblIn );
2102 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2103 {
2104 return DISP_E_OVERFLOW;
2105 }
2106
2107 *pbOut = (BYTE) dblIn;
2108
2109 return S_OK;
2110}
2111
2112/******************************************************************************
2113 * VarUI1FromDate32 [OLEAUT32.135]
2114 */
2115HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2116{
2117 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2118
2119 /* Check range of value.
2120 */
2121 dateIn = round( dateIn );
2122 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2123 {
2124 return DISP_E_OVERFLOW;
2125 }
2126
2127 *pbOut = (BYTE) dateIn;
2128
2129 return S_OK;
2130}
2131
2132/******************************************************************************
2133 * VarUI1FromBool32 [OLEAUT32.138]
2134 */
2135HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2136{
2137 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2138
2139 *pbOut = (BYTE) boolIn;
2140
2141 return S_OK;
2142}
2143
2144/******************************************************************************
2145 * VarUI1FromI132 [OLEAUT32.237]
2146 */
2147HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2148{
2149 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2150
2151 *pbOut = cIn;
2152
2153 return S_OK;
2154}
2155
2156/******************************************************************************
2157 * VarUI1FromUI232 [OLEAUT32.238]
2158 */
2159HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2160{
2161 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2162
2163 /* Check range of value.
2164 */
2165 if( uiIn > UI1_MAX )
2166 {
2167 return DISP_E_OVERFLOW;
2168 }
2169
2170 *pbOut = (BYTE) uiIn;
2171
2172 return S_OK;
2173}
2174
2175/******************************************************************************
2176 * VarUI1FromUI432 [OLEAUT32.239]
2177 */
2178HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2179{
2180 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2181
2182 /* Check range of value.
2183 */
2184 if( ulIn > UI1_MAX )
2185 {
2186 return DISP_E_OVERFLOW;
2187 }
2188
2189 *pbOut = (BYTE) ulIn;
2190
2191 return S_OK;
2192}
2193
2194
2195/******************************************************************************
2196 * VarUI1FromStr32 [OLEAUT32.54]
2197 */
2198HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2199{
2200 double dValue = 0.0;
2201 LPSTR pNewString = NULL;
2202
2203 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2204
2205 /* Check if we have a valid argument
2206 */
2207 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2208 RemoveCharacterFromString( pNewString, "," );
2209 if( IsValidRealString( pNewString ) == FALSE )
2210 {
2211 return DISP_E_TYPEMISMATCH;
2212 }
2213
2214 /* Convert the valid string to a floating point number.
2215 */
2216 dValue = atof( pNewString );
2217
2218 /* We don't need the string anymore so free it.
2219 */
2220 HeapFree( GetProcessHeap(), 0 , pNewString );
2221
2222 /* Check range of value.
2223 */
2224 dValue = round( dValue );
2225 if( dValue < UI1_MIN || dValue > UI1_MAX )
2226 {
2227 return DISP_E_OVERFLOW;
2228 }
2229
2230 *pbOut = (BYTE) dValue;
2231
2232 return S_OK;
2233}
2234
2235/**********************************************************************
2236 * VarUI1FromCy32 [OLEAUT32.134]
2237 * Convert currency to unsigned char
2238 */
2239HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2240 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2241
2242 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2243
2244 *pbOut = (BYTE)t;
2245 return S_OK;
2246}
2247
2248/******************************************************************************
2249 * VarI2FromUI132 [OLEAUT32.48]
2250 */
2251HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2252{
2253 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2254
2255 *psOut = (short) bIn;
2256
2257 return S_OK;
2258}
2259
2260/******************************************************************************
2261 * VarI2FromI432 [OLEAUT32.49]
2262 */
2263HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2264{
2265 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2266
2267 /* Check range of value.
2268 */
2269 if( lIn < I2_MIN || lIn > I2_MAX )
2270 {
2271 return DISP_E_OVERFLOW;
2272 }
2273
2274 *psOut = (short) lIn;
2275
2276 return S_OK;
2277}
2278
2279/******************************************************************************
2280 * VarI2FromR432 [OLEAUT32.50]
2281 */
2282HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2283{
2284 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2285
2286 /* Check range of value.
2287 */
2288 fltIn = round( fltIn );
2289 if( fltIn < I2_MIN || fltIn > I2_MAX )
2290 {
2291 return DISP_E_OVERFLOW;
2292 }
2293
2294 *psOut = (short) fltIn;
2295
2296 return S_OK;
2297}
2298
2299/******************************************************************************
2300 * VarI2FromR832 [OLEAUT32.51]
2301 */
2302HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2303{
2304 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2305
2306 /* Check range of value.
2307 */
2308 dblIn = round( dblIn );
2309 if( dblIn < I2_MIN || dblIn > I2_MAX )
2310 {
2311 return DISP_E_OVERFLOW;
2312 }
2313
2314 *psOut = (short) dblIn;
2315
2316 return S_OK;
2317}
2318
2319/******************************************************************************
2320 * VarI2FromDate32 [OLEAUT32.53]
2321 */
2322HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2323{
2324 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2325
2326 /* Check range of value.
2327 */
2328 dateIn = round( dateIn );
2329 if( dateIn < I2_MIN || dateIn > I2_MAX )
2330 {
2331 return DISP_E_OVERFLOW;
2332 }
2333
2334 *psOut = (short) dateIn;
2335
2336 return S_OK;
2337}
2338
2339/******************************************************************************
2340 * VarI2FromBool32 [OLEAUT32.56]
2341 */
2342HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2343{
2344 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2345
2346 *psOut = (short) boolIn;
2347
2348 return S_OK;
2349}
2350
2351/******************************************************************************
2352 * VarI2FromI132 [OLEAUT32.48]
2353 */
2354HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2355{
2356 TRACE("( %c, %p ), stub\n", cIn, psOut );
2357
2358 *psOut = (short) cIn;
2359
2360 return S_OK;
2361}
2362
2363/******************************************************************************
2364 * VarI2FromUI232 [OLEAUT32.206]
2365 */
2366HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2367{
2368 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2369
2370 /* Check range of value.
2371 */
2372 if( uiIn > I2_MAX )
2373 {
2374 return DISP_E_OVERFLOW;
2375 }
2376
2377 *psOut = (short) uiIn;
2378
2379 return S_OK;
2380}
2381
2382/******************************************************************************
2383 * VarI2FromUI432 [OLEAUT32.49]
2384 */
2385HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2386{
2387 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2388
2389 /* Check range of value.
2390 */
2391 if( ulIn < I2_MIN || ulIn > I2_MAX )
2392 {
2393 return DISP_E_OVERFLOW;
2394 }
2395
2396 *psOut = (short) ulIn;
2397
2398 return S_OK;
2399}
2400
2401/******************************************************************************
2402 * VarI2FromStr32 [OLEAUT32.54]
2403 */
2404HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2405{
2406 double dValue = 0.0;
2407 LPSTR pNewString = NULL;
2408
2409 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2410
2411 /* Check if we have a valid argument
2412 */
2413 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2414 RemoveCharacterFromString( pNewString, "," );
2415 if( IsValidRealString( pNewString ) == FALSE )
2416 {
2417 return DISP_E_TYPEMISMATCH;
2418 }
2419
2420 /* Convert the valid string to a floating point number.
2421 */
2422 dValue = atof( pNewString );
2423
2424 /* We don't need the string anymore so free it.
2425 */
2426 HeapFree( GetProcessHeap(), 0, pNewString );
2427
2428 /* Check range of value.
2429 */
2430 dValue = round( dValue );
2431 if( dValue < I2_MIN || dValue > I2_MAX )
2432 {
2433 return DISP_E_OVERFLOW;
2434 }
2435
2436 *psOut = (short) dValue;
2437
2438 return S_OK;
2439}
2440
2441/**********************************************************************
2442 * VarI2FromCy32 [OLEAUT32.52]
2443 * Convert currency to signed short
2444 */
2445HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2446 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2447
2448 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2449
2450 *psOut = (SHORT)t;
2451 return S_OK;
2452}
2453
2454/******************************************************************************
2455 * VarI4FromUI132 [OLEAUT32.58]
2456 */
2457HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2458{
2459 TRACE("( %X, %p ), stub\n", bIn, plOut );
2460
2461 *plOut = (LONG) bIn;
2462
2463 return S_OK;
2464}
2465
2466
2467/******************************************************************************
2468 * VarI4FromR432 [OLEAUT32.60]
2469 */
2470HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2471{
2472 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2473
2474 /* Check range of value.
2475 */
2476 fltIn = round( fltIn );
2477 if( fltIn < I4_MIN || fltIn > I4_MAX )
2478 {
2479 return DISP_E_OVERFLOW;
2480 }
2481
2482 *plOut = (LONG) fltIn;
2483
2484 return S_OK;
2485}
2486
2487/******************************************************************************
2488 * VarI4FromR832 [OLEAUT32.61]
2489 */
2490HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2491{
2492 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2493
2494 /* Check range of value.
2495 */
2496 dblIn = round( dblIn );
2497 if( dblIn < I4_MIN || dblIn > I4_MAX )
2498 {
2499 return DISP_E_OVERFLOW;
2500 }
2501
2502 *plOut = (LONG) dblIn;
2503
2504 return S_OK;
2505}
2506
2507/******************************************************************************
2508 * VarI4FromDate32 [OLEAUT32.63]
2509 */
2510HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2511{
2512 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2513
2514 /* Check range of value.
2515 */
2516 dateIn = round( dateIn );
2517 if( dateIn < I4_MIN || dateIn > I4_MAX )
2518 {
2519 return DISP_E_OVERFLOW;
2520 }
2521
2522 *plOut = (LONG) dateIn;
2523
2524 return S_OK;
2525}
2526
2527/******************************************************************************
2528 * VarI4FromBool32 [OLEAUT32.66]
2529 */
2530HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2531{
2532 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2533
2534 *plOut = (LONG) boolIn;
2535
2536 return S_OK;
2537}
2538
2539/******************************************************************************
2540 * VarI4FromI132 [OLEAUT32.209]
2541 */
2542HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2543{
2544 TRACE("( %c, %p ), stub\n", cIn, plOut );
2545
2546 *plOut = (LONG) cIn;
2547
2548 return S_OK;
2549}
2550
2551/******************************************************************************
2552 * VarI4FromUI232 [OLEAUT32.210]
2553 */
2554HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2555{
2556 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2557
2558 *plOut = (LONG) uiIn;
2559
2560 return S_OK;
2561}
2562
2563/******************************************************************************
2564 * VarI4FromUI432 [OLEAUT32.211]
2565 */
2566HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2567{
2568 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2569
2570 /* Check range of value.
2571 */
2572 if( ulIn < I4_MIN || ulIn > I4_MAX )
2573 {
2574 return DISP_E_OVERFLOW;
2575 }
2576
2577 *plOut = (LONG) ulIn;
2578
2579 return S_OK;
2580}
2581
2582/******************************************************************************
2583 * VarI4FromI232 [OLEAUT32.59]
2584 */
2585HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2586{
2587 TRACE("( %d, %p ), stub\n", sIn, plOut );
2588
2589 *plOut = (LONG) sIn;
2590
2591 return S_OK;
2592}
2593
2594/******************************************************************************
2595 * VarI4FromStr32 [OLEAUT32.64]
2596 */
2597HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2598{
2599 double dValue = 0.0;
2600 LPSTR pNewString = NULL;
2601
2602 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2603
2604 /* Check if we have a valid argument
2605 */
2606 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2607 RemoveCharacterFromString( pNewString, "," );
2608 if( IsValidRealString( pNewString ) == FALSE )
2609 {
2610 return DISP_E_TYPEMISMATCH;
2611 }
2612
2613 /* Convert the valid string to a floating point number.
2614 */
2615 dValue = atof( pNewString );
2616
2617 /* We don't need the string anymore so free it.
2618 */
2619 HeapFree( GetProcessHeap(), 0, pNewString );
2620
2621 /* Check range of value.
2622 */
2623 dValue = round( dValue );
2624 if( dValue < I4_MIN || dValue > I4_MAX )
2625 {
2626 return DISP_E_OVERFLOW;
2627 }
2628
2629 *plOut = (LONG) dValue;
2630
2631 return S_OK;
2632}
2633
2634/**********************************************************************
2635 * VarI4FromCy32 [OLEAUT32.62]
2636 * Convert currency to signed long
2637 */
2638HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2639 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2640
2641 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2642
2643 *plOut = (LONG)t;
2644 return S_OK;
2645}
2646
2647/******************************************************************************
2648 * VarR4FromUI132 [OLEAUT32.68]
2649 */
2650HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2651{
2652 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2653
2654 *pfltOut = (FLOAT) bIn;
2655
2656 return S_OK;
2657}
2658
2659/******************************************************************************
2660 * VarR4FromI232 [OLEAUT32.69]
2661 */
2662HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2663{
2664 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2665
2666 *pfltOut = (FLOAT) sIn;
2667
2668 return S_OK;
2669}
2670
2671/******************************************************************************
2672 * VarR4FromI432 [OLEAUT32.70]
2673 */
2674HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2675{
2676 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2677
2678 *pfltOut = (FLOAT) lIn;
2679
2680 return S_OK;
2681}
2682
2683/******************************************************************************
2684 * VarR4FromR832 [OLEAUT32.71]
2685 */
2686HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2687{
2688 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2689
2690 /* Check range of value.
2691 */
2692 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2693 {
2694 return DISP_E_OVERFLOW;
2695 }
2696
2697 *pfltOut = (FLOAT) dblIn;
2698
2699 return S_OK;
2700}
2701
2702/******************************************************************************
2703 * VarR4FromDate32 [OLEAUT32.73]
2704 */
2705HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2706{
2707 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2708
2709 /* Check range of value.
2710 */
2711 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2712 {
2713 return DISP_E_OVERFLOW;
2714 }
2715
2716 *pfltOut = (FLOAT) dateIn;
2717
2718 return S_OK;
2719}
2720
2721/******************************************************************************
2722 * VarR4FromBool32 [OLEAUT32.76]
2723 */
2724HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2725{
2726 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2727
2728 *pfltOut = (FLOAT) boolIn;
2729
2730 return S_OK;
2731}
2732
2733/******************************************************************************
2734 * VarR4FromI132 [OLEAUT32.213]
2735 */
2736HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2737{
2738 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2739
2740 *pfltOut = (FLOAT) cIn;
2741
2742 return S_OK;
2743}
2744
2745/******************************************************************************
2746 * VarR4FromUI232 [OLEAUT32.214]
2747 */
2748HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2749{
2750 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2751
2752 *pfltOut = (FLOAT) uiIn;
2753
2754 return S_OK;
2755}
2756
2757/******************************************************************************
2758 * VarR4FromUI432 [OLEAUT32.215]
2759 */
2760HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2761{
2762 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2763
2764 *pfltOut = (FLOAT) ulIn;
2765
2766 return S_OK;
2767}
2768
2769/******************************************************************************
2770 * VarR4FromStr32 [OLEAUT32.74]
2771 */
2772HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2773{
2774 double dValue = 0.0;
2775 LPSTR pNewString = NULL;
2776
2777 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2778
2779 /* Check if we have a valid argument
2780 */
2781 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2782 RemoveCharacterFromString( pNewString, "," );
2783 if( IsValidRealString( pNewString ) == FALSE )
2784 {
2785 return DISP_E_TYPEMISMATCH;
2786 }
2787
2788 /* Convert the valid string to a floating point number.
2789 */
2790 dValue = atof( pNewString );
2791
2792 /* We don't need the string anymore so free it.
2793 */
2794 HeapFree( GetProcessHeap(), 0, pNewString );
2795
2796 /* Check range of value.
2797 */
2798 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2799 {
2800 return DISP_E_OVERFLOW;
2801 }
2802
2803 *pfltOut = (FLOAT) dValue;
2804
2805 return S_OK;
2806}
2807
2808/**********************************************************************
2809 * VarR4FromCy32 [OLEAUT32.72]
2810 * Convert currency to float
2811 */
2812HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2813 *pfltOut = (FLOAT)((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2814
2815 return S_OK;
2816}
2817
2818/******************************************************************************
2819 * VarR8FromUI132 [OLEAUT32.68]
2820 */
2821HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2822{
2823 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2824
2825 *pdblOut = (double) bIn;
2826
2827 return S_OK;
2828}
2829
2830/******************************************************************************
2831 * VarR8FromI232 [OLEAUT32.69]
2832 */
2833HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2834{
2835 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2836
2837 *pdblOut = (double) sIn;
2838
2839 return S_OK;
2840}
2841
2842/******************************************************************************
2843 * VarR8FromI432 [OLEAUT32.70]
2844 */
2845HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2846{
2847 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2848
2849 *pdblOut = (double) lIn;
2850
2851 return S_OK;
2852}
2853
2854/******************************************************************************
2855 * VarR8FromR432 [OLEAUT32.81]
2856 */
2857HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2858{
2859 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2860
2861 *pdblOut = (double) fltIn;
2862
2863 return S_OK;
2864}
2865
2866/******************************************************************************
2867 * VarR8FromDate32 [OLEAUT32.83]
2868 */
2869HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2870{
2871 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2872
2873 *pdblOut = (double) dateIn;
2874
2875 return S_OK;
2876}
2877
2878/******************************************************************************
2879 * VarR8FromBool32 [OLEAUT32.86]
2880 */
2881HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2882{
2883 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2884
2885 *pdblOut = (double) boolIn;
2886
2887 return S_OK;
2888}
2889
2890/******************************************************************************
2891 * VarR8FromI132 [OLEAUT32.217]
2892 */
2893HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2894{
2895 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2896
2897 *pdblOut = (double) cIn;
2898
2899 return S_OK;
2900}
2901
2902/******************************************************************************
2903 * VarR8FromUI232 [OLEAUT32.218]
2904 */
2905HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2906{
2907 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2908
2909 *pdblOut = (double) uiIn;
2910
2911 return S_OK;
2912}
2913
2914/******************************************************************************
2915 * VarR8FromUI432 [OLEAUT32.219]
2916 */
2917HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2918{
2919 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2920
2921 *pdblOut = (double) ulIn;
2922
2923 return S_OK;
2924}
2925
2926/******************************************************************************
2927 * VarR8FromStr32 [OLEAUT32.84]
2928 */
2929HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2930{
2931 double dValue = 0.0;
2932 LPSTR pNewString = NULL;
2933
2934 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2935
2936 /* Check if we have a valid argument
2937 */
2938 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2939 RemoveCharacterFromString( pNewString, "," );
2940 if( IsValidRealString( pNewString ) == FALSE )
2941 {
2942 return DISP_E_TYPEMISMATCH;
2943 }
2944
2945 /* Convert the valid string to a floating point number.
2946 */
2947 dValue = atof( pNewString );
2948
2949 /* We don't need the string anymore so free it.
2950 */
2951 HeapFree( GetProcessHeap(), 0, pNewString );
2952
2953 *pdblOut = dValue;
2954
2955 return S_OK;
2956}
2957
2958/**********************************************************************
2959 * VarR8FromCy32 [OLEAUT32.82]
2960 * Convert currency to double
2961 */
2962HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2963 *pdblOut = (double)((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2964
2965 return S_OK;
2966}
2967
2968/******************************************************************************
2969 * VarDateFromUI132 [OLEAUT32.]
2970 */
2971HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2972{
2973 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2974
2975 *pdateOut = (DATE) bIn;
2976
2977 return S_OK;
2978}
2979
2980/******************************************************************************
2981 * VarDateFromI232 [OLEAUT32.222]
2982 */
2983HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2984{
2985 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2986
2987 *pdateOut = (DATE) sIn;
2988
2989 return S_OK;
2990}
2991
2992/******************************************************************************
2993 * VarDateFromI432 [OLEAUT32.90]
2994 */
2995HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
2996{
2997 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
2998
2999 if( lIn < DATE_MIN || lIn > DATE_MAX )
3000 {
3001 return DISP_E_OVERFLOW;
3002 }
3003
3004 *pdateOut = (DATE) lIn;
3005
3006 return S_OK;
3007}
3008
3009/******************************************************************************
3010 * VarDateFromR432 [OLEAUT32.91]
3011 */
3012HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3013{
3014 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3015
3016 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3017 {
3018 return DISP_E_OVERFLOW;
3019 }
3020
3021 *pdateOut = (DATE) fltIn;
3022
3023 return S_OK;
3024}
3025
3026/******************************************************************************
3027 * VarDateFromR832 [OLEAUT32.92]
3028 */
3029HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3030{
3031 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3032
3033 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3034 {
3035 return DISP_E_OVERFLOW;
3036 }
3037
3038 *pdateOut = (DATE) dblIn;
3039
3040 return S_OK;
3041}
3042
3043/******************************************************************************
3044 * VarDateFromStr32 [OLEAUT32.94]
3045 * The string representing the date is composed of two parts, a date and time.
3046 *
3047 * The format of the time is has follows:
3048 * hh[:mm][:ss][AM|PM]
3049 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3050 * of space and/or tab characters, which are ignored.
3051 *
3052 * The formats for the date part are has follows:
3053 * mm/[dd/][yy]yy
3054 * [dd/]mm/[yy]yy
3055 * [yy]yy/mm/dd
3056 * January dd[,] [yy]yy
3057 * dd January [yy]yy
3058 * [yy]yy January dd
3059 * Whitespace can be inserted anywhere between these tokens.
3060 *
3061 * The formats for the date and time string are has follows.
3062 * date[whitespace][time]
3063 * [time][whitespace]date
3064 *
3065 * These are the only characters allowed in a string representing a date and time:
3066 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3067 */
3068HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3069{
3070 HRESULT ret = S_OK;
3071 struct tm TM = { 0,0,0,0,0,0,0,0,0 };
3072
3073 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3074
3075 if( DateTimeStringToTm( strIn, lcid, &TM ) )
3076 {
3077 if( TmToDATE( &TM, pdateOut ) == FALSE )
3078 {
3079 ret = E_INVALIDARG;
3080 }
3081 }
3082 else
3083 {
3084 ret = DISP_E_TYPEMISMATCH;
3085 }
3086
3087
3088 return ret;
3089}
3090
3091/******************************************************************************
3092 * VarDateFromI132 [OLEAUT32.221]
3093 */
3094HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3095{
3096 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3097
3098 *pdateOut = (DATE) cIn;
3099
3100 return S_OK;
3101}
3102
3103/******************************************************************************
3104 * VarDateFromUI232 [OLEAUT32.222]
3105 */
3106HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3107{
3108 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3109
3110 if( uiIn > DATE_MAX )
3111 {
3112 return DISP_E_OVERFLOW;
3113 }
3114
3115 *pdateOut = (DATE) uiIn;
3116
3117 return S_OK;
3118}
3119
3120/******************************************************************************
3121 * VarDateFromUI432 [OLEAUT32.223]
3122 */
3123HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3124{
3125 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3126
3127 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3128 {
3129 return DISP_E_OVERFLOW;
3130 }
3131
3132 *pdateOut = (DATE) ulIn;
3133
3134 return S_OK;
3135}
3136
3137/******************************************************************************
3138 * VarDateFromBool32 [OLEAUT32.96]
3139 */
3140HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3141{
3142 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3143
3144 *pdateOut = (DATE) boolIn;
3145
3146 return S_OK;
3147}
3148
3149/**********************************************************************
3150 * VarDateFromCy32 [OLEAUT32.93]
3151 * Convert currency to date
3152 */
3153HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3154 *pdateOut = (DATE)((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
3155
3156 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3157 return S_OK;
3158}
3159
3160/******************************************************************************
3161 * VarBstrFromUI132 [OLEAUT32.108]
3162 */
3163HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3164{
3165 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3166 sprintf( pBuffer, "%d", bVal );
3167
3168 *pbstrOut = StringDupAtoBstr( pBuffer );
3169
3170 return S_OK;
3171}
3172
3173/******************************************************************************
3174 * VarBstrFromI232 [OLEAUT32.109]
3175 */
3176HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3177{
3178 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3179 sprintf( pBuffer, "%d", iVal );
3180 *pbstrOut = StringDupAtoBstr( pBuffer );
3181
3182 return S_OK;
3183}
3184
3185/******************************************************************************
3186 * VarBstrFromI432 [OLEAUT32.110]
3187 */
3188HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3189{
3190 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3191
3192 sprintf( pBuffer, "%ld", lIn );
3193 *pbstrOut = StringDupAtoBstr( pBuffer );
3194
3195 return S_OK;
3196}
3197
3198/******************************************************************************
3199 * VarBstrFromR432 [OLEAUT32.111]
3200 */
3201HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3202{
3203 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3204
3205 sprintf( pBuffer, "%.7g", fltIn );
3206 *pbstrOut = StringDupAtoBstr( pBuffer );
3207
3208 return S_OK;
3209}
3210
3211/******************************************************************************
3212 * VarBstrFromR832 [OLEAUT32.112]
3213 */
3214HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3215{
3216 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3217
3218 sprintf( pBuffer, "%.15g", dblIn );
3219 *pbstrOut = StringDupAtoBstr( pBuffer );
3220
3221 return S_OK;
3222}
3223
3224/******************************************************************************
3225 * VarBstrFromCy [OLEAUT32.113]
3226 */
3227HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3228 /* FIXME */
3229 return E_NOTIMPL;
3230}
3231
3232
3233/******************************************************************************
3234 * VarBstrFromDate32 [OLEAUT32.114]
3235 *
3236 * The date is implemented using an 8 byte floating-point number.
3237 * Days are represented by whole numbers increments starting with 0.00 has
3238 * being December 30 1899, midnight.
3239 * The hours are expressed as the fractional part of the number.
3240 * December 30 1899 at midnight = 0.00
3241 * January 1 1900 at midnight = 2.00
3242 * January 4 1900 at 6 AM = 5.25
3243 * January 4 1900 at noon = 5.50
3244 * December 29 1899 at midnight = -1.00
3245 * December 18 1899 at midnight = -12.00
3246 * December 18 1899 at 6AM = -12.25
3247 * December 18 1899 at 6PM = -12.75
3248 * December 19 1899 at midnight = -11.00
3249 * The tm structure is as follows:
3250 * struct tm {
3251 * int tm_sec; seconds after the minute - [0,59]
3252 * int tm_min; minutes after the hour - [0,59]
3253 * int tm_hour; hours since midnight - [0,23]
3254 * int tm_mday; day of the month - [1,31]
3255 * int tm_mon; months since January - [0,11]
3256 * int tm_year; years
3257 * int tm_wday; days since Sunday - [0,6]
3258 * int tm_yday; days since January 1 - [0,365]
3259 * int tm_isdst; daylight savings time flag
3260 * };
3261 */
3262HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3263{
3264 struct tm TM = {0,0,0,0,0,0,0,0,0};
3265
3266 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3267
3268 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3269 {
3270 return E_INVALIDARG;
3271 }
3272
3273 if( dwFlags & VAR_DATEVALUEONLY )
3274 strftime( pBuffer, BUFFER_MAX, "%lx", &TM );
3275 else if( dwFlags & VAR_TIMEVALUEONLY )
3276 strftime( pBuffer, BUFFER_MAX, "%lX", &TM );
3277 else
3278 strftime( pBuffer, BUFFER_MAX, "%lx %lX", &TM );
3279
3280 *pbstrOut = StringDupAtoBstr( pBuffer );
3281
3282 return S_OK;
3283}
3284
3285/******************************************************************************
3286 * VarBstrFromBool32 [OLEAUT32.116]
3287 */
3288HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3289{
3290 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3291
3292 if( boolIn == VARIANT_FALSE )
3293 {
3294 sprintf( pBuffer, "False" );
3295 }
3296 else
3297 {
3298 sprintf( pBuffer, "True" );
3299 }
3300
3301 *pbstrOut = StringDupAtoBstr( pBuffer );
3302
3303 return S_OK;
3304}
3305
3306/******************************************************************************
3307 * VarBstrFromI132 [OLEAUT32.229]
3308 */
3309HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3310{
3311 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3312 sprintf( pBuffer, "%d", cIn );
3313 *pbstrOut = StringDupAtoBstr( pBuffer );
3314
3315 return S_OK;
3316}
3317
3318/******************************************************************************
3319 * VarBstrFromUI232 [OLEAUT32.230]
3320 */
3321HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3322{
3323 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3324 sprintf( pBuffer, "%d", uiIn );
3325 *pbstrOut = StringDupAtoBstr( pBuffer );
3326
3327 return S_OK;
3328}
3329
3330/******************************************************************************
3331 * VarBstrFromUI432 [OLEAUT32.231]
3332 */
3333HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3334{
3335 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3336 sprintf( pBuffer, "%ld", ulIn );
3337 *pbstrOut = StringDupAtoBstr( pBuffer );
3338
3339 return S_OK;
3340}
3341
3342/******************************************************************************
3343 * VarBoolFromUI132 [OLEAUT32.118]
3344 */
3345HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3346{
3347 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3348
3349 if( bIn == 0 )
3350 {
3351 *pboolOut = VARIANT_FALSE;
3352 }
3353 else
3354 {
3355 *pboolOut = VARIANT_TRUE;
3356 }
3357
3358 return S_OK;
3359}
3360
3361/******************************************************************************
3362 * VarBoolFromI232 [OLEAUT32.119]
3363 */
3364HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3365{
3366 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3367
3368 if( sIn == 0 )
3369 {
3370 *pboolOut = VARIANT_FALSE;
3371 }
3372 else
3373 {
3374 *pboolOut = VARIANT_TRUE;
3375 }
3376
3377 return S_OK;
3378}
3379
3380/******************************************************************************
3381 * VarBoolFromI432 [OLEAUT32.120]
3382 */
3383HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3384{
3385 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3386
3387 if( lIn == 0 )
3388 {
3389 *pboolOut = VARIANT_FALSE;
3390 }
3391 else
3392 {
3393 *pboolOut = VARIANT_TRUE;
3394 }
3395
3396 return S_OK;
3397}
3398
3399/******************************************************************************
3400 * VarBoolFromR432 [OLEAUT32.121]
3401 */
3402HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3403{
3404 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3405
3406 if( fltIn == 0.0 )
3407 {
3408 *pboolOut = VARIANT_FALSE;
3409 }
3410 else
3411 {
3412 *pboolOut = VARIANT_TRUE;
3413 }
3414
3415 return S_OK;
3416}
3417
3418/******************************************************************************
3419 * VarBoolFromR832 [OLEAUT32.122]
3420 */
3421HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3422{
3423 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3424
3425 if( dblIn == 0.0 )
3426 {
3427 *pboolOut = VARIANT_FALSE;
3428 }
3429 else
3430 {
3431 *pboolOut = VARIANT_TRUE;
3432 }
3433
3434 return S_OK;
3435}
3436
3437/******************************************************************************
3438 * VarBoolFromDate32 [OLEAUT32.123]
3439 */
3440HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3441{
3442 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3443
3444 if( dateIn == 0.0 )
3445 {
3446 *pboolOut = VARIANT_FALSE;
3447 }
3448 else
3449 {
3450 *pboolOut = VARIANT_TRUE;
3451 }
3452
3453 return S_OK;
3454}
3455
3456/******************************************************************************
3457 * VarBoolFromStr32 [OLEAUT32.125]
3458 */
3459HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3460{
3461 HRESULT ret = S_OK;
3462 char* pNewString = NULL;
3463
3464 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3465
3466 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3467
3468 if( pNewString == NULL || strlen( pNewString ) == 0 )
3469 {
3470 ret = DISP_E_TYPEMISMATCH;
3471 }
3472
3473 if( ret == S_OK )
3474 {
3475 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3476 {
3477 *pboolOut = VARIANT_TRUE;
3478 }
3479 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3480 {
3481 *pboolOut = VARIANT_FALSE;
3482 }
3483 else
3484 {
3485 /* Try converting the string to a floating point number.
3486 */
3487 double dValue = 0.0;
3488 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3489 if( res != S_OK )
3490 {
3491 ret = DISP_E_TYPEMISMATCH;
3492 }
3493 else if( dValue == 0.0 )
3494 {
3495 *pboolOut = VARIANT_FALSE;
3496 }
3497 else
3498 {
3499 *pboolOut = VARIANT_TRUE;
3500 }
3501 }
3502 }
3503
3504 HeapFree( GetProcessHeap(), 0, pNewString );
3505
3506 return ret;
3507}
3508
3509/******************************************************************************
3510 * VarBoolFromI132 [OLEAUT32.233]
3511 */
3512HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3513{
3514 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3515
3516 if( cIn == 0 )
3517 {
3518 *pboolOut = VARIANT_FALSE;
3519 }
3520 else
3521 {
3522 *pboolOut = VARIANT_TRUE;
3523 }
3524
3525 return S_OK;
3526}
3527
3528/******************************************************************************
3529 * VarBoolFromUI232 [OLEAUT32.234]
3530 */
3531HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3532{
3533 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3534
3535 if( uiIn == 0 )
3536 {
3537 *pboolOut = VARIANT_FALSE;
3538 }
3539 else
3540 {
3541 *pboolOut = VARIANT_TRUE;
3542 }
3543
3544 return S_OK;
3545}
3546
3547/******************************************************************************
3548 * VarBoolFromUI432 [OLEAUT32.235]
3549 */
3550HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3551{
3552 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3553
3554 if( ulIn == 0 )
3555 {
3556 *pboolOut = VARIANT_FALSE;
3557 }
3558 else
3559 {
3560 *pboolOut = VARIANT_TRUE;
3561 }
3562
3563 return S_OK;
3564}
3565
3566/**********************************************************************
3567 * VarBoolFromCy32 [OLEAUT32.124]
3568 * Convert currency to boolean
3569 */
3570HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3571 if (cyIn.u.Hi || cyIn.u.Lo) *pboolOut = -1;
3572 else *pboolOut = 0;
3573
3574 return S_OK;
3575}
3576
3577/******************************************************************************
3578 * VarI1FromUI132 [OLEAUT32.244]
3579 */
3580HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3581{
3582 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3583
3584 /* Check range of value.
3585 */
3586 if( bIn > CHAR_MAX )
3587 {
3588 return DISP_E_OVERFLOW;
3589 }
3590
3591 *pcOut = (CHAR) bIn;
3592
3593 return S_OK;
3594}
3595
3596/******************************************************************************
3597 * VarI1FromI232 [OLEAUT32.245]
3598 */
3599HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3600{
3601 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3602
3603 if( uiIn > CHAR_MAX )
3604 {
3605 return DISP_E_OVERFLOW;
3606 }
3607
3608 *pcOut = (CHAR) uiIn;
3609
3610 return S_OK;
3611}
3612
3613/******************************************************************************
3614 * VarI1FromI432 [OLEAUT32.246]
3615 */
3616HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3617{
3618 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3619
3620 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3621 {
3622 return DISP_E_OVERFLOW;
3623 }
3624
3625 *pcOut = (CHAR) lIn;
3626
3627 return S_OK;
3628}
3629
3630/******************************************************************************
3631 * VarI1FromR432 [OLEAUT32.247]
3632 */
3633HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3634{
3635 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3636
3637 fltIn = round( fltIn );
3638 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3639 {
3640 return DISP_E_OVERFLOW;
3641 }
3642
3643 *pcOut = (CHAR) fltIn;
3644
3645 return S_OK;
3646}
3647
3648/******************************************************************************
3649 * VarI1FromR832 [OLEAUT32.248]
3650 */
3651HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3652{
3653 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3654
3655 dblIn = round( dblIn );
3656 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3657 {
3658 return DISP_E_OVERFLOW;
3659 }
3660
3661 *pcOut = (CHAR) dblIn;
3662
3663 return S_OK;
3664}
3665
3666/******************************************************************************
3667 * VarI1FromDate32 [OLEAUT32.249]
3668 */
3669HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3670{
3671 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3672
3673 dateIn = round( dateIn );
3674 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3675 {
3676 return DISP_E_OVERFLOW;
3677 }
3678
3679 *pcOut = (CHAR) dateIn;
3680
3681 return S_OK;
3682}
3683
3684/******************************************************************************
3685 * VarI1FromStr32 [OLEAUT32.251]
3686 */
3687HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3688{
3689 double dValue = 0.0;
3690 LPSTR pNewString = NULL;
3691
3692 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3693
3694 /* Check if we have a valid argument
3695 */
3696 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3697 RemoveCharacterFromString( pNewString, "," );
3698 if( IsValidRealString( pNewString ) == FALSE )
3699 {
3700 return DISP_E_TYPEMISMATCH;
3701 }
3702
3703 /* Convert the valid string to a floating point number.
3704 */
3705 dValue = atof( pNewString );
3706
3707 /* We don't need the string anymore so free it.
3708 */
3709 HeapFree( GetProcessHeap(), 0, pNewString );
3710
3711 /* Check range of value.
3712 */
3713 dValue = round( dValue );
3714 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3715 {
3716 return DISP_E_OVERFLOW;
3717 }
3718
3719 *pcOut = (CHAR) dValue;
3720
3721 return S_OK;
3722}
3723
3724/******************************************************************************
3725 * VarI1FromBool32 [OLEAUT32.253]
3726 */
3727HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3728{
3729 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3730
3731 *pcOut = (CHAR) boolIn;
3732
3733 return S_OK;
3734}
3735
3736/******************************************************************************
3737 * VarI1FromUI232 [OLEAUT32.254]
3738 */
3739HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3740{
3741 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3742
3743 if( uiIn > CHAR_MAX )
3744 {
3745 return DISP_E_OVERFLOW;
3746 }
3747
3748 *pcOut = (CHAR) uiIn;
3749
3750 return S_OK;
3751}
3752
3753/******************************************************************************
3754 * VarI1FromUI432 [OLEAUT32.255]
3755 */
3756HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3757{
3758 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3759
3760 if( ulIn > CHAR_MAX )
3761 {
3762 return DISP_E_OVERFLOW;
3763 }
3764
3765 *pcOut = (CHAR) ulIn;
3766
3767 return S_OK;
3768}
3769
3770/**********************************************************************
3771 * VarI1FromCy32 [OLEAUT32.250]
3772 * Convert currency to signed char
3773 */
3774HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3775 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
3776
3777 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3778
3779 *pcOut = (CHAR)t;
3780 return S_OK;
3781}
3782
3783/******************************************************************************
3784 * VarUI2FromUI132 [OLEAUT32.257]
3785 */
3786HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3787{
3788 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3789
3790 *puiOut = (USHORT) bIn;
3791
3792 return S_OK;
3793}
3794
3795/******************************************************************************
3796 * VarUI2FromI232 [OLEAUT32.258]
3797 */
3798HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3799{
3800 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3801
3802 if( uiIn < UI2_MIN )
3803 {
3804 return DISP_E_OVERFLOW;
3805 }
3806
3807 *puiOut = (USHORT) uiIn;
3808
3809 return S_OK;
3810}
3811
3812/******************************************************************************
3813 * VarUI2FromI432 [OLEAUT32.259]
3814 */
3815HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3816{
3817 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3818
3819 if( lIn < UI2_MIN || lIn > UI2_MAX )
3820 {
3821 return DISP_E_OVERFLOW;
3822 }
3823
3824 *puiOut = (USHORT) lIn;
3825
3826 return S_OK;
3827}
3828
3829/******************************************************************************
3830 * VarUI2FromR432 [OLEAUT32.260]
3831 */
3832HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3833{
3834 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3835
3836 fltIn = round( fltIn );
3837 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3838 {
3839 return DISP_E_OVERFLOW;
3840 }
3841
3842 *puiOut = (USHORT) fltIn;
3843
3844 return S_OK;
3845}
3846
3847/******************************************************************************
3848 * VarUI2FromR832 [OLEAUT32.261]
3849 */
3850HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3851{
3852 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3853
3854 dblIn = round( dblIn );
3855 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3856 {
3857 return DISP_E_OVERFLOW;
3858 }
3859
3860 *puiOut = (USHORT) dblIn;
3861
3862 return S_OK;
3863}
3864
3865/******************************************************************************
3866 * VarUI2FromDate32 [OLEAUT32.262]
3867 */
3868HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3869{
3870 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3871
3872 dateIn = round( dateIn );
3873 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3874 {
3875 return DISP_E_OVERFLOW;
3876 }
3877
3878 *puiOut = (USHORT) dateIn;
3879
3880 return S_OK;
3881}
3882
3883/******************************************************************************
3884 * VarUI2FromStr32 [OLEAUT32.264]
3885 */
3886HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3887{
3888 double dValue = 0.0;
3889 LPSTR pNewString = NULL;
3890
3891 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3892
3893 /* Check if we have a valid argument
3894 */
3895 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3896 RemoveCharacterFromString( pNewString, "," );
3897 if( IsValidRealString( pNewString ) == FALSE )
3898 {
3899 return DISP_E_TYPEMISMATCH;
3900 }
3901
3902 /* Convert the valid string to a floating point number.
3903 */
3904 dValue = atof( pNewString );
3905
3906 /* We don't need the string anymore so free it.
3907 */
3908 HeapFree( GetProcessHeap(), 0, pNewString );
3909
3910 /* Check range of value.
3911 */
3912 dValue = round( dValue );
3913 if( dValue < UI2_MIN || dValue > UI2_MAX )
3914 {
3915 return DISP_E_OVERFLOW;
3916 }
3917
3918 *puiOut = (USHORT) dValue;
3919
3920 return S_OK;
3921}
3922
3923/******************************************************************************
3924 * VarUI2FromBool32 [OLEAUT32.266]
3925 */
3926HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3927{
3928 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3929
3930 *puiOut = (USHORT) boolIn;
3931
3932 return S_OK;
3933}
3934
3935/******************************************************************************
3936 * VarUI2FromI132 [OLEAUT32.267]
3937 */
3938HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3939{
3940 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3941
3942 *puiOut = (USHORT) cIn;
3943
3944 return S_OK;
3945}
3946
3947/******************************************************************************
3948 * VarUI2FromUI432 [OLEAUT32.268]
3949 */
3950HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3951{
3952 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3953
3954 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3955 {
3956 return DISP_E_OVERFLOW;
3957 }
3958
3959 *puiOut = (USHORT) ulIn;
3960
3961 return S_OK;
3962}
3963
3964/******************************************************************************
3965 * VarUI4FromStr32 [OLEAUT32.277]
3966 */
3967HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3968{
3969 double dValue = 0.0;
3970 LPSTR pNewString = NULL;
3971
3972 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3973
3974 /* Check if we have a valid argument
3975 */
3976 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3977 RemoveCharacterFromString( pNewString, "," );
3978 if( IsValidRealString( pNewString ) == FALSE )
3979 {
3980 return DISP_E_TYPEMISMATCH;
3981 }
3982
3983 /* Convert the valid string to a floating point number.
3984 */
3985 dValue = atof( pNewString );
3986
3987 /* We don't need the string anymore so free it.
3988 */
3989 HeapFree( GetProcessHeap(), 0, pNewString );
3990
3991 /* Check range of value.
3992 */
3993 dValue = round( dValue );
3994 if( dValue < UI4_MIN || dValue > UI4_MAX )
3995 {
3996 return DISP_E_OVERFLOW;
3997 }
3998
3999 *pulOut = (ULONG) dValue;
4000
4001 return S_OK;
4002}
4003
4004/**********************************************************************
4005 * VarUI2FromCy32 [OLEAUT32.263]
4006 * Convert currency to unsigned short
4007 */
4008HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4009 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
4010
4011 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4012
4013 *pusOut = (USHORT)t;
4014
4015 return S_OK;
4016}
4017
4018/******************************************************************************
4019 * VarUI4FromUI132 [OLEAUT32.270]
4020 */
4021HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4022{
4023 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4024
4025 *pulOut = (USHORT) bIn;
4026
4027 return S_OK;
4028}
4029
4030/******************************************************************************
4031 * VarUI4FromI232 [OLEAUT32.271]
4032 */
4033HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4034{
4035 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4036
4037 if( uiIn < UI4_MIN )
4038 {
4039 return DISP_E_OVERFLOW;
4040 }
4041
4042 *pulOut = (ULONG) uiIn;
4043
4044 return S_OK;
4045}
4046
4047/******************************************************************************
4048 * VarUI4FromI432 [OLEAUT32.272]
4049 */
4050HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4051{
4052 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4053
4054 if( lIn < UI4_MIN )
4055 {
4056 return DISP_E_OVERFLOW;
4057 }
4058
4059 *pulOut = (ULONG) lIn;
4060
4061 return S_OK;
4062}
4063
4064/******************************************************************************
4065 * VarUI4FromR432 [OLEAUT32.273]
4066 */
4067HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4068{
4069 fltIn = round( fltIn );
4070 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4071 {
4072 return DISP_E_OVERFLOW;
4073 }
4074
4075 *pulOut = (ULONG) fltIn;
4076
4077 return S_OK;
4078}
4079
4080/******************************************************************************
4081 * VarUI4FromR832 [OLEAUT32.274]
4082 */
4083HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4084{
4085 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4086
4087 dblIn = round( dblIn );
4088 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4089 {
4090 return DISP_E_OVERFLOW;
4091 }
4092
4093 *pulOut = (ULONG) dblIn;
4094
4095 return S_OK;
4096}
4097
4098/******************************************************************************
4099 * VarUI4FromDate32 [OLEAUT32.275]
4100 */
4101HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4102{
4103 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4104
4105 dateIn = round( dateIn );
4106 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4107 {
4108 return DISP_E_OVERFLOW;
4109 }
4110
4111 *pulOut = (ULONG) dateIn;
4112
4113 return S_OK;
4114}
4115
4116/******************************************************************************
4117 * VarUI4FromBool32 [OLEAUT32.279]
4118 */
4119HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4120{
4121 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4122
4123 *pulOut = (ULONG) boolIn;
4124
4125 return S_OK;
4126}
4127
4128/******************************************************************************
4129 * VarUI4FromI132 [OLEAUT32.280]
4130 */
4131HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4132{
4133 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4134
4135 *pulOut = (ULONG) cIn;
4136
4137 return S_OK;
4138}
4139
4140/******************************************************************************
4141 * VarUI4FromUI232 [OLEAUT32.281]
4142 */
4143HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4144{
4145 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4146
4147 *pulOut = (ULONG) uiIn;
4148
4149 return S_OK;
4150}
4151
4152/**********************************************************************
4153 * VarUI4FromCy32 [OLEAUT32.276]
4154 * Convert currency to unsigned long
4155 */
4156HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4157 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
4158
4159 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4160
4161 *pulOut = (ULONG)t;
4162
4163 return S_OK;
4164}
4165
4166/**********************************************************************
4167 * VarCyFromUI132 [OLEAUT32.98]
4168 * Convert unsigned char to currency
4169 */
4170HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4171 pcyOut->u.Hi = 0;
4172 pcyOut->u.Lo = ((ULONG)bIn) * 10000;
4173
4174 return S_OK;
4175}
4176
4177/**********************************************************************
4178 * VarCyFromI232 [OLEAUT32.99]
4179 * Convert signed short to currency
4180 */
4181HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4182 if (sIn < 0) pcyOut->u.Hi = -1;
4183 else pcyOut->u.Hi = 0;
4184 pcyOut->u.Lo = ((ULONG)sIn) * 10000;
4185
4186 return S_OK;
4187}
4188
4189/**********************************************************************
4190 * VarCyFromI432 [OLEAUT32.100]
4191 * Convert signed long to currency
4192 */
4193HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4194 double t = (double)lIn * (double)10000;
4195 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4196 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4197 if (lIn < 0) pcyOut->u.Hi--;
4198
4199 return S_OK;
4200}
4201
4202/**********************************************************************
4203 * VarCyFromR432 [OLEAUT32.101]
4204 * Convert float to currency
4205 */
4206HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4207 double t = round((double)fltIn * (double)10000);
4208 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4209 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4210 if (fltIn < 0) pcyOut->u.Hi--;
4211
4212 return S_OK;
4213}
4214
4215/**********************************************************************
4216 * VarCyFromR832 [OLEAUT32.102]
4217 * Convert double to currency
4218 */
4219HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4220 double t = round(dblIn * (double)10000);
4221 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4222 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4223 if (dblIn < 0) pcyOut->u.Hi--;
4224
4225 return S_OK;
4226}
4227
4228/**********************************************************************
4229 * VarCyFromDate32 [OLEAUT32.103]
4230 * Convert date to currency
4231 */
4232HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4233 double t = round((double)dateIn * (double)10000);
4234 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4235 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4236 if (dateIn < 0) pcyOut->u.Hi--;
4237
4238 return S_OK;
4239}
4240
4241/**********************************************************************
4242 * VarCyFromDate32 [OLEAUT32.104]
4243 */
4244HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4245 /* FIXME */
4246 return E_NOTIMPL;
4247}
4248
4249
4250/**********************************************************************
4251 * VarCyFromBool32 [OLEAUT32.106]
4252 * Convert boolean to currency
4253 */
4254HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4255 if (boolIn < 0) pcyOut->u.Hi = -1;
4256 else pcyOut->u.Hi = 0;
4257 pcyOut->u.Lo = (ULONG)boolIn * (ULONG)10000;
4258
4259 return S_OK;
4260}
4261
4262/**********************************************************************
4263 * VarCyFromI132 [OLEAUT32.225]
4264 * Convert signed char to currency
4265 */
4266HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4267 if (cIn < 0) pcyOut->u.Hi = -1;
4268 else pcyOut->u.Hi = 0;
4269 pcyOut->u.Lo = (ULONG)cIn * (ULONG)10000;
4270
4271 return S_OK;
4272}
4273
4274/**********************************************************************
4275 * VarCyFromUI232 [OLEAUT32.226]
4276 * Convert unsigned short to currency
4277 */
4278HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4279 pcyOut->u.Hi = 0;
4280 pcyOut->u.Lo = (ULONG)usIn * (ULONG)10000;
4281
4282 return S_OK;
4283}
4284
4285/**********************************************************************
4286 * VarCyFromUI432 [OLEAUT32.227]
4287 * Convert unsigned long to currency
4288 */
4289HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4290 double t = (double)ulIn * (double)10000;
4291 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4292 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4293
4294 return S_OK;
4295}
4296
4297
4298/**********************************************************************
4299 * DosDateTimeToVariantTime [OLEAUT32.14]
4300 * Convert dos representation of time to the date and time representation
4301 * stored in a variant.
4302 */
4303INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4304 DATE *pvtime)
4305{
4306 struct tm t;
4307
4308 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4309
4310 t.tm_sec = (wDosTime & 0x001f) * 2;
4311 t.tm_min = (wDosTime & 0x07e0) >> 5;
4312 t.tm_hour = (wDosTime & 0xf800) >> 11;
4313
4314 t.tm_mday = (wDosDate & 0x001f);
4315 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4316 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4317
4318 return TmToDATE( &t, pvtime );
4319}
4320
4321
Note: See TracBrowser for help on using the repository browser.