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 are 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.
41 # define FLT_MAX MAXFLOAT
43 # error "Can't find #define for MAXFLOAT/FLT_MAX"
49 static const char CHAR_MAX
= 127;
50 static const char CHAR_MIN
= -128;
51 static const BYTE UI1_MAX
= 255;
52 static const BYTE UI1_MIN
= 0;
53 static const unsigned short UI2_MAX
= 65535;
54 static const unsigned short UI2_MIN
= 0;
55 static const short I2_MAX
= 32767;
56 static const short I2_MIN
= -32768;
57 static const unsigned long UI4_MAX
= 4294967295U;
58 static const unsigned long UI4_MIN
= 0;
59 static const long I4_MAX
= 2147483647;
60 static const long I4_MIN
= -(2147483648U);
61 static const DATE DATE_MIN
= -657434;
62 static const DATE DATE_MAX
= 2958465;
65 /* This mask is used to set a flag in wReserved1 of
66 * the VARIANTARG structure. The flag indicates if
67 * the API function is using an inner variant or not.
69 #define PROCESSING_INNER_VARIANT 0x0001
71 /* General use buffer.
73 #define BUFFER_MAX 1024
74 static char pBuffer
[BUFFER_MAX
];
77 * Note a leap year is one that is a multiple of 4
78 * but not of a 100. Except if it is a multiple of
79 * 400 then it is a leap year.
81 /* According to postgeSQL date parsing functions there is
82 * a leap year when this expression is true.
83 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
84 * So according to this there is 365.2515 days in one year.
85 * One + every four years: 1/4 -> 365.25
86 * One - every 100 years: 1/100 -> 365.001
87 * One + every 400 years: 1/400 -> 365.0025
89 static const double DAYS_IN_ONE_YEAR
= 365.2515;
93 /******************************************************************************
94 * DateTimeStringToTm [INTERNAL]
96 * Converts a string representation of a date and/or time to a tm structure.
98 * Note this function uses the postgresql date parsing functions found
99 * in the parsedt.c file.
101 * Returns TRUE if successfull.
103 * Note: This function does not parse the day of the week,
104 * daylight savings time. It will only fill the followin fields in
105 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
107 ******************************************************************************/
108 static BOOL
DateTimeStringToTm( OLECHAR
* strIn
, LCID lcid
, struct tm
* pTm
)
115 char *field
[MAXDATEFIELDS
];
116 int ftype
[MAXDATEFIELDS
];
117 char lowstr
[MAXDATELEN
+ 1];
118 char* strDateTime
= NULL
;
120 /* Convert the string to ASCII since this is the only format
121 * postgesql can handle.
123 strDateTime
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
125 if( strDateTime
!= NULL
)
127 /* Make sure we don't go over the maximum length
128 * accepted by postgesql.
130 if( strlen( strDateTime
) <= MAXDATELEN
)
132 if( ParseDateTime( strDateTime
, lowstr
, field
, ftype
, MAXDATEFIELDS
, &nf
) == 0 )
134 if( lcid
& VAR_DATEVALUEONLY
)
136 /* Get the date information.
137 * It returns 0 if date information was
138 * present and 1 if only time information was present.
139 * -1 if an error occures.
141 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) == 0 )
143 /* Eliminate the time information since we
144 * were asked to get date information only.
152 if( lcid
& VAR_TIMEVALUEONLY
)
154 /* Get time information only.
156 if( DecodeTimeOnly(field
, ftype
, nf
, &dtype
, pTm
, &fsec
) == 0 )
163 /* Get both date and time information.
164 * It returns 0 if date information was
165 * present and 1 if only time information was present.
166 * -1 if an error occures.
168 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) != -1 )
175 HeapFree( GetProcessHeap(), 0, strDateTime
);
186 /******************************************************************************
187 * TmToDATE [INTERNAL]
189 * The date is implemented using an 8 byte floating-point number.
190 * Days are represented by whole numbers increments starting with 0.00 has
191 * being December 30 1899, midnight.
192 * The hours are expressed as the fractional part of the number.
193 * December 30 1899 at midnight = 0.00
194 * January 1 1900 at midnight = 2.00
195 * January 4 1900 at 6 AM = 5.25
196 * January 4 1900 at noon = 5.50
197 * December 29 1899 at midnight = -1.00
198 * December 18 1899 at midnight = -12.00
199 * December 18 1899 at 6AM = -12.25
200 * December 18 1899 at 6PM = -12.75
201 * December 19 1899 at midnight = -11.00
202 * The tm structure is as follows:
204 * int tm_sec; seconds after the minute - [0,59]
205 * int tm_min; minutes after the hour - [0,59]
206 * int tm_hour; hours since midnight - [0,23]
207 * int tm_mday; day of the month - [1,31]
208 * int tm_mon; months since January - [0,11]
210 * int tm_wday; days since Sunday - [0,6]
211 * int tm_yday; days since January 1 - [0,365]
212 * int tm_isdst; daylight savings time flag
215 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
216 * and tm_isdst fields of the tm structure. And only converts years
219 * Returns TRUE if successfull.
221 static BOOL
TmToDATE( struct tm
* pTm
, DATE
*pDateOut
)
223 if( (pTm
->tm_year
- 1900) >= 0 )
227 /* Start at 1. This is the way DATE is defined.
228 * January 1, 1900 at Midnight is 1.00.
229 * January 1, 1900 at 6AM is 1.25.
234 /* Add the number of days corresponding to
237 *pDateOut
+= (pTm
->tm_year
- 1900) * 365;
239 /* Add the leap days in the previous years between now and 1900.
240 * Note a leap year is one that is a multiple of 4
241 * but not of a 100. Except if it is a multiple of
242 * 400 then it is a leap year.
244 *pDateOut
+= ( (pTm
->tm_year
- 1) / 4 ) - ( 1900 / 4 );
245 *pDateOut
-= ( (pTm
->tm_year
- 1) / 100 ) - ( 1900 / 100 );
246 *pDateOut
+= ( (pTm
->tm_year
- 1) / 400 ) - ( 1900 / 400 );
248 /* Set the leap year flag if the
249 * current year specified by tm_year is a
250 * leap year. This will be used to add a day
253 if( isleap( pTm
->tm_year
) )
256 /* Add the number of days corresponding to
259 switch( pTm
->tm_mon
)
265 *pDateOut
+= ( 59 + leapYear
);
268 *pDateOut
+= ( 90 + leapYear
);
271 *pDateOut
+= ( 120 + leapYear
);
274 *pDateOut
+= ( 151 + leapYear
);
277 *pDateOut
+= ( 181 + leapYear
);
280 *pDateOut
+= ( 212 + leapYear
);
283 *pDateOut
+= ( 243 + leapYear
);
286 *pDateOut
+= ( 273 + leapYear
);
289 *pDateOut
+= ( 304 + leapYear
);
292 *pDateOut
+= ( 334 + leapYear
);
295 /* Add the number of days in this month.
297 *pDateOut
+= pTm
->tm_mday
;
299 /* Add the number of seconds, minutes, and hours
300 * to the DATE. Note these are the fracionnal part
301 * of the DATE so seconds / number of seconds in a day.
303 *pDateOut
+= pTm
->tm_hour
/ 24.0;
304 *pDateOut
+= pTm
->tm_min
/ 1440.0;
305 *pDateOut
+= pTm
->tm_sec
/ 86400.0;
311 /******************************************************************************
312 * DateToTm [INTERNAL]
314 * This function converst a windows DATE to a tm structure.
316 * It does not fill all the fields of the tm structure.
317 * Here is a list of the fields that are filled:
318 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
320 * Note this function does not support dates before the January 1, 1900
321 * or ( dateIn < 2.0 ).
323 * Returns TRUE if successfull.
325 static BOOL
DateToTm( DATE dateIn
, LCID lcid
, struct tm
* pTm
)
327 /* Do not process dates smaller than January 1, 1900.
328 * Which corresponds to 2.0 in the windows DATE format.
332 double decimalPart
= 0.0;
333 double wholePart
= 0.0;
335 memset(pTm
,0,sizeof(*pTm
));
337 /* Because of the nature of DATE format witch
338 * associates 2.0 to January 1, 1900. We will
339 * remove 1.0 from the whole part of the DATE
340 * so that in the following code 1.0
341 * will correspond to January 1, 1900.
342 * This simplyfies the processing of the DATE value.
346 wholePart
= (double) floor( dateIn
);
347 decimalPart
= fmod( dateIn
, wholePart
);
349 if( !(lcid
& VAR_TIMEVALUEONLY
) )
353 double yearsSince1900
= 0;
354 /* Start at 1900, this where the DATE time 0.0 starts.
357 /* find in what year the day in the "wholePart" falls into.
358 * add the value to the year field.
360 yearsSince1900
= floor( wholePart
/ DAYS_IN_ONE_YEAR
);
361 pTm
->tm_year
+= yearsSince1900
;
362 /* determine if this is a leap year.
364 if( isleap( pTm
->tm_year
) )
366 /* find what day of that year does the "wholePart" corresponds to.
367 * Note: nDay is in [1-366] format
369 nDay
= (int) ( wholePart
- floor( yearsSince1900
* DAYS_IN_ONE_YEAR
) );
370 /* Set the tm_yday value.
371 * Note: The day is must be converted from [1-366] to [0-365]
373 /*pTm->tm_yday = nDay - 1;*/
374 /* find which mount this day corresponds to.
381 else if( nDay
<= ( 59 + leapYear
) )
383 pTm
->tm_mday
= nDay
- 31;
386 else if( nDay
<= ( 90 + leapYear
) )
388 pTm
->tm_mday
= nDay
- ( 59 + leapYear
);
391 else if( nDay
<= ( 120 + leapYear
) )
393 pTm
->tm_mday
= nDay
- ( 90 + leapYear
);
396 else if( nDay
<= ( 151 + leapYear
) )
398 pTm
->tm_mday
= nDay
- ( 120 + leapYear
);
401 else if( nDay
<= ( 181 + leapYear
) )
403 pTm
->tm_mday
= nDay
- ( 151 + leapYear
);
406 else if( nDay
<= ( 212 + leapYear
) )
408 pTm
->tm_mday
= nDay
- ( 181 + leapYear
);
411 else if( nDay
<= ( 243 + leapYear
) )
413 pTm
->tm_mday
= nDay
- ( 212 + leapYear
);
416 else if( nDay
<= ( 273 + leapYear
) )
418 pTm
->tm_mday
= nDay
- ( 243 + leapYear
);
421 else if( nDay
<= ( 304 + leapYear
) )
423 pTm
->tm_mday
= nDay
- ( 273 + leapYear
);
426 else if( nDay
<= ( 334 + leapYear
) )
428 pTm
->tm_mday
= nDay
- ( 304 + leapYear
);
431 else if( nDay
<= ( 365 + leapYear
) )
433 pTm
->tm_mday
= nDay
- ( 334 + leapYear
);
437 if( !(lcid
& VAR_DATEVALUEONLY
) )
439 /* find the number of seconds in this day.
440 * fractional part times, hours, minutes, seconds.
442 pTm
->tm_hour
= (int) ( decimalPart
* 24 );
443 pTm
->tm_min
= (int) ( ( ( decimalPart
* 24 ) - pTm
->tm_hour
) * 60 );
444 pTm
->tm_sec
= (int) ( ( ( decimalPart
* 24 * 60 ) - ( pTm
->tm_hour
* 60 ) - pTm
->tm_min
) * 60 );
453 /******************************************************************************
454 * SizeOfVariantData [INTERNAL]
456 * This function finds the size of the data referenced by a Variant based
457 * the type "vt" of the Variant.
459 static int SizeOfVariantData( VARIANT
* parg
)
462 switch( parg
->vt
& VT_TYPEMASK
)
465 size
= sizeof(short);
477 size
= sizeof(unsigned short);
480 size
= sizeof(unsigned int);
483 size
= sizeof(unsigned long);
486 size
= sizeof(float);
489 size
= sizeof(double);
495 size
= sizeof(VARIANT_BOOL
);
498 size
= sizeof(void*);
505 FIXME(ole
,"Add size information for type vt=%d\n", parg
->vt
& VT_TYPEMASK
);
511 /******************************************************************************
512 * StringDupAtoBstr [INTERNAL]
515 static BSTR
StringDupAtoBstr( char* strIn
)
518 OLECHAR
* pNewString
= NULL
;
519 pNewString
= HEAP_strdupAtoW( GetProcessHeap(), 0, strIn
);
520 bstr
= SysAllocString( pNewString
);
521 HeapFree( GetProcessHeap(), 0, pNewString
);
525 /******************************************************************************
528 * Round the double value to the nearest integer value.
530 static double round( double d
)
532 double decimals
= 0.0, integerValue
= 0.0, roundedValue
= 0.0;
533 BOOL bEvenNumber
= FALSE
;
536 /* Save the sign of the number
538 nSign
= (d
>= 0.0) ? 1 : -1;
541 /* Remove the decimals.
543 integerValue
= floor( d
);
545 /* Set the Even flag. This is used to round the number when
546 * the decimals are exactly 1/2. If the integer part is
547 * odd the number is rounded up. If the integer part
548 * is even the number is rounded down. Using this method
549 * numbers are rounded up|down half the time.
551 bEvenNumber
= (((short)fmod(integerValue
, 2)) == 0) ? TRUE
: FALSE
;
553 /* Remove the integral part of the number.
555 decimals
= d
- integerValue
;
557 /* Note: Ceil returns the smallest integer that is greater that x.
558 * and floor returns the largest integer that is less than or equal to x.
562 /* If the decimal part is greater than 1/2
564 roundedValue
= ceil( d
);
566 else if( decimals
< 0.5 )
568 /* If the decimal part is smaller than 1/2
570 roundedValue
= floor( d
);
574 /* the decimals are exactly 1/2 so round according to
575 * the bEvenNumber flag.
579 roundedValue
= floor( d
);
583 roundedValue
= ceil( d
);
587 return roundedValue
* nSign
;
590 /******************************************************************************
591 * RemoveCharacterFromString [INTERNAL]
593 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
595 static void RemoveCharacterFromString( LPSTR str
, LPSTR strOfCharToRemove
)
597 LPSTR pNewString
= NULL
;
598 LPSTR strToken
= NULL
;
601 /* Check if we have a valid argument
605 pNewString
= strdup( str
);
607 strToken
= strtok( pNewString
, strOfCharToRemove
);
608 while( strToken
!= NULL
) {
609 strcat( str
, strToken
);
610 strToken
= strtok( NULL
, strOfCharToRemove
);
617 /******************************************************************************
618 * GetValidRealString [INTERNAL]
620 * Checks if the string is of proper format to be converted to a real value.
622 static BOOL
IsValidRealString( LPSTR strRealString
)
624 /* Real values that have a decimal point are required to either have
625 * digits before or after the decimal point. We will assume that
626 * we do not have any digits at either position. If we do encounter
627 * some we will disable this flag.
629 BOOL bDigitsRequired
= TRUE
;
630 /* Processed fields in the string representation of the real number.
632 BOOL bWhiteSpaceProcessed
= FALSE
;
633 BOOL bFirstSignProcessed
= FALSE
;
634 BOOL bFirstDigitsProcessed
= FALSE
;
635 BOOL bDecimalPointProcessed
= FALSE
;
636 BOOL bSecondDigitsProcessed
= FALSE
;
637 BOOL bExponentProcessed
= FALSE
;
638 BOOL bSecondSignProcessed
= FALSE
;
639 BOOL bThirdDigitsProcessed
= FALSE
;
640 /* Assume string parameter "strRealString" is valid and try to disprove it.
642 BOOL bValidRealString
= TRUE
;
644 /* Used to count the number of tokens in the "strRealString".
646 LPSTR strToken
= NULL
;
650 /* Check if we have a valid argument
652 if( strRealString
== NULL
)
654 bValidRealString
= FALSE
;
657 if( bValidRealString
== TRUE
)
659 /* Make sure we only have ONE token in the string.
661 strToken
= strtok( strRealString
, " " );
662 while( strToken
!= NULL
) {
664 strToken
= strtok( NULL
, " " );
669 bValidRealString
= FALSE
;
674 /* Make sure this token contains only valid characters.
675 * The string argument to atof has the following form:
676 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
677 * Whitespace consists of space and|or <TAB> characters, which are ignored.
678 * Sign is either plus '+' or minus '-'.
679 * Digits are one or more decimal digits.
680 * Note: If no digits appear before the decimal point, at least one must
681 * appear after the decimal point.
682 * The decimal digits may be followed by an exponent.
683 * An Exponent consists of an introductory letter ( D, d, E, or e) and
684 * an optionally signed decimal integer.
686 pChar
= strRealString
;
687 while( bValidRealString
== TRUE
&& *pChar
!= '\0' )
695 if( bWhiteSpaceProcessed
||
696 bFirstSignProcessed
||
697 bFirstDigitsProcessed
||
698 bDecimalPointProcessed
||
699 bSecondDigitsProcessed
||
700 bExponentProcessed
||
701 bSecondSignProcessed
||
702 bThirdDigitsProcessed
)
704 bValidRealString
= FALSE
;
711 if( bFirstSignProcessed
== FALSE
)
713 if( bFirstDigitsProcessed
||
714 bDecimalPointProcessed
||
715 bSecondDigitsProcessed
||
716 bExponentProcessed
||
717 bSecondSignProcessed
||
718 bThirdDigitsProcessed
)
720 bValidRealString
= FALSE
;
722 bWhiteSpaceProcessed
= TRUE
;
723 bFirstSignProcessed
= TRUE
;
725 else if( bSecondSignProcessed
== FALSE
)
727 /* Note: The exponent must be present in
728 * order to accept the second sign...
730 if( bExponentProcessed
== FALSE
||
731 bThirdDigitsProcessed
||
734 bValidRealString
= FALSE
;
736 bFirstSignProcessed
= TRUE
;
737 bWhiteSpaceProcessed
= TRUE
;
738 bFirstDigitsProcessed
= TRUE
;
739 bDecimalPointProcessed
= TRUE
;
740 bSecondDigitsProcessed
= TRUE
;
741 bSecondSignProcessed
= TRUE
;
757 if( bFirstDigitsProcessed
== FALSE
)
759 if( bDecimalPointProcessed
||
760 bSecondDigitsProcessed
||
761 bExponentProcessed
||
762 bSecondSignProcessed
||
763 bThirdDigitsProcessed
)
765 bValidRealString
= FALSE
;
767 bFirstSignProcessed
= TRUE
;
768 bWhiteSpaceProcessed
= TRUE
;
769 /* We have found some digits before the decimal point
770 * so disable the "Digits required" flag.
772 bDigitsRequired
= FALSE
;
774 else if( bSecondDigitsProcessed
== FALSE
)
776 if( bExponentProcessed
||
777 bSecondSignProcessed
||
778 bThirdDigitsProcessed
)
780 bValidRealString
= FALSE
;
782 bFirstSignProcessed
= TRUE
;
783 bWhiteSpaceProcessed
= TRUE
;
784 bFirstDigitsProcessed
= TRUE
;
785 bDecimalPointProcessed
= TRUE
;
786 /* We have found some digits after the decimal point
787 * so disable the "Digits required" flag.
789 bDigitsRequired
= FALSE
;
791 else if( bThirdDigitsProcessed
== FALSE
)
793 /* Getting here means everything else should be processed.
794 * If we get anything else than a decimal following this
795 * digit it will be flagged by the other cases, so
796 * we do not really need to do anything in here.
800 /* If DecimalPoint...
803 if( bDecimalPointProcessed
||
804 bSecondDigitsProcessed
||
805 bExponentProcessed
||
806 bSecondSignProcessed
||
807 bThirdDigitsProcessed
)
809 bValidRealString
= FALSE
;
811 bFirstSignProcessed
= TRUE
;
812 bWhiteSpaceProcessed
= TRUE
;
813 bFirstDigitsProcessed
= TRUE
;
814 bDecimalPointProcessed
= TRUE
;
822 if( bExponentProcessed
||
823 bSecondSignProcessed
||
824 bThirdDigitsProcessed
||
827 bValidRealString
= FALSE
;
829 bFirstSignProcessed
= TRUE
;
830 bWhiteSpaceProcessed
= TRUE
;
831 bFirstDigitsProcessed
= TRUE
;
832 bDecimalPointProcessed
= TRUE
;
833 bSecondDigitsProcessed
= TRUE
;
834 bExponentProcessed
= TRUE
;
837 bValidRealString
= FALSE
;
840 /* Process next character.
845 /* If the required digits were not present we have an invalid
846 * string representation of a real number.
848 if( bDigitsRequired
== TRUE
)
850 bValidRealString
= FALSE
;
853 return bValidRealString
;
857 /******************************************************************************
860 * This function dispatches execution to the proper conversion API
861 * to do the necessary coercion.
863 static HRESULT
Coerce( VARIANTARG
* pd
, LCID lcid
, ULONG dwFlags
, VARIANTARG
* ps
, VARTYPE vt
)
866 unsigned short vtFrom
= 0;
867 vtFrom
= ps
->vt
& VT_TYPEMASK
;
869 /* Note: Since "long" and "int" values both have 4 bytes and are both signed integers
870 * "int" will be treated as "long" in the following code.
871 * The same goes for there unsigned versions.
878 res
= VariantClear( pd
);
881 res
= VariantClear( pd
);
891 res
= VariantCopy( pd
, ps
);
894 res
= VarI1FromI2( ps
->u
.iVal
, &(pd
->u
.cVal
) );
898 res
= VarI1FromI4( ps
->u
.lVal
, &(pd
->u
.cVal
) );
901 res
= VarI1FromUI1( ps
->u
.bVal
, &(pd
->u
.cVal
) );
904 res
= VarI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.cVal
) );
908 res
= VarI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.cVal
) );
911 res
= VarI1FromR4( ps
->u
.fltVal
, &(pd
->u
.cVal
) );
914 res
= VarI1FromR8( ps
->u
.dblVal
, &(pd
->u
.cVal
) );
917 res
= VarI1FromDate( ps
->u
.date
, &(pd
->u
.cVal
) );
920 res
= VarI1FromBool( ps
->u
.boolVal
, &(pd
->u
.cVal
) );
923 res
= VarI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.cVal
) );
926 res
= VarI1FromCy( ps
->u
.cyVal
, &(pd
->u
.cVal
) );
928 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
930 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
932 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
934 res
= DISP_E_TYPEMISMATCH
;
935 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
944 res
= VarI2FromI1( ps
->u
.cVal
, &(pd
->u
.iVal
) );
947 res
= VariantCopy( pd
, ps
);
951 res
= VarI2FromI4( ps
->u
.lVal
, &(pd
->u
.iVal
) );
954 res
= VarI2FromUI1( ps
->u
.bVal
, &(pd
->u
.iVal
) );
957 res
= VarI2FromUI2( ps
->u
.uiVal
, &(pd
->u
.iVal
) );
961 res
= VarI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.iVal
) );
964 res
= VarI2FromR4( ps
->u
.fltVal
, &(pd
->u
.iVal
) );
967 res
= VarI2FromR8( ps
->u
.dblVal
, &(pd
->u
.iVal
) );
970 res
= VarI2FromDate( ps
->u
.date
, &(pd
->u
.iVal
) );
973 res
= VarI2FromBool( ps
->u
.boolVal
, &(pd
->u
.iVal
) );
976 res
= VarI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.iVal
) );
979 res
= VarI2FromCy( ps
->u
.cyVal
, &(pd
->u
.iVal
) );
981 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
983 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
985 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
987 res
= DISP_E_TYPEMISMATCH
;
988 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
998 res
= VarI4FromI1( ps
->u
.cVal
, &(pd
->u
.lVal
) );
1001 res
= VarI4FromI2( ps
->u
.iVal
, &(pd
->u
.lVal
) );
1005 res
= VariantCopy( pd
, ps
);
1008 res
= VarI4FromUI1( ps
->u
.bVal
, &(pd
->u
.lVal
) );
1011 res
= VarI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.lVal
) );
1015 res
= VarI4FromUI4( ps
->u
.ulVal
, &(pd
->u
.lVal
) );
1018 res
= VarI4FromR4( ps
->u
.fltVal
, &(pd
->u
.lVal
) );
1021 res
= VarI4FromR8( ps
->u
.dblVal
, &(pd
->u
.lVal
) );
1024 res
= VarI4FromDate( ps
->u
.date
, &(pd
->u
.lVal
) );
1027 res
= VarI4FromBool( ps
->u
.boolVal
, &(pd
->u
.lVal
) );
1030 res
= VarI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.lVal
) );
1033 res
= VarI4FromCy( ps
->u
.cyVal
, &(pd
->u
.lVal
) );
1034 case( VT_DISPATCH
):
1035 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1037 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1039 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1041 res
= DISP_E_TYPEMISMATCH
;
1042 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1051 res
= VarUI1FromI1( ps
->u
.cVal
, &(pd
->u
.bVal
) );
1054 res
= VarUI1FromI2( ps
->u
.iVal
, &(pd
->u
.bVal
) );
1058 res
= VarUI1FromI4( ps
->u
.lVal
, &(pd
->u
.bVal
) );
1061 res
= VariantCopy( pd
, ps
);
1064 res
= VarUI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.bVal
) );
1068 res
= VarUI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.bVal
) );
1071 res
= VarUI1FromR4( ps
->u
.fltVal
, &(pd
->u
.bVal
) );
1074 res
= VarUI1FromR8( ps
->u
.dblVal
, &(pd
->u
.bVal
) );
1077 res
= VarUI1FromDate( ps
->u
.date
, &(pd
->u
.bVal
) );
1080 res
= VarUI1FromBool( ps
->u
.boolVal
, &(pd
->u
.bVal
) );
1083 res
= VarUI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.bVal
) );
1086 res
= VarUI1FromCy( ps
->u
.cyVal
, &(pd
->u
.bVal
) );
1087 case( VT_DISPATCH
):
1088 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1090 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1092 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1094 res
= DISP_E_TYPEMISMATCH
;
1095 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1104 res
= VarUI2FromI1( ps
->u
.cVal
, &(pd
->u
.uiVal
) );
1107 res
= VarUI2FromI2( ps
->u
.iVal
, &(pd
->u
.uiVal
) );
1111 res
= VarUI2FromI4( ps
->u
.lVal
, &(pd
->u
.uiVal
) );
1114 res
= VarUI2FromUI1( ps
->u
.bVal
, &(pd
->u
.uiVal
) );
1117 res
= VariantCopy( pd
, ps
);
1121 res
= VarUI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.uiVal
) );
1124 res
= VarUI2FromR4( ps
->u
.fltVal
, &(pd
->u
.uiVal
) );
1127 res
= VarUI2FromR8( ps
->u
.dblVal
, &(pd
->u
.uiVal
) );
1130 res
= VarUI2FromDate( ps
->u
.date
, &(pd
->u
.uiVal
) );
1133 res
= VarUI2FromBool( ps
->u
.boolVal
, &(pd
->u
.uiVal
) );
1136 res
= VarUI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.uiVal
) );
1139 res
= VarUI2FromCy( ps
->u
.cyVal
, &(pd
->u
.uiVal
) );
1140 case( VT_DISPATCH
):
1141 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1143 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1145 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1147 res
= DISP_E_TYPEMISMATCH
;
1148 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1158 res
= VarUI4FromI1( ps
->u
.cVal
, &(pd
->u
.ulVal
) );
1161 res
= VarUI4FromI2( ps
->u
.iVal
, &(pd
->u
.ulVal
) );
1165 res
= VarUI4FromI4( ps
->u
.lVal
, &(pd
->u
.ulVal
) );
1168 res
= VarUI4FromUI1( ps
->u
.bVal
, &(pd
->u
.ulVal
) );
1171 res
= VarUI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.ulVal
) );
1174 res
= VariantCopy( pd
, ps
);
1177 res
= VarUI4FromR4( ps
->u
.fltVal
, &(pd
->u
.ulVal
) );
1180 res
= VarUI4FromR8( ps
->u
.dblVal
, &(pd
->u
.ulVal
) );
1183 res
= VarUI4FromDate( ps
->u
.date
, &(pd
->u
.ulVal
) );
1186 res
= VarUI4FromBool( ps
->u
.boolVal
, &(pd
->u
.ulVal
) );
1189 res
= VarUI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.ulVal
) );
1192 res
= VarUI4FromCy( ps
->u
.cyVal
, &(pd
->u
.ulVal
) );
1193 case( VT_DISPATCH
):
1194 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1196 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1198 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1200 res
= DISP_E_TYPEMISMATCH
;
1201 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1210 res
= VarR4FromI1( ps
->u
.cVal
, &(pd
->u
.fltVal
) );
1213 res
= VarR4FromI2( ps
->u
.iVal
, &(pd
->u
.fltVal
) );
1217 res
= VarR4FromI4( ps
->u
.lVal
, &(pd
->u
.fltVal
) );
1220 res
= VarR4FromUI1( ps
->u
.bVal
, &(pd
->u
.fltVal
) );
1223 res
= VarR4FromUI2( ps
->u
.uiVal
, &(pd
->u
.fltVal
) );
1227 res
= VarR4FromUI4( ps
->u
.ulVal
, &(pd
->u
.fltVal
) );
1230 res
= VariantCopy( pd
, ps
);
1233 res
= VarR4FromR8( ps
->u
.dblVal
, &(pd
->u
.fltVal
) );
1236 res
= VarR4FromDate( ps
->u
.date
, &(pd
->u
.fltVal
) );
1239 res
= VarR4FromBool( ps
->u
.boolVal
, &(pd
->u
.fltVal
) );
1242 res
= VarR4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.fltVal
) );
1245 res
= VarR4FromCy( ps
->u
.cyVal
, &(pd
->u
.fltVal
) );
1246 case( VT_DISPATCH
):
1247 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1249 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1251 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1253 res
= DISP_E_TYPEMISMATCH
;
1254 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1263 res
= VarR8FromI1( ps
->u
.cVal
, &(pd
->u
.dblVal
) );
1266 res
= VarR8FromI2( ps
->u
.iVal
, &(pd
->u
.dblVal
) );
1270 res
= VarR8FromI4( ps
->u
.lVal
, &(pd
->u
.dblVal
) );
1273 res
= VarR8FromUI1( ps
->u
.bVal
, &(pd
->u
.dblVal
) );
1276 res
= VarR8FromUI2( ps
->u
.uiVal
, &(pd
->u
.dblVal
) );
1280 res
= VarR8FromUI4( ps
->u
.ulVal
, &(pd
->u
.dblVal
) );
1283 res
= VarR8FromR4( ps
->u
.fltVal
, &(pd
->u
.dblVal
) );
1286 res
= VariantCopy( pd
, ps
);
1289 res
= VarR8FromDate( ps
->u
.date
, &(pd
->u
.dblVal
) );
1292 res
= VarR8FromBool( ps
->u
.boolVal
, &(pd
->u
.dblVal
) );
1295 res
= VarR8FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.dblVal
) );
1298 res
= VarR8FromCy( ps
->u
.cyVal
, &(pd
->u
.dblVal
) );
1299 case( VT_DISPATCH
):
1300 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1302 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1304 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1306 res
= DISP_E_TYPEMISMATCH
;
1307 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1316 res
= VarDateFromI1( ps
->u
.cVal
, &(pd
->u
.date
) );
1319 res
= VarDateFromI2( ps
->u
.iVal
, &(pd
->u
.date
) );
1322 res
= VarDateFromInt( ps
->u
.intVal
, &(pd
->u
.date
) );
1325 res
= VarDateFromI4( ps
->u
.lVal
, &(pd
->u
.date
) );
1328 res
= VarDateFromUI1( ps
->u
.bVal
, &(pd
->u
.date
) );
1331 res
= VarDateFromUI2( ps
->u
.uiVal
, &(pd
->u
.date
) );
1334 res
= VarDateFromUint( ps
->u
.uintVal
, &(pd
->u
.date
) );
1337 res
= VarDateFromUI4( ps
->u
.ulVal
, &(pd
->u
.date
) );
1340 res
= VarDateFromR4( ps
->u
.fltVal
, &(pd
->u
.date
) );
1343 res
= VarDateFromR8( ps
->u
.dblVal
, &(pd
->u
.date
) );
1346 res
= VariantCopy( pd
, ps
);
1349 res
= VarDateFromBool( ps
->u
.boolVal
, &(pd
->u
.date
) );
1352 res
= VarDateFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.date
) );
1355 res
= VarDateFromCy( ps
->u
.cyVal
, &(pd
->u
.date
) );
1356 case( VT_DISPATCH
):
1357 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1359 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1361 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1363 res
= DISP_E_TYPEMISMATCH
;
1364 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1373 res
= VarBoolFromI1( ps
->u
.cVal
, &(pd
->u
.boolVal
) );
1376 res
= VarBoolFromI2( ps
->u
.iVal
, &(pd
->u
.boolVal
) );
1379 res
= VarBoolFromInt( ps
->u
.intVal
, &(pd
->u
.boolVal
) );
1382 res
= VarBoolFromI4( ps
->u
.lVal
, &(pd
->u
.boolVal
) );
1385 res
= VarBoolFromUI1( ps
->u
.bVal
, &(pd
->u
.boolVal
) );
1388 res
= VarBoolFromUI2( ps
->u
.uiVal
, &(pd
->u
.boolVal
) );
1391 res
= VarBoolFromUint( ps
->u
.uintVal
, &(pd
->u
.boolVal
) );
1394 res
= VarBoolFromUI4( ps
->u
.ulVal
, &(pd
->u
.boolVal
) );
1397 res
= VarBoolFromR4( ps
->u
.fltVal
, &(pd
->u
.boolVal
) );
1400 res
= VarBoolFromR8( ps
->u
.dblVal
, &(pd
->u
.boolVal
) );
1403 res
= VarBoolFromDate( ps
->u
.date
, &(pd
->u
.boolVal
) );
1406 res
= VariantCopy( pd
, ps
);
1409 res
= VarBoolFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.boolVal
) );
1412 res
= VarBoolFromCy( ps
->u
.cyVal
, &(pd
->u
.boolVal
) );
1413 case( VT_DISPATCH
):
1414 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1416 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1418 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1420 res
= DISP_E_TYPEMISMATCH
;
1421 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1430 res
= VarBstrFromI1( ps
->u
.cVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1433 res
= VarBstrFromI2( ps
->u
.iVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1436 res
= VarBstrFromInt( ps
->u
.intVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1439 res
= VarBstrFromI4( ps
->u
.lVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1442 res
= VarBstrFromUI1( ps
->u
.bVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1445 res
= VarBstrFromUI2( ps
->u
.uiVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1448 res
= VarBstrFromUint( ps
->u
.uintVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1451 res
= VarBstrFromUI4( ps
->u
.ulVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1454 res
= VarBstrFromR4( ps
->u
.fltVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1457 res
= VarBstrFromR8( ps
->u
.dblVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1460 res
= VarBstrFromDate( ps
->u
.date
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1463 res
= VarBstrFromBool( ps
->u
.boolVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1466 res
= VariantCopy( pd
, ps
);
1469 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1470 case( VT_DISPATCH
):
1471 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1473 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1475 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1477 res
= DISP_E_TYPEMISMATCH
;
1478 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1487 res
= VarCyFromI1( ps
->u
.cVal
, &(pd
->u
.cyVal
) );
1490 res
= VarCyFromI2( ps
->u
.iVal
, &(pd
->u
.cyVal
) );
1493 res
= VarCyFromInt( ps
->u
.intVal
, &(pd
->u
.cyVal
) );
1496 res
= VarCyFromI4( ps
->u
.lVal
, &(pd
->u
.cyVal
) );
1499 res
= VarCyFromUI1( ps
->u
.bVal
, &(pd
->u
.cyVal
) );
1502 res
= VarCyFromUI2( ps
->u
.uiVal
, &(pd
->u
.cyVal
) );
1505 res
= VarCyFromUint( ps
->u
.uintVal
, &(pd
->u
.cyVal
) );
1508 res
= VarCyFromUI4( ps
->u
.ulVal
, &(pd
->u
.cyVal
) );
1511 res
= VarCyFromR4( ps
->u
.fltVal
, &(pd
->u
.cyVal
) );
1514 res
= VarCyFromR8( ps
->u
.dblVal
, &(pd
->u
.cyVal
) );
1517 res
= VarCyFromDate( ps
->u
.date
, &(pd
->u
.cyVal
) );
1520 res
= VarCyFromBool( ps
->u
.date
, &(pd
->u
.cyVal
) );
1523 res
= VariantCopy( pd
, ps
);
1526 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1527 case( VT_DISPATCH
):
1528 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1530 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1532 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1534 res
= DISP_E_TYPEMISMATCH
;
1535 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1541 res
= DISP_E_TYPEMISMATCH
;
1542 FIXME(ole
,"Coercion from %d to %d\n", vtFrom
, vt
);
1549 /******************************************************************************
1550 * ValidateVtRange [INTERNAL]
1552 * Used internally by the hi-level Variant API to determine
1553 * if the vartypes are valid.
1555 static HRESULT WINAPI
ValidateVtRange( VARTYPE vt
)
1557 /* if by value we must make sure it is in the
1558 * range of the valid types.
1560 if( ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1562 return DISP_E_BADVARTYPE
;
1568 /******************************************************************************
1569 * ValidateVartype [INTERNAL]
1571 * Used internally by the hi-level Variant API to determine
1572 * if the vartypes are valid.
1574 static HRESULT WINAPI
ValidateVariantType( VARTYPE vt
)
1578 /* check if we have a valid argument.
1582 /* if by reference check that the type is in
1583 * the valid range and that it is not of empty or null type
1585 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1586 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1587 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1595 res
= ValidateVtRange( vt
);
1601 /******************************************************************************
1602 * ValidateVt [INTERNAL]
1604 * Used internally by the hi-level Variant API to determine
1605 * if the vartypes are valid.
1607 static HRESULT WINAPI
ValidateVt( VARTYPE vt
)
1611 /* check if we have a valid argument.
1615 /* if by reference check that the type is in
1616 * the valid range and that it is not of empty or null type
1618 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1619 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1620 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1622 res
= DISP_E_BADVARTYPE
;
1628 res
= ValidateVtRange( vt
);
1638 /******************************************************************************
1639 * VariantInit32 [OLEAUT32.8]
1641 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1642 * contents of the Variant.
1644 void WINAPI
VariantInit(VARIANTARG
* pvarg
)
1646 TRACE(ole
,"(%p),stub\n",pvarg
);
1648 memset(pvarg
, 0, sizeof (VARIANTARG
));
1649 pvarg
->vt
= VT_EMPTY
;
1654 /******************************************************************************
1655 * VariantClear32 [OLEAUT32.9]
1657 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1658 * sets the wReservedX field to 0. The current contents of the VARIANT are
1659 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1660 * released. If VT_ARRAY the array is freed.
1662 HRESULT WINAPI
VariantClear(VARIANTARG
* pvarg
)
1665 TRACE(ole
,"(%p)\n",pvarg
);
1667 res
= ValidateVariantType( pvarg
->vt
);
1670 if( !( pvarg
->vt
& VT_BYREF
) )
1673 * The VT_ARRAY flag is a special case of a safe array.
1675 if ( (pvarg
->vt
& VT_ARRAY
) != 0)
1677 SafeArrayDestroy(pvarg
->u
.parray
);
1681 switch( pvarg
->vt
& VT_TYPEMASK
)
1684 SysFreeString( pvarg
->u
.bstrVal
);
1686 case( VT_DISPATCH
):
1692 case( VT_SAFEARRAY
):
1693 SafeArrayDestroy(pvarg
->u
.parray
);
1702 * Empty all the fields and mark the type as empty.
1704 memset(pvarg
, 0, sizeof (VARIANTARG
));
1705 pvarg
->vt
= VT_EMPTY
;
1711 /******************************************************************************
1712 * VariantCopy32 [OLEAUT32.10]
1714 * Frees up the designation variant and makes a copy of the source.
1716 HRESULT WINAPI
VariantCopy(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
)
1720 TRACE(ole
,"(%p, %p)\n", pvargDest
, pvargSrc
);
1722 res
= ValidateVariantType( pvargSrc
->vt
);
1724 /* If the pointer are to the same variant we don't need
1727 if( pvargDest
!= pvargSrc
&& res
== S_OK
)
1729 res
= VariantClear( pvargDest
);
1733 if( pvargSrc
->vt
& VT_BYREF
)
1735 /* In the case of byreference we only need
1736 * to copy the pointer.
1738 pvargDest
->u
= pvargSrc
->u
;
1739 pvargDest
->vt
= pvargSrc
->vt
;
1744 * The VT_ARRAY flag is another way to designate a safe array.
1746 if (pvargSrc
->vt
& VT_ARRAY
)
1748 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1752 /* In the case of by value we need to
1753 * copy the actuall value. In the case of
1754 * VT_BSTR a copy of the string is made,
1755 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1756 * called to increment the object's reference count.
1758 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1761 pvargDest
->u
.bstrVal
= SysAllocString( pvargSrc
->u
.bstrVal
);
1763 case( VT_DISPATCH
):
1769 case( VT_SAFEARRAY
):
1770 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1773 pvargDest
->u
= pvargSrc
->u
;
1778 pvargDest
->vt
= pvargSrc
->vt
;
1787 /******************************************************************************
1788 * VariantCopyInd32 [OLEAUT32.11]
1790 * Frees up the destination variant and makes a copy of the source. If
1791 * the source is of type VT_BYREF it performs the necessary indirections.
1793 HRESULT WINAPI
VariantCopyInd(VARIANT
* pvargDest
, VARIANTARG
* pvargSrc
)
1797 TRACE(ole
,"(%p, %p)\n", pvargDest
, pvargSrc
);
1799 res
= ValidateVariantType( pvargSrc
->vt
);
1804 if( pvargSrc
->vt
& VT_BYREF
)
1807 VariantInit( &varg
);
1809 /* handle the in place copy.
1811 if( pvargDest
== pvargSrc
)
1813 /* we will use a copy of the source instead.
1815 res
= VariantCopy( &varg
, pvargSrc
);
1821 res
= VariantClear( pvargDest
);
1826 * The VT_ARRAY flag is another way to designate a safearray variant.
1828 if ( pvargSrc
->vt
& VT_ARRAY
)
1830 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1834 /* In the case of by reference we need
1835 * to copy the date pointed to by the variant.
1838 /* Get the variant type.
1840 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1843 pvargDest
->u
.bstrVal
= SysAllocString( *(pvargSrc
->u
.pbstrVal
) );
1845 case( VT_DISPATCH
):
1849 /* Prevent from cycling. According to tests on
1850 * VariantCopyInd in Windows and the documentation
1851 * this API dereferences the inner Variants to only one depth.
1852 * If the inner Variant itself contains an
1853 * other inner variant the E_INVALIDARG error is
1856 if( pvargSrc
->wReserved1
& PROCESSING_INNER_VARIANT
)
1858 /* If we get here we are attempting to deference
1859 * an inner variant that that is itself contained
1860 * in an inner variant so report E_INVALIDARG error.
1866 /* Set the processing inner variant flag.
1867 * We will set this flag in the inner variant
1868 * that will be passed to the VariantCopyInd function.
1870 (pvargSrc
->u
.pvarVal
)->wReserved1
|= PROCESSING_INNER_VARIANT
;
1872 /* Dereference the inner variant.
1874 res
= VariantCopyInd( pvargDest
, pvargSrc
->u
.pvarVal
);
1880 case( VT_SAFEARRAY
):
1881 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1884 /* This is a by reference Variant which means that the union
1885 * part of the Variant contains a pointer to some data of
1886 * type "pvargSrc->vt & VT_TYPEMASK".
1887 * We will deference this data in a generic fashion using
1888 * the void pointer "Variant.u.byref".
1889 * We will copy this data into the union of the destination
1892 memcpy( &pvargDest
->u
, pvargSrc
->u
.byref
, SizeOfVariantData( pvargSrc
) );
1897 pvargDest
->vt
= pvargSrc
->vt
& VT_TYPEMASK
;
1901 /* this should not fail.
1903 VariantClear( &varg
);
1907 res
= VariantCopy( pvargDest
, pvargSrc
);
1913 /******************************************************************************
1914 * VariantChangeType32 [OLEAUT32.12]
1916 HRESULT WINAPI
VariantChangeType(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1917 USHORT wFlags
, VARTYPE vt
)
1919 return VariantChangeTypeEx( pvargDest
, pvargSrc
, 0, wFlags
, vt
);
1922 /******************************************************************************
1923 * VariantChangeTypeEx32 [OLEAUT32.147]
1925 HRESULT WINAPI
VariantChangeTypeEx(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1926 LCID lcid
, USHORT wFlags
, VARTYPE vt
)
1930 VariantInit( &varg
);
1932 TRACE(ole
,"(%p, %p, %ld, %u, %u),stub\n", pvargDest
, pvargSrc
, lcid
, wFlags
, vt
);
1934 /* validate our source argument.
1936 res
= ValidateVariantType( pvargSrc
->vt
);
1938 /* validate the vartype.
1942 res
= ValidateVt( vt
);
1945 /* if we are doing an in-place conversion make a copy of the source.
1947 if( res
== S_OK
&& pvargDest
== pvargSrc
)
1949 res
= VariantCopy( &varg
, pvargSrc
);
1955 /* free up the destination variant.
1957 res
= VariantClear( pvargDest
);
1962 if( pvargSrc
->vt
& VT_BYREF
)
1964 /* Convert the source variant to a "byvalue" variant.
1967 VariantInit( &Variant
);
1968 res
= VariantCopyInd( &Variant
, pvargSrc
);
1971 res
= Coerce( pvargDest
, lcid
, wFlags
, &Variant
, vt
);
1972 /* this should not fail.
1974 VariantClear( &Variant
);
1980 /* Use the current "byvalue" source variant.
1982 res
= Coerce( pvargDest
, lcid
, wFlags
, pvargSrc
, vt
);
1985 /* this should not fail.
1987 VariantClear( &varg
);
1995 /******************************************************************************
1996 * VarUI1FromI232 [OLEAUT32.130]
1998 HRESULT WINAPI
VarUI1FromI2(short sIn
, BYTE
* pbOut
)
2000 TRACE( ole
, "( %d, %p ), stub\n", sIn
, pbOut
);
2002 /* Check range of value.
2004 if( sIn
< UI1_MIN
|| sIn
> UI1_MAX
)
2006 return DISP_E_OVERFLOW
;
2009 *pbOut
= (BYTE
) sIn
;
2014 /******************************************************************************
2015 * VarUI1FromI432 [OLEAUT32.131]
2017 HRESULT WINAPI
VarUI1FromI4(LONG lIn
, BYTE
* pbOut
)
2019 TRACE( ole
, "( %ld, %p ), stub\n", lIn
, pbOut
);
2021 /* Check range of value.
2023 if( lIn
< UI1_MIN
|| lIn
> UI1_MAX
)
2025 return DISP_E_OVERFLOW
;
2028 *pbOut
= (BYTE
) lIn
;
2034 /******************************************************************************
2035 * VarUI1FromR432 [OLEAUT32.132]
2037 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
2039 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, pbOut
);
2041 /* Check range of value.
2043 fltIn
= round( fltIn
);
2044 if( fltIn
< UI1_MIN
|| fltIn
> UI1_MAX
)
2046 return DISP_E_OVERFLOW
;
2049 *pbOut
= (BYTE
) fltIn
;
2054 /******************************************************************************
2055 * VarUI1FromR832 [OLEAUT32.133]
2057 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
2059 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, pbOut
);
2061 /* Check range of value.
2063 dblIn
= round( dblIn
);
2064 if( dblIn
< UI1_MIN
|| dblIn
> UI1_MAX
)
2066 return DISP_E_OVERFLOW
;
2069 *pbOut
= (BYTE
) dblIn
;
2074 /******************************************************************************
2075 * VarUI1FromDate32 [OLEAUT32.135]
2077 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
2079 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, pbOut
);
2081 /* Check range of value.
2083 dateIn
= round( dateIn
);
2084 if( dateIn
< UI1_MIN
|| dateIn
> UI1_MAX
)
2086 return DISP_E_OVERFLOW
;
2089 *pbOut
= (BYTE
) dateIn
;
2094 /******************************************************************************
2095 * VarUI1FromBool32 [OLEAUT32.138]
2097 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
2099 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, pbOut
);
2101 *pbOut
= (BYTE
) boolIn
;
2106 /******************************************************************************
2107 * VarUI1FromI132 [OLEAUT32.237]
2109 HRESULT WINAPI
VarUI1FromI1(CHAR cIn
, BYTE
* pbOut
)
2111 TRACE( ole
, "( %c, %p ), stub\n", cIn
, pbOut
);
2118 /******************************************************************************
2119 * VarUI1FromUI232 [OLEAUT32.238]
2121 HRESULT WINAPI
VarUI1FromUI2(USHORT uiIn
, BYTE
* pbOut
)
2123 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pbOut
);
2125 /* Check range of value.
2127 if( uiIn
> UI1_MAX
)
2129 return DISP_E_OVERFLOW
;
2132 *pbOut
= (BYTE
) uiIn
;
2137 /******************************************************************************
2138 * VarUI1FromUI432 [OLEAUT32.239]
2140 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
2142 TRACE( ole
, "( %ld, %p ), stub\n", ulIn
, pbOut
);
2144 /* Check range of value.
2146 if( ulIn
> UI1_MAX
)
2148 return DISP_E_OVERFLOW
;
2151 *pbOut
= (BYTE
) ulIn
;
2157 /******************************************************************************
2158 * VarUI1FromStr32 [OLEAUT32.54]
2160 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
2162 double dValue
= 0.0;
2163 LPSTR pNewString
= NULL
;
2165 TRACE( ole
, "( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pbOut
);
2167 /* Check if we have a valid argument
2169 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2170 RemoveCharacterFromString( pNewString
, "," );
2171 if( IsValidRealString( pNewString
) == FALSE
)
2173 return DISP_E_TYPEMISMATCH
;
2176 /* Convert the valid string to a floating point number.
2178 dValue
= atof( pNewString
);
2180 /* We don't need the string anymore so free it.
2182 HeapFree( GetProcessHeap(), 0 , pNewString
);
2184 /* Check range of value.
2186 dValue
= round( dValue
);
2187 if( dValue
< UI1_MIN
|| dValue
> UI1_MAX
)
2189 return DISP_E_OVERFLOW
;
2192 *pbOut
= (BYTE
) dValue
;
2197 /**********************************************************************
2198 * VarUI1FromCy32 [OLEAUT32.134]
2199 * Convert currency to unsigned char
2201 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
) {
2202 double t
= round((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
2204 if (t
> UI1_MAX
|| t
< UI1_MIN
) return DISP_E_OVERFLOW
;
2210 /******************************************************************************
2211 * VarI2FromUI132 [OLEAUT32.48]
2213 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, short* psOut
)
2215 TRACE( ole
, "( 0x%08x, %p ), stub\n", bIn
, psOut
);
2217 *psOut
= (short) bIn
;
2222 /******************************************************************************
2223 * VarI2FromI432 [OLEAUT32.49]
2225 HRESULT WINAPI
VarI2FromI4(LONG lIn
, short* psOut
)
2227 TRACE( ole
, "( %lx, %p ), stub\n", lIn
, psOut
);
2229 /* Check range of value.
2231 if( lIn
< I2_MIN
|| lIn
> I2_MAX
)
2233 return DISP_E_OVERFLOW
;
2236 *psOut
= (short) lIn
;
2241 /******************************************************************************
2242 * VarI2FromR432 [OLEAUT32.50]
2244 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, short* psOut
)
2246 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, psOut
);
2248 /* Check range of value.
2250 fltIn
= round( fltIn
);
2251 if( fltIn
< I2_MIN
|| fltIn
> I2_MAX
)
2253 return DISP_E_OVERFLOW
;
2256 *psOut
= (short) fltIn
;
2261 /******************************************************************************
2262 * VarI2FromR832 [OLEAUT32.51]
2264 HRESULT WINAPI
VarI2FromR8(double dblIn
, short* psOut
)
2266 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, psOut
);
2268 /* Check range of value.
2270 dblIn
= round( dblIn
);
2271 if( dblIn
< I2_MIN
|| dblIn
> I2_MAX
)
2273 return DISP_E_OVERFLOW
;
2276 *psOut
= (short) dblIn
;
2281 /******************************************************************************
2282 * VarI2FromDate32 [OLEAUT32.53]
2284 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, short* psOut
)
2286 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, psOut
);
2288 /* Check range of value.
2290 dateIn
= round( dateIn
);
2291 if( dateIn
< I2_MIN
|| dateIn
> I2_MAX
)
2293 return DISP_E_OVERFLOW
;
2296 *psOut
= (short) dateIn
;
2301 /******************************************************************************
2302 * VarI2FromBool32 [OLEAUT32.56]
2304 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, short* psOut
)
2306 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, psOut
);
2308 *psOut
= (short) boolIn
;
2313 /******************************************************************************
2314 * VarI2FromI132 [OLEAUT32.48]
2316 HRESULT WINAPI
VarI2FromI1(CHAR cIn
, short* psOut
)
2318 TRACE( ole
, "( %c, %p ), stub\n", cIn
, psOut
);
2320 *psOut
= (short) cIn
;
2325 /******************************************************************************
2326 * VarI2FromUI232 [OLEAUT32.206]
2328 HRESULT WINAPI
VarI2FromUI2(USHORT uiIn
, short* psOut
)
2330 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, psOut
);
2332 /* Check range of value.
2336 return DISP_E_OVERFLOW
;
2339 *psOut
= (short) uiIn
;
2344 /******************************************************************************
2345 * VarI2FromUI432 [OLEAUT32.49]
2347 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, short* psOut
)
2349 TRACE( ole
, "( %lx, %p ), stub\n", ulIn
, psOut
);
2351 /* Check range of value.
2353 if( ulIn
< I2_MIN
|| ulIn
> I2_MAX
)
2355 return DISP_E_OVERFLOW
;
2358 *psOut
= (short) ulIn
;
2363 /******************************************************************************
2364 * VarI2FromStr32 [OLEAUT32.54]
2366 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, short* psOut
)
2368 double dValue
= 0.0;
2369 LPSTR pNewString
= NULL
;
2371 TRACE( ole
, "( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, psOut
);
2373 /* Check if we have a valid argument
2375 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2376 RemoveCharacterFromString( pNewString
, "," );
2377 if( IsValidRealString( pNewString
) == FALSE
)
2379 return DISP_E_TYPEMISMATCH
;
2382 /* Convert the valid string to a floating point number.
2384 dValue
= atof( pNewString
);
2386 /* We don't need the string anymore so free it.
2388 HeapFree( GetProcessHeap(), 0, pNewString
);
2390 /* Check range of value.
2392 dValue
= round( dValue
);
2393 if( dValue
< I2_MIN
|| dValue
> I2_MAX
)
2395 return DISP_E_OVERFLOW
;
2398 *psOut
= (short) dValue
;
2403 /**********************************************************************
2404 * VarI2FromCy32 [OLEAUT32.52]
2405 * Convert currency to signed short
2407 HRESULT WINAPI
VarI2FromCy(CY cyIn
, short* psOut
) {
2408 double t
= round((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
2410 if (t
> I2_MAX
|| t
< I2_MIN
) return DISP_E_OVERFLOW
;
2416 /******************************************************************************
2417 * VarI4FromUI132 [OLEAUT32.58]
2419 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
* plOut
)
2421 TRACE( ole
, "( %X, %p ), stub\n", bIn
, plOut
);
2423 *plOut
= (LONG
) bIn
;
2429 /******************************************************************************
2430 * VarI4FromR432 [OLEAUT32.60]
2432 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
* plOut
)
2434 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, plOut
);
2436 /* Check range of value.
2438 fltIn
= round( fltIn
);
2439 if( fltIn
< I4_MIN
|| fltIn
> I4_MAX
)
2441 return DISP_E_OVERFLOW
;
2444 *plOut
= (LONG
) fltIn
;
2449 /******************************************************************************
2450 * VarI4FromR832 [OLEAUT32.61]
2452 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
* plOut
)
2454 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, plOut
);
2456 /* Check range of value.
2458 dblIn
= round( dblIn
);
2459 if( dblIn
< I4_MIN
|| dblIn
> I4_MAX
)
2461 return DISP_E_OVERFLOW
;
2464 *plOut
= (LONG
) dblIn
;
2469 /******************************************************************************
2470 * VarI4FromDate32 [OLEAUT32.63]
2472 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
* plOut
)
2474 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, plOut
);
2476 /* Check range of value.
2478 dateIn
= round( dateIn
);
2479 if( dateIn
< I4_MIN
|| dateIn
> I4_MAX
)
2481 return DISP_E_OVERFLOW
;
2484 *plOut
= (LONG
) dateIn
;
2489 /******************************************************************************
2490 * VarI4FromBool32 [OLEAUT32.66]
2492 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
* plOut
)
2494 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, plOut
);
2496 *plOut
= (LONG
) boolIn
;
2501 /******************************************************************************
2502 * VarI4FromI132 [OLEAUT32.209]
2504 HRESULT WINAPI
VarI4FromI1(CHAR cIn
, LONG
* plOut
)
2506 TRACE( ole
, "( %c, %p ), stub\n", cIn
, plOut
);
2508 *plOut
= (LONG
) cIn
;
2513 /******************************************************************************
2514 * VarI4FromUI232 [OLEAUT32.210]
2516 HRESULT WINAPI
VarI4FromUI2(USHORT uiIn
, LONG
* plOut
)
2518 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, plOut
);
2520 *plOut
= (LONG
) uiIn
;
2525 /******************************************************************************
2526 * VarI4FromUI432 [OLEAUT32.211]
2528 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
* plOut
)
2530 TRACE( ole
, "( %lx, %p ), stub\n", ulIn
, plOut
);
2532 /* Check range of value.
2534 if( ulIn
< I4_MIN
|| ulIn
> I4_MAX
)
2536 return DISP_E_OVERFLOW
;
2539 *plOut
= (LONG
) ulIn
;
2544 /******************************************************************************
2545 * VarI4FromI232 [OLEAUT32.59]
2547 HRESULT WINAPI
VarI4FromI2(short sIn
, LONG
* plOut
)
2549 TRACE( ole
, "( %d, %p ), stub\n", sIn
, plOut
);
2551 *plOut
= (LONG
) sIn
;
2556 /******************************************************************************
2557 * VarI4FromStr32 [OLEAUT32.64]
2559 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
* plOut
)
2561 double dValue
= 0.0;
2562 LPSTR pNewString
= NULL
;
2564 TRACE( ole
, "( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, plOut
);
2566 /* Check if we have a valid argument
2568 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2569 RemoveCharacterFromString( pNewString
, "," );
2570 if( IsValidRealString( pNewString
) == FALSE
)
2572 return DISP_E_TYPEMISMATCH
;
2575 /* Convert the valid string to a floating point number.
2577 dValue
= atof( pNewString
);
2579 /* We don't need the string anymore so free it.
2581 HeapFree( GetProcessHeap(), 0, pNewString
);
2583 /* Check range of value.
2585 dValue
= round( dValue
);
2586 if( dValue
< I4_MIN
|| dValue
> I4_MAX
)
2588 return DISP_E_OVERFLOW
;
2591 *plOut
= (LONG
) dValue
;
2596 /**********************************************************************
2597 * VarI4FromCy32 [OLEAUT32.62]
2598 * Convert currency to signed long
2600 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
* plOut
) {
2601 double t
= round((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
2603 if (t
> I4_MAX
|| t
< I4_MIN
) return DISP_E_OVERFLOW
;
2609 /******************************************************************************
2610 * VarR4FromUI132 [OLEAUT32.68]
2612 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, FLOAT
* pfltOut
)
2614 TRACE( ole
, "( %X, %p ), stub\n", bIn
, pfltOut
);
2616 *pfltOut
= (FLOAT
) bIn
;
2621 /******************************************************************************
2622 * VarR4FromI232 [OLEAUT32.69]
2624 HRESULT WINAPI
VarR4FromI2(short sIn
, FLOAT
* pfltOut
)
2626 TRACE( ole
, "( %d, %p ), stub\n", sIn
, pfltOut
);
2628 *pfltOut
= (FLOAT
) sIn
;
2633 /******************************************************************************
2634 * VarR4FromI432 [OLEAUT32.70]
2636 HRESULT WINAPI
VarR4FromI4(LONG lIn
, FLOAT
* pfltOut
)
2638 TRACE( ole
, "( %lx, %p ), stub\n", lIn
, pfltOut
);
2640 *pfltOut
= (FLOAT
) lIn
;
2645 /******************************************************************************
2646 * VarR4FromR832 [OLEAUT32.71]
2648 HRESULT WINAPI
VarR4FromR8(double dblIn
, FLOAT
* pfltOut
)
2650 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, pfltOut
);
2652 /* Check range of value.
2654 if( dblIn
< -(FLT_MAX
) || dblIn
> FLT_MAX
)
2656 return DISP_E_OVERFLOW
;
2659 *pfltOut
= (FLOAT
) dblIn
;
2664 /******************************************************************************
2665 * VarR4FromDate32 [OLEAUT32.73]
2667 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, FLOAT
* pfltOut
)
2669 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, pfltOut
);
2671 /* Check range of value.
2673 if( dateIn
< -(FLT_MAX
) || dateIn
> FLT_MAX
)
2675 return DISP_E_OVERFLOW
;
2678 *pfltOut
= (FLOAT
) dateIn
;
2683 /******************************************************************************
2684 * VarR4FromBool32 [OLEAUT32.76]
2686 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, FLOAT
* pfltOut
)
2688 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, pfltOut
);
2690 *pfltOut
= (FLOAT
) boolIn
;
2695 /******************************************************************************
2696 * VarR4FromI132 [OLEAUT32.213]
2698 HRESULT WINAPI
VarR4FromI1(CHAR cIn
, FLOAT
* pfltOut
)
2700 TRACE( ole
, "( %c, %p ), stub\n", cIn
, pfltOut
);
2702 *pfltOut
= (FLOAT
) cIn
;
2707 /******************************************************************************
2708 * VarR4FromUI232 [OLEAUT32.214]
2710 HRESULT WINAPI
VarR4FromUI2(USHORT uiIn
, FLOAT
* pfltOut
)
2712 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pfltOut
);
2714 *pfltOut
= (FLOAT
) uiIn
;
2719 /******************************************************************************
2720 * VarR4FromUI432 [OLEAUT32.215]
2722 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, FLOAT
* pfltOut
)
2724 TRACE( ole
, "( %ld, %p ), stub\n", ulIn
, pfltOut
);
2726 *pfltOut
= (FLOAT
) ulIn
;
2731 /******************************************************************************
2732 * VarR4FromStr32 [OLEAUT32.74]
2734 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, FLOAT
* pfltOut
)
2736 double dValue
= 0.0;
2737 LPSTR pNewString
= NULL
;
2739 TRACE( ole
, "( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pfltOut
);
2741 /* Check if we have a valid argument
2743 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2744 RemoveCharacterFromString( pNewString
, "," );
2745 if( IsValidRealString( pNewString
) == FALSE
)
2747 return DISP_E_TYPEMISMATCH
;
2750 /* Convert the valid string to a floating point number.
2752 dValue
= atof( pNewString
);
2754 /* We don't need the string anymore so free it.
2756 HeapFree( GetProcessHeap(), 0, pNewString
);
2758 /* Check range of value.
2760 if( dValue
< -(FLT_MAX
) || dValue
> FLT_MAX
)
2762 return DISP_E_OVERFLOW
;
2765 *pfltOut
= (FLOAT
) dValue
;
2770 /**********************************************************************
2771 * VarR4FromCy32 [OLEAUT32.72]
2772 * Convert currency to float
2774 HRESULT WINAPI
VarR4FromCy(CY cyIn
, FLOAT
* pfltOut
) {
2775 *pfltOut
= (FLOAT
)((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
2780 /******************************************************************************
2781 * VarR8FromUI132 [OLEAUT32.68]
2783 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double* pdblOut
)
2785 TRACE( ole
, "( %d, %p ), stub\n", bIn
, pdblOut
);
2787 *pdblOut
= (double) bIn
;
2792 /******************************************************************************
2793 * VarR8FromI232 [OLEAUT32.69]
2795 HRESULT WINAPI
VarR8FromI2(short sIn
, double* pdblOut
)
2797 TRACE( ole
, "( %d, %p ), stub\n", sIn
, pdblOut
);
2799 *pdblOut
= (double) sIn
;
2804 /******************************************************************************
2805 * VarR8FromI432 [OLEAUT32.70]
2807 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double* pdblOut
)
2809 TRACE( ole
, "( %ld, %p ), stub\n", lIn
, pdblOut
);
2811 *pdblOut
= (double) lIn
;
2816 /******************************************************************************
2817 * VarR8FromR432 [OLEAUT32.81]
2819 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double* pdblOut
)
2821 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, pdblOut
);
2823 *pdblOut
= (double) fltIn
;
2828 /******************************************************************************
2829 * VarR8FromDate32 [OLEAUT32.83]
2831 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double* pdblOut
)
2833 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, pdblOut
);
2835 *pdblOut
= (double) dateIn
;
2840 /******************************************************************************
2841 * VarR8FromBool32 [OLEAUT32.86]
2843 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double* pdblOut
)
2845 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, pdblOut
);
2847 *pdblOut
= (double) boolIn
;
2852 /******************************************************************************
2853 * VarR8FromI132 [OLEAUT32.217]
2855 HRESULT WINAPI
VarR8FromI1(CHAR cIn
, double* pdblOut
)
2857 TRACE( ole
, "( %c, %p ), stub\n", cIn
, pdblOut
);
2859 *pdblOut
= (double) cIn
;
2864 /******************************************************************************
2865 * VarR8FromUI232 [OLEAUT32.218]
2867 HRESULT WINAPI
VarR8FromUI2(USHORT uiIn
, double* pdblOut
)
2869 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pdblOut
);
2871 *pdblOut
= (double) uiIn
;
2876 /******************************************************************************
2877 * VarR8FromUI432 [OLEAUT32.219]
2879 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double* pdblOut
)
2881 TRACE( ole
, "( %ld, %p ), stub\n", ulIn
, pdblOut
);
2883 *pdblOut
= (double) ulIn
;
2888 /******************************************************************************
2889 * VarR8FromStr32 [OLEAUT32.84]
2891 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double* pdblOut
)
2893 double dValue
= 0.0;
2894 LPSTR pNewString
= NULL
;
2896 TRACE( ole
, "( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pdblOut
);
2898 /* Check if we have a valid argument
2900 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2901 RemoveCharacterFromString( pNewString
, "," );
2902 if( IsValidRealString( pNewString
) == FALSE
)
2904 return DISP_E_TYPEMISMATCH
;
2907 /* Convert the valid string to a floating point number.
2909 dValue
= atof( pNewString
);
2911 /* We don't need the string anymore so free it.
2913 HeapFree( GetProcessHeap(), 0, pNewString
);
2920 /**********************************************************************
2921 * VarR8FromCy32 [OLEAUT32.82]
2922 * Convert currency to double
2924 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double* pdblOut
) {
2925 *pdblOut
= (double)((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
2930 /******************************************************************************
2931 * VarDateFromUI132 [OLEAUT32.]
2933 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
2935 TRACE( ole
, "( %d, %p ), stub\n", bIn
, pdateOut
);
2937 *pdateOut
= (DATE
) bIn
;
2942 /******************************************************************************
2943 * VarDateFromI232 [OLEAUT32.222]
2945 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
2947 TRACE( ole
, "( %d, %p ), stub\n", sIn
, pdateOut
);
2949 *pdateOut
= (DATE
) sIn
;
2954 /******************************************************************************
2955 * VarDateFromI432 [OLEAUT32.90]
2957 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
2959 TRACE( ole
, "( %ld, %p ), stub\n", lIn
, pdateOut
);
2961 if( lIn
< DATE_MIN
|| lIn
> DATE_MAX
)
2963 return DISP_E_OVERFLOW
;
2966 *pdateOut
= (DATE
) lIn
;
2971 /******************************************************************************
2972 * VarDateFromR432 [OLEAUT32.91]
2974 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
2976 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, pdateOut
);
2978 if( ceil(fltIn
) < DATE_MIN
|| floor(fltIn
) > DATE_MAX
)
2980 return DISP_E_OVERFLOW
;
2983 *pdateOut
= (DATE
) fltIn
;
2988 /******************************************************************************
2989 * VarDateFromR832 [OLEAUT32.92]
2991 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
2993 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, pdateOut
);
2995 if( ceil(dblIn
) < DATE_MIN
|| floor(dblIn
) > DATE_MAX
)
2997 return DISP_E_OVERFLOW
;
3000 *pdateOut
= (DATE
) dblIn
;
3005 /******************************************************************************
3006 * VarDateFromStr32 [OLEAUT32.94]
3007 * The string representing the date is composed of two parts, a date and time.
3009 * The format of the time is has follows:
3010 * hh[:mm][:ss][AM|PM]
3011 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3012 * of space and/or tab characters, which are ignored.
3014 * The formats for the date part are has follows:
3018 * January dd[,] [yy]yy
3021 * Whitespace can be inserted anywhere between these tokens.
3023 * The formats for the date and time string are has follows.
3024 * date[whitespace][time]
3025 * [time][whitespace]date
3027 * These are the only characters allowed in a string representing a date and time:
3028 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3030 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
3033 struct tm TM
= { 0,0,0,0,0,0,0,0,0 };
3035 TRACE( ole
, "( %p, %lx, %lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pdateOut
);
3037 if( DateTimeStringToTm( strIn
, lcid
, &TM
) )
3039 if( TmToDATE( &TM
, pdateOut
) == FALSE
)
3046 ret
= DISP_E_TYPEMISMATCH
;
3053 /******************************************************************************
3054 * VarDateFromI132 [OLEAUT32.221]
3056 HRESULT WINAPI
VarDateFromI1(CHAR cIn
, DATE
* pdateOut
)
3058 TRACE( ole
, "( %c, %p ), stub\n", cIn
, pdateOut
);
3060 *pdateOut
= (DATE
) cIn
;
3065 /******************************************************************************
3066 * VarDateFromUI232 [OLEAUT32.222]
3068 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
3070 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pdateOut
);
3072 if( uiIn
> DATE_MAX
)
3074 return DISP_E_OVERFLOW
;
3077 *pdateOut
= (DATE
) uiIn
;
3082 /******************************************************************************
3083 * VarDateFromUI432 [OLEAUT32.223]
3085 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
3087 TRACE( ole
, "( %ld, %p ), stub\n", ulIn
, pdateOut
);
3089 if( ulIn
< DATE_MIN
|| ulIn
> DATE_MAX
)
3091 return DISP_E_OVERFLOW
;
3094 *pdateOut
= (DATE
) ulIn
;
3099 /******************************************************************************
3100 * VarDateFromBool32 [OLEAUT32.96]
3102 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
3104 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, pdateOut
);
3106 *pdateOut
= (DATE
) boolIn
;
3111 /**********************************************************************
3112 * VarDateFromCy32 [OLEAUT32.93]
3113 * Convert currency to date
3115 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
) {
3116 *pdateOut
= (DATE
)((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
3118 if (*pdateOut
> DATE_MAX
|| *pdateOut
< DATE_MIN
) return DISP_E_TYPEMISMATCH
;
3122 /******************************************************************************
3123 * VarBstrFromUI132 [OLEAUT32.108]
3125 HRESULT WINAPI
VarBstrFromUI1(BYTE bVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3127 TRACE( ole
, "( %d, %ld, %ld, %p ), stub\n", bVal
, lcid
, dwFlags
, pbstrOut
);
3128 sprintf( pBuffer
, "%d", bVal
);
3130 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3135 /******************************************************************************
3136 * VarBstrFromI232 [OLEAUT32.109]
3138 HRESULT WINAPI
VarBstrFromI2(short iVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3140 TRACE( ole
, "( %d, %ld, %ld, %p ), stub\n", iVal
, lcid
, dwFlags
, pbstrOut
);
3141 sprintf( pBuffer
, "%d", iVal
);
3142 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3147 /******************************************************************************
3148 * VarBstrFromI432 [OLEAUT32.110]
3150 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3152 TRACE( ole
, "( %ld, %ld, %ld, %p ), stub\n", lIn
, lcid
, dwFlags
, pbstrOut
);
3154 sprintf( pBuffer
, "%ld", lIn
);
3155 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3160 /******************************************************************************
3161 * VarBstrFromR432 [OLEAUT32.111]
3163 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3165 TRACE( ole
, "( %f, %ld, %ld, %p ), stub\n", fltIn
, lcid
, dwFlags
, pbstrOut
);
3167 sprintf( pBuffer
, "%.7g", fltIn
);
3168 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3173 /******************************************************************************
3174 * VarBstrFromR832 [OLEAUT32.112]
3176 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3178 TRACE( ole
, "( %f, %ld, %ld, %p ), stub\n", dblIn
, lcid
, dwFlags
, pbstrOut
);
3180 sprintf( pBuffer
, "%.15g", dblIn
);
3181 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3186 /******************************************************************************
3187 * VarBstrFromDate32 [OLEAUT32.114]
3189 * The date is implemented using an 8 byte floating-point number.
3190 * Days are represented by whole numbers increments starting with 0.00 has
3191 * being December 30 1899, midnight.
3192 * The hours are expressed as the fractional part of the number.
3193 * December 30 1899 at midnight = 0.00
3194 * January 1 1900 at midnight = 2.00
3195 * January 4 1900 at 6 AM = 5.25
3196 * January 4 1900 at noon = 5.50
3197 * December 29 1899 at midnight = -1.00
3198 * December 18 1899 at midnight = -12.00
3199 * December 18 1899 at 6AM = -12.25
3200 * December 18 1899 at 6PM = -12.75
3201 * December 19 1899 at midnight = -11.00
3202 * The tm structure is as follows:
3204 * int tm_sec; seconds after the minute - [0,59]
3205 * int tm_min; minutes after the hour - [0,59]
3206 * int tm_hour; hours since midnight - [0,23]
3207 * int tm_mday; day of the month - [1,31]
3208 * int tm_mon; months since January - [0,11]
3209 * int tm_year; years
3210 * int tm_wday; days since Sunday - [0,6]
3211 * int tm_yday; days since January 1 - [0,365]
3212 * int tm_isdst; daylight savings time flag
3215 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3217 struct tm TM
= {0,0,0,0,0,0,0,0,0};
3219 TRACE( ole
, "( %f, %ld, %ld, %p ), stub\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
3221 if( DateToTm( dateIn
, lcid
, &TM
) == FALSE
)
3223 return E_INVALIDARG
;
3226 if( lcid
& VAR_DATEVALUEONLY
)
3227 strftime( pBuffer
, BUFFER_MAX
, "%x", &TM
);
3228 else if( lcid
& VAR_TIMEVALUEONLY
)
3229 strftime( pBuffer
, BUFFER_MAX
, "%X", &TM
);
3231 strftime( pBuffer
, BUFFER_MAX
, "%x %X", &TM
);
3233 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3238 /******************************************************************************
3239 * VarBstrFromBool32 [OLEAUT32.116]
3241 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3243 TRACE( ole
, "( %d, %ld, %ld, %p ), stub\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
3245 if( boolIn
== VARIANT_FALSE
)
3247 sprintf( pBuffer
, "False" );
3251 sprintf( pBuffer
, "True" );
3254 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3259 /******************************************************************************
3260 * VarBstrFromI132 [OLEAUT32.229]
3262 HRESULT WINAPI
VarBstrFromI1(CHAR cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3264 TRACE( ole
, "( %c, %ld, %ld, %p ), stub\n", cIn
, lcid
, dwFlags
, pbstrOut
);
3265 sprintf( pBuffer
, "%d", cIn
);
3266 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3271 /******************************************************************************
3272 * VarBstrFromUI232 [OLEAUT32.230]
3274 HRESULT WINAPI
VarBstrFromUI2(USHORT uiIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3276 TRACE( ole
, "( %d, %ld, %ld, %p ), stub\n", uiIn
, lcid
, dwFlags
, pbstrOut
);
3277 sprintf( pBuffer
, "%d", uiIn
);
3278 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3283 /******************************************************************************
3284 * VarBstrFromUI432 [OLEAUT32.231]
3286 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3288 TRACE( ole
, "( %ld, %ld, %ld, %p ), stub\n", ulIn
, lcid
, dwFlags
, pbstrOut
);
3289 sprintf( pBuffer
, "%ld", ulIn
);
3290 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3295 /******************************************************************************
3296 * VarBoolFromUI132 [OLEAUT32.118]
3298 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
* pboolOut
)
3300 TRACE( ole
, "( %d, %p ), stub\n", bIn
, pboolOut
);
3304 *pboolOut
= VARIANT_FALSE
;
3308 *pboolOut
= VARIANT_TRUE
;
3314 /******************************************************************************
3315 * VarBoolFromI232 [OLEAUT32.119]
3317 HRESULT WINAPI
VarBoolFromI2(short sIn
, VARIANT_BOOL
* pboolOut
)
3319 TRACE( ole
, "( %d, %p ), stub\n", sIn
, pboolOut
);
3323 *pboolOut
= VARIANT_FALSE
;
3327 *pboolOut
= VARIANT_TRUE
;
3333 /******************************************************************************
3334 * VarBoolFromI432 [OLEAUT32.120]
3336 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
* pboolOut
)
3338 TRACE( ole
, "( %ld, %p ), stub\n", lIn
, pboolOut
);
3342 *pboolOut
= VARIANT_FALSE
;
3346 *pboolOut
= VARIANT_TRUE
;
3352 /******************************************************************************
3353 * VarBoolFromR432 [OLEAUT32.121]
3355 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
* pboolOut
)
3357 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, pboolOut
);
3361 *pboolOut
= VARIANT_FALSE
;
3365 *pboolOut
= VARIANT_TRUE
;
3371 /******************************************************************************
3372 * VarBoolFromR832 [OLEAUT32.122]
3374 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
* pboolOut
)
3376 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, pboolOut
);
3380 *pboolOut
= VARIANT_FALSE
;
3384 *pboolOut
= VARIANT_TRUE
;
3390 /******************************************************************************
3391 * VarBoolFromDate32 [OLEAUT32.123]
3393 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
* pboolOut
)
3395 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, pboolOut
);
3399 *pboolOut
= VARIANT_FALSE
;
3403 *pboolOut
= VARIANT_TRUE
;
3409 /******************************************************************************
3410 * VarBoolFromStr32 [OLEAUT32.125]
3412 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
* pboolOut
)
3415 char* pNewString
= NULL
;
3417 TRACE( ole
, "( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pboolOut
);
3419 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3421 if( pNewString
== NULL
|| strlen( pNewString
) == 0 )
3423 ret
= DISP_E_TYPEMISMATCH
;
3428 if( strncasecmp( pNewString
, "True", strlen( pNewString
) ) == 0 )
3430 *pboolOut
= VARIANT_TRUE
;
3432 else if( strncasecmp( pNewString
, "False", strlen( pNewString
) ) == 0 )
3434 *pboolOut
= VARIANT_FALSE
;
3438 /* Try converting the string to a floating point number.
3440 double dValue
= 0.0;
3441 HRESULT res
= VarR8FromStr( strIn
, lcid
, dwFlags
, &dValue
);
3444 ret
= DISP_E_TYPEMISMATCH
;
3446 else if( dValue
== 0.0 )
3448 *pboolOut
= VARIANT_FALSE
;
3452 *pboolOut
= VARIANT_TRUE
;
3457 HeapFree( GetProcessHeap(), 0, pNewString
);
3462 /******************************************************************************
3463 * VarBoolFromI132 [OLEAUT32.233]
3465 HRESULT WINAPI
VarBoolFromI1(CHAR cIn
, VARIANT_BOOL
* pboolOut
)
3467 TRACE( ole
, "( %c, %p ), stub\n", cIn
, pboolOut
);
3471 *pboolOut
= VARIANT_FALSE
;
3475 *pboolOut
= VARIANT_TRUE
;
3481 /******************************************************************************
3482 * VarBoolFromUI232 [OLEAUT32.234]
3484 HRESULT WINAPI
VarBoolFromUI2(USHORT uiIn
, VARIANT_BOOL
* pboolOut
)
3486 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pboolOut
);
3490 *pboolOut
= VARIANT_FALSE
;
3494 *pboolOut
= VARIANT_TRUE
;
3500 /******************************************************************************
3501 * VarBoolFromUI432 [OLEAUT32.235]
3503 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
* pboolOut
)
3505 TRACE( ole
, "( %ld, %p ), stub\n", ulIn
, pboolOut
);
3509 *pboolOut
= VARIANT_FALSE
;
3513 *pboolOut
= VARIANT_TRUE
;
3519 /**********************************************************************
3520 * VarBoolFromCy32 [OLEAUT32.124]
3521 * Convert currency to boolean
3523 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
* pboolOut
) {
3524 if (cyIn
.u
.Hi
|| cyIn
.u
.Lo
) *pboolOut
= -1;
3530 /******************************************************************************
3531 * VarI1FromUI132 [OLEAUT32.244]
3533 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, CHAR
* pcOut
)
3535 TRACE( ole
, "( %d, %p ), stub\n", bIn
, pcOut
);
3537 /* Check range of value.
3539 if( bIn
> CHAR_MAX
)
3541 return DISP_E_OVERFLOW
;
3544 *pcOut
= (CHAR
) bIn
;
3549 /******************************************************************************
3550 * VarI1FromI232 [OLEAUT32.245]
3552 HRESULT WINAPI
VarI1FromI2(short uiIn
, CHAR
* pcOut
)
3554 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pcOut
);
3556 if( uiIn
> CHAR_MAX
)
3558 return DISP_E_OVERFLOW
;
3561 *pcOut
= (CHAR
) uiIn
;
3566 /******************************************************************************
3567 * VarI1FromI432 [OLEAUT32.246]
3569 HRESULT WINAPI
VarI1FromI4(LONG lIn
, CHAR
* pcOut
)
3571 TRACE( ole
, "( %ld, %p ), stub\n", lIn
, pcOut
);
3573 if( lIn
< CHAR_MIN
|| lIn
> CHAR_MAX
)
3575 return DISP_E_OVERFLOW
;
3578 *pcOut
= (CHAR
) lIn
;
3583 /******************************************************************************
3584 * VarI1FromR432 [OLEAUT32.247]
3586 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, CHAR
* pcOut
)
3588 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, pcOut
);
3590 fltIn
= round( fltIn
);
3591 if( fltIn
< CHAR_MIN
|| fltIn
> CHAR_MAX
)
3593 return DISP_E_OVERFLOW
;
3596 *pcOut
= (CHAR
) fltIn
;
3601 /******************************************************************************
3602 * VarI1FromR832 [OLEAUT32.248]
3604 HRESULT WINAPI
VarI1FromR8(double dblIn
, CHAR
* pcOut
)
3606 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, pcOut
);
3608 dblIn
= round( dblIn
);
3609 if( dblIn
< CHAR_MIN
|| dblIn
> CHAR_MAX
)
3611 return DISP_E_OVERFLOW
;
3614 *pcOut
= (CHAR
) dblIn
;
3619 /******************************************************************************
3620 * VarI1FromDate32 [OLEAUT32.249]
3622 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, CHAR
* pcOut
)
3624 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, pcOut
);
3626 dateIn
= round( dateIn
);
3627 if( dateIn
< CHAR_MIN
|| dateIn
> CHAR_MAX
)
3629 return DISP_E_OVERFLOW
;
3632 *pcOut
= (CHAR
) dateIn
;
3637 /******************************************************************************
3638 * VarI1FromStr32 [OLEAUT32.251]
3640 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CHAR
* pcOut
)
3642 double dValue
= 0.0;
3643 LPSTR pNewString
= NULL
;
3645 TRACE( ole
, "( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pcOut
);
3647 /* Check if we have a valid argument
3649 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3650 RemoveCharacterFromString( pNewString
, "," );
3651 if( IsValidRealString( pNewString
) == FALSE
)
3653 return DISP_E_TYPEMISMATCH
;
3656 /* Convert the valid string to a floating point number.
3658 dValue
= atof( pNewString
);
3660 /* We don't need the string anymore so free it.
3662 HeapFree( GetProcessHeap(), 0, pNewString
);
3664 /* Check range of value.
3666 dValue
= round( dValue
);
3667 if( dValue
< CHAR_MIN
|| dValue
> CHAR_MAX
)
3669 return DISP_E_OVERFLOW
;
3672 *pcOut
= (CHAR
) dValue
;
3677 /******************************************************************************
3678 * VarI1FromBool32 [OLEAUT32.253]
3680 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, CHAR
* pcOut
)
3682 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, pcOut
);
3684 *pcOut
= (CHAR
) boolIn
;
3689 /******************************************************************************
3690 * VarI1FromUI232 [OLEAUT32.254]
3692 HRESULT WINAPI
VarI1FromUI2(USHORT uiIn
, CHAR
* pcOut
)
3694 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pcOut
);
3696 if( uiIn
> CHAR_MAX
)
3698 return DISP_E_OVERFLOW
;
3701 *pcOut
= (CHAR
) uiIn
;
3706 /******************************************************************************
3707 * VarI1FromUI432 [OLEAUT32.255]
3709 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, CHAR
* pcOut
)
3711 TRACE( ole
, "( %ld, %p ), stub\n", ulIn
, pcOut
);
3713 if( ulIn
> CHAR_MAX
)
3715 return DISP_E_OVERFLOW
;
3718 *pcOut
= (CHAR
) ulIn
;
3723 /**********************************************************************
3724 * VarI1FromCy32 [OLEAUT32.250]
3725 * Convert currency to signed char
3727 HRESULT WINAPI
VarI1FromCy(CY cyIn
, CHAR
* pcOut
) {
3728 double t
= round((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
3730 if (t
> CHAR_MAX
|| t
< CHAR_MIN
) return DISP_E_OVERFLOW
;
3736 /******************************************************************************
3737 * VarUI2FromUI132 [OLEAUT32.257]
3739 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* puiOut
)
3741 TRACE( ole
, "( %d, %p ), stub\n", bIn
, puiOut
);
3743 *puiOut
= (USHORT
) bIn
;
3748 /******************************************************************************
3749 * VarUI2FromI232 [OLEAUT32.258]
3751 HRESULT WINAPI
VarUI2FromI2(short uiIn
, USHORT
* puiOut
)
3753 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, puiOut
);
3755 if( uiIn
< UI2_MIN
)
3757 return DISP_E_OVERFLOW
;
3760 *puiOut
= (USHORT
) uiIn
;
3765 /******************************************************************************
3766 * VarUI2FromI432 [OLEAUT32.259]
3768 HRESULT WINAPI
VarUI2FromI4(LONG lIn
, USHORT
* puiOut
)
3770 TRACE( ole
, "( %ld, %p ), stub\n", lIn
, puiOut
);
3772 if( lIn
< UI2_MIN
|| lIn
> UI2_MAX
)
3774 return DISP_E_OVERFLOW
;
3777 *puiOut
= (USHORT
) lIn
;
3782 /******************************************************************************
3783 * VarUI2FromR432 [OLEAUT32.260]
3785 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* puiOut
)
3787 TRACE( ole
, "( %f, %p ), stub\n", fltIn
, puiOut
);
3789 fltIn
= round( fltIn
);
3790 if( fltIn
< UI2_MIN
|| fltIn
> UI2_MAX
)
3792 return DISP_E_OVERFLOW
;
3795 *puiOut
= (USHORT
) fltIn
;
3800 /******************************************************************************
3801 * VarUI2FromR832 [OLEAUT32.261]
3803 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* puiOut
)
3805 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, puiOut
);
3807 dblIn
= round( dblIn
);
3808 if( dblIn
< UI2_MIN
|| dblIn
> UI2_MAX
)
3810 return DISP_E_OVERFLOW
;
3813 *puiOut
= (USHORT
) dblIn
;
3818 /******************************************************************************
3819 * VarUI2FromDate32 [OLEAUT32.262]
3821 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* puiOut
)
3823 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, puiOut
);
3825 dateIn
= round( dateIn
);
3826 if( dateIn
< UI2_MIN
|| dateIn
> UI2_MAX
)
3828 return DISP_E_OVERFLOW
;
3831 *puiOut
= (USHORT
) dateIn
;
3836 /******************************************************************************
3837 * VarUI2FromStr32 [OLEAUT32.264]
3839 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* puiOut
)
3841 double dValue
= 0.0;
3842 LPSTR pNewString
= NULL
;
3844 TRACE( ole
, "( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, puiOut
);
3846 /* Check if we have a valid argument
3848 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3849 RemoveCharacterFromString( pNewString
, "," );
3850 if( IsValidRealString( pNewString
) == FALSE
)
3852 return DISP_E_TYPEMISMATCH
;
3855 /* Convert the valid string to a floating point number.
3857 dValue
= atof( pNewString
);
3859 /* We don't need the string anymore so free it.
3861 HeapFree( GetProcessHeap(), 0, pNewString
);
3863 /* Check range of value.
3865 dValue
= round( dValue
);
3866 if( dValue
< UI2_MIN
|| dValue
> UI2_MAX
)
3868 return DISP_E_OVERFLOW
;
3871 *puiOut
= (USHORT
) dValue
;
3876 /******************************************************************************
3877 * VarUI2FromBool32 [OLEAUT32.266]
3879 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* puiOut
)
3881 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, puiOut
);
3883 *puiOut
= (USHORT
) boolIn
;
3888 /******************************************************************************
3889 * VarUI2FromI132 [OLEAUT32.267]
3891 HRESULT WINAPI
VarUI2FromI1(CHAR cIn
, USHORT
* puiOut
)
3893 TRACE( ole
, "( %c, %p ), stub\n", cIn
, puiOut
);
3895 *puiOut
= (USHORT
) cIn
;
3900 /******************************************************************************
3901 * VarUI2FromUI432 [OLEAUT32.268]
3903 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* puiOut
)
3905 TRACE( ole
, "( %ld, %p ), stub\n", ulIn
, puiOut
);
3907 if( ulIn
< UI2_MIN
|| ulIn
> UI2_MAX
)
3909 return DISP_E_OVERFLOW
;
3912 *puiOut
= (USHORT
) ulIn
;
3917 /******************************************************************************
3918 * VarUI4FromStr32 [OLEAUT32.277]
3920 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
* pulOut
)
3922 double dValue
= 0.0;
3923 LPSTR pNewString
= NULL
;
3925 TRACE( ole
, "( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pulOut
);
3927 /* Check if we have a valid argument
3929 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3930 RemoveCharacterFromString( pNewString
, "," );
3931 if( IsValidRealString( pNewString
) == FALSE
)
3933 return DISP_E_TYPEMISMATCH
;
3936 /* Convert the valid string to a floating point number.
3938 dValue
= atof( pNewString
);
3940 /* We don't need the string anymore so free it.
3942 HeapFree( GetProcessHeap(), 0, pNewString
);
3944 /* Check range of value.
3946 dValue
= round( dValue
);
3947 if( dValue
< UI4_MIN
|| dValue
> UI4_MAX
)
3949 return DISP_E_OVERFLOW
;
3952 *pulOut
= (ULONG
) dValue
;
3957 /**********************************************************************
3958 * VarUI2FromCy32 [OLEAUT32.263]
3959 * Convert currency to unsigned short
3961 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
) {
3962 double t
= round((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
3964 if (t
> UI2_MAX
|| t
< UI2_MIN
) return DISP_E_OVERFLOW
;
3966 *pusOut
= (USHORT
)t
;
3971 /******************************************************************************
3972 * VarUI4FromUI132 [OLEAUT32.270]
3974 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
* pulOut
)
3976 TRACE( ole
, "( %d, %p ), stub\n", bIn
, pulOut
);
3978 *pulOut
= (USHORT
) bIn
;
3983 /******************************************************************************
3984 * VarUI4FromI232 [OLEAUT32.271]
3986 HRESULT WINAPI
VarUI4FromI2(short uiIn
, ULONG
* pulOut
)
3988 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pulOut
);
3990 if( uiIn
< UI4_MIN
)
3992 return DISP_E_OVERFLOW
;
3995 *pulOut
= (ULONG
) uiIn
;
4000 /******************************************************************************
4001 * VarUI4FromI432 [OLEAUT32.272]
4003 HRESULT WINAPI
VarUI4FromI4(LONG lIn
, ULONG
* pulOut
)
4005 TRACE( ole
, "( %ld, %p ), stub\n", lIn
, pulOut
);
4009 return DISP_E_OVERFLOW
;
4012 *pulOut
= (ULONG
) lIn
;
4017 /******************************************************************************
4018 * VarUI4FromR432 [OLEAUT32.273]
4020 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
* pulOut
)
4022 fltIn
= round( fltIn
);
4023 if( fltIn
< UI4_MIN
|| fltIn
> UI4_MAX
)
4025 return DISP_E_OVERFLOW
;
4028 *pulOut
= (ULONG
) fltIn
;
4033 /******************************************************************************
4034 * VarUI4FromR832 [OLEAUT32.274]
4036 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
* pulOut
)
4038 TRACE( ole
, "( %f, %p ), stub\n", dblIn
, pulOut
);
4040 dblIn
= round( dblIn
);
4041 if( dblIn
< UI4_MIN
|| dblIn
> UI4_MAX
)
4043 return DISP_E_OVERFLOW
;
4046 *pulOut
= (ULONG
) dblIn
;
4051 /******************************************************************************
4052 * VarUI4FromDate32 [OLEAUT32.275]
4054 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
* pulOut
)
4056 TRACE( ole
, "( %f, %p ), stub\n", dateIn
, pulOut
);
4058 dateIn
= round( dateIn
);
4059 if( dateIn
< UI4_MIN
|| dateIn
> UI4_MAX
)
4061 return DISP_E_OVERFLOW
;
4064 *pulOut
= (ULONG
) dateIn
;
4069 /******************************************************************************
4070 * VarUI4FromBool32 [OLEAUT32.279]
4072 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
* pulOut
)
4074 TRACE( ole
, "( %d, %p ), stub\n", boolIn
, pulOut
);
4076 *pulOut
= (ULONG
) boolIn
;
4081 /******************************************************************************
4082 * VarUI4FromI132 [OLEAUT32.280]
4084 HRESULT WINAPI
VarUI4FromI1(CHAR cIn
, ULONG
* pulOut
)
4086 TRACE( ole
, "( %c, %p ), stub\n", cIn
, pulOut
);
4088 *pulOut
= (ULONG
) cIn
;
4093 /******************************************************************************
4094 * VarUI4FromUI232 [OLEAUT32.281]
4096 HRESULT WINAPI
VarUI4FromUI2(USHORT uiIn
, ULONG
* pulOut
)
4098 TRACE( ole
, "( %d, %p ), stub\n", uiIn
, pulOut
);
4100 *pulOut
= (ULONG
) uiIn
;
4105 /**********************************************************************
4106 * VarUI4FromCy32 [OLEAUT32.276]
4107 * Convert currency to unsigned long
4109 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
* pulOut
) {
4110 double t
= round((((double)cyIn
.u
.Hi
* 4294967296.0) + (double)cyIn
.u
.Lo
) / 10000);
4112 if (t
> UI4_MAX
|| t
< UI4_MIN
) return DISP_E_OVERFLOW
;
4119 /**********************************************************************
4120 * VarCyFromUI132 [OLEAUT32.98]
4121 * Convert unsigned char to currency
4123 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pcyOut
) {
4125 pcyOut
->u
.Lo
= ((ULONG
)bIn
) * 10000;
4130 /**********************************************************************
4131 * VarCyFromI232 [OLEAUT32.99]
4132 * Convert signed short to currency
4134 HRESULT WINAPI
VarCyFromI2(short sIn
, CY
* pcyOut
) {
4135 if (sIn
< 0) pcyOut
->u
.Hi
= -1;
4136 else pcyOut
->u
.Hi
= 0;
4137 pcyOut
->u
.Lo
= ((ULONG
)sIn
) * 10000;
4142 /**********************************************************************
4143 * VarCyFromI432 [OLEAUT32.100]
4144 * Convert signed long to currency
4146 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pcyOut
) {
4147 double t
= (double)lIn
* (double)10000;
4148 pcyOut
->u
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4149 pcyOut
->u
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4150 if (lIn
< 0) pcyOut
->u
.Hi
--;
4155 /**********************************************************************
4156 * VarCyFromR432 [OLEAUT32.101]
4157 * Convert float to currency
4159 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pcyOut
) {
4160 double t
= round((double)fltIn
* (double)10000);
4161 pcyOut
->u
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4162 pcyOut
->u
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4163 if (fltIn
< 0) pcyOut
->u
.Hi
--;
4168 /**********************************************************************
4169 * VarCyFromR832 [OLEAUT32.102]
4170 * Convert double to currency
4172 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pcyOut
) {
4173 double t
= round(dblIn
* (double)10000);
4174 pcyOut
->u
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4175 pcyOut
->u
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4176 if (dblIn
< 0) pcyOut
->u
.Hi
--;
4181 /**********************************************************************
4182 * VarCyFromDate32 [OLEAUT32.103]
4183 * Convert date to currency
4185 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pcyOut
) {
4186 double t
= round((double)dateIn
* (double)10000);
4187 pcyOut
->u
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4188 pcyOut
->u
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4189 if (dateIn
< 0) pcyOut
->u
.Hi
--;
4194 /**********************************************************************
4195 * VarCyFromBool32 [OLEAUT32.106]
4196 * Convert boolean to currency
4198 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pcyOut
) {
4199 if (boolIn
< 0) pcyOut
->u
.Hi
= -1;
4200 else pcyOut
->u
.Hi
= 0;
4201 pcyOut
->u
.Lo
= (ULONG
)boolIn
* (ULONG
)10000;
4206 /**********************************************************************
4207 * VarCyFromI132 [OLEAUT32.225]
4208 * Convert signed char to currency
4210 HRESULT WINAPI
VarCyFromI1(CHAR cIn
, CY
* pcyOut
) {
4211 if (cIn
< 0) pcyOut
->u
.Hi
= -1;
4212 else pcyOut
->u
.Hi
= 0;
4213 pcyOut
->u
.Lo
= (ULONG
)cIn
* (ULONG
)10000;
4218 /**********************************************************************
4219 * VarCyFromUI232 [OLEAUT32.226]
4220 * Convert unsigned short to currency
4222 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pcyOut
) {
4224 pcyOut
->u
.Lo
= (ULONG
)usIn
* (ULONG
)10000;
4229 /**********************************************************************
4230 * VarCyFromUI432 [OLEAUT32.227]
4231 * Convert unsigned long to currency
4233 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pcyOut
) {
4234 double t
= (double)ulIn
* (double)10000;
4235 pcyOut
->u
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4236 pcyOut
->u
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);