4 * Copyright 1998 Jean-Claude Cote
7 * This implements the low-level and hi-level APIs for manipulating VARIANTs.
8 * The low-level APIs are used to do data coercion between different data types.
9 * The hi-level APIs are built on top of these low-level APIs and handle
10 * initialization, copying, destroying and changing the type of VARIANTs.
13 * - The Variant APIs do not support international languages, currency
14 * types, number formating and calendar. They only support U.S. English format.
15 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
16 * The prototypes for these are commented out in the oleauto.h file. They need
17 * to be implemented and cases need to be added to the switches of the existing APIs.
18 * - The parsing of date for the VarDateFromStr is not complete.
19 * - The date manipulations do not support dates prior to 1900.
20 * - The parsing does not accept as many formats as the Windows implementation.
38 #include "debugtools.h"
42 DEFAULT_DEBUG_CHANNEL(ole);
46 # define FLT_MAX MAXFLOAT
48 # error "Can't find #define for MAXFLOAT/FLT_MAX"
54 static const char CHAR_MAX = 127;
55 static const char CHAR_MIN = -128;
56 static const BYTE UI1_MAX = 255;
57 static const BYTE UI1_MIN = 0;
58 static const unsigned short UI2_MAX = 65535;
59 static const unsigned short UI2_MIN = 0;
60 static const short I2_MAX = 32767;
61 static const short I2_MIN = -32768;
62 static const unsigned long UI4_MAX = 4294967295U;
63 static const unsigned long UI4_MIN = 0;
64 static const long I4_MAX = 2147483647;
65 static const long I4_MIN = -(2147483648U);
66 static const DATE DATE_MIN = -657434;
67 static const DATE DATE_MAX = 2958465;
70 /* This mask is used to set a flag in wReserved1 of
71 * the VARIANTARG structure. The flag indicates if
72 * the API function is using an inner variant or not.
74 #define PROCESSING_INNER_VARIANT 0x0001
76 /* General use buffer.
78 #define BUFFER_MAX 1024
79 static char pBuffer[BUFFER_MAX];
82 * Note a leap year is one that is a multiple of 4
83 * but not of a 100. Except if it is a multiple of
84 * 400 then it is a leap year.
86 /* According to postgeSQL date parsing functions there is
87 * a leap year when this expression is true.
88 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
89 * So according to this there is 365.2515 days in one year.
90 * One + every four years: 1/4 -> 365.25
91 * One - every 100 years: 1/100 -> 365.01
92 * One + every 400 years: 1/400 -> 365.0025
94 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
96 * ^^ Might this be the key to an easy way to factor large prime numbers?
97 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
99 static const double DAYS_IN_ONE_YEAR = 365.2425;
101 /******************************************************************************
102 * DateTimeStringToTm [INTERNAL]
104 * Converts a string representation of a date and/or time to a tm structure.
106 * Note this function uses the postgresql date parsing functions found
107 * in the parsedt.c file.
109 * Returns TRUE if successful.
111 * Note: This function does not parse the day of the week,
112 * daylight savings time. It will only fill the followin fields in
113 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
115 ******************************************************************************/
116 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
123 char *field[MAXDATEFIELDS];
124 int ftype[MAXDATEFIELDS];
125 char lowstr[MAXDATELEN + 1];
126 char* strDateTime = NULL;
128 /* Convert the string to ASCII since this is the only format
129 * postgesql can handle.
131 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
133 if( strDateTime != NULL )
135 /* Make sure we don't go over the maximum length
136 * accepted by postgesql.
138 if( strlen( strDateTime ) <= MAXDATELEN )
140 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
142 if( lcid & VAR_DATEVALUEONLY )
144 /* Get the date information.
145 * It returns 0 if date information was
146 * present and 1 if only time information was present.
147 * -1 if an error occures.
149 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
151 /* Eliminate the time information since we
152 * were asked to get date information only.
160 if( lcid & VAR_TIMEVALUEONLY )
162 /* Get time information only.
164 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
171 /* Get both date and time information.
172 * It returns 0 if date information was
173 * present and 1 if only time information was present.
174 * -1 if an error occures.
176 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
183 HeapFree( GetProcessHeap(), 0, strDateTime );
194 /******************************************************************************
195 * TmToDATE [INTERNAL]
197 * The date is implemented using an 8 byte floating-point number.
198 * Days are represented by whole numbers increments starting with 0.00 has
199 * being December 30 1899, midnight.
200 * The hours are expressed as the fractional part of the number.
201 * December 30 1899 at midnight = 0.00
202 * January 1 1900 at midnight = 2.00
203 * January 4 1900 at 6 AM = 5.25
204 * January 4 1900 at noon = 5.50
205 * December 29 1899 at midnight = -1.00
206 * December 18 1899 at midnight = -12.00
207 * December 18 1899 at 6AM = -12.25
208 * December 18 1899 at 6PM = -12.75
209 * December 19 1899 at midnight = -11.00
210 * The tm structure is as follows:
212 * int tm_sec; seconds after the minute - [0,59]
213 * int tm_min; minutes after the hour - [0,59]
214 * int tm_hour; hours since midnight - [0,23]
215 * int tm_mday; day of the month - [1,31]
216 * int tm_mon; months since January - [0,11]
218 * int tm_wday; days since Sunday - [0,6]
219 * int tm_yday; days since January 1 - [0,365]
220 * int tm_isdst; daylight savings time flag
223 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
224 * and tm_isdst fields of the tm structure. And only converts years
227 * Returns TRUE if successful.
229 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
231 if( (pTm->tm_year - 1900) >= 0 )
235 /* Start at 1. This is the way DATE is defined.
236 * January 1, 1900 at Midnight is 1.00.
237 * January 1, 1900 at 6AM is 1.25.
242 /* Add the number of days corresponding to
245 *pDateOut += (pTm->tm_year - 1900) * 365;
247 /* Add the leap days in the previous years between now and 1900.
248 * Note a leap year is one that is a multiple of 4
249 * but not of a 100. Except if it is a multiple of
250 * 400 then it is a leap year.
252 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
253 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
254 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
256 /* Set the leap year flag if the
257 * current year specified by tm_year is a
258 * leap year. This will be used to add a day
261 if( isleap( pTm->tm_year ) )
264 /* Add the number of days corresponding to
267 switch( pTm->tm_mon )
273 *pDateOut += ( 59 + leapYear );
276 *pDateOut += ( 90 + leapYear );
279 *pDateOut += ( 120 + leapYear );
282 *pDateOut += ( 151 + leapYear );
285 *pDateOut += ( 181 + leapYear );
288 *pDateOut += ( 212 + leapYear );
291 *pDateOut += ( 243 + leapYear );
294 *pDateOut += ( 273 + leapYear );
297 *pDateOut += ( 304 + leapYear );
300 *pDateOut += ( 334 + leapYear );
303 /* Add the number of days in this month.
305 *pDateOut += pTm->tm_mday;
307 /* Add the number of seconds, minutes, and hours
308 * to the DATE. Note these are the fracionnal part
309 * of the DATE so seconds / number of seconds in a day.
311 *pDateOut += pTm->tm_hour / 24.0;
312 *pDateOut += pTm->tm_min / 1440.0;
313 *pDateOut += pTm->tm_sec / 86400.0;
319 /******************************************************************************
320 * DateToTm [INTERNAL]
322 * This function converts a windows DATE to a tm structure.
324 * It does not fill all the fields of the tm structure.
325 * Here is a list of the fields that are filled:
326 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
328 * Note this function does not support dates before the January 1, 1900
329 * or ( dateIn < 2.0 ).
331 * Returns TRUE if successful.
333 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
335 /* Do not process dates smaller than January 1, 1900.
336 * Which corresponds to 2.0 in the windows DATE format.
340 double decimalPart = 0.0;
341 double wholePart = 0.0;
343 memset(pTm,0,sizeof(*pTm));
345 /* Because of the nature of DATE format which
346 * associates 2.0 to January 1, 1900. We will
347 * remove 1.0 from the whole part of the DATE
348 * so that in the following code 1.0
349 * will correspond to January 1, 1900.
350 * This simplifies the processing of the DATE value.
354 wholePart = (double) floor( dateIn );
355 decimalPart = fmod( dateIn, wholePart );
357 if( !(lcid & VAR_TIMEVALUEONLY) )
361 double yearsSince1900 = 0;
362 /* Start at 1900, this is where the DATE time 0.0 starts.
365 /* find in what year the day in the "wholePart" falls into.
366 * add the value to the year field.
368 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
369 pTm->tm_year += yearsSince1900;
370 /* determine if this is a leap year.
372 if( isleap( pTm->tm_year ) )
378 /* find what day of that year the "wholePart" corresponds to.
379 * Note: nDay is in [1-366] format
381 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
382 /* Set the tm_yday value.
383 * Note: The day must be converted from [1-366] to [0-365]
385 /*pTm->tm_yday = nDay - 1;*/
386 /* find which month this day corresponds to.
393 else if( nDay <= ( 59 + leapYear ) )
395 pTm->tm_mday = nDay - 31;
398 else if( nDay <= ( 90 + leapYear ) )
400 pTm->tm_mday = nDay - ( 59 + leapYear );
403 else if( nDay <= ( 120 + leapYear ) )
405 pTm->tm_mday = nDay - ( 90 + leapYear );
408 else if( nDay <= ( 151 + leapYear ) )
410 pTm->tm_mday = nDay - ( 120 + leapYear );
413 else if( nDay <= ( 181 + leapYear ) )
415 pTm->tm_mday = nDay - ( 151 + leapYear );
418 else if( nDay <= ( 212 + leapYear ) )
420 pTm->tm_mday = nDay - ( 181 + leapYear );
423 else if( nDay <= ( 243 + leapYear ) )
425 pTm->tm_mday = nDay - ( 212 + leapYear );
428 else if( nDay <= ( 273 + leapYear ) )
430 pTm->tm_mday = nDay - ( 243 + leapYear );
433 else if( nDay <= ( 304 + leapYear ) )
435 pTm->tm_mday = nDay - ( 273 + leapYear );
438 else if( nDay <= ( 334 + leapYear ) )
440 pTm->tm_mday = nDay - ( 304 + leapYear );
443 else if( nDay <= ( 365 + leapYear ) )
445 pTm->tm_mday = nDay - ( 334 + leapYear );
449 if( !(lcid & VAR_DATEVALUEONLY) )
451 /* find the number of seconds in this day.
452 * fractional part times, hours, minutes, seconds.
454 pTm->tm_hour = (int) ( decimalPart * 24 );
455 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
456 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
465 /******************************************************************************
466 * SizeOfVariantData [INTERNAL]
468 * This function finds the size of the data referenced by a Variant based
469 * the type "vt" of the Variant.
471 static int SizeOfVariantData( VARIANT* parg )
474 switch( parg->vt & VT_TYPEMASK )
477 size = sizeof(short);
489 size = sizeof(unsigned short);
492 size = sizeof(unsigned int);
495 size = sizeof(unsigned long);
498 size = sizeof(float);
501 size = sizeof(double);
507 size = sizeof(VARIANT_BOOL);
510 size = sizeof(void*);
517 FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
523 /******************************************************************************
524 * StringDupAtoBstr [INTERNAL]
527 static BSTR StringDupAtoBstr( char* strIn )
530 OLECHAR* pNewString = NULL;
531 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
532 bstr = SysAllocString( pNewString );
533 HeapFree( GetProcessHeap(), 0, pNewString );
537 /******************************************************************************
540 * Round the double value to the nearest integer value.
542 static double round( double d )
544 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
545 BOOL bEvenNumber = FALSE;
548 /* Save the sign of the number
550 nSign = (d >= 0.0) ? 1 : -1;
553 /* Remove the decimals.
555 integerValue = floor( d );
557 /* Set the Even flag. This is used to round the number when
558 * the decimals are exactly 1/2. If the integer part is
559 * odd the number is rounded up. If the integer part
560 * is even the number is rounded down. Using this method
561 * numbers are rounded up|down half the time.
563 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
565 /* Remove the integral part of the number.
567 decimals = d - integerValue;
569 /* Note: Ceil returns the smallest integer that is greater that x.
570 * and floor returns the largest integer that is less than or equal to x.
574 /* If the decimal part is greater than 1/2
576 roundedValue = ceil( d );
578 else if( decimals < 0.5 )
580 /* If the decimal part is smaller than 1/2
582 roundedValue = floor( d );
586 /* the decimals are exactly 1/2 so round according to
587 * the bEvenNumber flag.
591 roundedValue = floor( d );
595 roundedValue = ceil( d );
599 return roundedValue * nSign;
602 /******************************************************************************
603 * RemoveCharacterFromString [INTERNAL]
605 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
607 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
609 LPSTR pNewString = NULL;
610 LPSTR strToken = NULL;
613 /* Check if we have a valid argument
617 pNewString = strdup( str );
619 strToken = strtok( pNewString, strOfCharToRemove );
620 while( strToken != NULL ) {
621 strcat( str, strToken );
622 strToken = strtok( NULL, strOfCharToRemove );
629 /******************************************************************************
630 * GetValidRealString [INTERNAL]
632 * Checks if the string is of proper format to be converted to a real value.
634 static BOOL IsValidRealString( LPSTR strRealString )
636 /* Real values that have a decimal point are required to either have
637 * digits before or after the decimal point. We will assume that
638 * we do not have any digits at either position. If we do encounter
639 * some we will disable this flag.
641 BOOL bDigitsRequired = TRUE;
642 /* Processed fields in the string representation of the real number.
644 BOOL bWhiteSpaceProcessed = FALSE;
645 BOOL bFirstSignProcessed = FALSE;
646 BOOL bFirstDigitsProcessed = FALSE;
647 BOOL bDecimalPointProcessed = FALSE;
648 BOOL bSecondDigitsProcessed = FALSE;
649 BOOL bExponentProcessed = FALSE;
650 BOOL bSecondSignProcessed = FALSE;
651 BOOL bThirdDigitsProcessed = FALSE;
652 /* Assume string parameter "strRealString" is valid and try to disprove it.
654 BOOL bValidRealString = TRUE;
656 /* Used to count the number of tokens in the "strRealString".
658 LPSTR strToken = NULL;
662 /* Check if we have a valid argument
664 if( strRealString == NULL )
666 bValidRealString = FALSE;
669 if( bValidRealString == TRUE )
671 /* Make sure we only have ONE token in the string.
673 strToken = strtok( strRealString, " " );
674 while( strToken != NULL ) {
676 strToken = strtok( NULL, " " );
681 bValidRealString = FALSE;
686 /* Make sure this token contains only valid characters.
687 * The string argument to atof has the following form:
688 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
689 * Whitespace consists of space and|or <TAB> characters, which are ignored.
690 * Sign is either plus '+' or minus '-'.
691 * Digits are one or more decimal digits.
692 * Note: If no digits appear before the decimal point, at least one must
693 * appear after the decimal point.
694 * The decimal digits may be followed by an exponent.
695 * An Exponent consists of an introductory letter ( D, d, E, or e) and
696 * an optionally signed decimal integer.
698 pChar = strRealString;
699 while( bValidRealString == TRUE && *pChar != '\0' )
707 if( bWhiteSpaceProcessed ||
708 bFirstSignProcessed ||
709 bFirstDigitsProcessed ||
710 bDecimalPointProcessed ||
711 bSecondDigitsProcessed ||
712 bExponentProcessed ||
713 bSecondSignProcessed ||
714 bThirdDigitsProcessed )
716 bValidRealString = FALSE;
723 if( bFirstSignProcessed == FALSE )
725 if( bFirstDigitsProcessed ||
726 bDecimalPointProcessed ||
727 bSecondDigitsProcessed ||
728 bExponentProcessed ||
729 bSecondSignProcessed ||
730 bThirdDigitsProcessed )
732 bValidRealString = FALSE;
734 bWhiteSpaceProcessed = TRUE;
735 bFirstSignProcessed = TRUE;
737 else if( bSecondSignProcessed == FALSE )
739 /* Note: The exponent must be present in
740 * order to accept the second sign...
742 if( bExponentProcessed == FALSE ||
743 bThirdDigitsProcessed ||
746 bValidRealString = FALSE;
748 bFirstSignProcessed = TRUE;
749 bWhiteSpaceProcessed = TRUE;
750 bFirstDigitsProcessed = TRUE;
751 bDecimalPointProcessed = TRUE;
752 bSecondDigitsProcessed = TRUE;
753 bSecondSignProcessed = TRUE;
769 if( bFirstDigitsProcessed == FALSE )
771 if( bDecimalPointProcessed ||
772 bSecondDigitsProcessed ||
773 bExponentProcessed ||
774 bSecondSignProcessed ||
775 bThirdDigitsProcessed )
777 bValidRealString = FALSE;
779 bFirstSignProcessed = TRUE;
780 bWhiteSpaceProcessed = TRUE;
781 /* We have found some digits before the decimal point
782 * so disable the "Digits required" flag.
784 bDigitsRequired = FALSE;
786 else if( bSecondDigitsProcessed == FALSE )
788 if( bExponentProcessed ||
789 bSecondSignProcessed ||
790 bThirdDigitsProcessed )
792 bValidRealString = FALSE;
794 bFirstSignProcessed = TRUE;
795 bWhiteSpaceProcessed = TRUE;
796 bFirstDigitsProcessed = TRUE;
797 bDecimalPointProcessed = TRUE;
798 /* We have found some digits after the decimal point
799 * so disable the "Digits required" flag.
801 bDigitsRequired = FALSE;
803 else if( bThirdDigitsProcessed == FALSE )
805 /* Getting here means everything else should be processed.
806 * If we get anything else than a decimal following this
807 * digit it will be flagged by the other cases, so
808 * we do not really need to do anything in here.
812 /* If DecimalPoint...
815 if( bDecimalPointProcessed ||
816 bSecondDigitsProcessed ||
817 bExponentProcessed ||
818 bSecondSignProcessed ||
819 bThirdDigitsProcessed )
821 bValidRealString = FALSE;
823 bFirstSignProcessed = TRUE;
824 bWhiteSpaceProcessed = TRUE;
825 bFirstDigitsProcessed = TRUE;
826 bDecimalPointProcessed = TRUE;
834 if( bExponentProcessed ||
835 bSecondSignProcessed ||
836 bThirdDigitsProcessed ||
839 bValidRealString = FALSE;
841 bFirstSignProcessed = TRUE;
842 bWhiteSpaceProcessed = TRUE;
843 bFirstDigitsProcessed = TRUE;
844 bDecimalPointProcessed = TRUE;
845 bSecondDigitsProcessed = TRUE;
846 bExponentProcessed = TRUE;
849 bValidRealString = FALSE;
852 /* Process next character.
857 /* If the required digits were not present we have an invalid
858 * string representation of a real number.
860 if( bDigitsRequired == TRUE )
862 bValidRealString = FALSE;
865 return bValidRealString;
869 /******************************************************************************
872 * This function dispatches execution to the proper conversion API
873 * to do the necessary coercion.
875 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
878 unsigned short vtFrom = 0;
879 vtFrom = ps->vt & VT_TYPEMASK;
881 /* Note: Since "long" and "int" values both have 4 bytes and are
882 * both signed integers "int" will be treated as "long" in the
884 * The same goes for their unsigned versions.
887 /* Trivial Case: If the coercion is from two types that are
888 * identical then we can blindly copy from one argument to another.*/
891 return VariantCopy(pd,ps);
894 /* Cases requiring thought*/
899 res = VariantClear( pd );
902 res = VariantClear( pd );
912 res = VariantCopy( pd, ps );
915 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
919 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
922 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
925 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
929 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
932 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
935 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
938 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
941 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
944 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
947 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
950 /*res = VarI1FromDisp( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
952 /*res = VarI1FromDec( ps->u.decVal, &(pd->u.cVal) );*/
955 res = DISP_E_TYPEMISMATCH;
956 FIXME("Coercion from %d to %d\n", vtFrom, vt );
965 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
968 res = VariantCopy( pd, ps );
972 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
975 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
978 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
982 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
985 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
988 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
991 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
994 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
997 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
1000 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
1002 case( VT_DISPATCH ):
1003 /*res = VarI2FromDisp( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1005 /*res = VarI2FromDec( ps->u.deiVal, &(pd->u.iVal) );*/
1008 res = DISP_E_TYPEMISMATCH;
1009 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1019 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1022 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1026 res = VariantCopy( pd, ps );
1029 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1032 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1036 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1039 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1042 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1045 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1048 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1051 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1054 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1056 case( VT_DISPATCH ):
1057 /*res = VarI4FromDisp( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1059 /*res = VarI4FromDec( ps->u.deiVal, &(pd->u.lVal) );*/
1062 res = DISP_E_TYPEMISMATCH;
1063 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1072 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1075 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1079 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1082 res = VariantCopy( pd, ps );
1085 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1089 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1092 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1095 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1098 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1101 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1104 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1107 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1109 case( VT_DISPATCH ):
1110 /*res = VarUI1FromDisp( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1112 /*res = VarUI1FromDec( ps->u.deiVal, &(pd->u.bVal) );*/
1115 res = DISP_E_TYPEMISMATCH;
1116 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1125 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1128 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1132 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1135 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1138 res = VariantCopy( pd, ps );
1142 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1145 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1148 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1151 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1154 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1157 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1160 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1162 case( VT_DISPATCH ):
1163 /*res = VarUI2FromDisp( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1165 /*res = VarUI2FromDec( ps->u.deiVal, &(pd->u.uiVal) );*/
1168 res = DISP_E_TYPEMISMATCH;
1169 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1179 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1182 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1186 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1189 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1192 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1195 res = VariantCopy( pd, ps );
1198 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1201 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1204 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1207 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1210 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1213 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1215 case( VT_DISPATCH ):
1216 /*res = VarUI4FromDisp( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1218 /*res = VarUI4FromDec( ps->u.deiVal, &(pd->u.ulVal) );*/
1221 res = DISP_E_TYPEMISMATCH;
1222 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1231 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1234 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1238 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1241 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1244 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1248 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1251 res = VariantCopy( pd, ps );
1254 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1257 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1260 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1263 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1266 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1268 case( VT_DISPATCH ):
1269 /*res = VarR4FromDisp( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1271 /*res = VarR4FromDec( ps->u.deiVal, &(pd->u.fltVal) );*/
1274 res = DISP_E_TYPEMISMATCH;
1275 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1284 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1287 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1291 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1294 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1297 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1301 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1304 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1307 res = VariantCopy( pd, ps );
1310 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1313 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1316 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1319 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1321 case( VT_DISPATCH ):
1322 /*res = VarR8FromDisp( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1324 /*res = VarR8FromDec( ps->u.deiVal, &(pd->u.dblVal) );*/
1327 res = DISP_E_TYPEMISMATCH;
1328 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1337 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1340 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1343 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1346 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1349 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1352 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1355 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1358 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1361 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1364 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1367 res = VariantCopy( pd, ps );
1370 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1373 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1376 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1378 case( VT_DISPATCH ):
1379 /*res = VarDateFromDisp( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1381 /*res = VarDateFromDec( ps->u.deiVal, &(pd->u.date) );*/
1384 res = DISP_E_TYPEMISMATCH;
1385 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1394 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1397 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1400 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1403 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1406 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1409 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1412 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1415 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1418 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1421 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1424 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1427 res = VariantCopy( pd, ps );
1430 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1433 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1435 case( VT_DISPATCH ):
1436 /*res = VarBoolFromDisp( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1438 /*res = VarBoolFromDec( ps->u.deiVal, &(pd->u.boolVal) );*/
1441 res = DISP_E_TYPEMISMATCH;
1442 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1451 if ((pd->u.bstrVal = SysAllocStringLen(NULL, 0)))
1454 res = E_OUTOFMEMORY;
1457 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1460 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1463 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1466 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1469 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1472 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1475 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1478 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1481 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1484 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1487 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1490 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1493 res = VariantCopy( pd, ps );
1496 res = VarBstrFromCy( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );
1498 case( VT_DISPATCH ):
1499 /*res = VarBstrFromDisp( ps->u.pdispVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1501 /*res = VarBstrFromDec( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1504 res = DISP_E_TYPEMISMATCH;
1505 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1514 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1517 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1520 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1523 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1526 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1529 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1532 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1535 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1538 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1541 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1544 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1547 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1550 res = VariantCopy( pd, ps );
1553 res = VarCyFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );
1555 case( VT_DISPATCH ):
1556 /*res = VarCyFromDisp( ps->u.pdispVal, lcid, &(pd->u.cyVal) );*/
1558 /*res = VarCyFromDec( ps->u.deiVal, &(pd->u.cyVal) );*/
1562 res = DISP_E_TYPEMISMATCH;
1563 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1569 res = DISP_E_TYPEMISMATCH;
1570 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1577 /******************************************************************************
1578 * ValidateVtRange [INTERNAL]
1580 * Used internally by the hi-level Variant API to determine
1581 * if the vartypes are valid.
1583 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1585 /* if by value we must make sure it is in the
1586 * range of the valid types.
1588 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1590 return DISP_E_BADVARTYPE;
1596 /******************************************************************************
1597 * ValidateVartype [INTERNAL]
1599 * Used internally by the hi-level Variant API to determine
1600 * if the vartypes are valid.
1602 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1606 /* check if we have a valid argument.
1610 /* if by reference check that the type is in
1611 * the valid range and that it is not of empty or null type
1613 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1614 ( vt & VT_TYPEMASK ) == VT_NULL ||
1615 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1623 res = ValidateVtRange( vt );
1629 /******************************************************************************
1630 * ValidateVt [INTERNAL]
1632 * Used internally by the hi-level Variant API to determine
1633 * if the vartypes are valid.
1635 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1639 /* check if we have a valid argument.
1643 /* if by reference check that the type is in
1644 * the valid range and that it is not of empty or null type
1646 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1647 ( vt & VT_TYPEMASK ) == VT_NULL ||
1648 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1650 res = DISP_E_BADVARTYPE;
1656 res = ValidateVtRange( vt );
1666 /******************************************************************************
1667 * VariantInit [OLEAUT32.8]
1669 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1670 * contents of the Variant.
1672 void WINAPI VariantInit(VARIANTARG* pvarg)
1674 TRACE("(%p),stub\n",pvarg);
1676 memset(pvarg, 0, sizeof (VARIANTARG));
1677 pvarg->vt = VT_EMPTY;
1682 /******************************************************************************
1683 * VariantClear [OLEAUT32.9]
1685 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1686 * sets the wReservedX field to 0. The current contents of the VARIANT are
1687 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1688 * released. If VT_ARRAY the array is freed.
1690 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1693 TRACE("(%p)\n",pvarg);
1695 res = ValidateVariantType( pvarg->vt );
1698 if( !( pvarg->vt & VT_BYREF ) )
1701 * The VT_ARRAY flag is a special case of a safe array.
1703 if ( (pvarg->vt & VT_ARRAY) != 0)
1705 SafeArrayDestroy(pvarg->u.parray);
1709 switch( pvarg->vt & VT_TYPEMASK )
1712 SysFreeString( pvarg->u.bstrVal );
1714 case( VT_DISPATCH ):
1715 if(pvarg->u.pdispVal!=NULL)
1716 ICOM_CALL(Release,pvarg->u.pdispVal);
1719 VariantClear(pvarg->u.pvarVal);
1722 if(pvarg->u.punkVal!=NULL)
1723 ICOM_CALL(Release,pvarg->u.punkVal);
1725 case( VT_SAFEARRAY ):
1726 SafeArrayDestroy(pvarg->u.parray);
1735 * Empty all the fields and mark the type as empty.
1737 memset(pvarg, 0, sizeof (VARIANTARG));
1738 pvarg->vt = VT_EMPTY;
1744 /******************************************************************************
1745 * VariantCopy [OLEAUT32.10]
1747 * Frees up the designation variant and makes a copy of the source.
1749 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1753 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1755 res = ValidateVariantType( pvargSrc->vt );
1757 /* If the pointer are to the same variant we don't need
1760 if( pvargDest != pvargSrc && res == S_OK )
1762 res = VariantClear( pvargDest );
1766 if( pvargSrc->vt & VT_BYREF )
1768 /* In the case of byreference we only need
1769 * to copy the pointer.
1771 pvargDest->u = pvargSrc->u;
1772 pvargDest->vt = pvargSrc->vt;
1777 * The VT_ARRAY flag is another way to designate a safe array.
1779 if (pvargSrc->vt & VT_ARRAY)
1781 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1785 /* In the case of by value we need to
1786 * copy the actuall value. In the case of
1787 * VT_BSTR a copy of the string is made,
1788 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1789 * called to increment the object's reference count.
1791 switch( pvargSrc->vt & VT_TYPEMASK )
1794 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1796 case( VT_DISPATCH ):
1797 pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1798 if (pvargDest->u.pdispVal!=NULL)
1799 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1802 VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1805 pvargDest->u.punkVal = pvargSrc->u.punkVal;
1806 if (pvargDest->u.pdispVal!=NULL)
1807 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1809 case( VT_SAFEARRAY ):
1810 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1813 pvargDest->u = pvargSrc->u;
1818 pvargDest->vt = pvargSrc->vt;
1827 /******************************************************************************
1828 * VariantCopyInd [OLEAUT32.11]
1830 * Frees up the destination variant and makes a copy of the source. If
1831 * the source is of type VT_BYREF it performs the necessary indirections.
1833 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1837 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1839 res = ValidateVariantType( pvargSrc->vt );
1844 if( pvargSrc->vt & VT_BYREF )
1847 VariantInit( &varg );
1849 /* handle the in place copy.
1851 if( pvargDest == pvargSrc )
1853 /* we will use a copy of the source instead.
1855 res = VariantCopy( &varg, pvargSrc );
1861 res = VariantClear( pvargDest );
1866 * The VT_ARRAY flag is another way to designate a safearray variant.
1868 if ( pvargSrc->vt & VT_ARRAY)
1870 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1874 /* In the case of by reference we need
1875 * to copy the date pointed to by the variant.
1878 /* Get the variant type.
1880 switch( pvargSrc->vt & VT_TYPEMASK )
1883 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1885 case( VT_DISPATCH ):
1889 /* Prevent from cycling. According to tests on
1890 * VariantCopyInd in Windows and the documentation
1891 * this API dereferences the inner Variants to only one depth.
1892 * If the inner Variant itself contains an
1893 * other inner variant the E_INVALIDARG error is
1896 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1898 /* If we get here we are attempting to deference
1899 * an inner variant that that is itself contained
1900 * in an inner variant so report E_INVALIDARG error.
1906 /* Set the processing inner variant flag.
1907 * We will set this flag in the inner variant
1908 * that will be passed to the VariantCopyInd function.
1910 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1912 /* Dereference the inner variant.
1914 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1915 /* We must also copy its type, I think.
1917 pvargSrc->vt = pvargSrc->u.pvarVal->vt;
1923 case( VT_SAFEARRAY ):
1924 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1927 /* This is a by reference Variant which means that the union
1928 * part of the Variant contains a pointer to some data of
1929 * type "pvargSrc->vt & VT_TYPEMASK".
1930 * We will deference this data in a generic fashion using
1931 * the void pointer "Variant.u.byref".
1932 * We will copy this data into the union of the destination
1935 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1940 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1944 /* this should not fail.
1946 VariantClear( &varg );
1950 res = VariantCopy( pvargDest, pvargSrc );
1956 /******************************************************************************
1957 * VariantChangeType [OLEAUT32.12]
1959 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1960 USHORT wFlags, VARTYPE vt)
1962 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1965 /******************************************************************************
1966 * VariantChangeTypeEx [OLEAUT32.147]
1968 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1969 LCID lcid, USHORT wFlags, VARTYPE vt)
1973 VariantInit( &varg );
1975 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1977 /* validate our source argument.
1979 res = ValidateVariantType( pvargSrc->vt );
1981 /* validate the vartype.
1985 res = ValidateVt( vt );
1988 /* if we are doing an in-place conversion make a copy of the source.
1990 if( res == S_OK && pvargDest == pvargSrc )
1992 res = VariantCopy( &varg, pvargSrc );
1998 /* free up the destination variant.
2000 res = VariantClear( pvargDest );
2005 if( pvargSrc->vt & VT_BYREF )
2007 /* Convert the source variant to a "byvalue" variant.
2010 VariantInit( &Variant );
2011 res = VariantCopyInd( &Variant, pvargSrc );
2014 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2015 /* this should not fail.
2017 VariantClear( &Variant );
2023 /* Use the current "byvalue" source variant.
2025 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2028 /* this should not fail.
2030 VariantClear( &varg );
2032 /* set the type of the destination
2043 /******************************************************************************
2044 * VarUI1FromI2 [OLEAUT32.130]
2046 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2048 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2050 /* Check range of value.
2052 if( sIn < UI1_MIN || sIn > UI1_MAX )
2054 return DISP_E_OVERFLOW;
2057 *pbOut = (BYTE) sIn;
2062 /******************************************************************************
2063 * VarUI1FromI4 [OLEAUT32.131]
2065 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2067 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2069 /* Check range of value.
2071 if( lIn < UI1_MIN || lIn > UI1_MAX )
2073 return DISP_E_OVERFLOW;
2076 *pbOut = (BYTE) lIn;
2082 /******************************************************************************
2083 * VarUI1FromR4 [OLEAUT32.132]
2085 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2087 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2089 /* Check range of value.
2091 fltIn = round( fltIn );
2092 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2094 return DISP_E_OVERFLOW;
2097 *pbOut = (BYTE) fltIn;
2102 /******************************************************************************
2103 * VarUI1FromR8 [OLEAUT32.133]
2105 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2107 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2109 /* Check range of value.
2111 dblIn = round( dblIn );
2112 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2114 return DISP_E_OVERFLOW;
2117 *pbOut = (BYTE) dblIn;
2122 /******************************************************************************
2123 * VarUI1FromDate [OLEAUT32.135]
2125 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2127 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2129 /* Check range of value.
2131 dateIn = round( dateIn );
2132 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2134 return DISP_E_OVERFLOW;
2137 *pbOut = (BYTE) dateIn;
2142 /******************************************************************************
2143 * VarUI1FromBool [OLEAUT32.138]
2145 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2147 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2149 *pbOut = (BYTE) boolIn;
2154 /******************************************************************************
2155 * VarUI1FromI1 [OLEAUT32.237]
2157 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2159 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2166 /******************************************************************************
2167 * VarUI1FromUI2 [OLEAUT32.238]
2169 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2171 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2173 /* Check range of value.
2175 if( uiIn > UI1_MAX )
2177 return DISP_E_OVERFLOW;
2180 *pbOut = (BYTE) uiIn;
2185 /******************************************************************************
2186 * VarUI1FromUI4 [OLEAUT32.239]
2188 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2190 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2192 /* Check range of value.
2194 if( ulIn > UI1_MAX )
2196 return DISP_E_OVERFLOW;
2199 *pbOut = (BYTE) ulIn;
2205 /******************************************************************************
2206 * VarUI1FromStr [OLEAUT32.136]
2208 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2210 double dValue = 0.0;
2211 LPSTR pNewString = NULL;
2213 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2215 /* Check if we have a valid argument
2217 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2218 RemoveCharacterFromString( pNewString, "," );
2219 if( IsValidRealString( pNewString ) == FALSE )
2221 return DISP_E_TYPEMISMATCH;
2224 /* Convert the valid string to a floating point number.
2226 dValue = atof( pNewString );
2228 /* We don't need the string anymore so free it.
2230 HeapFree( GetProcessHeap(), 0 , pNewString );
2232 /* Check range of value.
2234 dValue = round( dValue );
2235 if( dValue < UI1_MIN || dValue > UI1_MAX )
2237 return DISP_E_OVERFLOW;
2240 *pbOut = (BYTE) dValue;
2245 /**********************************************************************
2246 * VarUI1FromCy [OLEAUT32.134]
2247 * Convert currency to unsigned char
2249 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2250 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2252 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2258 /******************************************************************************
2259 * VarI2FromUI1 [OLEAUT32.48]
2261 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2263 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2265 *psOut = (short) bIn;
2270 /******************************************************************************
2271 * VarI2FromI4 [OLEAUT32.49]
2273 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2275 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2277 /* Check range of value.
2279 if( lIn < I2_MIN || lIn > I2_MAX )
2281 return DISP_E_OVERFLOW;
2284 *psOut = (short) lIn;
2289 /******************************************************************************
2290 * VarI2FromR4 [OLEAUT32.50]
2292 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2294 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2296 /* Check range of value.
2298 fltIn = round( fltIn );
2299 if( fltIn < I2_MIN || fltIn > I2_MAX )
2301 return DISP_E_OVERFLOW;
2304 *psOut = (short) fltIn;
2309 /******************************************************************************
2310 * VarI2FromR8 [OLEAUT32.51]
2312 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2314 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2316 /* Check range of value.
2318 dblIn = round( dblIn );
2319 if( dblIn < I2_MIN || dblIn > I2_MAX )
2321 return DISP_E_OVERFLOW;
2324 *psOut = (short) dblIn;
2329 /******************************************************************************
2330 * VarI2FromDate [OLEAUT32.53]
2332 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2334 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2336 /* Check range of value.
2338 dateIn = round( dateIn );
2339 if( dateIn < I2_MIN || dateIn > I2_MAX )
2341 return DISP_E_OVERFLOW;
2344 *psOut = (short) dateIn;
2349 /******************************************************************************
2350 * VarI2FromBool [OLEAUT32.56]
2352 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2354 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2356 *psOut = (short) boolIn;
2361 /******************************************************************************
2362 * VarI2FromI1 [OLEAUT32.205]
2364 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2366 TRACE("( %c, %p ), stub\n", cIn, psOut );
2368 *psOut = (short) cIn;
2373 /******************************************************************************
2374 * VarI2FromUI2 [OLEAUT32.206]
2376 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2378 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2380 /* Check range of value.
2384 return DISP_E_OVERFLOW;
2387 *psOut = (short) uiIn;
2392 /******************************************************************************
2393 * VarI2FromUI4 [OLEAUT32.207]
2395 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2397 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2399 /* Check range of value.
2401 if( ulIn < I2_MIN || ulIn > I2_MAX )
2403 return DISP_E_OVERFLOW;
2406 *psOut = (short) ulIn;
2411 /******************************************************************************
2412 * VarI2FromStr [OLEAUT32.54]
2414 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2416 double dValue = 0.0;
2417 LPSTR pNewString = NULL;
2419 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2421 /* Check if we have a valid argument
2423 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2424 RemoveCharacterFromString( pNewString, "," );
2425 if( IsValidRealString( pNewString ) == FALSE )
2427 return DISP_E_TYPEMISMATCH;
2430 /* Convert the valid string to a floating point number.
2432 dValue = atof( pNewString );
2434 /* We don't need the string anymore so free it.
2436 HeapFree( GetProcessHeap(), 0, pNewString );
2438 /* Check range of value.
2440 dValue = round( dValue );
2441 if( dValue < I2_MIN || dValue > I2_MAX )
2443 return DISP_E_OVERFLOW;
2446 *psOut = (short) dValue;
2451 /**********************************************************************
2452 * VarI2FromCy [OLEAUT32.52]
2453 * Convert currency to signed short
2455 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2456 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2458 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2464 /******************************************************************************
2465 * VarI4FromUI1 [OLEAUT32.58]
2467 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2469 TRACE("( %X, %p ), stub\n", bIn, plOut );
2471 *plOut = (LONG) bIn;
2477 /******************************************************************************
2478 * VarI4FromR4 [OLEAUT32.60]
2480 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2482 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2484 /* Check range of value.
2486 fltIn = round( fltIn );
2487 if( fltIn < I4_MIN || fltIn > I4_MAX )
2489 return DISP_E_OVERFLOW;
2492 *plOut = (LONG) fltIn;
2497 /******************************************************************************
2498 * VarI4FromR8 [OLEAUT32.61]
2500 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2502 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2504 /* Check range of value.
2506 dblIn = round( dblIn );
2507 if( dblIn < I4_MIN || dblIn > I4_MAX )
2509 return DISP_E_OVERFLOW;
2512 *plOut = (LONG) dblIn;
2517 /******************************************************************************
2518 * VarI4FromDate [OLEAUT32.63]
2520 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2522 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2524 /* Check range of value.
2526 dateIn = round( dateIn );
2527 if( dateIn < I4_MIN || dateIn > I4_MAX )
2529 return DISP_E_OVERFLOW;
2532 *plOut = (LONG) dateIn;
2537 /******************************************************************************
2538 * VarI4FromBool [OLEAUT32.66]
2540 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2542 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2544 *plOut = (LONG) boolIn;
2549 /******************************************************************************
2550 * VarI4FromI1 [OLEAUT32.209]
2552 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2554 TRACE("( %c, %p ), stub\n", cIn, plOut );
2556 *plOut = (LONG) cIn;
2561 /******************************************************************************
2562 * VarI4FromUI2 [OLEAUT32.210]
2564 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2566 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2568 *plOut = (LONG) uiIn;
2573 /******************************************************************************
2574 * VarI4FromUI4 [OLEAUT32.211]
2576 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2578 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2580 /* Check range of value.
2582 if( ulIn < I4_MIN || ulIn > I4_MAX )
2584 return DISP_E_OVERFLOW;
2587 *plOut = (LONG) ulIn;
2592 /******************************************************************************
2593 * VarI4FromI2 [OLEAUT32.59]
2595 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2597 TRACE("( %d, %p ), stub\n", sIn, plOut );
2599 *plOut = (LONG) sIn;
2604 /******************************************************************************
2605 * VarI4FromStr [OLEAUT32.64]
2607 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2609 double dValue = 0.0;
2610 LPSTR pNewString = NULL;
2612 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2614 /* Check if we have a valid argument
2616 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2617 RemoveCharacterFromString( pNewString, "," );
2618 if( IsValidRealString( pNewString ) == FALSE )
2620 return DISP_E_TYPEMISMATCH;
2623 /* Convert the valid string to a floating point number.
2625 dValue = atof( pNewString );
2627 /* We don't need the string anymore so free it.
2629 HeapFree( GetProcessHeap(), 0, pNewString );
2631 /* Check range of value.
2633 dValue = round( dValue );
2634 if( dValue < I4_MIN || dValue > I4_MAX )
2636 return DISP_E_OVERFLOW;
2639 *plOut = (LONG) dValue;
2644 /**********************************************************************
2645 * VarI4FromCy [OLEAUT32.62]
2646 * Convert currency to signed long
2648 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2649 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2651 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2657 /******************************************************************************
2658 * VarR4FromUI1 [OLEAUT32.68]
2660 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2662 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2664 *pfltOut = (FLOAT) bIn;
2669 /******************************************************************************
2670 * VarR4FromI2 [OLEAUT32.69]
2672 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2674 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2676 *pfltOut = (FLOAT) sIn;
2681 /******************************************************************************
2682 * VarR4FromI4 [OLEAUT32.70]
2684 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2686 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2688 *pfltOut = (FLOAT) lIn;
2693 /******************************************************************************
2694 * VarR4FromR8 [OLEAUT32.71]
2696 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2698 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2700 /* Check range of value.
2702 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2704 return DISP_E_OVERFLOW;
2707 *pfltOut = (FLOAT) dblIn;
2712 /******************************************************************************
2713 * VarR4FromDate [OLEAUT32.73]
2715 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2717 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2719 /* Check range of value.
2721 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2723 return DISP_E_OVERFLOW;
2726 *pfltOut = (FLOAT) dateIn;
2731 /******************************************************************************
2732 * VarR4FromBool [OLEAUT32.76]
2734 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2736 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2738 *pfltOut = (FLOAT) boolIn;
2743 /******************************************************************************
2744 * VarR4FromI1 [OLEAUT32.213]
2746 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2748 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2750 *pfltOut = (FLOAT) cIn;
2755 /******************************************************************************
2756 * VarR4FromUI2 [OLEAUT32.214]
2758 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2760 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2762 *pfltOut = (FLOAT) uiIn;
2767 /******************************************************************************
2768 * VarR4FromUI4 [OLEAUT32.215]
2770 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2772 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2774 *pfltOut = (FLOAT) ulIn;
2779 /******************************************************************************
2780 * VarR4FromStr [OLEAUT32.74]
2782 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2784 double dValue = 0.0;
2785 LPSTR pNewString = NULL;
2787 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2789 /* Check if we have a valid argument
2791 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2792 RemoveCharacterFromString( pNewString, "," );
2793 if( IsValidRealString( pNewString ) == FALSE )
2795 return DISP_E_TYPEMISMATCH;
2798 /* Convert the valid string to a floating point number.
2800 dValue = atof( pNewString );
2802 /* We don't need the string anymore so free it.
2804 HeapFree( GetProcessHeap(), 0, pNewString );
2806 /* Check range of value.
2808 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2810 return DISP_E_OVERFLOW;
2813 *pfltOut = (FLOAT) dValue;
2818 /**********************************************************************
2819 * VarR4FromCy [OLEAUT32.72]
2820 * Convert currency to float
2822 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2823 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2828 /******************************************************************************
2829 * VarR8FromUI1 [OLEAUT32.78]
2831 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2833 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2835 *pdblOut = (double) bIn;
2840 /******************************************************************************
2841 * VarR8FromI2 [OLEAUT32.79]
2843 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2845 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2847 *pdblOut = (double) sIn;
2852 /******************************************************************************
2853 * VarR8FromI4 [OLEAUT32.80]
2855 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2857 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2859 *pdblOut = (double) lIn;
2864 /******************************************************************************
2865 * VarR8FromR4 [OLEAUT32.81]
2867 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2869 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2871 *pdblOut = (double) fltIn;
2876 /******************************************************************************
2877 * VarR8FromDate [OLEAUT32.83]
2879 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2881 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2883 *pdblOut = (double) dateIn;
2888 /******************************************************************************
2889 * VarR8FromBool [OLEAUT32.86]
2891 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2893 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2895 *pdblOut = (double) boolIn;
2900 /******************************************************************************
2901 * VarR8FromI1 [OLEAUT32.217]
2903 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2905 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2907 *pdblOut = (double) cIn;
2912 /******************************************************************************
2913 * VarR8FromUI2 [OLEAUT32.218]
2915 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2917 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2919 *pdblOut = (double) uiIn;
2924 /******************************************************************************
2925 * VarR8FromUI4 [OLEAUT32.219]
2927 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2929 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2931 *pdblOut = (double) ulIn;
2936 /******************************************************************************
2937 * VarR8FromStr [OLEAUT32.84]
2939 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2941 double dValue = 0.0;
2942 LPSTR pNewString = NULL;
2944 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2946 /* Check if we have a valid argument
2948 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2949 RemoveCharacterFromString( pNewString, "," );
2950 if( IsValidRealString( pNewString ) == FALSE )
2952 return DISP_E_TYPEMISMATCH;
2955 /* Convert the valid string to a floating point number.
2957 dValue = atof( pNewString );
2959 /* We don't need the string anymore so free it.
2961 HeapFree( GetProcessHeap(), 0, pNewString );
2968 /**********************************************************************
2969 * VarR8FromCy [OLEAUT32.82]
2970 * Convert currency to double
2972 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2973 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2978 /******************************************************************************
2979 * VarDateFromUI1 [OLEAUT32.88]
2981 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2983 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2985 *pdateOut = (DATE) bIn;
2990 /******************************************************************************
2991 * VarDateFromI2 [OLEAUT32.89]
2993 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2995 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2997 *pdateOut = (DATE) sIn;
3002 /******************************************************************************
3003 * VarDateFromI4 [OLEAUT32.90]
3005 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
3007 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
3009 if( lIn < DATE_MIN || lIn > DATE_MAX )
3011 return DISP_E_OVERFLOW;
3014 *pdateOut = (DATE) lIn;
3019 /******************************************************************************
3020 * VarDateFromR4 [OLEAUT32.91]
3022 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3024 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3026 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3028 return DISP_E_OVERFLOW;
3031 *pdateOut = (DATE) fltIn;
3036 /******************************************************************************
3037 * VarDateFromR8 [OLEAUT32.92]
3039 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3041 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3043 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3045 return DISP_E_OVERFLOW;
3048 *pdateOut = (DATE) dblIn;
3053 /******************************************************************************
3054 * VarDateFromStr [OLEAUT32.94]
3055 * The string representing the date is composed of two parts, a date and time.
3057 * The format of the time is has follows:
3058 * hh[:mm][:ss][AM|PM]
3059 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3060 * of space and/or tab characters, which are ignored.
3062 * The formats for the date part are has follows:
3066 * January dd[,] [yy]yy
3069 * Whitespace can be inserted anywhere between these tokens.
3071 * The formats for the date and time string are has follows.
3072 * date[whitespace][time]
3073 * [time][whitespace]date
3075 * These are the only characters allowed in a string representing a date and time:
3076 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3078 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3083 memset( &TM, 0, sizeof(TM) );
3085 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3087 if( DateTimeStringToTm( strIn, lcid, &TM ) )
3089 if( TmToDATE( &TM, pdateOut ) == FALSE )
3096 ret = DISP_E_TYPEMISMATCH;
3103 /******************************************************************************
3104 * VarDateFromI1 [OLEAUT32.221]
3106 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3108 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3110 *pdateOut = (DATE) cIn;
3115 /******************************************************************************
3116 * VarDateFromUI2 [OLEAUT32.222]
3118 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3120 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3122 if( uiIn > DATE_MAX )
3124 return DISP_E_OVERFLOW;
3127 *pdateOut = (DATE) uiIn;
3132 /******************************************************************************
3133 * VarDateFromUI4 [OLEAUT32.223]
3135 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3137 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3139 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3141 return DISP_E_OVERFLOW;
3144 *pdateOut = (DATE) ulIn;
3149 /******************************************************************************
3150 * VarDateFromBool [OLEAUT32.96]
3152 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3154 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3156 *pdateOut = (DATE) boolIn;
3161 /**********************************************************************
3162 * VarDateFromCy [OLEAUT32.93]
3163 * Convert currency to date
3165 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3166 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3168 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3172 /******************************************************************************
3173 * VarBstrFromUI1 [OLEAUT32.108]
3175 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3177 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3178 sprintf( pBuffer, "%d", bVal );
3180 *pbstrOut = StringDupAtoBstr( pBuffer );
3185 /******************************************************************************
3186 * VarBstrFromI2 [OLEAUT32.109]
3188 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3190 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3191 sprintf( pBuffer, "%d", iVal );
3192 *pbstrOut = StringDupAtoBstr( pBuffer );
3197 /******************************************************************************
3198 * VarBstrFromI4 [OLEAUT32.110]
3200 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3202 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3204 sprintf( pBuffer, "%ld", lIn );
3205 *pbstrOut = StringDupAtoBstr( pBuffer );
3210 /******************************************************************************
3211 * VarBstrFromR4 [OLEAUT32.111]
3213 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3215 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3217 sprintf( pBuffer, "%.7g", fltIn );
3218 *pbstrOut = StringDupAtoBstr( pBuffer );
3223 /******************************************************************************
3224 * VarBstrFromR8 [OLEAUT32.112]
3226 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3228 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3230 sprintf( pBuffer, "%.15g", dblIn );
3231 *pbstrOut = StringDupAtoBstr( pBuffer );
3236 /******************************************************************************
3237 * VarBstrFromCy [OLEAUT32.113]
3239 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3245 /******************************************************************************
3246 * VarBstrFromDate [OLEAUT32.114]
3248 * The date is implemented using an 8 byte floating-point number.
3249 * Days are represented by whole numbers increments starting with 0.00 as
3250 * being December 30 1899, midnight.
3251 * The hours are expressed as the fractional part of the number.
3252 * December 30 1899 at midnight = 0.00
3253 * January 1 1900 at midnight = 2.00
3254 * January 4 1900 at 6 AM = 5.25
3255 * January 4 1900 at noon = 5.50
3256 * December 29 1899 at midnight = -1.00
3257 * December 18 1899 at midnight = -12.00
3258 * December 18 1899 at 6AM = -12.25
3259 * December 18 1899 at 6PM = -12.75
3260 * December 19 1899 at midnight = -11.00
3261 * The tm structure is as follows:
3263 * int tm_sec; seconds after the minute - [0,59]
3264 * int tm_min; minutes after the hour - [0,59]
3265 * int tm_hour; hours since midnight - [0,23]
3266 * int tm_mday; day of the month - [1,31]
3267 * int tm_mon; months since January - [0,11]
3268 * int tm_year; years
3269 * int tm_wday; days since Sunday - [0,6]
3270 * int tm_yday; days since January 1 - [0,365]
3271 * int tm_isdst; daylight savings time flag
3274 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3277 memset( &TM, 0, sizeof(TM) );
3279 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3281 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3283 return E_INVALIDARG;
3286 if( dwFlags & VAR_DATEVALUEONLY )
3287 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3288 else if( dwFlags & VAR_TIMEVALUEONLY )
3289 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3291 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3293 *pbstrOut = StringDupAtoBstr( pBuffer );
3298 /******************************************************************************
3299 * VarBstrFromBool [OLEAUT32.116]
3301 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3303 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3305 if( boolIn == VARIANT_FALSE )
3307 sprintf( pBuffer, "False" );
3311 sprintf( pBuffer, "True" );
3314 *pbstrOut = StringDupAtoBstr( pBuffer );
3319 /******************************************************************************
3320 * VarBstrFromI1 [OLEAUT32.229]
3322 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3324 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3325 sprintf( pBuffer, "%d", cIn );
3326 *pbstrOut = StringDupAtoBstr( pBuffer );
3331 /******************************************************************************
3332 * VarBstrFromUI2 [OLEAUT32.230]
3334 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3336 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3337 sprintf( pBuffer, "%d", uiIn );
3338 *pbstrOut = StringDupAtoBstr( pBuffer );
3343 /******************************************************************************
3344 * VarBstrFromUI4 [OLEAUT32.231]
3346 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3348 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3349 sprintf( pBuffer, "%ld", ulIn );
3350 *pbstrOut = StringDupAtoBstr( pBuffer );
3355 /******************************************************************************
3356 * VarBoolFromUI1 [OLEAUT32.118]
3358 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3360 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3364 *pboolOut = VARIANT_FALSE;
3368 *pboolOut = VARIANT_TRUE;
3374 /******************************************************************************
3375 * VarBoolFromI2 [OLEAUT32.119]
3377 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3379 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3383 *pboolOut = VARIANT_FALSE;
3387 *pboolOut = VARIANT_TRUE;
3393 /******************************************************************************
3394 * VarBoolFromI4 [OLEAUT32.120]
3396 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3398 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3402 *pboolOut = VARIANT_FALSE;
3406 *pboolOut = VARIANT_TRUE;
3412 /******************************************************************************
3413 * VarBoolFromR4 [OLEAUT32.121]
3415 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3417 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3421 *pboolOut = VARIANT_FALSE;
3425 *pboolOut = VARIANT_TRUE;
3431 /******************************************************************************
3432 * VarBoolFromR8 [OLEAUT32.122]
3434 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3436 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3440 *pboolOut = VARIANT_FALSE;
3444 *pboolOut = VARIANT_TRUE;
3450 /******************************************************************************
3451 * VarBoolFromDate [OLEAUT32.123]
3453 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3455 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3459 *pboolOut = VARIANT_FALSE;
3463 *pboolOut = VARIANT_TRUE;
3469 /******************************************************************************
3470 * VarBoolFromStr [OLEAUT32.125]
3472 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3475 char* pNewString = NULL;
3477 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3479 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3481 if( pNewString == NULL || strlen( pNewString ) == 0 )
3483 ret = DISP_E_TYPEMISMATCH;
3488 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3490 *pboolOut = VARIANT_TRUE;
3492 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3494 *pboolOut = VARIANT_FALSE;
3498 /* Try converting the string to a floating point number.
3500 double dValue = 0.0;
3501 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3504 ret = DISP_E_TYPEMISMATCH;
3506 else if( dValue == 0.0 )
3508 *pboolOut = VARIANT_FALSE;
3512 *pboolOut = VARIANT_TRUE;
3517 HeapFree( GetProcessHeap(), 0, pNewString );
3522 /******************************************************************************
3523 * VarBoolFromI1 [OLEAUT32.233]
3525 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3527 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3531 *pboolOut = VARIANT_FALSE;
3535 *pboolOut = VARIANT_TRUE;
3541 /******************************************************************************
3542 * VarBoolFromUI2 [OLEAUT32.234]
3544 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3546 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3550 *pboolOut = VARIANT_FALSE;
3554 *pboolOut = VARIANT_TRUE;
3560 /******************************************************************************
3561 * VarBoolFromUI4 [OLEAUT32.235]
3563 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3565 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3569 *pboolOut = VARIANT_FALSE;
3573 *pboolOut = VARIANT_TRUE;
3579 /**********************************************************************
3580 * VarBoolFromCy [OLEAUT32.124]
3581 * Convert currency to boolean
3583 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3584 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3590 /******************************************************************************
3591 * VarI1FromUI1 [OLEAUT32.244]
3593 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3595 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3597 /* Check range of value.
3599 if( bIn > CHAR_MAX )
3601 return DISP_E_OVERFLOW;
3604 *pcOut = (CHAR) bIn;
3609 /******************************************************************************
3610 * VarI1FromI2 [OLEAUT32.245]
3612 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3614 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3616 if( uiIn > CHAR_MAX )
3618 return DISP_E_OVERFLOW;
3621 *pcOut = (CHAR) uiIn;
3626 /******************************************************************************
3627 * VarI1FromI4 [OLEAUT32.246]
3629 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3631 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3633 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3635 return DISP_E_OVERFLOW;
3638 *pcOut = (CHAR) lIn;
3643 /******************************************************************************
3644 * VarI1FromR4 [OLEAUT32.247]
3646 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3648 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3650 fltIn = round( fltIn );
3651 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3653 return DISP_E_OVERFLOW;
3656 *pcOut = (CHAR) fltIn;
3661 /******************************************************************************
3662 * VarI1FromR8 [OLEAUT32.248]
3664 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3666 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3668 dblIn = round( dblIn );
3669 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3671 return DISP_E_OVERFLOW;
3674 *pcOut = (CHAR) dblIn;
3679 /******************************************************************************
3680 * VarI1FromDate [OLEAUT32.249]
3682 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3684 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3686 dateIn = round( dateIn );
3687 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3689 return DISP_E_OVERFLOW;
3692 *pcOut = (CHAR) dateIn;
3697 /******************************************************************************
3698 * VarI1FromStr [OLEAUT32.251]
3700 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3702 double dValue = 0.0;
3703 LPSTR pNewString = NULL;
3705 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3707 /* Check if we have a valid argument
3709 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3710 RemoveCharacterFromString( pNewString, "," );
3711 if( IsValidRealString( pNewString ) == FALSE )
3713 return DISP_E_TYPEMISMATCH;
3716 /* Convert the valid string to a floating point number.
3718 dValue = atof( pNewString );
3720 /* We don't need the string anymore so free it.
3722 HeapFree( GetProcessHeap(), 0, pNewString );
3724 /* Check range of value.
3726 dValue = round( dValue );
3727 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3729 return DISP_E_OVERFLOW;
3732 *pcOut = (CHAR) dValue;
3737 /******************************************************************************
3738 * VarI1FromBool [OLEAUT32.253]
3740 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3742 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3744 *pcOut = (CHAR) boolIn;
3749 /******************************************************************************
3750 * VarI1FromUI2 [OLEAUT32.254]
3752 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3754 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3756 if( uiIn > CHAR_MAX )
3758 return DISP_E_OVERFLOW;
3761 *pcOut = (CHAR) uiIn;
3766 /******************************************************************************
3767 * VarI1FromUI4 [OLEAUT32.255]
3769 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3771 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3773 if( ulIn > CHAR_MAX )
3775 return DISP_E_OVERFLOW;
3778 *pcOut = (CHAR) ulIn;
3783 /**********************************************************************
3784 * VarI1FromCy [OLEAUT32.250]
3785 * Convert currency to signed char
3787 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3788 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3790 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3796 /******************************************************************************
3797 * VarUI2FromUI1 [OLEAUT32.257]
3799 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3801 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3803 *puiOut = (USHORT) bIn;
3808 /******************************************************************************
3809 * VarUI2FromI2 [OLEAUT32.258]
3811 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3813 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3815 if( uiIn < UI2_MIN )
3817 return DISP_E_OVERFLOW;
3820 *puiOut = (USHORT) uiIn;
3825 /******************************************************************************
3826 * VarUI2FromI4 [OLEAUT32.259]
3828 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3830 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3832 if( lIn < UI2_MIN || lIn > UI2_MAX )
3834 return DISP_E_OVERFLOW;
3837 *puiOut = (USHORT) lIn;
3842 /******************************************************************************
3843 * VarUI2FromR4 [OLEAUT32.260]
3845 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3847 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3849 fltIn = round( fltIn );
3850 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3852 return DISP_E_OVERFLOW;
3855 *puiOut = (USHORT) fltIn;
3860 /******************************************************************************
3861 * VarUI2FromR8 [OLEAUT32.261]
3863 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3865 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3867 dblIn = round( dblIn );
3868 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3870 return DISP_E_OVERFLOW;
3873 *puiOut = (USHORT) dblIn;
3878 /******************************************************************************
3879 * VarUI2FromDate [OLEAUT32.262]
3881 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3883 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3885 dateIn = round( dateIn );
3886 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3888 return DISP_E_OVERFLOW;
3891 *puiOut = (USHORT) dateIn;
3896 /******************************************************************************
3897 * VarUI2FromStr [OLEAUT32.264]
3899 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3901 double dValue = 0.0;
3902 LPSTR pNewString = NULL;
3904 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3906 /* Check if we have a valid argument
3908 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3909 RemoveCharacterFromString( pNewString, "," );
3910 if( IsValidRealString( pNewString ) == FALSE )
3912 return DISP_E_TYPEMISMATCH;
3915 /* Convert the valid string to a floating point number.
3917 dValue = atof( pNewString );
3919 /* We don't need the string anymore so free it.
3921 HeapFree( GetProcessHeap(), 0, pNewString );
3923 /* Check range of value.
3925 dValue = round( dValue );
3926 if( dValue < UI2_MIN || dValue > UI2_MAX )
3928 return DISP_E_OVERFLOW;
3931 *puiOut = (USHORT) dValue;
3936 /******************************************************************************
3937 * VarUI2FromBool [OLEAUT32.266]
3939 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3941 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3943 *puiOut = (USHORT) boolIn;
3948 /******************************************************************************
3949 * VarUI2FromI1 [OLEAUT32.267]
3951 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3953 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3955 *puiOut = (USHORT) cIn;
3960 /******************************************************************************
3961 * VarUI2FromUI4 [OLEAUT32.268]
3963 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3965 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3967 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3969 return DISP_E_OVERFLOW;
3972 *puiOut = (USHORT) ulIn;
3977 /******************************************************************************
3978 * VarUI4FromStr [OLEAUT32.277]
3980 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3982 double dValue = 0.0;
3983 LPSTR pNewString = NULL;
3985 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3987 /* Check if we have a valid argument
3989 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3990 RemoveCharacterFromString( pNewString, "," );
3991 if( IsValidRealString( pNewString ) == FALSE )
3993 return DISP_E_TYPEMISMATCH;
3996 /* Convert the valid string to a floating point number.
3998 dValue = atof( pNewString );
4000 /* We don't need the string anymore so free it.
4002 HeapFree( GetProcessHeap(), 0, pNewString );
4004 /* Check range of value.
4006 dValue = round( dValue );
4007 if( dValue < UI4_MIN || dValue > UI4_MAX )
4009 return DISP_E_OVERFLOW;
4012 *pulOut = (ULONG) dValue;
4017 /**********************************************************************
4018 * VarUI2FromCy [OLEAUT32.263]
4019 * Convert currency to unsigned short
4021 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4022 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4024 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4026 *pusOut = (USHORT)t;
4031 /******************************************************************************
4032 * VarUI4FromUI1 [OLEAUT32.270]
4034 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4036 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4038 *pulOut = (USHORT) bIn;
4043 /******************************************************************************
4044 * VarUI4FromI2 [OLEAUT32.271]
4046 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4048 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4050 if( uiIn < UI4_MIN )
4052 return DISP_E_OVERFLOW;
4055 *pulOut = (ULONG) uiIn;
4060 /******************************************************************************
4061 * VarUI4FromI4 [OLEAUT32.272]
4063 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4065 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4069 return DISP_E_OVERFLOW;
4072 *pulOut = (ULONG) lIn;
4077 /******************************************************************************
4078 * VarUI4FromR4 [OLEAUT32.273]
4080 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4082 fltIn = round( fltIn );
4083 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4085 return DISP_E_OVERFLOW;
4088 *pulOut = (ULONG) fltIn;
4093 /******************************************************************************
4094 * VarUI4FromR8 [OLEAUT32.274]
4096 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4098 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4100 dblIn = round( dblIn );
4101 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4103 return DISP_E_OVERFLOW;
4106 *pulOut = (ULONG) dblIn;
4111 /******************************************************************************
4112 * VarUI4FromDate [OLEAUT32.275]
4114 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4116 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4118 dateIn = round( dateIn );
4119 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4121 return DISP_E_OVERFLOW;
4124 *pulOut = (ULONG) dateIn;
4129 /******************************************************************************
4130 * VarUI4FromBool [OLEAUT32.279]
4132 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4134 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4136 *pulOut = (ULONG) boolIn;
4141 /******************************************************************************
4142 * VarUI4FromI1 [OLEAUT32.280]
4144 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4146 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4148 *pulOut = (ULONG) cIn;
4153 /******************************************************************************
4154 * VarUI4FromUI2 [OLEAUT32.281]
4156 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4158 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4160 *pulOut = (ULONG) uiIn;
4165 /**********************************************************************
4166 * VarUI4FromCy [OLEAUT32.276]
4167 * Convert currency to unsigned long
4169 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4170 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4172 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4179 /**********************************************************************
4180 * VarCyFromUI1 [OLEAUT32.98]
4181 * Convert unsigned char to currency
4183 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4185 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4190 /**********************************************************************
4191 * VarCyFromI2 [OLEAUT32.99]
4192 * Convert signed short to currency
4194 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4195 if (sIn < 0) pcyOut->s.Hi = -1;
4196 else pcyOut->s.Hi = 0;
4197 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4202 /**********************************************************************
4203 * VarCyFromI4 [OLEAUT32.100]
4204 * Convert signed long to currency
4206 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4207 double t = (double)lIn * (double)10000;
4208 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4209 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4210 if (lIn < 0) pcyOut->s.Hi--;
4215 /**********************************************************************
4216 * VarCyFromR4 [OLEAUT32.101]
4217 * Convert float to currency
4219 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4220 double t = round((double)fltIn * (double)10000);
4221 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4222 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4223 if (fltIn < 0) pcyOut->s.Hi--;
4228 /**********************************************************************
4229 * VarCyFromR8 [OLEAUT32.102]
4230 * Convert double to currency
4232 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4233 double t = round(dblIn * (double)10000);
4234 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4235 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4236 if (dblIn < 0) pcyOut->s.Hi--;
4241 /**********************************************************************
4242 * VarCyFromDate [OLEAUT32.103]
4243 * Convert date to currency
4245 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4246 double t = round((double)dateIn * (double)10000);
4247 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4248 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4249 if (dateIn < 0) pcyOut->s.Hi--;
4254 /**********************************************************************
4255 * VarCyFromStr [OLEAUT32.104]
4257 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4263 /**********************************************************************
4264 * VarCyFromBool [OLEAUT32.106]
4265 * Convert boolean to currency
4267 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4268 if (boolIn < 0) pcyOut->s.Hi = -1;
4269 else pcyOut->s.Hi = 0;
4270 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4275 /**********************************************************************
4276 * VarCyFromI1 [OLEAUT32.225]
4277 * Convert signed char to currency
4279 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pcyOut) {
4280 if (cIn < 0) pcyOut->s.Hi = -1;
4281 else pcyOut->s.Hi = 0;
4282 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4287 /**********************************************************************
4288 * VarCyFromUI2 [OLEAUT32.226]
4289 * Convert unsigned short to currency
4291 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4293 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4298 /**********************************************************************
4299 * VarCyFromUI4 [OLEAUT32.227]
4300 * Convert unsigned long to currency
4302 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4303 double t = (double)ulIn * (double)10000;
4304 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4305 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4311 /**********************************************************************
4312 * DosDateTimeToVariantTime [OLEAUT32.14]
4313 * Convert dos representation of time to the date and time representation
4314 * stored in a variant.
4316 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4321 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4323 t.tm_sec = (wDosTime & 0x001f) * 2;
4324 t.tm_min = (wDosTime & 0x07e0) >> 5;
4325 t.tm_hour = (wDosTime & 0xf800) >> 11;
4327 t.tm_mday = (wDosDate & 0x001f);
4328 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4329 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4331 return TmToDATE( &t, pvtime );
4334 /**********************************************************************
4335 * VariantTimeToDosDateTime [OLEAUT32.??]
4336 * Convert variant representation of time to the date and time representation
4339 INT WINAPI VariantTimeToDosDateTime(DATE pvtime, USHORT *wDosDate, USHORT *wDosTime)
4345 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", *wDosDate, *wDosTime, &pvtime );
4347 if (DateToTm(pvtime, (LCID)NULL, &t) < 0) return 0;
4349 *wDosTime = *wDosTime | (t.tm_sec / 2);
4350 *wDosTime = *wDosTime | (t.tm_min << 5);
4351 *wDosTime = *wDosTime | (t.tm_hour << 11);
4353 *wDosDate = *wDosDate | t.tm_mday ;
4354 *wDosDate = *wDosDate | t.tm_mon << 5;
4355 *wDosDate = *wDosDate | ((t.tm_year - 1980) << 9) ;
4361 HRESULT WINAPI SystemTimeToVariantTime( LPSYSTEMTIME lpSystemTime, double *pvtime )
4363 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4364 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4368 TRACE(" %d/%d/%d %d:%d:%d\n",
4369 lpSystemTime->wMonth, lpSystemTime->wDay,
4370 lpSystemTime->wYear, lpSystemTime->wHour,
4371 lpSystemTime->wMinute, lpSystemTime->wSecond);
4373 if (lpSystemTime->wYear >= 1900)
4375 t.tm_sec = lpSystemTime->wSecond;
4376 t.tm_min = lpSystemTime->wMinute;
4377 t.tm_hour = lpSystemTime->wHour;
4379 t.tm_mday = lpSystemTime->wDay;
4380 t.tm_mon = lpSystemTime->wMonth;
4381 t.tm_year = lpSystemTime->wYear;
4383 return TmToDATE( &t, pvtime );
4387 t.tm_sec = lpSystemTime->wSecond;
4388 t.tm_min = lpSystemTime->wMinute;
4389 t.tm_hour = lpSystemTime->wHour;
4391 if (isleap(lpSystemTime->wYear) )
4392 t.tm_mday = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4394 t.tm_mday = Days_Per_Month[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4396 t.tm_mon = 13 - lpSystemTime->wMonth;
4397 t.tm_year = 1900 + 1899 - lpSystemTime->wYear;
4399 TmToDATE( &t, pvtime );
4409 HRESULT WINAPI VariantTimeToSystemTime( double vtime, LPSYSTEMTIME lpSystemTime )
4411 double t = 0, timeofday = 0;
4413 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4414 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4416 /* The Month_Code is used to find the Day of the Week (LY = LeapYear)*/
4417 static const BYTE Month_Code[] = {0, 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4418 static const BYTE Month_Code_LY[] = {0, 0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4420 /* The Century_Code is used to find the Day of the Week */
4421 static const BYTE Century_Code[] = {0, 6, 4, 2};
4425 TRACE(" Variant = %f SYSTEMTIME ptr %p", vtime, lpSystemTime);
4430 if (DateToTm(vtime, (LCID)NULL, &r ) <= 0) return 0;
4432 lpSystemTime->wSecond = r.tm_sec;
4433 lpSystemTime->wMinute = r.tm_min;
4434 lpSystemTime->wHour = r.tm_hour;
4435 lpSystemTime->wDay = r.tm_mday;
4436 lpSystemTime->wMonth = r.tm_mon;
4438 if (lpSystemTime->wMonth == 12)
4439 lpSystemTime->wMonth = 1;
4441 lpSystemTime->wMonth++;
4443 lpSystemTime->wYear = r.tm_year;
4449 if (DateToTm(vtime, (LCID)NULL, &r ) <= 0) return 0;
4451 lpSystemTime->wSecond = r.tm_sec;
4452 lpSystemTime->wMinute = r.tm_min;
4453 lpSystemTime->wHour = r.tm_hour;
4455 lpSystemTime->wMonth = 13 - r.tm_mon;
4457 if (lpSystemTime->wMonth == 1)
4458 lpSystemTime->wMonth = 12;
4460 lpSystemTime->wMonth--;
4462 lpSystemTime->wYear = 1899 - (r.tm_year - 1900);
4464 if (!isleap(lpSystemTime->wYear) )
4465 lpSystemTime->wDay = Days_Per_Month[13 - lpSystemTime->wMonth] - r.tm_mday;
4467 lpSystemTime->wDay = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - r.tm_mday;
4472 if (!isleap(lpSystemTime->wYear))
4475 (Century_Code+Month_Code+Year_Code+Day) % 7
4477 The century code repeats every 400 years , so the array
4478 works out like this,
4480 Century_Code[0] is for 16th/20th Centry
4481 Century_Code[1] is for 17th/21th Centry
4482 Century_Code[2] is for 18th/22th Centry
4483 Century_Code[3] is for 19th/23th Centry
4485 The year code is found with the formula (year + (year / 4))
4486 the "year" must be between 0 and 99 .
4488 The Month Code (Month_Code[1]) starts with January and
4492 lpSystemTime->wDayOfWeek = (
4493 Century_Code[(( (lpSystemTime->wYear+100) - lpSystemTime->wYear%100) /100) %4]+
4494 ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4495 Month_Code[lpSystemTime->wMonth]+
4496 lpSystemTime->wDay) % 7;
4498 if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4499 else lpSystemTime->wDayOfWeek -= 1;
4503 lpSystemTime->wDayOfWeek = (
4504 Century_Code[(((lpSystemTime->wYear+100) - lpSystemTime->wYear%100)/100)%4]+
4505 ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4506 Month_Code_LY[lpSystemTime->wMonth]+
4507 lpSystemTime->wDay) % 7;
4509 if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4510 else lpSystemTime->wDayOfWeek -= 1;
4514 timeofday = vtime - t;
4516 lpSystemTime->wMilliseconds = (timeofday
4517 - lpSystemTime->wHour*(1/24)
4518 - lpSystemTime->wMinute*(1/1440)
4519 - lpSystemTime->wSecond*(1/86400) )*(1/5184000);
4524 HRESULT WINAPI VarUdateFromDate( DATE datein, ULONG dwFlags, UDATE *pudateout)
4527 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4528 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4530 TRACE("DATE = %f\n", (double)datein);
4531 i = VariantTimeToSystemTime(datein, &(pudateout->st) );
4535 pudateout->wDayOfYear = 0;
4537 if (isleap(pudateout->st.wYear))
4539 for (i =1; i<pudateout->st.wMonth; i++)
4540 pudateout->wDayOfYear += Days_Per_Month[i];
4544 for (i =1; i<pudateout->st.wMonth; i++)
4545 pudateout->wDayOfYear += Days_Per_Month_LY[i];
4548 pudateout->wDayOfYear += pudateout->st.wDay;
4549 dwFlags = 0; /*VAR_VALIDDATE*/
4556 HRESULT WINAPI VarDateFromUdate(UDATE *pudateout,
4557 ULONG dwFlags, DATE *datein)
4561 TRACE(" %d/%d/%d %d:%d:%d\n",
4562 pudateout->st.wMonth, pudateout->st.wDay,
4563 pudateout->st.wYear, pudateout->st.wHour,
4564 pudateout->st.wMinute, pudateout->st.wSecond);
4567 i = SystemTimeToVariantTime(&(pudateout->st), &t);
4570 if (i) dwFlags = 0; /*VAR_VALIDDATE*/