4 * Copyright 1998 Jean-Claude Cote
7 * This implements the low-level and hi-level APIs for manipulating VARIANTs.
8 * The low-level APIs are used to do data coercion between different data types.
9 * The hi-level APIs are built on top of these low-level APIs and handle
10 * initialization, copying, destroying and changing the type of VARIANTs.
13 * - The Variant APIs do not support international languages, currency
14 * types, number formating and calendar. They only support U.S. English format.
15 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
16 * The prototypes for these are commented out in the oleauto.h file. They need
17 * to be implemented and cases need to be added to the switches of the existing APIs.
18 * - The parsing of date for the VarDateFromStr is not complete.
19 * - The date manipulations do not support date prior to 1900.
20 * - The parsing does not accept has many formats has the Windows implementation.
38 #include "debugtools.h"
42 DEFAULT_DEBUG_CHANNEL(ole
);
46 # define FLT_MAX MAXFLOAT
48 # error "Can't find #define for MAXFLOAT/FLT_MAX"
54 static const char CHAR_MAX
= 127;
55 static const char CHAR_MIN
= -128;
56 static const BYTE UI1_MAX
= 255;
57 static const BYTE UI1_MIN
= 0;
58 static const unsigned short UI2_MAX
= 65535;
59 static const unsigned short UI2_MIN
= 0;
60 static const short I2_MAX
= 32767;
61 static const short I2_MIN
= -32768;
62 static const unsigned long UI4_MAX
= 4294967295U;
63 static const unsigned long UI4_MIN
= 0;
64 static const long I4_MAX
= 2147483647;
65 static const long I4_MIN
= -(2147483648U);
66 static const DATE DATE_MIN
= -657434;
67 static const DATE DATE_MAX
= 2958465;
70 /* This mask is used to set a flag in wReserved1 of
71 * the VARIANTARG structure. The flag indicates if
72 * the API function is using an inner variant or not.
74 #define PROCESSING_INNER_VARIANT 0x0001
76 /* General use buffer.
78 #define BUFFER_MAX 1024
79 static char pBuffer
[BUFFER_MAX
];
82 * Note a leap year is one that is a multiple of 4
83 * but not of a 100. Except if it is a multiple of
84 * 400 then it is a leap year.
86 /* According to postgeSQL date parsing functions there is
87 * a leap year when this expression is true.
88 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
89 * So according to this there is 365.2515 days in one year.
90 * One + every four years: 1/4 -> 365.25
91 * One - every 100 years: 1/100 -> 365.01
92 * One + every 400 years: 1/400 -> 365.0025
94 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
96 * ^^ Might this be the key to an easy way to factor large prime numbers?
97 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
99 static const double DAYS_IN_ONE_YEAR
= 365.2425;
101 /******************************************************************************
102 * DateTimeStringToTm [INTERNAL]
104 * Converts a string representation of a date and/or time to a tm structure.
106 * Note this function uses the postgresql date parsing functions found
107 * in the parsedt.c file.
109 * Returns TRUE if successfull.
111 * Note: This function does not parse the day of the week,
112 * daylight savings time. It will only fill the followin fields in
113 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
115 ******************************************************************************/
116 static BOOL
DateTimeStringToTm( OLECHAR
* strIn
, LCID lcid
, struct tm
* pTm
)
123 char *field
[MAXDATEFIELDS
];
124 int ftype
[MAXDATEFIELDS
];
125 char lowstr
[MAXDATELEN
+ 1];
126 char* strDateTime
= NULL
;
128 /* Convert the string to ASCII since this is the only format
129 * postgesql can handle.
131 strDateTime
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
133 if( strDateTime
!= NULL
)
135 /* Make sure we don't go over the maximum length
136 * accepted by postgesql.
138 if( strlen( strDateTime
) <= MAXDATELEN
)
140 if( ParseDateTime( strDateTime
, lowstr
, field
, ftype
, MAXDATEFIELDS
, &nf
) == 0 )
142 if( lcid
& VAR_DATEVALUEONLY
)
144 /* Get the date information.
145 * It returns 0 if date information was
146 * present and 1 if only time information was present.
147 * -1 if an error occures.
149 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) == 0 )
151 /* Eliminate the time information since we
152 * were asked to get date information only.
160 if( lcid
& VAR_TIMEVALUEONLY
)
162 /* Get time information only.
164 if( DecodeTimeOnly(field
, ftype
, nf
, &dtype
, pTm
, &fsec
) == 0 )
171 /* Get both date and time information.
172 * It returns 0 if date information was
173 * present and 1 if only time information was present.
174 * -1 if an error occures.
176 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) != -1 )
183 HeapFree( GetProcessHeap(), 0, strDateTime
);
194 /******************************************************************************
195 * TmToDATE [INTERNAL]
197 * The date is implemented using an 8 byte floating-point number.
198 * Days are represented by whole numbers increments starting with 0.00 has
199 * being December 30 1899, midnight.
200 * The hours are expressed as the fractional part of the number.
201 * December 30 1899 at midnight = 0.00
202 * January 1 1900 at midnight = 2.00
203 * January 4 1900 at 6 AM = 5.25
204 * January 4 1900 at noon = 5.50
205 * December 29 1899 at midnight = -1.00
206 * December 18 1899 at midnight = -12.00
207 * December 18 1899 at 6AM = -12.25
208 * December 18 1899 at 6PM = -12.75
209 * December 19 1899 at midnight = -11.00
210 * The tm structure is as follows:
212 * int tm_sec; seconds after the minute - [0,59]
213 * int tm_min; minutes after the hour - [0,59]
214 * int tm_hour; hours since midnight - [0,23]
215 * int tm_mday; day of the month - [1,31]
216 * int tm_mon; months since January - [0,11]
218 * int tm_wday; days since Sunday - [0,6]
219 * int tm_yday; days since January 1 - [0,365]
220 * int tm_isdst; daylight savings time flag
223 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
224 * and tm_isdst fields of the tm structure. And only converts years
227 * Returns TRUE if successfull.
229 static BOOL
TmToDATE( struct tm
* pTm
, DATE
*pDateOut
)
231 if( (pTm
->tm_year
- 1900) >= 0 )
235 /* Start at 1. This is the way DATE is defined.
236 * January 1, 1900 at Midnight is 1.00.
237 * January 1, 1900 at 6AM is 1.25.
242 /* Add the number of days corresponding to
245 *pDateOut
+= (pTm
->tm_year
- 1900) * 365;
247 /* Add the leap days in the previous years between now and 1900.
248 * Note a leap year is one that is a multiple of 4
249 * but not of a 100. Except if it is a multiple of
250 * 400 then it is a leap year.
252 *pDateOut
+= ( (pTm
->tm_year
- 1) / 4 ) - ( 1900 / 4 );
253 *pDateOut
-= ( (pTm
->tm_year
- 1) / 100 ) - ( 1900 / 100 );
254 *pDateOut
+= ( (pTm
->tm_year
- 1) / 400 ) - ( 1900 / 400 );
256 /* Set the leap year flag if the
257 * current year specified by tm_year is a
258 * leap year. This will be used to add a day
261 if( isleap( pTm
->tm_year
) )
264 /* Add the number of days corresponding to
267 switch( pTm
->tm_mon
)
273 *pDateOut
+= ( 59 + leapYear
);
276 *pDateOut
+= ( 90 + leapYear
);
279 *pDateOut
+= ( 120 + leapYear
);
282 *pDateOut
+= ( 151 + leapYear
);
285 *pDateOut
+= ( 181 + leapYear
);
288 *pDateOut
+= ( 212 + leapYear
);
291 *pDateOut
+= ( 243 + leapYear
);
294 *pDateOut
+= ( 273 + leapYear
);
297 *pDateOut
+= ( 304 + leapYear
);
300 *pDateOut
+= ( 334 + leapYear
);
303 /* Add the number of days in this month.
305 *pDateOut
+= pTm
->tm_mday
;
307 /* Add the number of seconds, minutes, and hours
308 * to the DATE. Note these are the fracionnal part
309 * of the DATE so seconds / number of seconds in a day.
311 *pDateOut
+= pTm
->tm_hour
/ 24.0;
312 *pDateOut
+= pTm
->tm_min
/ 1440.0;
313 *pDateOut
+= pTm
->tm_sec
/ 86400.0;
319 /******************************************************************************
320 * DateToTm [INTERNAL]
322 * This function converst a windows DATE to a tm structure.
324 * It does not fill all the fields of the tm structure.
325 * Here is a list of the fields that are filled:
326 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
328 * Note this function does not support dates before the January 1, 1900
329 * or ( dateIn < 2.0 ).
331 * Returns TRUE if successfull.
333 static BOOL
DateToTm( DATE dateIn
, LCID lcid
, struct tm
* pTm
)
335 /* Do not process dates smaller than January 1, 1900.
336 * Which corresponds to 2.0 in the windows DATE format.
340 double decimalPart
= 0.0;
341 double wholePart
= 0.0;
343 memset(pTm
,0,sizeof(*pTm
));
345 /* Because of the nature of DATE format witch
346 * associates 2.0 to January 1, 1900. We will
347 * remove 1.0 from the whole part of the DATE
348 * so that in the following code 1.0
349 * will correspond to January 1, 1900.
350 * This simplyfies the processing of the DATE value.
354 wholePart
= (double) floor( dateIn
);
355 decimalPart
= fmod( dateIn
, wholePart
);
357 if( !(lcid
& VAR_TIMEVALUEONLY
) )
361 double yearsSince1900
= 0;
362 /* Start at 1900, this where the DATE time 0.0 starts.
365 /* find in what year the day in the "wholePart" falls into.
366 * add the value to the year field.
368 yearsSince1900
= floor( (wholePart
/ DAYS_IN_ONE_YEAR
) + 0.001 );
369 pTm
->tm_year
+= yearsSince1900
;
370 /* determine if this is a leap year.
372 if( isleap( pTm
->tm_year
) )
378 /* find what day of that year does the "wholePart" corresponds to.
379 * Note: nDay is in [1-366] format
381 nDay
= (int) ( wholePart
- floor( yearsSince1900
* DAYS_IN_ONE_YEAR
) );
382 /* Set the tm_yday value.
383 * Note: The day is must be converted from [1-366] to [0-365]
385 /*pTm->tm_yday = nDay - 1;*/
386 /* find which mount this day corresponds to.
393 else if( nDay
<= ( 59 + leapYear
) )
395 pTm
->tm_mday
= nDay
- 31;
398 else if( nDay
<= ( 90 + leapYear
) )
400 pTm
->tm_mday
= nDay
- ( 59 + leapYear
);
403 else if( nDay
<= ( 120 + leapYear
) )
405 pTm
->tm_mday
= nDay
- ( 90 + leapYear
);
408 else if( nDay
<= ( 151 + leapYear
) )
410 pTm
->tm_mday
= nDay
- ( 120 + leapYear
);
413 else if( nDay
<= ( 181 + leapYear
) )
415 pTm
->tm_mday
= nDay
- ( 151 + leapYear
);
418 else if( nDay
<= ( 212 + leapYear
) )
420 pTm
->tm_mday
= nDay
- ( 181 + leapYear
);
423 else if( nDay
<= ( 243 + leapYear
) )
425 pTm
->tm_mday
= nDay
- ( 212 + leapYear
);
428 else if( nDay
<= ( 273 + leapYear
) )
430 pTm
->tm_mday
= nDay
- ( 243 + leapYear
);
433 else if( nDay
<= ( 304 + leapYear
) )
435 pTm
->tm_mday
= nDay
- ( 273 + leapYear
);
438 else if( nDay
<= ( 334 + leapYear
) )
440 pTm
->tm_mday
= nDay
- ( 304 + leapYear
);
443 else if( nDay
<= ( 365 + leapYear
) )
445 pTm
->tm_mday
= nDay
- ( 334 + leapYear
);
449 if( !(lcid
& VAR_DATEVALUEONLY
) )
451 /* find the number of seconds in this day.
452 * fractional part times, hours, minutes, seconds.
454 pTm
->tm_hour
= (int) ( decimalPart
* 24 );
455 pTm
->tm_min
= (int) ( ( ( decimalPart
* 24 ) - pTm
->tm_hour
) * 60 );
456 pTm
->tm_sec
= (int) ( ( ( decimalPart
* 24 * 60 ) - ( pTm
->tm_hour
* 60 ) - pTm
->tm_min
) * 60 );
465 /******************************************************************************
466 * SizeOfVariantData [INTERNAL]
468 * This function finds the size of the data referenced by a Variant based
469 * the type "vt" of the Variant.
471 static int SizeOfVariantData( VARIANT
* parg
)
474 switch( parg
->vt
& VT_TYPEMASK
)
477 size
= sizeof(short);
489 size
= sizeof(unsigned short);
492 size
= sizeof(unsigned int);
495 size
= sizeof(unsigned long);
498 size
= sizeof(float);
501 size
= sizeof(double);
507 size
= sizeof(VARIANT_BOOL
);
510 size
= sizeof(void*);
517 FIXME("Add size information for type vt=%d\n", parg
->vt
& VT_TYPEMASK
);
523 /******************************************************************************
524 * StringDupAtoBstr [INTERNAL]
527 static BSTR
StringDupAtoBstr( char* strIn
)
530 OLECHAR
* pNewString
= NULL
;
531 pNewString
= HEAP_strdupAtoW( GetProcessHeap(), 0, strIn
);
532 bstr
= SysAllocString( pNewString
);
533 HeapFree( GetProcessHeap(), 0, pNewString
);
537 /******************************************************************************
540 * Round the double value to the nearest integer value.
542 static double round( double d
)
544 double decimals
= 0.0, integerValue
= 0.0, roundedValue
= 0.0;
545 BOOL bEvenNumber
= FALSE
;
548 /* Save the sign of the number
550 nSign
= (d
>= 0.0) ? 1 : -1;
553 /* Remove the decimals.
555 integerValue
= floor( d
);
557 /* Set the Even flag. This is used to round the number when
558 * the decimals are exactly 1/2. If the integer part is
559 * odd the number is rounded up. If the integer part
560 * is even the number is rounded down. Using this method
561 * numbers are rounded up|down half the time.
563 bEvenNumber
= (((short)fmod(integerValue
, 2)) == 0) ? TRUE
: FALSE
;
565 /* Remove the integral part of the number.
567 decimals
= d
- integerValue
;
569 /* Note: Ceil returns the smallest integer that is greater that x.
570 * and floor returns the largest integer that is less than or equal to x.
574 /* If the decimal part is greater than 1/2
576 roundedValue
= ceil( d
);
578 else if( decimals
< 0.5 )
580 /* If the decimal part is smaller than 1/2
582 roundedValue
= floor( d
);
586 /* the decimals are exactly 1/2 so round according to
587 * the bEvenNumber flag.
591 roundedValue
= floor( d
);
595 roundedValue
= ceil( d
);
599 return roundedValue
* nSign
;
602 /******************************************************************************
603 * RemoveCharacterFromString [INTERNAL]
605 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
607 static void RemoveCharacterFromString( LPSTR str
, LPSTR strOfCharToRemove
)
609 LPSTR pNewString
= NULL
;
610 LPSTR strToken
= NULL
;
613 /* Check if we have a valid argument
617 pNewString
= strdup( str
);
619 strToken
= strtok( pNewString
, strOfCharToRemove
);
620 while( strToken
!= NULL
) {
621 strcat( str
, strToken
);
622 strToken
= strtok( NULL
, strOfCharToRemove
);
629 /******************************************************************************
630 * GetValidRealString [INTERNAL]
632 * Checks if the string is of proper format to be converted to a real value.
634 static BOOL
IsValidRealString( LPSTR strRealString
)
636 /* Real values that have a decimal point are required to either have
637 * digits before or after the decimal point. We will assume that
638 * we do not have any digits at either position. If we do encounter
639 * some we will disable this flag.
641 BOOL bDigitsRequired
= TRUE
;
642 /* Processed fields in the string representation of the real number.
644 BOOL bWhiteSpaceProcessed
= FALSE
;
645 BOOL bFirstSignProcessed
= FALSE
;
646 BOOL bFirstDigitsProcessed
= FALSE
;
647 BOOL bDecimalPointProcessed
= FALSE
;
648 BOOL bSecondDigitsProcessed
= FALSE
;
649 BOOL bExponentProcessed
= FALSE
;
650 BOOL bSecondSignProcessed
= FALSE
;
651 BOOL bThirdDigitsProcessed
= FALSE
;
652 /* Assume string parameter "strRealString" is valid and try to disprove it.
654 BOOL bValidRealString
= TRUE
;
656 /* Used to count the number of tokens in the "strRealString".
658 LPSTR strToken
= NULL
;
662 /* Check if we have a valid argument
664 if( strRealString
== NULL
)
666 bValidRealString
= FALSE
;
669 if( bValidRealString
== TRUE
)
671 /* Make sure we only have ONE token in the string.
673 strToken
= strtok( strRealString
, " " );
674 while( strToken
!= NULL
) {
676 strToken
= strtok( NULL
, " " );
681 bValidRealString
= FALSE
;
686 /* Make sure this token contains only valid characters.
687 * The string argument to atof has the following form:
688 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
689 * Whitespace consists of space and|or <TAB> characters, which are ignored.
690 * Sign is either plus '+' or minus '-'.
691 * Digits are one or more decimal digits.
692 * Note: If no digits appear before the decimal point, at least one must
693 * appear after the decimal point.
694 * The decimal digits may be followed by an exponent.
695 * An Exponent consists of an introductory letter ( D, d, E, or e) and
696 * an optionally signed decimal integer.
698 pChar
= strRealString
;
699 while( bValidRealString
== TRUE
&& *pChar
!= '\0' )
707 if( bWhiteSpaceProcessed
||
708 bFirstSignProcessed
||
709 bFirstDigitsProcessed
||
710 bDecimalPointProcessed
||
711 bSecondDigitsProcessed
||
712 bExponentProcessed
||
713 bSecondSignProcessed
||
714 bThirdDigitsProcessed
)
716 bValidRealString
= FALSE
;
723 if( bFirstSignProcessed
== FALSE
)
725 if( bFirstDigitsProcessed
||
726 bDecimalPointProcessed
||
727 bSecondDigitsProcessed
||
728 bExponentProcessed
||
729 bSecondSignProcessed
||
730 bThirdDigitsProcessed
)
732 bValidRealString
= FALSE
;
734 bWhiteSpaceProcessed
= TRUE
;
735 bFirstSignProcessed
= TRUE
;
737 else if( bSecondSignProcessed
== FALSE
)
739 /* Note: The exponent must be present in
740 * order to accept the second sign...
742 if( bExponentProcessed
== FALSE
||
743 bThirdDigitsProcessed
||
746 bValidRealString
= FALSE
;
748 bFirstSignProcessed
= TRUE
;
749 bWhiteSpaceProcessed
= TRUE
;
750 bFirstDigitsProcessed
= TRUE
;
751 bDecimalPointProcessed
= TRUE
;
752 bSecondDigitsProcessed
= TRUE
;
753 bSecondSignProcessed
= TRUE
;
769 if( bFirstDigitsProcessed
== FALSE
)
771 if( bDecimalPointProcessed
||
772 bSecondDigitsProcessed
||
773 bExponentProcessed
||
774 bSecondSignProcessed
||
775 bThirdDigitsProcessed
)
777 bValidRealString
= FALSE
;
779 bFirstSignProcessed
= TRUE
;
780 bWhiteSpaceProcessed
= TRUE
;
781 /* We have found some digits before the decimal point
782 * so disable the "Digits required" flag.
784 bDigitsRequired
= FALSE
;
786 else if( bSecondDigitsProcessed
== FALSE
)
788 if( bExponentProcessed
||
789 bSecondSignProcessed
||
790 bThirdDigitsProcessed
)
792 bValidRealString
= FALSE
;
794 bFirstSignProcessed
= TRUE
;
795 bWhiteSpaceProcessed
= TRUE
;
796 bFirstDigitsProcessed
= TRUE
;
797 bDecimalPointProcessed
= TRUE
;
798 /* We have found some digits after the decimal point
799 * so disable the "Digits required" flag.
801 bDigitsRequired
= FALSE
;
803 else if( bThirdDigitsProcessed
== FALSE
)
805 /* Getting here means everything else should be processed.
806 * If we get anything else than a decimal following this
807 * digit it will be flagged by the other cases, so
808 * we do not really need to do anything in here.
812 /* If DecimalPoint...
815 if( bDecimalPointProcessed
||
816 bSecondDigitsProcessed
||
817 bExponentProcessed
||
818 bSecondSignProcessed
||
819 bThirdDigitsProcessed
)
821 bValidRealString
= FALSE
;
823 bFirstSignProcessed
= TRUE
;
824 bWhiteSpaceProcessed
= TRUE
;
825 bFirstDigitsProcessed
= TRUE
;
826 bDecimalPointProcessed
= TRUE
;
834 if( bExponentProcessed
||
835 bSecondSignProcessed
||
836 bThirdDigitsProcessed
||
839 bValidRealString
= FALSE
;
841 bFirstSignProcessed
= TRUE
;
842 bWhiteSpaceProcessed
= TRUE
;
843 bFirstDigitsProcessed
= TRUE
;
844 bDecimalPointProcessed
= TRUE
;
845 bSecondDigitsProcessed
= TRUE
;
846 bExponentProcessed
= TRUE
;
849 bValidRealString
= FALSE
;
852 /* Process next character.
857 /* If the required digits were not present we have an invalid
858 * string representation of a real number.
860 if( bDigitsRequired
== TRUE
)
862 bValidRealString
= FALSE
;
865 return bValidRealString
;
869 /******************************************************************************
872 * This function dispatches execution to the proper conversion API
873 * to do the necessary coercion.
875 static HRESULT
Coerce( VARIANTARG
* pd
, LCID lcid
, ULONG dwFlags
, VARIANTARG
* ps
, VARTYPE vt
)
878 unsigned short vtFrom
= 0;
879 vtFrom
= ps
->vt
& VT_TYPEMASK
;
881 /* Note: Since "long" and "int" values both have 4 bytes and are
882 * both signed integers "int" will be treated as "long" in the
884 * The same goes for their unsigned versions.
887 /* Trivial Case: If the coercion is from two types that are
888 * identical then we can blindly copy from one argument to another.*/
891 return VariantCopy(pd
,ps
);
894 /* Cases requiring thought*/
899 res
= VariantClear( pd
);
902 res
= VariantClear( pd
);
912 res
= VariantCopy( pd
, ps
);
915 res
= VarI1FromI2( ps
->u
.iVal
, &(pd
->u
.cVal
) );
919 res
= VarI1FromI4( ps
->u
.lVal
, &(pd
->u
.cVal
) );
922 res
= VarI1FromUI1( ps
->u
.bVal
, &(pd
->u
.cVal
) );
925 res
= VarI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.cVal
) );
929 res
= VarI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.cVal
) );
932 res
= VarI1FromR4( ps
->u
.fltVal
, &(pd
->u
.cVal
) );
935 res
= VarI1FromR8( ps
->u
.dblVal
, &(pd
->u
.cVal
) );
938 res
= VarI1FromDate( ps
->u
.date
, &(pd
->u
.cVal
) );
941 res
= VarI1FromBool( ps
->u
.boolVal
, &(pd
->u
.cVal
) );
944 res
= VarI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.cVal
) );
947 res
= VarI1FromCy( ps
->u
.cyVal
, &(pd
->u
.cVal
) );
949 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
951 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
953 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
955 res
= DISP_E_TYPEMISMATCH
;
956 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
965 res
= VarI2FromI1( ps
->u
.cVal
, &(pd
->u
.iVal
) );
968 res
= VariantCopy( pd
, ps
);
972 res
= VarI2FromI4( ps
->u
.lVal
, &(pd
->u
.iVal
) );
975 res
= VarI2FromUI1( ps
->u
.bVal
, &(pd
->u
.iVal
) );
978 res
= VarI2FromUI2( ps
->u
.uiVal
, &(pd
->u
.iVal
) );
982 res
= VarI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.iVal
) );
985 res
= VarI2FromR4( ps
->u
.fltVal
, &(pd
->u
.iVal
) );
988 res
= VarI2FromR8( ps
->u
.dblVal
, &(pd
->u
.iVal
) );
991 res
= VarI2FromDate( ps
->u
.date
, &(pd
->u
.iVal
) );
994 res
= VarI2FromBool( ps
->u
.boolVal
, &(pd
->u
.iVal
) );
997 res
= VarI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.iVal
) );
1000 res
= VarI2FromCy( ps
->u
.cyVal
, &(pd
->u
.iVal
) );
1001 case( VT_DISPATCH
):
1002 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1004 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
1006 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
1008 res
= DISP_E_TYPEMISMATCH
;
1009 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1019 res
= VarI4FromI1( ps
->u
.cVal
, &(pd
->u
.lVal
) );
1022 res
= VarI4FromI2( ps
->u
.iVal
, &(pd
->u
.lVal
) );
1026 res
= VariantCopy( pd
, ps
);
1029 res
= VarI4FromUI1( ps
->u
.bVal
, &(pd
->u
.lVal
) );
1032 res
= VarI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.lVal
) );
1036 res
= VarI4FromUI4( ps
->u
.ulVal
, &(pd
->u
.lVal
) );
1039 res
= VarI4FromR4( ps
->u
.fltVal
, &(pd
->u
.lVal
) );
1042 res
= VarI4FromR8( ps
->u
.dblVal
, &(pd
->u
.lVal
) );
1045 res
= VarI4FromDate( ps
->u
.date
, &(pd
->u
.lVal
) );
1048 res
= VarI4FromBool( ps
->u
.boolVal
, &(pd
->u
.lVal
) );
1051 res
= VarI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.lVal
) );
1054 res
= VarI4FromCy( ps
->u
.cyVal
, &(pd
->u
.lVal
) );
1055 case( VT_DISPATCH
):
1056 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1058 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1060 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1062 res
= DISP_E_TYPEMISMATCH
;
1063 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1072 res
= VarUI1FromI1( ps
->u
.cVal
, &(pd
->u
.bVal
) );
1075 res
= VarUI1FromI2( ps
->u
.iVal
, &(pd
->u
.bVal
) );
1079 res
= VarUI1FromI4( ps
->u
.lVal
, &(pd
->u
.bVal
) );
1082 res
= VariantCopy( pd
, ps
);
1085 res
= VarUI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.bVal
) );
1089 res
= VarUI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.bVal
) );
1092 res
= VarUI1FromR4( ps
->u
.fltVal
, &(pd
->u
.bVal
) );
1095 res
= VarUI1FromR8( ps
->u
.dblVal
, &(pd
->u
.bVal
) );
1098 res
= VarUI1FromDate( ps
->u
.date
, &(pd
->u
.bVal
) );
1101 res
= VarUI1FromBool( ps
->u
.boolVal
, &(pd
->u
.bVal
) );
1104 res
= VarUI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.bVal
) );
1107 res
= VarUI1FromCy( ps
->u
.cyVal
, &(pd
->u
.bVal
) );
1108 case( VT_DISPATCH
):
1109 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1111 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1113 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1115 res
= DISP_E_TYPEMISMATCH
;
1116 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1125 res
= VarUI2FromI1( ps
->u
.cVal
, &(pd
->u
.uiVal
) );
1128 res
= VarUI2FromI2( ps
->u
.iVal
, &(pd
->u
.uiVal
) );
1132 res
= VarUI2FromI4( ps
->u
.lVal
, &(pd
->u
.uiVal
) );
1135 res
= VarUI2FromUI1( ps
->u
.bVal
, &(pd
->u
.uiVal
) );
1138 res
= VariantCopy( pd
, ps
);
1142 res
= VarUI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.uiVal
) );
1145 res
= VarUI2FromR4( ps
->u
.fltVal
, &(pd
->u
.uiVal
) );
1148 res
= VarUI2FromR8( ps
->u
.dblVal
, &(pd
->u
.uiVal
) );
1151 res
= VarUI2FromDate( ps
->u
.date
, &(pd
->u
.uiVal
) );
1154 res
= VarUI2FromBool( ps
->u
.boolVal
, &(pd
->u
.uiVal
) );
1157 res
= VarUI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.uiVal
) );
1160 res
= VarUI2FromCy( ps
->u
.cyVal
, &(pd
->u
.uiVal
) );
1161 case( VT_DISPATCH
):
1162 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1164 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1166 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1168 res
= DISP_E_TYPEMISMATCH
;
1169 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1179 res
= VarUI4FromI1( ps
->u
.cVal
, &(pd
->u
.ulVal
) );
1182 res
= VarUI4FromI2( ps
->u
.iVal
, &(pd
->u
.ulVal
) );
1186 res
= VarUI4FromI4( ps
->u
.lVal
, &(pd
->u
.ulVal
) );
1189 res
= VarUI4FromUI1( ps
->u
.bVal
, &(pd
->u
.ulVal
) );
1192 res
= VarUI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.ulVal
) );
1195 res
= VariantCopy( pd
, ps
);
1198 res
= VarUI4FromR4( ps
->u
.fltVal
, &(pd
->u
.ulVal
) );
1201 res
= VarUI4FromR8( ps
->u
.dblVal
, &(pd
->u
.ulVal
) );
1204 res
= VarUI4FromDate( ps
->u
.date
, &(pd
->u
.ulVal
) );
1207 res
= VarUI4FromBool( ps
->u
.boolVal
, &(pd
->u
.ulVal
) );
1210 res
= VarUI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.ulVal
) );
1213 res
= VarUI4FromCy( ps
->u
.cyVal
, &(pd
->u
.ulVal
) );
1214 case( VT_DISPATCH
):
1215 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1217 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1219 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1221 res
= DISP_E_TYPEMISMATCH
;
1222 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1231 res
= VarR4FromI1( ps
->u
.cVal
, &(pd
->u
.fltVal
) );
1234 res
= VarR4FromI2( ps
->u
.iVal
, &(pd
->u
.fltVal
) );
1238 res
= VarR4FromI4( ps
->u
.lVal
, &(pd
->u
.fltVal
) );
1241 res
= VarR4FromUI1( ps
->u
.bVal
, &(pd
->u
.fltVal
) );
1244 res
= VarR4FromUI2( ps
->u
.uiVal
, &(pd
->u
.fltVal
) );
1248 res
= VarR4FromUI4( ps
->u
.ulVal
, &(pd
->u
.fltVal
) );
1251 res
= VariantCopy( pd
, ps
);
1254 res
= VarR4FromR8( ps
->u
.dblVal
, &(pd
->u
.fltVal
) );
1257 res
= VarR4FromDate( ps
->u
.date
, &(pd
->u
.fltVal
) );
1260 res
= VarR4FromBool( ps
->u
.boolVal
, &(pd
->u
.fltVal
) );
1263 res
= VarR4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.fltVal
) );
1266 res
= VarR4FromCy( ps
->u
.cyVal
, &(pd
->u
.fltVal
) );
1267 case( VT_DISPATCH
):
1268 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1270 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1272 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1274 res
= DISP_E_TYPEMISMATCH
;
1275 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1284 res
= VarR8FromI1( ps
->u
.cVal
, &(pd
->u
.dblVal
) );
1287 res
= VarR8FromI2( ps
->u
.iVal
, &(pd
->u
.dblVal
) );
1291 res
= VarR8FromI4( ps
->u
.lVal
, &(pd
->u
.dblVal
) );
1294 res
= VarR8FromUI1( ps
->u
.bVal
, &(pd
->u
.dblVal
) );
1297 res
= VarR8FromUI2( ps
->u
.uiVal
, &(pd
->u
.dblVal
) );
1301 res
= VarR8FromUI4( ps
->u
.ulVal
, &(pd
->u
.dblVal
) );
1304 res
= VarR8FromR4( ps
->u
.fltVal
, &(pd
->u
.dblVal
) );
1307 res
= VariantCopy( pd
, ps
);
1310 res
= VarR8FromDate( ps
->u
.date
, &(pd
->u
.dblVal
) );
1313 res
= VarR8FromBool( ps
->u
.boolVal
, &(pd
->u
.dblVal
) );
1316 res
= VarR8FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.dblVal
) );
1319 res
= VarR8FromCy( ps
->u
.cyVal
, &(pd
->u
.dblVal
) );
1320 case( VT_DISPATCH
):
1321 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1323 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1325 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1327 res
= DISP_E_TYPEMISMATCH
;
1328 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1337 res
= VarDateFromI1( ps
->u
.cVal
, &(pd
->u
.date
) );
1340 res
= VarDateFromI2( ps
->u
.iVal
, &(pd
->u
.date
) );
1343 res
= VarDateFromInt( ps
->u
.intVal
, &(pd
->u
.date
) );
1346 res
= VarDateFromI4( ps
->u
.lVal
, &(pd
->u
.date
) );
1349 res
= VarDateFromUI1( ps
->u
.bVal
, &(pd
->u
.date
) );
1352 res
= VarDateFromUI2( ps
->u
.uiVal
, &(pd
->u
.date
) );
1355 res
= VarDateFromUint( ps
->u
.uintVal
, &(pd
->u
.date
) );
1358 res
= VarDateFromUI4( ps
->u
.ulVal
, &(pd
->u
.date
) );
1361 res
= VarDateFromR4( ps
->u
.fltVal
, &(pd
->u
.date
) );
1364 res
= VarDateFromR8( ps
->u
.dblVal
, &(pd
->u
.date
) );
1367 res
= VariantCopy( pd
, ps
);
1370 res
= VarDateFromBool( ps
->u
.boolVal
, &(pd
->u
.date
) );
1373 res
= VarDateFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.date
) );
1376 res
= VarDateFromCy( ps
->u
.cyVal
, &(pd
->u
.date
) );
1377 case( VT_DISPATCH
):
1378 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1380 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1382 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1384 res
= DISP_E_TYPEMISMATCH
;
1385 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1394 res
= VarBoolFromI1( ps
->u
.cVal
, &(pd
->u
.boolVal
) );
1397 res
= VarBoolFromI2( ps
->u
.iVal
, &(pd
->u
.boolVal
) );
1400 res
= VarBoolFromInt( ps
->u
.intVal
, &(pd
->u
.boolVal
) );
1403 res
= VarBoolFromI4( ps
->u
.lVal
, &(pd
->u
.boolVal
) );
1406 res
= VarBoolFromUI1( ps
->u
.bVal
, &(pd
->u
.boolVal
) );
1409 res
= VarBoolFromUI2( ps
->u
.uiVal
, &(pd
->u
.boolVal
) );
1412 res
= VarBoolFromUint( ps
->u
.uintVal
, &(pd
->u
.boolVal
) );
1415 res
= VarBoolFromUI4( ps
->u
.ulVal
, &(pd
->u
.boolVal
) );
1418 res
= VarBoolFromR4( ps
->u
.fltVal
, &(pd
->u
.boolVal
) );
1421 res
= VarBoolFromR8( ps
->u
.dblVal
, &(pd
->u
.boolVal
) );
1424 res
= VarBoolFromDate( ps
->u
.date
, &(pd
->u
.boolVal
) );
1427 res
= VariantCopy( pd
, ps
);
1430 res
= VarBoolFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.boolVal
) );
1433 res
= VarBoolFromCy( ps
->u
.cyVal
, &(pd
->u
.boolVal
) );
1434 case( VT_DISPATCH
):
1435 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1437 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1439 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1441 res
= DISP_E_TYPEMISMATCH
;
1442 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1451 res
= VarBstrFromI1( ps
->u
.cVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1454 res
= VarBstrFromI2( ps
->u
.iVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1457 res
= VarBstrFromInt( ps
->u
.intVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1460 res
= VarBstrFromI4( ps
->u
.lVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1463 res
= VarBstrFromUI1( ps
->u
.bVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1466 res
= VarBstrFromUI2( ps
->u
.uiVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1469 res
= VarBstrFromUint( ps
->u
.uintVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1472 res
= VarBstrFromUI4( ps
->u
.ulVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1475 res
= VarBstrFromR4( ps
->u
.fltVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1478 res
= VarBstrFromR8( ps
->u
.dblVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1481 res
= VarBstrFromDate( ps
->u
.date
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1484 res
= VarBstrFromBool( ps
->u
.boolVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1487 res
= VariantCopy( pd
, ps
);
1490 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1491 case( VT_DISPATCH
):
1492 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1494 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1496 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1498 res
= DISP_E_TYPEMISMATCH
;
1499 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1508 res
= VarCyFromI1( ps
->u
.cVal
, &(pd
->u
.cyVal
) );
1511 res
= VarCyFromI2( ps
->u
.iVal
, &(pd
->u
.cyVal
) );
1514 res
= VarCyFromInt( ps
->u
.intVal
, &(pd
->u
.cyVal
) );
1517 res
= VarCyFromI4( ps
->u
.lVal
, &(pd
->u
.cyVal
) );
1520 res
= VarCyFromUI1( ps
->u
.bVal
, &(pd
->u
.cyVal
) );
1523 res
= VarCyFromUI2( ps
->u
.uiVal
, &(pd
->u
.cyVal
) );
1526 res
= VarCyFromUint( ps
->u
.uintVal
, &(pd
->u
.cyVal
) );
1529 res
= VarCyFromUI4( ps
->u
.ulVal
, &(pd
->u
.cyVal
) );
1532 res
= VarCyFromR4( ps
->u
.fltVal
, &(pd
->u
.cyVal
) );
1535 res
= VarCyFromR8( ps
->u
.dblVal
, &(pd
->u
.cyVal
) );
1538 res
= VarCyFromDate( ps
->u
.date
, &(pd
->u
.cyVal
) );
1541 res
= VarCyFromBool( ps
->u
.date
, &(pd
->u
.cyVal
) );
1544 res
= VariantCopy( pd
, ps
);
1547 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1548 case( VT_DISPATCH
):
1549 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1551 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1553 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1555 res
= DISP_E_TYPEMISMATCH
;
1556 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1562 res
= DISP_E_TYPEMISMATCH
;
1563 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1570 /******************************************************************************
1571 * ValidateVtRange [INTERNAL]
1573 * Used internally by the hi-level Variant API to determine
1574 * if the vartypes are valid.
1576 static HRESULT WINAPI
ValidateVtRange( VARTYPE vt
)
1578 /* if by value we must make sure it is in the
1579 * range of the valid types.
1581 if( ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1583 return DISP_E_BADVARTYPE
;
1589 /******************************************************************************
1590 * ValidateVartype [INTERNAL]
1592 * Used internally by the hi-level Variant API to determine
1593 * if the vartypes are valid.
1595 static HRESULT WINAPI
ValidateVariantType( VARTYPE vt
)
1599 /* check if we have a valid argument.
1603 /* if by reference check that the type is in
1604 * the valid range and that it is not of empty or null type
1606 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1607 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1608 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1616 res
= ValidateVtRange( vt
);
1622 /******************************************************************************
1623 * ValidateVt [INTERNAL]
1625 * Used internally by the hi-level Variant API to determine
1626 * if the vartypes are valid.
1628 static HRESULT WINAPI
ValidateVt( VARTYPE vt
)
1632 /* check if we have a valid argument.
1636 /* if by reference check that the type is in
1637 * the valid range and that it is not of empty or null type
1639 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1640 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1641 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1643 res
= DISP_E_BADVARTYPE
;
1649 res
= ValidateVtRange( vt
);
1659 /******************************************************************************
1660 * VariantInit [OLEAUT32.8]
1662 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1663 * contents of the Variant.
1665 void WINAPI
VariantInit(VARIANTARG
* pvarg
)
1667 TRACE("(%p),stub\n",pvarg
);
1669 memset(pvarg
, 0, sizeof (VARIANTARG
));
1670 pvarg
->vt
= VT_EMPTY
;
1675 /******************************************************************************
1676 * VariantClear [OLEAUT32.9]
1678 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1679 * sets the wReservedX field to 0. The current contents of the VARIANT are
1680 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1681 * released. If VT_ARRAY the array is freed.
1683 HRESULT WINAPI
VariantClear(VARIANTARG
* pvarg
)
1686 TRACE("(%p)\n",pvarg
);
1688 res
= ValidateVariantType( pvarg
->vt
);
1691 if( !( pvarg
->vt
& VT_BYREF
) )
1694 * The VT_ARRAY flag is a special case of a safe array.
1696 if ( (pvarg
->vt
& VT_ARRAY
) != 0)
1698 SafeArrayDestroy(pvarg
->u
.parray
);
1702 switch( pvarg
->vt
& VT_TYPEMASK
)
1705 SysFreeString( pvarg
->u
.bstrVal
);
1707 case( VT_DISPATCH
):
1708 if(pvarg
->u
.pdispVal
!=NULL
)
1709 ICOM_CALL(Release
,pvarg
->u
.pdispVal
);
1712 VariantClear(pvarg
->u
.pvarVal
);
1715 if(pvarg
->u
.punkVal
!=NULL
)
1716 ICOM_CALL(Release
,pvarg
->u
.punkVal
);
1718 case( VT_SAFEARRAY
):
1719 SafeArrayDestroy(pvarg
->u
.parray
);
1728 * Empty all the fields and mark the type as empty.
1730 memset(pvarg
, 0, sizeof (VARIANTARG
));
1731 pvarg
->vt
= VT_EMPTY
;
1737 /******************************************************************************
1738 * VariantCopy [OLEAUT32.10]
1740 * Frees up the designation variant and makes a copy of the source.
1742 HRESULT WINAPI
VariantCopy(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
)
1746 TRACE("(%p, %p)\n", pvargDest
, pvargSrc
);
1748 res
= ValidateVariantType( pvargSrc
->vt
);
1750 /* If the pointer are to the same variant we don't need
1753 if( pvargDest
!= pvargSrc
&& res
== S_OK
)
1755 res
= VariantClear( pvargDest
);
1759 if( pvargSrc
->vt
& VT_BYREF
)
1761 /* In the case of byreference we only need
1762 * to copy the pointer.
1764 pvargDest
->u
= pvargSrc
->u
;
1765 pvargDest
->vt
= pvargSrc
->vt
;
1770 * The VT_ARRAY flag is another way to designate a safe array.
1772 if (pvargSrc
->vt
& VT_ARRAY
)
1774 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1778 /* In the case of by value we need to
1779 * copy the actuall value. In the case of
1780 * VT_BSTR a copy of the string is made,
1781 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1782 * called to increment the object's reference count.
1784 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1787 pvargDest
->u
.bstrVal
= SysAllocString( pvargSrc
->u
.bstrVal
);
1789 case( VT_DISPATCH
):
1790 pvargDest
->u
.pdispVal
= pvargSrc
->u
.pdispVal
;
1791 if (pvargDest
->u
.pdispVal
!=NULL
)
1792 ICOM_CALL(AddRef
,pvargDest
->u
.pdispVal
);
1795 VariantCopy(pvargDest
->u
.pvarVal
,pvargSrc
->u
.pvarVal
);
1798 pvargDest
->u
.punkVal
= pvargSrc
->u
.punkVal
;
1799 if (pvargDest
->u
.pdispVal
!=NULL
)
1800 ICOM_CALL(AddRef
,pvargDest
->u
.punkVal
);
1802 case( VT_SAFEARRAY
):
1803 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1806 pvargDest
->u
= pvargSrc
->u
;
1811 pvargDest
->vt
= pvargSrc
->vt
;
1820 /******************************************************************************
1821 * VariantCopyInd [OLEAUT32.11]
1823 * Frees up the destination variant and makes a copy of the source. If
1824 * the source is of type VT_BYREF it performs the necessary indirections.
1826 HRESULT WINAPI
VariantCopyInd(VARIANT
* pvargDest
, VARIANTARG
* pvargSrc
)
1830 TRACE("(%p, %p)\n", pvargDest
, pvargSrc
);
1832 res
= ValidateVariantType( pvargSrc
->vt
);
1837 if( pvargSrc
->vt
& VT_BYREF
)
1840 VariantInit( &varg
);
1842 /* handle the in place copy.
1844 if( pvargDest
== pvargSrc
)
1846 /* we will use a copy of the source instead.
1848 res
= VariantCopy( &varg
, pvargSrc
);
1854 res
= VariantClear( pvargDest
);
1859 * The VT_ARRAY flag is another way to designate a safearray variant.
1861 if ( pvargSrc
->vt
& VT_ARRAY
)
1863 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1867 /* In the case of by reference we need
1868 * to copy the date pointed to by the variant.
1871 /* Get the variant type.
1873 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1876 pvargDest
->u
.bstrVal
= SysAllocString( *(pvargSrc
->u
.pbstrVal
) );
1878 case( VT_DISPATCH
):
1882 /* Prevent from cycling. According to tests on
1883 * VariantCopyInd in Windows and the documentation
1884 * this API dereferences the inner Variants to only one depth.
1885 * If the inner Variant itself contains an
1886 * other inner variant the E_INVALIDARG error is
1889 if( pvargSrc
->wReserved1
& PROCESSING_INNER_VARIANT
)
1891 /* If we get here we are attempting to deference
1892 * an inner variant that that is itself contained
1893 * in an inner variant so report E_INVALIDARG error.
1899 /* Set the processing inner variant flag.
1900 * We will set this flag in the inner variant
1901 * that will be passed to the VariantCopyInd function.
1903 (pvargSrc
->u
.pvarVal
)->wReserved1
|= PROCESSING_INNER_VARIANT
;
1905 /* Dereference the inner variant.
1907 res
= VariantCopyInd( pvargDest
, pvargSrc
->u
.pvarVal
);
1908 /* We must also copy its type, I think.
1910 pvargSrc
->vt
= pvargSrc
->u
.pvarVal
->vt
;
1916 case( VT_SAFEARRAY
):
1917 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1920 /* This is a by reference Variant which means that the union
1921 * part of the Variant contains a pointer to some data of
1922 * type "pvargSrc->vt & VT_TYPEMASK".
1923 * We will deference this data in a generic fashion using
1924 * the void pointer "Variant.u.byref".
1925 * We will copy this data into the union of the destination
1928 memcpy( &pvargDest
->u
, pvargSrc
->u
.byref
, SizeOfVariantData( pvargSrc
) );
1933 pvargDest
->vt
= pvargSrc
->vt
& VT_TYPEMASK
;
1937 /* this should not fail.
1939 VariantClear( &varg
);
1943 res
= VariantCopy( pvargDest
, pvargSrc
);
1949 /******************************************************************************
1950 * VariantChangeType [OLEAUT32.12]
1952 HRESULT WINAPI
VariantChangeType(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1953 USHORT wFlags
, VARTYPE vt
)
1955 return VariantChangeTypeEx( pvargDest
, pvargSrc
, 0, wFlags
, vt
);
1958 /******************************************************************************
1959 * VariantChangeTypeEx [OLEAUT32.147]
1961 HRESULT WINAPI
VariantChangeTypeEx(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1962 LCID lcid
, USHORT wFlags
, VARTYPE vt
)
1966 VariantInit( &varg
);
1968 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest
, pvargSrc
, lcid
, wFlags
, vt
);
1970 /* validate our source argument.
1972 res
= ValidateVariantType( pvargSrc
->vt
);
1974 /* validate the vartype.
1978 res
= ValidateVt( vt
);
1981 /* if we are doing an in-place conversion make a copy of the source.
1983 if( res
== S_OK
&& pvargDest
== pvargSrc
)
1985 res
= VariantCopy( &varg
, pvargSrc
);
1991 /* free up the destination variant.
1993 res
= VariantClear( pvargDest
);
1998 if( pvargSrc
->vt
& VT_BYREF
)
2000 /* Convert the source variant to a "byvalue" variant.
2003 VariantInit( &Variant
);
2004 res
= VariantCopyInd( &Variant
, pvargSrc
);
2007 res
= Coerce( pvargDest
, lcid
, wFlags
, &Variant
, vt
);
2008 /* this should not fail.
2010 VariantClear( &Variant
);
2016 /* Use the current "byvalue" source variant.
2018 res
= Coerce( pvargDest
, lcid
, wFlags
, pvargSrc
, vt
);
2021 /* this should not fail.
2023 VariantClear( &varg
);
2025 /* set the type of the destination
2036 /******************************************************************************
2037 * VarUI1FromI2 [OLEAUT32.130]
2039 HRESULT WINAPI
VarUI1FromI2(short sIn
, BYTE
* pbOut
)
2041 TRACE("( %d, %p ), stub\n", sIn
, pbOut
);
2043 /* Check range of value.
2045 if( sIn
< UI1_MIN
|| sIn
> UI1_MAX
)
2047 return DISP_E_OVERFLOW
;
2050 *pbOut
= (BYTE
) sIn
;
2055 /******************************************************************************
2056 * VarUI1FromI4 [OLEAUT32.131]
2058 HRESULT WINAPI
VarUI1FromI4(LONG lIn
, BYTE
* pbOut
)
2060 TRACE("( %ld, %p ), stub\n", lIn
, pbOut
);
2062 /* Check range of value.
2064 if( lIn
< UI1_MIN
|| lIn
> UI1_MAX
)
2066 return DISP_E_OVERFLOW
;
2069 *pbOut
= (BYTE
) lIn
;
2075 /******************************************************************************
2076 * VarUI1FromR4 [OLEAUT32.132]
2078 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
2080 TRACE("( %f, %p ), stub\n", fltIn
, pbOut
);
2082 /* Check range of value.
2084 fltIn
= round( fltIn
);
2085 if( fltIn
< UI1_MIN
|| fltIn
> UI1_MAX
)
2087 return DISP_E_OVERFLOW
;
2090 *pbOut
= (BYTE
) fltIn
;
2095 /******************************************************************************
2096 * VarUI1FromR8 [OLEAUT32.133]
2098 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
2100 TRACE("( %f, %p ), stub\n", dblIn
, pbOut
);
2102 /* Check range of value.
2104 dblIn
= round( dblIn
);
2105 if( dblIn
< UI1_MIN
|| dblIn
> UI1_MAX
)
2107 return DISP_E_OVERFLOW
;
2110 *pbOut
= (BYTE
) dblIn
;
2115 /******************************************************************************
2116 * VarUI1FromDate [OLEAUT32.135]
2118 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
2120 TRACE("( %f, %p ), stub\n", dateIn
, pbOut
);
2122 /* Check range of value.
2124 dateIn
= round( dateIn
);
2125 if( dateIn
< UI1_MIN
|| dateIn
> UI1_MAX
)
2127 return DISP_E_OVERFLOW
;
2130 *pbOut
= (BYTE
) dateIn
;
2135 /******************************************************************************
2136 * VarUI1FromBool [OLEAUT32.138]
2138 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
2140 TRACE("( %d, %p ), stub\n", boolIn
, pbOut
);
2142 *pbOut
= (BYTE
) boolIn
;
2147 /******************************************************************************
2148 * VarUI1FromI1 [OLEAUT32.237]
2150 HRESULT WINAPI
VarUI1FromI1(CHAR cIn
, BYTE
* pbOut
)
2152 TRACE("( %c, %p ), stub\n", cIn
, pbOut
);
2159 /******************************************************************************
2160 * VarUI1FromUI2 [OLEAUT32.238]
2162 HRESULT WINAPI
VarUI1FromUI2(USHORT uiIn
, BYTE
* pbOut
)
2164 TRACE("( %d, %p ), stub\n", uiIn
, pbOut
);
2166 /* Check range of value.
2168 if( uiIn
> UI1_MAX
)
2170 return DISP_E_OVERFLOW
;
2173 *pbOut
= (BYTE
) uiIn
;
2178 /******************************************************************************
2179 * VarUI1FromUI4 [OLEAUT32.239]
2181 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
2183 TRACE("( %ld, %p ), stub\n", ulIn
, pbOut
);
2185 /* Check range of value.
2187 if( ulIn
> UI1_MAX
)
2189 return DISP_E_OVERFLOW
;
2192 *pbOut
= (BYTE
) ulIn
;
2198 /******************************************************************************
2199 * VarUI1FromStr [OLEAUT32.54]
2201 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
2203 double dValue
= 0.0;
2204 LPSTR pNewString
= NULL
;
2206 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pbOut
);
2208 /* Check if we have a valid argument
2210 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2211 RemoveCharacterFromString( pNewString
, "," );
2212 if( IsValidRealString( pNewString
) == FALSE
)
2214 return DISP_E_TYPEMISMATCH
;
2217 /* Convert the valid string to a floating point number.
2219 dValue
= atof( pNewString
);
2221 /* We don't need the string anymore so free it.
2223 HeapFree( GetProcessHeap(), 0 , pNewString
);
2225 /* Check range of value.
2227 dValue
= round( dValue
);
2228 if( dValue
< UI1_MIN
|| dValue
> UI1_MAX
)
2230 return DISP_E_OVERFLOW
;
2233 *pbOut
= (BYTE
) dValue
;
2238 /**********************************************************************
2239 * VarUI1FromCy [OLEAUT32.134]
2240 * Convert currency to unsigned char
2242 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
) {
2243 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2245 if (t
> UI1_MAX
|| t
< UI1_MIN
) return DISP_E_OVERFLOW
;
2251 /******************************************************************************
2252 * VarI2FromUI1 [OLEAUT32.48]
2254 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, short* psOut
)
2256 TRACE("( 0x%08x, %p ), stub\n", bIn
, psOut
);
2258 *psOut
= (short) bIn
;
2263 /******************************************************************************
2264 * VarI2FromI4 [OLEAUT32.49]
2266 HRESULT WINAPI
VarI2FromI4(LONG lIn
, short* psOut
)
2268 TRACE("( %lx, %p ), stub\n", lIn
, psOut
);
2270 /* Check range of value.
2272 if( lIn
< I2_MIN
|| lIn
> I2_MAX
)
2274 return DISP_E_OVERFLOW
;
2277 *psOut
= (short) lIn
;
2282 /******************************************************************************
2283 * VarI2FromR4 [OLEAUT32.50]
2285 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, short* psOut
)
2287 TRACE("( %f, %p ), stub\n", fltIn
, psOut
);
2289 /* Check range of value.
2291 fltIn
= round( fltIn
);
2292 if( fltIn
< I2_MIN
|| fltIn
> I2_MAX
)
2294 return DISP_E_OVERFLOW
;
2297 *psOut
= (short) fltIn
;
2302 /******************************************************************************
2303 * VarI2FromR8 [OLEAUT32.51]
2305 HRESULT WINAPI
VarI2FromR8(double dblIn
, short* psOut
)
2307 TRACE("( %f, %p ), stub\n", dblIn
, psOut
);
2309 /* Check range of value.
2311 dblIn
= round( dblIn
);
2312 if( dblIn
< I2_MIN
|| dblIn
> I2_MAX
)
2314 return DISP_E_OVERFLOW
;
2317 *psOut
= (short) dblIn
;
2322 /******************************************************************************
2323 * VarI2FromDate [OLEAUT32.53]
2325 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, short* psOut
)
2327 TRACE("( %f, %p ), stub\n", dateIn
, psOut
);
2329 /* Check range of value.
2331 dateIn
= round( dateIn
);
2332 if( dateIn
< I2_MIN
|| dateIn
> I2_MAX
)
2334 return DISP_E_OVERFLOW
;
2337 *psOut
= (short) dateIn
;
2342 /******************************************************************************
2343 * VarI2FromBool [OLEAUT32.56]
2345 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, short* psOut
)
2347 TRACE("( %d, %p ), stub\n", boolIn
, psOut
);
2349 *psOut
= (short) boolIn
;
2354 /******************************************************************************
2355 * VarI2FromI1 [OLEAUT32.48]
2357 HRESULT WINAPI
VarI2FromI1(CHAR cIn
, short* psOut
)
2359 TRACE("( %c, %p ), stub\n", cIn
, psOut
);
2361 *psOut
= (short) cIn
;
2366 /******************************************************************************
2367 * VarI2FromUI2 [OLEAUT32.206]
2369 HRESULT WINAPI
VarI2FromUI2(USHORT uiIn
, short* psOut
)
2371 TRACE("( %d, %p ), stub\n", uiIn
, psOut
);
2373 /* Check range of value.
2377 return DISP_E_OVERFLOW
;
2380 *psOut
= (short) uiIn
;
2385 /******************************************************************************
2386 * VarI2FromUI4 [OLEAUT32.49]
2388 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, short* psOut
)
2390 TRACE("( %lx, %p ), stub\n", ulIn
, psOut
);
2392 /* Check range of value.
2394 if( ulIn
< I2_MIN
|| ulIn
> I2_MAX
)
2396 return DISP_E_OVERFLOW
;
2399 *psOut
= (short) ulIn
;
2404 /******************************************************************************
2405 * VarI2FromStr [OLEAUT32.54]
2407 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, short* psOut
)
2409 double dValue
= 0.0;
2410 LPSTR pNewString
= NULL
;
2412 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, psOut
);
2414 /* Check if we have a valid argument
2416 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2417 RemoveCharacterFromString( pNewString
, "," );
2418 if( IsValidRealString( pNewString
) == FALSE
)
2420 return DISP_E_TYPEMISMATCH
;
2423 /* Convert the valid string to a floating point number.
2425 dValue
= atof( pNewString
);
2427 /* We don't need the string anymore so free it.
2429 HeapFree( GetProcessHeap(), 0, pNewString
);
2431 /* Check range of value.
2433 dValue
= round( dValue
);
2434 if( dValue
< I2_MIN
|| dValue
> I2_MAX
)
2436 return DISP_E_OVERFLOW
;
2439 *psOut
= (short) dValue
;
2444 /**********************************************************************
2445 * VarI2FromCy [OLEAUT32.52]
2446 * Convert currency to signed short
2448 HRESULT WINAPI
VarI2FromCy(CY cyIn
, short* psOut
) {
2449 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2451 if (t
> I2_MAX
|| t
< I2_MIN
) return DISP_E_OVERFLOW
;
2457 /******************************************************************************
2458 * VarI4FromUI1 [OLEAUT32.58]
2460 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
* plOut
)
2462 TRACE("( %X, %p ), stub\n", bIn
, plOut
);
2464 *plOut
= (LONG
) bIn
;
2470 /******************************************************************************
2471 * VarI4FromR4 [OLEAUT32.60]
2473 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
* plOut
)
2475 TRACE("( %f, %p ), stub\n", fltIn
, plOut
);
2477 /* Check range of value.
2479 fltIn
= round( fltIn
);
2480 if( fltIn
< I4_MIN
|| fltIn
> I4_MAX
)
2482 return DISP_E_OVERFLOW
;
2485 *plOut
= (LONG
) fltIn
;
2490 /******************************************************************************
2491 * VarI4FromR8 [OLEAUT32.61]
2493 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
* plOut
)
2495 TRACE("( %f, %p ), stub\n", dblIn
, plOut
);
2497 /* Check range of value.
2499 dblIn
= round( dblIn
);
2500 if( dblIn
< I4_MIN
|| dblIn
> I4_MAX
)
2502 return DISP_E_OVERFLOW
;
2505 *plOut
= (LONG
) dblIn
;
2510 /******************************************************************************
2511 * VarI4FromDate [OLEAUT32.63]
2513 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
* plOut
)
2515 TRACE("( %f, %p ), stub\n", dateIn
, plOut
);
2517 /* Check range of value.
2519 dateIn
= round( dateIn
);
2520 if( dateIn
< I4_MIN
|| dateIn
> I4_MAX
)
2522 return DISP_E_OVERFLOW
;
2525 *plOut
= (LONG
) dateIn
;
2530 /******************************************************************************
2531 * VarI4FromBool [OLEAUT32.66]
2533 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
* plOut
)
2535 TRACE("( %d, %p ), stub\n", boolIn
, plOut
);
2537 *plOut
= (LONG
) boolIn
;
2542 /******************************************************************************
2543 * VarI4FromI1 [OLEAUT32.209]
2545 HRESULT WINAPI
VarI4FromI1(CHAR cIn
, LONG
* plOut
)
2547 TRACE("( %c, %p ), stub\n", cIn
, plOut
);
2549 *plOut
= (LONG
) cIn
;
2554 /******************************************************************************
2555 * VarI4FromUI2 [OLEAUT32.210]
2557 HRESULT WINAPI
VarI4FromUI2(USHORT uiIn
, LONG
* plOut
)
2559 TRACE("( %d, %p ), stub\n", uiIn
, plOut
);
2561 *plOut
= (LONG
) uiIn
;
2566 /******************************************************************************
2567 * VarI4FromUI4 [OLEAUT32.211]
2569 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
* plOut
)
2571 TRACE("( %lx, %p ), stub\n", ulIn
, plOut
);
2573 /* Check range of value.
2575 if( ulIn
< I4_MIN
|| ulIn
> I4_MAX
)
2577 return DISP_E_OVERFLOW
;
2580 *plOut
= (LONG
) ulIn
;
2585 /******************************************************************************
2586 * VarI4FromI2 [OLEAUT32.59]
2588 HRESULT WINAPI
VarI4FromI2(short sIn
, LONG
* plOut
)
2590 TRACE("( %d, %p ), stub\n", sIn
, plOut
);
2592 *plOut
= (LONG
) sIn
;
2597 /******************************************************************************
2598 * VarI4FromStr [OLEAUT32.64]
2600 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
* plOut
)
2602 double dValue
= 0.0;
2603 LPSTR pNewString
= NULL
;
2605 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, plOut
);
2607 /* Check if we have a valid argument
2609 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2610 RemoveCharacterFromString( pNewString
, "," );
2611 if( IsValidRealString( pNewString
) == FALSE
)
2613 return DISP_E_TYPEMISMATCH
;
2616 /* Convert the valid string to a floating point number.
2618 dValue
= atof( pNewString
);
2620 /* We don't need the string anymore so free it.
2622 HeapFree( GetProcessHeap(), 0, pNewString
);
2624 /* Check range of value.
2626 dValue
= round( dValue
);
2627 if( dValue
< I4_MIN
|| dValue
> I4_MAX
)
2629 return DISP_E_OVERFLOW
;
2632 *plOut
= (LONG
) dValue
;
2637 /**********************************************************************
2638 * VarI4FromCy [OLEAUT32.62]
2639 * Convert currency to signed long
2641 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
* plOut
) {
2642 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2644 if (t
> I4_MAX
|| t
< I4_MIN
) return DISP_E_OVERFLOW
;
2650 /******************************************************************************
2651 * VarR4FromUI1 [OLEAUT32.68]
2653 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, FLOAT
* pfltOut
)
2655 TRACE("( %X, %p ), stub\n", bIn
, pfltOut
);
2657 *pfltOut
= (FLOAT
) bIn
;
2662 /******************************************************************************
2663 * VarR4FromI2 [OLEAUT32.69]
2665 HRESULT WINAPI
VarR4FromI2(short sIn
, FLOAT
* pfltOut
)
2667 TRACE("( %d, %p ), stub\n", sIn
, pfltOut
);
2669 *pfltOut
= (FLOAT
) sIn
;
2674 /******************************************************************************
2675 * VarR4FromI4 [OLEAUT32.70]
2677 HRESULT WINAPI
VarR4FromI4(LONG lIn
, FLOAT
* pfltOut
)
2679 TRACE("( %lx, %p ), stub\n", lIn
, pfltOut
);
2681 *pfltOut
= (FLOAT
) lIn
;
2686 /******************************************************************************
2687 * VarR4FromR8 [OLEAUT32.71]
2689 HRESULT WINAPI
VarR4FromR8(double dblIn
, FLOAT
* pfltOut
)
2691 TRACE("( %f, %p ), stub\n", dblIn
, pfltOut
);
2693 /* Check range of value.
2695 if( dblIn
< -(FLT_MAX
) || dblIn
> FLT_MAX
)
2697 return DISP_E_OVERFLOW
;
2700 *pfltOut
= (FLOAT
) dblIn
;
2705 /******************************************************************************
2706 * VarR4FromDate [OLEAUT32.73]
2708 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, FLOAT
* pfltOut
)
2710 TRACE("( %f, %p ), stub\n", dateIn
, pfltOut
);
2712 /* Check range of value.
2714 if( dateIn
< -(FLT_MAX
) || dateIn
> FLT_MAX
)
2716 return DISP_E_OVERFLOW
;
2719 *pfltOut
= (FLOAT
) dateIn
;
2724 /******************************************************************************
2725 * VarR4FromBool [OLEAUT32.76]
2727 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, FLOAT
* pfltOut
)
2729 TRACE("( %d, %p ), stub\n", boolIn
, pfltOut
);
2731 *pfltOut
= (FLOAT
) boolIn
;
2736 /******************************************************************************
2737 * VarR4FromI1 [OLEAUT32.213]
2739 HRESULT WINAPI
VarR4FromI1(CHAR cIn
, FLOAT
* pfltOut
)
2741 TRACE("( %c, %p ), stub\n", cIn
, pfltOut
);
2743 *pfltOut
= (FLOAT
) cIn
;
2748 /******************************************************************************
2749 * VarR4FromUI2 [OLEAUT32.214]
2751 HRESULT WINAPI
VarR4FromUI2(USHORT uiIn
, FLOAT
* pfltOut
)
2753 TRACE("( %d, %p ), stub\n", uiIn
, pfltOut
);
2755 *pfltOut
= (FLOAT
) uiIn
;
2760 /******************************************************************************
2761 * VarR4FromUI4 [OLEAUT32.215]
2763 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, FLOAT
* pfltOut
)
2765 TRACE("( %ld, %p ), stub\n", ulIn
, pfltOut
);
2767 *pfltOut
= (FLOAT
) ulIn
;
2772 /******************************************************************************
2773 * VarR4FromStr [OLEAUT32.74]
2775 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, FLOAT
* pfltOut
)
2777 double dValue
= 0.0;
2778 LPSTR pNewString
= NULL
;
2780 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pfltOut
);
2782 /* Check if we have a valid argument
2784 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2785 RemoveCharacterFromString( pNewString
, "," );
2786 if( IsValidRealString( pNewString
) == FALSE
)
2788 return DISP_E_TYPEMISMATCH
;
2791 /* Convert the valid string to a floating point number.
2793 dValue
= atof( pNewString
);
2795 /* We don't need the string anymore so free it.
2797 HeapFree( GetProcessHeap(), 0, pNewString
);
2799 /* Check range of value.
2801 if( dValue
< -(FLT_MAX
) || dValue
> FLT_MAX
)
2803 return DISP_E_OVERFLOW
;
2806 *pfltOut
= (FLOAT
) dValue
;
2811 /**********************************************************************
2812 * VarR4FromCy [OLEAUT32.72]
2813 * Convert currency to float
2815 HRESULT WINAPI
VarR4FromCy(CY cyIn
, FLOAT
* pfltOut
) {
2816 *pfltOut
= (FLOAT
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2821 /******************************************************************************
2822 * VarR8FromUI1 [OLEAUT32.68]
2824 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double* pdblOut
)
2826 TRACE("( %d, %p ), stub\n", bIn
, pdblOut
);
2828 *pdblOut
= (double) bIn
;
2833 /******************************************************************************
2834 * VarR8FromI2 [OLEAUT32.69]
2836 HRESULT WINAPI
VarR8FromI2(short sIn
, double* pdblOut
)
2838 TRACE("( %d, %p ), stub\n", sIn
, pdblOut
);
2840 *pdblOut
= (double) sIn
;
2845 /******************************************************************************
2846 * VarR8FromI4 [OLEAUT32.70]
2848 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double* pdblOut
)
2850 TRACE("( %ld, %p ), stub\n", lIn
, pdblOut
);
2852 *pdblOut
= (double) lIn
;
2857 /******************************************************************************
2858 * VarR8FromR4 [OLEAUT32.81]
2860 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double* pdblOut
)
2862 TRACE("( %f, %p ), stub\n", fltIn
, pdblOut
);
2864 *pdblOut
= (double) fltIn
;
2869 /******************************************************************************
2870 * VarR8FromDate [OLEAUT32.83]
2872 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double* pdblOut
)
2874 TRACE("( %f, %p ), stub\n", dateIn
, pdblOut
);
2876 *pdblOut
= (double) dateIn
;
2881 /******************************************************************************
2882 * VarR8FromBool [OLEAUT32.86]
2884 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double* pdblOut
)
2886 TRACE("( %d, %p ), stub\n", boolIn
, pdblOut
);
2888 *pdblOut
= (double) boolIn
;
2893 /******************************************************************************
2894 * VarR8FromI1 [OLEAUT32.217]
2896 HRESULT WINAPI
VarR8FromI1(CHAR cIn
, double* pdblOut
)
2898 TRACE("( %c, %p ), stub\n", cIn
, pdblOut
);
2900 *pdblOut
= (double) cIn
;
2905 /******************************************************************************
2906 * VarR8FromUI2 [OLEAUT32.218]
2908 HRESULT WINAPI
VarR8FromUI2(USHORT uiIn
, double* pdblOut
)
2910 TRACE("( %d, %p ), stub\n", uiIn
, pdblOut
);
2912 *pdblOut
= (double) uiIn
;
2917 /******************************************************************************
2918 * VarR8FromUI4 [OLEAUT32.219]
2920 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double* pdblOut
)
2922 TRACE("( %ld, %p ), stub\n", ulIn
, pdblOut
);
2924 *pdblOut
= (double) ulIn
;
2929 /******************************************************************************
2930 * VarR8FromStr [OLEAUT32.84]
2932 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double* pdblOut
)
2934 double dValue
= 0.0;
2935 LPSTR pNewString
= NULL
;
2937 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pdblOut
);
2939 /* Check if we have a valid argument
2941 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2942 RemoveCharacterFromString( pNewString
, "," );
2943 if( IsValidRealString( pNewString
) == FALSE
)
2945 return DISP_E_TYPEMISMATCH
;
2948 /* Convert the valid string to a floating point number.
2950 dValue
= atof( pNewString
);
2952 /* We don't need the string anymore so free it.
2954 HeapFree( GetProcessHeap(), 0, pNewString
);
2961 /**********************************************************************
2962 * VarR8FromCy [OLEAUT32.82]
2963 * Convert currency to double
2965 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double* pdblOut
) {
2966 *pdblOut
= (double)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2971 /******************************************************************************
2972 * VarDateFromUI1 [OLEAUT32.]
2974 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
2976 TRACE("( %d, %p ), stub\n", bIn
, pdateOut
);
2978 *pdateOut
= (DATE
) bIn
;
2983 /******************************************************************************
2984 * VarDateFromI2 [OLEAUT32.222]
2986 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
2988 TRACE("( %d, %p ), stub\n", sIn
, pdateOut
);
2990 *pdateOut
= (DATE
) sIn
;
2995 /******************************************************************************
2996 * VarDateFromI4 [OLEAUT32.90]
2998 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
3000 TRACE("( %ld, %p ), stub\n", lIn
, pdateOut
);
3002 if( lIn
< DATE_MIN
|| lIn
> DATE_MAX
)
3004 return DISP_E_OVERFLOW
;
3007 *pdateOut
= (DATE
) lIn
;
3012 /******************************************************************************
3013 * VarDateFromR4 [OLEAUT32.91]
3015 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
3017 TRACE("( %f, %p ), stub\n", fltIn
, pdateOut
);
3019 if( ceil(fltIn
) < DATE_MIN
|| floor(fltIn
) > DATE_MAX
)
3021 return DISP_E_OVERFLOW
;
3024 *pdateOut
= (DATE
) fltIn
;
3029 /******************************************************************************
3030 * VarDateFromR8 [OLEAUT32.92]
3032 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
3034 TRACE("( %f, %p ), stub\n", dblIn
, pdateOut
);
3036 if( ceil(dblIn
) < DATE_MIN
|| floor(dblIn
) > DATE_MAX
)
3038 return DISP_E_OVERFLOW
;
3041 *pdateOut
= (DATE
) dblIn
;
3046 /******************************************************************************
3047 * VarDateFromStr [OLEAUT32.94]
3048 * The string representing the date is composed of two parts, a date and time.
3050 * The format of the time is has follows:
3051 * hh[:mm][:ss][AM|PM]
3052 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3053 * of space and/or tab characters, which are ignored.
3055 * The formats for the date part are has follows:
3059 * January dd[,] [yy]yy
3062 * Whitespace can be inserted anywhere between these tokens.
3064 * The formats for the date and time string are has follows.
3065 * date[whitespace][time]
3066 * [time][whitespace]date
3068 * These are the only characters allowed in a string representing a date and time:
3069 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3071 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
3074 struct tm TM
= { 0,0,0,0,0,0,0,0,0 };
3076 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pdateOut
);
3078 if( DateTimeStringToTm( strIn
, lcid
, &TM
) )
3080 if( TmToDATE( &TM
, pdateOut
) == FALSE
)
3087 ret
= DISP_E_TYPEMISMATCH
;
3094 /******************************************************************************
3095 * VarDateFromI1 [OLEAUT32.221]
3097 HRESULT WINAPI
VarDateFromI1(CHAR cIn
, DATE
* pdateOut
)
3099 TRACE("( %c, %p ), stub\n", cIn
, pdateOut
);
3101 *pdateOut
= (DATE
) cIn
;
3106 /******************************************************************************
3107 * VarDateFromUI2 [OLEAUT32.222]
3109 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
3111 TRACE("( %d, %p ), stub\n", uiIn
, pdateOut
);
3113 if( uiIn
> DATE_MAX
)
3115 return DISP_E_OVERFLOW
;
3118 *pdateOut
= (DATE
) uiIn
;
3123 /******************************************************************************
3124 * VarDateFromUI4 [OLEAUT32.223]
3126 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
3128 TRACE("( %ld, %p ), stub\n", ulIn
, pdateOut
);
3130 if( ulIn
< DATE_MIN
|| ulIn
> DATE_MAX
)
3132 return DISP_E_OVERFLOW
;
3135 *pdateOut
= (DATE
) ulIn
;
3140 /******************************************************************************
3141 * VarDateFromBool [OLEAUT32.96]
3143 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
3145 TRACE("( %d, %p ), stub\n", boolIn
, pdateOut
);
3147 *pdateOut
= (DATE
) boolIn
;
3152 /**********************************************************************
3153 * VarDateFromCy [OLEAUT32.93]
3154 * Convert currency to date
3156 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
) {
3157 *pdateOut
= (DATE
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3159 if (*pdateOut
> DATE_MAX
|| *pdateOut
< DATE_MIN
) return DISP_E_TYPEMISMATCH
;
3163 /******************************************************************************
3164 * VarBstrFromUI1 [OLEAUT32.108]
3166 HRESULT WINAPI
VarBstrFromUI1(BYTE bVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3168 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal
, lcid
, dwFlags
, pbstrOut
);
3169 sprintf( pBuffer
, "%d", bVal
);
3171 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3176 /******************************************************************************
3177 * VarBstrFromI2 [OLEAUT32.109]
3179 HRESULT WINAPI
VarBstrFromI2(short iVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3181 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal
, lcid
, dwFlags
, pbstrOut
);
3182 sprintf( pBuffer
, "%d", iVal
);
3183 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3188 /******************************************************************************
3189 * VarBstrFromI4 [OLEAUT32.110]
3191 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3193 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn
, lcid
, dwFlags
, pbstrOut
);
3195 sprintf( pBuffer
, "%ld", lIn
);
3196 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3201 /******************************************************************************
3202 * VarBstrFromR4 [OLEAUT32.111]
3204 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3206 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn
, lcid
, dwFlags
, pbstrOut
);
3208 sprintf( pBuffer
, "%.7g", fltIn
);
3209 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3214 /******************************************************************************
3215 * VarBstrFromR8 [OLEAUT32.112]
3217 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3219 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn
, lcid
, dwFlags
, pbstrOut
);
3221 sprintf( pBuffer
, "%.15g", dblIn
);
3222 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3227 /******************************************************************************
3228 * VarBstrFromCy [OLEAUT32.113]
3230 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
) {
3236 /******************************************************************************
3237 * VarBstrFromDate [OLEAUT32.114]
3239 * The date is implemented using an 8 byte floating-point number.
3240 * Days are represented by whole numbers increments starting with 0.00 has
3241 * being December 30 1899, midnight.
3242 * The hours are expressed as the fractional part of the number.
3243 * December 30 1899 at midnight = 0.00
3244 * January 1 1900 at midnight = 2.00
3245 * January 4 1900 at 6 AM = 5.25
3246 * January 4 1900 at noon = 5.50
3247 * December 29 1899 at midnight = -1.00
3248 * December 18 1899 at midnight = -12.00
3249 * December 18 1899 at 6AM = -12.25
3250 * December 18 1899 at 6PM = -12.75
3251 * December 19 1899 at midnight = -11.00
3252 * The tm structure is as follows:
3254 * int tm_sec; seconds after the minute - [0,59]
3255 * int tm_min; minutes after the hour - [0,59]
3256 * int tm_hour; hours since midnight - [0,23]
3257 * int tm_mday; day of the month - [1,31]
3258 * int tm_mon; months since January - [0,11]
3259 * int tm_year; years
3260 * int tm_wday; days since Sunday - [0,6]
3261 * int tm_yday; days since January 1 - [0,365]
3262 * int tm_isdst; daylight savings time flag
3265 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3267 struct tm TM
= {0,0,0,0,0,0,0,0,0};
3269 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
3271 if( DateToTm( dateIn
, lcid
, &TM
) == FALSE
)
3273 return E_INVALIDARG
;
3276 if( dwFlags
& VAR_DATEVALUEONLY
)
3277 strftime( pBuffer
, BUFFER_MAX
, "%x", &TM
);
3278 else if( dwFlags
& VAR_TIMEVALUEONLY
)
3279 strftime( pBuffer
, BUFFER_MAX
, "%X", &TM
);
3281 strftime( pBuffer
, BUFFER_MAX
, "%x %X", &TM
);
3283 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3288 /******************************************************************************
3289 * VarBstrFromBool [OLEAUT32.116]
3291 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3293 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
3295 if( boolIn
== VARIANT_FALSE
)
3297 sprintf( pBuffer
, "False" );
3301 sprintf( pBuffer
, "True" );
3304 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3309 /******************************************************************************
3310 * VarBstrFromI1 [OLEAUT32.229]
3312 HRESULT WINAPI
VarBstrFromI1(CHAR cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3314 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn
, lcid
, dwFlags
, pbstrOut
);
3315 sprintf( pBuffer
, "%d", cIn
);
3316 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3321 /******************************************************************************
3322 * VarBstrFromUI2 [OLEAUT32.230]
3324 HRESULT WINAPI
VarBstrFromUI2(USHORT uiIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3326 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn
, lcid
, dwFlags
, pbstrOut
);
3327 sprintf( pBuffer
, "%d", uiIn
);
3328 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3333 /******************************************************************************
3334 * VarBstrFromUI4 [OLEAUT32.231]
3336 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3338 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn
, lcid
, dwFlags
, pbstrOut
);
3339 sprintf( pBuffer
, "%ld", ulIn
);
3340 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3345 /******************************************************************************
3346 * VarBoolFromUI1 [OLEAUT32.118]
3348 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
* pboolOut
)
3350 TRACE("( %d, %p ), stub\n", bIn
, pboolOut
);
3354 *pboolOut
= VARIANT_FALSE
;
3358 *pboolOut
= VARIANT_TRUE
;
3364 /******************************************************************************
3365 * VarBoolFromI2 [OLEAUT32.119]
3367 HRESULT WINAPI
VarBoolFromI2(short sIn
, VARIANT_BOOL
* pboolOut
)
3369 TRACE("( %d, %p ), stub\n", sIn
, pboolOut
);
3373 *pboolOut
= VARIANT_FALSE
;
3377 *pboolOut
= VARIANT_TRUE
;
3383 /******************************************************************************
3384 * VarBoolFromI4 [OLEAUT32.120]
3386 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
* pboolOut
)
3388 TRACE("( %ld, %p ), stub\n", lIn
, pboolOut
);
3392 *pboolOut
= VARIANT_FALSE
;
3396 *pboolOut
= VARIANT_TRUE
;
3402 /******************************************************************************
3403 * VarBoolFromR4 [OLEAUT32.121]
3405 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
* pboolOut
)
3407 TRACE("( %f, %p ), stub\n", fltIn
, pboolOut
);
3411 *pboolOut
= VARIANT_FALSE
;
3415 *pboolOut
= VARIANT_TRUE
;
3421 /******************************************************************************
3422 * VarBoolFromR8 [OLEAUT32.122]
3424 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
* pboolOut
)
3426 TRACE("( %f, %p ), stub\n", dblIn
, pboolOut
);
3430 *pboolOut
= VARIANT_FALSE
;
3434 *pboolOut
= VARIANT_TRUE
;
3440 /******************************************************************************
3441 * VarBoolFromDate [OLEAUT32.123]
3443 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
* pboolOut
)
3445 TRACE("( %f, %p ), stub\n", dateIn
, pboolOut
);
3449 *pboolOut
= VARIANT_FALSE
;
3453 *pboolOut
= VARIANT_TRUE
;
3459 /******************************************************************************
3460 * VarBoolFromStr [OLEAUT32.125]
3462 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
* pboolOut
)
3465 char* pNewString
= NULL
;
3467 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pboolOut
);
3469 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3471 if( pNewString
== NULL
|| strlen( pNewString
) == 0 )
3473 ret
= DISP_E_TYPEMISMATCH
;
3478 if( strncasecmp( pNewString
, "True", strlen( pNewString
) ) == 0 )
3480 *pboolOut
= VARIANT_TRUE
;
3482 else if( strncasecmp( pNewString
, "False", strlen( pNewString
) ) == 0 )
3484 *pboolOut
= VARIANT_FALSE
;
3488 /* Try converting the string to a floating point number.
3490 double dValue
= 0.0;
3491 HRESULT res
= VarR8FromStr( strIn
, lcid
, dwFlags
, &dValue
);
3494 ret
= DISP_E_TYPEMISMATCH
;
3496 else if( dValue
== 0.0 )
3498 *pboolOut
= VARIANT_FALSE
;
3502 *pboolOut
= VARIANT_TRUE
;
3507 HeapFree( GetProcessHeap(), 0, pNewString
);
3512 /******************************************************************************
3513 * VarBoolFromI1 [OLEAUT32.233]
3515 HRESULT WINAPI
VarBoolFromI1(CHAR cIn
, VARIANT_BOOL
* pboolOut
)
3517 TRACE("( %c, %p ), stub\n", cIn
, pboolOut
);
3521 *pboolOut
= VARIANT_FALSE
;
3525 *pboolOut
= VARIANT_TRUE
;
3531 /******************************************************************************
3532 * VarBoolFromUI2 [OLEAUT32.234]
3534 HRESULT WINAPI
VarBoolFromUI2(USHORT uiIn
, VARIANT_BOOL
* pboolOut
)
3536 TRACE("( %d, %p ), stub\n", uiIn
, pboolOut
);
3540 *pboolOut
= VARIANT_FALSE
;
3544 *pboolOut
= VARIANT_TRUE
;
3550 /******************************************************************************
3551 * VarBoolFromUI4 [OLEAUT32.235]
3553 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
* pboolOut
)
3555 TRACE("( %ld, %p ), stub\n", ulIn
, pboolOut
);
3559 *pboolOut
= VARIANT_FALSE
;
3563 *pboolOut
= VARIANT_TRUE
;
3569 /**********************************************************************
3570 * VarBoolFromCy [OLEAUT32.124]
3571 * Convert currency to boolean
3573 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
* pboolOut
) {
3574 if (cyIn
.s
.Hi
|| cyIn
.s
.Lo
) *pboolOut
= -1;
3580 /******************************************************************************
3581 * VarI1FromUI1 [OLEAUT32.244]
3583 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, CHAR
* pcOut
)
3585 TRACE("( %d, %p ), stub\n", bIn
, pcOut
);
3587 /* Check range of value.
3589 if( bIn
> CHAR_MAX
)
3591 return DISP_E_OVERFLOW
;
3594 *pcOut
= (CHAR
) bIn
;
3599 /******************************************************************************
3600 * VarI1FromI2 [OLEAUT32.245]
3602 HRESULT WINAPI
VarI1FromI2(short uiIn
, CHAR
* pcOut
)
3604 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3606 if( uiIn
> CHAR_MAX
)
3608 return DISP_E_OVERFLOW
;
3611 *pcOut
= (CHAR
) uiIn
;
3616 /******************************************************************************
3617 * VarI1FromI4 [OLEAUT32.246]
3619 HRESULT WINAPI
VarI1FromI4(LONG lIn
, CHAR
* pcOut
)
3621 TRACE("( %ld, %p ), stub\n", lIn
, pcOut
);
3623 if( lIn
< CHAR_MIN
|| lIn
> CHAR_MAX
)
3625 return DISP_E_OVERFLOW
;
3628 *pcOut
= (CHAR
) lIn
;
3633 /******************************************************************************
3634 * VarI1FromR4 [OLEAUT32.247]
3636 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, CHAR
* pcOut
)
3638 TRACE("( %f, %p ), stub\n", fltIn
, pcOut
);
3640 fltIn
= round( fltIn
);
3641 if( fltIn
< CHAR_MIN
|| fltIn
> CHAR_MAX
)
3643 return DISP_E_OVERFLOW
;
3646 *pcOut
= (CHAR
) fltIn
;
3651 /******************************************************************************
3652 * VarI1FromR8 [OLEAUT32.248]
3654 HRESULT WINAPI
VarI1FromR8(double dblIn
, CHAR
* pcOut
)
3656 TRACE("( %f, %p ), stub\n", dblIn
, pcOut
);
3658 dblIn
= round( dblIn
);
3659 if( dblIn
< CHAR_MIN
|| dblIn
> CHAR_MAX
)
3661 return DISP_E_OVERFLOW
;
3664 *pcOut
= (CHAR
) dblIn
;
3669 /******************************************************************************
3670 * VarI1FromDate [OLEAUT32.249]
3672 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, CHAR
* pcOut
)
3674 TRACE("( %f, %p ), stub\n", dateIn
, pcOut
);
3676 dateIn
= round( dateIn
);
3677 if( dateIn
< CHAR_MIN
|| dateIn
> CHAR_MAX
)
3679 return DISP_E_OVERFLOW
;
3682 *pcOut
= (CHAR
) dateIn
;
3687 /******************************************************************************
3688 * VarI1FromStr [OLEAUT32.251]
3690 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CHAR
* pcOut
)
3692 double dValue
= 0.0;
3693 LPSTR pNewString
= NULL
;
3695 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pcOut
);
3697 /* Check if we have a valid argument
3699 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3700 RemoveCharacterFromString( pNewString
, "," );
3701 if( IsValidRealString( pNewString
) == FALSE
)
3703 return DISP_E_TYPEMISMATCH
;
3706 /* Convert the valid string to a floating point number.
3708 dValue
= atof( pNewString
);
3710 /* We don't need the string anymore so free it.
3712 HeapFree( GetProcessHeap(), 0, pNewString
);
3714 /* Check range of value.
3716 dValue
= round( dValue
);
3717 if( dValue
< CHAR_MIN
|| dValue
> CHAR_MAX
)
3719 return DISP_E_OVERFLOW
;
3722 *pcOut
= (CHAR
) dValue
;
3727 /******************************************************************************
3728 * VarI1FromBool [OLEAUT32.253]
3730 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, CHAR
* pcOut
)
3732 TRACE("( %d, %p ), stub\n", boolIn
, pcOut
);
3734 *pcOut
= (CHAR
) boolIn
;
3739 /******************************************************************************
3740 * VarI1FromUI2 [OLEAUT32.254]
3742 HRESULT WINAPI
VarI1FromUI2(USHORT uiIn
, CHAR
* pcOut
)
3744 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3746 if( uiIn
> CHAR_MAX
)
3748 return DISP_E_OVERFLOW
;
3751 *pcOut
= (CHAR
) uiIn
;
3756 /******************************************************************************
3757 * VarI1FromUI4 [OLEAUT32.255]
3759 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, CHAR
* pcOut
)
3761 TRACE("( %ld, %p ), stub\n", ulIn
, pcOut
);
3763 if( ulIn
> CHAR_MAX
)
3765 return DISP_E_OVERFLOW
;
3768 *pcOut
= (CHAR
) ulIn
;
3773 /**********************************************************************
3774 * VarI1FromCy [OLEAUT32.250]
3775 * Convert currency to signed char
3777 HRESULT WINAPI
VarI1FromCy(CY cyIn
, CHAR
* pcOut
) {
3778 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3780 if (t
> CHAR_MAX
|| t
< CHAR_MIN
) return DISP_E_OVERFLOW
;
3786 /******************************************************************************
3787 * VarUI2FromUI1 [OLEAUT32.257]
3789 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* puiOut
)
3791 TRACE("( %d, %p ), stub\n", bIn
, puiOut
);
3793 *puiOut
= (USHORT
) bIn
;
3798 /******************************************************************************
3799 * VarUI2FromI2 [OLEAUT32.258]
3801 HRESULT WINAPI
VarUI2FromI2(short uiIn
, USHORT
* puiOut
)
3803 TRACE("( %d, %p ), stub\n", uiIn
, puiOut
);
3805 if( uiIn
< UI2_MIN
)
3807 return DISP_E_OVERFLOW
;
3810 *puiOut
= (USHORT
) uiIn
;
3815 /******************************************************************************
3816 * VarUI2FromI4 [OLEAUT32.259]
3818 HRESULT WINAPI
VarUI2FromI4(LONG lIn
, USHORT
* puiOut
)
3820 TRACE("( %ld, %p ), stub\n", lIn
, puiOut
);
3822 if( lIn
< UI2_MIN
|| lIn
> UI2_MAX
)
3824 return DISP_E_OVERFLOW
;
3827 *puiOut
= (USHORT
) lIn
;
3832 /******************************************************************************
3833 * VarUI2FromR4 [OLEAUT32.260]
3835 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* puiOut
)
3837 TRACE("( %f, %p ), stub\n", fltIn
, puiOut
);
3839 fltIn
= round( fltIn
);
3840 if( fltIn
< UI2_MIN
|| fltIn
> UI2_MAX
)
3842 return DISP_E_OVERFLOW
;
3845 *puiOut
= (USHORT
) fltIn
;
3850 /******************************************************************************
3851 * VarUI2FromR8 [OLEAUT32.261]
3853 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* puiOut
)
3855 TRACE("( %f, %p ), stub\n", dblIn
, puiOut
);
3857 dblIn
= round( dblIn
);
3858 if( dblIn
< UI2_MIN
|| dblIn
> UI2_MAX
)
3860 return DISP_E_OVERFLOW
;
3863 *puiOut
= (USHORT
) dblIn
;
3868 /******************************************************************************
3869 * VarUI2FromDate [OLEAUT32.262]
3871 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* puiOut
)
3873 TRACE("( %f, %p ), stub\n", dateIn
, puiOut
);
3875 dateIn
= round( dateIn
);
3876 if( dateIn
< UI2_MIN
|| dateIn
> UI2_MAX
)
3878 return DISP_E_OVERFLOW
;
3881 *puiOut
= (USHORT
) dateIn
;
3886 /******************************************************************************
3887 * VarUI2FromStr [OLEAUT32.264]
3889 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* puiOut
)
3891 double dValue
= 0.0;
3892 LPSTR pNewString
= NULL
;
3894 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, puiOut
);
3896 /* Check if we have a valid argument
3898 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3899 RemoveCharacterFromString( pNewString
, "," );
3900 if( IsValidRealString( pNewString
) == FALSE
)
3902 return DISP_E_TYPEMISMATCH
;
3905 /* Convert the valid string to a floating point number.
3907 dValue
= atof( pNewString
);
3909 /* We don't need the string anymore so free it.
3911 HeapFree( GetProcessHeap(), 0, pNewString
);
3913 /* Check range of value.
3915 dValue
= round( dValue
);
3916 if( dValue
< UI2_MIN
|| dValue
> UI2_MAX
)
3918 return DISP_E_OVERFLOW
;
3921 *puiOut
= (USHORT
) dValue
;
3926 /******************************************************************************
3927 * VarUI2FromBool [OLEAUT32.266]
3929 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* puiOut
)
3931 TRACE("( %d, %p ), stub\n", boolIn
, puiOut
);
3933 *puiOut
= (USHORT
) boolIn
;
3938 /******************************************************************************
3939 * VarUI2FromI1 [OLEAUT32.267]
3941 HRESULT WINAPI
VarUI2FromI1(CHAR cIn
, USHORT
* puiOut
)
3943 TRACE("( %c, %p ), stub\n", cIn
, puiOut
);
3945 *puiOut
= (USHORT
) cIn
;
3950 /******************************************************************************
3951 * VarUI2FromUI4 [OLEAUT32.268]
3953 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* puiOut
)
3955 TRACE("( %ld, %p ), stub\n", ulIn
, puiOut
);
3957 if( ulIn
< UI2_MIN
|| ulIn
> UI2_MAX
)
3959 return DISP_E_OVERFLOW
;
3962 *puiOut
= (USHORT
) ulIn
;
3967 /******************************************************************************
3968 * VarUI4FromStr [OLEAUT32.277]
3970 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
* pulOut
)
3972 double dValue
= 0.0;
3973 LPSTR pNewString
= NULL
;
3975 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pulOut
);
3977 /* Check if we have a valid argument
3979 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3980 RemoveCharacterFromString( pNewString
, "," );
3981 if( IsValidRealString( pNewString
) == FALSE
)
3983 return DISP_E_TYPEMISMATCH
;
3986 /* Convert the valid string to a floating point number.
3988 dValue
= atof( pNewString
);
3990 /* We don't need the string anymore so free it.
3992 HeapFree( GetProcessHeap(), 0, pNewString
);
3994 /* Check range of value.
3996 dValue
= round( dValue
);
3997 if( dValue
< UI4_MIN
|| dValue
> UI4_MAX
)
3999 return DISP_E_OVERFLOW
;
4002 *pulOut
= (ULONG
) dValue
;
4007 /**********************************************************************
4008 * VarUI2FromCy [OLEAUT32.263]
4009 * Convert currency to unsigned short
4011 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
) {
4012 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
4014 if (t
> UI2_MAX
|| t
< UI2_MIN
) return DISP_E_OVERFLOW
;
4016 *pusOut
= (USHORT
)t
;
4021 /******************************************************************************
4022 * VarUI4FromUI1 [OLEAUT32.270]
4024 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
* pulOut
)
4026 TRACE("( %d, %p ), stub\n", bIn
, pulOut
);
4028 *pulOut
= (USHORT
) bIn
;
4033 /******************************************************************************
4034 * VarUI4FromI2 [OLEAUT32.271]
4036 HRESULT WINAPI
VarUI4FromI2(short uiIn
, ULONG
* pulOut
)
4038 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4040 if( uiIn
< UI4_MIN
)
4042 return DISP_E_OVERFLOW
;
4045 *pulOut
= (ULONG
) uiIn
;
4050 /******************************************************************************
4051 * VarUI4FromI4 [OLEAUT32.272]
4053 HRESULT WINAPI
VarUI4FromI4(LONG lIn
, ULONG
* pulOut
)
4055 TRACE("( %ld, %p ), stub\n", lIn
, pulOut
);
4059 return DISP_E_OVERFLOW
;
4062 *pulOut
= (ULONG
) lIn
;
4067 /******************************************************************************
4068 * VarUI4FromR4 [OLEAUT32.273]
4070 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
* pulOut
)
4072 fltIn
= round( fltIn
);
4073 if( fltIn
< UI4_MIN
|| fltIn
> UI4_MAX
)
4075 return DISP_E_OVERFLOW
;
4078 *pulOut
= (ULONG
) fltIn
;
4083 /******************************************************************************
4084 * VarUI4FromR8 [OLEAUT32.274]
4086 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
* pulOut
)
4088 TRACE("( %f, %p ), stub\n", dblIn
, pulOut
);
4090 dblIn
= round( dblIn
);
4091 if( dblIn
< UI4_MIN
|| dblIn
> UI4_MAX
)
4093 return DISP_E_OVERFLOW
;
4096 *pulOut
= (ULONG
) dblIn
;
4101 /******************************************************************************
4102 * VarUI4FromDate [OLEAUT32.275]
4104 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
* pulOut
)
4106 TRACE("( %f, %p ), stub\n", dateIn
, pulOut
);
4108 dateIn
= round( dateIn
);
4109 if( dateIn
< UI4_MIN
|| dateIn
> UI4_MAX
)
4111 return DISP_E_OVERFLOW
;
4114 *pulOut
= (ULONG
) dateIn
;
4119 /******************************************************************************
4120 * VarUI4FromBool [OLEAUT32.279]
4122 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
* pulOut
)
4124 TRACE("( %d, %p ), stub\n", boolIn
, pulOut
);
4126 *pulOut
= (ULONG
) boolIn
;
4131 /******************************************************************************
4132 * VarUI4FromI1 [OLEAUT32.280]
4134 HRESULT WINAPI
VarUI4FromI1(CHAR cIn
, ULONG
* pulOut
)
4136 TRACE("( %c, %p ), stub\n", cIn
, pulOut
);
4138 *pulOut
= (ULONG
) cIn
;
4143 /******************************************************************************
4144 * VarUI4FromUI2 [OLEAUT32.281]
4146 HRESULT WINAPI
VarUI4FromUI2(USHORT uiIn
, ULONG
* pulOut
)
4148 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4150 *pulOut
= (ULONG
) uiIn
;
4155 /**********************************************************************
4156 * VarUI4FromCy [OLEAUT32.276]
4157 * Convert currency to unsigned long
4159 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
* pulOut
) {
4160 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
4162 if (t
> UI4_MAX
|| t
< UI4_MIN
) return DISP_E_OVERFLOW
;
4169 /**********************************************************************
4170 * VarCyFromUI1 [OLEAUT32.98]
4171 * Convert unsigned char to currency
4173 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pcyOut
) {
4175 pcyOut
->s
.Lo
= ((ULONG
)bIn
) * 10000;
4180 /**********************************************************************
4181 * VarCyFromI2 [OLEAUT32.99]
4182 * Convert signed short to currency
4184 HRESULT WINAPI
VarCyFromI2(short sIn
, CY
* pcyOut
) {
4185 if (sIn
< 0) pcyOut
->s
.Hi
= -1;
4186 else pcyOut
->s
.Hi
= 0;
4187 pcyOut
->s
.Lo
= ((ULONG
)sIn
) * 10000;
4192 /**********************************************************************
4193 * VarCyFromI4 [OLEAUT32.100]
4194 * Convert signed long to currency
4196 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pcyOut
) {
4197 double t
= (double)lIn
* (double)10000;
4198 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4199 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4200 if (lIn
< 0) pcyOut
->s
.Hi
--;
4205 /**********************************************************************
4206 * VarCyFromR4 [OLEAUT32.101]
4207 * Convert float to currency
4209 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pcyOut
) {
4210 double t
= round((double)fltIn
* (double)10000);
4211 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4212 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4213 if (fltIn
< 0) pcyOut
->s
.Hi
--;
4218 /**********************************************************************
4219 * VarCyFromR8 [OLEAUT32.102]
4220 * Convert double to currency
4222 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pcyOut
) {
4223 double t
= round(dblIn
* (double)10000);
4224 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4225 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4226 if (dblIn
< 0) pcyOut
->s
.Hi
--;
4231 /**********************************************************************
4232 * VarCyFromDate [OLEAUT32.103]
4233 * Convert date to currency
4235 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pcyOut
) {
4236 double t
= round((double)dateIn
* (double)10000);
4237 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4238 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4239 if (dateIn
< 0) pcyOut
->s
.Hi
--;
4244 /**********************************************************************
4245 * VarCyFromStr [OLEAUT32.104]
4247 HRESULT WINAPI
VarCyFromStr(OLECHAR
*strIn
, LCID lcid
, ULONG dwFlags
, CY
*pcyOut
) {
4253 /**********************************************************************
4254 * VarCyFromBool [OLEAUT32.106]
4255 * Convert boolean to currency
4257 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pcyOut
) {
4258 if (boolIn
< 0) pcyOut
->s
.Hi
= -1;
4259 else pcyOut
->s
.Hi
= 0;
4260 pcyOut
->s
.Lo
= (ULONG
)boolIn
* (ULONG
)10000;
4265 /**********************************************************************
4266 * VarCyFromI1 [OLEAUT32.225]
4267 * Convert signed char to currency
4269 HRESULT WINAPI
VarCyFromI1(CHAR cIn
, CY
* pcyOut
) {
4270 if (cIn
< 0) pcyOut
->s
.Hi
= -1;
4271 else pcyOut
->s
.Hi
= 0;
4272 pcyOut
->s
.Lo
= (ULONG
)cIn
* (ULONG
)10000;
4277 /**********************************************************************
4278 * VarCyFromUI2 [OLEAUT32.226]
4279 * Convert unsigned short to currency
4281 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pcyOut
) {
4283 pcyOut
->s
.Lo
= (ULONG
)usIn
* (ULONG
)10000;
4288 /**********************************************************************
4289 * VarCyFromUI4 [OLEAUT32.227]
4290 * Convert unsigned long to currency
4292 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pcyOut
) {
4293 double t
= (double)ulIn
* (double)10000;
4294 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4295 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4301 /**********************************************************************
4302 * DosDateTimeToVariantTime [OLEAUT32.14]
4303 * Convert dos representation of time to the date and time representation
4304 * stored in a variant.
4306 INT WINAPI
DosDateTimeToVariantTime(USHORT wDosDate
, USHORT wDosTime
,
4311 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate
, wDosTime
, pvtime
);
4313 t
.tm_sec
= (wDosTime
& 0x001f) * 2;
4314 t
.tm_min
= (wDosTime
& 0x07e0) >> 5;
4315 t
.tm_hour
= (wDosTime
& 0xf800) >> 11;
4317 t
.tm_mday
= (wDosDate
& 0x001f);
4318 t
.tm_mon
= (wDosDate
& 0x01e0) >> 5;
4319 t
.tm_year
= ((wDosDate
& 0xfe00) >> 9) + 1980;
4321 return TmToDATE( &t
, pvtime
);