4 * Copyright 1998 Jean-Claude Cote
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * This implements the low-level and hi-level APIs for manipulating VARIANTs.
22 * The low-level APIs are used to do data coercion between different data types.
23 * The hi-level APIs are built on top of these low-level APIs and handle
24 * initialization, copying, destroying and changing the type of VARIANTs.
27 * - The Variant APIs do not support international languages, currency
28 * types, number formating and calendar. They only support U.S. English format.
29 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
30 * The prototypes for these are commented out in the oleauto.h file. They need
31 * to be implemented and cases need to be added to the switches of the existing APIs.
32 * - The parsing of date for the VarDateFromStr is not complete.
33 * - The date manipulations do not support dates prior to 1900.
34 * - The parsing does not accept as many formats as the Windows implementation.
52 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(ole);
58 #define SYSDUPSTRING(str) SysAllocStringLen((str), SysStringLen(str))
62 # define FLT_MAX MAXFLOAT
64 # error "Can't find #define for MAXFLOAT/FLT_MAX"
70 static const char CHAR_MAX = 127;
71 static const char CHAR_MIN = -128;
72 static const BYTE UI1_MAX = 255;
73 static const BYTE UI1_MIN = 0;
74 static const unsigned short UI2_MAX = 65535;
75 static const unsigned short UI2_MIN = 0;
76 static const short I2_MAX = 32767;
77 static const short I2_MIN = -32768;
78 static const unsigned long UI4_MAX = 4294967295U;
79 static const unsigned long UI4_MIN = 0;
80 static const long I4_MAX = 2147483647;
81 static const long I4_MIN = -(2147483648U);
82 static const DATE DATE_MIN = -657434;
83 static const DATE DATE_MAX = 2958465;
86 /* This mask is used to set a flag in wReserved1 of
87 * the VARIANTARG structure. The flag indicates if
88 * the API function is using an inner variant or not.
90 #define PROCESSING_INNER_VARIANT 0x0001
92 /* General use buffer.
94 #define BUFFER_MAX 1024
95 static char pBuffer[BUFFER_MAX];
98 * Note a leap year is one that is a multiple of 4
99 * but not of a 100. Except if it is a multiple of
100 * 400 then it is a leap year.
102 /* According to postgreSQL date parsing functions there is
103 * a leap year when this expression is true.
104 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
105 * So according to this there is 365.2515 days in one year.
106 * One + every four years: 1/4 -> 365.25
107 * One - every 100 years: 1/100 -> 365.01
108 * One + every 400 years: 1/400 -> 365.0025
110 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
112 * ^^ Might this be the key to an easy way to factor large prime numbers?
113 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
115 static const double DAYS_IN_ONE_YEAR = 365.2425;
118 /******************************************************************************
119 * DateTimeStringToTm [INTERNAL]
121 * Converts a string representation of a date and/or time to a tm structure.
123 * Note this function uses the postgresql date parsing functions found
124 * in the parsedt.c file.
126 * Returns TRUE if successful.
128 * Note: This function does not parse the day of the week,
129 * daylight savings time. It will only fill the followin fields in
130 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
132 ******************************************************************************/
133 static BOOL DateTimeStringToTm( OLECHAR* strIn, DWORD dwFlags, struct tm* pTm )
140 char *field[MAXDATEFIELDS];
141 int ftype[MAXDATEFIELDS];
142 char lowstr[MAXDATELEN + 1];
143 char* strDateTime = NULL;
145 /* Convert the string to ASCII since this is the only format
146 * postgesql can handle.
148 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
150 if( strDateTime != NULL )
152 /* Make sure we don't go over the maximum length
153 * accepted by postgesql.
155 if( strlen( strDateTime ) <= MAXDATELEN )
157 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
159 if( dwFlags & VAR_DATEVALUEONLY )
161 /* Get the date information.
162 * It returns 0 if date information was
163 * present and 1 if only time information was present.
164 * -1 if an error occures.
166 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
168 /* Eliminate the time information since we
169 * were asked to get date information only.
177 if( dwFlags & VAR_TIMEVALUEONLY )
179 /* Get time information only.
181 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
188 /* Get both date and time information.
189 * It returns 0 if date information was
190 * present and 1 if only time information was present.
191 * -1 if an error occures.
193 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
200 HeapFree( GetProcessHeap(), 0, strDateTime );
211 /******************************************************************************
212 * TmToDATE [INTERNAL]
214 * The date is implemented using an 8 byte floating-point number.
215 * Days are represented by whole numbers increments starting with 0.00 has
216 * being December 30 1899, midnight.
217 * The hours are expressed as the fractional part of the number.
218 * December 30 1899 at midnight = 0.00
219 * January 1 1900 at midnight = 2.00
220 * January 4 1900 at 6 AM = 5.25
221 * January 4 1900 at noon = 5.50
222 * December 29 1899 at midnight = -1.00
223 * December 18 1899 at midnight = -12.00
224 * December 18 1899 at 6AM = -12.25
225 * December 18 1899 at 6PM = -12.75
226 * December 19 1899 at midnight = -11.00
227 * The tm structure is as follows:
229 * int tm_sec; seconds after the minute - [0,59]
230 * int tm_min; minutes after the hour - [0,59]
231 * int tm_hour; hours since midnight - [0,23]
232 * int tm_mday; day of the month - [1,31]
233 * int tm_mon; months since January - [0,11]
235 * int tm_wday; days since Sunday - [0,6]
236 * int tm_yday; days since January 1 - [0,365]
237 * int tm_isdst; daylight savings time flag
240 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
241 * and tm_isdst fields of the tm structure. And only converts years
244 * Returns TRUE if successful.
246 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
250 if( (pTm->tm_year - 1900) < 0 ) return FALSE;
252 /* Start at 1. This is the way DATE is defined.
253 * January 1, 1900 at Midnight is 1.00.
254 * January 1, 1900 at 6AM is 1.25.
259 /* Add the number of days corresponding to
262 *pDateOut += (pTm->tm_year - 1900) * 365;
264 /* Add the leap days in the previous years between now and 1900.
265 * Note a leap year is one that is a multiple of 4
266 * but not of a 100. Except if it is a multiple of
267 * 400 then it is a leap year.
269 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
270 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
271 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
273 /* Set the leap year flag if the
274 * current year specified by tm_year is a
275 * leap year. This will be used to add a day
278 if( isleap( pTm->tm_year ) )
281 /* Add the number of days corresponding to
284 switch( pTm->tm_mon )
290 *pDateOut += ( 59 + leapYear );
293 *pDateOut += ( 90 + leapYear );
296 *pDateOut += ( 120 + leapYear );
299 *pDateOut += ( 151 + leapYear );
302 *pDateOut += ( 181 + leapYear );
305 *pDateOut += ( 212 + leapYear );
308 *pDateOut += ( 243 + leapYear );
311 *pDateOut += ( 273 + leapYear );
314 *pDateOut += ( 304 + leapYear );
317 *pDateOut += ( 334 + leapYear );
320 /* Add the number of days in this month.
322 *pDateOut += pTm->tm_mday;
324 /* Add the number of seconds, minutes, and hours
325 * to the DATE. Note these are the fracionnal part
326 * of the DATE so seconds / number of seconds in a day.
328 *pDateOut += pTm->tm_hour / 24.0;
329 *pDateOut += pTm->tm_min / 1440.0;
330 *pDateOut += pTm->tm_sec / 86400.0;
334 /******************************************************************************
335 * DateToTm [INTERNAL]
337 * This function converts a windows DATE to a tm structure.
339 * It does not fill all the fields of the tm structure.
340 * Here is a list of the fields that are filled:
341 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
343 * Note this function does not support dates before the January 1, 1900
344 * or ( dateIn < 2.0 ).
346 * Returns TRUE if successful.
348 static BOOL DateToTm( DATE dateIn, DWORD dwFlags, struct tm* pTm )
350 double decimalPart = 0.0;
351 double wholePart = 0.0;
353 /* Do not process dates smaller than January 1, 1900.
354 * Which corresponds to 2.0 in the windows DATE format.
356 if( dateIn < 2.0 ) return FALSE;
358 memset(pTm,0,sizeof(*pTm));
360 /* Because of the nature of DATE format which
361 * associates 2.0 to January 1, 1900. We will
362 * remove 1.0 from the whole part of the DATE
363 * so that in the following code 1.0
364 * will correspond to January 1, 1900.
365 * This simplifies the processing of the DATE value.
369 wholePart = (double) floor( dateIn );
370 decimalPart = fmod( dateIn, wholePart );
372 if( !(dwFlags & VAR_TIMEVALUEONLY) )
376 double yearsSince1900 = 0;
377 /* Start at 1900, this is where the DATE time 0.0 starts.
380 /* find in what year the day in the "wholePart" falls into.
381 * add the value to the year field.
383 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
384 pTm->tm_year += yearsSince1900;
385 /* determine if this is a leap year.
387 if( isleap( pTm->tm_year ) )
393 /* find what day of that year the "wholePart" corresponds to.
394 * Note: nDay is in [1-366] format
396 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
397 /* Set the tm_yday value.
398 * Note: The day must be converted from [1-366] to [0-365]
400 /*pTm->tm_yday = nDay - 1;*/
401 /* find which month this day corresponds to.
408 else if( nDay <= ( 59 + leapYear ) )
410 pTm->tm_mday = nDay - 31;
413 else if( nDay <= ( 90 + leapYear ) )
415 pTm->tm_mday = nDay - ( 59 + leapYear );
418 else if( nDay <= ( 120 + leapYear ) )
420 pTm->tm_mday = nDay - ( 90 + leapYear );
423 else if( nDay <= ( 151 + leapYear ) )
425 pTm->tm_mday = nDay - ( 120 + leapYear );
428 else if( nDay <= ( 181 + leapYear ) )
430 pTm->tm_mday = nDay - ( 151 + leapYear );
433 else if( nDay <= ( 212 + leapYear ) )
435 pTm->tm_mday = nDay - ( 181 + leapYear );
438 else if( nDay <= ( 243 + leapYear ) )
440 pTm->tm_mday = nDay - ( 212 + leapYear );
443 else if( nDay <= ( 273 + leapYear ) )
445 pTm->tm_mday = nDay - ( 243 + leapYear );
448 else if( nDay <= ( 304 + leapYear ) )
450 pTm->tm_mday = nDay - ( 273 + leapYear );
453 else if( nDay <= ( 334 + leapYear ) )
455 pTm->tm_mday = nDay - ( 304 + leapYear );
458 else if( nDay <= ( 365 + leapYear ) )
460 pTm->tm_mday = nDay - ( 334 + leapYear );
464 if( !(dwFlags & VAR_DATEVALUEONLY) )
466 /* find the number of seconds in this day.
467 * fractional part times, hours, minutes, seconds.
469 pTm->tm_hour = (int) ( decimalPart * 24 );
470 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
471 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
478 /******************************************************************************
479 * SizeOfVariantData [INTERNAL]
481 * This function finds the size of the data referenced by a Variant based
482 * the type "vt" of the Variant.
484 static int SizeOfVariantData( VARIANT* parg )
487 switch( V_VT(parg) & VT_TYPEMASK )
490 size = sizeof(short);
502 size = sizeof(unsigned short);
505 size = sizeof(unsigned int);
508 size = sizeof(unsigned long);
511 size = sizeof(float);
514 size = sizeof(double);
520 size = sizeof(VARIANT_BOOL);
523 size = sizeof(void*);
530 FIXME("Add size information for type vt=%d\n", V_VT(parg) & VT_TYPEMASK );
536 /******************************************************************************
537 * StringDupAtoBstr [INTERNAL]
540 static BSTR StringDupAtoBstr( char* strIn )
543 OLECHAR* pNewString = NULL;
544 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
545 bstr = SysAllocString( pNewString );
546 HeapFree( GetProcessHeap(), 0, pNewString );
550 /******************************************************************************
553 * Round the double value to the nearest integer value.
555 static double round( double d )
557 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
558 BOOL bEvenNumber = FALSE;
561 /* Save the sign of the number
563 nSign = (d >= 0.0) ? 1 : -1;
566 /* Remove the decimals.
568 integerValue = floor( d );
570 /* Set the Even flag. This is used to round the number when
571 * the decimals are exactly 1/2. If the integer part is
572 * odd the number is rounded up. If the integer part
573 * is even the number is rounded down. Using this method
574 * numbers are rounded up|down half the time.
576 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
578 /* Remove the integral part of the number.
580 decimals = d - integerValue;
582 /* Note: Ceil returns the smallest integer that is greater that x.
583 * and floor returns the largest integer that is less than or equal to x.
587 /* If the decimal part is greater than 1/2
589 roundedValue = ceil( d );
591 else if( decimals < 0.5 )
593 /* If the decimal part is smaller than 1/2
595 roundedValue = floor( d );
599 /* the decimals are exactly 1/2 so round according to
600 * the bEvenNumber flag.
604 roundedValue = floor( d );
608 roundedValue = ceil( d );
612 return roundedValue * nSign;
615 /******************************************************************************
616 * RemoveCharacterFromString [INTERNAL]
618 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
620 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
622 LPSTR pNewString = NULL;
623 LPSTR strToken = NULL;
625 /* Check if we have a valid argument
629 pNewString = strdup( str );
631 strToken = strtok( pNewString, strOfCharToRemove );
632 while( strToken != NULL ) {
633 strcat( str, strToken );
634 strToken = strtok( NULL, strOfCharToRemove );
641 /******************************************************************************
642 * GetValidRealString [INTERNAL]
644 * Checks if the string is of proper format to be converted to a real value.
646 static BOOL IsValidRealString( LPSTR strRealString )
648 /* Real values that have a decimal point are required to either have
649 * digits before or after the decimal point. We will assume that
650 * we do not have any digits at either position. If we do encounter
651 * some we will disable this flag.
653 BOOL bDigitsRequired = TRUE;
654 /* Processed fields in the string representation of the real number.
656 BOOL bWhiteSpaceProcessed = FALSE;
657 BOOL bFirstSignProcessed = FALSE;
658 BOOL bFirstDigitsProcessed = FALSE;
659 BOOL bDecimalPointProcessed = FALSE;
660 BOOL bSecondDigitsProcessed = FALSE;
661 BOOL bExponentProcessed = FALSE;
662 BOOL bSecondSignProcessed = FALSE;
663 BOOL bThirdDigitsProcessed = FALSE;
664 /* Assume string parameter "strRealString" is valid and try to disprove it.
666 BOOL bValidRealString = TRUE;
668 /* Used to count the number of tokens in the "strRealString".
670 LPSTR strToken = NULL;
674 /* Check if we have a valid argument
676 if( strRealString == NULL )
678 bValidRealString = FALSE;
681 if( bValidRealString == TRUE )
683 /* Make sure we only have ONE token in the string.
685 strToken = strtok( strRealString, " " );
686 while( strToken != NULL ) {
688 strToken = strtok( NULL, " " );
693 bValidRealString = FALSE;
698 /* Make sure this token contains only valid characters.
699 * The string argument to atof has the following form:
700 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
701 * Whitespace consists of space and|or <TAB> characters, which are ignored.
702 * Sign is either plus '+' or minus '-'.
703 * Digits are one or more decimal digits.
704 * Note: If no digits appear before the decimal point, at least one must
705 * appear after the decimal point.
706 * The decimal digits may be followed by an exponent.
707 * An Exponent consists of an introductory letter ( D, d, E, or e) and
708 * an optionally signed decimal integer.
710 pChar = strRealString;
711 while( bValidRealString == TRUE && *pChar != '\0' )
719 if( bWhiteSpaceProcessed ||
720 bFirstSignProcessed ||
721 bFirstDigitsProcessed ||
722 bDecimalPointProcessed ||
723 bSecondDigitsProcessed ||
724 bExponentProcessed ||
725 bSecondSignProcessed ||
726 bThirdDigitsProcessed )
728 bValidRealString = FALSE;
735 if( bFirstSignProcessed == FALSE )
737 if( bFirstDigitsProcessed ||
738 bDecimalPointProcessed ||
739 bSecondDigitsProcessed ||
740 bExponentProcessed ||
741 bSecondSignProcessed ||
742 bThirdDigitsProcessed )
744 bValidRealString = FALSE;
746 bWhiteSpaceProcessed = TRUE;
747 bFirstSignProcessed = TRUE;
749 else if( bSecondSignProcessed == FALSE )
751 /* Note: The exponent must be present in
752 * order to accept the second sign...
754 if( bExponentProcessed == FALSE ||
755 bThirdDigitsProcessed ||
758 bValidRealString = FALSE;
760 bFirstSignProcessed = TRUE;
761 bWhiteSpaceProcessed = TRUE;
762 bFirstDigitsProcessed = TRUE;
763 bDecimalPointProcessed = TRUE;
764 bSecondDigitsProcessed = TRUE;
765 bSecondSignProcessed = TRUE;
781 if( bFirstDigitsProcessed == FALSE )
783 if( bDecimalPointProcessed ||
784 bSecondDigitsProcessed ||
785 bExponentProcessed ||
786 bSecondSignProcessed ||
787 bThirdDigitsProcessed )
789 bValidRealString = FALSE;
791 bFirstSignProcessed = TRUE;
792 bWhiteSpaceProcessed = TRUE;
793 /* We have found some digits before the decimal point
794 * so disable the "Digits required" flag.
796 bDigitsRequired = FALSE;
798 else if( bSecondDigitsProcessed == FALSE )
800 if( bExponentProcessed ||
801 bSecondSignProcessed ||
802 bThirdDigitsProcessed )
804 bValidRealString = FALSE;
806 bFirstSignProcessed = TRUE;
807 bWhiteSpaceProcessed = TRUE;
808 bFirstDigitsProcessed = TRUE;
809 bDecimalPointProcessed = TRUE;
810 /* We have found some digits after the decimal point
811 * so disable the "Digits required" flag.
813 bDigitsRequired = FALSE;
815 else if( bThirdDigitsProcessed == FALSE )
817 /* Getting here means everything else should be processed.
818 * If we get anything else than a decimal following this
819 * digit it will be flagged by the other cases, so
820 * we do not really need to do anything in here.
824 /* If DecimalPoint...
827 if( bDecimalPointProcessed ||
828 bSecondDigitsProcessed ||
829 bExponentProcessed ||
830 bSecondSignProcessed ||
831 bThirdDigitsProcessed )
833 bValidRealString = FALSE;
835 bFirstSignProcessed = TRUE;
836 bWhiteSpaceProcessed = TRUE;
837 bFirstDigitsProcessed = TRUE;
838 bDecimalPointProcessed = TRUE;
846 if( bExponentProcessed ||
847 bSecondSignProcessed ||
848 bThirdDigitsProcessed ||
851 bValidRealString = FALSE;
853 bFirstSignProcessed = TRUE;
854 bWhiteSpaceProcessed = TRUE;
855 bFirstDigitsProcessed = TRUE;
856 bDecimalPointProcessed = TRUE;
857 bSecondDigitsProcessed = TRUE;
858 bExponentProcessed = TRUE;
861 bValidRealString = FALSE;
864 /* Process next character.
869 /* If the required digits were not present we have an invalid
870 * string representation of a real number.
872 if( bDigitsRequired == TRUE )
874 bValidRealString = FALSE;
877 return bValidRealString;
881 /******************************************************************************
884 * This function dispatches execution to the proper conversion API
885 * to do the necessary coercion.
887 * FIXME: Passing down dwFlags to the conversion functions is wrong, this
888 * is a different flagmask. Check MSDN.
890 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
893 unsigned short vtFrom = 0;
894 vtFrom = V_VT(ps) & VT_TYPEMASK;
897 /* Note: Since "long" and "int" values both have 4 bytes and are
898 * both signed integers "int" will be treated as "long" in the
900 * The same goes for their unsigned versions.
903 /* Trivial Case: If the coercion is from two types that are
904 * identical then we can blindly copy from one argument to another.*/
907 return VariantCopy(pd,ps);
910 /* Cases requiring thought*/
915 res = VariantClear( pd );
918 res = VariantClear( pd );
928 res = VariantCopy( pd, ps );
931 res = VarI1FromI2( V_UNION(ps,iVal), &V_UNION(pd,cVal) );
935 res = VarI1FromI4( V_UNION(ps,lVal), &V_UNION(pd,cVal) );
938 res = VarI1FromUI1( V_UNION(ps,bVal), &V_UNION(pd,cVal) );
941 res = VarI1FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,cVal) );
945 res = VarI1FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,cVal) );
948 res = VarI1FromR4( V_UNION(ps,fltVal), &V_UNION(pd,cVal) );
951 res = VarI1FromR8( V_UNION(ps,dblVal), &V_UNION(pd,cVal) );
954 res = VarI1FromDate( V_UNION(ps,date), &V_UNION(pd,cVal) );
957 res = VarI1FromBool( V_UNION(ps,boolVal), &V_UNION(pd,cVal) );
960 res = VarI1FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,cVal) );
963 res = VarI1FromCy( V_UNION(ps,cyVal), &V_UNION(pd,cVal) );
966 /*res = VarI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cVal) );*/
968 /*res = VarI1FromDec( V_UNION(ps,decVal), &V_UNION(pd,cVal) );*/
971 res = DISP_E_TYPEMISMATCH;
972 FIXME("Coercion from %d to %d\n", vtFrom, vt );
981 res = VarI2FromI1( V_UNION(ps,cVal), &V_UNION(pd,iVal) );
984 res = VariantCopy( pd, ps );
988 res = VarI2FromI4( V_UNION(ps,lVal), &V_UNION(pd,iVal) );
991 res = VarI2FromUI1( V_UNION(ps,bVal), &V_UNION(pd,iVal) );
994 res = VarI2FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,iVal) );
998 res = VarI2FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,iVal) );
1001 res = VarI2FromR4( V_UNION(ps,fltVal), &V_UNION(pd,iVal) );
1004 res = VarI2FromR8( V_UNION(ps,dblVal), &V_UNION(pd,iVal) );
1007 res = VarI2FromDate( V_UNION(ps,date), &V_UNION(pd,iVal) );
1010 res = VarI2FromBool( V_UNION(ps,boolVal), &V_UNION(pd,iVal) );
1013 res = VarI2FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,iVal) );
1016 res = VarI2FromCy( V_UNION(ps,cyVal), &V_UNION(pd,iVal) );
1018 case( VT_DISPATCH ):
1019 /*res = VarI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,iVal) );*/
1021 /*res = VarI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,iVal) );*/
1024 res = DISP_E_TYPEMISMATCH;
1025 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1035 V_UNION(pd,lVal) = 0;
1039 res = VarI4FromI1( V_UNION(ps,cVal), &V_UNION(pd,lVal) );
1042 res = VarI4FromI2( V_UNION(ps,iVal), &V_UNION(pd,lVal) );
1046 res = VariantCopy( pd, ps );
1049 res = VarI4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,lVal) );
1052 res = VarI4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,lVal) );
1056 res = VarI4FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,lVal) );
1059 res = VarI4FromR4( V_UNION(ps,fltVal), &V_UNION(pd,lVal) );
1062 res = VarI4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,lVal) );
1065 res = VarI4FromDate( V_UNION(ps,date), &V_UNION(pd,lVal) );
1068 res = VarI4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,lVal) );
1071 res = VarI4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,lVal) );
1074 res = VarI4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,lVal) );
1076 case( VT_DISPATCH ):
1077 /*res = VarI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,lVal) );*/
1079 /*res = VarI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,lVal) );*/
1082 res = DISP_E_TYPEMISMATCH;
1083 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1092 res = VarUI1FromI1( V_UNION(ps,cVal), &V_UNION(pd,bVal) );
1095 res = VarUI1FromI2( V_UNION(ps,iVal), &V_UNION(pd,bVal) );
1099 res = VarUI1FromI4( V_UNION(ps,lVal), &V_UNION(pd,bVal) );
1102 res = VariantCopy( pd, ps );
1105 res = VarUI1FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,bVal) );
1109 res = VarUI1FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,bVal) );
1112 res = VarUI1FromR4( V_UNION(ps,fltVal), &V_UNION(pd,bVal) );
1115 res = VarUI1FromR8( V_UNION(ps,dblVal), &V_UNION(pd,bVal) );
1118 res = VarUI1FromDate( V_UNION(ps,date), &V_UNION(pd,bVal) );
1121 res = VarUI1FromBool( V_UNION(ps,boolVal), &V_UNION(pd,bVal) );
1124 res = VarUI1FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,bVal) );
1127 res = VarUI1FromCy( V_UNION(ps,cyVal), &V_UNION(pd,bVal) );
1129 case( VT_DISPATCH ):
1130 /*res = VarUI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,bVal) );*/
1132 /*res = VarUI1FromDec( V_UNION(ps,deiVal), &V_UNION(pd,bVal) );*/
1135 res = DISP_E_TYPEMISMATCH;
1136 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1145 res = VarUI2FromI1( V_UNION(ps,cVal), &V_UNION(pd,uiVal) );
1148 res = VarUI2FromI2( V_UNION(ps,iVal), &V_UNION(pd,uiVal) );
1152 res = VarUI2FromI4( V_UNION(ps,lVal), &V_UNION(pd,uiVal) );
1155 res = VarUI2FromUI1( V_UNION(ps,bVal), &V_UNION(pd,uiVal) );
1158 res = VariantCopy( pd, ps );
1162 res = VarUI2FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,uiVal) );
1165 res = VarUI2FromR4( V_UNION(ps,fltVal), &V_UNION(pd,uiVal) );
1168 res = VarUI2FromR8( V_UNION(ps,dblVal), &V_UNION(pd,uiVal) );
1171 res = VarUI2FromDate( V_UNION(ps,date), &V_UNION(pd,uiVal) );
1174 res = VarUI2FromBool( V_UNION(ps,boolVal), &V_UNION(pd,uiVal) );
1177 res = VarUI2FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,uiVal) );
1180 res = VarUI2FromCy( V_UNION(ps,cyVal), &V_UNION(pd,uiVal) );
1182 case( VT_DISPATCH ):
1183 /*res = VarUI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,uiVal) );*/
1185 /*res = VarUI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,uiVal) );*/
1188 res = DISP_E_TYPEMISMATCH;
1189 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1199 res = VarUI4FromI1( V_UNION(ps,cVal), &V_UNION(pd,ulVal) );
1202 res = VarUI4FromI2( V_UNION(ps,iVal), &V_UNION(pd,ulVal) );
1206 res = VarUI4FromI4( V_UNION(ps,lVal), &V_UNION(pd,ulVal) );
1209 res = VarUI4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,ulVal) );
1212 res = VarUI4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,ulVal) );
1215 res = VariantCopy( pd, ps );
1218 res = VarUI4FromR4( V_UNION(ps,fltVal), &V_UNION(pd,ulVal) );
1221 res = VarUI4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,ulVal) );
1224 res = VarUI4FromDate( V_UNION(ps,date), &V_UNION(pd,ulVal) );
1227 res = VarUI4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,ulVal) );
1230 res = VarUI4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,ulVal) );
1233 res = VarUI4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,ulVal) );
1235 case( VT_DISPATCH ):
1236 /*res = VarUI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,ulVal) );*/
1238 /*res = VarUI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,ulVal) );*/
1241 res = DISP_E_TYPEMISMATCH;
1242 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1251 res = VarR4FromI1( V_UNION(ps,cVal), &V_UNION(pd,fltVal) );
1254 res = VarR4FromI2( V_UNION(ps,iVal), &V_UNION(pd,fltVal) );
1258 res = VarR4FromI4( V_UNION(ps,lVal), &V_UNION(pd,fltVal) );
1261 res = VarR4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,fltVal) );
1264 res = VarR4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,fltVal) );
1268 res = VarR4FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,fltVal) );
1271 res = VariantCopy( pd, ps );
1274 res = VarR4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,fltVal) );
1277 res = VarR4FromDate( V_UNION(ps,date), &V_UNION(pd,fltVal) );
1280 res = VarR4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,fltVal) );
1283 res = VarR4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,fltVal) );
1286 res = VarR4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,fltVal) );
1288 case( VT_DISPATCH ):
1289 /*res = VarR4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,fltVal) );*/
1291 /*res = VarR4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,fltVal) );*/
1294 res = DISP_E_TYPEMISMATCH;
1295 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1304 res = VarR8FromI1( V_UNION(ps,cVal), &V_UNION(pd,dblVal) );
1307 res = VarR8FromI2( V_UNION(ps,iVal), &V_UNION(pd,dblVal) );
1311 res = VarR8FromI4( V_UNION(ps,lVal), &V_UNION(pd,dblVal) );
1314 res = VarR8FromUI1( V_UNION(ps,bVal), &V_UNION(pd,dblVal) );
1317 res = VarR8FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,dblVal) );
1321 res = VarR8FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,dblVal) );
1324 res = VarR8FromR4( V_UNION(ps,fltVal), &V_UNION(pd,dblVal) );
1327 res = VariantCopy( pd, ps );
1330 res = VarR8FromDate( V_UNION(ps,date), &V_UNION(pd,dblVal) );
1333 res = VarR8FromBool( V_UNION(ps,boolVal), &V_UNION(pd,dblVal) );
1336 res = VarR8FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,dblVal) );
1339 res = VarR8FromCy( V_UNION(ps,cyVal), &V_UNION(pd,dblVal) );
1341 case( VT_DISPATCH ):
1342 /*res = VarR8FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,dblVal) );*/
1344 /*res = VarR8FromDec( V_UNION(ps,deiVal), &V_UNION(pd,dblVal) );*/
1347 res = DISP_E_TYPEMISMATCH;
1348 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1357 res = VarDateFromI1( V_UNION(ps,cVal), &V_UNION(pd,date) );
1360 res = VarDateFromI2( V_UNION(ps,iVal), &V_UNION(pd,date) );
1363 res = VarDateFromInt( V_UNION(ps,intVal), &V_UNION(pd,date) );
1366 res = VarDateFromI4( V_UNION(ps,lVal), &V_UNION(pd,date) );
1369 res = VarDateFromUI1( V_UNION(ps,bVal), &V_UNION(pd,date) );
1372 res = VarDateFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,date) );
1375 res = VarDateFromUint( V_UNION(ps,uintVal), &V_UNION(pd,date) );
1378 res = VarDateFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,date) );
1381 res = VarDateFromR4( V_UNION(ps,fltVal), &V_UNION(pd,date) );
1384 res = VarDateFromR8( V_UNION(ps,dblVal), &V_UNION(pd,date) );
1387 res = VariantCopy( pd, ps );
1390 res = VarDateFromBool( V_UNION(ps,boolVal), &V_UNION(pd,date) );
1393 res = VarDateFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,date) );
1396 res = VarDateFromCy( V_UNION(ps,cyVal), &V_UNION(pd,date) );
1398 case( VT_DISPATCH ):
1399 /*res = VarDateFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,date) );*/
1401 /*res = VarDateFromDec( V_UNION(ps,deiVal), &V_UNION(pd,date) );*/
1404 res = DISP_E_TYPEMISMATCH;
1405 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1415 V_UNION(pd,boolVal) = VARIANT_FALSE;
1418 res = VarBoolFromI1( V_UNION(ps,cVal), &V_UNION(pd,boolVal) );
1421 res = VarBoolFromI2( V_UNION(ps,iVal), &V_UNION(pd,boolVal) );
1424 res = VarBoolFromInt( V_UNION(ps,intVal), &V_UNION(pd,boolVal) );
1427 res = VarBoolFromI4( V_UNION(ps,lVal), &V_UNION(pd,boolVal) );
1430 res = VarBoolFromUI1( V_UNION(ps,bVal), &V_UNION(pd,boolVal) );
1433 res = VarBoolFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,boolVal) );
1436 res = VarBoolFromUint( V_UNION(ps,uintVal), &V_UNION(pd,boolVal) );
1439 res = VarBoolFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,boolVal) );
1442 res = VarBoolFromR4( V_UNION(ps,fltVal), &V_UNION(pd,boolVal) );
1445 res = VarBoolFromR8( V_UNION(ps,dblVal), &V_UNION(pd,boolVal) );
1448 res = VarBoolFromDate( V_UNION(ps,date), &V_UNION(pd,boolVal) );
1451 res = VariantCopy( pd, ps );
1454 res = VarBoolFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,boolVal) );
1457 res = VarBoolFromCy( V_UNION(ps,cyVal), &V_UNION(pd,boolVal) );
1459 case( VT_DISPATCH ):
1460 /*res = VarBoolFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,boolVal) );*/
1462 /*res = VarBoolFromDec( V_UNION(ps,deiVal), &V_UNION(pd,boolVal) );*/
1465 res = DISP_E_TYPEMISMATCH;
1466 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1475 if ((V_UNION(pd,bstrVal) = SysAllocStringLen(NULL, 0)))
1478 res = E_OUTOFMEMORY;
1481 res = VarBstrFromI1( V_UNION(ps,cVal), lcid, 0, &V_UNION(pd,bstrVal) );
1484 res = VarBstrFromI2( V_UNION(ps,iVal), lcid, 0, &V_UNION(pd,bstrVal) );
1487 res = VarBstrFromInt( V_UNION(ps,intVal), lcid, 0, &V_UNION(pd,bstrVal) );
1490 res = VarBstrFromI4( V_UNION(ps,lVal), lcid, 0, &V_UNION(pd,bstrVal) );
1493 res = VarBstrFromUI1( V_UNION(ps,bVal), lcid, 0, &V_UNION(pd,bstrVal) );
1496 res = VarBstrFromUI2( V_UNION(ps,uiVal), lcid, 0, &V_UNION(pd,bstrVal) );
1499 res = VarBstrFromUint( V_UNION(ps,uintVal), lcid, 0, &V_UNION(pd,bstrVal) );
1502 res = VarBstrFromUI4( V_UNION(ps,ulVal), lcid, 0, &V_UNION(pd,bstrVal) );
1505 res = VarBstrFromR4( V_UNION(ps,fltVal), lcid, 0, &V_UNION(pd,bstrVal) );
1508 res = VarBstrFromR8( V_UNION(ps,dblVal), lcid, 0, &V_UNION(pd,bstrVal) );
1511 res = VarBstrFromDate( V_UNION(ps,date), lcid, 0, &V_UNION(pd,bstrVal) );
1514 res = VarBstrFromBool( V_UNION(ps,boolVal), lcid, 0, &V_UNION(pd,bstrVal) );
1517 res = VariantCopy( pd, ps );
1520 res = VarBstrFromCy( V_UNION(ps,cyVal), lcid, 0, &V_UNION(pd,bstrVal) );
1522 case( VT_DISPATCH ):
1523 /*res = VarBstrFromDisp( V_UNION(ps,pdispVal), lcid, 0, &(pd,bstrVal) );*/
1525 /*res = VarBstrFromDec( V_UNION(ps,deiVal), lcid, 0, &(pd,bstrVal) );*/
1528 res = DISP_E_TYPEMISMATCH;
1529 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1538 res = VarCyFromI1( V_UNION(ps,cVal), &V_UNION(pd,cyVal) );
1541 res = VarCyFromI2( V_UNION(ps,iVal), &V_UNION(pd,cyVal) );
1544 res = VarCyFromInt( V_UNION(ps,intVal), &V_UNION(pd,cyVal) );
1547 res = VarCyFromI4( V_UNION(ps,lVal), &V_UNION(pd,cyVal) );
1550 res = VarCyFromUI1( V_UNION(ps,bVal), &V_UNION(pd,cyVal) );
1553 res = VarCyFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,cyVal) );
1556 res = VarCyFromUint( V_UNION(ps,uintVal), &V_UNION(pd,cyVal) );
1559 res = VarCyFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,cyVal) );
1562 res = VarCyFromR4( V_UNION(ps,fltVal), &V_UNION(pd,cyVal) );
1565 res = VarCyFromR8( V_UNION(ps,dblVal), &V_UNION(pd,cyVal) );
1568 res = VarCyFromDate( V_UNION(ps,date), &V_UNION(pd,cyVal) );
1571 res = VarCyFromBool( V_UNION(ps,date), &V_UNION(pd,cyVal) );
1574 res = VariantCopy( pd, ps );
1577 res = VarCyFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,cyVal) );
1579 case( VT_DISPATCH ):
1580 /*res = VarCyFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cyVal) );*/
1582 /*res = VarCyFromDec( V_UNION(ps,deiVal), &V_UNION(pd,cyVal) );*/
1586 res = DISP_E_TYPEMISMATCH;
1587 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1593 if (vtFrom == VT_DISPATCH)
1595 res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd));
1599 res = DISP_E_TYPEMISMATCH;
1600 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1605 res = DISP_E_TYPEMISMATCH;
1606 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1613 /******************************************************************************
1614 * ValidateVtRange [INTERNAL]
1616 * Used internally by the hi-level Variant API to determine
1617 * if the vartypes are valid.
1619 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1621 /* if by value we must make sure it is in the
1622 * range of the valid types.
1624 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1626 return DISP_E_BADVARTYPE;
1632 /******************************************************************************
1633 * ValidateVartype [INTERNAL]
1635 * Used internally by the hi-level Variant API to determine
1636 * if the vartypes are valid.
1638 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1642 /* check if we have a valid argument.
1646 /* if by reference check that the type is in
1647 * the valid range and that it is not of empty or null type
1649 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1650 ( vt & VT_TYPEMASK ) == VT_NULL ||
1651 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1653 res = DISP_E_BADVARTYPE;
1659 res = ValidateVtRange( vt );
1665 /******************************************************************************
1666 * ValidateVt [INTERNAL]
1668 * Used internally by the hi-level Variant API to determine
1669 * if the vartypes are valid.
1671 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1675 /* check if we have a valid argument.
1679 /* if by reference check that the type is in
1680 * the valid range and that it is not of empty or null type
1682 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1683 ( vt & VT_TYPEMASK ) == VT_NULL ||
1684 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1686 res = DISP_E_BADVARTYPE;
1692 res = ValidateVtRange( vt );
1702 /******************************************************************************
1703 * VariantInit [OLEAUT32.8]
1705 * Initializes the Variant. Unlike VariantClear it does not interpret
1706 * the current contents of the Variant.
1708 void WINAPI VariantInit(VARIANTARG* pvarg)
1710 TRACE("(%p)\n",pvarg);
1712 memset(pvarg, 0, sizeof (VARIANTARG));
1713 V_VT(pvarg) = VT_EMPTY;
1718 /******************************************************************************
1719 * VariantClear [OLEAUT32.9]
1721 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1722 * sets the wReservedX field to 0. The current contents of the VARIANT are
1723 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1724 * released. If VT_ARRAY the array is freed.
1726 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1729 TRACE("(%p)\n",pvarg);
1731 res = ValidateVariantType( V_VT(pvarg) );
1734 if( !( V_VT(pvarg) & VT_BYREF ) )
1737 * The VT_ARRAY flag is a special case of a safe array.
1739 if ( (V_VT(pvarg) & VT_ARRAY) != 0)
1741 SafeArrayDestroy(V_UNION(pvarg,parray));
1745 switch( V_VT(pvarg) & VT_TYPEMASK )
1748 SysFreeString( V_UNION(pvarg,bstrVal) );
1750 case( VT_DISPATCH ):
1751 if(V_UNION(pvarg,pdispVal)!=NULL)
1752 ICOM_CALL(Release,V_UNION(pvarg,pdispVal));
1755 VariantClear(V_UNION(pvarg,pvarVal));
1758 if(V_UNION(pvarg,punkVal)!=NULL)
1759 ICOM_CALL(Release,V_UNION(pvarg,punkVal));
1761 case( VT_SAFEARRAY ):
1762 SafeArrayDestroy(V_UNION(pvarg,parray));
1771 * Empty all the fields and mark the type as empty.
1773 memset(pvarg, 0, sizeof (VARIANTARG));
1774 V_VT(pvarg) = VT_EMPTY;
1780 /******************************************************************************
1781 * VariantCopy [OLEAUT32.10]
1783 * Frees up the designation variant and makes a copy of the source.
1785 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1789 TRACE("(%p, %p), vt=%d\n", pvargDest, pvargSrc, V_VT(pvargSrc));
1791 res = ValidateVariantType( V_VT(pvargSrc) );
1793 /* If the pointer are to the same variant we don't need
1796 if( pvargDest != pvargSrc && res == S_OK )
1798 res = VariantClear( pvargDest );
1802 if( V_VT(pvargSrc) & VT_BYREF )
1804 /* In the case of byreference we only need
1805 * to copy the pointer.
1807 pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3;
1808 V_VT(pvargDest) = V_VT(pvargSrc);
1813 * The VT_ARRAY flag is another way to designate a safe array.
1815 if (V_VT(pvargSrc) & VT_ARRAY)
1817 SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray));
1821 /* In the case of by value we need to
1822 * copy the actual value. In the case of
1823 * VT_BSTR a copy of the string is made,
1824 * if VT_DISPATCH or VT_IUNKNOWN AddRef is
1825 * called to increment the object's reference count.
1827 switch( V_VT(pvargSrc) & VT_TYPEMASK )
1830 V_UNION(pvargDest,bstrVal) = SYSDUPSTRING( V_UNION(pvargSrc,bstrVal) );
1832 case( VT_DISPATCH ):
1833 V_UNION(pvargDest,pdispVal) = V_UNION(pvargSrc,pdispVal);
1834 if (V_UNION(pvargDest,pdispVal)!=NULL)
1835 ICOM_CALL(AddRef,V_UNION(pvargDest,pdispVal));
1838 VariantCopy(V_UNION(pvargDest,pvarVal),V_UNION(pvargSrc,pvarVal));
1841 V_UNION(pvargDest,punkVal) = V_UNION(pvargSrc,punkVal);
1842 if (V_UNION(pvargDest,pdispVal)!=NULL)
1843 ICOM_CALL(AddRef,V_UNION(pvargDest,punkVal));
1845 case( VT_SAFEARRAY ):
1846 SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray));
1849 pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3;
1854 V_VT(pvargDest) = V_VT(pvargSrc);
1863 /******************************************************************************
1864 * VariantCopyInd [OLEAUT32.11]
1866 * Frees up the destination variant and makes a copy of the source. If
1867 * the source is of type VT_BYREF it performs the necessary indirections.
1869 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1873 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1875 res = ValidateVariantType( V_VT(pvargSrc) );
1880 if( V_VT(pvargSrc) & VT_BYREF )
1883 VariantInit( &varg );
1885 /* handle the in place copy.
1887 if( pvargDest == pvargSrc )
1889 /* we will use a copy of the source instead.
1891 res = VariantCopy( &varg, pvargSrc );
1897 res = VariantClear( pvargDest );
1902 * The VT_ARRAY flag is another way to designate a safearray variant.
1904 if ( V_VT(pvargSrc) & VT_ARRAY)
1906 SafeArrayCopy(*V_UNION(pvargSrc,pparray), &V_UNION(pvargDest,parray));
1910 /* In the case of by reference we need
1911 * to copy the date pointed to by the variant.
1914 /* Get the variant type.
1916 switch( V_VT(pvargSrc) & VT_TYPEMASK )
1919 V_UNION(pvargDest,bstrVal) = SYSDUPSTRING( *(V_UNION(pvargSrc,pbstrVal)) );
1921 case( VT_DISPATCH ):
1925 /* Prevent from cycling. According to tests on
1926 * VariantCopyInd in Windows and the documentation
1927 * this API dereferences the inner Variants to only one depth.
1928 * If the inner Variant itself contains an
1929 * other inner variant the E_INVALIDARG error is
1932 if( pvargSrc->n1.n2.wReserved1 & PROCESSING_INNER_VARIANT )
1934 /* If we get here we are attempting to deference
1935 * an inner variant that that is itself contained
1936 * in an inner variant so report E_INVALIDARG error.
1942 /* Set the processing inner variant flag.
1943 * We will set this flag in the inner variant
1944 * that will be passed to the VariantCopyInd function.
1946 (V_UNION(pvargSrc,pvarVal))->n1.n2.wReserved1 |= PROCESSING_INNER_VARIANT;
1948 /* Dereference the inner variant.
1950 res = VariantCopyInd( pvargDest, V_UNION(pvargSrc,pvarVal) );
1951 /* We must also copy its type, I think.
1953 V_VT(pvargSrc) = V_VT(V_UNION(pvargSrc,pvarVal));
1959 case( VT_SAFEARRAY ):
1960 SafeArrayCopy(*V_UNION(pvargSrc,pparray), &V_UNION(pvargDest,parray));
1963 /* This is a by reference Variant which means that the union
1964 * part of the Variant contains a pointer to some data of
1965 * type "V_VT(pvargSrc) & VT_TYPEMASK".
1966 * We will deference this data in a generic fashion using
1967 * the void pointer "Variant.u.byref".
1968 * We will copy this data into the union of the destination
1971 memcpy( &pvargDest->n1.n2.n3, V_UNION(pvargSrc,byref), SizeOfVariantData( pvargSrc ) );
1976 if (res == S_OK) V_VT(pvargDest) = V_VT(pvargSrc) & VT_TYPEMASK;
1980 /* this should not fail.
1982 VariantClear( &varg );
1986 res = VariantCopy( pvargDest, pvargSrc );
1992 /******************************************************************************
1993 * VariantChangeType [OLEAUT32.12]
1995 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1996 USHORT wFlags, VARTYPE vt)
1998 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
2001 /******************************************************************************
2002 * VariantChangeTypeEx [OLEAUT32.147]
2004 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
2005 LCID lcid, USHORT wFlags, VARTYPE vt)
2009 VariantInit( &varg );
2011 TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
2013 /* validate our source argument.
2015 res = ValidateVariantType( V_VT(pvargSrc) );
2017 /* validate the vartype.
2021 res = ValidateVt( vt );
2024 /* if we are doing an in-place conversion make a copy of the source.
2026 if( res == S_OK && pvargDest == pvargSrc )
2028 res = VariantCopy( &varg, pvargSrc );
2034 /* free up the destination variant.
2036 res = VariantClear( pvargDest );
2041 if( V_VT(pvargSrc) & VT_BYREF )
2043 /* Convert the source variant to a "byvalue" variant.
2046 VariantInit( &Variant );
2047 res = VariantCopyInd( &Variant, pvargSrc );
2050 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2051 /* this should not fail.
2053 VariantClear( &Variant );
2059 /* Use the current "byvalue" source variant.
2061 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2064 /* this should not fail.
2066 VariantClear( &varg );
2068 /* set the type of the destination
2071 V_VT(pvargDest) = vt;
2079 /******************************************************************************
2080 * VarUI1FromI2 [OLEAUT32.130]
2082 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2084 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2086 /* Check range of value.
2088 if( sIn < UI1_MIN || sIn > UI1_MAX )
2090 return DISP_E_OVERFLOW;
2093 *pbOut = (BYTE) sIn;
2098 /******************************************************************************
2099 * VarUI1FromI4 [OLEAUT32.131]
2101 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2103 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2105 /* Check range of value.
2107 if( lIn < UI1_MIN || lIn > UI1_MAX )
2109 return DISP_E_OVERFLOW;
2112 *pbOut = (BYTE) lIn;
2118 /******************************************************************************
2119 * VarUI1FromR4 [OLEAUT32.132]
2121 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2123 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2125 /* Check range of value.
2127 fltIn = round( fltIn );
2128 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2130 return DISP_E_OVERFLOW;
2133 *pbOut = (BYTE) fltIn;
2138 /******************************************************************************
2139 * VarUI1FromR8 [OLEAUT32.133]
2141 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2143 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2145 /* Check range of value.
2147 dblIn = round( dblIn );
2148 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2150 return DISP_E_OVERFLOW;
2153 *pbOut = (BYTE) dblIn;
2158 /******************************************************************************
2159 * VarUI1FromDate [OLEAUT32.135]
2161 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2163 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2165 /* Check range of value.
2167 dateIn = round( dateIn );
2168 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2170 return DISP_E_OVERFLOW;
2173 *pbOut = (BYTE) dateIn;
2178 /******************************************************************************
2179 * VarUI1FromBool [OLEAUT32.138]
2181 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2183 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2185 *pbOut = (BYTE) boolIn;
2190 /******************************************************************************
2191 * VarUI1FromI1 [OLEAUT32.237]
2193 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2195 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2202 /******************************************************************************
2203 * VarUI1FromUI2 [OLEAUT32.238]
2205 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2207 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2209 /* Check range of value.
2211 if( uiIn > UI1_MAX )
2213 return DISP_E_OVERFLOW;
2216 *pbOut = (BYTE) uiIn;
2221 /******************************************************************************
2222 * VarUI1FromUI4 [OLEAUT32.239]
2224 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2226 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2228 /* Check range of value.
2230 if( ulIn > UI1_MAX )
2232 return DISP_E_OVERFLOW;
2235 *pbOut = (BYTE) ulIn;
2241 /******************************************************************************
2242 * VarUI1FromStr [OLEAUT32.136]
2244 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2246 double dValue = 0.0;
2247 LPSTR pNewString = NULL;
2249 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2251 /* Check if we have a valid argument
2253 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2254 RemoveCharacterFromString( pNewString, "," );
2255 if( IsValidRealString( pNewString ) == FALSE )
2257 return DISP_E_TYPEMISMATCH;
2260 /* Convert the valid string to a floating point number.
2262 dValue = atof( pNewString );
2264 /* We don't need the string anymore so free it.
2266 HeapFree( GetProcessHeap(), 0 , pNewString );
2268 /* Check range of value.
2270 dValue = round( dValue );
2271 if( dValue < UI1_MIN || dValue > UI1_MAX )
2273 return DISP_E_OVERFLOW;
2276 *pbOut = (BYTE) dValue;
2281 /**********************************************************************
2282 * VarUI1FromCy [OLEAUT32.134]
2283 * Convert currency to unsigned char
2285 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2286 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2288 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2294 /******************************************************************************
2295 * VarI2FromUI1 [OLEAUT32.48]
2297 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2299 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2301 *psOut = (short) bIn;
2306 /******************************************************************************
2307 * VarI2FromI4 [OLEAUT32.49]
2309 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2311 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2313 /* Check range of value.
2315 if( lIn < I2_MIN || lIn > I2_MAX )
2317 return DISP_E_OVERFLOW;
2320 *psOut = (short) lIn;
2325 /******************************************************************************
2326 * VarI2FromR4 [OLEAUT32.50]
2328 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2330 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2332 /* Check range of value.
2334 fltIn = round( fltIn );
2335 if( fltIn < I2_MIN || fltIn > I2_MAX )
2337 return DISP_E_OVERFLOW;
2340 *psOut = (short) fltIn;
2345 /******************************************************************************
2346 * VarI2FromR8 [OLEAUT32.51]
2348 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2350 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2352 /* Check range of value.
2354 dblIn = round( dblIn );
2355 if( dblIn < I2_MIN || dblIn > I2_MAX )
2357 return DISP_E_OVERFLOW;
2360 *psOut = (short) dblIn;
2365 /******************************************************************************
2366 * VarI2FromDate [OLEAUT32.53]
2368 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2370 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2372 /* Check range of value.
2374 dateIn = round( dateIn );
2375 if( dateIn < I2_MIN || dateIn > I2_MAX )
2377 return DISP_E_OVERFLOW;
2380 *psOut = (short) dateIn;
2385 /******************************************************************************
2386 * VarI2FromBool [OLEAUT32.56]
2388 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2390 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2392 *psOut = (short) boolIn;
2397 /******************************************************************************
2398 * VarI2FromI1 [OLEAUT32.205]
2400 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2402 TRACE("( %c, %p ), stub\n", cIn, psOut );
2404 *psOut = (short) cIn;
2409 /******************************************************************************
2410 * VarI2FromUI2 [OLEAUT32.206]
2412 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2414 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2416 /* Check range of value.
2420 return DISP_E_OVERFLOW;
2423 *psOut = (short) uiIn;
2428 /******************************************************************************
2429 * VarI2FromUI4 [OLEAUT32.207]
2431 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2433 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2435 /* Check range of value.
2437 if( ulIn < I2_MIN || ulIn > I2_MAX )
2439 return DISP_E_OVERFLOW;
2442 *psOut = (short) ulIn;
2447 /******************************************************************************
2448 * VarI2FromStr [OLEAUT32.54]
2450 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2452 double dValue = 0.0;
2453 LPSTR pNewString = NULL;
2455 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2457 /* Check if we have a valid argument
2459 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2460 RemoveCharacterFromString( pNewString, "," );
2461 if( IsValidRealString( pNewString ) == FALSE )
2463 return DISP_E_TYPEMISMATCH;
2466 /* Convert the valid string to a floating point number.
2468 dValue = atof( pNewString );
2470 /* We don't need the string anymore so free it.
2472 HeapFree( GetProcessHeap(), 0, pNewString );
2474 /* Check range of value.
2476 dValue = round( dValue );
2477 if( dValue < I2_MIN || dValue > I2_MAX )
2479 return DISP_E_OVERFLOW;
2482 *psOut = (short) dValue;
2487 /**********************************************************************
2488 * VarI2FromCy [OLEAUT32.52]
2489 * Convert currency to signed short
2491 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2492 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2494 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2500 /******************************************************************************
2501 * VarI4FromUI1 [OLEAUT32.58]
2503 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2505 TRACE("( %X, %p ), stub\n", bIn, plOut );
2507 *plOut = (LONG) bIn;
2513 /******************************************************************************
2514 * VarI4FromR4 [OLEAUT32.60]
2516 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2518 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2520 /* Check range of value.
2522 fltIn = round( fltIn );
2523 if( fltIn < I4_MIN || fltIn > I4_MAX )
2525 return DISP_E_OVERFLOW;
2528 *plOut = (LONG) fltIn;
2533 /******************************************************************************
2534 * VarI4FromR8 [OLEAUT32.61]
2536 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2538 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2540 /* Check range of value.
2542 dblIn = round( dblIn );
2543 if( dblIn < I4_MIN || dblIn > I4_MAX )
2545 return DISP_E_OVERFLOW;
2548 *plOut = (LONG) dblIn;
2553 /******************************************************************************
2554 * VarI4FromDate [OLEAUT32.63]
2556 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2558 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2560 /* Check range of value.
2562 dateIn = round( dateIn );
2563 if( dateIn < I4_MIN || dateIn > I4_MAX )
2565 return DISP_E_OVERFLOW;
2568 *plOut = (LONG) dateIn;
2573 /******************************************************************************
2574 * VarI4FromBool [OLEAUT32.66]
2576 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2578 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2580 *plOut = (LONG) boolIn;
2585 /******************************************************************************
2586 * VarI4FromI1 [OLEAUT32.209]
2588 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2590 TRACE("( %c, %p ), stub\n", cIn, plOut );
2592 *plOut = (LONG) cIn;
2597 /******************************************************************************
2598 * VarI4FromUI2 [OLEAUT32.210]
2600 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2602 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2604 *plOut = (LONG) uiIn;
2609 /******************************************************************************
2610 * VarI4FromUI4 [OLEAUT32.211]
2612 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2614 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2616 /* Check range of value.
2618 if( ulIn < I4_MIN || ulIn > I4_MAX )
2620 return DISP_E_OVERFLOW;
2623 *plOut = (LONG) ulIn;
2628 /******************************************************************************
2629 * VarI4FromI2 [OLEAUT32.59]
2631 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2633 TRACE("( %d, %p ), stub\n", sIn, plOut );
2635 *plOut = (LONG) sIn;
2640 /******************************************************************************
2641 * VarI4FromStr [OLEAUT32.64]
2643 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2645 double dValue = 0.0;
2646 LPSTR pNewString = NULL;
2648 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2650 /* Check if we have a valid argument
2652 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2653 RemoveCharacterFromString( pNewString, "," );
2654 if( IsValidRealString( pNewString ) == FALSE )
2656 return DISP_E_TYPEMISMATCH;
2659 /* Convert the valid string to a floating point number.
2661 dValue = atof( pNewString );
2663 /* We don't need the string anymore so free it.
2665 HeapFree( GetProcessHeap(), 0, pNewString );
2667 /* Check range of value.
2669 dValue = round( dValue );
2670 if( dValue < I4_MIN || dValue > I4_MAX )
2672 return DISP_E_OVERFLOW;
2675 *plOut = (LONG) dValue;
2680 /**********************************************************************
2681 * VarI4FromCy [OLEAUT32.62]
2682 * Convert currency to signed long
2684 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2685 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2687 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2693 /******************************************************************************
2694 * VarR4FromUI1 [OLEAUT32.68]
2696 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2698 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2700 *pfltOut = (FLOAT) bIn;
2705 /******************************************************************************
2706 * VarR4FromI2 [OLEAUT32.69]
2708 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2710 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2712 *pfltOut = (FLOAT) sIn;
2717 /******************************************************************************
2718 * VarR4FromI4 [OLEAUT32.70]
2720 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2722 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2724 *pfltOut = (FLOAT) lIn;
2729 /******************************************************************************
2730 * VarR4FromR8 [OLEAUT32.71]
2732 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2734 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2736 /* Check range of value.
2738 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2740 return DISP_E_OVERFLOW;
2743 *pfltOut = (FLOAT) dblIn;
2748 /******************************************************************************
2749 * VarR4FromDate [OLEAUT32.73]
2751 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2753 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2755 /* Check range of value.
2757 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2759 return DISP_E_OVERFLOW;
2762 *pfltOut = (FLOAT) dateIn;
2767 /******************************************************************************
2768 * VarR4FromBool [OLEAUT32.76]
2770 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2772 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2774 *pfltOut = (FLOAT) boolIn;
2779 /******************************************************************************
2780 * VarR4FromI1 [OLEAUT32.213]
2782 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2784 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2786 *pfltOut = (FLOAT) cIn;
2791 /******************************************************************************
2792 * VarR4FromUI2 [OLEAUT32.214]
2794 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2796 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2798 *pfltOut = (FLOAT) uiIn;
2803 /******************************************************************************
2804 * VarR4FromUI4 [OLEAUT32.215]
2806 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2808 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2810 *pfltOut = (FLOAT) ulIn;
2815 /******************************************************************************
2816 * VarR4FromStr [OLEAUT32.74]
2818 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2820 double dValue = 0.0;
2821 LPSTR pNewString = NULL;
2823 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2825 /* Check if we have a valid argument
2827 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2828 RemoveCharacterFromString( pNewString, "," );
2829 if( IsValidRealString( pNewString ) == FALSE )
2831 return DISP_E_TYPEMISMATCH;
2834 /* Convert the valid string to a floating point number.
2836 dValue = atof( pNewString );
2838 /* We don't need the string anymore so free it.
2840 HeapFree( GetProcessHeap(), 0, pNewString );
2842 /* Check range of value.
2844 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2846 return DISP_E_OVERFLOW;
2849 *pfltOut = (FLOAT) dValue;
2854 /**********************************************************************
2855 * VarR4FromCy [OLEAUT32.72]
2856 * Convert currency to float
2858 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2859 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2864 /******************************************************************************
2865 * VarR8FromUI1 [OLEAUT32.78]
2867 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2869 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2871 *pdblOut = (double) bIn;
2876 /******************************************************************************
2877 * VarR8FromI2 [OLEAUT32.79]
2879 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2881 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2883 *pdblOut = (double) sIn;
2888 /******************************************************************************
2889 * VarR8FromI4 [OLEAUT32.80]
2891 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2893 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2895 *pdblOut = (double) lIn;
2900 /******************************************************************************
2901 * VarR8FromR4 [OLEAUT32.81]
2903 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2905 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2907 *pdblOut = (double) fltIn;
2912 /******************************************************************************
2913 * VarR8FromDate [OLEAUT32.83]
2915 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2917 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2919 *pdblOut = (double) dateIn;
2924 /******************************************************************************
2925 * VarR8FromBool [OLEAUT32.86]
2927 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2929 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2931 *pdblOut = (double) boolIn;
2936 /******************************************************************************
2937 * VarR8FromI1 [OLEAUT32.217]
2939 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2941 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2943 *pdblOut = (double) cIn;
2948 /******************************************************************************
2949 * VarR8FromUI2 [OLEAUT32.218]
2951 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2953 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2955 *pdblOut = (double) uiIn;
2960 /******************************************************************************
2961 * VarR8FromUI4 [OLEAUT32.219]
2963 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2965 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2967 *pdblOut = (double) ulIn;
2972 /******************************************************************************
2973 * VarR8FromStr [OLEAUT32.84]
2975 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2977 double dValue = 0.0;
2978 LPSTR pNewString = NULL;
2980 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2982 /* Check if we have a valid argument
2984 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2985 RemoveCharacterFromString( pNewString, "," );
2986 if( IsValidRealString( pNewString ) == FALSE )
2988 return DISP_E_TYPEMISMATCH;
2991 /* Convert the valid string to a floating point number.
2993 dValue = atof( pNewString );
2995 /* We don't need the string anymore so free it.
2997 HeapFree( GetProcessHeap(), 0, pNewString );
3004 /**********************************************************************
3005 * VarR8FromCy [OLEAUT32.82]
3006 * Convert currency to double
3008 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
3009 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3014 /******************************************************************************
3015 * VarDateFromUI1 [OLEAUT32.88]
3017 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
3019 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
3021 *pdateOut = (DATE) bIn;
3026 /******************************************************************************
3027 * VarDateFromI2 [OLEAUT32.89]
3029 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
3031 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
3033 *pdateOut = (DATE) sIn;
3038 /******************************************************************************
3039 * VarDateFromI4 [OLEAUT32.90]
3041 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
3043 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
3045 if( lIn < DATE_MIN || lIn > DATE_MAX )
3047 return DISP_E_OVERFLOW;
3050 *pdateOut = (DATE) lIn;
3055 /******************************************************************************
3056 * VarDateFromR4 [OLEAUT32.91]
3058 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3060 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3062 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3064 return DISP_E_OVERFLOW;
3067 *pdateOut = (DATE) fltIn;
3072 /******************************************************************************
3073 * VarDateFromR8 [OLEAUT32.92]
3075 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3077 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3079 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3081 return DISP_E_OVERFLOW;
3084 *pdateOut = (DATE) dblIn;
3089 /******************************************************************************
3090 * VarDateFromStr [OLEAUT32.94]
3091 * The string representing the date is composed of two parts, a date and time.
3093 * The format of the time is has follows:
3094 * hh[:mm][:ss][AM|PM]
3095 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3096 * of space and/or tab characters, which are ignored.
3098 * The formats for the date part are has follows:
3102 * January dd[,] [yy]yy
3105 * Whitespace can be inserted anywhere between these tokens.
3107 * The formats for the date and time string are has follows.
3108 * date[whitespace][time]
3109 * [time][whitespace]date
3111 * These are the only characters allowed in a string representing a date and time:
3112 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3114 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3119 memset( &TM, 0, sizeof(TM) );
3121 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3123 if( DateTimeStringToTm( strIn, dwFlags, &TM ) )
3125 if( TmToDATE( &TM, pdateOut ) == FALSE )
3132 ret = DISP_E_TYPEMISMATCH;
3139 /******************************************************************************
3140 * VarDateFromI1 [OLEAUT32.221]
3142 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3144 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3146 *pdateOut = (DATE) cIn;
3151 /******************************************************************************
3152 * VarDateFromUI2 [OLEAUT32.222]
3154 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3156 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3158 if( uiIn > DATE_MAX )
3160 return DISP_E_OVERFLOW;
3163 *pdateOut = (DATE) uiIn;
3168 /******************************************************************************
3169 * VarDateFromUI4 [OLEAUT32.223]
3171 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3173 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3175 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3177 return DISP_E_OVERFLOW;
3180 *pdateOut = (DATE) ulIn;
3185 /******************************************************************************
3186 * VarDateFromBool [OLEAUT32.96]
3188 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3190 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3192 *pdateOut = (DATE) boolIn;
3197 /**********************************************************************
3198 * VarDateFromCy [OLEAUT32.93]
3199 * Convert currency to date
3201 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3202 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3204 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3208 /******************************************************************************
3209 * VarBstrFromUI1 [OLEAUT32.108]
3211 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3213 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3214 sprintf( pBuffer, "%d", bVal );
3216 *pbstrOut = StringDupAtoBstr( pBuffer );
3221 /******************************************************************************
3222 * VarBstrFromI2 [OLEAUT32.109]
3224 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3226 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3227 sprintf( pBuffer, "%d", iVal );
3228 *pbstrOut = StringDupAtoBstr( pBuffer );
3233 /******************************************************************************
3234 * VarBstrFromI4 [OLEAUT32.110]
3236 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3238 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3240 sprintf( pBuffer, "%ld", lIn );
3241 *pbstrOut = StringDupAtoBstr( pBuffer );
3246 /******************************************************************************
3247 * VarBstrFromR4 [OLEAUT32.111]
3249 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3251 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3253 sprintf( pBuffer, "%.7g", fltIn );
3254 *pbstrOut = StringDupAtoBstr( pBuffer );
3259 /******************************************************************************
3260 * VarBstrFromR8 [OLEAUT32.112]
3262 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3264 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3266 sprintf( pBuffer, "%.15g", dblIn );
3267 *pbstrOut = StringDupAtoBstr( pBuffer );
3272 /******************************************************************************
3273 * VarBstrFromCy [OLEAUT32.113]
3275 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3276 FIXME("([cyIn], %08lx, %08lx, %p), stub.\n", lcid, dwFlags, pbstrOut);
3281 /******************************************************************************
3282 * VarBstrFromDate [OLEAUT32.114]
3284 * The date is implemented using an 8 byte floating-point number.
3285 * Days are represented by whole numbers increments starting with 0.00 as
3286 * being December 30 1899, midnight.
3287 * The hours are expressed as the fractional part of the number.
3288 * December 30 1899 at midnight = 0.00
3289 * January 1 1900 at midnight = 2.00
3290 * January 4 1900 at 6 AM = 5.25
3291 * January 4 1900 at noon = 5.50
3292 * December 29 1899 at midnight = -1.00
3293 * December 18 1899 at midnight = -12.00
3294 * December 18 1899 at 6AM = -12.25
3295 * December 18 1899 at 6PM = -12.75
3296 * December 19 1899 at midnight = -11.00
3297 * The tm structure is as follows:
3299 * int tm_sec; seconds after the minute - [0,59]
3300 * int tm_min; minutes after the hour - [0,59]
3301 * int tm_hour; hours since midnight - [0,23]
3302 * int tm_mday; day of the month - [1,31]
3303 * int tm_mon; months since January - [0,11]
3304 * int tm_year; years
3305 * int tm_wday; days since Sunday - [0,6]
3306 * int tm_yday; days since January 1 - [0,365]
3307 * int tm_isdst; daylight savings time flag
3310 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3313 memset( &TM, 0, sizeof(TM) );
3315 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3317 if( DateToTm( dateIn, dwFlags, &TM ) == FALSE )
3319 return E_INVALIDARG;
3322 if( dwFlags & VAR_DATEVALUEONLY )
3323 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3324 else if( dwFlags & VAR_TIMEVALUEONLY )
3325 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3327 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3329 *pbstrOut = StringDupAtoBstr( pBuffer );
3334 /******************************************************************************
3335 * VarBstrFromBool [OLEAUT32.116]
3337 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3339 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3341 sprintf( pBuffer, (boolIn == VARIANT_FALSE) ? "False" : "True" );
3343 *pbstrOut = StringDupAtoBstr( pBuffer );
3348 /******************************************************************************
3349 * VarBstrFromI1 [OLEAUT32.229]
3351 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3353 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3354 sprintf( pBuffer, "%d", cIn );
3355 *pbstrOut = StringDupAtoBstr( pBuffer );
3360 /******************************************************************************
3361 * VarBstrFromUI2 [OLEAUT32.230]
3363 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3365 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3366 sprintf( pBuffer, "%d", uiIn );
3367 *pbstrOut = StringDupAtoBstr( pBuffer );
3372 /******************************************************************************
3373 * VarBstrFromUI4 [OLEAUT32.231]
3375 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3377 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3378 sprintf( pBuffer, "%ld", ulIn );
3379 *pbstrOut = StringDupAtoBstr( pBuffer );
3384 /******************************************************************************
3385 * VarBoolFromUI1 [OLEAUT32.118]
3387 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3389 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3393 *pboolOut = VARIANT_FALSE;
3397 *pboolOut = VARIANT_TRUE;
3403 /******************************************************************************
3404 * VarBoolFromI2 [OLEAUT32.119]
3406 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3408 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3410 *pboolOut = (sIn) ? VARIANT_TRUE : VARIANT_FALSE;
3415 /******************************************************************************
3416 * VarBoolFromI4 [OLEAUT32.120]
3418 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3420 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3422 *pboolOut = (lIn) ? VARIANT_TRUE : VARIANT_FALSE;
3427 /******************************************************************************
3428 * VarBoolFromR4 [OLEAUT32.121]
3430 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3432 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3434 *pboolOut = (fltIn == 0.0) ? VARIANT_FALSE : VARIANT_TRUE;
3439 /******************************************************************************
3440 * VarBoolFromR8 [OLEAUT32.122]
3442 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3444 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3446 *pboolOut = (dblIn == 0.0) ? VARIANT_FALSE : VARIANT_TRUE;
3451 /******************************************************************************
3452 * VarBoolFromDate [OLEAUT32.123]
3454 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3456 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3458 *pboolOut = (dateIn == 0.0) ? VARIANT_FALSE : VARIANT_TRUE;
3463 /******************************************************************************
3464 * VarBoolFromStr [OLEAUT32.125]
3466 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3469 char* pNewString = NULL;
3471 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3473 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3475 if( pNewString == NULL || strlen( pNewString ) == 0 )
3477 ret = DISP_E_TYPEMISMATCH;
3482 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3484 *pboolOut = VARIANT_TRUE;
3486 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3488 *pboolOut = VARIANT_FALSE;
3492 /* Try converting the string to a floating point number.
3494 double dValue = 0.0;
3495 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3498 ret = DISP_E_TYPEMISMATCH;
3501 *pboolOut = (dValue == 0.0) ?
3502 VARIANT_FALSE : VARIANT_TRUE;
3506 HeapFree( GetProcessHeap(), 0, pNewString );
3511 /******************************************************************************
3512 * VarBoolFromI1 [OLEAUT32.233]
3514 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3516 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3518 *pboolOut = (cIn == 0) ? VARIANT_FALSE : VARIANT_TRUE;
3523 /******************************************************************************
3524 * VarBoolFromUI2 [OLEAUT32.234]
3526 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3528 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3530 *pboolOut = (uiIn == 0) ? VARIANT_FALSE : VARIANT_TRUE;
3535 /******************************************************************************
3536 * VarBoolFromUI4 [OLEAUT32.235]
3538 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3540 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3542 *pboolOut = (ulIn == 0) ? VARIANT_FALSE : VARIANT_TRUE;
3547 /**********************************************************************
3548 * VarBoolFromCy [OLEAUT32.124]
3549 * Convert currency to boolean
3551 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3552 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3558 /******************************************************************************
3559 * VarI1FromUI1 [OLEAUT32.244]
3561 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3563 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3565 /* Check range of value.
3567 if( bIn > CHAR_MAX )
3569 return DISP_E_OVERFLOW;
3572 *pcOut = (CHAR) bIn;
3577 /******************************************************************************
3578 * VarI1FromI2 [OLEAUT32.245]
3580 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3582 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3584 if( uiIn > CHAR_MAX )
3586 return DISP_E_OVERFLOW;
3589 *pcOut = (CHAR) uiIn;
3594 /******************************************************************************
3595 * VarI1FromI4 [OLEAUT32.246]
3597 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3599 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3601 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3603 return DISP_E_OVERFLOW;
3606 *pcOut = (CHAR) lIn;
3611 /******************************************************************************
3612 * VarI1FromR4 [OLEAUT32.247]
3614 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3616 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3618 fltIn = round( fltIn );
3619 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3621 return DISP_E_OVERFLOW;
3624 *pcOut = (CHAR) fltIn;
3629 /******************************************************************************
3630 * VarI1FromR8 [OLEAUT32.248]
3632 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3634 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3636 dblIn = round( dblIn );
3637 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3639 return DISP_E_OVERFLOW;
3642 *pcOut = (CHAR) dblIn;
3647 /******************************************************************************
3648 * VarI1FromDate [OLEAUT32.249]
3650 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3652 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3654 dateIn = round( dateIn );
3655 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3657 return DISP_E_OVERFLOW;
3660 *pcOut = (CHAR) dateIn;
3665 /******************************************************************************
3666 * VarI1FromStr [OLEAUT32.251]
3668 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3670 double dValue = 0.0;
3671 LPSTR pNewString = NULL;
3673 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3675 /* Check if we have a valid argument
3677 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3678 RemoveCharacterFromString( pNewString, "," );
3679 if( IsValidRealString( pNewString ) == FALSE )
3681 return DISP_E_TYPEMISMATCH;
3684 /* Convert the valid string to a floating point number.
3686 dValue = atof( pNewString );
3688 /* We don't need the string anymore so free it.
3690 HeapFree( GetProcessHeap(), 0, pNewString );
3692 /* Check range of value.
3694 dValue = round( dValue );
3695 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3697 return DISP_E_OVERFLOW;
3700 *pcOut = (CHAR) dValue;
3705 /******************************************************************************
3706 * VarI1FromBool [OLEAUT32.253]
3708 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3710 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3712 *pcOut = (CHAR) boolIn;
3717 /******************************************************************************
3718 * VarI1FromUI2 [OLEAUT32.254]
3720 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3722 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3724 if( uiIn > CHAR_MAX )
3726 return DISP_E_OVERFLOW;
3729 *pcOut = (CHAR) uiIn;
3734 /******************************************************************************
3735 * VarI1FromUI4 [OLEAUT32.255]
3737 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3739 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3741 if( ulIn > CHAR_MAX )
3743 return DISP_E_OVERFLOW;
3746 *pcOut = (CHAR) ulIn;
3751 /**********************************************************************
3752 * VarI1FromCy [OLEAUT32.250]
3753 * Convert currency to signed char
3755 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3756 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3758 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3764 /******************************************************************************
3765 * VarUI2FromUI1 [OLEAUT32.257]
3767 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3769 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3771 *puiOut = (USHORT) bIn;
3776 /******************************************************************************
3777 * VarUI2FromI2 [OLEAUT32.258]
3779 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3781 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3783 if( uiIn < UI2_MIN )
3785 return DISP_E_OVERFLOW;
3788 *puiOut = (USHORT) uiIn;
3793 /******************************************************************************
3794 * VarUI2FromI4 [OLEAUT32.259]
3796 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3798 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3800 if( lIn < UI2_MIN || lIn > UI2_MAX )
3802 return DISP_E_OVERFLOW;
3805 *puiOut = (USHORT) lIn;
3810 /******************************************************************************
3811 * VarUI2FromR4 [OLEAUT32.260]
3813 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3815 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3817 fltIn = round( fltIn );
3818 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3820 return DISP_E_OVERFLOW;
3823 *puiOut = (USHORT) fltIn;
3828 /******************************************************************************
3829 * VarUI2FromR8 [OLEAUT32.261]
3831 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3833 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3835 dblIn = round( dblIn );
3836 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3838 return DISP_E_OVERFLOW;
3841 *puiOut = (USHORT) dblIn;
3846 /******************************************************************************
3847 * VarUI2FromDate [OLEAUT32.262]
3849 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3851 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3853 dateIn = round( dateIn );
3854 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3856 return DISP_E_OVERFLOW;
3859 *puiOut = (USHORT) dateIn;
3864 /******************************************************************************
3865 * VarUI2FromStr [OLEAUT32.264]
3867 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3869 double dValue = 0.0;
3870 LPSTR pNewString = NULL;
3872 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3874 /* Check if we have a valid argument
3876 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3877 RemoveCharacterFromString( pNewString, "," );
3878 if( IsValidRealString( pNewString ) == FALSE )
3880 return DISP_E_TYPEMISMATCH;
3883 /* Convert the valid string to a floating point number.
3885 dValue = atof( pNewString );
3887 /* We don't need the string anymore so free it.
3889 HeapFree( GetProcessHeap(), 0, pNewString );
3891 /* Check range of value.
3893 dValue = round( dValue );
3894 if( dValue < UI2_MIN || dValue > UI2_MAX )
3896 return DISP_E_OVERFLOW;
3899 *puiOut = (USHORT) dValue;
3904 /******************************************************************************
3905 * VarUI2FromBool [OLEAUT32.266]
3907 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3909 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3911 *puiOut = (USHORT) boolIn;
3916 /******************************************************************************
3917 * VarUI2FromI1 [OLEAUT32.267]
3919 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3921 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3923 *puiOut = (USHORT) cIn;
3928 /******************************************************************************
3929 * VarUI2FromUI4 [OLEAUT32.268]
3931 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3933 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3935 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3937 return DISP_E_OVERFLOW;
3940 *puiOut = (USHORT) ulIn;
3945 /******************************************************************************
3946 * VarUI4FromStr [OLEAUT32.277]
3948 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3950 double dValue = 0.0;
3951 LPSTR pNewString = NULL;
3953 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3955 /* Check if we have a valid argument
3957 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3958 RemoveCharacterFromString( pNewString, "," );
3959 if( IsValidRealString( pNewString ) == FALSE )
3961 return DISP_E_TYPEMISMATCH;
3964 /* Convert the valid string to a floating point number.
3966 dValue = atof( pNewString );
3968 /* We don't need the string anymore so free it.
3970 HeapFree( GetProcessHeap(), 0, pNewString );
3972 /* Check range of value.
3974 dValue = round( dValue );
3975 if( dValue < UI4_MIN || dValue > UI4_MAX )
3977 return DISP_E_OVERFLOW;
3980 *pulOut = (ULONG) dValue;
3985 /**********************************************************************
3986 * VarUI2FromCy [OLEAUT32.263]
3987 * Convert currency to unsigned short
3989 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
3990 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3992 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
3994 *pusOut = (USHORT)t;
3999 /******************************************************************************
4000 * VarUI4FromUI1 [OLEAUT32.270]
4002 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4004 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4006 *pulOut = (USHORT) bIn;
4011 /******************************************************************************
4012 * VarUI4FromI2 [OLEAUT32.271]
4014 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4016 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4018 if( uiIn < UI4_MIN )
4020 return DISP_E_OVERFLOW;
4023 *pulOut = (ULONG) uiIn;
4028 /******************************************************************************
4029 * VarUI4FromI4 [OLEAUT32.272]
4031 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4033 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4037 return DISP_E_OVERFLOW;
4040 *pulOut = (ULONG) lIn;
4045 /******************************************************************************
4046 * VarUI4FromR4 [OLEAUT32.273]
4048 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4050 fltIn = round( fltIn );
4051 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4053 return DISP_E_OVERFLOW;
4056 *pulOut = (ULONG) fltIn;
4061 /******************************************************************************
4062 * VarUI4FromR8 [OLEAUT32.274]
4064 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4066 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4068 dblIn = round( dblIn );
4069 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4071 return DISP_E_OVERFLOW;
4074 *pulOut = (ULONG) dblIn;
4079 /******************************************************************************
4080 * VarUI4FromDate [OLEAUT32.275]
4082 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4084 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4086 dateIn = round( dateIn );
4087 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4089 return DISP_E_OVERFLOW;
4092 *pulOut = (ULONG) dateIn;
4097 /******************************************************************************
4098 * VarUI4FromBool [OLEAUT32.279]
4100 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4102 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4104 *pulOut = (ULONG) boolIn;
4109 /******************************************************************************
4110 * VarUI4FromI1 [OLEAUT32.280]
4112 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4114 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4116 *pulOut = (ULONG) cIn;
4121 /******************************************************************************
4122 * VarUI4FromUI2 [OLEAUT32.281]
4124 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4126 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4128 *pulOut = (ULONG) uiIn;
4133 /**********************************************************************
4134 * VarUI4FromCy [OLEAUT32.276]
4135 * Convert currency to unsigned long
4137 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4138 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4140 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4147 /**********************************************************************
4148 * VarCyFromUI1 [OLEAUT32.98]
4149 * Convert unsigned char to currency
4151 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4153 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4158 /**********************************************************************
4159 * VarCyFromI2 [OLEAUT32.99]
4160 * Convert signed short to currency
4162 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4163 if (sIn < 0) pcyOut->s.Hi = -1;
4164 else pcyOut->s.Hi = 0;
4165 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4170 /**********************************************************************
4171 * VarCyFromI4 [OLEAUT32.100]
4172 * Convert signed long to currency
4174 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4175 double t = (double)lIn * (double)10000;
4176 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4177 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4178 if (lIn < 0) pcyOut->s.Hi--;
4183 /**********************************************************************
4184 * VarCyFromR4 [OLEAUT32.101]
4185 * Convert float to currency
4187 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4188 double t = round((double)fltIn * (double)10000);
4189 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4190 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4191 if (fltIn < 0) pcyOut->s.Hi--;
4196 /**********************************************************************
4197 * VarCyFromR8 [OLEAUT32.102]
4198 * Convert double to currency
4200 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4201 double t = round(dblIn * (double)10000);
4202 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4203 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4204 if (dblIn < 0) pcyOut->s.Hi--;
4209 /**********************************************************************
4210 * VarCyFromDate [OLEAUT32.103]
4211 * Convert date to currency
4213 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4214 double t = round((double)dateIn * (double)10000);
4215 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4216 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4217 if (dateIn < 0) pcyOut->s.Hi--;
4222 /**********************************************************************
4223 * VarCyFromStr [OLEAUT32.104]
4225 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4226 FIXME("(%p, %08lx, %08lx, %p), stub.\n", strIn, lcid, dwFlags, pcyOut);
4231 /**********************************************************************
4232 * VarCyFromBool [OLEAUT32.106]
4233 * Convert boolean to currency
4235 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4236 if (boolIn < 0) pcyOut->s.Hi = -1;
4237 else pcyOut->s.Hi = 0;
4238 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4243 /**********************************************************************
4244 * VarCyFromI1 [OLEAUT32.225]
4245 * Convert signed char to currency
4247 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pcyOut) {
4248 if (cIn < 0) pcyOut->s.Hi = -1;
4249 else pcyOut->s.Hi = 0;
4250 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4255 /**********************************************************************
4256 * VarCyFromUI2 [OLEAUT32.226]
4257 * Convert unsigned short to currency
4259 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4261 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4266 /**********************************************************************
4267 * VarCyFromUI4 [OLEAUT32.227]
4268 * Convert unsigned long to currency
4270 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4271 double t = (double)ulIn * (double)10000;
4272 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4273 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4279 /**********************************************************************
4280 * DosDateTimeToVariantTime [OLEAUT32.14]
4281 * Convert dos representation of time to the date and time representation
4282 * stored in a variant.
4284 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4289 TRACE("( 0x%x, 0x%x, %p ), stub\n", wDosDate, wDosTime, pvtime );
4291 t.tm_sec = (wDosTime & 0x001f) * 2;
4292 t.tm_min = (wDosTime & 0x07e0) >> 5;
4293 t.tm_hour = (wDosTime & 0xf800) >> 11;
4295 t.tm_mday = (wDosDate & 0x001f);
4296 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4297 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4299 return TmToDATE( &t, pvtime );
4303 /**********************************************************************
4304 * VarParseNumFromStr [OLEAUT32.46]
4306 HRESULT WINAPI VarParseNumFromStr(OLECHAR * strIn, LCID lcid, ULONG dwFlags,
4307 NUMPARSE * pnumprs, BYTE * rgbDig)
4311 FIXME("(%s,flags=%lx,....), partial stub!\n",debugstr_w(strIn),dwFlags);
4312 FIXME("numparse: cDig=%d, InFlags=%lx\n",pnumprs->cDig,pnumprs->dwInFlags);
4314 /* The other struct components are to be set by us */
4316 memset(rgbDig,0,pnumprs->cDig);
4319 for (i=0; strIn[i] ;i++) {
4320 if ((strIn[i]>='0') && (strIn[i]<='9')) {
4321 if (pnumprs->cDig > cDig) {
4322 *(rgbDig++)=strIn[i]-'0';
4328 pnumprs->cDig = cDig;
4330 /* FIXME: Just patching some values in */
4331 pnumprs->nPwr10 = 0;
4332 pnumprs->nBaseShift = 0;
4333 pnumprs->cchUsed = lastent;
4334 pnumprs->dwOutFlags = NUMPRS_DECIMAL;
4339 /**********************************************************************
4340 * VarNumFromParseNum [OLEAUT32.47]
4342 HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig,
4343 ULONG dwVtBits, VARIANT * pvar)
4347 FIXME("(,dwVtBits=%lx,....), partial stub!\n",dwVtBits);
4350 for (i=0;i<pnumprs->cDig;i++)
4351 xint = xint*10 + rgbDig[i];
4354 if (dwVtBits & VTBIT_I4) {
4356 V_UNION(pvar,intVal) = xint;
4359 if (dwVtBits & VTBIT_R8) {
4361 V_UNION(pvar,dblVal) = xint;
4364 FIXME("vtbitmask is unsupported %lx\n",dwVtBits);
4370 /**********************************************************************
4371 * VariantTimeToDosDateTime [OLEAUT32.13]
4372 * Convert variant representation of time to the date and time representation
4375 INT WINAPI VariantTimeToDosDateTime(DATE pvtime, USHORT *wDosDate, USHORT *wDosTime)
4381 TRACE("( 0x%x, 0x%x, %p ), stub\n", *wDosDate, *wDosTime, &pvtime );
4383 if (DateToTm(pvtime, 0, &t) < 0) return 0;
4385 *wDosTime = *wDosTime | (t.tm_sec / 2);
4386 *wDosTime = *wDosTime | (t.tm_min << 5);
4387 *wDosTime = *wDosTime | (t.tm_hour << 11);
4389 *wDosDate = *wDosDate | t.tm_mday ;
4390 *wDosDate = *wDosDate | t.tm_mon << 5;
4391 *wDosDate = *wDosDate | ((t.tm_year - 1980) << 9) ;
4397 /***********************************************************************
4398 * SystemTimeToVariantTime [OLEAUT32.184]
4400 HRESULT WINAPI SystemTimeToVariantTime( LPSYSTEMTIME lpSystemTime, double *pvtime )
4402 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4403 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4407 TRACE(" %d/%d/%d %d:%d:%d\n",
4408 lpSystemTime->wMonth, lpSystemTime->wDay,
4409 lpSystemTime->wYear, lpSystemTime->wHour,
4410 lpSystemTime->wMinute, lpSystemTime->wSecond);
4412 if (lpSystemTime->wYear >= 1900)
4414 t.tm_sec = lpSystemTime->wSecond;
4415 t.tm_min = lpSystemTime->wMinute;
4416 t.tm_hour = lpSystemTime->wHour;
4418 t.tm_mday = lpSystemTime->wDay;
4419 t.tm_mon = lpSystemTime->wMonth;
4420 t.tm_year = lpSystemTime->wYear;
4422 return TmToDATE( &t, pvtime );
4426 t.tm_sec = lpSystemTime->wSecond;
4427 t.tm_min = lpSystemTime->wMinute;
4428 t.tm_hour = lpSystemTime->wHour;
4430 if (isleap(lpSystemTime->wYear) )
4431 t.tm_mday = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4433 t.tm_mday = Days_Per_Month[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4435 t.tm_mon = 13 - lpSystemTime->wMonth;
4436 t.tm_year = 1900 + 1899 - lpSystemTime->wYear;
4438 TmToDATE( &t, pvtime );
4448 /***********************************************************************
4449 * VariantTimeToSystemTime [OLEAUT32.185]
4451 HRESULT WINAPI VariantTimeToSystemTime( double vtime, LPSYSTEMTIME lpSystemTime )
4453 double t = 0, timeofday = 0;
4455 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4456 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4458 /* The Month_Code is used to find the Day of the Week (LY = LeapYear)*/
4459 static const BYTE Month_Code[] = {0, 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4460 static const BYTE Month_Code_LY[] = {0, 0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4462 /* The Century_Code is used to find the Day of the Week */
4463 static const BYTE Century_Code[] = {0, 6, 4, 2};
4467 TRACE(" Variant = %f SYSTEMTIME ptr %p\n", vtime, lpSystemTime);
4472 if (DateToTm(vtime, 0, &r ) <= 0) return 0;
4474 lpSystemTime->wSecond = r.tm_sec;
4475 lpSystemTime->wMinute = r.tm_min;
4476 lpSystemTime->wHour = r.tm_hour;
4477 lpSystemTime->wDay = r.tm_mday;
4478 lpSystemTime->wMonth = r.tm_mon;
4480 if (lpSystemTime->wMonth == 12)
4481 lpSystemTime->wMonth = 1;
4483 lpSystemTime->wMonth++;
4485 lpSystemTime->wYear = r.tm_year;
4491 if (DateToTm(vtime, 0, &r ) <= 0) return 0;
4493 lpSystemTime->wSecond = r.tm_sec;
4494 lpSystemTime->wMinute = r.tm_min;
4495 lpSystemTime->wHour = r.tm_hour;
4497 lpSystemTime->wMonth = 13 - r.tm_mon;
4499 if (lpSystemTime->wMonth == 1)
4500 lpSystemTime->wMonth = 12;
4502 lpSystemTime->wMonth--;
4504 lpSystemTime->wYear = 1899 - (r.tm_year - 1900);
4506 if (!isleap(lpSystemTime->wYear) )
4507 lpSystemTime->wDay = Days_Per_Month[13 - lpSystemTime->wMonth] - r.tm_mday;
4509 lpSystemTime->wDay = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - r.tm_mday;
4514 if (!isleap(lpSystemTime->wYear))
4517 (Century_Code+Month_Code+Year_Code+Day) % 7
4519 The century code repeats every 400 years , so the array
4520 works out like this,
4522 Century_Code[0] is for 16th/20th Centry
4523 Century_Code[1] is for 17th/21th Centry
4524 Century_Code[2] is for 18th/22th Centry
4525 Century_Code[3] is for 19th/23th Centry
4527 The year code is found with the formula (year + (year / 4))
4528 the "year" must be between 0 and 99 .
4530 The Month Code (Month_Code[1]) starts with January and
4534 lpSystemTime->wDayOfWeek = (
4535 Century_Code[(( (lpSystemTime->wYear+100) - lpSystemTime->wYear%100) /100) %4]+
4536 ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4537 Month_Code[lpSystemTime->wMonth]+
4538 lpSystemTime->wDay) % 7;
4540 if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4541 else lpSystemTime->wDayOfWeek -= 1;
4545 lpSystemTime->wDayOfWeek = (
4546 Century_Code[(((lpSystemTime->wYear+100) - lpSystemTime->wYear%100)/100)%4]+
4547 ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4548 Month_Code_LY[lpSystemTime->wMonth]+
4549 lpSystemTime->wDay) % 7;
4551 if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4552 else lpSystemTime->wDayOfWeek -= 1;
4556 timeofday = vtime - t;
4558 lpSystemTime->wMilliseconds = (timeofday
4559 - lpSystemTime->wHour*(1/24)
4560 - lpSystemTime->wMinute*(1/1440)
4561 - lpSystemTime->wSecond*(1/86400) )*(1/5184000);
4566 /***********************************************************************
4567 * VarUdateFromDate [OLEAUT32.331]
4569 HRESULT WINAPI VarUdateFromDate( DATE datein, ULONG dwFlags, UDATE *pudateout)
4572 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4573 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4575 TRACE("DATE = %f\n", (double)datein);
4576 i = VariantTimeToSystemTime(datein, &(pudateout->st) );
4580 pudateout->wDayOfYear = 0;
4582 if (isleap(pudateout->st.wYear))
4584 for (i =1; i<pudateout->st.wMonth; i++)
4585 pudateout->wDayOfYear += Days_Per_Month[i];
4589 for (i =1; i<pudateout->st.wMonth; i++)
4590 pudateout->wDayOfYear += Days_Per_Month_LY[i];
4593 pudateout->wDayOfYear += pudateout->st.wDay;
4594 dwFlags = 0; /*VAR_VALIDDATE*/
4601 /***********************************************************************
4602 * VarDateFromUdate [OLEAUT32.330]
4604 HRESULT WINAPI VarDateFromUdate(UDATE *pudateout,
4605 ULONG dwFlags, DATE *datein)
4609 TRACE(" %d/%d/%d %d:%d:%d\n",
4610 pudateout->st.wMonth, pudateout->st.wDay,
4611 pudateout->st.wYear, pudateout->st.wHour,
4612 pudateout->st.wMinute, pudateout->st.wSecond);
4615 i = SystemTimeToVariantTime(&(pudateout->st), &t);
4618 if (i) dwFlags = 0; /*VAR_VALIDDATE*/
4625 /**********************************************************************
4626 * VarBstrCmp [OLEAUT32.440]
4629 * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS
4630 * NORM_IGNORESTRINGWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA
4633 HRESULT WINAPI VarBstrCmp(BSTR left, BSTR right, LCID lcid, DWORD flags)
4637 FIXME("( %s %s %ld %lx ) partial stub\n", debugstr_w(left), debugstr_w(right), lcid, flags);
4639 if((!left) || (!right))
4642 if(flags&NORM_IGNORECASE)
4643 r = lstrcmpiW(left,right);
4645 r = lstrcmpW(left,right);
4655 /**********************************************************************
4656 * VarBstrCat [OLEAUT32.439]
4658 HRESULT WINAPI VarBstrCat(BSTR left, BSTR right, BSTR *out)
4662 TRACE("( %s %s %p )\n", debugstr_w(left), debugstr_w(right), out);
4664 if( (!left) || (!right) || (!out) )
4667 result = SysAllocStringLen(left, lstrlenW(left)+lstrlenW(right));
4668 lstrcatW(result,right);
4675 /**********************************************************************
4676 * VarCat [OLEAUT32.441]
4678 HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
4680 /* Should we VariantClear out? */
4681 /* Can we handle array, vector, by ref etc. */
4682 if ((V_VT(left)&VT_TYPEMASK) == VT_NULL &&
4683 (V_VT(right)&VT_TYPEMASK) == VT_NULL)
4685 V_VT(out) = VT_NULL;
4688 else if (V_VT(left) == VT_BSTR && V_VT(right) == VT_BSTR)
4690 V_VT(out) = VT_BSTR;
4691 VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out));
4695 FIXME ("types not supported\n");