4 * Copyright 1998 Jean-Claude Cote
7 * This implements the low-level and hi-level APIs for manipulating VARIANTs.
8 * The low-level APIs are used to do data coercion between different data types.
9 * The hi-level APIs are built on top of these low-level APIs and handle
10 * initialization, copying, destroying and changing the type of VARIANTs.
13 * - The Variant APIs do not support international languages, currency
14 * types, number formating and calendar. They only support U.S. English format.
15 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
16 * The prototypes for these are commented out in the oleauto.h file. They need
17 * to be implemented and cases need to be added to the switches of the existing APIs.
18 * - The parsing of date for the VarDateFromStr is not complete.
19 * - The date manipulations do not support date prior to 1900.
20 * - The parsing does not accept has many formats has the Windows implementation.
26 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(ole
)
43 # define FLT_MAX MAXFLOAT
45 # error "Can't find #define for MAXFLOAT/FLT_MAX"
51 static const char CHAR_MAX
= 127;
52 static const char CHAR_MIN
= -128;
53 static const BYTE UI1_MAX
= 255;
54 static const BYTE UI1_MIN
= 0;
55 static const unsigned short UI2_MAX
= 65535;
56 static const unsigned short UI2_MIN
= 0;
57 static const short I2_MAX
= 32767;
58 static const short I2_MIN
= -32768;
59 static const unsigned long UI4_MAX
= 4294967295U;
60 static const unsigned long UI4_MIN
= 0;
61 static const long I4_MAX
= 2147483647;
62 static const long I4_MIN
= -(2147483648U);
63 static const DATE DATE_MIN
= -657434;
64 static const DATE DATE_MAX
= 2958465;
67 /* This mask is used to set a flag in wReserved1 of
68 * the VARIANTARG structure. The flag indicates if
69 * the API function is using an inner variant or not.
71 #define PROCESSING_INNER_VARIANT 0x0001
73 /* General use buffer.
75 #define BUFFER_MAX 1024
76 static char pBuffer
[BUFFER_MAX
];
79 * Note a leap year is one that is a multiple of 4
80 * but not of a 100. Except if it is a multiple of
81 * 400 then it is a leap year.
83 /* According to postgeSQL date parsing functions there is
84 * a leap year when this expression is true.
85 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
86 * So according to this there is 365.2515 days in one year.
87 * One + every four years: 1/4 -> 365.25
88 * One - every 100 years: 1/100 -> 365.001
89 * One + every 400 years: 1/400 -> 365.0025
91 static const double DAYS_IN_ONE_YEAR
= 365.2515;
95 /******************************************************************************
96 * DateTimeStringToTm [INTERNAL]
98 * Converts a string representation of a date and/or time to a tm structure.
100 * Note this function uses the postgresql date parsing functions found
101 * in the parsedt.c file.
103 * Returns TRUE if successfull.
105 * Note: This function does not parse the day of the week,
106 * daylight savings time. It will only fill the followin fields in
107 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
109 ******************************************************************************/
110 static BOOL
DateTimeStringToTm( OLECHAR
* strIn
, LCID lcid
, struct tm
* pTm
)
117 char *field
[MAXDATEFIELDS
];
118 int ftype
[MAXDATEFIELDS
];
119 char lowstr
[MAXDATELEN
+ 1];
120 char* strDateTime
= NULL
;
122 /* Convert the string to ASCII since this is the only format
123 * postgesql can handle.
125 strDateTime
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
127 if( strDateTime
!= NULL
)
129 /* Make sure we don't go over the maximum length
130 * accepted by postgesql.
132 if( strlen( strDateTime
) <= MAXDATELEN
)
134 if( ParseDateTime( strDateTime
, lowstr
, field
, ftype
, MAXDATEFIELDS
, &nf
) == 0 )
136 if( lcid
& VAR_DATEVALUEONLY
)
138 /* Get the date information.
139 * It returns 0 if date information was
140 * present and 1 if only time information was present.
141 * -1 if an error occures.
143 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) == 0 )
145 /* Eliminate the time information since we
146 * were asked to get date information only.
154 if( lcid
& VAR_TIMEVALUEONLY
)
156 /* Get time information only.
158 if( DecodeTimeOnly(field
, ftype
, nf
, &dtype
, pTm
, &fsec
) == 0 )
165 /* Get both date and time information.
166 * It returns 0 if date information was
167 * present and 1 if only time information was present.
168 * -1 if an error occures.
170 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) != -1 )
177 HeapFree( GetProcessHeap(), 0, strDateTime
);
188 /******************************************************************************
189 * TmToDATE [INTERNAL]
191 * The date is implemented using an 8 byte floating-point number.
192 * Days are represented by whole numbers increments starting with 0.00 has
193 * being December 30 1899, midnight.
194 * The hours are expressed as the fractional part of the number.
195 * December 30 1899 at midnight = 0.00
196 * January 1 1900 at midnight = 2.00
197 * January 4 1900 at 6 AM = 5.25
198 * January 4 1900 at noon = 5.50
199 * December 29 1899 at midnight = -1.00
200 * December 18 1899 at midnight = -12.00
201 * December 18 1899 at 6AM = -12.25
202 * December 18 1899 at 6PM = -12.75
203 * December 19 1899 at midnight = -11.00
204 * The tm structure is as follows:
206 * int tm_sec; seconds after the minute - [0,59]
207 * int tm_min; minutes after the hour - [0,59]
208 * int tm_hour; hours since midnight - [0,23]
209 * int tm_mday; day of the month - [1,31]
210 * int tm_mon; months since January - [0,11]
212 * int tm_wday; days since Sunday - [0,6]
213 * int tm_yday; days since January 1 - [0,365]
214 * int tm_isdst; daylight savings time flag
217 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
218 * and tm_isdst fields of the tm structure. And only converts years
221 * Returns TRUE if successfull.
223 static BOOL
TmToDATE( struct tm
* pTm
, DATE
*pDateOut
)
225 if( (pTm
->tm_year
- 1900) >= 0 )
229 /* Start at 1. This is the way DATE is defined.
230 * January 1, 1900 at Midnight is 1.00.
231 * January 1, 1900 at 6AM is 1.25.
236 /* Add the number of days corresponding to
239 *pDateOut
+= (pTm
->tm_year
- 1900) * 365;
241 /* Add the leap days in the previous years between now and 1900.
242 * Note a leap year is one that is a multiple of 4
243 * but not of a 100. Except if it is a multiple of
244 * 400 then it is a leap year.
246 *pDateOut
+= ( (pTm
->tm_year
- 1) / 4 ) - ( 1900 / 4 );
247 *pDateOut
-= ( (pTm
->tm_year
- 1) / 100 ) - ( 1900 / 100 );
248 *pDateOut
+= ( (pTm
->tm_year
- 1) / 400 ) - ( 1900 / 400 );
250 /* Set the leap year flag if the
251 * current year specified by tm_year is a
252 * leap year. This will be used to add a day
255 if( isleap( pTm
->tm_year
) )
258 /* Add the number of days corresponding to
261 switch( pTm
->tm_mon
)
267 *pDateOut
+= ( 59 + leapYear
);
270 *pDateOut
+= ( 90 + leapYear
);
273 *pDateOut
+= ( 120 + leapYear
);
276 *pDateOut
+= ( 151 + leapYear
);
279 *pDateOut
+= ( 181 + leapYear
);
282 *pDateOut
+= ( 212 + leapYear
);
285 *pDateOut
+= ( 243 + leapYear
);
288 *pDateOut
+= ( 273 + leapYear
);
291 *pDateOut
+= ( 304 + leapYear
);
294 *pDateOut
+= ( 334 + leapYear
);
297 /* Add the number of days in this month.
299 *pDateOut
+= pTm
->tm_mday
;
301 /* Add the number of seconds, minutes, and hours
302 * to the DATE. Note these are the fracionnal part
303 * of the DATE so seconds / number of seconds in a day.
305 *pDateOut
+= pTm
->tm_hour
/ 24.0;
306 *pDateOut
+= pTm
->tm_min
/ 1440.0;
307 *pDateOut
+= pTm
->tm_sec
/ 86400.0;
313 /******************************************************************************
314 * DateToTm [INTERNAL]
316 * This function converst a windows DATE to a tm structure.
318 * It does not fill all the fields of the tm structure.
319 * Here is a list of the fields that are filled:
320 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
322 * Note this function does not support dates before the January 1, 1900
323 * or ( dateIn < 2.0 ).
325 * Returns TRUE if successfull.
327 static BOOL
DateToTm( DATE dateIn
, LCID lcid
, struct tm
* pTm
)
329 /* Do not process dates smaller than January 1, 1900.
330 * Which corresponds to 2.0 in the windows DATE format.
334 double decimalPart
= 0.0;
335 double wholePart
= 0.0;
337 memset(pTm
,0,sizeof(*pTm
));
339 /* Because of the nature of DATE format witch
340 * associates 2.0 to January 1, 1900. We will
341 * remove 1.0 from the whole part of the DATE
342 * so that in the following code 1.0
343 * will correspond to January 1, 1900.
344 * This simplyfies the processing of the DATE value.
348 wholePart
= (double) floor( dateIn
);
349 decimalPart
= fmod( dateIn
, wholePart
);
351 if( !(lcid
& VAR_TIMEVALUEONLY
) )
355 double yearsSince1900
= 0;
356 /* Start at 1900, this where the DATE time 0.0 starts.
359 /* find in what year the day in the "wholePart" falls into.
360 * add the value to the year field.
362 yearsSince1900
= floor( wholePart
/ DAYS_IN_ONE_YEAR
);
363 pTm
->tm_year
+= yearsSince1900
;
364 /* determine if this is a leap year.
366 if( isleap( pTm
->tm_year
) )
368 /* find what day of that year does the "wholePart" corresponds to.
369 * Note: nDay is in [1-366] format
371 nDay
= (int) ( wholePart
- floor( yearsSince1900
* DAYS_IN_ONE_YEAR
) );
372 /* Set the tm_yday value.
373 * Note: The day is must be converted from [1-366] to [0-365]
375 /*pTm->tm_yday = nDay - 1;*/
376 /* find which mount this day corresponds to.
383 else if( nDay
<= ( 59 + leapYear
) )
385 pTm
->tm_mday
= nDay
- 31;
388 else if( nDay
<= ( 90 + leapYear
) )
390 pTm
->tm_mday
= nDay
- ( 59 + leapYear
);
393 else if( nDay
<= ( 120 + leapYear
) )
395 pTm
->tm_mday
= nDay
- ( 90 + leapYear
);
398 else if( nDay
<= ( 151 + leapYear
) )
400 pTm
->tm_mday
= nDay
- ( 120 + leapYear
);
403 else if( nDay
<= ( 181 + leapYear
) )
405 pTm
->tm_mday
= nDay
- ( 151 + leapYear
);
408 else if( nDay
<= ( 212 + leapYear
) )
410 pTm
->tm_mday
= nDay
- ( 181 + leapYear
);
413 else if( nDay
<= ( 243 + leapYear
) )
415 pTm
->tm_mday
= nDay
- ( 212 + leapYear
);
418 else if( nDay
<= ( 273 + leapYear
) )
420 pTm
->tm_mday
= nDay
- ( 243 + leapYear
);
423 else if( nDay
<= ( 304 + leapYear
) )
425 pTm
->tm_mday
= nDay
- ( 273 + leapYear
);
428 else if( nDay
<= ( 334 + leapYear
) )
430 pTm
->tm_mday
= nDay
- ( 304 + leapYear
);
433 else if( nDay
<= ( 365 + leapYear
) )
435 pTm
->tm_mday
= nDay
- ( 334 + leapYear
);
439 if( !(lcid
& VAR_DATEVALUEONLY
) )
441 /* find the number of seconds in this day.
442 * fractional part times, hours, minutes, seconds.
444 pTm
->tm_hour
= (int) ( decimalPart
* 24 );
445 pTm
->tm_min
= (int) ( ( ( decimalPart
* 24 ) - pTm
->tm_hour
) * 60 );
446 pTm
->tm_sec
= (int) ( ( ( decimalPart
* 24 * 60 ) - ( pTm
->tm_hour
* 60 ) - pTm
->tm_min
) * 60 );
455 /******************************************************************************
456 * SizeOfVariantData [INTERNAL]
458 * This function finds the size of the data referenced by a Variant based
459 * the type "vt" of the Variant.
461 static int SizeOfVariantData( VARIANT
* parg
)
464 switch( parg
->vt
& VT_TYPEMASK
)
467 size
= sizeof(short);
479 size
= sizeof(unsigned short);
482 size
= sizeof(unsigned int);
485 size
= sizeof(unsigned long);
488 size
= sizeof(float);
491 size
= sizeof(double);
497 size
= sizeof(VARIANT_BOOL
);
500 size
= sizeof(void*);
507 FIXME("Add size information for type vt=%d\n", parg
->vt
& VT_TYPEMASK
);
513 /******************************************************************************
514 * StringDupAtoBstr [INTERNAL]
517 static BSTR
StringDupAtoBstr( char* strIn
)
520 OLECHAR
* pNewString
= NULL
;
521 pNewString
= HEAP_strdupAtoW( GetProcessHeap(), 0, strIn
);
522 bstr
= SysAllocString( pNewString
);
523 HeapFree( GetProcessHeap(), 0, pNewString
);
527 /******************************************************************************
530 * Round the double value to the nearest integer value.
532 static double round( double d
)
534 double decimals
= 0.0, integerValue
= 0.0, roundedValue
= 0.0;
535 BOOL bEvenNumber
= FALSE
;
538 /* Save the sign of the number
540 nSign
= (d
>= 0.0) ? 1 : -1;
543 /* Remove the decimals.
545 integerValue
= floor( d
);
547 /* Set the Even flag. This is used to round the number when
548 * the decimals are exactly 1/2. If the integer part is
549 * odd the number is rounded up. If the integer part
550 * is even the number is rounded down. Using this method
551 * numbers are rounded up|down half the time.
553 bEvenNumber
= (((short)fmod(integerValue
, 2)) == 0) ? TRUE
: FALSE
;
555 /* Remove the integral part of the number.
557 decimals
= d
- integerValue
;
559 /* Note: Ceil returns the smallest integer that is greater that x.
560 * and floor returns the largest integer that is less than or equal to x.
564 /* If the decimal part is greater than 1/2
566 roundedValue
= ceil( d
);
568 else if( decimals
< 0.5 )
570 /* If the decimal part is smaller than 1/2
572 roundedValue
= floor( d
);
576 /* the decimals are exactly 1/2 so round according to
577 * the bEvenNumber flag.
581 roundedValue
= floor( d
);
585 roundedValue
= ceil( d
);
589 return roundedValue
* nSign
;
592 /******************************************************************************
593 * RemoveCharacterFromString [INTERNAL]
595 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
597 static void RemoveCharacterFromString( LPSTR str
, LPSTR strOfCharToRemove
)
599 LPSTR pNewString
= NULL
;
600 LPSTR strToken
= NULL
;
603 /* Check if we have a valid argument
607 pNewString
= strdup( str
);
609 strToken
= strtok( pNewString
, strOfCharToRemove
);
610 while( strToken
!= NULL
) {
611 strcat( str
, strToken
);
612 strToken
= strtok( NULL
, strOfCharToRemove
);
619 /******************************************************************************
620 * GetValidRealString [INTERNAL]
622 * Checks if the string is of proper format to be converted to a real value.
624 static BOOL
IsValidRealString( LPSTR strRealString
)
626 /* Real values that have a decimal point are required to either have
627 * digits before or after the decimal point. We will assume that
628 * we do not have any digits at either position. If we do encounter
629 * some we will disable this flag.
631 BOOL bDigitsRequired
= TRUE
;
632 /* Processed fields in the string representation of the real number.
634 BOOL bWhiteSpaceProcessed
= FALSE
;
635 BOOL bFirstSignProcessed
= FALSE
;
636 BOOL bFirstDigitsProcessed
= FALSE
;
637 BOOL bDecimalPointProcessed
= FALSE
;
638 BOOL bSecondDigitsProcessed
= FALSE
;
639 BOOL bExponentProcessed
= FALSE
;
640 BOOL bSecondSignProcessed
= FALSE
;
641 BOOL bThirdDigitsProcessed
= FALSE
;
642 /* Assume string parameter "strRealString" is valid and try to disprove it.
644 BOOL bValidRealString
= TRUE
;
646 /* Used to count the number of tokens in the "strRealString".
648 LPSTR strToken
= NULL
;
652 /* Check if we have a valid argument
654 if( strRealString
== NULL
)
656 bValidRealString
= FALSE
;
659 if( bValidRealString
== TRUE
)
661 /* Make sure we only have ONE token in the string.
663 strToken
= strtok( strRealString
, " " );
664 while( strToken
!= NULL
) {
666 strToken
= strtok( NULL
, " " );
671 bValidRealString
= FALSE
;
676 /* Make sure this token contains only valid characters.
677 * The string argument to atof has the following form:
678 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
679 * Whitespace consists of space and|or <TAB> characters, which are ignored.
680 * Sign is either plus '+' or minus '-'.
681 * Digits are one or more decimal digits.
682 * Note: If no digits appear before the decimal point, at least one must
683 * appear after the decimal point.
684 * The decimal digits may be followed by an exponent.
685 * An Exponent consists of an introductory letter ( D, d, E, or e) and
686 * an optionally signed decimal integer.
688 pChar
= strRealString
;
689 while( bValidRealString
== TRUE
&& *pChar
!= '\0' )
697 if( bWhiteSpaceProcessed
||
698 bFirstSignProcessed
||
699 bFirstDigitsProcessed
||
700 bDecimalPointProcessed
||
701 bSecondDigitsProcessed
||
702 bExponentProcessed
||
703 bSecondSignProcessed
||
704 bThirdDigitsProcessed
)
706 bValidRealString
= FALSE
;
713 if( bFirstSignProcessed
== FALSE
)
715 if( bFirstDigitsProcessed
||
716 bDecimalPointProcessed
||
717 bSecondDigitsProcessed
||
718 bExponentProcessed
||
719 bSecondSignProcessed
||
720 bThirdDigitsProcessed
)
722 bValidRealString
= FALSE
;
724 bWhiteSpaceProcessed
= TRUE
;
725 bFirstSignProcessed
= TRUE
;
727 else if( bSecondSignProcessed
== FALSE
)
729 /* Note: The exponent must be present in
730 * order to accept the second sign...
732 if( bExponentProcessed
== FALSE
||
733 bThirdDigitsProcessed
||
736 bValidRealString
= FALSE
;
738 bFirstSignProcessed
= TRUE
;
739 bWhiteSpaceProcessed
= TRUE
;
740 bFirstDigitsProcessed
= TRUE
;
741 bDecimalPointProcessed
= TRUE
;
742 bSecondDigitsProcessed
= TRUE
;
743 bSecondSignProcessed
= TRUE
;
759 if( bFirstDigitsProcessed
== FALSE
)
761 if( bDecimalPointProcessed
||
762 bSecondDigitsProcessed
||
763 bExponentProcessed
||
764 bSecondSignProcessed
||
765 bThirdDigitsProcessed
)
767 bValidRealString
= FALSE
;
769 bFirstSignProcessed
= TRUE
;
770 bWhiteSpaceProcessed
= TRUE
;
771 /* We have found some digits before the decimal point
772 * so disable the "Digits required" flag.
774 bDigitsRequired
= FALSE
;
776 else if( bSecondDigitsProcessed
== FALSE
)
778 if( bExponentProcessed
||
779 bSecondSignProcessed
||
780 bThirdDigitsProcessed
)
782 bValidRealString
= FALSE
;
784 bFirstSignProcessed
= TRUE
;
785 bWhiteSpaceProcessed
= TRUE
;
786 bFirstDigitsProcessed
= TRUE
;
787 bDecimalPointProcessed
= TRUE
;
788 /* We have found some digits after the decimal point
789 * so disable the "Digits required" flag.
791 bDigitsRequired
= FALSE
;
793 else if( bThirdDigitsProcessed
== FALSE
)
795 /* Getting here means everything else should be processed.
796 * If we get anything else than a decimal following this
797 * digit it will be flagged by the other cases, so
798 * we do not really need to do anything in here.
802 /* If DecimalPoint...
805 if( bDecimalPointProcessed
||
806 bSecondDigitsProcessed
||
807 bExponentProcessed
||
808 bSecondSignProcessed
||
809 bThirdDigitsProcessed
)
811 bValidRealString
= FALSE
;
813 bFirstSignProcessed
= TRUE
;
814 bWhiteSpaceProcessed
= TRUE
;
815 bFirstDigitsProcessed
= TRUE
;
816 bDecimalPointProcessed
= TRUE
;
824 if( bExponentProcessed
||
825 bSecondSignProcessed
||
826 bThirdDigitsProcessed
||
829 bValidRealString
= FALSE
;
831 bFirstSignProcessed
= TRUE
;
832 bWhiteSpaceProcessed
= TRUE
;
833 bFirstDigitsProcessed
= TRUE
;
834 bDecimalPointProcessed
= TRUE
;
835 bSecondDigitsProcessed
= TRUE
;
836 bExponentProcessed
= TRUE
;
839 bValidRealString
= FALSE
;
842 /* Process next character.
847 /* If the required digits were not present we have an invalid
848 * string representation of a real number.
850 if( bDigitsRequired
== TRUE
)
852 bValidRealString
= FALSE
;
855 return bValidRealString
;
859 /******************************************************************************
862 * This function dispatches execution to the proper conversion API
863 * to do the necessary coercion.
865 static HRESULT
Coerce( VARIANTARG
* pd
, LCID lcid
, ULONG dwFlags
, VARIANTARG
* ps
, VARTYPE vt
)
868 unsigned short vtFrom
= 0;
869 vtFrom
= ps
->vt
& VT_TYPEMASK
;
871 /* Note: Since "long" and "int" values both have 4 bytes and are both signed integers
872 * "int" will be treated as "long" in the following code.
873 * The same goes for there unsigned versions.
880 res
= VariantClear( pd
);
883 res
= VariantClear( pd
);
893 res
= VariantCopy( pd
, ps
);
896 res
= VarI1FromI2( ps
->u
.iVal
, &(pd
->u
.cVal
) );
900 res
= VarI1FromI4( ps
->u
.lVal
, &(pd
->u
.cVal
) );
903 res
= VarI1FromUI1( ps
->u
.bVal
, &(pd
->u
.cVal
) );
906 res
= VarI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.cVal
) );
910 res
= VarI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.cVal
) );
913 res
= VarI1FromR4( ps
->u
.fltVal
, &(pd
->u
.cVal
) );
916 res
= VarI1FromR8( ps
->u
.dblVal
, &(pd
->u
.cVal
) );
919 res
= VarI1FromDate( ps
->u
.date
, &(pd
->u
.cVal
) );
922 res
= VarI1FromBool( ps
->u
.boolVal
, &(pd
->u
.cVal
) );
925 res
= VarI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.cVal
) );
928 res
= VarI1FromCy( ps
->u
.cyVal
, &(pd
->u
.cVal
) );
930 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
932 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
934 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
936 res
= DISP_E_TYPEMISMATCH
;
937 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
946 res
= VarI2FromI1( ps
->u
.cVal
, &(pd
->u
.iVal
) );
949 res
= VariantCopy( pd
, ps
);
953 res
= VarI2FromI4( ps
->u
.lVal
, &(pd
->u
.iVal
) );
956 res
= VarI2FromUI1( ps
->u
.bVal
, &(pd
->u
.iVal
) );
959 res
= VarI2FromUI2( ps
->u
.uiVal
, &(pd
->u
.iVal
) );
963 res
= VarI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.iVal
) );
966 res
= VarI2FromR4( ps
->u
.fltVal
, &(pd
->u
.iVal
) );
969 res
= VarI2FromR8( ps
->u
.dblVal
, &(pd
->u
.iVal
) );
972 res
= VarI2FromDate( ps
->u
.date
, &(pd
->u
.iVal
) );
975 res
= VarI2FromBool( ps
->u
.boolVal
, &(pd
->u
.iVal
) );
978 res
= VarI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.iVal
) );
981 res
= VarI2FromCy( ps
->u
.cyVal
, &(pd
->u
.iVal
) );
983 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
985 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
987 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
989 res
= DISP_E_TYPEMISMATCH
;
990 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1000 res
= VarI4FromI1( ps
->u
.cVal
, &(pd
->u
.lVal
) );
1003 res
= VarI4FromI2( ps
->u
.iVal
, &(pd
->u
.lVal
) );
1007 res
= VariantCopy( pd
, ps
);
1010 res
= VarI4FromUI1( ps
->u
.bVal
, &(pd
->u
.lVal
) );
1013 res
= VarI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.lVal
) );
1017 res
= VarI4FromUI4( ps
->u
.ulVal
, &(pd
->u
.lVal
) );
1020 res
= VarI4FromR4( ps
->u
.fltVal
, &(pd
->u
.lVal
) );
1023 res
= VarI4FromR8( ps
->u
.dblVal
, &(pd
->u
.lVal
) );
1026 res
= VarI4FromDate( ps
->u
.date
, &(pd
->u
.lVal
) );
1029 res
= VarI4FromBool( ps
->u
.boolVal
, &(pd
->u
.lVal
) );
1032 res
= VarI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.lVal
) );
1035 res
= VarI4FromCy( ps
->u
.cyVal
, &(pd
->u
.lVal
) );
1036 case( VT_DISPATCH
):
1037 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1039 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1041 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1043 res
= DISP_E_TYPEMISMATCH
;
1044 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1053 res
= VarUI1FromI1( ps
->u
.cVal
, &(pd
->u
.bVal
) );
1056 res
= VarUI1FromI2( ps
->u
.iVal
, &(pd
->u
.bVal
) );
1060 res
= VarUI1FromI4( ps
->u
.lVal
, &(pd
->u
.bVal
) );
1063 res
= VariantCopy( pd
, ps
);
1066 res
= VarUI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.bVal
) );
1070 res
= VarUI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.bVal
) );
1073 res
= VarUI1FromR4( ps
->u
.fltVal
, &(pd
->u
.bVal
) );
1076 res
= VarUI1FromR8( ps
->u
.dblVal
, &(pd
->u
.bVal
) );
1079 res
= VarUI1FromDate( ps
->u
.date
, &(pd
->u
.bVal
) );
1082 res
= VarUI1FromBool( ps
->u
.boolVal
, &(pd
->u
.bVal
) );
1085 res
= VarUI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.bVal
) );
1088 res
= VarUI1FromCy( ps
->u
.cyVal
, &(pd
->u
.bVal
) );
1089 case( VT_DISPATCH
):
1090 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1092 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1094 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1096 res
= DISP_E_TYPEMISMATCH
;
1097 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1106 res
= VarUI2FromI1( ps
->u
.cVal
, &(pd
->u
.uiVal
) );
1109 res
= VarUI2FromI2( ps
->u
.iVal
, &(pd
->u
.uiVal
) );
1113 res
= VarUI2FromI4( ps
->u
.lVal
, &(pd
->u
.uiVal
) );
1116 res
= VarUI2FromUI1( ps
->u
.bVal
, &(pd
->u
.uiVal
) );
1119 res
= VariantCopy( pd
, ps
);
1123 res
= VarUI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.uiVal
) );
1126 res
= VarUI2FromR4( ps
->u
.fltVal
, &(pd
->u
.uiVal
) );
1129 res
= VarUI2FromR8( ps
->u
.dblVal
, &(pd
->u
.uiVal
) );
1132 res
= VarUI2FromDate( ps
->u
.date
, &(pd
->u
.uiVal
) );
1135 res
= VarUI2FromBool( ps
->u
.boolVal
, &(pd
->u
.uiVal
) );
1138 res
= VarUI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.uiVal
) );
1141 res
= VarUI2FromCy( ps
->u
.cyVal
, &(pd
->u
.uiVal
) );
1142 case( VT_DISPATCH
):
1143 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1145 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1147 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1149 res
= DISP_E_TYPEMISMATCH
;
1150 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1160 res
= VarUI4FromI1( ps
->u
.cVal
, &(pd
->u
.ulVal
) );
1163 res
= VarUI4FromI2( ps
->u
.iVal
, &(pd
->u
.ulVal
) );
1167 res
= VarUI4FromI4( ps
->u
.lVal
, &(pd
->u
.ulVal
) );
1170 res
= VarUI4FromUI1( ps
->u
.bVal
, &(pd
->u
.ulVal
) );
1173 res
= VarUI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.ulVal
) );
1176 res
= VariantCopy( pd
, ps
);
1179 res
= VarUI4FromR4( ps
->u
.fltVal
, &(pd
->u
.ulVal
) );
1182 res
= VarUI4FromR8( ps
->u
.dblVal
, &(pd
->u
.ulVal
) );
1185 res
= VarUI4FromDate( ps
->u
.date
, &(pd
->u
.ulVal
) );
1188 res
= VarUI4FromBool( ps
->u
.boolVal
, &(pd
->u
.ulVal
) );
1191 res
= VarUI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.ulVal
) );
1194 res
= VarUI4FromCy( ps
->u
.cyVal
, &(pd
->u
.ulVal
) );
1195 case( VT_DISPATCH
):
1196 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1198 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1200 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1202 res
= DISP_E_TYPEMISMATCH
;
1203 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1212 res
= VarR4FromI1( ps
->u
.cVal
, &(pd
->u
.fltVal
) );
1215 res
= VarR4FromI2( ps
->u
.iVal
, &(pd
->u
.fltVal
) );
1219 res
= VarR4FromI4( ps
->u
.lVal
, &(pd
->u
.fltVal
) );
1222 res
= VarR4FromUI1( ps
->u
.bVal
, &(pd
->u
.fltVal
) );
1225 res
= VarR4FromUI2( ps
->u
.uiVal
, &(pd
->u
.fltVal
) );
1229 res
= VarR4FromUI4( ps
->u
.ulVal
, &(pd
->u
.fltVal
) );
1232 res
= VariantCopy( pd
, ps
);
1235 res
= VarR4FromR8( ps
->u
.dblVal
, &(pd
->u
.fltVal
) );
1238 res
= VarR4FromDate( ps
->u
.date
, &(pd
->u
.fltVal
) );
1241 res
= VarR4FromBool( ps
->u
.boolVal
, &(pd
->u
.fltVal
) );
1244 res
= VarR4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.fltVal
) );
1247 res
= VarR4FromCy( ps
->u
.cyVal
, &(pd
->u
.fltVal
) );
1248 case( VT_DISPATCH
):
1249 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1251 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1253 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1255 res
= DISP_E_TYPEMISMATCH
;
1256 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1265 res
= VarR8FromI1( ps
->u
.cVal
, &(pd
->u
.dblVal
) );
1268 res
= VarR8FromI2( ps
->u
.iVal
, &(pd
->u
.dblVal
) );
1272 res
= VarR8FromI4( ps
->u
.lVal
, &(pd
->u
.dblVal
) );
1275 res
= VarR8FromUI1( ps
->u
.bVal
, &(pd
->u
.dblVal
) );
1278 res
= VarR8FromUI2( ps
->u
.uiVal
, &(pd
->u
.dblVal
) );
1282 res
= VarR8FromUI4( ps
->u
.ulVal
, &(pd
->u
.dblVal
) );
1285 res
= VarR8FromR4( ps
->u
.fltVal
, &(pd
->u
.dblVal
) );
1288 res
= VariantCopy( pd
, ps
);
1291 res
= VarR8FromDate( ps
->u
.date
, &(pd
->u
.dblVal
) );
1294 res
= VarR8FromBool( ps
->u
.boolVal
, &(pd
->u
.dblVal
) );
1297 res
= VarR8FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.dblVal
) );
1300 res
= VarR8FromCy( ps
->u
.cyVal
, &(pd
->u
.dblVal
) );
1301 case( VT_DISPATCH
):
1302 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1304 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1306 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1308 res
= DISP_E_TYPEMISMATCH
;
1309 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1318 res
= VarDateFromI1( ps
->u
.cVal
, &(pd
->u
.date
) );
1321 res
= VarDateFromI2( ps
->u
.iVal
, &(pd
->u
.date
) );
1324 res
= VarDateFromInt( ps
->u
.intVal
, &(pd
->u
.date
) );
1327 res
= VarDateFromI4( ps
->u
.lVal
, &(pd
->u
.date
) );
1330 res
= VarDateFromUI1( ps
->u
.bVal
, &(pd
->u
.date
) );
1333 res
= VarDateFromUI2( ps
->u
.uiVal
, &(pd
->u
.date
) );
1336 res
= VarDateFromUint( ps
->u
.uintVal
, &(pd
->u
.date
) );
1339 res
= VarDateFromUI4( ps
->u
.ulVal
, &(pd
->u
.date
) );
1342 res
= VarDateFromR4( ps
->u
.fltVal
, &(pd
->u
.date
) );
1345 res
= VarDateFromR8( ps
->u
.dblVal
, &(pd
->u
.date
) );
1348 res
= VariantCopy( pd
, ps
);
1351 res
= VarDateFromBool( ps
->u
.boolVal
, &(pd
->u
.date
) );
1354 res
= VarDateFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.date
) );
1357 res
= VarDateFromCy( ps
->u
.cyVal
, &(pd
->u
.date
) );
1358 case( VT_DISPATCH
):
1359 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1361 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1363 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1365 res
= DISP_E_TYPEMISMATCH
;
1366 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1375 res
= VarBoolFromI1( ps
->u
.cVal
, &(pd
->u
.boolVal
) );
1378 res
= VarBoolFromI2( ps
->u
.iVal
, &(pd
->u
.boolVal
) );
1381 res
= VarBoolFromInt( ps
->u
.intVal
, &(pd
->u
.boolVal
) );
1384 res
= VarBoolFromI4( ps
->u
.lVal
, &(pd
->u
.boolVal
) );
1387 res
= VarBoolFromUI1( ps
->u
.bVal
, &(pd
->u
.boolVal
) );
1390 res
= VarBoolFromUI2( ps
->u
.uiVal
, &(pd
->u
.boolVal
) );
1393 res
= VarBoolFromUint( ps
->u
.uintVal
, &(pd
->u
.boolVal
) );
1396 res
= VarBoolFromUI4( ps
->u
.ulVal
, &(pd
->u
.boolVal
) );
1399 res
= VarBoolFromR4( ps
->u
.fltVal
, &(pd
->u
.boolVal
) );
1402 res
= VarBoolFromR8( ps
->u
.dblVal
, &(pd
->u
.boolVal
) );
1405 res
= VarBoolFromDate( ps
->u
.date
, &(pd
->u
.boolVal
) );
1408 res
= VariantCopy( pd
, ps
);
1411 res
= VarBoolFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.boolVal
) );
1414 res
= VarBoolFromCy( ps
->u
.cyVal
, &(pd
->u
.boolVal
) );
1415 case( VT_DISPATCH
):
1416 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1418 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1420 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1422 res
= DISP_E_TYPEMISMATCH
;
1423 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1432 res
= VarBstrFromI1( ps
->u
.cVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1435 res
= VarBstrFromI2( ps
->u
.iVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1438 res
= VarBstrFromInt( ps
->u
.intVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1441 res
= VarBstrFromI4( ps
->u
.lVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1444 res
= VarBstrFromUI1( ps
->u
.bVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1447 res
= VarBstrFromUI2( ps
->u
.uiVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1450 res
= VarBstrFromUint( ps
->u
.uintVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1453 res
= VarBstrFromUI4( ps
->u
.ulVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1456 res
= VarBstrFromR4( ps
->u
.fltVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1459 res
= VarBstrFromR8( ps
->u
.dblVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1462 res
= VarBstrFromDate( ps
->u
.date
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1465 res
= VarBstrFromBool( ps
->u
.boolVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1468 res
= VariantCopy( pd
, ps
);
1471 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1472 case( VT_DISPATCH
):
1473 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1475 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1477 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1479 res
= DISP_E_TYPEMISMATCH
;
1480 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1489 res
= VarCyFromI1( ps
->u
.cVal
, &(pd
->u
.cyVal
) );
1492 res
= VarCyFromI2( ps
->u
.iVal
, &(pd
->u
.cyVal
) );
1495 res
= VarCyFromInt( ps
->u
.intVal
, &(pd
->u
.cyVal
) );
1498 res
= VarCyFromI4( ps
->u
.lVal
, &(pd
->u
.cyVal
) );
1501 res
= VarCyFromUI1( ps
->u
.bVal
, &(pd
->u
.cyVal
) );
1504 res
= VarCyFromUI2( ps
->u
.uiVal
, &(pd
->u
.cyVal
) );
1507 res
= VarCyFromUint( ps
->u
.uintVal
, &(pd
->u
.cyVal
) );
1510 res
= VarCyFromUI4( ps
->u
.ulVal
, &(pd
->u
.cyVal
) );
1513 res
= VarCyFromR4( ps
->u
.fltVal
, &(pd
->u
.cyVal
) );
1516 res
= VarCyFromR8( ps
->u
.dblVal
, &(pd
->u
.cyVal
) );
1519 res
= VarCyFromDate( ps
->u
.date
, &(pd
->u
.cyVal
) );
1522 res
= VarCyFromBool( ps
->u
.date
, &(pd
->u
.cyVal
) );
1525 res
= VariantCopy( pd
, ps
);
1528 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1529 case( VT_DISPATCH
):
1530 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1532 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1534 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1536 res
= DISP_E_TYPEMISMATCH
;
1537 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1543 res
= DISP_E_TYPEMISMATCH
;
1544 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1551 /******************************************************************************
1552 * ValidateVtRange [INTERNAL]
1554 * Used internally by the hi-level Variant API to determine
1555 * if the vartypes are valid.
1557 static HRESULT WINAPI
ValidateVtRange( VARTYPE vt
)
1559 /* if by value we must make sure it is in the
1560 * range of the valid types.
1562 if( ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1564 return DISP_E_BADVARTYPE
;
1570 /******************************************************************************
1571 * ValidateVartype [INTERNAL]
1573 * Used internally by the hi-level Variant API to determine
1574 * if the vartypes are valid.
1576 static HRESULT WINAPI
ValidateVariantType( VARTYPE vt
)
1580 /* check if we have a valid argument.
1584 /* if by reference check that the type is in
1585 * the valid range and that it is not of empty or null type
1587 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1588 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1589 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1597 res
= ValidateVtRange( vt
);
1603 /******************************************************************************
1604 * ValidateVt [INTERNAL]
1606 * Used internally by the hi-level Variant API to determine
1607 * if the vartypes are valid.
1609 static HRESULT WINAPI
ValidateVt( VARTYPE vt
)
1613 /* check if we have a valid argument.
1617 /* if by reference check that the type is in
1618 * the valid range and that it is not of empty or null type
1620 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1621 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1622 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1624 res
= DISP_E_BADVARTYPE
;
1630 res
= ValidateVtRange( vt
);
1640 /******************************************************************************
1641 * VariantInit32 [OLEAUT32.8]
1643 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1644 * contents of the Variant.
1646 void WINAPI
VariantInit(VARIANTARG
* pvarg
)
1648 TRACE("(%p),stub\n",pvarg
);
1650 memset(pvarg
, 0, sizeof (VARIANTARG
));
1651 pvarg
->vt
= VT_EMPTY
;
1656 /******************************************************************************
1657 * VariantClear32 [OLEAUT32.9]
1659 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1660 * sets the wReservedX field to 0. The current contents of the VARIANT are
1661 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1662 * released. If VT_ARRAY the array is freed.
1664 HRESULT WINAPI
VariantClear(VARIANTARG
* pvarg
)
1667 TRACE("(%p)\n",pvarg
);
1669 res
= ValidateVariantType( pvarg
->vt
);
1672 if( !( pvarg
->vt
& VT_BYREF
) )
1675 * The VT_ARRAY flag is a special case of a safe array.
1677 if ( (pvarg
->vt
& VT_ARRAY
) != 0)
1679 SafeArrayDestroy(pvarg
->u
.parray
);
1683 switch( pvarg
->vt
& VT_TYPEMASK
)
1686 SysFreeString( pvarg
->u
.bstrVal
);
1688 case( VT_DISPATCH
):
1694 case( VT_SAFEARRAY
):
1695 SafeArrayDestroy(pvarg
->u
.parray
);
1704 * Empty all the fields and mark the type as empty.
1706 memset(pvarg
, 0, sizeof (VARIANTARG
));
1707 pvarg
->vt
= VT_EMPTY
;
1713 /******************************************************************************
1714 * VariantCopy32 [OLEAUT32.10]
1716 * Frees up the designation variant and makes a copy of the source.
1718 HRESULT WINAPI
VariantCopy(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
)
1722 TRACE("(%p, %p)\n", pvargDest
, pvargSrc
);
1724 res
= ValidateVariantType( pvargSrc
->vt
);
1726 /* If the pointer are to the same variant we don't need
1729 if( pvargDest
!= pvargSrc
&& res
== S_OK
)
1731 res
= VariantClear( pvargDest
);
1735 if( pvargSrc
->vt
& VT_BYREF
)
1737 /* In the case of byreference we only need
1738 * to copy the pointer.
1740 pvargDest
->u
= pvargSrc
->u
;
1741 pvargDest
->vt
= pvargSrc
->vt
;
1746 * The VT_ARRAY flag is another way to designate a safe array.
1748 if (pvargSrc
->vt
& VT_ARRAY
)
1750 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1754 /* In the case of by value we need to
1755 * copy the actuall value. In the case of
1756 * VT_BSTR a copy of the string is made,
1757 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1758 * called to increment the object's reference count.
1760 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1763 pvargDest
->u
.bstrVal
= SysAllocString( pvargSrc
->u
.bstrVal
);
1765 case( VT_DISPATCH
):
1771 case( VT_SAFEARRAY
):
1772 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1775 pvargDest
->u
= pvargSrc
->u
;
1780 pvargDest
->vt
= pvargSrc
->vt
;
1789 /******************************************************************************
1790 * VariantCopyInd32 [OLEAUT32.11]
1792 * Frees up the destination variant and makes a copy of the source. If
1793 * the source is of type VT_BYREF it performs the necessary indirections.
1795 HRESULT WINAPI
VariantCopyInd(VARIANT
* pvargDest
, VARIANTARG
* pvargSrc
)
1799 TRACE("(%p, %p)\n", pvargDest
, pvargSrc
);
1801 res
= ValidateVariantType( pvargSrc
->vt
);
1806 if( pvargSrc
->vt
& VT_BYREF
)
1809 VariantInit( &varg
);
1811 /* handle the in place copy.
1813 if( pvargDest
== pvargSrc
)
1815 /* we will use a copy of the source instead.
1817 res
= VariantCopy( &varg
, pvargSrc
);
1823 res
= VariantClear( pvargDest
);
1828 * The VT_ARRAY flag is another way to designate a safearray variant.
1830 if ( pvargSrc
->vt
& VT_ARRAY
)
1832 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1836 /* In the case of by reference we need
1837 * to copy the date pointed to by the variant.
1840 /* Get the variant type.
1842 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1845 pvargDest
->u
.bstrVal
= SysAllocString( *(pvargSrc
->u
.pbstrVal
) );
1847 case( VT_DISPATCH
):
1851 /* Prevent from cycling. According to tests on
1852 * VariantCopyInd in Windows and the documentation
1853 * this API dereferences the inner Variants to only one depth.
1854 * If the inner Variant itself contains an
1855 * other inner variant the E_INVALIDARG error is
1858 if( pvargSrc
->wReserved1
& PROCESSING_INNER_VARIANT
)
1860 /* If we get here we are attempting to deference
1861 * an inner variant that that is itself contained
1862 * in an inner variant so report E_INVALIDARG error.
1868 /* Set the processing inner variant flag.
1869 * We will set this flag in the inner variant
1870 * that will be passed to the VariantCopyInd function.
1872 (pvargSrc
->u
.pvarVal
)->wReserved1
|= PROCESSING_INNER_VARIANT
;
1874 /* Dereference the inner variant.
1876 res
= VariantCopyInd( pvargDest
, pvargSrc
->u
.pvarVal
);
1882 case( VT_SAFEARRAY
):
1883 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1886 /* This is a by reference Variant which means that the union
1887 * part of the Variant contains a pointer to some data of
1888 * type "pvargSrc->vt & VT_TYPEMASK".
1889 * We will deference this data in a generic fashion using
1890 * the void pointer "Variant.u.byref".
1891 * We will copy this data into the union of the destination
1894 memcpy( &pvargDest
->u
, pvargSrc
->u
.byref
, SizeOfVariantData( pvargSrc
) );
1899 pvargDest
->vt
= pvargSrc
->vt
& VT_TYPEMASK
;
1903 /* this should not fail.
1905 VariantClear( &varg
);
1909 res
= VariantCopy( pvargDest
, pvargSrc
);
1915 /******************************************************************************
1916 * VariantChangeType32 [OLEAUT32.12]
1918 HRESULT WINAPI
VariantChangeType(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1919 USHORT wFlags
, VARTYPE vt
)
1921 return VariantChangeTypeEx( pvargDest
, pvargSrc
, 0, wFlags
, vt
);
1924 /******************************************************************************
1925 * VariantChangeTypeEx32 [OLEAUT32.147]
1927 HRESULT WINAPI
VariantChangeTypeEx(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1928 LCID lcid
, USHORT wFlags
, VARTYPE vt
)
1932 VariantInit( &varg
);
1934 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest
, pvargSrc
, lcid
, wFlags
, vt
);
1936 /* validate our source argument.
1938 res
= ValidateVariantType( pvargSrc
->vt
);
1940 /* validate the vartype.
1944 res
= ValidateVt( vt
);
1947 /* if we are doing an in-place conversion make a copy of the source.
1949 if( res
== S_OK
&& pvargDest
== pvargSrc
)
1951 res
= VariantCopy( &varg
, pvargSrc
);
1957 /* free up the destination variant.
1959 res
= VariantClear( pvargDest
);
1964 if( pvargSrc
->vt
& VT_BYREF
)
1966 /* Convert the source variant to a "byvalue" variant.
1969 VariantInit( &Variant
);
1970 res
= VariantCopyInd( &Variant
, pvargSrc
);
1973 res
= Coerce( pvargDest
, lcid
, wFlags
, &Variant
, vt
);
1974 /* this should not fail.
1976 VariantClear( &Variant
);
1982 /* Use the current "byvalue" source variant.
1984 res
= Coerce( pvargDest
, lcid
, wFlags
, pvargSrc
, vt
);
1987 /* this should not fail.
1989 VariantClear( &varg
);
1991 /* set the type of the destination
2002 /******************************************************************************
2003 * VarUI1FromI232 [OLEAUT32.130]
2005 HRESULT WINAPI
VarUI1FromI2(short sIn
, BYTE
* pbOut
)
2007 TRACE("( %d, %p ), stub\n", sIn
, pbOut
);
2009 /* Check range of value.
2011 if( sIn
< UI1_MIN
|| sIn
> UI1_MAX
)
2013 return DISP_E_OVERFLOW
;
2016 *pbOut
= (BYTE
) sIn
;
2021 /******************************************************************************
2022 * VarUI1FromI432 [OLEAUT32.131]
2024 HRESULT WINAPI
VarUI1FromI4(LONG lIn
, BYTE
* pbOut
)
2026 TRACE("( %ld, %p ), stub\n", lIn
, pbOut
);
2028 /* Check range of value.
2030 if( lIn
< UI1_MIN
|| lIn
> UI1_MAX
)
2032 return DISP_E_OVERFLOW
;
2035 *pbOut
= (BYTE
) lIn
;
2041 /******************************************************************************
2042 * VarUI1FromR432 [OLEAUT32.132]
2044 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
2046 TRACE("( %f, %p ), stub\n", fltIn
, pbOut
);
2048 /* Check range of value.
2050 fltIn
= round( fltIn
);
2051 if( fltIn
< UI1_MIN
|| fltIn
> UI1_MAX
)
2053 return DISP_E_OVERFLOW
;
2056 *pbOut
= (BYTE
) fltIn
;
2061 /******************************************************************************
2062 * VarUI1FromR832 [OLEAUT32.133]
2064 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
2066 TRACE("( %f, %p ), stub\n", dblIn
, pbOut
);
2068 /* Check range of value.
2070 dblIn
= round( dblIn
);
2071 if( dblIn
< UI1_MIN
|| dblIn
> UI1_MAX
)
2073 return DISP_E_OVERFLOW
;
2076 *pbOut
= (BYTE
) dblIn
;
2081 /******************************************************************************
2082 * VarUI1FromDate32 [OLEAUT32.135]
2084 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
2086 TRACE("( %f, %p ), stub\n", dateIn
, pbOut
);
2088 /* Check range of value.
2090 dateIn
= round( dateIn
);
2091 if( dateIn
< UI1_MIN
|| dateIn
> UI1_MAX
)
2093 return DISP_E_OVERFLOW
;
2096 *pbOut
= (BYTE
) dateIn
;
2101 /******************************************************************************
2102 * VarUI1FromBool32 [OLEAUT32.138]
2104 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
2106 TRACE("( %d, %p ), stub\n", boolIn
, pbOut
);
2108 *pbOut
= (BYTE
) boolIn
;
2113 /******************************************************************************
2114 * VarUI1FromI132 [OLEAUT32.237]
2116 HRESULT WINAPI
VarUI1FromI1(CHAR cIn
, BYTE
* pbOut
)
2118 TRACE("( %c, %p ), stub\n", cIn
, pbOut
);
2125 /******************************************************************************
2126 * VarUI1FromUI232 [OLEAUT32.238]
2128 HRESULT WINAPI
VarUI1FromUI2(USHORT uiIn
, BYTE
* pbOut
)
2130 TRACE("( %d, %p ), stub\n", uiIn
, pbOut
);
2132 /* Check range of value.
2134 if( uiIn
> UI1_MAX
)
2136 return DISP_E_OVERFLOW
;
2139 *pbOut
= (BYTE
) uiIn
;
2144 /******************************************************************************
2145 * VarUI1FromUI432 [OLEAUT32.239]
2147 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
2149 TRACE("( %ld, %p ), stub\n", ulIn
, pbOut
);
2151 /* Check range of value.
2153 if( ulIn
> UI1_MAX
)
2155 return DISP_E_OVERFLOW
;
2158 *pbOut
= (BYTE
) ulIn
;
2164 /******************************************************************************
2165 * VarUI1FromStr32 [OLEAUT32.54]
2167 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
2169 double dValue
= 0.0;
2170 LPSTR pNewString
= NULL
;
2172 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pbOut
);
2174 /* Check if we have a valid argument
2176 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2177 RemoveCharacterFromString( pNewString
, "," );
2178 if( IsValidRealString( pNewString
) == FALSE
)
2180 return DISP_E_TYPEMISMATCH
;
2183 /* Convert the valid string to a floating point number.
2185 dValue
= atof( pNewString
);
2187 /* We don't need the string anymore so free it.
2189 HeapFree( GetProcessHeap(), 0 , pNewString
);
2191 /* Check range of value.
2193 dValue
= round( dValue
);
2194 if( dValue
< UI1_MIN
|| dValue
> UI1_MAX
)
2196 return DISP_E_OVERFLOW
;
2199 *pbOut
= (BYTE
) dValue
;
2204 /**********************************************************************
2205 * VarUI1FromCy32 [OLEAUT32.134]
2206 * Convert currency to unsigned char
2208 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
) {
2209 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2211 if (t
> UI1_MAX
|| t
< UI1_MIN
) return DISP_E_OVERFLOW
;
2217 /******************************************************************************
2218 * VarI2FromUI132 [OLEAUT32.48]
2220 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, short* psOut
)
2222 TRACE("( 0x%08x, %p ), stub\n", bIn
, psOut
);
2224 *psOut
= (short) bIn
;
2229 /******************************************************************************
2230 * VarI2FromI432 [OLEAUT32.49]
2232 HRESULT WINAPI
VarI2FromI4(LONG lIn
, short* psOut
)
2234 TRACE("( %lx, %p ), stub\n", lIn
, psOut
);
2236 /* Check range of value.
2238 if( lIn
< I2_MIN
|| lIn
> I2_MAX
)
2240 return DISP_E_OVERFLOW
;
2243 *psOut
= (short) lIn
;
2248 /******************************************************************************
2249 * VarI2FromR432 [OLEAUT32.50]
2251 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, short* psOut
)
2253 TRACE("( %f, %p ), stub\n", fltIn
, psOut
);
2255 /* Check range of value.
2257 fltIn
= round( fltIn
);
2258 if( fltIn
< I2_MIN
|| fltIn
> I2_MAX
)
2260 return DISP_E_OVERFLOW
;
2263 *psOut
= (short) fltIn
;
2268 /******************************************************************************
2269 * VarI2FromR832 [OLEAUT32.51]
2271 HRESULT WINAPI
VarI2FromR8(double dblIn
, short* psOut
)
2273 TRACE("( %f, %p ), stub\n", dblIn
, psOut
);
2275 /* Check range of value.
2277 dblIn
= round( dblIn
);
2278 if( dblIn
< I2_MIN
|| dblIn
> I2_MAX
)
2280 return DISP_E_OVERFLOW
;
2283 *psOut
= (short) dblIn
;
2288 /******************************************************************************
2289 * VarI2FromDate32 [OLEAUT32.53]
2291 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, short* psOut
)
2293 TRACE("( %f, %p ), stub\n", dateIn
, psOut
);
2295 /* Check range of value.
2297 dateIn
= round( dateIn
);
2298 if( dateIn
< I2_MIN
|| dateIn
> I2_MAX
)
2300 return DISP_E_OVERFLOW
;
2303 *psOut
= (short) dateIn
;
2308 /******************************************************************************
2309 * VarI2FromBool32 [OLEAUT32.56]
2311 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, short* psOut
)
2313 TRACE("( %d, %p ), stub\n", boolIn
, psOut
);
2315 *psOut
= (short) boolIn
;
2320 /******************************************************************************
2321 * VarI2FromI132 [OLEAUT32.48]
2323 HRESULT WINAPI
VarI2FromI1(CHAR cIn
, short* psOut
)
2325 TRACE("( %c, %p ), stub\n", cIn
, psOut
);
2327 *psOut
= (short) cIn
;
2332 /******************************************************************************
2333 * VarI2FromUI232 [OLEAUT32.206]
2335 HRESULT WINAPI
VarI2FromUI2(USHORT uiIn
, short* psOut
)
2337 TRACE("( %d, %p ), stub\n", uiIn
, psOut
);
2339 /* Check range of value.
2343 return DISP_E_OVERFLOW
;
2346 *psOut
= (short) uiIn
;
2351 /******************************************************************************
2352 * VarI2FromUI432 [OLEAUT32.49]
2354 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, short* psOut
)
2356 TRACE("( %lx, %p ), stub\n", ulIn
, psOut
);
2358 /* Check range of value.
2360 if( ulIn
< I2_MIN
|| ulIn
> I2_MAX
)
2362 return DISP_E_OVERFLOW
;
2365 *psOut
= (short) ulIn
;
2370 /******************************************************************************
2371 * VarI2FromStr32 [OLEAUT32.54]
2373 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, short* psOut
)
2375 double dValue
= 0.0;
2376 LPSTR pNewString
= NULL
;
2378 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, psOut
);
2380 /* Check if we have a valid argument
2382 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2383 RemoveCharacterFromString( pNewString
, "," );
2384 if( IsValidRealString( pNewString
) == FALSE
)
2386 return DISP_E_TYPEMISMATCH
;
2389 /* Convert the valid string to a floating point number.
2391 dValue
= atof( pNewString
);
2393 /* We don't need the string anymore so free it.
2395 HeapFree( GetProcessHeap(), 0, pNewString
);
2397 /* Check range of value.
2399 dValue
= round( dValue
);
2400 if( dValue
< I2_MIN
|| dValue
> I2_MAX
)
2402 return DISP_E_OVERFLOW
;
2405 *psOut
= (short) dValue
;
2410 /**********************************************************************
2411 * VarI2FromCy32 [OLEAUT32.52]
2412 * Convert currency to signed short
2414 HRESULT WINAPI
VarI2FromCy(CY cyIn
, short* psOut
) {
2415 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2417 if (t
> I2_MAX
|| t
< I2_MIN
) return DISP_E_OVERFLOW
;
2423 /******************************************************************************
2424 * VarI4FromUI132 [OLEAUT32.58]
2426 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
* plOut
)
2428 TRACE("( %X, %p ), stub\n", bIn
, plOut
);
2430 *plOut
= (LONG
) bIn
;
2436 /******************************************************************************
2437 * VarI4FromR432 [OLEAUT32.60]
2439 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
* plOut
)
2441 TRACE("( %f, %p ), stub\n", fltIn
, plOut
);
2443 /* Check range of value.
2445 fltIn
= round( fltIn
);
2446 if( fltIn
< I4_MIN
|| fltIn
> I4_MAX
)
2448 return DISP_E_OVERFLOW
;
2451 *plOut
= (LONG
) fltIn
;
2456 /******************************************************************************
2457 * VarI4FromR832 [OLEAUT32.61]
2459 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
* plOut
)
2461 TRACE("( %f, %p ), stub\n", dblIn
, plOut
);
2463 /* Check range of value.
2465 dblIn
= round( dblIn
);
2466 if( dblIn
< I4_MIN
|| dblIn
> I4_MAX
)
2468 return DISP_E_OVERFLOW
;
2471 *plOut
= (LONG
) dblIn
;
2476 /******************************************************************************
2477 * VarI4FromDate32 [OLEAUT32.63]
2479 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
* plOut
)
2481 TRACE("( %f, %p ), stub\n", dateIn
, plOut
);
2483 /* Check range of value.
2485 dateIn
= round( dateIn
);
2486 if( dateIn
< I4_MIN
|| dateIn
> I4_MAX
)
2488 return DISP_E_OVERFLOW
;
2491 *plOut
= (LONG
) dateIn
;
2496 /******************************************************************************
2497 * VarI4FromBool32 [OLEAUT32.66]
2499 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
* plOut
)
2501 TRACE("( %d, %p ), stub\n", boolIn
, plOut
);
2503 *plOut
= (LONG
) boolIn
;
2508 /******************************************************************************
2509 * VarI4FromI132 [OLEAUT32.209]
2511 HRESULT WINAPI
VarI4FromI1(CHAR cIn
, LONG
* plOut
)
2513 TRACE("( %c, %p ), stub\n", cIn
, plOut
);
2515 *plOut
= (LONG
) cIn
;
2520 /******************************************************************************
2521 * VarI4FromUI232 [OLEAUT32.210]
2523 HRESULT WINAPI
VarI4FromUI2(USHORT uiIn
, LONG
* plOut
)
2525 TRACE("( %d, %p ), stub\n", uiIn
, plOut
);
2527 *plOut
= (LONG
) uiIn
;
2532 /******************************************************************************
2533 * VarI4FromUI432 [OLEAUT32.211]
2535 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
* plOut
)
2537 TRACE("( %lx, %p ), stub\n", ulIn
, plOut
);
2539 /* Check range of value.
2541 if( ulIn
< I4_MIN
|| ulIn
> I4_MAX
)
2543 return DISP_E_OVERFLOW
;
2546 *plOut
= (LONG
) ulIn
;
2551 /******************************************************************************
2552 * VarI4FromI232 [OLEAUT32.59]
2554 HRESULT WINAPI
VarI4FromI2(short sIn
, LONG
* plOut
)
2556 TRACE("( %d, %p ), stub\n", sIn
, plOut
);
2558 *plOut
= (LONG
) sIn
;
2563 /******************************************************************************
2564 * VarI4FromStr32 [OLEAUT32.64]
2566 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
* plOut
)
2568 double dValue
= 0.0;
2569 LPSTR pNewString
= NULL
;
2571 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, plOut
);
2573 /* Check if we have a valid argument
2575 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2576 RemoveCharacterFromString( pNewString
, "," );
2577 if( IsValidRealString( pNewString
) == FALSE
)
2579 return DISP_E_TYPEMISMATCH
;
2582 /* Convert the valid string to a floating point number.
2584 dValue
= atof( pNewString
);
2586 /* We don't need the string anymore so free it.
2588 HeapFree( GetProcessHeap(), 0, pNewString
);
2590 /* Check range of value.
2592 dValue
= round( dValue
);
2593 if( dValue
< I4_MIN
|| dValue
> I4_MAX
)
2595 return DISP_E_OVERFLOW
;
2598 *plOut
= (LONG
) dValue
;
2603 /**********************************************************************
2604 * VarI4FromCy32 [OLEAUT32.62]
2605 * Convert currency to signed long
2607 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
* plOut
) {
2608 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2610 if (t
> I4_MAX
|| t
< I4_MIN
) return DISP_E_OVERFLOW
;
2616 /******************************************************************************
2617 * VarR4FromUI132 [OLEAUT32.68]
2619 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, FLOAT
* pfltOut
)
2621 TRACE("( %X, %p ), stub\n", bIn
, pfltOut
);
2623 *pfltOut
= (FLOAT
) bIn
;
2628 /******************************************************************************
2629 * VarR4FromI232 [OLEAUT32.69]
2631 HRESULT WINAPI
VarR4FromI2(short sIn
, FLOAT
* pfltOut
)
2633 TRACE("( %d, %p ), stub\n", sIn
, pfltOut
);
2635 *pfltOut
= (FLOAT
) sIn
;
2640 /******************************************************************************
2641 * VarR4FromI432 [OLEAUT32.70]
2643 HRESULT WINAPI
VarR4FromI4(LONG lIn
, FLOAT
* pfltOut
)
2645 TRACE("( %lx, %p ), stub\n", lIn
, pfltOut
);
2647 *pfltOut
= (FLOAT
) lIn
;
2652 /******************************************************************************
2653 * VarR4FromR832 [OLEAUT32.71]
2655 HRESULT WINAPI
VarR4FromR8(double dblIn
, FLOAT
* pfltOut
)
2657 TRACE("( %f, %p ), stub\n", dblIn
, pfltOut
);
2659 /* Check range of value.
2661 if( dblIn
< -(FLT_MAX
) || dblIn
> FLT_MAX
)
2663 return DISP_E_OVERFLOW
;
2666 *pfltOut
= (FLOAT
) dblIn
;
2671 /******************************************************************************
2672 * VarR4FromDate32 [OLEAUT32.73]
2674 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, FLOAT
* pfltOut
)
2676 TRACE("( %f, %p ), stub\n", dateIn
, pfltOut
);
2678 /* Check range of value.
2680 if( dateIn
< -(FLT_MAX
) || dateIn
> FLT_MAX
)
2682 return DISP_E_OVERFLOW
;
2685 *pfltOut
= (FLOAT
) dateIn
;
2690 /******************************************************************************
2691 * VarR4FromBool32 [OLEAUT32.76]
2693 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, FLOAT
* pfltOut
)
2695 TRACE("( %d, %p ), stub\n", boolIn
, pfltOut
);
2697 *pfltOut
= (FLOAT
) boolIn
;
2702 /******************************************************************************
2703 * VarR4FromI132 [OLEAUT32.213]
2705 HRESULT WINAPI
VarR4FromI1(CHAR cIn
, FLOAT
* pfltOut
)
2707 TRACE("( %c, %p ), stub\n", cIn
, pfltOut
);
2709 *pfltOut
= (FLOAT
) cIn
;
2714 /******************************************************************************
2715 * VarR4FromUI232 [OLEAUT32.214]
2717 HRESULT WINAPI
VarR4FromUI2(USHORT uiIn
, FLOAT
* pfltOut
)
2719 TRACE("( %d, %p ), stub\n", uiIn
, pfltOut
);
2721 *pfltOut
= (FLOAT
) uiIn
;
2726 /******************************************************************************
2727 * VarR4FromUI432 [OLEAUT32.215]
2729 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, FLOAT
* pfltOut
)
2731 TRACE("( %ld, %p ), stub\n", ulIn
, pfltOut
);
2733 *pfltOut
= (FLOAT
) ulIn
;
2738 /******************************************************************************
2739 * VarR4FromStr32 [OLEAUT32.74]
2741 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, FLOAT
* pfltOut
)
2743 double dValue
= 0.0;
2744 LPSTR pNewString
= NULL
;
2746 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pfltOut
);
2748 /* Check if we have a valid argument
2750 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2751 RemoveCharacterFromString( pNewString
, "," );
2752 if( IsValidRealString( pNewString
) == FALSE
)
2754 return DISP_E_TYPEMISMATCH
;
2757 /* Convert the valid string to a floating point number.
2759 dValue
= atof( pNewString
);
2761 /* We don't need the string anymore so free it.
2763 HeapFree( GetProcessHeap(), 0, pNewString
);
2765 /* Check range of value.
2767 if( dValue
< -(FLT_MAX
) || dValue
> FLT_MAX
)
2769 return DISP_E_OVERFLOW
;
2772 *pfltOut
= (FLOAT
) dValue
;
2777 /**********************************************************************
2778 * VarR4FromCy32 [OLEAUT32.72]
2779 * Convert currency to float
2781 HRESULT WINAPI
VarR4FromCy(CY cyIn
, FLOAT
* pfltOut
) {
2782 *pfltOut
= (FLOAT
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2787 /******************************************************************************
2788 * VarR8FromUI132 [OLEAUT32.68]
2790 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double* pdblOut
)
2792 TRACE("( %d, %p ), stub\n", bIn
, pdblOut
);
2794 *pdblOut
= (double) bIn
;
2799 /******************************************************************************
2800 * VarR8FromI232 [OLEAUT32.69]
2802 HRESULT WINAPI
VarR8FromI2(short sIn
, double* pdblOut
)
2804 TRACE("( %d, %p ), stub\n", sIn
, pdblOut
);
2806 *pdblOut
= (double) sIn
;
2811 /******************************************************************************
2812 * VarR8FromI432 [OLEAUT32.70]
2814 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double* pdblOut
)
2816 TRACE("( %ld, %p ), stub\n", lIn
, pdblOut
);
2818 *pdblOut
= (double) lIn
;
2823 /******************************************************************************
2824 * VarR8FromR432 [OLEAUT32.81]
2826 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double* pdblOut
)
2828 TRACE("( %f, %p ), stub\n", fltIn
, pdblOut
);
2830 *pdblOut
= (double) fltIn
;
2835 /******************************************************************************
2836 * VarR8FromDate32 [OLEAUT32.83]
2838 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double* pdblOut
)
2840 TRACE("( %f, %p ), stub\n", dateIn
, pdblOut
);
2842 *pdblOut
= (double) dateIn
;
2847 /******************************************************************************
2848 * VarR8FromBool32 [OLEAUT32.86]
2850 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double* pdblOut
)
2852 TRACE("( %d, %p ), stub\n", boolIn
, pdblOut
);
2854 *pdblOut
= (double) boolIn
;
2859 /******************************************************************************
2860 * VarR8FromI132 [OLEAUT32.217]
2862 HRESULT WINAPI
VarR8FromI1(CHAR cIn
, double* pdblOut
)
2864 TRACE("( %c, %p ), stub\n", cIn
, pdblOut
);
2866 *pdblOut
= (double) cIn
;
2871 /******************************************************************************
2872 * VarR8FromUI232 [OLEAUT32.218]
2874 HRESULT WINAPI
VarR8FromUI2(USHORT uiIn
, double* pdblOut
)
2876 TRACE("( %d, %p ), stub\n", uiIn
, pdblOut
);
2878 *pdblOut
= (double) uiIn
;
2883 /******************************************************************************
2884 * VarR8FromUI432 [OLEAUT32.219]
2886 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double* pdblOut
)
2888 TRACE("( %ld, %p ), stub\n", ulIn
, pdblOut
);
2890 *pdblOut
= (double) ulIn
;
2895 /******************************************************************************
2896 * VarR8FromStr32 [OLEAUT32.84]
2898 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double* pdblOut
)
2900 double dValue
= 0.0;
2901 LPSTR pNewString
= NULL
;
2903 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pdblOut
);
2905 /* Check if we have a valid argument
2907 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2908 RemoveCharacterFromString( pNewString
, "," );
2909 if( IsValidRealString( pNewString
) == FALSE
)
2911 return DISP_E_TYPEMISMATCH
;
2914 /* Convert the valid string to a floating point number.
2916 dValue
= atof( pNewString
);
2918 /* We don't need the string anymore so free it.
2920 HeapFree( GetProcessHeap(), 0, pNewString
);
2927 /**********************************************************************
2928 * VarR8FromCy32 [OLEAUT32.82]
2929 * Convert currency to double
2931 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double* pdblOut
) {
2932 *pdblOut
= (double)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2937 /******************************************************************************
2938 * VarDateFromUI132 [OLEAUT32.]
2940 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
2942 TRACE("( %d, %p ), stub\n", bIn
, pdateOut
);
2944 *pdateOut
= (DATE
) bIn
;
2949 /******************************************************************************
2950 * VarDateFromI232 [OLEAUT32.222]
2952 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
2954 TRACE("( %d, %p ), stub\n", sIn
, pdateOut
);
2956 *pdateOut
= (DATE
) sIn
;
2961 /******************************************************************************
2962 * VarDateFromI432 [OLEAUT32.90]
2964 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
2966 TRACE("( %ld, %p ), stub\n", lIn
, pdateOut
);
2968 if( lIn
< DATE_MIN
|| lIn
> DATE_MAX
)
2970 return DISP_E_OVERFLOW
;
2973 *pdateOut
= (DATE
) lIn
;
2978 /******************************************************************************
2979 * VarDateFromR432 [OLEAUT32.91]
2981 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
2983 TRACE("( %f, %p ), stub\n", fltIn
, pdateOut
);
2985 if( ceil(fltIn
) < DATE_MIN
|| floor(fltIn
) > DATE_MAX
)
2987 return DISP_E_OVERFLOW
;
2990 *pdateOut
= (DATE
) fltIn
;
2995 /******************************************************************************
2996 * VarDateFromR832 [OLEAUT32.92]
2998 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
3000 TRACE("( %f, %p ), stub\n", dblIn
, pdateOut
);
3002 if( ceil(dblIn
) < DATE_MIN
|| floor(dblIn
) > DATE_MAX
)
3004 return DISP_E_OVERFLOW
;
3007 *pdateOut
= (DATE
) dblIn
;
3012 /******************************************************************************
3013 * VarDateFromStr32 [OLEAUT32.94]
3014 * The string representing the date is composed of two parts, a date and time.
3016 * The format of the time is has follows:
3017 * hh[:mm][:ss][AM|PM]
3018 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3019 * of space and/or tab characters, which are ignored.
3021 * The formats for the date part are has follows:
3025 * January dd[,] [yy]yy
3028 * Whitespace can be inserted anywhere between these tokens.
3030 * The formats for the date and time string are has follows.
3031 * date[whitespace][time]
3032 * [time][whitespace]date
3034 * These are the only characters allowed in a string representing a date and time:
3035 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3037 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
3040 struct tm TM
= { 0,0,0,0,0,0,0,0,0 };
3042 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pdateOut
);
3044 if( DateTimeStringToTm( strIn
, lcid
, &TM
) )
3046 if( TmToDATE( &TM
, pdateOut
) == FALSE
)
3053 ret
= DISP_E_TYPEMISMATCH
;
3060 /******************************************************************************
3061 * VarDateFromI132 [OLEAUT32.221]
3063 HRESULT WINAPI
VarDateFromI1(CHAR cIn
, DATE
* pdateOut
)
3065 TRACE("( %c, %p ), stub\n", cIn
, pdateOut
);
3067 *pdateOut
= (DATE
) cIn
;
3072 /******************************************************************************
3073 * VarDateFromUI232 [OLEAUT32.222]
3075 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
3077 TRACE("( %d, %p ), stub\n", uiIn
, pdateOut
);
3079 if( uiIn
> DATE_MAX
)
3081 return DISP_E_OVERFLOW
;
3084 *pdateOut
= (DATE
) uiIn
;
3089 /******************************************************************************
3090 * VarDateFromUI432 [OLEAUT32.223]
3092 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
3094 TRACE("( %ld, %p ), stub\n", ulIn
, pdateOut
);
3096 if( ulIn
< DATE_MIN
|| ulIn
> DATE_MAX
)
3098 return DISP_E_OVERFLOW
;
3101 *pdateOut
= (DATE
) ulIn
;
3106 /******************************************************************************
3107 * VarDateFromBool32 [OLEAUT32.96]
3109 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
3111 TRACE("( %d, %p ), stub\n", boolIn
, pdateOut
);
3113 *pdateOut
= (DATE
) boolIn
;
3118 /**********************************************************************
3119 * VarDateFromCy32 [OLEAUT32.93]
3120 * Convert currency to date
3122 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
) {
3123 *pdateOut
= (DATE
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3125 if (*pdateOut
> DATE_MAX
|| *pdateOut
< DATE_MIN
) return DISP_E_TYPEMISMATCH
;
3129 /******************************************************************************
3130 * VarBstrFromUI132 [OLEAUT32.108]
3132 HRESULT WINAPI
VarBstrFromUI1(BYTE bVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3134 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal
, lcid
, dwFlags
, pbstrOut
);
3135 sprintf( pBuffer
, "%d", bVal
);
3137 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3142 /******************************************************************************
3143 * VarBstrFromI232 [OLEAUT32.109]
3145 HRESULT WINAPI
VarBstrFromI2(short iVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3147 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal
, lcid
, dwFlags
, pbstrOut
);
3148 sprintf( pBuffer
, "%d", iVal
);
3149 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3154 /******************************************************************************
3155 * VarBstrFromI432 [OLEAUT32.110]
3157 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3159 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn
, lcid
, dwFlags
, pbstrOut
);
3161 sprintf( pBuffer
, "%ld", lIn
);
3162 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3167 /******************************************************************************
3168 * VarBstrFromR432 [OLEAUT32.111]
3170 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3172 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn
, lcid
, dwFlags
, pbstrOut
);
3174 sprintf( pBuffer
, "%.7g", fltIn
);
3175 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3180 /******************************************************************************
3181 * VarBstrFromR832 [OLEAUT32.112]
3183 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3185 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn
, lcid
, dwFlags
, pbstrOut
);
3187 sprintf( pBuffer
, "%.15g", dblIn
);
3188 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3193 /******************************************************************************
3194 * VarBstrFromCy [OLEAUT32.113]
3196 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
) {
3202 /******************************************************************************
3203 * VarBstrFromDate32 [OLEAUT32.114]
3205 * The date is implemented using an 8 byte floating-point number.
3206 * Days are represented by whole numbers increments starting with 0.00 has
3207 * being December 30 1899, midnight.
3208 * The hours are expressed as the fractional part of the number.
3209 * December 30 1899 at midnight = 0.00
3210 * January 1 1900 at midnight = 2.00
3211 * January 4 1900 at 6 AM = 5.25
3212 * January 4 1900 at noon = 5.50
3213 * December 29 1899 at midnight = -1.00
3214 * December 18 1899 at midnight = -12.00
3215 * December 18 1899 at 6AM = -12.25
3216 * December 18 1899 at 6PM = -12.75
3217 * December 19 1899 at midnight = -11.00
3218 * The tm structure is as follows:
3220 * int tm_sec; seconds after the minute - [0,59]
3221 * int tm_min; minutes after the hour - [0,59]
3222 * int tm_hour; hours since midnight - [0,23]
3223 * int tm_mday; day of the month - [1,31]
3224 * int tm_mon; months since January - [0,11]
3225 * int tm_year; years
3226 * int tm_wday; days since Sunday - [0,6]
3227 * int tm_yday; days since January 1 - [0,365]
3228 * int tm_isdst; daylight savings time flag
3231 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3233 struct tm TM
= {0,0,0,0,0,0,0,0,0};
3235 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
3237 if( DateToTm( dateIn
, lcid
, &TM
) == FALSE
)
3239 return E_INVALIDARG
;
3242 if( lcid
& VAR_DATEVALUEONLY
)
3243 strftime( pBuffer
, BUFFER_MAX
, "%x", &TM
);
3244 else if( lcid
& VAR_TIMEVALUEONLY
)
3245 strftime( pBuffer
, BUFFER_MAX
, "%X", &TM
);
3247 strftime( pBuffer
, BUFFER_MAX
, "%x %X", &TM
);
3249 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3254 /******************************************************************************
3255 * VarBstrFromBool32 [OLEAUT32.116]
3257 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3259 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
3261 if( boolIn
== VARIANT_FALSE
)
3263 sprintf( pBuffer
, "False" );
3267 sprintf( pBuffer
, "True" );
3270 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3275 /******************************************************************************
3276 * VarBstrFromI132 [OLEAUT32.229]
3278 HRESULT WINAPI
VarBstrFromI1(CHAR cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3280 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn
, lcid
, dwFlags
, pbstrOut
);
3281 sprintf( pBuffer
, "%d", cIn
);
3282 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3287 /******************************************************************************
3288 * VarBstrFromUI232 [OLEAUT32.230]
3290 HRESULT WINAPI
VarBstrFromUI2(USHORT uiIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3292 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn
, lcid
, dwFlags
, pbstrOut
);
3293 sprintf( pBuffer
, "%d", uiIn
);
3294 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3299 /******************************************************************************
3300 * VarBstrFromUI432 [OLEAUT32.231]
3302 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3304 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn
, lcid
, dwFlags
, pbstrOut
);
3305 sprintf( pBuffer
, "%ld", ulIn
);
3306 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3311 /******************************************************************************
3312 * VarBoolFromUI132 [OLEAUT32.118]
3314 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
* pboolOut
)
3316 TRACE("( %d, %p ), stub\n", bIn
, pboolOut
);
3320 *pboolOut
= VARIANT_FALSE
;
3324 *pboolOut
= VARIANT_TRUE
;
3330 /******************************************************************************
3331 * VarBoolFromI232 [OLEAUT32.119]
3333 HRESULT WINAPI
VarBoolFromI2(short sIn
, VARIANT_BOOL
* pboolOut
)
3335 TRACE("( %d, %p ), stub\n", sIn
, pboolOut
);
3339 *pboolOut
= VARIANT_FALSE
;
3343 *pboolOut
= VARIANT_TRUE
;
3349 /******************************************************************************
3350 * VarBoolFromI432 [OLEAUT32.120]
3352 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
* pboolOut
)
3354 TRACE("( %ld, %p ), stub\n", lIn
, pboolOut
);
3358 *pboolOut
= VARIANT_FALSE
;
3362 *pboolOut
= VARIANT_TRUE
;
3368 /******************************************************************************
3369 * VarBoolFromR432 [OLEAUT32.121]
3371 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
* pboolOut
)
3373 TRACE("( %f, %p ), stub\n", fltIn
, pboolOut
);
3377 *pboolOut
= VARIANT_FALSE
;
3381 *pboolOut
= VARIANT_TRUE
;
3387 /******************************************************************************
3388 * VarBoolFromR832 [OLEAUT32.122]
3390 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
* pboolOut
)
3392 TRACE("( %f, %p ), stub\n", dblIn
, pboolOut
);
3396 *pboolOut
= VARIANT_FALSE
;
3400 *pboolOut
= VARIANT_TRUE
;
3406 /******************************************************************************
3407 * VarBoolFromDate32 [OLEAUT32.123]
3409 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
* pboolOut
)
3411 TRACE("( %f, %p ), stub\n", dateIn
, pboolOut
);
3415 *pboolOut
= VARIANT_FALSE
;
3419 *pboolOut
= VARIANT_TRUE
;
3425 /******************************************************************************
3426 * VarBoolFromStr32 [OLEAUT32.125]
3428 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
* pboolOut
)
3431 char* pNewString
= NULL
;
3433 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pboolOut
);
3435 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3437 if( pNewString
== NULL
|| strlen( pNewString
) == 0 )
3439 ret
= DISP_E_TYPEMISMATCH
;
3444 if( strncasecmp( pNewString
, "True", strlen( pNewString
) ) == 0 )
3446 *pboolOut
= VARIANT_TRUE
;
3448 else if( strncasecmp( pNewString
, "False", strlen( pNewString
) ) == 0 )
3450 *pboolOut
= VARIANT_FALSE
;
3454 /* Try converting the string to a floating point number.
3456 double dValue
= 0.0;
3457 HRESULT res
= VarR8FromStr( strIn
, lcid
, dwFlags
, &dValue
);
3460 ret
= DISP_E_TYPEMISMATCH
;
3462 else if( dValue
== 0.0 )
3464 *pboolOut
= VARIANT_FALSE
;
3468 *pboolOut
= VARIANT_TRUE
;
3473 HeapFree( GetProcessHeap(), 0, pNewString
);
3478 /******************************************************************************
3479 * VarBoolFromI132 [OLEAUT32.233]
3481 HRESULT WINAPI
VarBoolFromI1(CHAR cIn
, VARIANT_BOOL
* pboolOut
)
3483 TRACE("( %c, %p ), stub\n", cIn
, pboolOut
);
3487 *pboolOut
= VARIANT_FALSE
;
3491 *pboolOut
= VARIANT_TRUE
;
3497 /******************************************************************************
3498 * VarBoolFromUI232 [OLEAUT32.234]
3500 HRESULT WINAPI
VarBoolFromUI2(USHORT uiIn
, VARIANT_BOOL
* pboolOut
)
3502 TRACE("( %d, %p ), stub\n", uiIn
, pboolOut
);
3506 *pboolOut
= VARIANT_FALSE
;
3510 *pboolOut
= VARIANT_TRUE
;
3516 /******************************************************************************
3517 * VarBoolFromUI432 [OLEAUT32.235]
3519 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
* pboolOut
)
3521 TRACE("( %ld, %p ), stub\n", ulIn
, pboolOut
);
3525 *pboolOut
= VARIANT_FALSE
;
3529 *pboolOut
= VARIANT_TRUE
;
3535 /**********************************************************************
3536 * VarBoolFromCy32 [OLEAUT32.124]
3537 * Convert currency to boolean
3539 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
* pboolOut
) {
3540 if (cyIn
.s
.Hi
|| cyIn
.s
.Lo
) *pboolOut
= -1;
3546 /******************************************************************************
3547 * VarI1FromUI132 [OLEAUT32.244]
3549 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, CHAR
* pcOut
)
3551 TRACE("( %d, %p ), stub\n", bIn
, pcOut
);
3553 /* Check range of value.
3555 if( bIn
> CHAR_MAX
)
3557 return DISP_E_OVERFLOW
;
3560 *pcOut
= (CHAR
) bIn
;
3565 /******************************************************************************
3566 * VarI1FromI232 [OLEAUT32.245]
3568 HRESULT WINAPI
VarI1FromI2(short uiIn
, CHAR
* pcOut
)
3570 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3572 if( uiIn
> CHAR_MAX
)
3574 return DISP_E_OVERFLOW
;
3577 *pcOut
= (CHAR
) uiIn
;
3582 /******************************************************************************
3583 * VarI1FromI432 [OLEAUT32.246]
3585 HRESULT WINAPI
VarI1FromI4(LONG lIn
, CHAR
* pcOut
)
3587 TRACE("( %ld, %p ), stub\n", lIn
, pcOut
);
3589 if( lIn
< CHAR_MIN
|| lIn
> CHAR_MAX
)
3591 return DISP_E_OVERFLOW
;
3594 *pcOut
= (CHAR
) lIn
;
3599 /******************************************************************************
3600 * VarI1FromR432 [OLEAUT32.247]
3602 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, CHAR
* pcOut
)
3604 TRACE("( %f, %p ), stub\n", fltIn
, pcOut
);
3606 fltIn
= round( fltIn
);
3607 if( fltIn
< CHAR_MIN
|| fltIn
> CHAR_MAX
)
3609 return DISP_E_OVERFLOW
;
3612 *pcOut
= (CHAR
) fltIn
;
3617 /******************************************************************************
3618 * VarI1FromR832 [OLEAUT32.248]
3620 HRESULT WINAPI
VarI1FromR8(double dblIn
, CHAR
* pcOut
)
3622 TRACE("( %f, %p ), stub\n", dblIn
, pcOut
);
3624 dblIn
= round( dblIn
);
3625 if( dblIn
< CHAR_MIN
|| dblIn
> CHAR_MAX
)
3627 return DISP_E_OVERFLOW
;
3630 *pcOut
= (CHAR
) dblIn
;
3635 /******************************************************************************
3636 * VarI1FromDate32 [OLEAUT32.249]
3638 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, CHAR
* pcOut
)
3640 TRACE("( %f, %p ), stub\n", dateIn
, pcOut
);
3642 dateIn
= round( dateIn
);
3643 if( dateIn
< CHAR_MIN
|| dateIn
> CHAR_MAX
)
3645 return DISP_E_OVERFLOW
;
3648 *pcOut
= (CHAR
) dateIn
;
3653 /******************************************************************************
3654 * VarI1FromStr32 [OLEAUT32.251]
3656 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CHAR
* pcOut
)
3658 double dValue
= 0.0;
3659 LPSTR pNewString
= NULL
;
3661 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pcOut
);
3663 /* Check if we have a valid argument
3665 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3666 RemoveCharacterFromString( pNewString
, "," );
3667 if( IsValidRealString( pNewString
) == FALSE
)
3669 return DISP_E_TYPEMISMATCH
;
3672 /* Convert the valid string to a floating point number.
3674 dValue
= atof( pNewString
);
3676 /* We don't need the string anymore so free it.
3678 HeapFree( GetProcessHeap(), 0, pNewString
);
3680 /* Check range of value.
3682 dValue
= round( dValue
);
3683 if( dValue
< CHAR_MIN
|| dValue
> CHAR_MAX
)
3685 return DISP_E_OVERFLOW
;
3688 *pcOut
= (CHAR
) dValue
;
3693 /******************************************************************************
3694 * VarI1FromBool32 [OLEAUT32.253]
3696 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, CHAR
* pcOut
)
3698 TRACE("( %d, %p ), stub\n", boolIn
, pcOut
);
3700 *pcOut
= (CHAR
) boolIn
;
3705 /******************************************************************************
3706 * VarI1FromUI232 [OLEAUT32.254]
3708 HRESULT WINAPI
VarI1FromUI2(USHORT uiIn
, CHAR
* pcOut
)
3710 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3712 if( uiIn
> CHAR_MAX
)
3714 return DISP_E_OVERFLOW
;
3717 *pcOut
= (CHAR
) uiIn
;
3722 /******************************************************************************
3723 * VarI1FromUI432 [OLEAUT32.255]
3725 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, CHAR
* pcOut
)
3727 TRACE("( %ld, %p ), stub\n", ulIn
, pcOut
);
3729 if( ulIn
> CHAR_MAX
)
3731 return DISP_E_OVERFLOW
;
3734 *pcOut
= (CHAR
) ulIn
;
3739 /**********************************************************************
3740 * VarI1FromCy32 [OLEAUT32.250]
3741 * Convert currency to signed char
3743 HRESULT WINAPI
VarI1FromCy(CY cyIn
, CHAR
* pcOut
) {
3744 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3746 if (t
> CHAR_MAX
|| t
< CHAR_MIN
) return DISP_E_OVERFLOW
;
3752 /******************************************************************************
3753 * VarUI2FromUI132 [OLEAUT32.257]
3755 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* puiOut
)
3757 TRACE("( %d, %p ), stub\n", bIn
, puiOut
);
3759 *puiOut
= (USHORT
) bIn
;
3764 /******************************************************************************
3765 * VarUI2FromI232 [OLEAUT32.258]
3767 HRESULT WINAPI
VarUI2FromI2(short uiIn
, USHORT
* puiOut
)
3769 TRACE("( %d, %p ), stub\n", uiIn
, puiOut
);
3771 if( uiIn
< UI2_MIN
)
3773 return DISP_E_OVERFLOW
;
3776 *puiOut
= (USHORT
) uiIn
;
3781 /******************************************************************************
3782 * VarUI2FromI432 [OLEAUT32.259]
3784 HRESULT WINAPI
VarUI2FromI4(LONG lIn
, USHORT
* puiOut
)
3786 TRACE("( %ld, %p ), stub\n", lIn
, puiOut
);
3788 if( lIn
< UI2_MIN
|| lIn
> UI2_MAX
)
3790 return DISP_E_OVERFLOW
;
3793 *puiOut
= (USHORT
) lIn
;
3798 /******************************************************************************
3799 * VarUI2FromR432 [OLEAUT32.260]
3801 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* puiOut
)
3803 TRACE("( %f, %p ), stub\n", fltIn
, puiOut
);
3805 fltIn
= round( fltIn
);
3806 if( fltIn
< UI2_MIN
|| fltIn
> UI2_MAX
)
3808 return DISP_E_OVERFLOW
;
3811 *puiOut
= (USHORT
) fltIn
;
3816 /******************************************************************************
3817 * VarUI2FromR832 [OLEAUT32.261]
3819 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* puiOut
)
3821 TRACE("( %f, %p ), stub\n", dblIn
, puiOut
);
3823 dblIn
= round( dblIn
);
3824 if( dblIn
< UI2_MIN
|| dblIn
> UI2_MAX
)
3826 return DISP_E_OVERFLOW
;
3829 *puiOut
= (USHORT
) dblIn
;
3834 /******************************************************************************
3835 * VarUI2FromDate32 [OLEAUT32.262]
3837 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* puiOut
)
3839 TRACE("( %f, %p ), stub\n", dateIn
, puiOut
);
3841 dateIn
= round( dateIn
);
3842 if( dateIn
< UI2_MIN
|| dateIn
> UI2_MAX
)
3844 return DISP_E_OVERFLOW
;
3847 *puiOut
= (USHORT
) dateIn
;
3852 /******************************************************************************
3853 * VarUI2FromStr32 [OLEAUT32.264]
3855 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* puiOut
)
3857 double dValue
= 0.0;
3858 LPSTR pNewString
= NULL
;
3860 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, puiOut
);
3862 /* Check if we have a valid argument
3864 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3865 RemoveCharacterFromString( pNewString
, "," );
3866 if( IsValidRealString( pNewString
) == FALSE
)
3868 return DISP_E_TYPEMISMATCH
;
3871 /* Convert the valid string to a floating point number.
3873 dValue
= atof( pNewString
);
3875 /* We don't need the string anymore so free it.
3877 HeapFree( GetProcessHeap(), 0, pNewString
);
3879 /* Check range of value.
3881 dValue
= round( dValue
);
3882 if( dValue
< UI2_MIN
|| dValue
> UI2_MAX
)
3884 return DISP_E_OVERFLOW
;
3887 *puiOut
= (USHORT
) dValue
;
3892 /******************************************************************************
3893 * VarUI2FromBool32 [OLEAUT32.266]
3895 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* puiOut
)
3897 TRACE("( %d, %p ), stub\n", boolIn
, puiOut
);
3899 *puiOut
= (USHORT
) boolIn
;
3904 /******************************************************************************
3905 * VarUI2FromI132 [OLEAUT32.267]
3907 HRESULT WINAPI
VarUI2FromI1(CHAR cIn
, USHORT
* puiOut
)
3909 TRACE("( %c, %p ), stub\n", cIn
, puiOut
);
3911 *puiOut
= (USHORT
) cIn
;
3916 /******************************************************************************
3917 * VarUI2FromUI432 [OLEAUT32.268]
3919 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* puiOut
)
3921 TRACE("( %ld, %p ), stub\n", ulIn
, puiOut
);
3923 if( ulIn
< UI2_MIN
|| ulIn
> UI2_MAX
)
3925 return DISP_E_OVERFLOW
;
3928 *puiOut
= (USHORT
) ulIn
;
3933 /******************************************************************************
3934 * VarUI4FromStr32 [OLEAUT32.277]
3936 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
* pulOut
)
3938 double dValue
= 0.0;
3939 LPSTR pNewString
= NULL
;
3941 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pulOut
);
3943 /* Check if we have a valid argument
3945 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3946 RemoveCharacterFromString( pNewString
, "," );
3947 if( IsValidRealString( pNewString
) == FALSE
)
3949 return DISP_E_TYPEMISMATCH
;
3952 /* Convert the valid string to a floating point number.
3954 dValue
= atof( pNewString
);
3956 /* We don't need the string anymore so free it.
3958 HeapFree( GetProcessHeap(), 0, pNewString
);
3960 /* Check range of value.
3962 dValue
= round( dValue
);
3963 if( dValue
< UI4_MIN
|| dValue
> UI4_MAX
)
3965 return DISP_E_OVERFLOW
;
3968 *pulOut
= (ULONG
) dValue
;
3973 /**********************************************************************
3974 * VarUI2FromCy32 [OLEAUT32.263]
3975 * Convert currency to unsigned short
3977 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
) {
3978 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3980 if (t
> UI2_MAX
|| t
< UI2_MIN
) return DISP_E_OVERFLOW
;
3982 *pusOut
= (USHORT
)t
;
3987 /******************************************************************************
3988 * VarUI4FromUI132 [OLEAUT32.270]
3990 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
* pulOut
)
3992 TRACE("( %d, %p ), stub\n", bIn
, pulOut
);
3994 *pulOut
= (USHORT
) bIn
;
3999 /******************************************************************************
4000 * VarUI4FromI232 [OLEAUT32.271]
4002 HRESULT WINAPI
VarUI4FromI2(short uiIn
, ULONG
* pulOut
)
4004 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4006 if( uiIn
< UI4_MIN
)
4008 return DISP_E_OVERFLOW
;
4011 *pulOut
= (ULONG
) uiIn
;
4016 /******************************************************************************
4017 * VarUI4FromI432 [OLEAUT32.272]
4019 HRESULT WINAPI
VarUI4FromI4(LONG lIn
, ULONG
* pulOut
)
4021 TRACE("( %ld, %p ), stub\n", lIn
, pulOut
);
4025 return DISP_E_OVERFLOW
;
4028 *pulOut
= (ULONG
) lIn
;
4033 /******************************************************************************
4034 * VarUI4FromR432 [OLEAUT32.273]
4036 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
* pulOut
)
4038 fltIn
= round( fltIn
);
4039 if( fltIn
< UI4_MIN
|| fltIn
> UI4_MAX
)
4041 return DISP_E_OVERFLOW
;
4044 *pulOut
= (ULONG
) fltIn
;
4049 /******************************************************************************
4050 * VarUI4FromR832 [OLEAUT32.274]
4052 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
* pulOut
)
4054 TRACE("( %f, %p ), stub\n", dblIn
, pulOut
);
4056 dblIn
= round( dblIn
);
4057 if( dblIn
< UI4_MIN
|| dblIn
> UI4_MAX
)
4059 return DISP_E_OVERFLOW
;
4062 *pulOut
= (ULONG
) dblIn
;
4067 /******************************************************************************
4068 * VarUI4FromDate32 [OLEAUT32.275]
4070 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
* pulOut
)
4072 TRACE("( %f, %p ), stub\n", dateIn
, pulOut
);
4074 dateIn
= round( dateIn
);
4075 if( dateIn
< UI4_MIN
|| dateIn
> UI4_MAX
)
4077 return DISP_E_OVERFLOW
;
4080 *pulOut
= (ULONG
) dateIn
;
4085 /******************************************************************************
4086 * VarUI4FromBool32 [OLEAUT32.279]
4088 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
* pulOut
)
4090 TRACE("( %d, %p ), stub\n", boolIn
, pulOut
);
4092 *pulOut
= (ULONG
) boolIn
;
4097 /******************************************************************************
4098 * VarUI4FromI132 [OLEAUT32.280]
4100 HRESULT WINAPI
VarUI4FromI1(CHAR cIn
, ULONG
* pulOut
)
4102 TRACE("( %c, %p ), stub\n", cIn
, pulOut
);
4104 *pulOut
= (ULONG
) cIn
;
4109 /******************************************************************************
4110 * VarUI4FromUI232 [OLEAUT32.281]
4112 HRESULT WINAPI
VarUI4FromUI2(USHORT uiIn
, ULONG
* pulOut
)
4114 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4116 *pulOut
= (ULONG
) uiIn
;
4121 /**********************************************************************
4122 * VarUI4FromCy32 [OLEAUT32.276]
4123 * Convert currency to unsigned long
4125 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
* pulOut
) {
4126 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
4128 if (t
> UI4_MAX
|| t
< UI4_MIN
) return DISP_E_OVERFLOW
;
4135 /**********************************************************************
4136 * VarCyFromUI132 [OLEAUT32.98]
4137 * Convert unsigned char to currency
4139 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pcyOut
) {
4141 pcyOut
->s
.Lo
= ((ULONG
)bIn
) * 10000;
4146 /**********************************************************************
4147 * VarCyFromI232 [OLEAUT32.99]
4148 * Convert signed short to currency
4150 HRESULT WINAPI
VarCyFromI2(short sIn
, CY
* pcyOut
) {
4151 if (sIn
< 0) pcyOut
->s
.Hi
= -1;
4152 else pcyOut
->s
.Hi
= 0;
4153 pcyOut
->s
.Lo
= ((ULONG
)sIn
) * 10000;
4158 /**********************************************************************
4159 * VarCyFromI432 [OLEAUT32.100]
4160 * Convert signed long to currency
4162 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pcyOut
) {
4163 double t
= (double)lIn
* (double)10000;
4164 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4165 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4166 if (lIn
< 0) pcyOut
->s
.Hi
--;
4171 /**********************************************************************
4172 * VarCyFromR432 [OLEAUT32.101]
4173 * Convert float to currency
4175 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pcyOut
) {
4176 double t
= round((double)fltIn
* (double)10000);
4177 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4178 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4179 if (fltIn
< 0) pcyOut
->s
.Hi
--;
4184 /**********************************************************************
4185 * VarCyFromR832 [OLEAUT32.102]
4186 * Convert double to currency
4188 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pcyOut
) {
4189 double t
= round(dblIn
* (double)10000);
4190 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4191 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4192 if (dblIn
< 0) pcyOut
->s
.Hi
--;
4197 /**********************************************************************
4198 * VarCyFromDate32 [OLEAUT32.103]
4199 * Convert date to currency
4201 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pcyOut
) {
4202 double t
= round((double)dateIn
* (double)10000);
4203 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4204 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4205 if (dateIn
< 0) pcyOut
->s
.Hi
--;
4210 /**********************************************************************
4211 * VarCyFromDate32 [OLEAUT32.104]
4213 HRESULT WINAPI
VarCyFromStr(OLECHAR
*strIn
, LCID lcid
, ULONG dwFlags
, CY
*pcyOut
) {
4219 /**********************************************************************
4220 * VarCyFromBool32 [OLEAUT32.106]
4221 * Convert boolean to currency
4223 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pcyOut
) {
4224 if (boolIn
< 0) pcyOut
->s
.Hi
= -1;
4225 else pcyOut
->s
.Hi
= 0;
4226 pcyOut
->s
.Lo
= (ULONG
)boolIn
* (ULONG
)10000;
4231 /**********************************************************************
4232 * VarCyFromI132 [OLEAUT32.225]
4233 * Convert signed char to currency
4235 HRESULT WINAPI
VarCyFromI1(CHAR cIn
, CY
* pcyOut
) {
4236 if (cIn
< 0) pcyOut
->s
.Hi
= -1;
4237 else pcyOut
->s
.Hi
= 0;
4238 pcyOut
->s
.Lo
= (ULONG
)cIn
* (ULONG
)10000;
4243 /**********************************************************************
4244 * VarCyFromUI232 [OLEAUT32.226]
4245 * Convert unsigned short to currency
4247 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pcyOut
) {
4249 pcyOut
->s
.Lo
= (ULONG
)usIn
* (ULONG
)10000;
4254 /**********************************************************************
4255 * VarCyFromUI432 [OLEAUT32.227]
4256 * Convert unsigned long to currency
4258 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pcyOut
) {
4259 double t
= (double)ulIn
* (double)10000;
4260 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4261 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4267 /**********************************************************************
4268 * DosDateTimeToVariantTime [OLEAUT32.14]
4269 * Convert dos representation of time to the date and time representation
4270 * stored in a variant.
4272 INT WINAPI
DosDateTimeToVariantTime(USHORT wDosDate
, USHORT wDosTime
,
4277 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate
, wDosTime
, pvtime
);
4279 t
.tm_sec
= (wDosTime
& 0x001f) * 2;
4280 t
.tm_min
= (wDosTime
& 0x07e0) >> 5;
4281 t
.tm_hour
= (wDosTime
& 0xf800) >> 11;
4283 t
.tm_mday
= (wDosDate
& 0x001f);
4284 t
.tm_mon
= (wDosDate
& 0x01e0) >> 5;
4285 t
.tm_year
= ((wDosDate
& 0xfe00) >> 9) + 1980;
4287 return TmToDATE( &t
, pvtime
);