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 date prior to 1900.
20 * - The parsing does not accept has many formats has 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.001
92 * One + every 400 years: 1/400 -> 365.0025
94 static const double DAYS_IN_ONE_YEAR = 365.2515;
98 /******************************************************************************
99 * DateTimeStringToTm [INTERNAL]
101 * Converts a string representation of a date and/or time to a tm structure.
103 * Note this function uses the postgresql date parsing functions found
104 * in the parsedt.c file.
106 * Returns TRUE if successfull.
108 * Note: This function does not parse the day of the week,
109 * daylight savings time. It will only fill the followin fields in
110 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
112 ******************************************************************************/
113 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
120 char *field[MAXDATEFIELDS];
121 int ftype[MAXDATEFIELDS];
122 char lowstr[MAXDATELEN + 1];
123 char* strDateTime = NULL;
125 /* Convert the string to ASCII since this is the only format
126 * postgesql can handle.
128 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
130 if( strDateTime != NULL )
132 /* Make sure we don't go over the maximum length
133 * accepted by postgesql.
135 if( strlen( strDateTime ) <= MAXDATELEN )
137 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
139 if( lcid & VAR_DATEVALUEONLY )
141 /* Get the date information.
142 * It returns 0 if date information was
143 * present and 1 if only time information was present.
144 * -1 if an error occures.
146 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
148 /* Eliminate the time information since we
149 * were asked to get date information only.
157 if( lcid & VAR_TIMEVALUEONLY )
159 /* Get time information only.
161 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
168 /* Get both date and time information.
169 * It returns 0 if date information was
170 * present and 1 if only time information was present.
171 * -1 if an error occures.
173 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
180 HeapFree( GetProcessHeap(), 0, strDateTime );
191 /******************************************************************************
192 * TmToDATE [INTERNAL]
194 * The date is implemented using an 8 byte floating-point number.
195 * Days are represented by whole numbers increments starting with 0.00 has
196 * being December 30 1899, midnight.
197 * The hours are expressed as the fractional part of the number.
198 * December 30 1899 at midnight = 0.00
199 * January 1 1900 at midnight = 2.00
200 * January 4 1900 at 6 AM = 5.25
201 * January 4 1900 at noon = 5.50
202 * December 29 1899 at midnight = -1.00
203 * December 18 1899 at midnight = -12.00
204 * December 18 1899 at 6AM = -12.25
205 * December 18 1899 at 6PM = -12.75
206 * December 19 1899 at midnight = -11.00
207 * The tm structure is as follows:
209 * int tm_sec; seconds after the minute - [0,59]
210 * int tm_min; minutes after the hour - [0,59]
211 * int tm_hour; hours since midnight - [0,23]
212 * int tm_mday; day of the month - [1,31]
213 * int tm_mon; months since January - [0,11]
215 * int tm_wday; days since Sunday - [0,6]
216 * int tm_yday; days since January 1 - [0,365]
217 * int tm_isdst; daylight savings time flag
220 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
221 * and tm_isdst fields of the tm structure. And only converts years
224 * Returns TRUE if successfull.
226 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
228 if( (pTm->tm_year - 1900) >= 0 )
232 /* Start at 1. This is the way DATE is defined.
233 * January 1, 1900 at Midnight is 1.00.
234 * January 1, 1900 at 6AM is 1.25.
239 /* Add the number of days corresponding to
242 *pDateOut += (pTm->tm_year - 1900) * 365;
244 /* Add the leap days in the previous years between now and 1900.
245 * Note a leap year is one that is a multiple of 4
246 * but not of a 100. Except if it is a multiple of
247 * 400 then it is a leap year.
249 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
250 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
251 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
253 /* Set the leap year flag if the
254 * current year specified by tm_year is a
255 * leap year. This will be used to add a day
258 if( isleap( pTm->tm_year ) )
261 /* Add the number of days corresponding to
264 switch( pTm->tm_mon )
270 *pDateOut += ( 59 + leapYear );
273 *pDateOut += ( 90 + leapYear );
276 *pDateOut += ( 120 + leapYear );
279 *pDateOut += ( 151 + leapYear );
282 *pDateOut += ( 181 + leapYear );
285 *pDateOut += ( 212 + leapYear );
288 *pDateOut += ( 243 + leapYear );
291 *pDateOut += ( 273 + leapYear );
294 *pDateOut += ( 304 + leapYear );
297 *pDateOut += ( 334 + leapYear );
300 /* Add the number of days in this month.
302 *pDateOut += pTm->tm_mday;
304 /* Add the number of seconds, minutes, and hours
305 * to the DATE. Note these are the fracionnal part
306 * of the DATE so seconds / number of seconds in a day.
308 *pDateOut += pTm->tm_hour / 24.0;
309 *pDateOut += pTm->tm_min / 1440.0;
310 *pDateOut += pTm->tm_sec / 86400.0;
316 /******************************************************************************
317 * DateToTm [INTERNAL]
319 * This function converst a windows DATE to a tm structure.
321 * It does not fill all the fields of the tm structure.
322 * Here is a list of the fields that are filled:
323 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
325 * Note this function does not support dates before the January 1, 1900
326 * or ( dateIn < 2.0 ).
328 * Returns TRUE if successfull.
330 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
332 /* Do not process dates smaller than January 1, 1900.
333 * Which corresponds to 2.0 in the windows DATE format.
337 double decimalPart = 0.0;
338 double wholePart = 0.0;
340 memset(pTm,0,sizeof(*pTm));
342 /* Because of the nature of DATE format witch
343 * associates 2.0 to January 1, 1900. We will
344 * remove 1.0 from the whole part of the DATE
345 * so that in the following code 1.0
346 * will correspond to January 1, 1900.
347 * This simplyfies the processing of the DATE value.
351 wholePart = (double) floor( dateIn );
352 decimalPart = fmod( dateIn, wholePart );
354 if( !(lcid & VAR_TIMEVALUEONLY) )
358 double yearsSince1900 = 0;
359 /* Start at 1900, this where the DATE time 0.0 starts.
362 /* find in what year the day in the "wholePart" falls into.
363 * add the value to the year field.
365 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
366 pTm->tm_year += yearsSince1900;
367 /* determine if this is a leap year.
369 if( isleap( pTm->tm_year ) )
375 /* find what day of that year does the "wholePart" corresponds to.
376 * Note: nDay is in [1-366] format
378 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
379 /* Set the tm_yday value.
380 * Note: The day is must be converted from [1-366] to [0-365]
382 /*pTm->tm_yday = nDay - 1;*/
383 /* find which mount this day corresponds to.
390 else if( nDay <= ( 59 + leapYear ) )
392 pTm->tm_mday = nDay - 31;
395 else if( nDay <= ( 90 + leapYear ) )
397 pTm->tm_mday = nDay - ( 59 + leapYear );
400 else if( nDay <= ( 120 + leapYear ) )
402 pTm->tm_mday = nDay - ( 90 + leapYear );
405 else if( nDay <= ( 151 + leapYear ) )
407 pTm->tm_mday = nDay - ( 120 + leapYear );
410 else if( nDay <= ( 181 + leapYear ) )
412 pTm->tm_mday = nDay - ( 151 + leapYear );
415 else if( nDay <= ( 212 + leapYear ) )
417 pTm->tm_mday = nDay - ( 181 + leapYear );
420 else if( nDay <= ( 243 + leapYear ) )
422 pTm->tm_mday = nDay - ( 212 + leapYear );
425 else if( nDay <= ( 273 + leapYear ) )
427 pTm->tm_mday = nDay - ( 243 + leapYear );
430 else if( nDay <= ( 304 + leapYear ) )
432 pTm->tm_mday = nDay - ( 273 + leapYear );
435 else if( nDay <= ( 334 + leapYear ) )
437 pTm->tm_mday = nDay - ( 304 + leapYear );
440 else if( nDay <= ( 365 + leapYear ) )
442 pTm->tm_mday = nDay - ( 334 + leapYear );
446 if( !(lcid & VAR_DATEVALUEONLY) )
448 /* find the number of seconds in this day.
449 * fractional part times, hours, minutes, seconds.
451 pTm->tm_hour = (int) ( decimalPart * 24 );
452 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
453 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
462 /******************************************************************************
463 * SizeOfVariantData [INTERNAL]
465 * This function finds the size of the data referenced by a Variant based
466 * the type "vt" of the Variant.
468 static int SizeOfVariantData( VARIANT* parg )
471 switch( parg->vt & VT_TYPEMASK )
474 size = sizeof(short);
486 size = sizeof(unsigned short);
489 size = sizeof(unsigned int);
492 size = sizeof(unsigned long);
495 size = sizeof(float);
498 size = sizeof(double);
504 size = sizeof(VARIANT_BOOL);
507 size = sizeof(void*);
514 FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
520 /******************************************************************************
521 * StringDupAtoBstr [INTERNAL]
524 static BSTR StringDupAtoBstr( char* strIn )
527 OLECHAR* pNewString = NULL;
528 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
529 bstr = SysAllocString( pNewString );
530 HeapFree( GetProcessHeap(), 0, pNewString );
534 /******************************************************************************
537 * Round the double value to the nearest integer value.
539 static double round( double d )
541 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
542 BOOL bEvenNumber = FALSE;
545 /* Save the sign of the number
547 nSign = (d >= 0.0) ? 1 : -1;
550 /* Remove the decimals.
552 integerValue = floor( d );
554 /* Set the Even flag. This is used to round the number when
555 * the decimals are exactly 1/2. If the integer part is
556 * odd the number is rounded up. If the integer part
557 * is even the number is rounded down. Using this method
558 * numbers are rounded up|down half the time.
560 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
562 /* Remove the integral part of the number.
564 decimals = d - integerValue;
566 /* Note: Ceil returns the smallest integer that is greater that x.
567 * and floor returns the largest integer that is less than or equal to x.
571 /* If the decimal part is greater than 1/2
573 roundedValue = ceil( d );
575 else if( decimals < 0.5 )
577 /* If the decimal part is smaller than 1/2
579 roundedValue = floor( d );
583 /* the decimals are exactly 1/2 so round according to
584 * the bEvenNumber flag.
588 roundedValue = floor( d );
592 roundedValue = ceil( d );
596 return roundedValue * nSign;
599 /******************************************************************************
600 * RemoveCharacterFromString [INTERNAL]
602 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
604 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
606 LPSTR pNewString = NULL;
607 LPSTR strToken = NULL;
610 /* Check if we have a valid argument
614 pNewString = strdup( str );
616 strToken = strtok( pNewString, strOfCharToRemove );
617 while( strToken != NULL ) {
618 strcat( str, strToken );
619 strToken = strtok( NULL, strOfCharToRemove );
626 /******************************************************************************
627 * GetValidRealString [INTERNAL]
629 * Checks if the string is of proper format to be converted to a real value.
631 static BOOL IsValidRealString( LPSTR strRealString )
633 /* Real values that have a decimal point are required to either have
634 * digits before or after the decimal point. We will assume that
635 * we do not have any digits at either position. If we do encounter
636 * some we will disable this flag.
638 BOOL bDigitsRequired = TRUE;
639 /* Processed fields in the string representation of the real number.
641 BOOL bWhiteSpaceProcessed = FALSE;
642 BOOL bFirstSignProcessed = FALSE;
643 BOOL bFirstDigitsProcessed = FALSE;
644 BOOL bDecimalPointProcessed = FALSE;
645 BOOL bSecondDigitsProcessed = FALSE;
646 BOOL bExponentProcessed = FALSE;
647 BOOL bSecondSignProcessed = FALSE;
648 BOOL bThirdDigitsProcessed = FALSE;
649 /* Assume string parameter "strRealString" is valid and try to disprove it.
651 BOOL bValidRealString = TRUE;
653 /* Used to count the number of tokens in the "strRealString".
655 LPSTR strToken = NULL;
659 /* Check if we have a valid argument
661 if( strRealString == NULL )
663 bValidRealString = FALSE;
666 if( bValidRealString == TRUE )
668 /* Make sure we only have ONE token in the string.
670 strToken = strtok( strRealString, " " );
671 while( strToken != NULL ) {
673 strToken = strtok( NULL, " " );
678 bValidRealString = FALSE;
683 /* Make sure this token contains only valid characters.
684 * The string argument to atof has the following form:
685 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
686 * Whitespace consists of space and|or <TAB> characters, which are ignored.
687 * Sign is either plus '+' or minus '-'.
688 * Digits are one or more decimal digits.
689 * Note: If no digits appear before the decimal point, at least one must
690 * appear after the decimal point.
691 * The decimal digits may be followed by an exponent.
692 * An Exponent consists of an introductory letter ( D, d, E, or e) and
693 * an optionally signed decimal integer.
695 pChar = strRealString;
696 while( bValidRealString == TRUE && *pChar != '\0' )
704 if( bWhiteSpaceProcessed ||
705 bFirstSignProcessed ||
706 bFirstDigitsProcessed ||
707 bDecimalPointProcessed ||
708 bSecondDigitsProcessed ||
709 bExponentProcessed ||
710 bSecondSignProcessed ||
711 bThirdDigitsProcessed )
713 bValidRealString = FALSE;
720 if( bFirstSignProcessed == FALSE )
722 if( bFirstDigitsProcessed ||
723 bDecimalPointProcessed ||
724 bSecondDigitsProcessed ||
725 bExponentProcessed ||
726 bSecondSignProcessed ||
727 bThirdDigitsProcessed )
729 bValidRealString = FALSE;
731 bWhiteSpaceProcessed = TRUE;
732 bFirstSignProcessed = TRUE;
734 else if( bSecondSignProcessed == FALSE )
736 /* Note: The exponent must be present in
737 * order to accept the second sign...
739 if( bExponentProcessed == FALSE ||
740 bThirdDigitsProcessed ||
743 bValidRealString = FALSE;
745 bFirstSignProcessed = TRUE;
746 bWhiteSpaceProcessed = TRUE;
747 bFirstDigitsProcessed = TRUE;
748 bDecimalPointProcessed = TRUE;
749 bSecondDigitsProcessed = TRUE;
750 bSecondSignProcessed = TRUE;
766 if( bFirstDigitsProcessed == FALSE )
768 if( bDecimalPointProcessed ||
769 bSecondDigitsProcessed ||
770 bExponentProcessed ||
771 bSecondSignProcessed ||
772 bThirdDigitsProcessed )
774 bValidRealString = FALSE;
776 bFirstSignProcessed = TRUE;
777 bWhiteSpaceProcessed = TRUE;
778 /* We have found some digits before the decimal point
779 * so disable the "Digits required" flag.
781 bDigitsRequired = FALSE;
783 else if( bSecondDigitsProcessed == FALSE )
785 if( bExponentProcessed ||
786 bSecondSignProcessed ||
787 bThirdDigitsProcessed )
789 bValidRealString = FALSE;
791 bFirstSignProcessed = TRUE;
792 bWhiteSpaceProcessed = TRUE;
793 bFirstDigitsProcessed = TRUE;
794 bDecimalPointProcessed = TRUE;
795 /* We have found some digits after the decimal point
796 * so disable the "Digits required" flag.
798 bDigitsRequired = FALSE;
800 else if( bThirdDigitsProcessed == FALSE )
802 /* Getting here means everything else should be processed.
803 * If we get anything else than a decimal following this
804 * digit it will be flagged by the other cases, so
805 * we do not really need to do anything in here.
809 /* If DecimalPoint...
812 if( bDecimalPointProcessed ||
813 bSecondDigitsProcessed ||
814 bExponentProcessed ||
815 bSecondSignProcessed ||
816 bThirdDigitsProcessed )
818 bValidRealString = FALSE;
820 bFirstSignProcessed = TRUE;
821 bWhiteSpaceProcessed = TRUE;
822 bFirstDigitsProcessed = TRUE;
823 bDecimalPointProcessed = TRUE;
831 if( bExponentProcessed ||
832 bSecondSignProcessed ||
833 bThirdDigitsProcessed ||
836 bValidRealString = FALSE;
838 bFirstSignProcessed = TRUE;
839 bWhiteSpaceProcessed = TRUE;
840 bFirstDigitsProcessed = TRUE;
841 bDecimalPointProcessed = TRUE;
842 bSecondDigitsProcessed = TRUE;
843 bExponentProcessed = TRUE;
846 bValidRealString = FALSE;
849 /* Process next character.
854 /* If the required digits were not present we have an invalid
855 * string representation of a real number.
857 if( bDigitsRequired == TRUE )
859 bValidRealString = FALSE;
862 return bValidRealString;
866 /******************************************************************************
869 * This function dispatches execution to the proper conversion API
870 * to do the necessary coercion.
872 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
875 unsigned short vtFrom = 0;
876 vtFrom = ps->vt & VT_TYPEMASK;
878 /* Note: Since "long" and "int" values both have 4 bytes and are
879 * both signed integers "int" will be treated as "long" in the
881 * The same goes for their unsigned versions.
884 /* Trivial Case: If the coercion is from two types that are
885 * identical then we can blindly copy from one argument to another.*/
888 return VariantCopy(pd,ps);
891 /* Cases requiring thought*/
896 res = VariantClear( pd );
899 res = VariantClear( pd );
909 res = VariantCopy( pd, ps );
912 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
916 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
919 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
922 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
926 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
929 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
932 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
935 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
938 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
941 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
944 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
946 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
948 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
950 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
952 res = DISP_E_TYPEMISMATCH;
953 FIXME("Coercion from %d to %d\n", vtFrom, vt );
962 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
965 res = VariantCopy( pd, ps );
969 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
972 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
975 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
979 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
982 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
985 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
988 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
991 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
994 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
997 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
999 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1001 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
1003 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
1005 res = DISP_E_TYPEMISMATCH;
1006 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1016 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1019 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1023 res = VariantCopy( pd, ps );
1026 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1029 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1033 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1036 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1039 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1042 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1045 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1048 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1051 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1052 case( VT_DISPATCH ):
1053 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1055 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1057 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1059 res = DISP_E_TYPEMISMATCH;
1060 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1069 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1072 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1076 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1079 res = VariantCopy( pd, ps );
1082 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1086 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1089 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1092 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1095 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1098 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1101 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1104 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1105 case( VT_DISPATCH ):
1106 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1108 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1110 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1112 res = DISP_E_TYPEMISMATCH;
1113 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1122 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1125 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1129 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1132 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1135 res = VariantCopy( pd, ps );
1139 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1142 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1145 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1148 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1151 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1154 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1157 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1158 case( VT_DISPATCH ):
1159 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1161 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1163 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1165 res = DISP_E_TYPEMISMATCH;
1166 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1176 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1179 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1183 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1186 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1189 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1192 res = VariantCopy( pd, ps );
1195 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1198 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1201 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1204 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1207 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1210 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1211 case( VT_DISPATCH ):
1212 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1214 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1216 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1218 res = DISP_E_TYPEMISMATCH;
1219 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1228 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1231 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1235 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1238 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1241 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1245 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1248 res = VariantCopy( pd, ps );
1251 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1254 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1257 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1260 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1263 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1264 case( VT_DISPATCH ):
1265 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1267 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1269 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1271 res = DISP_E_TYPEMISMATCH;
1272 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1281 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1284 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1288 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1291 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1294 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1298 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1301 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1304 res = VariantCopy( pd, ps );
1307 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1310 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1313 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1316 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1317 case( VT_DISPATCH ):
1318 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1320 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1322 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1324 res = DISP_E_TYPEMISMATCH;
1325 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1334 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1337 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1340 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1343 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1346 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1349 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1352 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1355 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1358 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1361 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1364 res = VariantCopy( pd, ps );
1367 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1370 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1373 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1374 case( VT_DISPATCH ):
1375 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1377 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1379 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1381 res = DISP_E_TYPEMISMATCH;
1382 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1391 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1394 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1397 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1400 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1403 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1406 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1409 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1412 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1415 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1418 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1421 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1424 res = VariantCopy( pd, ps );
1427 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1430 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1431 case( VT_DISPATCH ):
1432 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1434 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1436 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1438 res = DISP_E_TYPEMISMATCH;
1439 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1448 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1451 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1454 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1457 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1460 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1463 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1466 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1469 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1472 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1475 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1478 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1481 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1484 res = VariantCopy( pd, ps );
1487 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1488 case( VT_DISPATCH ):
1489 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1491 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1493 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1495 res = DISP_E_TYPEMISMATCH;
1496 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1505 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1508 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1511 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1514 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1517 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1520 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1523 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1526 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1529 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1532 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1535 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1538 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1541 res = VariantCopy( pd, ps );
1544 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1545 case( VT_DISPATCH ):
1546 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1548 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1550 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1552 res = DISP_E_TYPEMISMATCH;
1553 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1559 res = DISP_E_TYPEMISMATCH;
1560 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1567 /******************************************************************************
1568 * ValidateVtRange [INTERNAL]
1570 * Used internally by the hi-level Variant API to determine
1571 * if the vartypes are valid.
1573 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1575 /* if by value we must make sure it is in the
1576 * range of the valid types.
1578 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1580 return DISP_E_BADVARTYPE;
1586 /******************************************************************************
1587 * ValidateVartype [INTERNAL]
1589 * Used internally by the hi-level Variant API to determine
1590 * if the vartypes are valid.
1592 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1596 /* check if we have a valid argument.
1600 /* if by reference check that the type is in
1601 * the valid range and that it is not of empty or null type
1603 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1604 ( vt & VT_TYPEMASK ) == VT_NULL ||
1605 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1613 res = ValidateVtRange( vt );
1619 /******************************************************************************
1620 * ValidateVt [INTERNAL]
1622 * Used internally by the hi-level Variant API to determine
1623 * if the vartypes are valid.
1625 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1629 /* check if we have a valid argument.
1633 /* if by reference check that the type is in
1634 * the valid range and that it is not of empty or null type
1636 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1637 ( vt & VT_TYPEMASK ) == VT_NULL ||
1638 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1640 res = DISP_E_BADVARTYPE;
1646 res = ValidateVtRange( vt );
1656 /******************************************************************************
1657 * VariantInit32 [OLEAUT32.8]
1659 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1660 * contents of the Variant.
1662 void WINAPI VariantInit(VARIANTARG* pvarg)
1664 TRACE("(%p),stub\n",pvarg);
1666 memset(pvarg, 0, sizeof (VARIANTARG));
1667 pvarg->vt = VT_EMPTY;
1672 /******************************************************************************
1673 * VariantClear32 [OLEAUT32.9]
1675 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1676 * sets the wReservedX field to 0. The current contents of the VARIANT are
1677 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1678 * released. If VT_ARRAY the array is freed.
1680 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1683 TRACE("(%p)\n",pvarg);
1685 res = ValidateVariantType( pvarg->vt );
1688 if( !( pvarg->vt & VT_BYREF ) )
1691 * The VT_ARRAY flag is a special case of a safe array.
1693 if ( (pvarg->vt & VT_ARRAY) != 0)
1695 SafeArrayDestroy(pvarg->u.parray);
1699 switch( pvarg->vt & VT_TYPEMASK )
1702 SysFreeString( pvarg->u.bstrVal );
1704 case( VT_DISPATCH ):
1705 if(pvarg->u.pdispVal!=NULL)
1706 ICOM_CALL(Release,pvarg->u.pdispVal);
1709 VariantClear(pvarg->u.pvarVal);
1712 if(pvarg->u.punkVal!=NULL)
1713 ICOM_CALL(Release,pvarg->u.punkVal);
1715 case( VT_SAFEARRAY ):
1716 SafeArrayDestroy(pvarg->u.parray);
1725 * Empty all the fields and mark the type as empty.
1727 memset(pvarg, 0, sizeof (VARIANTARG));
1728 pvarg->vt = VT_EMPTY;
1734 /******************************************************************************
1735 * VariantCopy32 [OLEAUT32.10]
1737 * Frees up the designation variant and makes a copy of the source.
1739 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1743 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1745 res = ValidateVariantType( pvargSrc->vt );
1747 /* If the pointer are to the same variant we don't need
1750 if( pvargDest != pvargSrc && res == S_OK )
1752 res = VariantClear( pvargDest );
1756 if( pvargSrc->vt & VT_BYREF )
1758 /* In the case of byreference we only need
1759 * to copy the pointer.
1761 pvargDest->u = pvargSrc->u;
1762 pvargDest->vt = pvargSrc->vt;
1767 * The VT_ARRAY flag is another way to designate a safe array.
1769 if (pvargSrc->vt & VT_ARRAY)
1771 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1775 /* In the case of by value we need to
1776 * copy the actuall value. In the case of
1777 * VT_BSTR a copy of the string is made,
1778 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1779 * called to increment the object's reference count.
1781 switch( pvargSrc->vt & VT_TYPEMASK )
1784 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1786 case( VT_DISPATCH ):
1787 pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1788 if (pvargDest->u.pdispVal!=NULL)
1789 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1792 VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1795 pvargDest->u.punkVal = pvargSrc->u.punkVal;
1796 if (pvargDest->u.pdispVal!=NULL)
1797 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1799 case( VT_SAFEARRAY ):
1800 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1803 pvargDest->u = pvargSrc->u;
1808 pvargDest->vt = pvargSrc->vt;
1817 /******************************************************************************
1818 * VariantCopyInd32 [OLEAUT32.11]
1820 * Frees up the destination variant and makes a copy of the source. If
1821 * the source is of type VT_BYREF it performs the necessary indirections.
1823 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1827 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1829 res = ValidateVariantType( pvargSrc->vt );
1834 if( pvargSrc->vt & VT_BYREF )
1837 VariantInit( &varg );
1839 /* handle the in place copy.
1841 if( pvargDest == pvargSrc )
1843 /* we will use a copy of the source instead.
1845 res = VariantCopy( &varg, pvargSrc );
1851 res = VariantClear( pvargDest );
1856 * The VT_ARRAY flag is another way to designate a safearray variant.
1858 if ( pvargSrc->vt & VT_ARRAY)
1860 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1864 /* In the case of by reference we need
1865 * to copy the date pointed to by the variant.
1868 /* Get the variant type.
1870 switch( pvargSrc->vt & VT_TYPEMASK )
1873 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1875 case( VT_DISPATCH ):
1879 /* Prevent from cycling. According to tests on
1880 * VariantCopyInd in Windows and the documentation
1881 * this API dereferences the inner Variants to only one depth.
1882 * If the inner Variant itself contains an
1883 * other inner variant the E_INVALIDARG error is
1886 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1888 /* If we get here we are attempting to deference
1889 * an inner variant that that is itself contained
1890 * in an inner variant so report E_INVALIDARG error.
1896 /* Set the processing inner variant flag.
1897 * We will set this flag in the inner variant
1898 * that will be passed to the VariantCopyInd function.
1900 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1902 /* Dereference the inner variant.
1904 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1910 case( VT_SAFEARRAY ):
1911 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1914 /* This is a by reference Variant which means that the union
1915 * part of the Variant contains a pointer to some data of
1916 * type "pvargSrc->vt & VT_TYPEMASK".
1917 * We will deference this data in a generic fashion using
1918 * the void pointer "Variant.u.byref".
1919 * We will copy this data into the union of the destination
1922 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1927 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1931 /* this should not fail.
1933 VariantClear( &varg );
1937 res = VariantCopy( pvargDest, pvargSrc );
1943 /******************************************************************************
1944 * VariantChangeType32 [OLEAUT32.12]
1946 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1947 USHORT wFlags, VARTYPE vt)
1949 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1952 /******************************************************************************
1953 * VariantChangeTypeEx32 [OLEAUT32.147]
1955 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1956 LCID lcid, USHORT wFlags, VARTYPE vt)
1960 VariantInit( &varg );
1962 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1964 /* validate our source argument.
1966 res = ValidateVariantType( pvargSrc->vt );
1968 /* validate the vartype.
1972 res = ValidateVt( vt );
1975 /* if we are doing an in-place conversion make a copy of the source.
1977 if( res == S_OK && pvargDest == pvargSrc )
1979 res = VariantCopy( &varg, pvargSrc );
1985 /* free up the destination variant.
1987 res = VariantClear( pvargDest );
1992 if( pvargSrc->vt & VT_BYREF )
1994 /* Convert the source variant to a "byvalue" variant.
1997 VariantInit( &Variant );
1998 res = VariantCopyInd( &Variant, pvargSrc );
2001 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2002 /* this should not fail.
2004 VariantClear( &Variant );
2010 /* Use the current "byvalue" source variant.
2012 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2015 /* this should not fail.
2017 VariantClear( &varg );
2019 /* set the type of the destination
2030 /******************************************************************************
2031 * VarUI1FromI232 [OLEAUT32.130]
2033 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2035 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2037 /* Check range of value.
2039 if( sIn < UI1_MIN || sIn > UI1_MAX )
2041 return DISP_E_OVERFLOW;
2044 *pbOut = (BYTE) sIn;
2049 /******************************************************************************
2050 * VarUI1FromI432 [OLEAUT32.131]
2052 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2054 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2056 /* Check range of value.
2058 if( lIn < UI1_MIN || lIn > UI1_MAX )
2060 return DISP_E_OVERFLOW;
2063 *pbOut = (BYTE) lIn;
2069 /******************************************************************************
2070 * VarUI1FromR432 [OLEAUT32.132]
2072 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2074 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2076 /* Check range of value.
2078 fltIn = round( fltIn );
2079 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2081 return DISP_E_OVERFLOW;
2084 *pbOut = (BYTE) fltIn;
2089 /******************************************************************************
2090 * VarUI1FromR832 [OLEAUT32.133]
2092 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2094 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2096 /* Check range of value.
2098 dblIn = round( dblIn );
2099 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2101 return DISP_E_OVERFLOW;
2104 *pbOut = (BYTE) dblIn;
2109 /******************************************************************************
2110 * VarUI1FromDate32 [OLEAUT32.135]
2112 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2114 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2116 /* Check range of value.
2118 dateIn = round( dateIn );
2119 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2121 return DISP_E_OVERFLOW;
2124 *pbOut = (BYTE) dateIn;
2129 /******************************************************************************
2130 * VarUI1FromBool32 [OLEAUT32.138]
2132 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2134 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2136 *pbOut = (BYTE) boolIn;
2141 /******************************************************************************
2142 * VarUI1FromI132 [OLEAUT32.237]
2144 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2146 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2153 /******************************************************************************
2154 * VarUI1FromUI232 [OLEAUT32.238]
2156 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2158 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2160 /* Check range of value.
2162 if( uiIn > UI1_MAX )
2164 return DISP_E_OVERFLOW;
2167 *pbOut = (BYTE) uiIn;
2172 /******************************************************************************
2173 * VarUI1FromUI432 [OLEAUT32.239]
2175 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2177 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2179 /* Check range of value.
2181 if( ulIn > UI1_MAX )
2183 return DISP_E_OVERFLOW;
2186 *pbOut = (BYTE) ulIn;
2192 /******************************************************************************
2193 * VarUI1FromStr32 [OLEAUT32.54]
2195 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2197 double dValue = 0.0;
2198 LPSTR pNewString = NULL;
2200 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2202 /* Check if we have a valid argument
2204 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2205 RemoveCharacterFromString( pNewString, "," );
2206 if( IsValidRealString( pNewString ) == FALSE )
2208 return DISP_E_TYPEMISMATCH;
2211 /* Convert the valid string to a floating point number.
2213 dValue = atof( pNewString );
2215 /* We don't need the string anymore so free it.
2217 HeapFree( GetProcessHeap(), 0 , pNewString );
2219 /* Check range of value.
2221 dValue = round( dValue );
2222 if( dValue < UI1_MIN || dValue > UI1_MAX )
2224 return DISP_E_OVERFLOW;
2227 *pbOut = (BYTE) dValue;
2232 /**********************************************************************
2233 * VarUI1FromCy32 [OLEAUT32.134]
2234 * Convert currency to unsigned char
2236 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2237 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2239 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2245 /******************************************************************************
2246 * VarI2FromUI132 [OLEAUT32.48]
2248 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2250 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2252 *psOut = (short) bIn;
2257 /******************************************************************************
2258 * VarI2FromI432 [OLEAUT32.49]
2260 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2262 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2264 /* Check range of value.
2266 if( lIn < I2_MIN || lIn > I2_MAX )
2268 return DISP_E_OVERFLOW;
2271 *psOut = (short) lIn;
2276 /******************************************************************************
2277 * VarI2FromR432 [OLEAUT32.50]
2279 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2281 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2283 /* Check range of value.
2285 fltIn = round( fltIn );
2286 if( fltIn < I2_MIN || fltIn > I2_MAX )
2288 return DISP_E_OVERFLOW;
2291 *psOut = (short) fltIn;
2296 /******************************************************************************
2297 * VarI2FromR832 [OLEAUT32.51]
2299 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2301 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2303 /* Check range of value.
2305 dblIn = round( dblIn );
2306 if( dblIn < I2_MIN || dblIn > I2_MAX )
2308 return DISP_E_OVERFLOW;
2311 *psOut = (short) dblIn;
2316 /******************************************************************************
2317 * VarI2FromDate32 [OLEAUT32.53]
2319 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2321 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2323 /* Check range of value.
2325 dateIn = round( dateIn );
2326 if( dateIn < I2_MIN || dateIn > I2_MAX )
2328 return DISP_E_OVERFLOW;
2331 *psOut = (short) dateIn;
2336 /******************************************************************************
2337 * VarI2FromBool32 [OLEAUT32.56]
2339 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2341 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2343 *psOut = (short) boolIn;
2348 /******************************************************************************
2349 * VarI2FromI132 [OLEAUT32.48]
2351 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2353 TRACE("( %c, %p ), stub\n", cIn, psOut );
2355 *psOut = (short) cIn;
2360 /******************************************************************************
2361 * VarI2FromUI232 [OLEAUT32.206]
2363 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2365 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2367 /* Check range of value.
2371 return DISP_E_OVERFLOW;
2374 *psOut = (short) uiIn;
2379 /******************************************************************************
2380 * VarI2FromUI432 [OLEAUT32.49]
2382 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2384 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2386 /* Check range of value.
2388 if( ulIn < I2_MIN || ulIn > I2_MAX )
2390 return DISP_E_OVERFLOW;
2393 *psOut = (short) ulIn;
2398 /******************************************************************************
2399 * VarI2FromStr32 [OLEAUT32.54]
2401 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2403 double dValue = 0.0;
2404 LPSTR pNewString = NULL;
2406 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2408 /* Check if we have a valid argument
2410 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2411 RemoveCharacterFromString( pNewString, "," );
2412 if( IsValidRealString( pNewString ) == FALSE )
2414 return DISP_E_TYPEMISMATCH;
2417 /* Convert the valid string to a floating point number.
2419 dValue = atof( pNewString );
2421 /* We don't need the string anymore so free it.
2423 HeapFree( GetProcessHeap(), 0, pNewString );
2425 /* Check range of value.
2427 dValue = round( dValue );
2428 if( dValue < I2_MIN || dValue > I2_MAX )
2430 return DISP_E_OVERFLOW;
2433 *psOut = (short) dValue;
2438 /**********************************************************************
2439 * VarI2FromCy32 [OLEAUT32.52]
2440 * Convert currency to signed short
2442 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2443 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2445 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2451 /******************************************************************************
2452 * VarI4FromUI132 [OLEAUT32.58]
2454 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2456 TRACE("( %X, %p ), stub\n", bIn, plOut );
2458 *plOut = (LONG) bIn;
2464 /******************************************************************************
2465 * VarI4FromR432 [OLEAUT32.60]
2467 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2469 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2471 /* Check range of value.
2473 fltIn = round( fltIn );
2474 if( fltIn < I4_MIN || fltIn > I4_MAX )
2476 return DISP_E_OVERFLOW;
2479 *plOut = (LONG) fltIn;
2484 /******************************************************************************
2485 * VarI4FromR832 [OLEAUT32.61]
2487 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2489 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2491 /* Check range of value.
2493 dblIn = round( dblIn );
2494 if( dblIn < I4_MIN || dblIn > I4_MAX )
2496 return DISP_E_OVERFLOW;
2499 *plOut = (LONG) dblIn;
2504 /******************************************************************************
2505 * VarI4FromDate32 [OLEAUT32.63]
2507 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2509 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2511 /* Check range of value.
2513 dateIn = round( dateIn );
2514 if( dateIn < I4_MIN || dateIn > I4_MAX )
2516 return DISP_E_OVERFLOW;
2519 *plOut = (LONG) dateIn;
2524 /******************************************************************************
2525 * VarI4FromBool32 [OLEAUT32.66]
2527 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2529 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2531 *plOut = (LONG) boolIn;
2536 /******************************************************************************
2537 * VarI4FromI132 [OLEAUT32.209]
2539 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2541 TRACE("( %c, %p ), stub\n", cIn, plOut );
2543 *plOut = (LONG) cIn;
2548 /******************************************************************************
2549 * VarI4FromUI232 [OLEAUT32.210]
2551 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2553 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2555 *plOut = (LONG) uiIn;
2560 /******************************************************************************
2561 * VarI4FromUI432 [OLEAUT32.211]
2563 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2565 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2567 /* Check range of value.
2569 if( ulIn < I4_MIN || ulIn > I4_MAX )
2571 return DISP_E_OVERFLOW;
2574 *plOut = (LONG) ulIn;
2579 /******************************************************************************
2580 * VarI4FromI232 [OLEAUT32.59]
2582 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2584 TRACE("( %d, %p ), stub\n", sIn, plOut );
2586 *plOut = (LONG) sIn;
2591 /******************************************************************************
2592 * VarI4FromStr32 [OLEAUT32.64]
2594 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2596 double dValue = 0.0;
2597 LPSTR pNewString = NULL;
2599 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2601 /* Check if we have a valid argument
2603 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2604 RemoveCharacterFromString( pNewString, "," );
2605 if( IsValidRealString( pNewString ) == FALSE )
2607 return DISP_E_TYPEMISMATCH;
2610 /* Convert the valid string to a floating point number.
2612 dValue = atof( pNewString );
2614 /* We don't need the string anymore so free it.
2616 HeapFree( GetProcessHeap(), 0, pNewString );
2618 /* Check range of value.
2620 dValue = round( dValue );
2621 if( dValue < I4_MIN || dValue > I4_MAX )
2623 return DISP_E_OVERFLOW;
2626 *plOut = (LONG) dValue;
2631 /**********************************************************************
2632 * VarI4FromCy32 [OLEAUT32.62]
2633 * Convert currency to signed long
2635 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2636 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2638 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2644 /******************************************************************************
2645 * VarR4FromUI132 [OLEAUT32.68]
2647 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2649 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2651 *pfltOut = (FLOAT) bIn;
2656 /******************************************************************************
2657 * VarR4FromI232 [OLEAUT32.69]
2659 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2661 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2663 *pfltOut = (FLOAT) sIn;
2668 /******************************************************************************
2669 * VarR4FromI432 [OLEAUT32.70]
2671 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2673 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2675 *pfltOut = (FLOAT) lIn;
2680 /******************************************************************************
2681 * VarR4FromR832 [OLEAUT32.71]
2683 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2685 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2687 /* Check range of value.
2689 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2691 return DISP_E_OVERFLOW;
2694 *pfltOut = (FLOAT) dblIn;
2699 /******************************************************************************
2700 * VarR4FromDate32 [OLEAUT32.73]
2702 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2704 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2706 /* Check range of value.
2708 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2710 return DISP_E_OVERFLOW;
2713 *pfltOut = (FLOAT) dateIn;
2718 /******************************************************************************
2719 * VarR4FromBool32 [OLEAUT32.76]
2721 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2723 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2725 *pfltOut = (FLOAT) boolIn;
2730 /******************************************************************************
2731 * VarR4FromI132 [OLEAUT32.213]
2733 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2735 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2737 *pfltOut = (FLOAT) cIn;
2742 /******************************************************************************
2743 * VarR4FromUI232 [OLEAUT32.214]
2745 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2747 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2749 *pfltOut = (FLOAT) uiIn;
2754 /******************************************************************************
2755 * VarR4FromUI432 [OLEAUT32.215]
2757 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2759 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2761 *pfltOut = (FLOAT) ulIn;
2766 /******************************************************************************
2767 * VarR4FromStr32 [OLEAUT32.74]
2769 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2771 double dValue = 0.0;
2772 LPSTR pNewString = NULL;
2774 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2776 /* Check if we have a valid argument
2778 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2779 RemoveCharacterFromString( pNewString, "," );
2780 if( IsValidRealString( pNewString ) == FALSE )
2782 return DISP_E_TYPEMISMATCH;
2785 /* Convert the valid string to a floating point number.
2787 dValue = atof( pNewString );
2789 /* We don't need the string anymore so free it.
2791 HeapFree( GetProcessHeap(), 0, pNewString );
2793 /* Check range of value.
2795 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2797 return DISP_E_OVERFLOW;
2800 *pfltOut = (FLOAT) dValue;
2805 /**********************************************************************
2806 * VarR4FromCy32 [OLEAUT32.72]
2807 * Convert currency to float
2809 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2810 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2815 /******************************************************************************
2816 * VarR8FromUI132 [OLEAUT32.68]
2818 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2820 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2822 *pdblOut = (double) bIn;
2827 /******************************************************************************
2828 * VarR8FromI232 [OLEAUT32.69]
2830 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2832 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2834 *pdblOut = (double) sIn;
2839 /******************************************************************************
2840 * VarR8FromI432 [OLEAUT32.70]
2842 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2844 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2846 *pdblOut = (double) lIn;
2851 /******************************************************************************
2852 * VarR8FromR432 [OLEAUT32.81]
2854 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2856 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2858 *pdblOut = (double) fltIn;
2863 /******************************************************************************
2864 * VarR8FromDate32 [OLEAUT32.83]
2866 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2868 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2870 *pdblOut = (double) dateIn;
2875 /******************************************************************************
2876 * VarR8FromBool32 [OLEAUT32.86]
2878 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2880 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2882 *pdblOut = (double) boolIn;
2887 /******************************************************************************
2888 * VarR8FromI132 [OLEAUT32.217]
2890 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2892 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2894 *pdblOut = (double) cIn;
2899 /******************************************************************************
2900 * VarR8FromUI232 [OLEAUT32.218]
2902 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2904 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2906 *pdblOut = (double) uiIn;
2911 /******************************************************************************
2912 * VarR8FromUI432 [OLEAUT32.219]
2914 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2916 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2918 *pdblOut = (double) ulIn;
2923 /******************************************************************************
2924 * VarR8FromStr32 [OLEAUT32.84]
2926 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2928 double dValue = 0.0;
2929 LPSTR pNewString = NULL;
2931 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2933 /* Check if we have a valid argument
2935 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2936 RemoveCharacterFromString( pNewString, "," );
2937 if( IsValidRealString( pNewString ) == FALSE )
2939 return DISP_E_TYPEMISMATCH;
2942 /* Convert the valid string to a floating point number.
2944 dValue = atof( pNewString );
2946 /* We don't need the string anymore so free it.
2948 HeapFree( GetProcessHeap(), 0, pNewString );
2955 /**********************************************************************
2956 * VarR8FromCy32 [OLEAUT32.82]
2957 * Convert currency to double
2959 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2960 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2965 /******************************************************************************
2966 * VarDateFromUI132 [OLEAUT32.]
2968 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2970 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2972 *pdateOut = (DATE) bIn;
2977 /******************************************************************************
2978 * VarDateFromI232 [OLEAUT32.222]
2980 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2982 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2984 *pdateOut = (DATE) sIn;
2989 /******************************************************************************
2990 * VarDateFromI432 [OLEAUT32.90]
2992 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
2994 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
2996 if( lIn < DATE_MIN || lIn > DATE_MAX )
2998 return DISP_E_OVERFLOW;
3001 *pdateOut = (DATE) lIn;
3006 /******************************************************************************
3007 * VarDateFromR432 [OLEAUT32.91]
3009 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3011 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3013 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3015 return DISP_E_OVERFLOW;
3018 *pdateOut = (DATE) fltIn;
3023 /******************************************************************************
3024 * VarDateFromR832 [OLEAUT32.92]
3026 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3028 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3030 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3032 return DISP_E_OVERFLOW;
3035 *pdateOut = (DATE) dblIn;
3040 /******************************************************************************
3041 * VarDateFromStr32 [OLEAUT32.94]
3042 * The string representing the date is composed of two parts, a date and time.
3044 * The format of the time is has follows:
3045 * hh[:mm][:ss][AM|PM]
3046 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3047 * of space and/or tab characters, which are ignored.
3049 * The formats for the date part are has follows:
3053 * January dd[,] [yy]yy
3056 * Whitespace can be inserted anywhere between these tokens.
3058 * The formats for the date and time string are has follows.
3059 * date[whitespace][time]
3060 * [time][whitespace]date
3062 * These are the only characters allowed in a string representing a date and time:
3063 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3065 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3068 struct tm TM = { 0,0,0,0,0,0,0,0,0 };
3070 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3072 if( DateTimeStringToTm( strIn, lcid, &TM ) )
3074 if( TmToDATE( &TM, pdateOut ) == FALSE )
3081 ret = DISP_E_TYPEMISMATCH;
3088 /******************************************************************************
3089 * VarDateFromI132 [OLEAUT32.221]
3091 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3093 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3095 *pdateOut = (DATE) cIn;
3100 /******************************************************************************
3101 * VarDateFromUI232 [OLEAUT32.222]
3103 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3105 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3107 if( uiIn > DATE_MAX )
3109 return DISP_E_OVERFLOW;
3112 *pdateOut = (DATE) uiIn;
3117 /******************************************************************************
3118 * VarDateFromUI432 [OLEAUT32.223]
3120 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3122 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3124 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3126 return DISP_E_OVERFLOW;
3129 *pdateOut = (DATE) ulIn;
3134 /******************************************************************************
3135 * VarDateFromBool32 [OLEAUT32.96]
3137 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3139 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3141 *pdateOut = (DATE) boolIn;
3146 /**********************************************************************
3147 * VarDateFromCy32 [OLEAUT32.93]
3148 * Convert currency to date
3150 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3151 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3153 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3157 /******************************************************************************
3158 * VarBstrFromUI132 [OLEAUT32.108]
3160 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3162 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3163 sprintf( pBuffer, "%d", bVal );
3165 *pbstrOut = StringDupAtoBstr( pBuffer );
3170 /******************************************************************************
3171 * VarBstrFromI232 [OLEAUT32.109]
3173 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3175 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3176 sprintf( pBuffer, "%d", iVal );
3177 *pbstrOut = StringDupAtoBstr( pBuffer );
3182 /******************************************************************************
3183 * VarBstrFromI432 [OLEAUT32.110]
3185 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3187 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3189 sprintf( pBuffer, "%ld", lIn );
3190 *pbstrOut = StringDupAtoBstr( pBuffer );
3195 /******************************************************************************
3196 * VarBstrFromR432 [OLEAUT32.111]
3198 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3200 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3202 sprintf( pBuffer, "%.7g", fltIn );
3203 *pbstrOut = StringDupAtoBstr( pBuffer );
3208 /******************************************************************************
3209 * VarBstrFromR832 [OLEAUT32.112]
3211 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3213 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3215 sprintf( pBuffer, "%.15g", dblIn );
3216 *pbstrOut = StringDupAtoBstr( pBuffer );
3221 /******************************************************************************
3222 * VarBstrFromCy [OLEAUT32.113]
3224 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3230 /******************************************************************************
3231 * VarBstrFromDate32 [OLEAUT32.114]
3233 * The date is implemented using an 8 byte floating-point number.
3234 * Days are represented by whole numbers increments starting with 0.00 has
3235 * being December 30 1899, midnight.
3236 * The hours are expressed as the fractional part of the number.
3237 * December 30 1899 at midnight = 0.00
3238 * January 1 1900 at midnight = 2.00
3239 * January 4 1900 at 6 AM = 5.25
3240 * January 4 1900 at noon = 5.50
3241 * December 29 1899 at midnight = -1.00
3242 * December 18 1899 at midnight = -12.00
3243 * December 18 1899 at 6AM = -12.25
3244 * December 18 1899 at 6PM = -12.75
3245 * December 19 1899 at midnight = -11.00
3246 * The tm structure is as follows:
3248 * int tm_sec; seconds after the minute - [0,59]
3249 * int tm_min; minutes after the hour - [0,59]
3250 * int tm_hour; hours since midnight - [0,23]
3251 * int tm_mday; day of the month - [1,31]
3252 * int tm_mon; months since January - [0,11]
3253 * int tm_year; years
3254 * int tm_wday; days since Sunday - [0,6]
3255 * int tm_yday; days since January 1 - [0,365]
3256 * int tm_isdst; daylight savings time flag
3259 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3261 struct tm TM = {0,0,0,0,0,0,0,0,0};
3263 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3265 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3267 return E_INVALIDARG;
3270 if( dwFlags & VAR_DATEVALUEONLY )
3271 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3272 else if( dwFlags & VAR_TIMEVALUEONLY )
3273 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3275 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3277 *pbstrOut = StringDupAtoBstr( pBuffer );
3282 /******************************************************************************
3283 * VarBstrFromBool32 [OLEAUT32.116]
3285 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3287 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3289 if( boolIn == VARIANT_FALSE )
3291 sprintf( pBuffer, "False" );
3295 sprintf( pBuffer, "True" );
3298 *pbstrOut = StringDupAtoBstr( pBuffer );
3303 /******************************************************************************
3304 * VarBstrFromI132 [OLEAUT32.229]
3306 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3308 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3309 sprintf( pBuffer, "%d", cIn );
3310 *pbstrOut = StringDupAtoBstr( pBuffer );
3315 /******************************************************************************
3316 * VarBstrFromUI232 [OLEAUT32.230]
3318 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3320 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3321 sprintf( pBuffer, "%d", uiIn );
3322 *pbstrOut = StringDupAtoBstr( pBuffer );
3327 /******************************************************************************
3328 * VarBstrFromUI432 [OLEAUT32.231]
3330 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3332 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3333 sprintf( pBuffer, "%ld", ulIn );
3334 *pbstrOut = StringDupAtoBstr( pBuffer );
3339 /******************************************************************************
3340 * VarBoolFromUI132 [OLEAUT32.118]
3342 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3344 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3348 *pboolOut = VARIANT_FALSE;
3352 *pboolOut = VARIANT_TRUE;
3358 /******************************************************************************
3359 * VarBoolFromI232 [OLEAUT32.119]
3361 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3363 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3367 *pboolOut = VARIANT_FALSE;
3371 *pboolOut = VARIANT_TRUE;
3377 /******************************************************************************
3378 * VarBoolFromI432 [OLEAUT32.120]
3380 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3382 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3386 *pboolOut = VARIANT_FALSE;
3390 *pboolOut = VARIANT_TRUE;
3396 /******************************************************************************
3397 * VarBoolFromR432 [OLEAUT32.121]
3399 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3401 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3405 *pboolOut = VARIANT_FALSE;
3409 *pboolOut = VARIANT_TRUE;
3415 /******************************************************************************
3416 * VarBoolFromR832 [OLEAUT32.122]
3418 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3420 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3424 *pboolOut = VARIANT_FALSE;
3428 *pboolOut = VARIANT_TRUE;
3434 /******************************************************************************
3435 * VarBoolFromDate32 [OLEAUT32.123]
3437 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3439 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3443 *pboolOut = VARIANT_FALSE;
3447 *pboolOut = VARIANT_TRUE;
3453 /******************************************************************************
3454 * VarBoolFromStr32 [OLEAUT32.125]
3456 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3459 char* pNewString = NULL;
3461 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3463 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3465 if( pNewString == NULL || strlen( pNewString ) == 0 )
3467 ret = DISP_E_TYPEMISMATCH;
3472 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3474 *pboolOut = VARIANT_TRUE;
3476 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3478 *pboolOut = VARIANT_FALSE;
3482 /* Try converting the string to a floating point number.
3484 double dValue = 0.0;
3485 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3488 ret = DISP_E_TYPEMISMATCH;
3490 else if( dValue == 0.0 )
3492 *pboolOut = VARIANT_FALSE;
3496 *pboolOut = VARIANT_TRUE;
3501 HeapFree( GetProcessHeap(), 0, pNewString );
3506 /******************************************************************************
3507 * VarBoolFromI132 [OLEAUT32.233]
3509 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3511 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3515 *pboolOut = VARIANT_FALSE;
3519 *pboolOut = VARIANT_TRUE;
3525 /******************************************************************************
3526 * VarBoolFromUI232 [OLEAUT32.234]
3528 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3530 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3534 *pboolOut = VARIANT_FALSE;
3538 *pboolOut = VARIANT_TRUE;
3544 /******************************************************************************
3545 * VarBoolFromUI432 [OLEAUT32.235]
3547 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3549 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3553 *pboolOut = VARIANT_FALSE;
3557 *pboolOut = VARIANT_TRUE;
3563 /**********************************************************************
3564 * VarBoolFromCy32 [OLEAUT32.124]
3565 * Convert currency to boolean
3567 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3568 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3574 /******************************************************************************
3575 * VarI1FromUI132 [OLEAUT32.244]
3577 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3579 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3581 /* Check range of value.
3583 if( bIn > CHAR_MAX )
3585 return DISP_E_OVERFLOW;
3588 *pcOut = (CHAR) bIn;
3593 /******************************************************************************
3594 * VarI1FromI232 [OLEAUT32.245]
3596 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3598 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3600 if( uiIn > CHAR_MAX )
3602 return DISP_E_OVERFLOW;
3605 *pcOut = (CHAR) uiIn;
3610 /******************************************************************************
3611 * VarI1FromI432 [OLEAUT32.246]
3613 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3615 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3617 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3619 return DISP_E_OVERFLOW;
3622 *pcOut = (CHAR) lIn;
3627 /******************************************************************************
3628 * VarI1FromR432 [OLEAUT32.247]
3630 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3632 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3634 fltIn = round( fltIn );
3635 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3637 return DISP_E_OVERFLOW;
3640 *pcOut = (CHAR) fltIn;
3645 /******************************************************************************
3646 * VarI1FromR832 [OLEAUT32.248]
3648 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3650 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3652 dblIn = round( dblIn );
3653 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3655 return DISP_E_OVERFLOW;
3658 *pcOut = (CHAR) dblIn;
3663 /******************************************************************************
3664 * VarI1FromDate32 [OLEAUT32.249]
3666 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3668 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3670 dateIn = round( dateIn );
3671 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3673 return DISP_E_OVERFLOW;
3676 *pcOut = (CHAR) dateIn;
3681 /******************************************************************************
3682 * VarI1FromStr32 [OLEAUT32.251]
3684 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3686 double dValue = 0.0;
3687 LPSTR pNewString = NULL;
3689 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3691 /* Check if we have a valid argument
3693 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3694 RemoveCharacterFromString( pNewString, "," );
3695 if( IsValidRealString( pNewString ) == FALSE )
3697 return DISP_E_TYPEMISMATCH;
3700 /* Convert the valid string to a floating point number.
3702 dValue = atof( pNewString );
3704 /* We don't need the string anymore so free it.
3706 HeapFree( GetProcessHeap(), 0, pNewString );
3708 /* Check range of value.
3710 dValue = round( dValue );
3711 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3713 return DISP_E_OVERFLOW;
3716 *pcOut = (CHAR) dValue;
3721 /******************************************************************************
3722 * VarI1FromBool32 [OLEAUT32.253]
3724 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3726 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3728 *pcOut = (CHAR) boolIn;
3733 /******************************************************************************
3734 * VarI1FromUI232 [OLEAUT32.254]
3736 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3738 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3740 if( uiIn > CHAR_MAX )
3742 return DISP_E_OVERFLOW;
3745 *pcOut = (CHAR) uiIn;
3750 /******************************************************************************
3751 * VarI1FromUI432 [OLEAUT32.255]
3753 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3755 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3757 if( ulIn > CHAR_MAX )
3759 return DISP_E_OVERFLOW;
3762 *pcOut = (CHAR) ulIn;
3767 /**********************************************************************
3768 * VarI1FromCy32 [OLEAUT32.250]
3769 * Convert currency to signed char
3771 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3772 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3774 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3780 /******************************************************************************
3781 * VarUI2FromUI132 [OLEAUT32.257]
3783 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3785 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3787 *puiOut = (USHORT) bIn;
3792 /******************************************************************************
3793 * VarUI2FromI232 [OLEAUT32.258]
3795 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3797 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3799 if( uiIn < UI2_MIN )
3801 return DISP_E_OVERFLOW;
3804 *puiOut = (USHORT) uiIn;
3809 /******************************************************************************
3810 * VarUI2FromI432 [OLEAUT32.259]
3812 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3814 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3816 if( lIn < UI2_MIN || lIn > UI2_MAX )
3818 return DISP_E_OVERFLOW;
3821 *puiOut = (USHORT) lIn;
3826 /******************************************************************************
3827 * VarUI2FromR432 [OLEAUT32.260]
3829 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3831 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3833 fltIn = round( fltIn );
3834 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3836 return DISP_E_OVERFLOW;
3839 *puiOut = (USHORT) fltIn;
3844 /******************************************************************************
3845 * VarUI2FromR832 [OLEAUT32.261]
3847 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3849 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3851 dblIn = round( dblIn );
3852 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3854 return DISP_E_OVERFLOW;
3857 *puiOut = (USHORT) dblIn;
3862 /******************************************************************************
3863 * VarUI2FromDate32 [OLEAUT32.262]
3865 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3867 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3869 dateIn = round( dateIn );
3870 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3872 return DISP_E_OVERFLOW;
3875 *puiOut = (USHORT) dateIn;
3880 /******************************************************************************
3881 * VarUI2FromStr32 [OLEAUT32.264]
3883 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3885 double dValue = 0.0;
3886 LPSTR pNewString = NULL;
3888 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3890 /* Check if we have a valid argument
3892 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3893 RemoveCharacterFromString( pNewString, "," );
3894 if( IsValidRealString( pNewString ) == FALSE )
3896 return DISP_E_TYPEMISMATCH;
3899 /* Convert the valid string to a floating point number.
3901 dValue = atof( pNewString );
3903 /* We don't need the string anymore so free it.
3905 HeapFree( GetProcessHeap(), 0, pNewString );
3907 /* Check range of value.
3909 dValue = round( dValue );
3910 if( dValue < UI2_MIN || dValue > UI2_MAX )
3912 return DISP_E_OVERFLOW;
3915 *puiOut = (USHORT) dValue;
3920 /******************************************************************************
3921 * VarUI2FromBool32 [OLEAUT32.266]
3923 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3925 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3927 *puiOut = (USHORT) boolIn;
3932 /******************************************************************************
3933 * VarUI2FromI132 [OLEAUT32.267]
3935 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3937 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3939 *puiOut = (USHORT) cIn;
3944 /******************************************************************************
3945 * VarUI2FromUI432 [OLEAUT32.268]
3947 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3949 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3951 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3953 return DISP_E_OVERFLOW;
3956 *puiOut = (USHORT) ulIn;
3961 /******************************************************************************
3962 * VarUI4FromStr32 [OLEAUT32.277]
3964 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3966 double dValue = 0.0;
3967 LPSTR pNewString = NULL;
3969 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3971 /* Check if we have a valid argument
3973 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3974 RemoveCharacterFromString( pNewString, "," );
3975 if( IsValidRealString( pNewString ) == FALSE )
3977 return DISP_E_TYPEMISMATCH;
3980 /* Convert the valid string to a floating point number.
3982 dValue = atof( pNewString );
3984 /* We don't need the string anymore so free it.
3986 HeapFree( GetProcessHeap(), 0, pNewString );
3988 /* Check range of value.
3990 dValue = round( dValue );
3991 if( dValue < UI4_MIN || dValue > UI4_MAX )
3993 return DISP_E_OVERFLOW;
3996 *pulOut = (ULONG) dValue;
4001 /**********************************************************************
4002 * VarUI2FromCy32 [OLEAUT32.263]
4003 * Convert currency to unsigned short
4005 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4006 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4008 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4010 *pusOut = (USHORT)t;
4015 /******************************************************************************
4016 * VarUI4FromUI132 [OLEAUT32.270]
4018 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4020 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4022 *pulOut = (USHORT) bIn;
4027 /******************************************************************************
4028 * VarUI4FromI232 [OLEAUT32.271]
4030 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4032 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4034 if( uiIn < UI4_MIN )
4036 return DISP_E_OVERFLOW;
4039 *pulOut = (ULONG) uiIn;
4044 /******************************************************************************
4045 * VarUI4FromI432 [OLEAUT32.272]
4047 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4049 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4053 return DISP_E_OVERFLOW;
4056 *pulOut = (ULONG) lIn;
4061 /******************************************************************************
4062 * VarUI4FromR432 [OLEAUT32.273]
4064 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4066 fltIn = round( fltIn );
4067 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4069 return DISP_E_OVERFLOW;
4072 *pulOut = (ULONG) fltIn;
4077 /******************************************************************************
4078 * VarUI4FromR832 [OLEAUT32.274]
4080 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4082 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4084 dblIn = round( dblIn );
4085 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4087 return DISP_E_OVERFLOW;
4090 *pulOut = (ULONG) dblIn;
4095 /******************************************************************************
4096 * VarUI4FromDate32 [OLEAUT32.275]
4098 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4100 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4102 dateIn = round( dateIn );
4103 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4105 return DISP_E_OVERFLOW;
4108 *pulOut = (ULONG) dateIn;
4113 /******************************************************************************
4114 * VarUI4FromBool32 [OLEAUT32.279]
4116 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4118 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4120 *pulOut = (ULONG) boolIn;
4125 /******************************************************************************
4126 * VarUI4FromI132 [OLEAUT32.280]
4128 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4130 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4132 *pulOut = (ULONG) cIn;
4137 /******************************************************************************
4138 * VarUI4FromUI232 [OLEAUT32.281]
4140 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4142 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4144 *pulOut = (ULONG) uiIn;
4149 /**********************************************************************
4150 * VarUI4FromCy32 [OLEAUT32.276]
4151 * Convert currency to unsigned long
4153 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4154 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4156 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4163 /**********************************************************************
4164 * VarCyFromUI132 [OLEAUT32.98]
4165 * Convert unsigned char to currency
4167 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4169 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4174 /**********************************************************************
4175 * VarCyFromI232 [OLEAUT32.99]
4176 * Convert signed short to currency
4178 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4179 if (sIn < 0) pcyOut->s.Hi = -1;
4180 else pcyOut->s.Hi = 0;
4181 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4186 /**********************************************************************
4187 * VarCyFromI432 [OLEAUT32.100]
4188 * Convert signed long to currency
4190 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4191 double t = (double)lIn * (double)10000;
4192 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4193 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4194 if (lIn < 0) pcyOut->s.Hi--;
4199 /**********************************************************************
4200 * VarCyFromR432 [OLEAUT32.101]
4201 * Convert float to currency
4203 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4204 double t = round((double)fltIn * (double)10000);
4205 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4206 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4207 if (fltIn < 0) pcyOut->s.Hi--;
4212 /**********************************************************************
4213 * VarCyFromR832 [OLEAUT32.102]
4214 * Convert double to currency
4216 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4217 double t = round(dblIn * (double)10000);
4218 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4219 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4220 if (dblIn < 0) pcyOut->s.Hi--;
4225 /**********************************************************************
4226 * VarCyFromDate32 [OLEAUT32.103]
4227 * Convert date to currency
4229 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4230 double t = round((double)dateIn * (double)10000);
4231 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4232 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4233 if (dateIn < 0) pcyOut->s.Hi--;
4238 /**********************************************************************
4239 * VarCyFromDate32 [OLEAUT32.104]
4241 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4247 /**********************************************************************
4248 * VarCyFromBool32 [OLEAUT32.106]
4249 * Convert boolean to currency
4251 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4252 if (boolIn < 0) pcyOut->s.Hi = -1;
4253 else pcyOut->s.Hi = 0;
4254 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4259 /**********************************************************************
4260 * VarCyFromI132 [OLEAUT32.225]
4261 * Convert signed char to currency
4263 HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4264 if (cIn < 0) pcyOut->s.Hi = -1;
4265 else pcyOut->s.Hi = 0;
4266 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4271 /**********************************************************************
4272 * VarCyFromUI232 [OLEAUT32.226]
4273 * Convert unsigned short to currency
4275 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4277 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4282 /**********************************************************************
4283 * VarCyFromUI432 [OLEAUT32.227]
4284 * Convert unsigned long to currency
4286 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4287 double t = (double)ulIn * (double)10000;
4288 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4289 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4295 /**********************************************************************
4296 * DosDateTimeToVariantTime [OLEAUT32.14]
4297 * Convert dos representation of time to the date and time representation
4298 * stored in a variant.
4300 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4305 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4307 t.tm_sec = (wDosTime & 0x001f) * 2;
4308 t.tm_min = (wDosTime & 0x07e0) >> 5;
4309 t.tm_hour = (wDosTime & 0xf800) >> 11;
4311 t.tm_mday = (wDosDate & 0x001f);
4312 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4313 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4315 return TmToDATE( &t, pvtime );