4 * Copyright 1998 Jean-Claude Cote
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.
13 * - The Variant APIs 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 dates prior to 1900.
20 * - The parsing does not accept as many formats as the Windows implementation.
38 #include "debugtools.h"
42 DEFAULT_DEBUG_CHANNEL(ole);
46 # define FLT_MAX MAXFLOAT
48 # error "Can't find #define for MAXFLOAT/FLT_MAX"
54 static const char CHAR_MAX = 127;
55 static const char CHAR_MIN = -128;
56 static const BYTE UI1_MAX = 255;
57 static const BYTE UI1_MIN = 0;
58 static const unsigned short UI2_MAX = 65535;
59 static const unsigned short UI2_MIN = 0;
60 static const short I2_MAX = 32767;
61 static const short I2_MIN = -32768;
62 static const unsigned long UI4_MAX = 4294967295U;
63 static const unsigned long UI4_MIN = 0;
64 static const long I4_MAX = 2147483647;
65 static const long I4_MIN = -(2147483648U);
66 static const DATE DATE_MIN = -657434;
67 static const DATE DATE_MAX = 2958465;
70 /* This mask is used to set a flag in wReserved1 of
71 * the VARIANTARG structure. The flag indicates if
72 * the API function is using an inner variant or not.
74 #define PROCESSING_INNER_VARIANT 0x0001
76 /* General use buffer.
78 #define BUFFER_MAX 1024
79 static char pBuffer[BUFFER_MAX];
82 * Note a leap year is one that is a multiple of 4
83 * but not of a 100. Except if it is a multiple of
84 * 400 then it is a leap year.
86 /* According to postgeSQL date parsing functions there is
87 * a leap year when this expression is true.
88 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
89 * So according to this there is 365.2515 days in one year.
90 * One + every four years: 1/4 -> 365.25
91 * One - every 100 years: 1/100 -> 365.01
92 * One + every 400 years: 1/400 -> 365.0025
94 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
96 * ^^ Might this be the key to an easy way to factor large prime numbers?
97 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
99 static const double DAYS_IN_ONE_YEAR = 365.2425;
101 /******************************************************************************
102 * DateTimeStringToTm [INTERNAL]
104 * Converts a string representation of a date and/or time to a tm structure.
106 * Note this function uses the postgresql date parsing functions found
107 * in the parsedt.c file.
109 * Returns TRUE if successful.
111 * Note: This function does not parse the day of the week,
112 * daylight savings time. It will only fill the followin fields in
113 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
115 ******************************************************************************/
116 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
123 char *field[MAXDATEFIELDS];
124 int ftype[MAXDATEFIELDS];
125 char lowstr[MAXDATELEN + 1];
126 char* strDateTime = NULL;
128 /* Convert the string to ASCII since this is the only format
129 * postgesql can handle.
131 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
133 if( strDateTime != NULL )
135 /* Make sure we don't go over the maximum length
136 * accepted by postgesql.
138 if( strlen( strDateTime ) <= MAXDATELEN )
140 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
142 if( lcid & VAR_DATEVALUEONLY )
144 /* Get the date information.
145 * It returns 0 if date information was
146 * present and 1 if only time information was present.
147 * -1 if an error occures.
149 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
151 /* Eliminate the time information since we
152 * were asked to get date information only.
160 if( lcid & VAR_TIMEVALUEONLY )
162 /* Get time information only.
164 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
171 /* Get both date and time information.
172 * It returns 0 if date information was
173 * present and 1 if only time information was present.
174 * -1 if an error occures.
176 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
183 HeapFree( GetProcessHeap(), 0, strDateTime );
194 /******************************************************************************
195 * TmToDATE [INTERNAL]
197 * The date is implemented using an 8 byte floating-point number.
198 * Days are represented by whole numbers increments starting with 0.00 has
199 * being December 30 1899, midnight.
200 * The hours are expressed as the fractional part of the number.
201 * December 30 1899 at midnight = 0.00
202 * January 1 1900 at midnight = 2.00
203 * January 4 1900 at 6 AM = 5.25
204 * January 4 1900 at noon = 5.50
205 * December 29 1899 at midnight = -1.00
206 * December 18 1899 at midnight = -12.00
207 * December 18 1899 at 6AM = -12.25
208 * December 18 1899 at 6PM = -12.75
209 * December 19 1899 at midnight = -11.00
210 * The tm structure is as follows:
212 * int tm_sec; seconds after the minute - [0,59]
213 * int tm_min; minutes after the hour - [0,59]
214 * int tm_hour; hours since midnight - [0,23]
215 * int tm_mday; day of the month - [1,31]
216 * int tm_mon; months since January - [0,11]
218 * int tm_wday; days since Sunday - [0,6]
219 * int tm_yday; days since January 1 - [0,365]
220 * int tm_isdst; daylight savings time flag
223 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
224 * and tm_isdst fields of the tm structure. And only converts years
227 * Returns TRUE if successful.
229 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
231 if( (pTm->tm_year - 1900) >= 0 )
235 /* Start at 1. This is the way DATE is defined.
236 * January 1, 1900 at Midnight is 1.00.
237 * January 1, 1900 at 6AM is 1.25.
242 /* Add the number of days corresponding to
245 *pDateOut += (pTm->tm_year - 1900) * 365;
247 /* Add the leap days in the previous years between now and 1900.
248 * Note a leap year is one that is a multiple of 4
249 * but not of a 100. Except if it is a multiple of
250 * 400 then it is a leap year.
252 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
253 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
254 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
256 /* Set the leap year flag if the
257 * current year specified by tm_year is a
258 * leap year. This will be used to add a day
261 if( isleap( pTm->tm_year ) )
264 /* Add the number of days corresponding to
267 switch( pTm->tm_mon )
273 *pDateOut += ( 59 + leapYear );
276 *pDateOut += ( 90 + leapYear );
279 *pDateOut += ( 120 + leapYear );
282 *pDateOut += ( 151 + leapYear );
285 *pDateOut += ( 181 + leapYear );
288 *pDateOut += ( 212 + leapYear );
291 *pDateOut += ( 243 + leapYear );
294 *pDateOut += ( 273 + leapYear );
297 *pDateOut += ( 304 + leapYear );
300 *pDateOut += ( 334 + leapYear );
303 /* Add the number of days in this month.
305 *pDateOut += pTm->tm_mday;
307 /* Add the number of seconds, minutes, and hours
308 * to the DATE. Note these are the fracionnal part
309 * of the DATE so seconds / number of seconds in a day.
311 *pDateOut += pTm->tm_hour / 24.0;
312 *pDateOut += pTm->tm_min / 1440.0;
313 *pDateOut += pTm->tm_sec / 86400.0;
319 /******************************************************************************
320 * DateToTm [INTERNAL]
322 * This function converts a windows DATE to a tm structure.
324 * It does not fill all the fields of the tm structure.
325 * Here is a list of the fields that are filled:
326 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
328 * Note this function does not support dates before the January 1, 1900
329 * or ( dateIn < 2.0 ).
331 * Returns TRUE if successful.
333 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
335 /* Do not process dates smaller than January 1, 1900.
336 * Which corresponds to 2.0 in the windows DATE format.
340 double decimalPart = 0.0;
341 double wholePart = 0.0;
343 memset(pTm,0,sizeof(*pTm));
345 /* Because of the nature of DATE format witch
346 * associates 2.0 to January 1, 1900. We will
347 * remove 1.0 from the whole part of the DATE
348 * so that in the following code 1.0
349 * will correspond to January 1, 1900.
350 * This simplyfies the processing of the DATE value.
354 wholePart = (double) floor( dateIn );
355 decimalPart = fmod( dateIn, wholePart );
357 if( !(lcid & VAR_TIMEVALUEONLY) )
361 double yearsSince1900 = 0;
362 /* Start at 1900, this where the DATE time 0.0 starts.
365 /* find in what year the day in the "wholePart" falls into.
366 * add the value to the year field.
368 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
369 pTm->tm_year += yearsSince1900;
370 /* determine if this is a leap year.
372 if( isleap( pTm->tm_year ) )
378 /* find what day of that year does the "wholePart" corresponds to.
379 * Note: nDay is in [1-366] format
381 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
382 /* Set the tm_yday value.
383 * Note: The day is must be converted from [1-366] to [0-365]
385 /*pTm->tm_yday = nDay - 1;*/
386 /* find which mount this day corresponds to.
393 else if( nDay <= ( 59 + leapYear ) )
395 pTm->tm_mday = nDay - 31;
398 else if( nDay <= ( 90 + leapYear ) )
400 pTm->tm_mday = nDay - ( 59 + leapYear );
403 else if( nDay <= ( 120 + leapYear ) )
405 pTm->tm_mday = nDay - ( 90 + leapYear );
408 else if( nDay <= ( 151 + leapYear ) )
410 pTm->tm_mday = nDay - ( 120 + leapYear );
413 else if( nDay <= ( 181 + leapYear ) )
415 pTm->tm_mday = nDay - ( 151 + leapYear );
418 else if( nDay <= ( 212 + leapYear ) )
420 pTm->tm_mday = nDay - ( 181 + leapYear );
423 else if( nDay <= ( 243 + leapYear ) )
425 pTm->tm_mday = nDay - ( 212 + leapYear );
428 else if( nDay <= ( 273 + leapYear ) )
430 pTm->tm_mday = nDay - ( 243 + leapYear );
433 else if( nDay <= ( 304 + leapYear ) )
435 pTm->tm_mday = nDay - ( 273 + leapYear );
438 else if( nDay <= ( 334 + leapYear ) )
440 pTm->tm_mday = nDay - ( 304 + leapYear );
443 else if( nDay <= ( 365 + leapYear ) )
445 pTm->tm_mday = nDay - ( 334 + leapYear );
449 if( !(lcid & VAR_DATEVALUEONLY) )
451 /* find the number of seconds in this day.
452 * fractional part times, hours, minutes, seconds.
454 pTm->tm_hour = (int) ( decimalPart * 24 );
455 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
456 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
465 /******************************************************************************
466 * SizeOfVariantData [INTERNAL]
468 * This function finds the size of the data referenced by a Variant based
469 * the type "vt" of the Variant.
471 static int SizeOfVariantData( VARIANT* parg )
474 switch( parg->vt & VT_TYPEMASK )
477 size = sizeof(short);
489 size = sizeof(unsigned short);
492 size = sizeof(unsigned int);
495 size = sizeof(unsigned long);
498 size = sizeof(float);
501 size = sizeof(double);
507 size = sizeof(VARIANT_BOOL);
510 size = sizeof(void*);
517 FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
523 /******************************************************************************
524 * StringDupAtoBstr [INTERNAL]
527 static BSTR StringDupAtoBstr( char* strIn )
530 OLECHAR* pNewString = NULL;
531 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
532 bstr = SysAllocString( pNewString );
533 HeapFree( GetProcessHeap(), 0, pNewString );
537 /******************************************************************************
540 * Round the double value to the nearest integer value.
542 static double round( double d )
544 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
545 BOOL bEvenNumber = FALSE;
548 /* Save the sign of the number
550 nSign = (d >= 0.0) ? 1 : -1;
553 /* Remove the decimals.
555 integerValue = floor( d );
557 /* Set the Even flag. This is used to round the number when
558 * the decimals are exactly 1/2. If the integer part is
559 * odd the number is rounded up. If the integer part
560 * is even the number is rounded down. Using this method
561 * numbers are rounded up|down half the time.
563 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
565 /* Remove the integral part of the number.
567 decimals = d - integerValue;
569 /* Note: Ceil returns the smallest integer that is greater that x.
570 * and floor returns the largest integer that is less than or equal to x.
574 /* If the decimal part is greater than 1/2
576 roundedValue = ceil( d );
578 else if( decimals < 0.5 )
580 /* If the decimal part is smaller than 1/2
582 roundedValue = floor( d );
586 /* the decimals are exactly 1/2 so round according to
587 * the bEvenNumber flag.
591 roundedValue = floor( d );
595 roundedValue = ceil( d );
599 return roundedValue * nSign;
602 /******************************************************************************
603 * RemoveCharacterFromString [INTERNAL]
605 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
607 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
609 LPSTR pNewString = NULL;
610 LPSTR strToken = NULL;
613 /* Check if we have a valid argument
617 pNewString = strdup( str );
619 strToken = strtok( pNewString, strOfCharToRemove );
620 while( strToken != NULL ) {
621 strcat( str, strToken );
622 strToken = strtok( NULL, strOfCharToRemove );
629 /******************************************************************************
630 * GetValidRealString [INTERNAL]
632 * Checks if the string is of proper format to be converted to a real value.
634 static BOOL IsValidRealString( LPSTR strRealString )
636 /* Real values that have a decimal point are required to either have
637 * digits before or after the decimal point. We will assume that
638 * we do not have any digits at either position. If we do encounter
639 * some we will disable this flag.
641 BOOL bDigitsRequired = TRUE;
642 /* Processed fields in the string representation of the real number.
644 BOOL bWhiteSpaceProcessed = FALSE;
645 BOOL bFirstSignProcessed = FALSE;
646 BOOL bFirstDigitsProcessed = FALSE;
647 BOOL bDecimalPointProcessed = FALSE;
648 BOOL bSecondDigitsProcessed = FALSE;
649 BOOL bExponentProcessed = FALSE;
650 BOOL bSecondSignProcessed = FALSE;
651 BOOL bThirdDigitsProcessed = FALSE;
652 /* Assume string parameter "strRealString" is valid and try to disprove it.
654 BOOL bValidRealString = TRUE;
656 /* Used to count the number of tokens in the "strRealString".
658 LPSTR strToken = NULL;
662 /* Check if we have a valid argument
664 if( strRealString == NULL )
666 bValidRealString = FALSE;
669 if( bValidRealString == TRUE )
671 /* Make sure we only have ONE token in the string.
673 strToken = strtok( strRealString, " " );
674 while( strToken != NULL ) {
676 strToken = strtok( NULL, " " );
681 bValidRealString = FALSE;
686 /* Make sure this token contains only valid characters.
687 * The string argument to atof has the following form:
688 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
689 * Whitespace consists of space and|or <TAB> characters, which are ignored.
690 * Sign is either plus '+' or minus '-'.
691 * Digits are one or more decimal digits.
692 * Note: If no digits appear before the decimal point, at least one must
693 * appear after the decimal point.
694 * The decimal digits may be followed by an exponent.
695 * An Exponent consists of an introductory letter ( D, d, E, or e) and
696 * an optionally signed decimal integer.
698 pChar = strRealString;
699 while( bValidRealString == TRUE && *pChar != '\0' )
707 if( bWhiteSpaceProcessed ||
708 bFirstSignProcessed ||
709 bFirstDigitsProcessed ||
710 bDecimalPointProcessed ||
711 bSecondDigitsProcessed ||
712 bExponentProcessed ||
713 bSecondSignProcessed ||
714 bThirdDigitsProcessed )
716 bValidRealString = FALSE;
723 if( bFirstSignProcessed == FALSE )
725 if( bFirstDigitsProcessed ||
726 bDecimalPointProcessed ||
727 bSecondDigitsProcessed ||
728 bExponentProcessed ||
729 bSecondSignProcessed ||
730 bThirdDigitsProcessed )
732 bValidRealString = FALSE;
734 bWhiteSpaceProcessed = TRUE;
735 bFirstSignProcessed = TRUE;
737 else if( bSecondSignProcessed == FALSE )
739 /* Note: The exponent must be present in
740 * order to accept the second sign...
742 if( bExponentProcessed == FALSE ||
743 bThirdDigitsProcessed ||
746 bValidRealString = FALSE;
748 bFirstSignProcessed = TRUE;
749 bWhiteSpaceProcessed = TRUE;
750 bFirstDigitsProcessed = TRUE;
751 bDecimalPointProcessed = TRUE;
752 bSecondDigitsProcessed = TRUE;
753 bSecondSignProcessed = TRUE;
769 if( bFirstDigitsProcessed == FALSE )
771 if( bDecimalPointProcessed ||
772 bSecondDigitsProcessed ||
773 bExponentProcessed ||
774 bSecondSignProcessed ||
775 bThirdDigitsProcessed )
777 bValidRealString = FALSE;
779 bFirstSignProcessed = TRUE;
780 bWhiteSpaceProcessed = TRUE;
781 /* We have found some digits before the decimal point
782 * so disable the "Digits required" flag.
784 bDigitsRequired = FALSE;
786 else if( bSecondDigitsProcessed == FALSE )
788 if( bExponentProcessed ||
789 bSecondSignProcessed ||
790 bThirdDigitsProcessed )
792 bValidRealString = FALSE;
794 bFirstSignProcessed = TRUE;
795 bWhiteSpaceProcessed = TRUE;
796 bFirstDigitsProcessed = TRUE;
797 bDecimalPointProcessed = TRUE;
798 /* We have found some digits after the decimal point
799 * so disable the "Digits required" flag.
801 bDigitsRequired = FALSE;
803 else if( bThirdDigitsProcessed == FALSE )
805 /* Getting here means everything else should be processed.
806 * If we get anything else than a decimal following this
807 * digit it will be flagged by the other cases, so
808 * we do not really need to do anything in here.
812 /* If DecimalPoint...
815 if( bDecimalPointProcessed ||
816 bSecondDigitsProcessed ||
817 bExponentProcessed ||
818 bSecondSignProcessed ||
819 bThirdDigitsProcessed )
821 bValidRealString = FALSE;
823 bFirstSignProcessed = TRUE;
824 bWhiteSpaceProcessed = TRUE;
825 bFirstDigitsProcessed = TRUE;
826 bDecimalPointProcessed = TRUE;
834 if( bExponentProcessed ||
835 bSecondSignProcessed ||
836 bThirdDigitsProcessed ||
839 bValidRealString = FALSE;
841 bFirstSignProcessed = TRUE;
842 bWhiteSpaceProcessed = TRUE;
843 bFirstDigitsProcessed = TRUE;
844 bDecimalPointProcessed = TRUE;
845 bSecondDigitsProcessed = TRUE;
846 bExponentProcessed = TRUE;
849 bValidRealString = FALSE;
852 /* Process next character.
857 /* If the required digits were not present we have an invalid
858 * string representation of a real number.
860 if( bDigitsRequired == TRUE )
862 bValidRealString = FALSE;
865 return bValidRealString;
869 /******************************************************************************
872 * This function dispatches execution to the proper conversion API
873 * to do the necessary coercion.
875 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
878 unsigned short vtFrom = 0;
879 vtFrom = ps->vt & VT_TYPEMASK;
881 /* Note: Since "long" and "int" values both have 4 bytes and are
882 * both signed integers "int" will be treated as "long" in the
884 * The same goes for their unsigned versions.
887 /* Trivial Case: If the coercion is from two types that are
888 * identical then we can blindly copy from one argument to another.*/
891 return VariantCopy(pd,ps);
894 /* Cases requiring thought*/
899 res = VariantClear( pd );
902 res = VariantClear( pd );
912 res = VariantCopy( pd, ps );
915 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
919 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
922 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
925 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
929 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
932 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
935 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
938 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
941 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
944 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
947 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
949 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
951 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
953 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
955 res = DISP_E_TYPEMISMATCH;
956 FIXME("Coercion from %d to %d\n", vtFrom, vt );
965 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
968 res = VariantCopy( pd, ps );
972 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
975 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
978 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
982 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
985 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
988 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
991 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
994 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
997 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
1000 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
1001 case( VT_DISPATCH ):
1002 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1004 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
1006 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
1008 res = DISP_E_TYPEMISMATCH;
1009 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1019 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1022 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1026 res = VariantCopy( pd, ps );
1029 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1032 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1036 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1039 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1042 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1045 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1048 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1051 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1054 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1055 case( VT_DISPATCH ):
1056 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1058 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1060 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1062 res = DISP_E_TYPEMISMATCH;
1063 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1072 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1075 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1079 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1082 res = VariantCopy( pd, ps );
1085 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1089 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1092 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1095 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1098 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1101 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1104 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1107 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1108 case( VT_DISPATCH ):
1109 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1111 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1113 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1115 res = DISP_E_TYPEMISMATCH;
1116 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1125 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1128 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1132 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1135 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1138 res = VariantCopy( pd, ps );
1142 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1145 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1148 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1151 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1154 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1157 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1160 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1161 case( VT_DISPATCH ):
1162 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1164 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1166 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1168 res = DISP_E_TYPEMISMATCH;
1169 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1179 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1182 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1186 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1189 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1192 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1195 res = VariantCopy( pd, ps );
1198 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1201 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1204 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1207 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1210 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1213 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1214 case( VT_DISPATCH ):
1215 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1217 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1219 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1221 res = DISP_E_TYPEMISMATCH;
1222 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1231 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1234 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1238 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1241 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1244 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1248 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1251 res = VariantCopy( pd, ps );
1254 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1257 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1260 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1263 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1266 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1267 case( VT_DISPATCH ):
1268 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1270 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1272 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1274 res = DISP_E_TYPEMISMATCH;
1275 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1284 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1287 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1291 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1294 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1297 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1301 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1304 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1307 res = VariantCopy( pd, ps );
1310 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1313 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1316 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1319 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1320 case( VT_DISPATCH ):
1321 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1323 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1325 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1327 res = DISP_E_TYPEMISMATCH;
1328 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1337 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1340 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1343 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1346 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1349 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1352 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1355 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1358 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1361 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1364 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1367 res = VariantCopy( pd, ps );
1370 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1373 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1376 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1377 case( VT_DISPATCH ):
1378 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1380 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1382 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1384 res = DISP_E_TYPEMISMATCH;
1385 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1394 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1397 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1400 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1403 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1406 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1409 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1412 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1415 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1418 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1421 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1424 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1427 res = VariantCopy( pd, ps );
1430 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1433 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1434 case( VT_DISPATCH ):
1435 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1437 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1439 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1441 res = DISP_E_TYPEMISMATCH;
1442 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1451 if ((pd->u.bstrVal = SysAllocStringLen(NULL, 0)))
1454 res = E_OUTOFMEMORY;
1457 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1460 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1463 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1466 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1469 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1472 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1475 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1478 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1481 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1484 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1487 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1490 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1493 res = VariantCopy( pd, ps );
1496 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1497 case( VT_DISPATCH ):
1498 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1500 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1502 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1504 res = DISP_E_TYPEMISMATCH;
1505 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1514 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1517 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1520 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1523 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1526 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1529 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1532 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1535 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1538 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1541 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1544 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1547 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1550 res = VariantCopy( pd, ps );
1553 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1554 case( VT_DISPATCH ):
1555 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1557 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1559 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1561 res = DISP_E_TYPEMISMATCH;
1562 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1568 res = DISP_E_TYPEMISMATCH;
1569 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1576 /******************************************************************************
1577 * ValidateVtRange [INTERNAL]
1579 * Used internally by the hi-level Variant API to determine
1580 * if the vartypes are valid.
1582 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1584 /* if by value we must make sure it is in the
1585 * range of the valid types.
1587 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1589 return DISP_E_BADVARTYPE;
1595 /******************************************************************************
1596 * ValidateVartype [INTERNAL]
1598 * Used internally by the hi-level Variant API to determine
1599 * if the vartypes are valid.
1601 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1605 /* check if we have a valid argument.
1609 /* if by reference check that the type is in
1610 * the valid range and that it is not of empty or null type
1612 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1613 ( vt & VT_TYPEMASK ) == VT_NULL ||
1614 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1622 res = ValidateVtRange( vt );
1628 /******************************************************************************
1629 * ValidateVt [INTERNAL]
1631 * Used internally by the hi-level Variant API to determine
1632 * if the vartypes are valid.
1634 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1638 /* check if we have a valid argument.
1642 /* if by reference check that the type is in
1643 * the valid range and that it is not of empty or null type
1645 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1646 ( vt & VT_TYPEMASK ) == VT_NULL ||
1647 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1649 res = DISP_E_BADVARTYPE;
1655 res = ValidateVtRange( vt );
1665 /******************************************************************************
1666 * VariantInit [OLEAUT32.8]
1668 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1669 * contents of the Variant.
1671 void WINAPI VariantInit(VARIANTARG* pvarg)
1673 TRACE("(%p),stub\n",pvarg);
1675 memset(pvarg, 0, sizeof (VARIANTARG));
1676 pvarg->vt = VT_EMPTY;
1681 /******************************************************************************
1682 * VariantClear [OLEAUT32.9]
1684 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1685 * sets the wReservedX field to 0. The current contents of the VARIANT are
1686 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1687 * released. If VT_ARRAY the array is freed.
1689 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1692 TRACE("(%p)\n",pvarg);
1694 res = ValidateVariantType( pvarg->vt );
1697 if( !( pvarg->vt & VT_BYREF ) )
1700 * The VT_ARRAY flag is a special case of a safe array.
1702 if ( (pvarg->vt & VT_ARRAY) != 0)
1704 SafeArrayDestroy(pvarg->u.parray);
1708 switch( pvarg->vt & VT_TYPEMASK )
1711 SysFreeString( pvarg->u.bstrVal );
1713 case( VT_DISPATCH ):
1714 if(pvarg->u.pdispVal!=NULL)
1715 ICOM_CALL(Release,pvarg->u.pdispVal);
1718 VariantClear(pvarg->u.pvarVal);
1721 if(pvarg->u.punkVal!=NULL)
1722 ICOM_CALL(Release,pvarg->u.punkVal);
1724 case( VT_SAFEARRAY ):
1725 SafeArrayDestroy(pvarg->u.parray);
1734 * Empty all the fields and mark the type as empty.
1736 memset(pvarg, 0, sizeof (VARIANTARG));
1737 pvarg->vt = VT_EMPTY;
1743 /******************************************************************************
1744 * VariantCopy [OLEAUT32.10]
1746 * Frees up the designation variant and makes a copy of the source.
1748 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1752 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1754 res = ValidateVariantType( pvargSrc->vt );
1756 /* If the pointer are to the same variant we don't need
1759 if( pvargDest != pvargSrc && res == S_OK )
1761 res = VariantClear( pvargDest );
1765 if( pvargSrc->vt & VT_BYREF )
1767 /* In the case of byreference we only need
1768 * to copy the pointer.
1770 pvargDest->u = pvargSrc->u;
1771 pvargDest->vt = pvargSrc->vt;
1776 * The VT_ARRAY flag is another way to designate a safe array.
1778 if (pvargSrc->vt & VT_ARRAY)
1780 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1784 /* In the case of by value we need to
1785 * copy the actuall value. In the case of
1786 * VT_BSTR a copy of the string is made,
1787 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1788 * called to increment the object's reference count.
1790 switch( pvargSrc->vt & VT_TYPEMASK )
1793 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1795 case( VT_DISPATCH ):
1796 pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1797 if (pvargDest->u.pdispVal!=NULL)
1798 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1801 VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1804 pvargDest->u.punkVal = pvargSrc->u.punkVal;
1805 if (pvargDest->u.pdispVal!=NULL)
1806 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1808 case( VT_SAFEARRAY ):
1809 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1812 pvargDest->u = pvargSrc->u;
1817 pvargDest->vt = pvargSrc->vt;
1826 /******************************************************************************
1827 * VariantCopyInd [OLEAUT32.11]
1829 * Frees up the destination variant and makes a copy of the source. If
1830 * the source is of type VT_BYREF it performs the necessary indirections.
1832 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1836 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1838 res = ValidateVariantType( pvargSrc->vt );
1843 if( pvargSrc->vt & VT_BYREF )
1846 VariantInit( &varg );
1848 /* handle the in place copy.
1850 if( pvargDest == pvargSrc )
1852 /* we will use a copy of the source instead.
1854 res = VariantCopy( &varg, pvargSrc );
1860 res = VariantClear( pvargDest );
1865 * The VT_ARRAY flag is another way to designate a safearray variant.
1867 if ( pvargSrc->vt & VT_ARRAY)
1869 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1873 /* In the case of by reference we need
1874 * to copy the date pointed to by the variant.
1877 /* Get the variant type.
1879 switch( pvargSrc->vt & VT_TYPEMASK )
1882 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1884 case( VT_DISPATCH ):
1888 /* Prevent from cycling. According to tests on
1889 * VariantCopyInd in Windows and the documentation
1890 * this API dereferences the inner Variants to only one depth.
1891 * If the inner Variant itself contains an
1892 * other inner variant the E_INVALIDARG error is
1895 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1897 /* If we get here we are attempting to deference
1898 * an inner variant that that is itself contained
1899 * in an inner variant so report E_INVALIDARG error.
1905 /* Set the processing inner variant flag.
1906 * We will set this flag in the inner variant
1907 * that will be passed to the VariantCopyInd function.
1909 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1911 /* Dereference the inner variant.
1913 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1914 /* We must also copy its type, I think.
1916 pvargSrc->vt = pvargSrc->u.pvarVal->vt;
1922 case( VT_SAFEARRAY ):
1923 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1926 /* This is a by reference Variant which means that the union
1927 * part of the Variant contains a pointer to some data of
1928 * type "pvargSrc->vt & VT_TYPEMASK".
1929 * We will deference this data in a generic fashion using
1930 * the void pointer "Variant.u.byref".
1931 * We will copy this data into the union of the destination
1934 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1939 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1943 /* this should not fail.
1945 VariantClear( &varg );
1949 res = VariantCopy( pvargDest, pvargSrc );
1955 /******************************************************************************
1956 * VariantChangeType [OLEAUT32.12]
1958 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1959 USHORT wFlags, VARTYPE vt)
1961 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1964 /******************************************************************************
1965 * VariantChangeTypeEx [OLEAUT32.147]
1967 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1968 LCID lcid, USHORT wFlags, VARTYPE vt)
1972 VariantInit( &varg );
1974 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1976 /* validate our source argument.
1978 res = ValidateVariantType( pvargSrc->vt );
1980 /* validate the vartype.
1984 res = ValidateVt( vt );
1987 /* if we are doing an in-place conversion make a copy of the source.
1989 if( res == S_OK && pvargDest == pvargSrc )
1991 res = VariantCopy( &varg, pvargSrc );
1997 /* free up the destination variant.
1999 res = VariantClear( pvargDest );
2004 if( pvargSrc->vt & VT_BYREF )
2006 /* Convert the source variant to a "byvalue" variant.
2009 VariantInit( &Variant );
2010 res = VariantCopyInd( &Variant, pvargSrc );
2013 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2014 /* this should not fail.
2016 VariantClear( &Variant );
2022 /* Use the current "byvalue" source variant.
2024 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2027 /* this should not fail.
2029 VariantClear( &varg );
2031 /* set the type of the destination
2042 /******************************************************************************
2043 * VarUI1FromI2 [OLEAUT32.130]
2045 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2047 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2049 /* Check range of value.
2051 if( sIn < UI1_MIN || sIn > UI1_MAX )
2053 return DISP_E_OVERFLOW;
2056 *pbOut = (BYTE) sIn;
2061 /******************************************************************************
2062 * VarUI1FromI4 [OLEAUT32.131]
2064 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2066 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2068 /* Check range of value.
2070 if( lIn < UI1_MIN || lIn > UI1_MAX )
2072 return DISP_E_OVERFLOW;
2075 *pbOut = (BYTE) lIn;
2081 /******************************************************************************
2082 * VarUI1FromR4 [OLEAUT32.132]
2084 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2086 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2088 /* Check range of value.
2090 fltIn = round( fltIn );
2091 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2093 return DISP_E_OVERFLOW;
2096 *pbOut = (BYTE) fltIn;
2101 /******************************************************************************
2102 * VarUI1FromR8 [OLEAUT32.133]
2104 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2106 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2108 /* Check range of value.
2110 dblIn = round( dblIn );
2111 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2113 return DISP_E_OVERFLOW;
2116 *pbOut = (BYTE) dblIn;
2121 /******************************************************************************
2122 * VarUI1FromDate [OLEAUT32.135]
2124 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2126 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2128 /* Check range of value.
2130 dateIn = round( dateIn );
2131 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2133 return DISP_E_OVERFLOW;
2136 *pbOut = (BYTE) dateIn;
2141 /******************************************************************************
2142 * VarUI1FromBool [OLEAUT32.138]
2144 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2146 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2148 *pbOut = (BYTE) boolIn;
2153 /******************************************************************************
2154 * VarUI1FromI1 [OLEAUT32.237]
2156 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2158 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2165 /******************************************************************************
2166 * VarUI1FromUI2 [OLEAUT32.238]
2168 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2170 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2172 /* Check range of value.
2174 if( uiIn > UI1_MAX )
2176 return DISP_E_OVERFLOW;
2179 *pbOut = (BYTE) uiIn;
2184 /******************************************************************************
2185 * VarUI1FromUI4 [OLEAUT32.239]
2187 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2189 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2191 /* Check range of value.
2193 if( ulIn > UI1_MAX )
2195 return DISP_E_OVERFLOW;
2198 *pbOut = (BYTE) ulIn;
2204 /******************************************************************************
2205 * VarUI1FromStr [OLEAUT32.54]
2207 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2209 double dValue = 0.0;
2210 LPSTR pNewString = NULL;
2212 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2214 /* Check if we have a valid argument
2216 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2217 RemoveCharacterFromString( pNewString, "," );
2218 if( IsValidRealString( pNewString ) == FALSE )
2220 return DISP_E_TYPEMISMATCH;
2223 /* Convert the valid string to a floating point number.
2225 dValue = atof( pNewString );
2227 /* We don't need the string anymore so free it.
2229 HeapFree( GetProcessHeap(), 0 , pNewString );
2231 /* Check range of value.
2233 dValue = round( dValue );
2234 if( dValue < UI1_MIN || dValue > UI1_MAX )
2236 return DISP_E_OVERFLOW;
2239 *pbOut = (BYTE) dValue;
2244 /**********************************************************************
2245 * VarUI1FromCy [OLEAUT32.134]
2246 * Convert currency to unsigned char
2248 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2249 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2251 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2257 /******************************************************************************
2258 * VarI2FromUI1 [OLEAUT32.48]
2260 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2262 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2264 *psOut = (short) bIn;
2269 /******************************************************************************
2270 * VarI2FromI4 [OLEAUT32.49]
2272 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2274 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2276 /* Check range of value.
2278 if( lIn < I2_MIN || lIn > I2_MAX )
2280 return DISP_E_OVERFLOW;
2283 *psOut = (short) lIn;
2288 /******************************************************************************
2289 * VarI2FromR4 [OLEAUT32.50]
2291 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2293 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2295 /* Check range of value.
2297 fltIn = round( fltIn );
2298 if( fltIn < I2_MIN || fltIn > I2_MAX )
2300 return DISP_E_OVERFLOW;
2303 *psOut = (short) fltIn;
2308 /******************************************************************************
2309 * VarI2FromR8 [OLEAUT32.51]
2311 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2313 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2315 /* Check range of value.
2317 dblIn = round( dblIn );
2318 if( dblIn < I2_MIN || dblIn > I2_MAX )
2320 return DISP_E_OVERFLOW;
2323 *psOut = (short) dblIn;
2328 /******************************************************************************
2329 * VarI2FromDate [OLEAUT32.53]
2331 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2333 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2335 /* Check range of value.
2337 dateIn = round( dateIn );
2338 if( dateIn < I2_MIN || dateIn > I2_MAX )
2340 return DISP_E_OVERFLOW;
2343 *psOut = (short) dateIn;
2348 /******************************************************************************
2349 * VarI2FromBool [OLEAUT32.56]
2351 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2353 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2355 *psOut = (short) boolIn;
2360 /******************************************************************************
2361 * VarI2FromI1 [OLEAUT32.48]
2363 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2365 TRACE("( %c, %p ), stub\n", cIn, psOut );
2367 *psOut = (short) cIn;
2372 /******************************************************************************
2373 * VarI2FromUI2 [OLEAUT32.206]
2375 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2377 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2379 /* Check range of value.
2383 return DISP_E_OVERFLOW;
2386 *psOut = (short) uiIn;
2391 /******************************************************************************
2392 * VarI2FromUI4 [OLEAUT32.49]
2394 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2396 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2398 /* Check range of value.
2400 if( ulIn < I2_MIN || ulIn > I2_MAX )
2402 return DISP_E_OVERFLOW;
2405 *psOut = (short) ulIn;
2410 /******************************************************************************
2411 * VarI2FromStr [OLEAUT32.54]
2413 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2415 double dValue = 0.0;
2416 LPSTR pNewString = NULL;
2418 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2420 /* Check if we have a valid argument
2422 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2423 RemoveCharacterFromString( pNewString, "," );
2424 if( IsValidRealString( pNewString ) == FALSE )
2426 return DISP_E_TYPEMISMATCH;
2429 /* Convert the valid string to a floating point number.
2431 dValue = atof( pNewString );
2433 /* We don't need the string anymore so free it.
2435 HeapFree( GetProcessHeap(), 0, pNewString );
2437 /* Check range of value.
2439 dValue = round( dValue );
2440 if( dValue < I2_MIN || dValue > I2_MAX )
2442 return DISP_E_OVERFLOW;
2445 *psOut = (short) dValue;
2450 /**********************************************************************
2451 * VarI2FromCy [OLEAUT32.52]
2452 * Convert currency to signed short
2454 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2455 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2457 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2463 /******************************************************************************
2464 * VarI4FromUI1 [OLEAUT32.58]
2466 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2468 TRACE("( %X, %p ), stub\n", bIn, plOut );
2470 *plOut = (LONG) bIn;
2476 /******************************************************************************
2477 * VarI4FromR4 [OLEAUT32.60]
2479 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2481 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2483 /* Check range of value.
2485 fltIn = round( fltIn );
2486 if( fltIn < I4_MIN || fltIn > I4_MAX )
2488 return DISP_E_OVERFLOW;
2491 *plOut = (LONG) fltIn;
2496 /******************************************************************************
2497 * VarI4FromR8 [OLEAUT32.61]
2499 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2501 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2503 /* Check range of value.
2505 dblIn = round( dblIn );
2506 if( dblIn < I4_MIN || dblIn > I4_MAX )
2508 return DISP_E_OVERFLOW;
2511 *plOut = (LONG) dblIn;
2516 /******************************************************************************
2517 * VarI4FromDate [OLEAUT32.63]
2519 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2521 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2523 /* Check range of value.
2525 dateIn = round( dateIn );
2526 if( dateIn < I4_MIN || dateIn > I4_MAX )
2528 return DISP_E_OVERFLOW;
2531 *plOut = (LONG) dateIn;
2536 /******************************************************************************
2537 * VarI4FromBool [OLEAUT32.66]
2539 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2541 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2543 *plOut = (LONG) boolIn;
2548 /******************************************************************************
2549 * VarI4FromI1 [OLEAUT32.209]
2551 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2553 TRACE("( %c, %p ), stub\n", cIn, plOut );
2555 *plOut = (LONG) cIn;
2560 /******************************************************************************
2561 * VarI4FromUI2 [OLEAUT32.210]
2563 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2565 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2567 *plOut = (LONG) uiIn;
2572 /******************************************************************************
2573 * VarI4FromUI4 [OLEAUT32.211]
2575 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2577 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2579 /* Check range of value.
2581 if( ulIn < I4_MIN || ulIn > I4_MAX )
2583 return DISP_E_OVERFLOW;
2586 *plOut = (LONG) ulIn;
2591 /******************************************************************************
2592 * VarI4FromI2 [OLEAUT32.59]
2594 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2596 TRACE("( %d, %p ), stub\n", sIn, plOut );
2598 *plOut = (LONG) sIn;
2603 /******************************************************************************
2604 * VarI4FromStr [OLEAUT32.64]
2606 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2608 double dValue = 0.0;
2609 LPSTR pNewString = NULL;
2611 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2613 /* Check if we have a valid argument
2615 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2616 RemoveCharacterFromString( pNewString, "," );
2617 if( IsValidRealString( pNewString ) == FALSE )
2619 return DISP_E_TYPEMISMATCH;
2622 /* Convert the valid string to a floating point number.
2624 dValue = atof( pNewString );
2626 /* We don't need the string anymore so free it.
2628 HeapFree( GetProcessHeap(), 0, pNewString );
2630 /* Check range of value.
2632 dValue = round( dValue );
2633 if( dValue < I4_MIN || dValue > I4_MAX )
2635 return DISP_E_OVERFLOW;
2638 *plOut = (LONG) dValue;
2643 /**********************************************************************
2644 * VarI4FromCy [OLEAUT32.62]
2645 * Convert currency to signed long
2647 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2648 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2650 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2656 /******************************************************************************
2657 * VarR4FromUI1 [OLEAUT32.68]
2659 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2661 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2663 *pfltOut = (FLOAT) bIn;
2668 /******************************************************************************
2669 * VarR4FromI2 [OLEAUT32.69]
2671 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2673 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2675 *pfltOut = (FLOAT) sIn;
2680 /******************************************************************************
2681 * VarR4FromI4 [OLEAUT32.70]
2683 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2685 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2687 *pfltOut = (FLOAT) lIn;
2692 /******************************************************************************
2693 * VarR4FromR8 [OLEAUT32.71]
2695 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2697 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2699 /* Check range of value.
2701 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2703 return DISP_E_OVERFLOW;
2706 *pfltOut = (FLOAT) dblIn;
2711 /******************************************************************************
2712 * VarR4FromDate [OLEAUT32.73]
2714 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2716 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2718 /* Check range of value.
2720 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2722 return DISP_E_OVERFLOW;
2725 *pfltOut = (FLOAT) dateIn;
2730 /******************************************************************************
2731 * VarR4FromBool [OLEAUT32.76]
2733 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2735 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2737 *pfltOut = (FLOAT) boolIn;
2742 /******************************************************************************
2743 * VarR4FromI1 [OLEAUT32.213]
2745 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2747 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2749 *pfltOut = (FLOAT) cIn;
2754 /******************************************************************************
2755 * VarR4FromUI2 [OLEAUT32.214]
2757 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2759 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2761 *pfltOut = (FLOAT) uiIn;
2766 /******************************************************************************
2767 * VarR4FromUI4 [OLEAUT32.215]
2769 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2771 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2773 *pfltOut = (FLOAT) ulIn;
2778 /******************************************************************************
2779 * VarR4FromStr [OLEAUT32.74]
2781 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2783 double dValue = 0.0;
2784 LPSTR pNewString = NULL;
2786 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2788 /* Check if we have a valid argument
2790 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2791 RemoveCharacterFromString( pNewString, "," );
2792 if( IsValidRealString( pNewString ) == FALSE )
2794 return DISP_E_TYPEMISMATCH;
2797 /* Convert the valid string to a floating point number.
2799 dValue = atof( pNewString );
2801 /* We don't need the string anymore so free it.
2803 HeapFree( GetProcessHeap(), 0, pNewString );
2805 /* Check range of value.
2807 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2809 return DISP_E_OVERFLOW;
2812 *pfltOut = (FLOAT) dValue;
2817 /**********************************************************************
2818 * VarR4FromCy [OLEAUT32.72]
2819 * Convert currency to float
2821 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2822 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2827 /******************************************************************************
2828 * VarR8FromUI1 [OLEAUT32.68]
2830 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2832 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2834 *pdblOut = (double) bIn;
2839 /******************************************************************************
2840 * VarR8FromI2 [OLEAUT32.69]
2842 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2844 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2846 *pdblOut = (double) sIn;
2851 /******************************************************************************
2852 * VarR8FromI4 [OLEAUT32.70]
2854 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2856 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2858 *pdblOut = (double) lIn;
2863 /******************************************************************************
2864 * VarR8FromR4 [OLEAUT32.81]
2866 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2868 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2870 *pdblOut = (double) fltIn;
2875 /******************************************************************************
2876 * VarR8FromDate [OLEAUT32.83]
2878 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2880 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2882 *pdblOut = (double) dateIn;
2887 /******************************************************************************
2888 * VarR8FromBool [OLEAUT32.86]
2890 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2892 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2894 *pdblOut = (double) boolIn;
2899 /******************************************************************************
2900 * VarR8FromI1 [OLEAUT32.217]
2902 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2904 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2906 *pdblOut = (double) cIn;
2911 /******************************************************************************
2912 * VarR8FromUI2 [OLEAUT32.218]
2914 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2916 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2918 *pdblOut = (double) uiIn;
2923 /******************************************************************************
2924 * VarR8FromUI4 [OLEAUT32.219]
2926 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2928 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2930 *pdblOut = (double) ulIn;
2935 /******************************************************************************
2936 * VarR8FromStr [OLEAUT32.84]
2938 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2940 double dValue = 0.0;
2941 LPSTR pNewString = NULL;
2943 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2945 /* Check if we have a valid argument
2947 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2948 RemoveCharacterFromString( pNewString, "," );
2949 if( IsValidRealString( pNewString ) == FALSE )
2951 return DISP_E_TYPEMISMATCH;
2954 /* Convert the valid string to a floating point number.
2956 dValue = atof( pNewString );
2958 /* We don't need the string anymore so free it.
2960 HeapFree( GetProcessHeap(), 0, pNewString );
2967 /**********************************************************************
2968 * VarR8FromCy [OLEAUT32.82]
2969 * Convert currency to double
2971 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2972 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2977 /******************************************************************************
2978 * VarDateFromUI1 [OLEAUT32.]
2980 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2982 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2984 *pdateOut = (DATE) bIn;
2989 /******************************************************************************
2990 * VarDateFromI2 [OLEAUT32.222]
2992 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2994 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2996 *pdateOut = (DATE) sIn;
3001 /******************************************************************************
3002 * VarDateFromI4 [OLEAUT32.90]
3004 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
3006 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
3008 if( lIn < DATE_MIN || lIn > DATE_MAX )
3010 return DISP_E_OVERFLOW;
3013 *pdateOut = (DATE) lIn;
3018 /******************************************************************************
3019 * VarDateFromR4 [OLEAUT32.91]
3021 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3023 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3025 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3027 return DISP_E_OVERFLOW;
3030 *pdateOut = (DATE) fltIn;
3035 /******************************************************************************
3036 * VarDateFromR8 [OLEAUT32.92]
3038 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3040 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3042 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3044 return DISP_E_OVERFLOW;
3047 *pdateOut = (DATE) dblIn;
3052 /******************************************************************************
3053 * VarDateFromStr [OLEAUT32.94]
3054 * The string representing the date is composed of two parts, a date and time.
3056 * The format of the time is has follows:
3057 * hh[:mm][:ss][AM|PM]
3058 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3059 * of space and/or tab characters, which are ignored.
3061 * The formats for the date part are has follows:
3065 * January dd[,] [yy]yy
3068 * Whitespace can be inserted anywhere between these tokens.
3070 * The formats for the date and time string are has follows.
3071 * date[whitespace][time]
3072 * [time][whitespace]date
3074 * These are the only characters allowed in a string representing a date and time:
3075 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3077 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3082 memset( &TM, 0, sizeof(TM) );
3084 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3086 if( DateTimeStringToTm( strIn, lcid, &TM ) )
3088 if( TmToDATE( &TM, pdateOut ) == FALSE )
3095 ret = DISP_E_TYPEMISMATCH;
3102 /******************************************************************************
3103 * VarDateFromI1 [OLEAUT32.221]
3105 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3107 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3109 *pdateOut = (DATE) cIn;
3114 /******************************************************************************
3115 * VarDateFromUI2 [OLEAUT32.222]
3117 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3119 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3121 if( uiIn > DATE_MAX )
3123 return DISP_E_OVERFLOW;
3126 *pdateOut = (DATE) uiIn;
3131 /******************************************************************************
3132 * VarDateFromUI4 [OLEAUT32.223]
3134 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3136 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3138 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3140 return DISP_E_OVERFLOW;
3143 *pdateOut = (DATE) ulIn;
3148 /******************************************************************************
3149 * VarDateFromBool [OLEAUT32.96]
3151 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3153 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3155 *pdateOut = (DATE) boolIn;
3160 /**********************************************************************
3161 * VarDateFromCy [OLEAUT32.93]
3162 * Convert currency to date
3164 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3165 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3167 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3171 /******************************************************************************
3172 * VarBstrFromUI1 [OLEAUT32.108]
3174 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3176 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3177 sprintf( pBuffer, "%d", bVal );
3179 *pbstrOut = StringDupAtoBstr( pBuffer );
3184 /******************************************************************************
3185 * VarBstrFromI2 [OLEAUT32.109]
3187 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3189 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3190 sprintf( pBuffer, "%d", iVal );
3191 *pbstrOut = StringDupAtoBstr( pBuffer );
3196 /******************************************************************************
3197 * VarBstrFromI4 [OLEAUT32.110]
3199 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3201 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3203 sprintf( pBuffer, "%ld", lIn );
3204 *pbstrOut = StringDupAtoBstr( pBuffer );
3209 /******************************************************************************
3210 * VarBstrFromR4 [OLEAUT32.111]
3212 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3214 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3216 sprintf( pBuffer, "%.7g", fltIn );
3217 *pbstrOut = StringDupAtoBstr( pBuffer );
3222 /******************************************************************************
3223 * VarBstrFromR8 [OLEAUT32.112]
3225 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3227 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3229 sprintf( pBuffer, "%.15g", dblIn );
3230 *pbstrOut = StringDupAtoBstr( pBuffer );
3235 /******************************************************************************
3236 * VarBstrFromCy [OLEAUT32.113]
3238 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3244 /******************************************************************************
3245 * VarBstrFromDate [OLEAUT32.114]
3247 * The date is implemented using an 8 byte floating-point number.
3248 * Days are represented by whole numbers increments starting with 0.00 has
3249 * being December 30 1899, midnight.
3250 * The hours are expressed as the fractional part of the number.
3251 * December 30 1899 at midnight = 0.00
3252 * January 1 1900 at midnight = 2.00
3253 * January 4 1900 at 6 AM = 5.25
3254 * January 4 1900 at noon = 5.50
3255 * December 29 1899 at midnight = -1.00
3256 * December 18 1899 at midnight = -12.00
3257 * December 18 1899 at 6AM = -12.25
3258 * December 18 1899 at 6PM = -12.75
3259 * December 19 1899 at midnight = -11.00
3260 * The tm structure is as follows:
3262 * int tm_sec; seconds after the minute - [0,59]
3263 * int tm_min; minutes after the hour - [0,59]
3264 * int tm_hour; hours since midnight - [0,23]
3265 * int tm_mday; day of the month - [1,31]
3266 * int tm_mon; months since January - [0,11]
3267 * int tm_year; years
3268 * int tm_wday; days since Sunday - [0,6]
3269 * int tm_yday; days since January 1 - [0,365]
3270 * int tm_isdst; daylight savings time flag
3273 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3276 memset( &TM, 0, sizeof(TM) );
3278 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3280 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3282 return E_INVALIDARG;
3285 if( dwFlags & VAR_DATEVALUEONLY )
3286 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3287 else if( dwFlags & VAR_TIMEVALUEONLY )
3288 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3290 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3292 *pbstrOut = StringDupAtoBstr( pBuffer );
3297 /******************************************************************************
3298 * VarBstrFromBool [OLEAUT32.116]
3300 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3302 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3304 if( boolIn == VARIANT_FALSE )
3306 sprintf( pBuffer, "False" );
3310 sprintf( pBuffer, "True" );
3313 *pbstrOut = StringDupAtoBstr( pBuffer );
3318 /******************************************************************************
3319 * VarBstrFromI1 [OLEAUT32.229]
3321 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3323 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3324 sprintf( pBuffer, "%d", cIn );
3325 *pbstrOut = StringDupAtoBstr( pBuffer );
3330 /******************************************************************************
3331 * VarBstrFromUI2 [OLEAUT32.230]
3333 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3335 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3336 sprintf( pBuffer, "%d", uiIn );
3337 *pbstrOut = StringDupAtoBstr( pBuffer );
3342 /******************************************************************************
3343 * VarBstrFromUI4 [OLEAUT32.231]
3345 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3347 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3348 sprintf( pBuffer, "%ld", ulIn );
3349 *pbstrOut = StringDupAtoBstr( pBuffer );
3354 /******************************************************************************
3355 * VarBoolFromUI1 [OLEAUT32.118]
3357 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3359 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3363 *pboolOut = VARIANT_FALSE;
3367 *pboolOut = VARIANT_TRUE;
3373 /******************************************************************************
3374 * VarBoolFromI2 [OLEAUT32.119]
3376 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3378 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3382 *pboolOut = VARIANT_FALSE;
3386 *pboolOut = VARIANT_TRUE;
3392 /******************************************************************************
3393 * VarBoolFromI4 [OLEAUT32.120]
3395 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3397 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3401 *pboolOut = VARIANT_FALSE;
3405 *pboolOut = VARIANT_TRUE;
3411 /******************************************************************************
3412 * VarBoolFromR4 [OLEAUT32.121]
3414 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3416 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3420 *pboolOut = VARIANT_FALSE;
3424 *pboolOut = VARIANT_TRUE;
3430 /******************************************************************************
3431 * VarBoolFromR8 [OLEAUT32.122]
3433 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3435 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3439 *pboolOut = VARIANT_FALSE;
3443 *pboolOut = VARIANT_TRUE;
3449 /******************************************************************************
3450 * VarBoolFromDate [OLEAUT32.123]
3452 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3454 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3458 *pboolOut = VARIANT_FALSE;
3462 *pboolOut = VARIANT_TRUE;
3468 /******************************************************************************
3469 * VarBoolFromStr [OLEAUT32.125]
3471 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3474 char* pNewString = NULL;
3476 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3478 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3480 if( pNewString == NULL || strlen( pNewString ) == 0 )
3482 ret = DISP_E_TYPEMISMATCH;
3487 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3489 *pboolOut = VARIANT_TRUE;
3491 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3493 *pboolOut = VARIANT_FALSE;
3497 /* Try converting the string to a floating point number.
3499 double dValue = 0.0;
3500 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3503 ret = DISP_E_TYPEMISMATCH;
3505 else if( dValue == 0.0 )
3507 *pboolOut = VARIANT_FALSE;
3511 *pboolOut = VARIANT_TRUE;
3516 HeapFree( GetProcessHeap(), 0, pNewString );
3521 /******************************************************************************
3522 * VarBoolFromI1 [OLEAUT32.233]
3524 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3526 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3530 *pboolOut = VARIANT_FALSE;
3534 *pboolOut = VARIANT_TRUE;
3540 /******************************************************************************
3541 * VarBoolFromUI2 [OLEAUT32.234]
3543 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3545 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3549 *pboolOut = VARIANT_FALSE;
3553 *pboolOut = VARIANT_TRUE;
3559 /******************************************************************************
3560 * VarBoolFromUI4 [OLEAUT32.235]
3562 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3564 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3568 *pboolOut = VARIANT_FALSE;
3572 *pboolOut = VARIANT_TRUE;
3578 /**********************************************************************
3579 * VarBoolFromCy [OLEAUT32.124]
3580 * Convert currency to boolean
3582 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3583 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3589 /******************************************************************************
3590 * VarI1FromUI1 [OLEAUT32.244]
3592 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3594 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3596 /* Check range of value.
3598 if( bIn > CHAR_MAX )
3600 return DISP_E_OVERFLOW;
3603 *pcOut = (CHAR) bIn;
3608 /******************************************************************************
3609 * VarI1FromI2 [OLEAUT32.245]
3611 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3613 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3615 if( uiIn > CHAR_MAX )
3617 return DISP_E_OVERFLOW;
3620 *pcOut = (CHAR) uiIn;
3625 /******************************************************************************
3626 * VarI1FromI4 [OLEAUT32.246]
3628 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3630 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3632 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3634 return DISP_E_OVERFLOW;
3637 *pcOut = (CHAR) lIn;
3642 /******************************************************************************
3643 * VarI1FromR4 [OLEAUT32.247]
3645 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3647 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3649 fltIn = round( fltIn );
3650 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3652 return DISP_E_OVERFLOW;
3655 *pcOut = (CHAR) fltIn;
3660 /******************************************************************************
3661 * VarI1FromR8 [OLEAUT32.248]
3663 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3665 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3667 dblIn = round( dblIn );
3668 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3670 return DISP_E_OVERFLOW;
3673 *pcOut = (CHAR) dblIn;
3678 /******************************************************************************
3679 * VarI1FromDate [OLEAUT32.249]
3681 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3683 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3685 dateIn = round( dateIn );
3686 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3688 return DISP_E_OVERFLOW;
3691 *pcOut = (CHAR) dateIn;
3696 /******************************************************************************
3697 * VarI1FromStr [OLEAUT32.251]
3699 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3701 double dValue = 0.0;
3702 LPSTR pNewString = NULL;
3704 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3706 /* Check if we have a valid argument
3708 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3709 RemoveCharacterFromString( pNewString, "," );
3710 if( IsValidRealString( pNewString ) == FALSE )
3712 return DISP_E_TYPEMISMATCH;
3715 /* Convert the valid string to a floating point number.
3717 dValue = atof( pNewString );
3719 /* We don't need the string anymore so free it.
3721 HeapFree( GetProcessHeap(), 0, pNewString );
3723 /* Check range of value.
3725 dValue = round( dValue );
3726 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3728 return DISP_E_OVERFLOW;
3731 *pcOut = (CHAR) dValue;
3736 /******************************************************************************
3737 * VarI1FromBool [OLEAUT32.253]
3739 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3741 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3743 *pcOut = (CHAR) boolIn;
3748 /******************************************************************************
3749 * VarI1FromUI2 [OLEAUT32.254]
3751 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3753 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3755 if( uiIn > CHAR_MAX )
3757 return DISP_E_OVERFLOW;
3760 *pcOut = (CHAR) uiIn;
3765 /******************************************************************************
3766 * VarI1FromUI4 [OLEAUT32.255]
3768 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3770 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3772 if( ulIn > CHAR_MAX )
3774 return DISP_E_OVERFLOW;
3777 *pcOut = (CHAR) ulIn;
3782 /**********************************************************************
3783 * VarI1FromCy [OLEAUT32.250]
3784 * Convert currency to signed char
3786 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3787 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3789 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3795 /******************************************************************************
3796 * VarUI2FromUI1 [OLEAUT32.257]
3798 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3800 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3802 *puiOut = (USHORT) bIn;
3807 /******************************************************************************
3808 * VarUI2FromI2 [OLEAUT32.258]
3810 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3812 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3814 if( uiIn < UI2_MIN )
3816 return DISP_E_OVERFLOW;
3819 *puiOut = (USHORT) uiIn;
3824 /******************************************************************************
3825 * VarUI2FromI4 [OLEAUT32.259]
3827 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3829 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3831 if( lIn < UI2_MIN || lIn > UI2_MAX )
3833 return DISP_E_OVERFLOW;
3836 *puiOut = (USHORT) lIn;
3841 /******************************************************************************
3842 * VarUI2FromR4 [OLEAUT32.260]
3844 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3846 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3848 fltIn = round( fltIn );
3849 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3851 return DISP_E_OVERFLOW;
3854 *puiOut = (USHORT) fltIn;
3859 /******************************************************************************
3860 * VarUI2FromR8 [OLEAUT32.261]
3862 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3864 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3866 dblIn = round( dblIn );
3867 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3869 return DISP_E_OVERFLOW;
3872 *puiOut = (USHORT) dblIn;
3877 /******************************************************************************
3878 * VarUI2FromDate [OLEAUT32.262]
3880 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3882 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3884 dateIn = round( dateIn );
3885 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3887 return DISP_E_OVERFLOW;
3890 *puiOut = (USHORT) dateIn;
3895 /******************************************************************************
3896 * VarUI2FromStr [OLEAUT32.264]
3898 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3900 double dValue = 0.0;
3901 LPSTR pNewString = NULL;
3903 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3905 /* Check if we have a valid argument
3907 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3908 RemoveCharacterFromString( pNewString, "," );
3909 if( IsValidRealString( pNewString ) == FALSE )
3911 return DISP_E_TYPEMISMATCH;
3914 /* Convert the valid string to a floating point number.
3916 dValue = atof( pNewString );
3918 /* We don't need the string anymore so free it.
3920 HeapFree( GetProcessHeap(), 0, pNewString );
3922 /* Check range of value.
3924 dValue = round( dValue );
3925 if( dValue < UI2_MIN || dValue > UI2_MAX )
3927 return DISP_E_OVERFLOW;
3930 *puiOut = (USHORT) dValue;
3935 /******************************************************************************
3936 * VarUI2FromBool [OLEAUT32.266]
3938 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3940 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3942 *puiOut = (USHORT) boolIn;
3947 /******************************************************************************
3948 * VarUI2FromI1 [OLEAUT32.267]
3950 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3952 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3954 *puiOut = (USHORT) cIn;
3959 /******************************************************************************
3960 * VarUI2FromUI4 [OLEAUT32.268]
3962 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3964 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3966 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3968 return DISP_E_OVERFLOW;
3971 *puiOut = (USHORT) ulIn;
3976 /******************************************************************************
3977 * VarUI4FromStr [OLEAUT32.277]
3979 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3981 double dValue = 0.0;
3982 LPSTR pNewString = NULL;
3984 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3986 /* Check if we have a valid argument
3988 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3989 RemoveCharacterFromString( pNewString, "," );
3990 if( IsValidRealString( pNewString ) == FALSE )
3992 return DISP_E_TYPEMISMATCH;
3995 /* Convert the valid string to a floating point number.
3997 dValue = atof( pNewString );
3999 /* We don't need the string anymore so free it.
4001 HeapFree( GetProcessHeap(), 0, pNewString );
4003 /* Check range of value.
4005 dValue = round( dValue );
4006 if( dValue < UI4_MIN || dValue > UI4_MAX )
4008 return DISP_E_OVERFLOW;
4011 *pulOut = (ULONG) dValue;
4016 /**********************************************************************
4017 * VarUI2FromCy [OLEAUT32.263]
4018 * Convert currency to unsigned short
4020 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4021 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4023 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4025 *pusOut = (USHORT)t;
4030 /******************************************************************************
4031 * VarUI4FromUI1 [OLEAUT32.270]
4033 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4035 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4037 *pulOut = (USHORT) bIn;
4042 /******************************************************************************
4043 * VarUI4FromI2 [OLEAUT32.271]
4045 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4047 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4049 if( uiIn < UI4_MIN )
4051 return DISP_E_OVERFLOW;
4054 *pulOut = (ULONG) uiIn;
4059 /******************************************************************************
4060 * VarUI4FromI4 [OLEAUT32.272]
4062 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4064 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4068 return DISP_E_OVERFLOW;
4071 *pulOut = (ULONG) lIn;
4076 /******************************************************************************
4077 * VarUI4FromR4 [OLEAUT32.273]
4079 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4081 fltIn = round( fltIn );
4082 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4084 return DISP_E_OVERFLOW;
4087 *pulOut = (ULONG) fltIn;
4092 /******************************************************************************
4093 * VarUI4FromR8 [OLEAUT32.274]
4095 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4097 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4099 dblIn = round( dblIn );
4100 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4102 return DISP_E_OVERFLOW;
4105 *pulOut = (ULONG) dblIn;
4110 /******************************************************************************
4111 * VarUI4FromDate [OLEAUT32.275]
4113 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4115 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4117 dateIn = round( dateIn );
4118 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4120 return DISP_E_OVERFLOW;
4123 *pulOut = (ULONG) dateIn;
4128 /******************************************************************************
4129 * VarUI4FromBool [OLEAUT32.279]
4131 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4133 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4135 *pulOut = (ULONG) boolIn;
4140 /******************************************************************************
4141 * VarUI4FromI1 [OLEAUT32.280]
4143 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4145 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4147 *pulOut = (ULONG) cIn;
4152 /******************************************************************************
4153 * VarUI4FromUI2 [OLEAUT32.281]
4155 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4157 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4159 *pulOut = (ULONG) uiIn;
4164 /**********************************************************************
4165 * VarUI4FromCy [OLEAUT32.276]
4166 * Convert currency to unsigned long
4168 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4169 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4171 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4178 /**********************************************************************
4179 * VarCyFromUI1 [OLEAUT32.98]
4180 * Convert unsigned char to currency
4182 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4184 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4189 /**********************************************************************
4190 * VarCyFromI2 [OLEAUT32.99]
4191 * Convert signed short to currency
4193 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4194 if (sIn < 0) pcyOut->s.Hi = -1;
4195 else pcyOut->s.Hi = 0;
4196 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4201 /**********************************************************************
4202 * VarCyFromI4 [OLEAUT32.100]
4203 * Convert signed long to currency
4205 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4206 double t = (double)lIn * (double)10000;
4207 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4208 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4209 if (lIn < 0) pcyOut->s.Hi--;
4214 /**********************************************************************
4215 * VarCyFromR4 [OLEAUT32.101]
4216 * Convert float to currency
4218 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4219 double t = round((double)fltIn * (double)10000);
4220 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4221 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4222 if (fltIn < 0) pcyOut->s.Hi--;
4227 /**********************************************************************
4228 * VarCyFromR8 [OLEAUT32.102]
4229 * Convert double to currency
4231 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4232 double t = round(dblIn * (double)10000);
4233 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4234 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4235 if (dblIn < 0) pcyOut->s.Hi--;
4240 /**********************************************************************
4241 * VarCyFromDate [OLEAUT32.103]
4242 * Convert date to currency
4244 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4245 double t = round((double)dateIn * (double)10000);
4246 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4247 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4248 if (dateIn < 0) pcyOut->s.Hi--;
4253 /**********************************************************************
4254 * VarCyFromStr [OLEAUT32.104]
4256 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4262 /**********************************************************************
4263 * VarCyFromBool [OLEAUT32.106]
4264 * Convert boolean to currency
4266 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4267 if (boolIn < 0) pcyOut->s.Hi = -1;
4268 else pcyOut->s.Hi = 0;
4269 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4274 /**********************************************************************
4275 * VarCyFromI1 [OLEAUT32.225]
4276 * Convert signed char to currency
4278 HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4279 if (cIn < 0) pcyOut->s.Hi = -1;
4280 else pcyOut->s.Hi = 0;
4281 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4286 /**********************************************************************
4287 * VarCyFromUI2 [OLEAUT32.226]
4288 * Convert unsigned short to currency
4290 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4292 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4297 /**********************************************************************
4298 * VarCyFromUI4 [OLEAUT32.227]
4299 * Convert unsigned long to currency
4301 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4302 double t = (double)ulIn * (double)10000;
4303 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4304 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4310 /**********************************************************************
4311 * DosDateTimeToVariantTime [OLEAUT32.14]
4312 * Convert dos representation of time to the date and time representation
4313 * stored in a variant.
4315 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4320 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4322 t.tm_sec = (wDosTime & 0x001f) * 2;
4323 t.tm_min = (wDosTime & 0x07e0) >> 5;
4324 t.tm_hour = (wDosTime & 0xf800) >> 11;
4326 t.tm_mday = (wDosDate & 0x001f);
4327 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4328 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4330 return TmToDATE( &t, pvtime );