Release 990226.
[wine/gsoc-2012-control.git] / ole / variant.c
blob348cdc0c7b2cd8b8363781e2b027729bc163df68
1 /*
2 * VARIANT
4 * Copyright 1998 Jean-Claude Cote
6 * NOTES
7 * This implements the low-level and hi-level APIs for manipulating VARIANTs.
8 * The low-level APIs are used to do data coercion between different data types.
9 * The hi-level APIs are built on top of these low-level APIs and handle
10 * initialization, copying, destroying and changing the type of VARIANTs.
12 * TODO:
13 * - The Variant APIs are do not support international languages, currency
14 * types, number formating and calendar. They only support U.S. English format.
15 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
16 * The prototypes for these are commented out in the oleauto.h file. They need
17 * to be implemented and cases need to be added to the switches of the existing APIs.
18 * - The parsing of date for the VarDateFromStr is not complete.
19 * - The date manipulations do not support date prior to 1900.
20 * - The parsing does not accept has many formats has the Windows implementation.
23 #include "wintypes.h"
24 #include "oleauto.h"
25 #include "heap.h"
26 #include "debug.h"
27 #include "winerror.h"
28 #include "mapidefs.h"
29 #include "parsedt.h"
31 #include <string.h>
32 #include <stdlib.h>
33 #include <math.h>
34 #include <time.h>
36 #ifdef HAVE_FLOAT_H
37 # include <float.h>
38 #endif
40 #ifndef FLT_MAX
41 # ifdef MAXFLOAT
42 # define FLT_MAX MAXFLOAT
43 # else
44 # error "Can't find #define for MAXFLOAT/FLT_MAX"
45 # endif
46 #endif
48 #undef CHAR_MAX
49 #undef CHAR_MIN
50 static const char CHAR_MAX = 127;
51 static const char CHAR_MIN = -128;
52 static const BYTE UI1_MAX = 255;
53 static const BYTE UI1_MIN = 0;
54 static const unsigned short UI2_MAX = 65535;
55 static const unsigned short UI2_MIN = 0;
56 static const short I2_MAX = 32767;
57 static const short I2_MIN = -32768;
58 static const unsigned long UI4_MAX = 4294967295U;
59 static const unsigned long UI4_MIN = 0;
60 static const long I4_MAX = 2147483647;
61 static const long I4_MIN = -(2147483648U);
62 static const DATE DATE_MIN = -657434;
63 static const DATE DATE_MAX = 2958465;
66 /* This mask is used to set a flag in wReserved1 of
67 * the VARIANTARG structure. The flag indicates if
68 * the API function is using an inner variant or not.
70 #define PROCESSING_INNER_VARIANT 0x0001
72 /* General use buffer.
74 #define BUFFER_MAX 1024
75 static char pBuffer[BUFFER_MAX];
78 * Note a leap year is one that is a multiple of 4
79 * but not of a 100. Except if it is a multiple of
80 * 400 then it is a leap year.
82 /* According to postgeSQL date parsing functions there is
83 * a leap year when this expression is true.
84 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
85 * So according to this there is 365.2515 days in one year.
86 * One + every four years: 1/4 -> 365.25
87 * One - every 100 years: 1/100 -> 365.001
88 * One + every 400 years: 1/400 -> 365.0025
90 static const double DAYS_IN_ONE_YEAR = 365.2515;
94 /******************************************************************************
95 * DateTimeStringToTm [INTERNAL]
97 * Converts a string representation of a date and/or time to a tm structure.
99 * Note this function uses the postgresql date parsing functions found
100 * in the parsedt.c file.
102 * Returns TRUE if successfull.
104 * Note: This function does not parse the day of the week,
105 * daylight savings time. It will only fill the followin fields in
106 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
108 ******************************************************************************/
109 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
111 BOOL res = FALSE;
112 double fsec;
113 int tzp;
114 int dtype;
115 int nf;
116 char *field[MAXDATEFIELDS];
117 int ftype[MAXDATEFIELDS];
118 char lowstr[MAXDATELEN + 1];
119 char* strDateTime = NULL;
121 /* Convert the string to ASCII since this is the only format
122 * postgesql can handle.
124 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
126 if( strDateTime != NULL )
128 /* Make sure we don't go over the maximum length
129 * accepted by postgesql.
131 if( strlen( strDateTime ) <= MAXDATELEN )
133 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
135 if( lcid & VAR_DATEVALUEONLY )
137 /* Get the date information.
138 * It returns 0 if date information was
139 * present and 1 if only time information was present.
140 * -1 if an error occures.
142 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
144 /* Eliminate the time information since we
145 * were asked to get date information only.
147 pTm->tm_sec = 0;
148 pTm->tm_min = 0;
149 pTm->tm_hour = 0;
150 res = TRUE;
153 if( lcid & VAR_TIMEVALUEONLY )
155 /* Get time information only.
157 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
159 res = TRUE;
162 else
164 /* Get both date and time information.
165 * It returns 0 if date information was
166 * present and 1 if only time information was present.
167 * -1 if an error occures.
169 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
171 res = TRUE;
176 HeapFree( GetProcessHeap(), 0, strDateTime );
179 return res;
187 /******************************************************************************
188 * TmToDATE [INTERNAL]
190 * The date is implemented using an 8 byte floating-point number.
191 * Days are represented by whole numbers increments starting with 0.00 has
192 * being December 30 1899, midnight.
193 * The hours are expressed as the fractional part of the number.
194 * December 30 1899 at midnight = 0.00
195 * January 1 1900 at midnight = 2.00
196 * January 4 1900 at 6 AM = 5.25
197 * January 4 1900 at noon = 5.50
198 * December 29 1899 at midnight = -1.00
199 * December 18 1899 at midnight = -12.00
200 * December 18 1899 at 6AM = -12.25
201 * December 18 1899 at 6PM = -12.75
202 * December 19 1899 at midnight = -11.00
203 * The tm structure is as follows:
204 * struct tm {
205 * int tm_sec; seconds after the minute - [0,59]
206 * int tm_min; minutes after the hour - [0,59]
207 * int tm_hour; hours since midnight - [0,23]
208 * int tm_mday; day of the month - [1,31]
209 * int tm_mon; months since January - [0,11]
210 * int tm_year; years
211 * int tm_wday; days since Sunday - [0,6]
212 * int tm_yday; days since January 1 - [0,365]
213 * int tm_isdst; daylight savings time flag
214 * };
216 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
217 * and tm_isdst fields of the tm structure. And only converts years
218 * after 1900.
220 * Returns TRUE if successfull.
222 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
224 if( (pTm->tm_year - 1900) >= 0 )
226 int leapYear = 0;
228 /* Start at 1. This is the way DATE is defined.
229 * January 1, 1900 at Midnight is 1.00.
230 * January 1, 1900 at 6AM is 1.25.
231 * and so on.
233 *pDateOut = 1;
235 /* Add the number of days corresponding to
236 * tm_year.
238 *pDateOut += (pTm->tm_year - 1900) * 365;
240 /* Add the leap days in the previous years between now and 1900.
241 * Note a leap year is one that is a multiple of 4
242 * but not of a 100. Except if it is a multiple of
243 * 400 then it is a leap year.
245 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
246 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
247 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
249 /* Set the leap year flag if the
250 * current year specified by tm_year is a
251 * leap year. This will be used to add a day
252 * to the day count.
254 if( isleap( pTm->tm_year ) )
255 leapYear = 1;
257 /* Add the number of days corresponding to
258 * the month.
260 switch( pTm->tm_mon )
262 case 2:
263 *pDateOut += 31;
264 break;
265 case 3:
266 *pDateOut += ( 59 + leapYear );
267 break;
268 case 4:
269 *pDateOut += ( 90 + leapYear );
270 break;
271 case 5:
272 *pDateOut += ( 120 + leapYear );
273 break;
274 case 6:
275 *pDateOut += ( 151 + leapYear );
276 break;
277 case 7:
278 *pDateOut += ( 181 + leapYear );
279 break;
280 case 8:
281 *pDateOut += ( 212 + leapYear );
282 break;
283 case 9:
284 *pDateOut += ( 243 + leapYear );
285 break;
286 case 10:
287 *pDateOut += ( 273 + leapYear );
288 break;
289 case 11:
290 *pDateOut += ( 304 + leapYear );
291 break;
292 case 12:
293 *pDateOut += ( 334 + leapYear );
294 break;
296 /* Add the number of days in this month.
298 *pDateOut += pTm->tm_mday;
300 /* Add the number of seconds, minutes, and hours
301 * to the DATE. Note these are the fracionnal part
302 * of the DATE so seconds / number of seconds in a day.
304 *pDateOut += pTm->tm_hour / 24.0;
305 *pDateOut += pTm->tm_min / 1440.0;
306 *pDateOut += pTm->tm_sec / 86400.0;
307 return TRUE;
309 return FALSE;
312 /******************************************************************************
313 * DateToTm [INTERNAL]
315 * This function converst a windows DATE to a tm structure.
317 * It does not fill all the fields of the tm structure.
318 * Here is a list of the fields that are filled:
319 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
321 * Note this function does not support dates before the January 1, 1900
322 * or ( dateIn < 2.0 ).
324 * Returns TRUE if successfull.
326 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
328 /* Do not process dates smaller than January 1, 1900.
329 * Which corresponds to 2.0 in the windows DATE format.
331 if( dateIn >= 2.0 )
333 double decimalPart = 0.0;
334 double wholePart = 0.0;
336 memset(pTm,0,sizeof(*pTm));
338 /* Because of the nature of DATE format witch
339 * associates 2.0 to January 1, 1900. We will
340 * remove 1.0 from the whole part of the DATE
341 * so that in the following code 1.0
342 * will correspond to January 1, 1900.
343 * This simplyfies the processing of the DATE value.
345 dateIn -= 1.0;
347 wholePart = (double) floor( dateIn );
348 decimalPart = fmod( dateIn, wholePart );
350 if( !(lcid & VAR_TIMEVALUEONLY) )
352 int nDay = 0;
353 int leapYear = 0;
354 double yearsSince1900 = 0;
355 /* Start at 1900, this where the DATE time 0.0 starts.
357 pTm->tm_year = 1900;
358 /* find in what year the day in the "wholePart" falls into.
359 * add the value to the year field.
361 yearsSince1900 = floor( wholePart / DAYS_IN_ONE_YEAR );
362 pTm->tm_year += yearsSince1900;
363 /* determine if this is a leap year.
365 if( isleap( pTm->tm_year ) )
366 leapYear = 1;
367 /* find what day of that year does the "wholePart" corresponds to.
368 * Note: nDay is in [1-366] format
370 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
371 /* Set the tm_yday value.
372 * Note: The day is must be converted from [1-366] to [0-365]
374 /*pTm->tm_yday = nDay - 1;*/
375 /* find which mount this day corresponds to.
377 if( nDay <= 31 )
379 pTm->tm_mday = nDay;
380 pTm->tm_mon = 0;
382 else if( nDay <= ( 59 + leapYear ) )
384 pTm->tm_mday = nDay - 31;
385 pTm->tm_mon = 1;
387 else if( nDay <= ( 90 + leapYear ) )
389 pTm->tm_mday = nDay - ( 59 + leapYear );
390 pTm->tm_mon = 2;
392 else if( nDay <= ( 120 + leapYear ) )
394 pTm->tm_mday = nDay - ( 90 + leapYear );
395 pTm->tm_mon = 3;
397 else if( nDay <= ( 151 + leapYear ) )
399 pTm->tm_mday = nDay - ( 120 + leapYear );
400 pTm->tm_mon = 4;
402 else if( nDay <= ( 181 + leapYear ) )
404 pTm->tm_mday = nDay - ( 151 + leapYear );
405 pTm->tm_mon = 5;
407 else if( nDay <= ( 212 + leapYear ) )
409 pTm->tm_mday = nDay - ( 181 + leapYear );
410 pTm->tm_mon = 6;
412 else if( nDay <= ( 243 + leapYear ) )
414 pTm->tm_mday = nDay - ( 212 + leapYear );
415 pTm->tm_mon = 7;
417 else if( nDay <= ( 273 + leapYear ) )
419 pTm->tm_mday = nDay - ( 243 + leapYear );
420 pTm->tm_mon = 8;
422 else if( nDay <= ( 304 + leapYear ) )
424 pTm->tm_mday = nDay - ( 273 + leapYear );
425 pTm->tm_mon = 9;
427 else if( nDay <= ( 334 + leapYear ) )
429 pTm->tm_mday = nDay - ( 304 + leapYear );
430 pTm->tm_mon = 10;
432 else if( nDay <= ( 365 + leapYear ) )
434 pTm->tm_mday = nDay - ( 334 + leapYear );
435 pTm->tm_mon = 11;
438 if( !(lcid & VAR_DATEVALUEONLY) )
440 /* find the number of seconds in this day.
441 * fractional part times, hours, minutes, seconds.
443 pTm->tm_hour = (int) ( decimalPart * 24 );
444 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
445 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
447 return TRUE;
449 return FALSE;
454 /******************************************************************************
455 * SizeOfVariantData [INTERNAL]
457 * This function finds the size of the data referenced by a Variant based
458 * the type "vt" of the Variant.
460 static int SizeOfVariantData( VARIANT* parg )
462 int size = 0;
463 switch( parg->vt & VT_TYPEMASK )
465 case( VT_I2 ):
466 size = sizeof(short);
467 break;
468 case( VT_INT ):
469 size = sizeof(int);
470 break;
471 case( VT_I4 ):
472 size = sizeof(long);
473 break;
474 case( VT_UI1 ):
475 size = sizeof(BYTE);
476 break;
477 case( VT_UI2 ):
478 size = sizeof(unsigned short);
479 break;
480 case( VT_UINT ):
481 size = sizeof(unsigned int);
482 break;
483 case( VT_UI4 ):
484 size = sizeof(unsigned long);
485 break;
486 case( VT_R4 ):
487 size = sizeof(float);
488 break;
489 case( VT_R8 ):
490 size = sizeof(double);
491 break;
492 case( VT_DATE ):
493 size = sizeof(DATE);
494 break;
495 case( VT_BOOL ):
496 size = sizeof(VARIANT_BOOL);
497 break;
498 case( VT_BSTR ):
499 size = sizeof(void*);
500 break;
501 case( VT_CY ):
502 case( VT_DISPATCH ):
503 case( VT_UNKNOWN ):
504 case( VT_DECIMAL ):
505 default:
506 FIXME(ole,"Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
507 break;
510 return size;
512 /******************************************************************************
513 * StringDupAtoBstr [INTERNAL]
516 static BSTR StringDupAtoBstr( char* strIn )
518 BSTR bstr = NULL;
519 OLECHAR* pNewString = NULL;
520 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
521 bstr = SysAllocString( pNewString );
522 HeapFree( GetProcessHeap(), 0, pNewString );
523 return bstr;
526 /******************************************************************************
527 * round [INTERNAL]
529 * Round the double value to the nearest integer value.
531 static double round( double d )
533 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
534 BOOL bEvenNumber = FALSE;
535 int nSign = 0;
537 /* Save the sign of the number
539 nSign = (d >= 0.0) ? 1 : -1;
540 d = fabs( d );
542 /* Remove the decimals.
544 integerValue = floor( d );
546 /* Set the Even flag. This is used to round the number when
547 * the decimals are exactly 1/2. If the integer part is
548 * odd the number is rounded up. If the integer part
549 * is even the number is rounded down. Using this method
550 * numbers are rounded up|down half the time.
552 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
554 /* Remove the integral part of the number.
556 decimals = d - integerValue;
558 /* Note: Ceil returns the smallest integer that is greater that x.
559 * and floor returns the largest integer that is less than or equal to x.
561 if( decimals > 0.5 )
563 /* If the decimal part is greater than 1/2
565 roundedValue = ceil( d );
567 else if( decimals < 0.5 )
569 /* If the decimal part is smaller than 1/2
571 roundedValue = floor( d );
573 else
575 /* the decimals are exactly 1/2 so round according to
576 * the bEvenNumber flag.
578 if( bEvenNumber )
580 roundedValue = floor( d );
582 else
584 roundedValue = ceil( d );
588 return roundedValue * nSign;
591 /******************************************************************************
592 * RemoveCharacterFromString [INTERNAL]
594 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
596 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
598 LPSTR pNewString = NULL;
599 LPSTR strToken = NULL;
602 /* Check if we have a valid argument
604 if( str != NULL )
606 pNewString = strdup( str );
607 str[0] = '\0';
608 strToken = strtok( pNewString, strOfCharToRemove );
609 while( strToken != NULL ) {
610 strcat( str, strToken );
611 strToken = strtok( NULL, strOfCharToRemove );
613 free( pNewString );
615 return;
618 /******************************************************************************
619 * GetValidRealString [INTERNAL]
621 * Checks if the string is of proper format to be converted to a real value.
623 static BOOL IsValidRealString( LPSTR strRealString )
625 /* Real values that have a decimal point are required to either have
626 * digits before or after the decimal point. We will assume that
627 * we do not have any digits at either position. If we do encounter
628 * some we will disable this flag.
630 BOOL bDigitsRequired = TRUE;
631 /* Processed fields in the string representation of the real number.
633 BOOL bWhiteSpaceProcessed = FALSE;
634 BOOL bFirstSignProcessed = FALSE;
635 BOOL bFirstDigitsProcessed = FALSE;
636 BOOL bDecimalPointProcessed = FALSE;
637 BOOL bSecondDigitsProcessed = FALSE;
638 BOOL bExponentProcessed = FALSE;
639 BOOL bSecondSignProcessed = FALSE;
640 BOOL bThirdDigitsProcessed = FALSE;
641 /* Assume string parameter "strRealString" is valid and try to disprove it.
643 BOOL bValidRealString = TRUE;
645 /* Used to count the number of tokens in the "strRealString".
647 LPSTR strToken = NULL;
648 int nTokens = 0;
649 LPSTR pChar = NULL;
651 /* Check if we have a valid argument
653 if( strRealString == NULL )
655 bValidRealString = FALSE;
658 if( bValidRealString == TRUE )
660 /* Make sure we only have ONE token in the string.
662 strToken = strtok( strRealString, " " );
663 while( strToken != NULL ) {
664 nTokens++;
665 strToken = strtok( NULL, " " );
668 if( nTokens != 1 )
670 bValidRealString = FALSE;
675 /* Make sure this token contains only valid characters.
676 * The string argument to atof has the following form:
677 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
678 * Whitespace consists of space and|or <TAB> characters, which are ignored.
679 * Sign is either plus '+' or minus '-'.
680 * Digits are one or more decimal digits.
681 * Note: If no digits appear before the decimal point, at least one must
682 * appear after the decimal point.
683 * The decimal digits may be followed by an exponent.
684 * An Exponent consists of an introductory letter ( D, d, E, or e) and
685 * an optionally signed decimal integer.
687 pChar = strRealString;
688 while( bValidRealString == TRUE && *pChar != '\0' )
690 switch( *pChar )
692 /* If whitespace...
694 case ' ':
695 case '\t':
696 if( bWhiteSpaceProcessed ||
697 bFirstSignProcessed ||
698 bFirstDigitsProcessed ||
699 bDecimalPointProcessed ||
700 bSecondDigitsProcessed ||
701 bExponentProcessed ||
702 bSecondSignProcessed ||
703 bThirdDigitsProcessed )
705 bValidRealString = FALSE;
707 break;
708 /* If sign...
710 case '+':
711 case '-':
712 if( bFirstSignProcessed == FALSE )
714 if( bFirstDigitsProcessed ||
715 bDecimalPointProcessed ||
716 bSecondDigitsProcessed ||
717 bExponentProcessed ||
718 bSecondSignProcessed ||
719 bThirdDigitsProcessed )
721 bValidRealString = FALSE;
723 bWhiteSpaceProcessed = TRUE;
724 bFirstSignProcessed = TRUE;
726 else if( bSecondSignProcessed == FALSE )
728 /* Note: The exponent must be present in
729 * order to accept the second sign...
731 if( bExponentProcessed == FALSE ||
732 bThirdDigitsProcessed ||
733 bDigitsRequired )
735 bValidRealString = FALSE;
737 bFirstSignProcessed = TRUE;
738 bWhiteSpaceProcessed = TRUE;
739 bFirstDigitsProcessed = TRUE;
740 bDecimalPointProcessed = TRUE;
741 bSecondDigitsProcessed = TRUE;
742 bSecondSignProcessed = TRUE;
744 break;
746 /* If decimals...
748 case '0':
749 case '1':
750 case '2':
751 case '3':
752 case '4':
753 case '5':
754 case '6':
755 case '7':
756 case '8':
757 case '9':
758 if( bFirstDigitsProcessed == FALSE )
760 if( bDecimalPointProcessed ||
761 bSecondDigitsProcessed ||
762 bExponentProcessed ||
763 bSecondSignProcessed ||
764 bThirdDigitsProcessed )
766 bValidRealString = FALSE;
768 bFirstSignProcessed = TRUE;
769 bWhiteSpaceProcessed = TRUE;
770 /* We have found some digits before the decimal point
771 * so disable the "Digits required" flag.
773 bDigitsRequired = FALSE;
775 else if( bSecondDigitsProcessed == FALSE )
777 if( bExponentProcessed ||
778 bSecondSignProcessed ||
779 bThirdDigitsProcessed )
781 bValidRealString = FALSE;
783 bFirstSignProcessed = TRUE;
784 bWhiteSpaceProcessed = TRUE;
785 bFirstDigitsProcessed = TRUE;
786 bDecimalPointProcessed = TRUE;
787 /* We have found some digits after the decimal point
788 * so disable the "Digits required" flag.
790 bDigitsRequired = FALSE;
792 else if( bThirdDigitsProcessed == FALSE )
794 /* Getting here means everything else should be processed.
795 * If we get anything else than a decimal following this
796 * digit it will be flagged by the other cases, so
797 * we do not really need to do anything in here.
800 break;
801 /* If DecimalPoint...
803 case '.':
804 if( bDecimalPointProcessed ||
805 bSecondDigitsProcessed ||
806 bExponentProcessed ||
807 bSecondSignProcessed ||
808 bThirdDigitsProcessed )
810 bValidRealString = FALSE;
812 bFirstSignProcessed = TRUE;
813 bWhiteSpaceProcessed = TRUE;
814 bFirstDigitsProcessed = TRUE;
815 bDecimalPointProcessed = TRUE;
816 break;
817 /* If Exponent...
819 case 'e':
820 case 'E':
821 case 'd':
822 case 'D':
823 if( bExponentProcessed ||
824 bSecondSignProcessed ||
825 bThirdDigitsProcessed ||
826 bDigitsRequired )
828 bValidRealString = FALSE;
830 bFirstSignProcessed = TRUE;
831 bWhiteSpaceProcessed = TRUE;
832 bFirstDigitsProcessed = TRUE;
833 bDecimalPointProcessed = TRUE;
834 bSecondDigitsProcessed = TRUE;
835 bExponentProcessed = TRUE;
836 break;
837 default:
838 bValidRealString = FALSE;
839 break;
841 /* Process next character.
843 pChar++;
846 /* If the required digits were not present we have an invalid
847 * string representation of a real number.
849 if( bDigitsRequired == TRUE )
851 bValidRealString = FALSE;
854 return bValidRealString;
858 /******************************************************************************
859 * Coerce [INTERNAL]
861 * This function dispatches execution to the proper conversion API
862 * to do the necessary coercion.
864 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
866 HRESULT res = S_OK;
867 unsigned short vtFrom = 0;
868 vtFrom = ps->vt & VT_TYPEMASK;
870 /* Note: Since "long" and "int" values both have 4 bytes and are both signed integers
871 * "int" will be treated as "long" in the following code.
872 * The same goes for there unsigned versions.
875 switch( vt )
878 case( VT_EMPTY ):
879 res = VariantClear( pd );
880 break;
881 case( VT_NULL ):
882 res = VariantClear( pd );
883 if( res == S_OK )
885 pd->vt = VT_NULL;
887 break;
888 case( VT_I1 ):
889 switch( vtFrom )
891 case( VT_I1 ):
892 res = VariantCopy( pd, ps );
893 break;
894 case( VT_I2 ):
895 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
896 break;
897 case( VT_INT ):
898 case( VT_I4 ):
899 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
900 break;
901 case( VT_UI1 ):
902 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
903 break;
904 case( VT_UI2 ):
905 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
906 break;
907 case( VT_UINT ):
908 case( VT_UI4 ):
909 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
910 break;
911 case( VT_R4 ):
912 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
913 break;
914 case( VT_R8 ):
915 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
916 break;
917 case( VT_DATE ):
918 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
919 break;
920 case( VT_BOOL ):
921 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
922 break;
923 case( VT_BSTR ):
924 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
925 break;
926 case( VT_CY ):
927 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
928 case( VT_DISPATCH ):
929 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
930 case( VT_UNKNOWN ):
931 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
932 case( VT_DECIMAL ):
933 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
934 default:
935 res = DISP_E_TYPEMISMATCH;
936 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
937 break;
939 break;
941 case( VT_I2 ):
942 switch( vtFrom )
944 case( VT_I1 ):
945 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
946 break;
947 case( VT_I2 ):
948 res = VariantCopy( pd, ps );
949 break;
950 case( VT_INT ):
951 case( VT_I4 ):
952 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
953 break;
954 case( VT_UI1 ):
955 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
956 break;
957 case( VT_UI2 ):
958 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
959 break;
960 case( VT_UINT ):
961 case( VT_UI4 ):
962 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
963 break;
964 case( VT_R4 ):
965 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
966 break;
967 case( VT_R8 ):
968 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
969 break;
970 case( VT_DATE ):
971 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
972 break;
973 case( VT_BOOL ):
974 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
975 break;
976 case( VT_BSTR ):
977 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
978 break;
979 case( VT_CY ):
980 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
981 case( VT_DISPATCH ):
982 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
983 case( VT_UNKNOWN ):
984 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
985 case( VT_DECIMAL ):
986 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
987 default:
988 res = DISP_E_TYPEMISMATCH;
989 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
990 break;
992 break;
994 case( VT_INT ):
995 case( VT_I4 ):
996 switch( vtFrom )
998 case( VT_I1 ):
999 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1000 break;
1001 case( VT_I2 ):
1002 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1003 break;
1004 case( VT_INT ):
1005 case( VT_I4 ):
1006 res = VariantCopy( pd, ps );
1007 break;
1008 case( VT_UI1 ):
1009 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1010 break;
1011 case( VT_UI2 ):
1012 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1013 break;
1014 case( VT_UINT ):
1015 case( VT_UI4 ):
1016 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1017 break;
1018 case( VT_R4 ):
1019 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1020 break;
1021 case( VT_R8 ):
1022 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1023 break;
1024 case( VT_DATE ):
1025 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1026 break;
1027 case( VT_BOOL ):
1028 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1029 break;
1030 case( VT_BSTR ):
1031 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1032 break;
1033 case( VT_CY ):
1034 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1035 case( VT_DISPATCH ):
1036 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1037 case( VT_UNKNOWN ):
1038 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1039 case( VT_DECIMAL ):
1040 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1041 default:
1042 res = DISP_E_TYPEMISMATCH;
1043 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1044 break;
1046 break;
1048 case( VT_UI1 ):
1049 switch( vtFrom )
1051 case( VT_I1 ):
1052 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1053 break;
1054 case( VT_I2 ):
1055 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1056 break;
1057 case( VT_INT ):
1058 case( VT_I4 ):
1059 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1060 break;
1061 case( VT_UI1 ):
1062 res = VariantCopy( pd, ps );
1063 break;
1064 case( VT_UI2 ):
1065 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1066 break;
1067 case( VT_UINT ):
1068 case( VT_UI4 ):
1069 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1070 break;
1071 case( VT_R4 ):
1072 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1073 break;
1074 case( VT_R8 ):
1075 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1076 break;
1077 case( VT_DATE ):
1078 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1079 break;
1080 case( VT_BOOL ):
1081 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1082 break;
1083 case( VT_BSTR ):
1084 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1085 break;
1086 case( VT_CY ):
1087 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1088 case( VT_DISPATCH ):
1089 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1090 case( VT_UNKNOWN ):
1091 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1092 case( VT_DECIMAL ):
1093 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1094 default:
1095 res = DISP_E_TYPEMISMATCH;
1096 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1097 break;
1099 break;
1101 case( VT_UI2 ):
1102 switch( vtFrom )
1104 case( VT_I1 ):
1105 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1106 break;
1107 case( VT_I2 ):
1108 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1109 break;
1110 case( VT_INT ):
1111 case( VT_I4 ):
1112 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1113 break;
1114 case( VT_UI1 ):
1115 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1116 break;
1117 case( VT_UI2 ):
1118 res = VariantCopy( pd, ps );
1119 break;
1120 case( VT_UINT ):
1121 case( VT_UI4 ):
1122 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1123 break;
1124 case( VT_R4 ):
1125 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1126 break;
1127 case( VT_R8 ):
1128 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1129 break;
1130 case( VT_DATE ):
1131 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1132 break;
1133 case( VT_BOOL ):
1134 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1135 break;
1136 case( VT_BSTR ):
1137 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1138 break;
1139 case( VT_CY ):
1140 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1141 case( VT_DISPATCH ):
1142 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1143 case( VT_UNKNOWN ):
1144 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1145 case( VT_DECIMAL ):
1146 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1147 default:
1148 res = DISP_E_TYPEMISMATCH;
1149 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1150 break;
1152 break;
1154 case( VT_UINT ):
1155 case( VT_UI4 ):
1156 switch( vtFrom )
1158 case( VT_I1 ):
1159 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1160 break;
1161 case( VT_I2 ):
1162 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1163 break;
1164 case( VT_INT ):
1165 case( VT_I4 ):
1166 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1167 break;
1168 case( VT_UI1 ):
1169 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1170 break;
1171 case( VT_UI2 ):
1172 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1173 break;
1174 case( VT_UI4 ):
1175 res = VariantCopy( pd, ps );
1176 break;
1177 case( VT_R4 ):
1178 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1179 break;
1180 case( VT_R8 ):
1181 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1182 break;
1183 case( VT_DATE ):
1184 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1185 break;
1186 case( VT_BOOL ):
1187 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1188 break;
1189 case( VT_BSTR ):
1190 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1191 break;
1192 case( VT_CY ):
1193 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1194 case( VT_DISPATCH ):
1195 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1196 case( VT_UNKNOWN ):
1197 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1198 case( VT_DECIMAL ):
1199 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1200 default:
1201 res = DISP_E_TYPEMISMATCH;
1202 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1203 break;
1205 break;
1207 case( VT_R4 ):
1208 switch( vtFrom )
1210 case( VT_I1 ):
1211 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1212 break;
1213 case( VT_I2 ):
1214 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1215 break;
1216 case( VT_INT ):
1217 case( VT_I4 ):
1218 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1219 break;
1220 case( VT_UI1 ):
1221 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1222 break;
1223 case( VT_UI2 ):
1224 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1225 break;
1226 case( VT_UINT ):
1227 case( VT_UI4 ):
1228 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1229 break;
1230 case( VT_R4 ):
1231 res = VariantCopy( pd, ps );
1232 break;
1233 case( VT_R8 ):
1234 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1235 break;
1236 case( VT_DATE ):
1237 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1238 break;
1239 case( VT_BOOL ):
1240 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1241 break;
1242 case( VT_BSTR ):
1243 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1244 break;
1245 case( VT_CY ):
1246 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1247 case( VT_DISPATCH ):
1248 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1249 case( VT_UNKNOWN ):
1250 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1251 case( VT_DECIMAL ):
1252 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1253 default:
1254 res = DISP_E_TYPEMISMATCH;
1255 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1256 break;
1258 break;
1260 case( VT_R8 ):
1261 switch( vtFrom )
1263 case( VT_I1 ):
1264 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1265 break;
1266 case( VT_I2 ):
1267 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1268 break;
1269 case( VT_INT ):
1270 case( VT_I4 ):
1271 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1272 break;
1273 case( VT_UI1 ):
1274 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1275 break;
1276 case( VT_UI2 ):
1277 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1278 break;
1279 case( VT_UINT ):
1280 case( VT_UI4 ):
1281 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1282 break;
1283 case( VT_R4 ):
1284 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1285 break;
1286 case( VT_R8 ):
1287 res = VariantCopy( pd, ps );
1288 break;
1289 case( VT_DATE ):
1290 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1291 break;
1292 case( VT_BOOL ):
1293 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1294 break;
1295 case( VT_BSTR ):
1296 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1297 break;
1298 case( VT_CY ):
1299 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1300 case( VT_DISPATCH ):
1301 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1302 case( VT_UNKNOWN ):
1303 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1304 case( VT_DECIMAL ):
1305 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1306 default:
1307 res = DISP_E_TYPEMISMATCH;
1308 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1309 break;
1311 break;
1313 case( VT_DATE ):
1314 switch( vtFrom )
1316 case( VT_I1 ):
1317 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1318 break;
1319 case( VT_I2 ):
1320 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1321 break;
1322 case( VT_INT ):
1323 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1324 break;
1325 case( VT_I4 ):
1326 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1327 break;
1328 case( VT_UI1 ):
1329 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1330 break;
1331 case( VT_UI2 ):
1332 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1333 break;
1334 case( VT_UINT ):
1335 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1336 break;
1337 case( VT_UI4 ):
1338 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1339 break;
1340 case( VT_R4 ):
1341 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1342 break;
1343 case( VT_R8 ):
1344 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1345 break;
1346 case( VT_DATE ):
1347 res = VariantCopy( pd, ps );
1348 break;
1349 case( VT_BOOL ):
1350 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1351 break;
1352 case( VT_BSTR ):
1353 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1354 break;
1355 case( VT_CY ):
1356 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1357 case( VT_DISPATCH ):
1358 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1359 case( VT_UNKNOWN ):
1360 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1361 case( VT_DECIMAL ):
1362 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1363 default:
1364 res = DISP_E_TYPEMISMATCH;
1365 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1366 break;
1368 break;
1370 case( VT_BOOL ):
1371 switch( vtFrom )
1373 case( VT_I1 ):
1374 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1375 break;
1376 case( VT_I2 ):
1377 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1378 break;
1379 case( VT_INT ):
1380 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1381 break;
1382 case( VT_I4 ):
1383 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1384 break;
1385 case( VT_UI1 ):
1386 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1387 break;
1388 case( VT_UI2 ):
1389 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1390 break;
1391 case( VT_UINT ):
1392 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1393 break;
1394 case( VT_UI4 ):
1395 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1396 break;
1397 case( VT_R4 ):
1398 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1399 break;
1400 case( VT_R8 ):
1401 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1402 break;
1403 case( VT_DATE ):
1404 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1405 break;
1406 case( VT_BOOL ):
1407 res = VariantCopy( pd, ps );
1408 break;
1409 case( VT_BSTR ):
1410 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1411 break;
1412 case( VT_CY ):
1413 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1414 case( VT_DISPATCH ):
1415 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1416 case( VT_UNKNOWN ):
1417 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1418 case( VT_DECIMAL ):
1419 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1420 default:
1421 res = DISP_E_TYPEMISMATCH;
1422 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1423 break;
1425 break;
1427 case( VT_BSTR ):
1428 switch( vtFrom )
1430 case( VT_I1 ):
1431 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1432 break;
1433 case( VT_I2 ):
1434 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1435 break;
1436 case( VT_INT ):
1437 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1438 break;
1439 case( VT_I4 ):
1440 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1441 break;
1442 case( VT_UI1 ):
1443 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1444 break;
1445 case( VT_UI2 ):
1446 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1447 break;
1448 case( VT_UINT ):
1449 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1450 break;
1451 case( VT_UI4 ):
1452 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1453 break;
1454 case( VT_R4 ):
1455 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1456 break;
1457 case( VT_R8 ):
1458 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1459 break;
1460 case( VT_DATE ):
1461 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1462 break;
1463 case( VT_BOOL ):
1464 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1465 break;
1466 case( VT_BSTR ):
1467 res = VariantCopy( pd, ps );
1468 break;
1469 case( VT_CY ):
1470 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1471 case( VT_DISPATCH ):
1472 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1473 case( VT_UNKNOWN ):
1474 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1475 case( VT_DECIMAL ):
1476 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1477 default:
1478 res = DISP_E_TYPEMISMATCH;
1479 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1480 break;
1482 break;
1484 case( VT_CY ):
1485 switch( vtFrom )
1487 case( VT_I1 ):
1488 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1489 break;
1490 case( VT_I2 ):
1491 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1492 break;
1493 case( VT_INT ):
1494 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1495 break;
1496 case( VT_I4 ):
1497 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1498 break;
1499 case( VT_UI1 ):
1500 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1501 break;
1502 case( VT_UI2 ):
1503 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1504 break;
1505 case( VT_UINT ):
1506 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1507 break;
1508 case( VT_UI4 ):
1509 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1510 break;
1511 case( VT_R4 ):
1512 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1513 break;
1514 case( VT_R8 ):
1515 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1516 break;
1517 case( VT_DATE ):
1518 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1519 break;
1520 case( VT_BOOL ):
1521 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1522 break;
1523 case( VT_CY ):
1524 res = VariantCopy( pd, ps );
1525 break;
1526 case( VT_BSTR ):
1527 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1528 case( VT_DISPATCH ):
1529 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1530 case( VT_UNKNOWN ):
1531 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1532 case( VT_DECIMAL ):
1533 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1534 default:
1535 res = DISP_E_TYPEMISMATCH;
1536 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1537 break;
1539 break;
1541 default:
1542 res = DISP_E_TYPEMISMATCH;
1543 FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
1544 break;
1547 return res;
1550 /******************************************************************************
1551 * ValidateVtRange [INTERNAL]
1553 * Used internally by the hi-level Variant API to determine
1554 * if the vartypes are valid.
1556 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1558 /* if by value we must make sure it is in the
1559 * range of the valid types.
1561 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1563 return DISP_E_BADVARTYPE;
1565 return S_OK;
1569 /******************************************************************************
1570 * ValidateVartype [INTERNAL]
1572 * Used internally by the hi-level Variant API to determine
1573 * if the vartypes are valid.
1575 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1577 HRESULT res = S_OK;
1579 /* check if we have a valid argument.
1581 if( vt & VT_BYREF )
1583 /* if by reference check that the type is in
1584 * the valid range and that it is not of empty or null type
1586 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1587 ( vt & VT_TYPEMASK ) == VT_NULL ||
1588 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1590 res = E_INVALIDARG;
1594 else
1596 res = ValidateVtRange( vt );
1599 return res;
1602 /******************************************************************************
1603 * ValidateVt [INTERNAL]
1605 * Used internally by the hi-level Variant API to determine
1606 * if the vartypes are valid.
1608 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1610 HRESULT res = S_OK;
1612 /* check if we have a valid argument.
1614 if( vt & VT_BYREF )
1616 /* if by reference check that the type is in
1617 * the valid range and that it is not of empty or null type
1619 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1620 ( vt & VT_TYPEMASK ) == VT_NULL ||
1621 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1623 res = DISP_E_BADVARTYPE;
1627 else
1629 res = ValidateVtRange( vt );
1632 return res;
1639 /******************************************************************************
1640 * VariantInit32 [OLEAUT32.8]
1642 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1643 * contents of the Variant.
1645 void WINAPI VariantInit(VARIANTARG* pvarg)
1647 TRACE(ole,"(%p),stub\n",pvarg);
1649 pvarg->vt = VT_EMPTY;
1650 pvarg->wReserved1 = 0;
1651 pvarg->wReserved2= 0;
1652 pvarg->wReserved3= 0;
1654 return;
1657 /******************************************************************************
1658 * VariantClear32 [OLEAUT32.9]
1660 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1661 * sets the wReservedX field to 0. The current contents of the VARIANT are
1662 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1663 * released. If VT_ARRAY the array is freed.
1665 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1667 HRESULT res = S_OK;
1668 TRACE(ole,"(%p),stub\n",pvarg);
1670 res = ValidateVariantType( pvarg->vt );
1671 if( res == S_OK )
1673 if( !( pvarg->vt & VT_BYREF ) )
1675 switch( pvarg->vt & VT_TYPEMASK )
1677 case( VT_BSTR ):
1678 SysFreeString( pvarg->u.bstrVal );
1679 break;
1680 case( VT_DISPATCH ):
1681 break;
1682 case( VT_VARIANT ):
1683 break;
1684 case( VT_UNKNOWN ):
1685 break;
1686 case( VT_SAFEARRAY ):
1687 break;
1688 default:
1689 break;
1693 /* Set the fields to empty.
1695 pvarg->wReserved1 = 0;
1696 pvarg->wReserved2 = 0;
1697 pvarg->wReserved3 = 0;
1698 pvarg->vt = VT_EMPTY;
1701 return res;
1704 /******************************************************************************
1705 * VariantCopy32 [OLEAUT32.10]
1707 * Frees up the designation variant and makes a copy of the source.
1709 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1711 HRESULT res = S_OK;
1712 TRACE(ole,"(%p, %p),stub\n", pvargDest, pvargSrc);
1714 res = ValidateVariantType( pvargSrc->vt );
1715 /* If the pointer are to the same variant we don't need
1716 * to do anything.
1718 if( pvargDest != pvargSrc && res == S_OK )
1720 res = VariantClear( pvargDest );
1722 if( res == S_OK )
1724 if( pvargSrc->vt & VT_BYREF )
1726 /* In the case of byreference we only need
1727 * to copy the pointer.
1729 pvargDest->u = pvargSrc->u;
1730 pvargDest->vt = pvargSrc->vt;
1732 else
1734 /* In the case of by value we need to
1735 * copy the actuall value. In the case of
1736 * VT_BSTR a copy of the string is made,
1737 * if VT_ARRAY the entire array is copied
1738 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1739 * called to increment the object's reference count.
1741 switch( pvargSrc->vt & VT_TYPEMASK )
1743 case( VT_BSTR ):
1744 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1745 break;
1746 case( VT_DISPATCH ):
1747 break;
1748 case( VT_VARIANT ):
1749 break;
1750 case( VT_UNKNOWN ):
1751 break;
1752 case( VT_SAFEARRAY ):
1753 break;
1754 default:
1755 pvargDest->u = pvargSrc->u;
1756 break;
1758 pvargDest->vt = pvargSrc->vt;
1763 return res;
1767 /******************************************************************************
1768 * VariantCopyInd32 [OLEAUT32.11]
1770 * Frees up the destination variant and makes a copy of the source. If
1771 * the source is of type VT_BYREF it performs the necessary indirections.
1773 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1775 HRESULT res = S_OK;
1776 TRACE(ole,"(%p, %p),stub\n", pvargDest, pvargSrc);
1778 res = ValidateVariantType( pvargSrc->vt );
1779 if( res != S_OK )
1780 return res;
1782 if( pvargSrc->vt & VT_BYREF )
1784 VARIANTARG varg;
1785 VariantInit( &varg );
1786 /* handle the in place copy.
1788 if( pvargDest == pvargSrc )
1790 /* we will use a copy of the source instead.
1792 res = VariantCopy( &varg, pvargSrc );
1793 pvargSrc = &varg;
1795 if( res == S_OK )
1797 res = VariantClear( pvargDest );
1798 if( res == S_OK )
1800 /* In the case of by reference we need
1801 * to copy the date pointed to by the variant.
1803 /* Get the variant type.
1805 switch( pvargSrc->vt & VT_TYPEMASK )
1807 case( VT_BSTR ):
1808 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1809 break;
1810 case( VT_DISPATCH ):
1811 break;
1812 case( VT_VARIANT ):
1814 /* Prevent from cycling. According to tests on
1815 * VariantCopyInd in Windows and the documentation
1816 * this API dereferences the inner Variants to only one depth.
1817 * If the inner Variant itself contains an
1818 * other inner variant the E_INVALIDARG error is
1819 * returned.
1821 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1823 /* If we get here we are attempting to deference
1824 * an inner variant that that is itself contained
1825 * in an inner variant so report E_INVALIDARG error.
1827 res = E_INVALIDARG;
1829 else
1831 /* Set the processing inner variant flag.
1832 * We will set this flag in the inner variant
1833 * that will be passed to the VariantCopyInd function.
1835 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1836 /* Dereference the inner variant.
1838 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1841 break;
1842 case( VT_UNKNOWN ):
1843 break;
1844 case( VT_SAFEARRAY ):
1845 break;
1846 default:
1847 /* This is a by reference Variant which means that the union
1848 * part of the Variant contains a pointer to some data of
1849 * type "pvargSrc->vt & VT_TYPEMASK".
1850 * We will deference this data in a generic fashion using
1851 * the void pointer "Variant.u.byref".
1852 * We will copy this data into the union of the destination
1853 * Variant.
1855 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1856 break;
1858 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1861 /* this should not fail.
1863 VariantClear( &varg );
1865 else
1867 res = VariantCopy( pvargDest, pvargSrc );
1869 return res;
1872 /******************************************************************************
1873 * VariantChangeType32 [OLEAUT32.12]
1875 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1876 USHORT wFlags, VARTYPE vt)
1878 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1881 /******************************************************************************
1882 * VariantChangeTypeEx32 [OLEAUT32.147]
1884 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1885 LCID lcid, USHORT wFlags, VARTYPE vt)
1887 HRESULT res = S_OK;
1888 VARIANTARG varg;
1889 VariantInit( &varg );
1891 TRACE(ole,"(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1893 /* validate our source argument.
1895 res = ValidateVariantType( pvargSrc->vt );
1897 /* validate the vartype.
1899 if( res == S_OK )
1901 res = ValidateVt( vt );
1904 /* if we are doing an in-place conversion make a copy of the source.
1906 if( res == S_OK && pvargDest == pvargSrc )
1908 res = VariantCopy( &varg, pvargSrc );
1909 pvargSrc = &varg;
1912 if( res == S_OK )
1914 /* free up the destination variant.
1916 res = VariantClear( pvargDest );
1919 if( res == S_OK )
1921 if( pvargSrc->vt & VT_BYREF )
1923 /* Convert the source variant to a "byvalue" variant.
1925 VARIANTARG Variant;
1926 VariantInit( &Variant );
1927 res = VariantCopyInd( &Variant, pvargSrc );
1928 if( res == S_OK )
1930 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
1931 /* this should not fail.
1933 VariantClear( &Variant );
1937 else
1939 /* Use the current "byvalue" source variant.
1941 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
1944 /* this should not fail.
1946 VariantClear( &varg );
1948 return res;
1954 /******************************************************************************
1955 * VarUI1FromI232 [OLEAUT32.130]
1957 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
1959 TRACE( ole, "( %d, %p ), stub\n", sIn, pbOut );
1961 /* Check range of value.
1963 if( sIn < UI1_MIN || sIn > UI1_MAX )
1965 return DISP_E_OVERFLOW;
1968 *pbOut = (BYTE) sIn;
1970 return S_OK;
1973 /******************************************************************************
1974 * VarUI1FromI432 [OLEAUT32.131]
1976 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
1978 TRACE( ole, "( %ld, %p ), stub\n", lIn, pbOut );
1980 /* Check range of value.
1982 if( lIn < UI1_MIN || lIn > UI1_MAX )
1984 return DISP_E_OVERFLOW;
1987 *pbOut = (BYTE) lIn;
1989 return S_OK;
1993 /******************************************************************************
1994 * VarUI1FromR432 [OLEAUT32.132]
1996 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
1998 TRACE( ole, "( %f, %p ), stub\n", fltIn, pbOut );
2000 /* Check range of value.
2002 fltIn = round( fltIn );
2003 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2005 return DISP_E_OVERFLOW;
2008 *pbOut = (BYTE) fltIn;
2010 return S_OK;
2013 /******************************************************************************
2014 * VarUI1FromR832 [OLEAUT32.133]
2016 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2018 TRACE( ole, "( %f, %p ), stub\n", dblIn, pbOut );
2020 /* Check range of value.
2022 dblIn = round( dblIn );
2023 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2025 return DISP_E_OVERFLOW;
2028 *pbOut = (BYTE) dblIn;
2030 return S_OK;
2033 /******************************************************************************
2034 * VarUI1FromDate32 [OLEAUT32.135]
2036 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2038 TRACE( ole, "( %f, %p ), stub\n", dateIn, pbOut );
2040 /* Check range of value.
2042 dateIn = round( dateIn );
2043 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2045 return DISP_E_OVERFLOW;
2048 *pbOut = (BYTE) dateIn;
2050 return S_OK;
2053 /******************************************************************************
2054 * VarUI1FromBool32 [OLEAUT32.138]
2056 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2058 TRACE( ole, "( %d, %p ), stub\n", boolIn, pbOut );
2060 *pbOut = (BYTE) boolIn;
2062 return S_OK;
2065 /******************************************************************************
2066 * VarUI1FromI132 [OLEAUT32.237]
2068 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2070 TRACE( ole, "( %c, %p ), stub\n", cIn, pbOut );
2072 *pbOut = cIn;
2074 return S_OK;
2077 /******************************************************************************
2078 * VarUI1FromUI232 [OLEAUT32.238]
2080 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2082 TRACE( ole, "( %d, %p ), stub\n", uiIn, pbOut );
2084 /* Check range of value.
2086 if( uiIn > UI1_MAX )
2088 return DISP_E_OVERFLOW;
2091 *pbOut = (BYTE) uiIn;
2093 return S_OK;
2096 /******************************************************************************
2097 * VarUI1FromUI432 [OLEAUT32.239]
2099 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2101 TRACE( ole, "( %ld, %p ), stub\n", ulIn, pbOut );
2103 /* Check range of value.
2105 if( ulIn > UI1_MAX )
2107 return DISP_E_OVERFLOW;
2110 *pbOut = (BYTE) ulIn;
2112 return S_OK;
2116 /******************************************************************************
2117 * VarUI1FromStr32 [OLEAUT32.54]
2119 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2121 double dValue = 0.0;
2122 LPSTR pNewString = NULL;
2124 TRACE( ole, "( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2126 /* Check if we have a valid argument
2128 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2129 RemoveCharacterFromString( pNewString, "," );
2130 if( IsValidRealString( pNewString ) == FALSE )
2132 return DISP_E_TYPEMISMATCH;
2135 /* Convert the valid string to a floating point number.
2137 dValue = atof( pNewString );
2139 /* We don't need the string anymore so free it.
2141 HeapFree( GetProcessHeap(), 0 , pNewString );
2143 /* Check range of value.
2145 dValue = round( dValue );
2146 if( dValue < UI1_MIN || dValue > UI1_MAX )
2148 return DISP_E_OVERFLOW;
2151 *pbOut = (BYTE) dValue;
2153 return S_OK;
2156 /**********************************************************************
2157 * VarUI1FromCy32 [OLEAUT32.134]
2158 * Convert currency to unsigned char
2160 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2161 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2163 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2165 *pbOut = (BYTE)t;
2166 return S_OK;
2169 /******************************************************************************
2170 * VarI2FromUI132 [OLEAUT32.48]
2172 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2174 TRACE( ole, "( 0x%08x, %p ), stub\n", bIn, psOut );
2176 *psOut = (short) bIn;
2178 return S_OK;
2181 /******************************************************************************
2182 * VarI2FromI432 [OLEAUT32.49]
2184 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2186 TRACE( ole, "( %lx, %p ), stub\n", lIn, psOut );
2188 /* Check range of value.
2190 if( lIn < I2_MIN || lIn > I2_MAX )
2192 return DISP_E_OVERFLOW;
2195 *psOut = (short) lIn;
2197 return S_OK;
2200 /******************************************************************************
2201 * VarI2FromR432 [OLEAUT32.50]
2203 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2205 TRACE( ole, "( %f, %p ), stub\n", fltIn, psOut );
2207 /* Check range of value.
2209 fltIn = round( fltIn );
2210 if( fltIn < I2_MIN || fltIn > I2_MAX )
2212 return DISP_E_OVERFLOW;
2215 *psOut = (short) fltIn;
2217 return S_OK;
2220 /******************************************************************************
2221 * VarI2FromR832 [OLEAUT32.51]
2223 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2225 TRACE( ole, "( %f, %p ), stub\n", dblIn, psOut );
2227 /* Check range of value.
2229 dblIn = round( dblIn );
2230 if( dblIn < I2_MIN || dblIn > I2_MAX )
2232 return DISP_E_OVERFLOW;
2235 *psOut = (short) dblIn;
2237 return S_OK;
2240 /******************************************************************************
2241 * VarI2FromDate32 [OLEAUT32.53]
2243 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2245 TRACE( ole, "( %f, %p ), stub\n", dateIn, psOut );
2247 /* Check range of value.
2249 dateIn = round( dateIn );
2250 if( dateIn < I2_MIN || dateIn > I2_MAX )
2252 return DISP_E_OVERFLOW;
2255 *psOut = (short) dateIn;
2257 return S_OK;
2260 /******************************************************************************
2261 * VarI2FromBool32 [OLEAUT32.56]
2263 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2265 TRACE( ole, "( %d, %p ), stub\n", boolIn, psOut );
2267 *psOut = (short) boolIn;
2269 return S_OK;
2272 /******************************************************************************
2273 * VarI2FromI132 [OLEAUT32.48]
2275 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2277 TRACE( ole, "( %c, %p ), stub\n", cIn, psOut );
2279 *psOut = (short) cIn;
2281 return S_OK;
2284 /******************************************************************************
2285 * VarI2FromUI232 [OLEAUT32.206]
2287 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2289 TRACE( ole, "( %d, %p ), stub\n", uiIn, psOut );
2291 /* Check range of value.
2293 if( uiIn > I2_MAX )
2295 return DISP_E_OVERFLOW;
2298 *psOut = (short) uiIn;
2300 return S_OK;
2303 /******************************************************************************
2304 * VarI2FromUI432 [OLEAUT32.49]
2306 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2308 TRACE( ole, "( %lx, %p ), stub\n", ulIn, psOut );
2310 /* Check range of value.
2312 if( ulIn < I2_MIN || ulIn > I2_MAX )
2314 return DISP_E_OVERFLOW;
2317 *psOut = (short) ulIn;
2319 return S_OK;
2322 /******************************************************************************
2323 * VarI2FromStr32 [OLEAUT32.54]
2325 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2327 double dValue = 0.0;
2328 LPSTR pNewString = NULL;
2330 TRACE( ole, "( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2332 /* Check if we have a valid argument
2334 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2335 RemoveCharacterFromString( pNewString, "," );
2336 if( IsValidRealString( pNewString ) == FALSE )
2338 return DISP_E_TYPEMISMATCH;
2341 /* Convert the valid string to a floating point number.
2343 dValue = atof( pNewString );
2345 /* We don't need the string anymore so free it.
2347 HeapFree( GetProcessHeap(), 0, pNewString );
2349 /* Check range of value.
2351 dValue = round( dValue );
2352 if( dValue < I2_MIN || dValue > I2_MAX )
2354 return DISP_E_OVERFLOW;
2357 *psOut = (short) dValue;
2359 return S_OK;
2362 /**********************************************************************
2363 * VarI2FromCy32 [OLEAUT32.52]
2364 * Convert currency to signed short
2366 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2367 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2369 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2371 *psOut = (SHORT)t;
2372 return S_OK;
2375 /******************************************************************************
2376 * VarI4FromUI132 [OLEAUT32.58]
2378 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2380 TRACE( ole, "( %X, %p ), stub\n", bIn, plOut );
2382 *plOut = (LONG) bIn;
2384 return S_OK;
2388 /******************************************************************************
2389 * VarI4FromR432 [OLEAUT32.60]
2391 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2393 TRACE( ole, "( %f, %p ), stub\n", fltIn, plOut );
2395 /* Check range of value.
2397 fltIn = round( fltIn );
2398 if( fltIn < I4_MIN || fltIn > I4_MAX )
2400 return DISP_E_OVERFLOW;
2403 *plOut = (LONG) fltIn;
2405 return S_OK;
2408 /******************************************************************************
2409 * VarI4FromR832 [OLEAUT32.61]
2411 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2413 TRACE( ole, "( %f, %p ), stub\n", dblIn, plOut );
2415 /* Check range of value.
2417 dblIn = round( dblIn );
2418 if( dblIn < I4_MIN || dblIn > I4_MAX )
2420 return DISP_E_OVERFLOW;
2423 *plOut = (LONG) dblIn;
2425 return S_OK;
2428 /******************************************************************************
2429 * VarI4FromDate32 [OLEAUT32.63]
2431 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2433 TRACE( ole, "( %f, %p ), stub\n", dateIn, plOut );
2435 /* Check range of value.
2437 dateIn = round( dateIn );
2438 if( dateIn < I4_MIN || dateIn > I4_MAX )
2440 return DISP_E_OVERFLOW;
2443 *plOut = (LONG) dateIn;
2445 return S_OK;
2448 /******************************************************************************
2449 * VarI4FromBool32 [OLEAUT32.66]
2451 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2453 TRACE( ole, "( %d, %p ), stub\n", boolIn, plOut );
2455 *plOut = (LONG) boolIn;
2457 return S_OK;
2460 /******************************************************************************
2461 * VarI4FromI132 [OLEAUT32.209]
2463 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2465 TRACE( ole, "( %c, %p ), stub\n", cIn, plOut );
2467 *plOut = (LONG) cIn;
2469 return S_OK;
2472 /******************************************************************************
2473 * VarI4FromUI232 [OLEAUT32.210]
2475 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2477 TRACE( ole, "( %d, %p ), stub\n", uiIn, plOut );
2479 *plOut = (LONG) uiIn;
2481 return S_OK;
2484 /******************************************************************************
2485 * VarI4FromUI432 [OLEAUT32.211]
2487 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2489 TRACE( ole, "( %lx, %p ), stub\n", ulIn, plOut );
2491 /* Check range of value.
2493 if( ulIn < I4_MIN || ulIn > I4_MAX )
2495 return DISP_E_OVERFLOW;
2498 *plOut = (LONG) ulIn;
2500 return S_OK;
2503 /******************************************************************************
2504 * VarI4FromI232 [OLEAUT32.59]
2506 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2508 TRACE( ole, "( %d, %p ), stub\n", sIn, plOut );
2510 *plOut = (LONG) sIn;
2512 return S_OK;
2515 /******************************************************************************
2516 * VarI4FromStr32 [OLEAUT32.64]
2518 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2520 double dValue = 0.0;
2521 LPSTR pNewString = NULL;
2523 TRACE( ole, "( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2525 /* Check if we have a valid argument
2527 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2528 RemoveCharacterFromString( pNewString, "," );
2529 if( IsValidRealString( pNewString ) == FALSE )
2531 return DISP_E_TYPEMISMATCH;
2534 /* Convert the valid string to a floating point number.
2536 dValue = atof( pNewString );
2538 /* We don't need the string anymore so free it.
2540 HeapFree( GetProcessHeap(), 0, pNewString );
2542 /* Check range of value.
2544 dValue = round( dValue );
2545 if( dValue < I4_MIN || dValue > I4_MAX )
2547 return DISP_E_OVERFLOW;
2550 *plOut = (LONG) dValue;
2552 return S_OK;
2555 /**********************************************************************
2556 * VarI4FromCy32 [OLEAUT32.62]
2557 * Convert currency to signed long
2559 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2560 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2562 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2564 *plOut = (LONG)t;
2565 return S_OK;
2568 /******************************************************************************
2569 * VarR4FromUI132 [OLEAUT32.68]
2571 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2573 TRACE( ole, "( %X, %p ), stub\n", bIn, pfltOut );
2575 *pfltOut = (FLOAT) bIn;
2577 return S_OK;
2580 /******************************************************************************
2581 * VarR4FromI232 [OLEAUT32.69]
2583 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2585 TRACE( ole, "( %d, %p ), stub\n", sIn, pfltOut );
2587 *pfltOut = (FLOAT) sIn;
2589 return S_OK;
2592 /******************************************************************************
2593 * VarR4FromI432 [OLEAUT32.70]
2595 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2597 TRACE( ole, "( %lx, %p ), stub\n", lIn, pfltOut );
2599 *pfltOut = (FLOAT) lIn;
2601 return S_OK;
2604 /******************************************************************************
2605 * VarR4FromR832 [OLEAUT32.71]
2607 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2609 TRACE( ole, "( %f, %p ), stub\n", dblIn, pfltOut );
2611 /* Check range of value.
2613 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2615 return DISP_E_OVERFLOW;
2618 *pfltOut = (FLOAT) dblIn;
2620 return S_OK;
2623 /******************************************************************************
2624 * VarR4FromDate32 [OLEAUT32.73]
2626 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2628 TRACE( ole, "( %f, %p ), stub\n", dateIn, pfltOut );
2630 /* Check range of value.
2632 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2634 return DISP_E_OVERFLOW;
2637 *pfltOut = (FLOAT) dateIn;
2639 return S_OK;
2642 /******************************************************************************
2643 * VarR4FromBool32 [OLEAUT32.76]
2645 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2647 TRACE( ole, "( %d, %p ), stub\n", boolIn, pfltOut );
2649 *pfltOut = (FLOAT) boolIn;
2651 return S_OK;
2654 /******************************************************************************
2655 * VarR4FromI132 [OLEAUT32.213]
2657 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2659 TRACE( ole, "( %c, %p ), stub\n", cIn, pfltOut );
2661 *pfltOut = (FLOAT) cIn;
2663 return S_OK;
2666 /******************************************************************************
2667 * VarR4FromUI232 [OLEAUT32.214]
2669 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2671 TRACE( ole, "( %d, %p ), stub\n", uiIn, pfltOut );
2673 *pfltOut = (FLOAT) uiIn;
2675 return S_OK;
2678 /******************************************************************************
2679 * VarR4FromUI432 [OLEAUT32.215]
2681 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2683 TRACE( ole, "( %ld, %p ), stub\n", ulIn, pfltOut );
2685 *pfltOut = (FLOAT) ulIn;
2687 return S_OK;
2690 /******************************************************************************
2691 * VarR4FromStr32 [OLEAUT32.74]
2693 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2695 double dValue = 0.0;
2696 LPSTR pNewString = NULL;
2698 TRACE( ole, "( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2700 /* Check if we have a valid argument
2702 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2703 RemoveCharacterFromString( pNewString, "," );
2704 if( IsValidRealString( pNewString ) == FALSE )
2706 return DISP_E_TYPEMISMATCH;
2709 /* Convert the valid string to a floating point number.
2711 dValue = atof( pNewString );
2713 /* We don't need the string anymore so free it.
2715 HeapFree( GetProcessHeap(), 0, pNewString );
2717 /* Check range of value.
2719 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2721 return DISP_E_OVERFLOW;
2724 *pfltOut = (FLOAT) dValue;
2726 return S_OK;
2729 /**********************************************************************
2730 * VarR4FromCy32 [OLEAUT32.72]
2731 * Convert currency to float
2733 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2734 *pfltOut = (FLOAT)((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2736 return S_OK;
2739 /******************************************************************************
2740 * VarR8FromUI132 [OLEAUT32.68]
2742 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2744 TRACE( ole, "( %d, %p ), stub\n", bIn, pdblOut );
2746 *pdblOut = (double) bIn;
2748 return S_OK;
2751 /******************************************************************************
2752 * VarR8FromI232 [OLEAUT32.69]
2754 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2756 TRACE( ole, "( %d, %p ), stub\n", sIn, pdblOut );
2758 *pdblOut = (double) sIn;
2760 return S_OK;
2763 /******************************************************************************
2764 * VarR8FromI432 [OLEAUT32.70]
2766 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2768 TRACE( ole, "( %ld, %p ), stub\n", lIn, pdblOut );
2770 *pdblOut = (double) lIn;
2772 return S_OK;
2775 /******************************************************************************
2776 * VarR8FromR432 [OLEAUT32.81]
2778 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2780 TRACE( ole, "( %f, %p ), stub\n", fltIn, pdblOut );
2782 *pdblOut = (double) fltIn;
2784 return S_OK;
2787 /******************************************************************************
2788 * VarR8FromDate32 [OLEAUT32.83]
2790 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2792 TRACE( ole, "( %f, %p ), stub\n", dateIn, pdblOut );
2794 *pdblOut = (double) dateIn;
2796 return S_OK;
2799 /******************************************************************************
2800 * VarR8FromBool32 [OLEAUT32.86]
2802 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2804 TRACE( ole, "( %d, %p ), stub\n", boolIn, pdblOut );
2806 *pdblOut = (double) boolIn;
2808 return S_OK;
2811 /******************************************************************************
2812 * VarR8FromI132 [OLEAUT32.217]
2814 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2816 TRACE( ole, "( %c, %p ), stub\n", cIn, pdblOut );
2818 *pdblOut = (double) cIn;
2820 return S_OK;
2823 /******************************************************************************
2824 * VarR8FromUI232 [OLEAUT32.218]
2826 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2828 TRACE( ole, "( %d, %p ), stub\n", uiIn, pdblOut );
2830 *pdblOut = (double) uiIn;
2832 return S_OK;
2835 /******************************************************************************
2836 * VarR8FromUI432 [OLEAUT32.219]
2838 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2840 TRACE( ole, "( %ld, %p ), stub\n", ulIn, pdblOut );
2842 *pdblOut = (double) ulIn;
2844 return S_OK;
2847 /******************************************************************************
2848 * VarR8FromStr32 [OLEAUT32.84]
2850 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2852 double dValue = 0.0;
2853 LPSTR pNewString = NULL;
2855 TRACE( ole, "( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2857 /* Check if we have a valid argument
2859 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2860 RemoveCharacterFromString( pNewString, "," );
2861 if( IsValidRealString( pNewString ) == FALSE )
2863 return DISP_E_TYPEMISMATCH;
2866 /* Convert the valid string to a floating point number.
2868 dValue = atof( pNewString );
2870 /* We don't need the string anymore so free it.
2872 HeapFree( GetProcessHeap(), 0, pNewString );
2874 *pdblOut = dValue;
2876 return S_OK;
2879 /**********************************************************************
2880 * VarR8FromCy32 [OLEAUT32.82]
2881 * Convert currency to double
2883 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2884 *pdblOut = (double)((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
2886 return S_OK;
2889 /******************************************************************************
2890 * VarDateFromUI132 [OLEAUT32.]
2892 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2894 TRACE( ole, "( %d, %p ), stub\n", bIn, pdateOut );
2896 *pdateOut = (DATE) bIn;
2898 return S_OK;
2901 /******************************************************************************
2902 * VarDateFromI232 [OLEAUT32.222]
2904 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2906 TRACE( ole, "( %d, %p ), stub\n", sIn, pdateOut );
2908 *pdateOut = (DATE) sIn;
2910 return S_OK;
2913 /******************************************************************************
2914 * VarDateFromI432 [OLEAUT32.90]
2916 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
2918 TRACE( ole, "( %ld, %p ), stub\n", lIn, pdateOut );
2920 if( lIn < DATE_MIN || lIn > DATE_MAX )
2922 return DISP_E_OVERFLOW;
2925 *pdateOut = (DATE) lIn;
2927 return S_OK;
2930 /******************************************************************************
2931 * VarDateFromR432 [OLEAUT32.91]
2933 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
2935 TRACE( ole, "( %f, %p ), stub\n", fltIn, pdateOut );
2937 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
2939 return DISP_E_OVERFLOW;
2942 *pdateOut = (DATE) fltIn;
2944 return S_OK;
2947 /******************************************************************************
2948 * VarDateFromR832 [OLEAUT32.92]
2950 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
2952 TRACE( ole, "( %f, %p ), stub\n", dblIn, pdateOut );
2954 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
2956 return DISP_E_OVERFLOW;
2959 *pdateOut = (DATE) dblIn;
2961 return S_OK;
2964 /******************************************************************************
2965 * VarDateFromStr32 [OLEAUT32.94]
2966 * The string representing the date is composed of two parts, a date and time.
2968 * The format of the time is has follows:
2969 * hh[:mm][:ss][AM|PM]
2970 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
2971 * of space and/or tab characters, which are ignored.
2973 * The formats for the date part are has follows:
2974 * mm/[dd/][yy]yy
2975 * [dd/]mm/[yy]yy
2976 * [yy]yy/mm/dd
2977 * January dd[,] [yy]yy
2978 * dd January [yy]yy
2979 * [yy]yy January dd
2980 * Whitespace can be inserted anywhere between these tokens.
2982 * The formats for the date and time string are has follows.
2983 * date[whitespace][time]
2984 * [time][whitespace]date
2986 * These are the only characters allowed in a string representing a date and time:
2987 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
2989 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
2991 HRESULT ret = S_OK;
2992 struct tm TM = { 0,0,0,0,0,0,0,0,0 };
2994 TRACE( ole, "( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
2996 if( DateTimeStringToTm( strIn, lcid, &TM ) )
2998 if( TmToDATE( &TM, pdateOut ) == FALSE )
3000 ret = E_INVALIDARG;
3003 else
3005 ret = DISP_E_TYPEMISMATCH;
3009 return ret;
3012 /******************************************************************************
3013 * VarDateFromI132 [OLEAUT32.221]
3015 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3017 TRACE( ole, "( %c, %p ), stub\n", cIn, pdateOut );
3019 *pdateOut = (DATE) cIn;
3021 return S_OK;
3024 /******************************************************************************
3025 * VarDateFromUI232 [OLEAUT32.222]
3027 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3029 TRACE( ole, "( %d, %p ), stub\n", uiIn, pdateOut );
3031 if( uiIn > DATE_MAX )
3033 return DISP_E_OVERFLOW;
3036 *pdateOut = (DATE) uiIn;
3038 return S_OK;
3041 /******************************************************************************
3042 * VarDateFromUI432 [OLEAUT32.223]
3044 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3046 TRACE( ole, "( %ld, %p ), stub\n", ulIn, pdateOut );
3048 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3050 return DISP_E_OVERFLOW;
3053 *pdateOut = (DATE) ulIn;
3055 return S_OK;
3058 /******************************************************************************
3059 * VarDateFromBool32 [OLEAUT32.96]
3061 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3063 TRACE( ole, "( %d, %p ), stub\n", boolIn, pdateOut );
3065 *pdateOut = (DATE) boolIn;
3067 return S_OK;
3070 /**********************************************************************
3071 * VarDateFromCy32 [OLEAUT32.93]
3072 * Convert currency to date
3074 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3075 *pdateOut = (DATE)((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
3077 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3078 return S_OK;
3081 /******************************************************************************
3082 * VarBstrFromUI132 [OLEAUT32.108]
3084 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3086 TRACE( ole, "( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3087 sprintf( pBuffer, "%d", bVal );
3089 *pbstrOut = StringDupAtoBstr( pBuffer );
3091 return S_OK;
3094 /******************************************************************************
3095 * VarBstrFromI232 [OLEAUT32.109]
3097 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3099 TRACE( ole, "( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3100 sprintf( pBuffer, "%d", iVal );
3101 *pbstrOut = StringDupAtoBstr( pBuffer );
3103 return S_OK;
3106 /******************************************************************************
3107 * VarBstrFromI432 [OLEAUT32.110]
3109 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3111 TRACE( ole, "( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3113 sprintf( pBuffer, "%ld", lIn );
3114 *pbstrOut = StringDupAtoBstr( pBuffer );
3116 return S_OK;
3119 /******************************************************************************
3120 * VarBstrFromR432 [OLEAUT32.111]
3122 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3124 TRACE( ole, "( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3126 sprintf( pBuffer, "%.7g", fltIn );
3127 *pbstrOut = StringDupAtoBstr( pBuffer );
3129 return S_OK;
3132 /******************************************************************************
3133 * VarBstrFromR832 [OLEAUT32.112]
3135 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3137 TRACE( ole, "( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3139 sprintf( pBuffer, "%.15g", dblIn );
3140 *pbstrOut = StringDupAtoBstr( pBuffer );
3142 return S_OK;
3145 /******************************************************************************
3146 * VarBstrFromDate32 [OLEAUT32.114]
3148 * The date is implemented using an 8 byte floating-point number.
3149 * Days are represented by whole numbers increments starting with 0.00 has
3150 * being December 30 1899, midnight.
3151 * The hours are expressed as the fractional part of the number.
3152 * December 30 1899 at midnight = 0.00
3153 * January 1 1900 at midnight = 2.00
3154 * January 4 1900 at 6 AM = 5.25
3155 * January 4 1900 at noon = 5.50
3156 * December 29 1899 at midnight = -1.00
3157 * December 18 1899 at midnight = -12.00
3158 * December 18 1899 at 6AM = -12.25
3159 * December 18 1899 at 6PM = -12.75
3160 * December 19 1899 at midnight = -11.00
3161 * The tm structure is as follows:
3162 * struct tm {
3163 * int tm_sec; seconds after the minute - [0,59]
3164 * int tm_min; minutes after the hour - [0,59]
3165 * int tm_hour; hours since midnight - [0,23]
3166 * int tm_mday; day of the month - [1,31]
3167 * int tm_mon; months since January - [0,11]
3168 * int tm_year; years
3169 * int tm_wday; days since Sunday - [0,6]
3170 * int tm_yday; days since January 1 - [0,365]
3171 * int tm_isdst; daylight savings time flag
3172 * };
3174 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3176 struct tm TM = {0,0,0,0,0,0,0,0,0};
3178 TRACE( ole, "( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3180 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3182 return E_INVALIDARG;
3185 if( lcid & VAR_DATEVALUEONLY )
3186 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3187 else if( lcid & VAR_TIMEVALUEONLY )
3188 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3189 else
3190 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3192 *pbstrOut = StringDupAtoBstr( pBuffer );
3194 return S_OK;
3197 /******************************************************************************
3198 * VarBstrFromBool32 [OLEAUT32.116]
3200 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3202 TRACE( ole, "( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3204 if( boolIn == VARIANT_FALSE )
3206 sprintf( pBuffer, "False" );
3208 else
3210 sprintf( pBuffer, "True" );
3213 *pbstrOut = StringDupAtoBstr( pBuffer );
3215 return S_OK;
3218 /******************************************************************************
3219 * VarBstrFromI132 [OLEAUT32.229]
3221 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3223 TRACE( ole, "( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3224 sprintf( pBuffer, "%d", cIn );
3225 *pbstrOut = StringDupAtoBstr( pBuffer );
3227 return S_OK;
3230 /******************************************************************************
3231 * VarBstrFromUI232 [OLEAUT32.230]
3233 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3235 TRACE( ole, "( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3236 sprintf( pBuffer, "%d", uiIn );
3237 *pbstrOut = StringDupAtoBstr( pBuffer );
3239 return S_OK;
3242 /******************************************************************************
3243 * VarBstrFromUI432 [OLEAUT32.231]
3245 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3247 TRACE( ole, "( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3248 sprintf( pBuffer, "%ld", ulIn );
3249 *pbstrOut = StringDupAtoBstr( pBuffer );
3251 return S_OK;
3254 /******************************************************************************
3255 * VarBoolFromUI132 [OLEAUT32.118]
3257 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3259 TRACE( ole, "( %d, %p ), stub\n", bIn, pboolOut );
3261 if( bIn == 0 )
3263 *pboolOut = VARIANT_FALSE;
3265 else
3267 *pboolOut = VARIANT_TRUE;
3270 return S_OK;
3273 /******************************************************************************
3274 * VarBoolFromI232 [OLEAUT32.119]
3276 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3278 TRACE( ole, "( %d, %p ), stub\n", sIn, pboolOut );
3280 if( sIn == 0 )
3282 *pboolOut = VARIANT_FALSE;
3284 else
3286 *pboolOut = VARIANT_TRUE;
3289 return S_OK;
3292 /******************************************************************************
3293 * VarBoolFromI432 [OLEAUT32.120]
3295 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3297 TRACE( ole, "( %ld, %p ), stub\n", lIn, pboolOut );
3299 if( lIn == 0 )
3301 *pboolOut = VARIANT_FALSE;
3303 else
3305 *pboolOut = VARIANT_TRUE;
3308 return S_OK;
3311 /******************************************************************************
3312 * VarBoolFromR432 [OLEAUT32.121]
3314 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3316 TRACE( ole, "( %f, %p ), stub\n", fltIn, pboolOut );
3318 if( fltIn == 0.0 )
3320 *pboolOut = VARIANT_FALSE;
3322 else
3324 *pboolOut = VARIANT_TRUE;
3327 return S_OK;
3330 /******************************************************************************
3331 * VarBoolFromR832 [OLEAUT32.122]
3333 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3335 TRACE( ole, "( %f, %p ), stub\n", dblIn, pboolOut );
3337 if( dblIn == 0.0 )
3339 *pboolOut = VARIANT_FALSE;
3341 else
3343 *pboolOut = VARIANT_TRUE;
3346 return S_OK;
3349 /******************************************************************************
3350 * VarBoolFromDate32 [OLEAUT32.123]
3352 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3354 TRACE( ole, "( %f, %p ), stub\n", dateIn, pboolOut );
3356 if( dateIn == 0.0 )
3358 *pboolOut = VARIANT_FALSE;
3360 else
3362 *pboolOut = VARIANT_TRUE;
3365 return S_OK;
3368 /******************************************************************************
3369 * VarBoolFromStr32 [OLEAUT32.125]
3371 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3373 HRESULT ret = S_OK;
3374 char* pNewString = NULL;
3376 TRACE( ole, "( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3378 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3380 if( pNewString == NULL || strlen( pNewString ) == 0 )
3382 ret = DISP_E_TYPEMISMATCH;
3385 if( ret == S_OK )
3387 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3389 *pboolOut = VARIANT_TRUE;
3391 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3393 *pboolOut = VARIANT_FALSE;
3395 else
3397 /* Try converting the string to a floating point number.
3399 double dValue = 0.0;
3400 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3401 if( res != S_OK )
3403 ret = DISP_E_TYPEMISMATCH;
3405 else if( dValue == 0.0 )
3407 *pboolOut = VARIANT_FALSE;
3409 else
3411 *pboolOut = VARIANT_TRUE;
3416 HeapFree( GetProcessHeap(), 0, pNewString );
3418 return ret;
3421 /******************************************************************************
3422 * VarBoolFromI132 [OLEAUT32.233]
3424 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3426 TRACE( ole, "( %c, %p ), stub\n", cIn, pboolOut );
3428 if( cIn == 0 )
3430 *pboolOut = VARIANT_FALSE;
3432 else
3434 *pboolOut = VARIANT_TRUE;
3437 return S_OK;
3440 /******************************************************************************
3441 * VarBoolFromUI232 [OLEAUT32.234]
3443 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3445 TRACE( ole, "( %d, %p ), stub\n", uiIn, pboolOut );
3447 if( uiIn == 0 )
3449 *pboolOut = VARIANT_FALSE;
3451 else
3453 *pboolOut = VARIANT_TRUE;
3456 return S_OK;
3459 /******************************************************************************
3460 * VarBoolFromUI432 [OLEAUT32.235]
3462 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3464 TRACE( ole, "( %ld, %p ), stub\n", ulIn, pboolOut );
3466 if( ulIn == 0 )
3468 *pboolOut = VARIANT_FALSE;
3470 else
3472 *pboolOut = VARIANT_TRUE;
3475 return S_OK;
3478 /**********************************************************************
3479 * VarBoolFromCy32 [OLEAUT32.124]
3480 * Convert currency to boolean
3482 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3483 if (cyIn.u.Hi || cyIn.u.Lo) *pboolOut = -1;
3484 else *pboolOut = 0;
3486 return S_OK;
3489 /******************************************************************************
3490 * VarI1FromUI132 [OLEAUT32.244]
3492 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3494 TRACE( ole, "( %d, %p ), stub\n", bIn, pcOut );
3496 /* Check range of value.
3498 if( bIn > CHAR_MAX )
3500 return DISP_E_OVERFLOW;
3503 *pcOut = (CHAR) bIn;
3505 return S_OK;
3508 /******************************************************************************
3509 * VarI1FromI232 [OLEAUT32.245]
3511 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3513 TRACE( ole, "( %d, %p ), stub\n", uiIn, pcOut );
3515 if( uiIn > CHAR_MAX )
3517 return DISP_E_OVERFLOW;
3520 *pcOut = (CHAR) uiIn;
3522 return S_OK;
3525 /******************************************************************************
3526 * VarI1FromI432 [OLEAUT32.246]
3528 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3530 TRACE( ole, "( %ld, %p ), stub\n", lIn, pcOut );
3532 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3534 return DISP_E_OVERFLOW;
3537 *pcOut = (CHAR) lIn;
3539 return S_OK;
3542 /******************************************************************************
3543 * VarI1FromR432 [OLEAUT32.247]
3545 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3547 TRACE( ole, "( %f, %p ), stub\n", fltIn, pcOut );
3549 fltIn = round( fltIn );
3550 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3552 return DISP_E_OVERFLOW;
3555 *pcOut = (CHAR) fltIn;
3557 return S_OK;
3560 /******************************************************************************
3561 * VarI1FromR832 [OLEAUT32.248]
3563 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3565 TRACE( ole, "( %f, %p ), stub\n", dblIn, pcOut );
3567 dblIn = round( dblIn );
3568 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3570 return DISP_E_OVERFLOW;
3573 *pcOut = (CHAR) dblIn;
3575 return S_OK;
3578 /******************************************************************************
3579 * VarI1FromDate32 [OLEAUT32.249]
3581 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3583 TRACE( ole, "( %f, %p ), stub\n", dateIn, pcOut );
3585 dateIn = round( dateIn );
3586 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3588 return DISP_E_OVERFLOW;
3591 *pcOut = (CHAR) dateIn;
3593 return S_OK;
3596 /******************************************************************************
3597 * VarI1FromStr32 [OLEAUT32.251]
3599 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3601 double dValue = 0.0;
3602 LPSTR pNewString = NULL;
3604 TRACE( ole, "( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3606 /* Check if we have a valid argument
3608 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3609 RemoveCharacterFromString( pNewString, "," );
3610 if( IsValidRealString( pNewString ) == FALSE )
3612 return DISP_E_TYPEMISMATCH;
3615 /* Convert the valid string to a floating point number.
3617 dValue = atof( pNewString );
3619 /* We don't need the string anymore so free it.
3621 HeapFree( GetProcessHeap(), 0, pNewString );
3623 /* Check range of value.
3625 dValue = round( dValue );
3626 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3628 return DISP_E_OVERFLOW;
3631 *pcOut = (CHAR) dValue;
3633 return S_OK;
3636 /******************************************************************************
3637 * VarI1FromBool32 [OLEAUT32.253]
3639 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3641 TRACE( ole, "( %d, %p ), stub\n", boolIn, pcOut );
3643 *pcOut = (CHAR) boolIn;
3645 return S_OK;
3648 /******************************************************************************
3649 * VarI1FromUI232 [OLEAUT32.254]
3651 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3653 TRACE( ole, "( %d, %p ), stub\n", uiIn, pcOut );
3655 if( uiIn > CHAR_MAX )
3657 return DISP_E_OVERFLOW;
3660 *pcOut = (CHAR) uiIn;
3662 return S_OK;
3665 /******************************************************************************
3666 * VarI1FromUI432 [OLEAUT32.255]
3668 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3670 TRACE( ole, "( %ld, %p ), stub\n", ulIn, pcOut );
3672 if( ulIn > CHAR_MAX )
3674 return DISP_E_OVERFLOW;
3677 *pcOut = (CHAR) ulIn;
3679 return S_OK;
3682 /**********************************************************************
3683 * VarI1FromCy32 [OLEAUT32.250]
3684 * Convert currency to signed char
3686 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3687 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
3689 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3691 *pcOut = (CHAR)t;
3692 return S_OK;
3695 /******************************************************************************
3696 * VarUI2FromUI132 [OLEAUT32.257]
3698 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3700 TRACE( ole, "( %d, %p ), stub\n", bIn, puiOut );
3702 *puiOut = (USHORT) bIn;
3704 return S_OK;
3707 /******************************************************************************
3708 * VarUI2FromI232 [OLEAUT32.258]
3710 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3712 TRACE( ole, "( %d, %p ), stub\n", uiIn, puiOut );
3714 if( uiIn < UI2_MIN )
3716 return DISP_E_OVERFLOW;
3719 *puiOut = (USHORT) uiIn;
3721 return S_OK;
3724 /******************************************************************************
3725 * VarUI2FromI432 [OLEAUT32.259]
3727 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3729 TRACE( ole, "( %ld, %p ), stub\n", lIn, puiOut );
3731 if( lIn < UI2_MIN || lIn > UI2_MAX )
3733 return DISP_E_OVERFLOW;
3736 *puiOut = (USHORT) lIn;
3738 return S_OK;
3741 /******************************************************************************
3742 * VarUI2FromR432 [OLEAUT32.260]
3744 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3746 TRACE( ole, "( %f, %p ), stub\n", fltIn, puiOut );
3748 fltIn = round( fltIn );
3749 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3751 return DISP_E_OVERFLOW;
3754 *puiOut = (USHORT) fltIn;
3756 return S_OK;
3759 /******************************************************************************
3760 * VarUI2FromR832 [OLEAUT32.261]
3762 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3764 TRACE( ole, "( %f, %p ), stub\n", dblIn, puiOut );
3766 dblIn = round( dblIn );
3767 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3769 return DISP_E_OVERFLOW;
3772 *puiOut = (USHORT) dblIn;
3774 return S_OK;
3777 /******************************************************************************
3778 * VarUI2FromDate32 [OLEAUT32.262]
3780 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3782 TRACE( ole, "( %f, %p ), stub\n", dateIn, puiOut );
3784 dateIn = round( dateIn );
3785 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3787 return DISP_E_OVERFLOW;
3790 *puiOut = (USHORT) dateIn;
3792 return S_OK;
3795 /******************************************************************************
3796 * VarUI2FromStr32 [OLEAUT32.264]
3798 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3800 double dValue = 0.0;
3801 LPSTR pNewString = NULL;
3803 TRACE( ole, "( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3805 /* Check if we have a valid argument
3807 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3808 RemoveCharacterFromString( pNewString, "," );
3809 if( IsValidRealString( pNewString ) == FALSE )
3811 return DISP_E_TYPEMISMATCH;
3814 /* Convert the valid string to a floating point number.
3816 dValue = atof( pNewString );
3818 /* We don't need the string anymore so free it.
3820 HeapFree( GetProcessHeap(), 0, pNewString );
3822 /* Check range of value.
3824 dValue = round( dValue );
3825 if( dValue < UI2_MIN || dValue > UI2_MAX )
3827 return DISP_E_OVERFLOW;
3830 *puiOut = (USHORT) dValue;
3832 return S_OK;
3835 /******************************************************************************
3836 * VarUI2FromBool32 [OLEAUT32.266]
3838 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3840 TRACE( ole, "( %d, %p ), stub\n", boolIn, puiOut );
3842 *puiOut = (USHORT) boolIn;
3844 return S_OK;
3847 /******************************************************************************
3848 * VarUI2FromI132 [OLEAUT32.267]
3850 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3852 TRACE( ole, "( %c, %p ), stub\n", cIn, puiOut );
3854 *puiOut = (USHORT) cIn;
3856 return S_OK;
3859 /******************************************************************************
3860 * VarUI2FromUI432 [OLEAUT32.268]
3862 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3864 TRACE( ole, "( %ld, %p ), stub\n", ulIn, puiOut );
3866 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3868 return DISP_E_OVERFLOW;
3871 *puiOut = (USHORT) ulIn;
3873 return S_OK;
3876 /******************************************************************************
3877 * VarUI4FromStr32 [OLEAUT32.277]
3879 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3881 double dValue = 0.0;
3882 LPSTR pNewString = NULL;
3884 TRACE( ole, "( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3886 /* Check if we have a valid argument
3888 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3889 RemoveCharacterFromString( pNewString, "," );
3890 if( IsValidRealString( pNewString ) == FALSE )
3892 return DISP_E_TYPEMISMATCH;
3895 /* Convert the valid string to a floating point number.
3897 dValue = atof( pNewString );
3899 /* We don't need the string anymore so free it.
3901 HeapFree( GetProcessHeap(), 0, pNewString );
3903 /* Check range of value.
3905 dValue = round( dValue );
3906 if( dValue < UI4_MIN || dValue > UI4_MAX )
3908 return DISP_E_OVERFLOW;
3911 *pulOut = (ULONG) dValue;
3913 return S_OK;
3916 /**********************************************************************
3917 * VarUI2FromCy32 [OLEAUT32.263]
3918 * Convert currency to unsigned short
3920 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
3921 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
3923 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
3925 *pusOut = (USHORT)t;
3927 return S_OK;
3930 /******************************************************************************
3931 * VarUI4FromUI132 [OLEAUT32.270]
3933 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
3935 TRACE( ole, "( %d, %p ), stub\n", bIn, pulOut );
3937 *pulOut = (USHORT) bIn;
3939 return S_OK;
3942 /******************************************************************************
3943 * VarUI4FromI232 [OLEAUT32.271]
3945 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
3947 TRACE( ole, "( %d, %p ), stub\n", uiIn, pulOut );
3949 if( uiIn < UI4_MIN )
3951 return DISP_E_OVERFLOW;
3954 *pulOut = (ULONG) uiIn;
3956 return S_OK;
3959 /******************************************************************************
3960 * VarUI4FromI432 [OLEAUT32.272]
3962 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
3964 TRACE( ole, "( %ld, %p ), stub\n", lIn, pulOut );
3966 if( lIn < UI4_MIN )
3968 return DISP_E_OVERFLOW;
3971 *pulOut = (ULONG) lIn;
3973 return S_OK;
3976 /******************************************************************************
3977 * VarUI4FromR432 [OLEAUT32.273]
3979 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
3981 fltIn = round( fltIn );
3982 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
3984 return DISP_E_OVERFLOW;
3987 *pulOut = (ULONG) fltIn;
3989 return S_OK;
3992 /******************************************************************************
3993 * VarUI4FromR832 [OLEAUT32.274]
3995 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
3997 TRACE( ole, "( %f, %p ), stub\n", dblIn, pulOut );
3999 dblIn = round( dblIn );
4000 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4002 return DISP_E_OVERFLOW;
4005 *pulOut = (ULONG) dblIn;
4007 return S_OK;
4010 /******************************************************************************
4011 * VarUI4FromDate32 [OLEAUT32.275]
4013 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4015 TRACE( ole, "( %f, %p ), stub\n", dateIn, pulOut );
4017 dateIn = round( dateIn );
4018 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4020 return DISP_E_OVERFLOW;
4023 *pulOut = (ULONG) dateIn;
4025 return S_OK;
4028 /******************************************************************************
4029 * VarUI4FromBool32 [OLEAUT32.279]
4031 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4033 TRACE( ole, "( %d, %p ), stub\n", boolIn, pulOut );
4035 *pulOut = (ULONG) boolIn;
4037 return S_OK;
4040 /******************************************************************************
4041 * VarUI4FromI132 [OLEAUT32.280]
4043 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4045 TRACE( ole, "( %c, %p ), stub\n", cIn, pulOut );
4047 *pulOut = (ULONG) cIn;
4049 return S_OK;
4052 /******************************************************************************
4053 * VarUI4FromUI232 [OLEAUT32.281]
4055 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4057 TRACE( ole, "( %d, %p ), stub\n", uiIn, pulOut );
4059 *pulOut = (ULONG) uiIn;
4061 return S_OK;
4064 /**********************************************************************
4065 * VarUI4FromCy32 [OLEAUT32.276]
4066 * Convert currency to unsigned long
4068 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4069 double t = round((((double)cyIn.u.Hi * 4294967296.0) + (double)cyIn.u.Lo) / 10000);
4071 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4073 *pulOut = (ULONG)t;
4075 return S_OK;
4078 /**********************************************************************
4079 * VarCyFromUI132 [OLEAUT32.98]
4080 * Convert unsigned char to currency
4082 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4083 pcyOut->u.Hi = 0;
4084 pcyOut->u.Lo = ((ULONG)bIn) * 10000;
4086 return S_OK;
4089 /**********************************************************************
4090 * VarCyFromI232 [OLEAUT32.99]
4091 * Convert signed short to currency
4093 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4094 if (sIn < 0) pcyOut->u.Hi = -1;
4095 else pcyOut->u.Hi = 0;
4096 pcyOut->u.Lo = ((ULONG)sIn) * 10000;
4098 return S_OK;
4101 /**********************************************************************
4102 * VarCyFromI432 [OLEAUT32.100]
4103 * Convert signed long to currency
4105 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4106 double t = (double)lIn * (double)10000;
4107 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4108 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4109 if (lIn < 0) pcyOut->u.Hi--;
4111 return S_OK;
4114 /**********************************************************************
4115 * VarCyFromR432 [OLEAUT32.101]
4116 * Convert float to currency
4118 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4119 double t = round((double)fltIn * (double)10000);
4120 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4121 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4122 if (fltIn < 0) pcyOut->u.Hi--;
4124 return S_OK;
4127 /**********************************************************************
4128 * VarCyFromR832 [OLEAUT32.102]
4129 * Convert double to currency
4131 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4132 double t = round(dblIn * (double)10000);
4133 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4134 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4135 if (dblIn < 0) pcyOut->u.Hi--;
4137 return S_OK;
4140 /**********************************************************************
4141 * VarCyFromDate32 [OLEAUT32.103]
4142 * Convert date to currency
4144 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4145 double t = round((double)dateIn * (double)10000);
4146 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4147 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4148 if (dateIn < 0) pcyOut->u.Hi--;
4150 return S_OK;
4153 /**********************************************************************
4154 * VarCyFromBool32 [OLEAUT32.106]
4155 * Convert boolean to currency
4157 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4158 if (boolIn < 0) pcyOut->u.Hi = -1;
4159 else pcyOut->u.Hi = 0;
4160 pcyOut->u.Lo = (ULONG)boolIn * (ULONG)10000;
4162 return S_OK;
4165 /**********************************************************************
4166 * VarCyFromI132 [OLEAUT32.225]
4167 * Convert signed char to currency
4169 HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4170 if (cIn < 0) pcyOut->u.Hi = -1;
4171 else pcyOut->u.Hi = 0;
4172 pcyOut->u.Lo = (ULONG)cIn * (ULONG)10000;
4174 return S_OK;
4177 /**********************************************************************
4178 * VarCyFromUI232 [OLEAUT32.226]
4179 * Convert unsigned short to currency
4181 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4182 pcyOut->u.Hi = 0;
4183 pcyOut->u.Lo = (ULONG)usIn * (ULONG)10000;
4185 return S_OK;
4188 /**********************************************************************
4189 * VarCyFromUI432 [OLEAUT32.227]
4190 * Convert unsigned long to currency
4192 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4193 double t = (double)ulIn * (double)10000;
4194 pcyOut->u.Hi = (LONG)(t / (double)4294967296.0);
4195 pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296.0);
4197 return S_OK;