4 * Copyright 1998 Jean-Claude Cote
7 * This implements the low-level and hi-level APIs for manipulating VARIANTs.
8 * The low-level APIs are used to do data coercion between different data types.
9 * The hi-level APIs are built on top of these low-level APIs and handle
10 * initialization, copying, destroying and changing the type of VARIANTs.
13 * - The Variant APIs do not support international languages, currency
14 * types, number formating and calendar. They only support U.S. English format.
15 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
16 * The prototypes for these are commented out in the oleauto.h file. They need
17 * to be implemented and cases need to be added to the switches of the existing APIs.
18 * - The parsing of date for the VarDateFromStr is not complete.
19 * - The date manipulations do not support dates prior to 1900.
20 * - The parsing does not accept as many formats as the Windows implementation.
38 #include "debugtools.h"
42 DEFAULT_DEBUG_CHANNEL(ole
);
46 # define FLT_MAX MAXFLOAT
48 # error "Can't find #define for MAXFLOAT/FLT_MAX"
54 static const char CHAR_MAX
= 127;
55 static const char CHAR_MIN
= -128;
56 static const BYTE UI1_MAX
= 255;
57 static const BYTE UI1_MIN
= 0;
58 static const unsigned short UI2_MAX
= 65535;
59 static const unsigned short UI2_MIN
= 0;
60 static const short I2_MAX
= 32767;
61 static const short I2_MIN
= -32768;
62 static const unsigned long UI4_MAX
= 4294967295U;
63 static const unsigned long UI4_MIN
= 0;
64 static const long I4_MAX
= 2147483647;
65 static const long I4_MIN
= -(2147483648U);
66 static const DATE DATE_MIN
= -657434;
67 static const DATE DATE_MAX
= 2958465;
70 /* This mask is used to set a flag in wReserved1 of
71 * the VARIANTARG structure. The flag indicates if
72 * the API function is using an inner variant or not.
74 #define PROCESSING_INNER_VARIANT 0x0001
76 /* General use buffer.
78 #define BUFFER_MAX 1024
79 static char pBuffer
[BUFFER_MAX
];
82 * Note a leap year is one that is a multiple of 4
83 * but not of a 100. Except if it is a multiple of
84 * 400 then it is a leap year.
86 /* According to postgeSQL date parsing functions there is
87 * a leap year when this expression is true.
88 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
89 * So according to this there is 365.2515 days in one year.
90 * One + every four years: 1/4 -> 365.25
91 * One - every 100 years: 1/100 -> 365.01
92 * One + every 400 years: 1/400 -> 365.0025
94 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
96 * ^^ Might this be the key to an easy way to factor large prime numbers?
97 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
99 static const double DAYS_IN_ONE_YEAR
= 365.2425;
101 /******************************************************************************
102 * DateTimeStringToTm [INTERNAL]
104 * Converts a string representation of a date and/or time to a tm structure.
106 * Note this function uses the postgresql date parsing functions found
107 * in the parsedt.c file.
109 * Returns TRUE if successful.
111 * Note: This function does not parse the day of the week,
112 * daylight savings time. It will only fill the followin fields in
113 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
115 ******************************************************************************/
116 static BOOL
DateTimeStringToTm( OLECHAR
* strIn
, LCID lcid
, struct tm
* pTm
)
123 char *field
[MAXDATEFIELDS
];
124 int ftype
[MAXDATEFIELDS
];
125 char lowstr
[MAXDATELEN
+ 1];
126 char* strDateTime
= NULL
;
128 /* Convert the string to ASCII since this is the only format
129 * postgesql can handle.
131 strDateTime
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
133 if( strDateTime
!= NULL
)
135 /* Make sure we don't go over the maximum length
136 * accepted by postgesql.
138 if( strlen( strDateTime
) <= MAXDATELEN
)
140 if( ParseDateTime( strDateTime
, lowstr
, field
, ftype
, MAXDATEFIELDS
, &nf
) == 0 )
142 if( lcid
& VAR_DATEVALUEONLY
)
144 /* Get the date information.
145 * It returns 0 if date information was
146 * present and 1 if only time information was present.
147 * -1 if an error occures.
149 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) == 0 )
151 /* Eliminate the time information since we
152 * were asked to get date information only.
160 if( lcid
& VAR_TIMEVALUEONLY
)
162 /* Get time information only.
164 if( DecodeTimeOnly(field
, ftype
, nf
, &dtype
, pTm
, &fsec
) == 0 )
171 /* Get both date and time information.
172 * It returns 0 if date information was
173 * present and 1 if only time information was present.
174 * -1 if an error occures.
176 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) != -1 )
183 HeapFree( GetProcessHeap(), 0, strDateTime
);
194 /******************************************************************************
195 * TmToDATE [INTERNAL]
197 * The date is implemented using an 8 byte floating-point number.
198 * Days are represented by whole numbers increments starting with 0.00 has
199 * being December 30 1899, midnight.
200 * The hours are expressed as the fractional part of the number.
201 * December 30 1899 at midnight = 0.00
202 * January 1 1900 at midnight = 2.00
203 * January 4 1900 at 6 AM = 5.25
204 * January 4 1900 at noon = 5.50
205 * December 29 1899 at midnight = -1.00
206 * December 18 1899 at midnight = -12.00
207 * December 18 1899 at 6AM = -12.25
208 * December 18 1899 at 6PM = -12.75
209 * December 19 1899 at midnight = -11.00
210 * The tm structure is as follows:
212 * int tm_sec; seconds after the minute - [0,59]
213 * int tm_min; minutes after the hour - [0,59]
214 * int tm_hour; hours since midnight - [0,23]
215 * int tm_mday; day of the month - [1,31]
216 * int tm_mon; months since January - [0,11]
218 * int tm_wday; days since Sunday - [0,6]
219 * int tm_yday; days since January 1 - [0,365]
220 * int tm_isdst; daylight savings time flag
223 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
224 * and tm_isdst fields of the tm structure. And only converts years
227 * Returns TRUE if successful.
229 static BOOL
TmToDATE( struct tm
* pTm
, DATE
*pDateOut
)
231 if( (pTm
->tm_year
- 1900) >= 0 )
235 /* Start at 1. This is the way DATE is defined.
236 * January 1, 1900 at Midnight is 1.00.
237 * January 1, 1900 at 6AM is 1.25.
242 /* Add the number of days corresponding to
245 *pDateOut
+= (pTm
->tm_year
- 1900) * 365;
247 /* Add the leap days in the previous years between now and 1900.
248 * Note a leap year is one that is a multiple of 4
249 * but not of a 100. Except if it is a multiple of
250 * 400 then it is a leap year.
252 *pDateOut
+= ( (pTm
->tm_year
- 1) / 4 ) - ( 1900 / 4 );
253 *pDateOut
-= ( (pTm
->tm_year
- 1) / 100 ) - ( 1900 / 100 );
254 *pDateOut
+= ( (pTm
->tm_year
- 1) / 400 ) - ( 1900 / 400 );
256 /* Set the leap year flag if the
257 * current year specified by tm_year is a
258 * leap year. This will be used to add a day
261 if( isleap( pTm
->tm_year
) )
264 /* Add the number of days corresponding to
267 switch( pTm
->tm_mon
)
273 *pDateOut
+= ( 59 + leapYear
);
276 *pDateOut
+= ( 90 + leapYear
);
279 *pDateOut
+= ( 120 + leapYear
);
282 *pDateOut
+= ( 151 + leapYear
);
285 *pDateOut
+= ( 181 + leapYear
);
288 *pDateOut
+= ( 212 + leapYear
);
291 *pDateOut
+= ( 243 + leapYear
);
294 *pDateOut
+= ( 273 + leapYear
);
297 *pDateOut
+= ( 304 + leapYear
);
300 *pDateOut
+= ( 334 + leapYear
);
303 /* Add the number of days in this month.
305 *pDateOut
+= pTm
->tm_mday
;
307 /* Add the number of seconds, minutes, and hours
308 * to the DATE. Note these are the fracionnal part
309 * of the DATE so seconds / number of seconds in a day.
311 *pDateOut
+= pTm
->tm_hour
/ 24.0;
312 *pDateOut
+= pTm
->tm_min
/ 1440.0;
313 *pDateOut
+= pTm
->tm_sec
/ 86400.0;
319 /******************************************************************************
320 * DateToTm [INTERNAL]
322 * This function converts a windows DATE to a tm structure.
324 * It does not fill all the fields of the tm structure.
325 * Here is a list of the fields that are filled:
326 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
328 * Note this function does not support dates before the January 1, 1900
329 * or ( dateIn < 2.0 ).
331 * Returns TRUE if successful.
333 static BOOL
DateToTm( DATE dateIn
, LCID lcid
, struct tm
* pTm
)
335 /* Do not process dates smaller than January 1, 1900.
336 * Which corresponds to 2.0 in the windows DATE format.
340 double decimalPart
= 0.0;
341 double wholePart
= 0.0;
343 memset(pTm
,0,sizeof(*pTm
));
345 /* Because of the nature of DATE format which
346 * associates 2.0 to January 1, 1900. We will
347 * remove 1.0 from the whole part of the DATE
348 * so that in the following code 1.0
349 * will correspond to January 1, 1900.
350 * This simplifies the processing of the DATE value.
354 wholePart
= (double) floor( dateIn
);
355 decimalPart
= fmod( dateIn
, wholePart
);
357 if( !(lcid
& VAR_TIMEVALUEONLY
) )
361 double yearsSince1900
= 0;
362 /* Start at 1900, this is where the DATE time 0.0 starts.
365 /* find in what year the day in the "wholePart" falls into.
366 * add the value to the year field.
368 yearsSince1900
= floor( (wholePart
/ DAYS_IN_ONE_YEAR
) + 0.001 );
369 pTm
->tm_year
+= yearsSince1900
;
370 /* determine if this is a leap year.
372 if( isleap( pTm
->tm_year
) )
378 /* find what day of that year the "wholePart" corresponds to.
379 * Note: nDay is in [1-366] format
381 nDay
= (int) ( wholePart
- floor( yearsSince1900
* DAYS_IN_ONE_YEAR
) );
382 /* Set the tm_yday value.
383 * Note: The day must be converted from [1-366] to [0-365]
385 /*pTm->tm_yday = nDay - 1;*/
386 /* find which mount this day corresponds to.
393 else if( nDay
<= ( 59 + leapYear
) )
395 pTm
->tm_mday
= nDay
- 31;
398 else if( nDay
<= ( 90 + leapYear
) )
400 pTm
->tm_mday
= nDay
- ( 59 + leapYear
);
403 else if( nDay
<= ( 120 + leapYear
) )
405 pTm
->tm_mday
= nDay
- ( 90 + leapYear
);
408 else if( nDay
<= ( 151 + leapYear
) )
410 pTm
->tm_mday
= nDay
- ( 120 + leapYear
);
413 else if( nDay
<= ( 181 + leapYear
) )
415 pTm
->tm_mday
= nDay
- ( 151 + leapYear
);
418 else if( nDay
<= ( 212 + leapYear
) )
420 pTm
->tm_mday
= nDay
- ( 181 + leapYear
);
423 else if( nDay
<= ( 243 + leapYear
) )
425 pTm
->tm_mday
= nDay
- ( 212 + leapYear
);
428 else if( nDay
<= ( 273 + leapYear
) )
430 pTm
->tm_mday
= nDay
- ( 243 + leapYear
);
433 else if( nDay
<= ( 304 + leapYear
) )
435 pTm
->tm_mday
= nDay
- ( 273 + leapYear
);
438 else if( nDay
<= ( 334 + leapYear
) )
440 pTm
->tm_mday
= nDay
- ( 304 + leapYear
);
443 else if( nDay
<= ( 365 + leapYear
) )
445 pTm
->tm_mday
= nDay
- ( 334 + leapYear
);
449 if( !(lcid
& VAR_DATEVALUEONLY
) )
451 /* find the number of seconds in this day.
452 * fractional part times, hours, minutes, seconds.
454 pTm
->tm_hour
= (int) ( decimalPart
* 24 );
455 pTm
->tm_min
= (int) ( ( ( decimalPart
* 24 ) - pTm
->tm_hour
) * 60 );
456 pTm
->tm_sec
= (int) ( ( ( decimalPart
* 24 * 60 ) - ( pTm
->tm_hour
* 60 ) - pTm
->tm_min
) * 60 );
465 /******************************************************************************
466 * SizeOfVariantData [INTERNAL]
468 * This function finds the size of the data referenced by a Variant based
469 * the type "vt" of the Variant.
471 static int SizeOfVariantData( VARIANT
* parg
)
474 switch( parg
->vt
& VT_TYPEMASK
)
477 size
= sizeof(short);
489 size
= sizeof(unsigned short);
492 size
= sizeof(unsigned int);
495 size
= sizeof(unsigned long);
498 size
= sizeof(float);
501 size
= sizeof(double);
507 size
= sizeof(VARIANT_BOOL
);
510 size
= sizeof(void*);
517 FIXME("Add size information for type vt=%d\n", parg
->vt
& VT_TYPEMASK
);
523 /******************************************************************************
524 * StringDupAtoBstr [INTERNAL]
527 static BSTR
StringDupAtoBstr( char* strIn
)
530 OLECHAR
* pNewString
= NULL
;
531 pNewString
= HEAP_strdupAtoW( GetProcessHeap(), 0, strIn
);
532 bstr
= SysAllocString( pNewString
);
533 HeapFree( GetProcessHeap(), 0, pNewString
);
537 /******************************************************************************
540 * Round the double value to the nearest integer value.
542 static double round( double d
)
544 double decimals
= 0.0, integerValue
= 0.0, roundedValue
= 0.0;
545 BOOL bEvenNumber
= FALSE
;
548 /* Save the sign of the number
550 nSign
= (d
>= 0.0) ? 1 : -1;
553 /* Remove the decimals.
555 integerValue
= floor( d
);
557 /* Set the Even flag. This is used to round the number when
558 * the decimals are exactly 1/2. If the integer part is
559 * odd the number is rounded up. If the integer part
560 * is even the number is rounded down. Using this method
561 * numbers are rounded up|down half the time.
563 bEvenNumber
= (((short)fmod(integerValue
, 2)) == 0) ? TRUE
: FALSE
;
565 /* Remove the integral part of the number.
567 decimals
= d
- integerValue
;
569 /* Note: Ceil returns the smallest integer that is greater that x.
570 * and floor returns the largest integer that is less than or equal to x.
574 /* If the decimal part is greater than 1/2
576 roundedValue
= ceil( d
);
578 else if( decimals
< 0.5 )
580 /* If the decimal part is smaller than 1/2
582 roundedValue
= floor( d
);
586 /* the decimals are exactly 1/2 so round according to
587 * the bEvenNumber flag.
591 roundedValue
= floor( d
);
595 roundedValue
= ceil( d
);
599 return roundedValue
* nSign
;
602 /******************************************************************************
603 * RemoveCharacterFromString [INTERNAL]
605 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
607 static void RemoveCharacterFromString( LPSTR str
, LPSTR strOfCharToRemove
)
609 LPSTR pNewString
= NULL
;
610 LPSTR strToken
= NULL
;
613 /* Check if we have a valid argument
617 pNewString
= strdup( str
);
619 strToken
= strtok( pNewString
, strOfCharToRemove
);
620 while( strToken
!= NULL
) {
621 strcat( str
, strToken
);
622 strToken
= strtok( NULL
, strOfCharToRemove
);
629 /******************************************************************************
630 * GetValidRealString [INTERNAL]
632 * Checks if the string is of proper format to be converted to a real value.
634 static BOOL
IsValidRealString( LPSTR strRealString
)
636 /* Real values that have a decimal point are required to either have
637 * digits before or after the decimal point. We will assume that
638 * we do not have any digits at either position. If we do encounter
639 * some we will disable this flag.
641 BOOL bDigitsRequired
= TRUE
;
642 /* Processed fields in the string representation of the real number.
644 BOOL bWhiteSpaceProcessed
= FALSE
;
645 BOOL bFirstSignProcessed
= FALSE
;
646 BOOL bFirstDigitsProcessed
= FALSE
;
647 BOOL bDecimalPointProcessed
= FALSE
;
648 BOOL bSecondDigitsProcessed
= FALSE
;
649 BOOL bExponentProcessed
= FALSE
;
650 BOOL bSecondSignProcessed
= FALSE
;
651 BOOL bThirdDigitsProcessed
= FALSE
;
652 /* Assume string parameter "strRealString" is valid and try to disprove it.
654 BOOL bValidRealString
= TRUE
;
656 /* Used to count the number of tokens in the "strRealString".
658 LPSTR strToken
= NULL
;
662 /* Check if we have a valid argument
664 if( strRealString
== NULL
)
666 bValidRealString
= FALSE
;
669 if( bValidRealString
== TRUE
)
671 /* Make sure we only have ONE token in the string.
673 strToken
= strtok( strRealString
, " " );
674 while( strToken
!= NULL
) {
676 strToken
= strtok( NULL
, " " );
681 bValidRealString
= FALSE
;
686 /* Make sure this token contains only valid characters.
687 * The string argument to atof has the following form:
688 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
689 * Whitespace consists of space and|or <TAB> characters, which are ignored.
690 * Sign is either plus '+' or minus '-'.
691 * Digits are one or more decimal digits.
692 * Note: If no digits appear before the decimal point, at least one must
693 * appear after the decimal point.
694 * The decimal digits may be followed by an exponent.
695 * An Exponent consists of an introductory letter ( D, d, E, or e) and
696 * an optionally signed decimal integer.
698 pChar
= strRealString
;
699 while( bValidRealString
== TRUE
&& *pChar
!= '\0' )
707 if( bWhiteSpaceProcessed
||
708 bFirstSignProcessed
||
709 bFirstDigitsProcessed
||
710 bDecimalPointProcessed
||
711 bSecondDigitsProcessed
||
712 bExponentProcessed
||
713 bSecondSignProcessed
||
714 bThirdDigitsProcessed
)
716 bValidRealString
= FALSE
;
723 if( bFirstSignProcessed
== FALSE
)
725 if( bFirstDigitsProcessed
||
726 bDecimalPointProcessed
||
727 bSecondDigitsProcessed
||
728 bExponentProcessed
||
729 bSecondSignProcessed
||
730 bThirdDigitsProcessed
)
732 bValidRealString
= FALSE
;
734 bWhiteSpaceProcessed
= TRUE
;
735 bFirstSignProcessed
= TRUE
;
737 else if( bSecondSignProcessed
== FALSE
)
739 /* Note: The exponent must be present in
740 * order to accept the second sign...
742 if( bExponentProcessed
== FALSE
||
743 bThirdDigitsProcessed
||
746 bValidRealString
= FALSE
;
748 bFirstSignProcessed
= TRUE
;
749 bWhiteSpaceProcessed
= TRUE
;
750 bFirstDigitsProcessed
= TRUE
;
751 bDecimalPointProcessed
= TRUE
;
752 bSecondDigitsProcessed
= TRUE
;
753 bSecondSignProcessed
= TRUE
;
769 if( bFirstDigitsProcessed
== FALSE
)
771 if( bDecimalPointProcessed
||
772 bSecondDigitsProcessed
||
773 bExponentProcessed
||
774 bSecondSignProcessed
||
775 bThirdDigitsProcessed
)
777 bValidRealString
= FALSE
;
779 bFirstSignProcessed
= TRUE
;
780 bWhiteSpaceProcessed
= TRUE
;
781 /* We have found some digits before the decimal point
782 * so disable the "Digits required" flag.
784 bDigitsRequired
= FALSE
;
786 else if( bSecondDigitsProcessed
== FALSE
)
788 if( bExponentProcessed
||
789 bSecondSignProcessed
||
790 bThirdDigitsProcessed
)
792 bValidRealString
= FALSE
;
794 bFirstSignProcessed
= TRUE
;
795 bWhiteSpaceProcessed
= TRUE
;
796 bFirstDigitsProcessed
= TRUE
;
797 bDecimalPointProcessed
= TRUE
;
798 /* We have found some digits after the decimal point
799 * so disable the "Digits required" flag.
801 bDigitsRequired
= FALSE
;
803 else if( bThirdDigitsProcessed
== FALSE
)
805 /* Getting here means everything else should be processed.
806 * If we get anything else than a decimal following this
807 * digit it will be flagged by the other cases, so
808 * we do not really need to do anything in here.
812 /* If DecimalPoint...
815 if( bDecimalPointProcessed
||
816 bSecondDigitsProcessed
||
817 bExponentProcessed
||
818 bSecondSignProcessed
||
819 bThirdDigitsProcessed
)
821 bValidRealString
= FALSE
;
823 bFirstSignProcessed
= TRUE
;
824 bWhiteSpaceProcessed
= TRUE
;
825 bFirstDigitsProcessed
= TRUE
;
826 bDecimalPointProcessed
= TRUE
;
834 if( bExponentProcessed
||
835 bSecondSignProcessed
||
836 bThirdDigitsProcessed
||
839 bValidRealString
= FALSE
;
841 bFirstSignProcessed
= TRUE
;
842 bWhiteSpaceProcessed
= TRUE
;
843 bFirstDigitsProcessed
= TRUE
;
844 bDecimalPointProcessed
= TRUE
;
845 bSecondDigitsProcessed
= TRUE
;
846 bExponentProcessed
= TRUE
;
849 bValidRealString
= FALSE
;
852 /* Process next character.
857 /* If the required digits were not present we have an invalid
858 * string representation of a real number.
860 if( bDigitsRequired
== TRUE
)
862 bValidRealString
= FALSE
;
865 return bValidRealString
;
869 /******************************************************************************
872 * This function dispatches execution to the proper conversion API
873 * to do the necessary coercion.
875 static HRESULT
Coerce( VARIANTARG
* pd
, LCID lcid
, ULONG dwFlags
, VARIANTARG
* ps
, VARTYPE vt
)
878 unsigned short vtFrom
= 0;
879 vtFrom
= ps
->vt
& VT_TYPEMASK
;
881 /* Note: Since "long" and "int" values both have 4 bytes and are
882 * both signed integers "int" will be treated as "long" in the
884 * The same goes for their unsigned versions.
887 /* Trivial Case: If the coercion is from two types that are
888 * identical then we can blindly copy from one argument to another.*/
891 return VariantCopy(pd
,ps
);
894 /* Cases requiring thought*/
899 res
= VariantClear( pd
);
902 res
= VariantClear( pd
);
912 res
= VariantCopy( pd
, ps
);
915 res
= VarI1FromI2( ps
->u
.iVal
, &(pd
->u
.cVal
) );
919 res
= VarI1FromI4( ps
->u
.lVal
, &(pd
->u
.cVal
) );
922 res
= VarI1FromUI1( ps
->u
.bVal
, &(pd
->u
.cVal
) );
925 res
= VarI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.cVal
) );
929 res
= VarI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.cVal
) );
932 res
= VarI1FromR4( ps
->u
.fltVal
, &(pd
->u
.cVal
) );
935 res
= VarI1FromR8( ps
->u
.dblVal
, &(pd
->u
.cVal
) );
938 res
= VarI1FromDate( ps
->u
.date
, &(pd
->u
.cVal
) );
941 res
= VarI1FromBool( ps
->u
.boolVal
, &(pd
->u
.cVal
) );
944 res
= VarI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.cVal
) );
947 res
= VarI1FromCy( ps
->u
.cyVal
, &(pd
->u
.cVal
) );
949 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
951 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
953 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
955 res
= DISP_E_TYPEMISMATCH
;
956 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
965 res
= VarI2FromI1( ps
->u
.cVal
, &(pd
->u
.iVal
) );
968 res
= VariantCopy( pd
, ps
);
972 res
= VarI2FromI4( ps
->u
.lVal
, &(pd
->u
.iVal
) );
975 res
= VarI2FromUI1( ps
->u
.bVal
, &(pd
->u
.iVal
) );
978 res
= VarI2FromUI2( ps
->u
.uiVal
, &(pd
->u
.iVal
) );
982 res
= VarI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.iVal
) );
985 res
= VarI2FromR4( ps
->u
.fltVal
, &(pd
->u
.iVal
) );
988 res
= VarI2FromR8( ps
->u
.dblVal
, &(pd
->u
.iVal
) );
991 res
= VarI2FromDate( ps
->u
.date
, &(pd
->u
.iVal
) );
994 res
= VarI2FromBool( ps
->u
.boolVal
, &(pd
->u
.iVal
) );
997 res
= VarI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.iVal
) );
1000 res
= VarI2FromCy( ps
->u
.cyVal
, &(pd
->u
.iVal
) );
1001 case( VT_DISPATCH
):
1002 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1004 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
1006 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
1008 res
= DISP_E_TYPEMISMATCH
;
1009 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1019 res
= VarI4FromI1( ps
->u
.cVal
, &(pd
->u
.lVal
) );
1022 res
= VarI4FromI2( ps
->u
.iVal
, &(pd
->u
.lVal
) );
1026 res
= VariantCopy( pd
, ps
);
1029 res
= VarI4FromUI1( ps
->u
.bVal
, &(pd
->u
.lVal
) );
1032 res
= VarI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.lVal
) );
1036 res
= VarI4FromUI4( ps
->u
.ulVal
, &(pd
->u
.lVal
) );
1039 res
= VarI4FromR4( ps
->u
.fltVal
, &(pd
->u
.lVal
) );
1042 res
= VarI4FromR8( ps
->u
.dblVal
, &(pd
->u
.lVal
) );
1045 res
= VarI4FromDate( ps
->u
.date
, &(pd
->u
.lVal
) );
1048 res
= VarI4FromBool( ps
->u
.boolVal
, &(pd
->u
.lVal
) );
1051 res
= VarI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.lVal
) );
1054 res
= VarI4FromCy( ps
->u
.cyVal
, &(pd
->u
.lVal
) );
1055 case( VT_DISPATCH
):
1056 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1058 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1060 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1062 res
= DISP_E_TYPEMISMATCH
;
1063 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1072 res
= VarUI1FromI1( ps
->u
.cVal
, &(pd
->u
.bVal
) );
1075 res
= VarUI1FromI2( ps
->u
.iVal
, &(pd
->u
.bVal
) );
1079 res
= VarUI1FromI4( ps
->u
.lVal
, &(pd
->u
.bVal
) );
1082 res
= VariantCopy( pd
, ps
);
1085 res
= VarUI1FromUI2( ps
->u
.uiVal
, &(pd
->u
.bVal
) );
1089 res
= VarUI1FromUI4( ps
->u
.ulVal
, &(pd
->u
.bVal
) );
1092 res
= VarUI1FromR4( ps
->u
.fltVal
, &(pd
->u
.bVal
) );
1095 res
= VarUI1FromR8( ps
->u
.dblVal
, &(pd
->u
.bVal
) );
1098 res
= VarUI1FromDate( ps
->u
.date
, &(pd
->u
.bVal
) );
1101 res
= VarUI1FromBool( ps
->u
.boolVal
, &(pd
->u
.bVal
) );
1104 res
= VarUI1FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.bVal
) );
1107 res
= VarUI1FromCy( ps
->u
.cyVal
, &(pd
->u
.bVal
) );
1108 case( VT_DISPATCH
):
1109 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1111 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1113 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1115 res
= DISP_E_TYPEMISMATCH
;
1116 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1125 res
= VarUI2FromI1( ps
->u
.cVal
, &(pd
->u
.uiVal
) );
1128 res
= VarUI2FromI2( ps
->u
.iVal
, &(pd
->u
.uiVal
) );
1132 res
= VarUI2FromI4( ps
->u
.lVal
, &(pd
->u
.uiVal
) );
1135 res
= VarUI2FromUI1( ps
->u
.bVal
, &(pd
->u
.uiVal
) );
1138 res
= VariantCopy( pd
, ps
);
1142 res
= VarUI2FromUI4( ps
->u
.ulVal
, &(pd
->u
.uiVal
) );
1145 res
= VarUI2FromR4( ps
->u
.fltVal
, &(pd
->u
.uiVal
) );
1148 res
= VarUI2FromR8( ps
->u
.dblVal
, &(pd
->u
.uiVal
) );
1151 res
= VarUI2FromDate( ps
->u
.date
, &(pd
->u
.uiVal
) );
1154 res
= VarUI2FromBool( ps
->u
.boolVal
, &(pd
->u
.uiVal
) );
1157 res
= VarUI2FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.uiVal
) );
1160 res
= VarUI2FromCy( ps
->u
.cyVal
, &(pd
->u
.uiVal
) );
1161 case( VT_DISPATCH
):
1162 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1164 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1166 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1168 res
= DISP_E_TYPEMISMATCH
;
1169 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1179 res
= VarUI4FromI1( ps
->u
.cVal
, &(pd
->u
.ulVal
) );
1182 res
= VarUI4FromI2( ps
->u
.iVal
, &(pd
->u
.ulVal
) );
1186 res
= VarUI4FromI4( ps
->u
.lVal
, &(pd
->u
.ulVal
) );
1189 res
= VarUI4FromUI1( ps
->u
.bVal
, &(pd
->u
.ulVal
) );
1192 res
= VarUI4FromUI2( ps
->u
.uiVal
, &(pd
->u
.ulVal
) );
1195 res
= VariantCopy( pd
, ps
);
1198 res
= VarUI4FromR4( ps
->u
.fltVal
, &(pd
->u
.ulVal
) );
1201 res
= VarUI4FromR8( ps
->u
.dblVal
, &(pd
->u
.ulVal
) );
1204 res
= VarUI4FromDate( ps
->u
.date
, &(pd
->u
.ulVal
) );
1207 res
= VarUI4FromBool( ps
->u
.boolVal
, &(pd
->u
.ulVal
) );
1210 res
= VarUI4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.ulVal
) );
1213 res
= VarUI4FromCy( ps
->u
.cyVal
, &(pd
->u
.ulVal
) );
1214 case( VT_DISPATCH
):
1215 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1217 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1219 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1221 res
= DISP_E_TYPEMISMATCH
;
1222 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1231 res
= VarR4FromI1( ps
->u
.cVal
, &(pd
->u
.fltVal
) );
1234 res
= VarR4FromI2( ps
->u
.iVal
, &(pd
->u
.fltVal
) );
1238 res
= VarR4FromI4( ps
->u
.lVal
, &(pd
->u
.fltVal
) );
1241 res
= VarR4FromUI1( ps
->u
.bVal
, &(pd
->u
.fltVal
) );
1244 res
= VarR4FromUI2( ps
->u
.uiVal
, &(pd
->u
.fltVal
) );
1248 res
= VarR4FromUI4( ps
->u
.ulVal
, &(pd
->u
.fltVal
) );
1251 res
= VariantCopy( pd
, ps
);
1254 res
= VarR4FromR8( ps
->u
.dblVal
, &(pd
->u
.fltVal
) );
1257 res
= VarR4FromDate( ps
->u
.date
, &(pd
->u
.fltVal
) );
1260 res
= VarR4FromBool( ps
->u
.boolVal
, &(pd
->u
.fltVal
) );
1263 res
= VarR4FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.fltVal
) );
1266 res
= VarR4FromCy( ps
->u
.cyVal
, &(pd
->u
.fltVal
) );
1267 case( VT_DISPATCH
):
1268 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1270 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1272 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1274 res
= DISP_E_TYPEMISMATCH
;
1275 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1284 res
= VarR8FromI1( ps
->u
.cVal
, &(pd
->u
.dblVal
) );
1287 res
= VarR8FromI2( ps
->u
.iVal
, &(pd
->u
.dblVal
) );
1291 res
= VarR8FromI4( ps
->u
.lVal
, &(pd
->u
.dblVal
) );
1294 res
= VarR8FromUI1( ps
->u
.bVal
, &(pd
->u
.dblVal
) );
1297 res
= VarR8FromUI2( ps
->u
.uiVal
, &(pd
->u
.dblVal
) );
1301 res
= VarR8FromUI4( ps
->u
.ulVal
, &(pd
->u
.dblVal
) );
1304 res
= VarR8FromR4( ps
->u
.fltVal
, &(pd
->u
.dblVal
) );
1307 res
= VariantCopy( pd
, ps
);
1310 res
= VarR8FromDate( ps
->u
.date
, &(pd
->u
.dblVal
) );
1313 res
= VarR8FromBool( ps
->u
.boolVal
, &(pd
->u
.dblVal
) );
1316 res
= VarR8FromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.dblVal
) );
1319 res
= VarR8FromCy( ps
->u
.cyVal
, &(pd
->u
.dblVal
) );
1320 case( VT_DISPATCH
):
1321 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1323 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1325 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1327 res
= DISP_E_TYPEMISMATCH
;
1328 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1337 res
= VarDateFromI1( ps
->u
.cVal
, &(pd
->u
.date
) );
1340 res
= VarDateFromI2( ps
->u
.iVal
, &(pd
->u
.date
) );
1343 res
= VarDateFromInt( ps
->u
.intVal
, &(pd
->u
.date
) );
1346 res
= VarDateFromI4( ps
->u
.lVal
, &(pd
->u
.date
) );
1349 res
= VarDateFromUI1( ps
->u
.bVal
, &(pd
->u
.date
) );
1352 res
= VarDateFromUI2( ps
->u
.uiVal
, &(pd
->u
.date
) );
1355 res
= VarDateFromUint( ps
->u
.uintVal
, &(pd
->u
.date
) );
1358 res
= VarDateFromUI4( ps
->u
.ulVal
, &(pd
->u
.date
) );
1361 res
= VarDateFromR4( ps
->u
.fltVal
, &(pd
->u
.date
) );
1364 res
= VarDateFromR8( ps
->u
.dblVal
, &(pd
->u
.date
) );
1367 res
= VariantCopy( pd
, ps
);
1370 res
= VarDateFromBool( ps
->u
.boolVal
, &(pd
->u
.date
) );
1373 res
= VarDateFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.date
) );
1376 res
= VarDateFromCy( ps
->u
.cyVal
, &(pd
->u
.date
) );
1377 case( VT_DISPATCH
):
1378 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1380 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1382 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1384 res
= DISP_E_TYPEMISMATCH
;
1385 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1394 res
= VarBoolFromI1( ps
->u
.cVal
, &(pd
->u
.boolVal
) );
1397 res
= VarBoolFromI2( ps
->u
.iVal
, &(pd
->u
.boolVal
) );
1400 res
= VarBoolFromInt( ps
->u
.intVal
, &(pd
->u
.boolVal
) );
1403 res
= VarBoolFromI4( ps
->u
.lVal
, &(pd
->u
.boolVal
) );
1406 res
= VarBoolFromUI1( ps
->u
.bVal
, &(pd
->u
.boolVal
) );
1409 res
= VarBoolFromUI2( ps
->u
.uiVal
, &(pd
->u
.boolVal
) );
1412 res
= VarBoolFromUint( ps
->u
.uintVal
, &(pd
->u
.boolVal
) );
1415 res
= VarBoolFromUI4( ps
->u
.ulVal
, &(pd
->u
.boolVal
) );
1418 res
= VarBoolFromR4( ps
->u
.fltVal
, &(pd
->u
.boolVal
) );
1421 res
= VarBoolFromR8( ps
->u
.dblVal
, &(pd
->u
.boolVal
) );
1424 res
= VarBoolFromDate( ps
->u
.date
, &(pd
->u
.boolVal
) );
1427 res
= VariantCopy( pd
, ps
);
1430 res
= VarBoolFromStr( ps
->u
.bstrVal
, lcid
, dwFlags
, &(pd
->u
.boolVal
) );
1433 res
= VarBoolFromCy( ps
->u
.cyVal
, &(pd
->u
.boolVal
) );
1434 case( VT_DISPATCH
):
1435 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1437 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1439 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1441 res
= DISP_E_TYPEMISMATCH
;
1442 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1451 if ((pd
->u
.bstrVal
= SysAllocStringLen(NULL
, 0)))
1454 res
= E_OUTOFMEMORY
;
1457 res
= VarBstrFromI1( ps
->u
.cVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1460 res
= VarBstrFromI2( ps
->u
.iVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1463 res
= VarBstrFromInt( ps
->u
.intVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1466 res
= VarBstrFromI4( ps
->u
.lVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1469 res
= VarBstrFromUI1( ps
->u
.bVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1472 res
= VarBstrFromUI2( ps
->u
.uiVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1475 res
= VarBstrFromUint( ps
->u
.uintVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1478 res
= VarBstrFromUI4( ps
->u
.ulVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1481 res
= VarBstrFromR4( ps
->u
.fltVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1484 res
= VarBstrFromR8( ps
->u
.dblVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1487 res
= VarBstrFromDate( ps
->u
.date
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1490 res
= VarBstrFromBool( ps
->u
.boolVal
, lcid
, dwFlags
, &(pd
->u
.bstrVal
) );
1493 res
= VariantCopy( pd
, ps
);
1496 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1497 case( VT_DISPATCH
):
1498 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1500 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1502 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1504 res
= DISP_E_TYPEMISMATCH
;
1505 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1514 res
= VarCyFromI1( ps
->u
.cVal
, &(pd
->u
.cyVal
) );
1517 res
= VarCyFromI2( ps
->u
.iVal
, &(pd
->u
.cyVal
) );
1520 res
= VarCyFromInt( ps
->u
.intVal
, &(pd
->u
.cyVal
) );
1523 res
= VarCyFromI4( ps
->u
.lVal
, &(pd
->u
.cyVal
) );
1526 res
= VarCyFromUI1( ps
->u
.bVal
, &(pd
->u
.cyVal
) );
1529 res
= VarCyFromUI2( ps
->u
.uiVal
, &(pd
->u
.cyVal
) );
1532 res
= VarCyFromUint( ps
->u
.uintVal
, &(pd
->u
.cyVal
) );
1535 res
= VarCyFromUI4( ps
->u
.ulVal
, &(pd
->u
.cyVal
) );
1538 res
= VarCyFromR4( ps
->u
.fltVal
, &(pd
->u
.cyVal
) );
1541 res
= VarCyFromR8( ps
->u
.dblVal
, &(pd
->u
.cyVal
) );
1544 res
= VarCyFromDate( ps
->u
.date
, &(pd
->u
.cyVal
) );
1547 res
= VarCyFromBool( ps
->u
.date
, &(pd
->u
.cyVal
) );
1550 res
= VariantCopy( pd
, ps
);
1553 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1554 case( VT_DISPATCH
):
1555 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1557 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1559 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1561 res
= DISP_E_TYPEMISMATCH
;
1562 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1568 res
= DISP_E_TYPEMISMATCH
;
1569 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1576 /******************************************************************************
1577 * ValidateVtRange [INTERNAL]
1579 * Used internally by the hi-level Variant API to determine
1580 * if the vartypes are valid.
1582 static HRESULT WINAPI
ValidateVtRange( VARTYPE vt
)
1584 /* if by value we must make sure it is in the
1585 * range of the valid types.
1587 if( ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1589 return DISP_E_BADVARTYPE
;
1595 /******************************************************************************
1596 * ValidateVartype [INTERNAL]
1598 * Used internally by the hi-level Variant API to determine
1599 * if the vartypes are valid.
1601 static HRESULT WINAPI
ValidateVariantType( VARTYPE vt
)
1605 /* check if we have a valid argument.
1609 /* if by reference check that the type is in
1610 * the valid range and that it is not of empty or null type
1612 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1613 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1614 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1622 res
= ValidateVtRange( vt
);
1628 /******************************************************************************
1629 * ValidateVt [INTERNAL]
1631 * Used internally by the hi-level Variant API to determine
1632 * if the vartypes are valid.
1634 static HRESULT WINAPI
ValidateVt( VARTYPE vt
)
1638 /* check if we have a valid argument.
1642 /* if by reference check that the type is in
1643 * the valid range and that it is not of empty or null type
1645 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1646 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1647 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1649 res
= DISP_E_BADVARTYPE
;
1655 res
= ValidateVtRange( vt
);
1665 /******************************************************************************
1666 * VariantInit [OLEAUT32.8]
1668 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1669 * contents of the Variant.
1671 void WINAPI
VariantInit(VARIANTARG
* pvarg
)
1673 TRACE("(%p),stub\n",pvarg
);
1675 memset(pvarg
, 0, sizeof (VARIANTARG
));
1676 pvarg
->vt
= VT_EMPTY
;
1681 /******************************************************************************
1682 * VariantClear [OLEAUT32.9]
1684 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1685 * sets the wReservedX field to 0. The current contents of the VARIANT are
1686 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1687 * released. If VT_ARRAY the array is freed.
1689 HRESULT WINAPI
VariantClear(VARIANTARG
* pvarg
)
1692 TRACE("(%p)\n",pvarg
);
1694 res
= ValidateVariantType( pvarg
->vt
);
1697 if( !( pvarg
->vt
& VT_BYREF
) )
1700 * The VT_ARRAY flag is a special case of a safe array.
1702 if ( (pvarg
->vt
& VT_ARRAY
) != 0)
1704 SafeArrayDestroy(pvarg
->u
.parray
);
1708 switch( pvarg
->vt
& VT_TYPEMASK
)
1711 SysFreeString( pvarg
->u
.bstrVal
);
1713 case( VT_DISPATCH
):
1714 if(pvarg
->u
.pdispVal
!=NULL
)
1715 ICOM_CALL(Release
,pvarg
->u
.pdispVal
);
1718 VariantClear(pvarg
->u
.pvarVal
);
1721 if(pvarg
->u
.punkVal
!=NULL
)
1722 ICOM_CALL(Release
,pvarg
->u
.punkVal
);
1724 case( VT_SAFEARRAY
):
1725 SafeArrayDestroy(pvarg
->u
.parray
);
1734 * Empty all the fields and mark the type as empty.
1736 memset(pvarg
, 0, sizeof (VARIANTARG
));
1737 pvarg
->vt
= VT_EMPTY
;
1743 /******************************************************************************
1744 * VariantCopy [OLEAUT32.10]
1746 * Frees up the designation variant and makes a copy of the source.
1748 HRESULT WINAPI
VariantCopy(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
)
1752 TRACE("(%p, %p)\n", pvargDest
, pvargSrc
);
1754 res
= ValidateVariantType( pvargSrc
->vt
);
1756 /* If the pointer are to the same variant we don't need
1759 if( pvargDest
!= pvargSrc
&& res
== S_OK
)
1761 res
= VariantClear( pvargDest
);
1765 if( pvargSrc
->vt
& VT_BYREF
)
1767 /* In the case of byreference we only need
1768 * to copy the pointer.
1770 pvargDest
->u
= pvargSrc
->u
;
1771 pvargDest
->vt
= pvargSrc
->vt
;
1776 * The VT_ARRAY flag is another way to designate a safe array.
1778 if (pvargSrc
->vt
& VT_ARRAY
)
1780 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1784 /* In the case of by value we need to
1785 * copy the actuall value. In the case of
1786 * VT_BSTR a copy of the string is made,
1787 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1788 * called to increment the object's reference count.
1790 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1793 pvargDest
->u
.bstrVal
= SysAllocString( pvargSrc
->u
.bstrVal
);
1795 case( VT_DISPATCH
):
1796 pvargDest
->u
.pdispVal
= pvargSrc
->u
.pdispVal
;
1797 if (pvargDest
->u
.pdispVal
!=NULL
)
1798 ICOM_CALL(AddRef
,pvargDest
->u
.pdispVal
);
1801 VariantCopy(pvargDest
->u
.pvarVal
,pvargSrc
->u
.pvarVal
);
1804 pvargDest
->u
.punkVal
= pvargSrc
->u
.punkVal
;
1805 if (pvargDest
->u
.pdispVal
!=NULL
)
1806 ICOM_CALL(AddRef
,pvargDest
->u
.punkVal
);
1808 case( VT_SAFEARRAY
):
1809 SafeArrayCopy(pvargSrc
->u
.parray
, &pvargDest
->u
.parray
);
1812 pvargDest
->u
= pvargSrc
->u
;
1817 pvargDest
->vt
= pvargSrc
->vt
;
1826 /******************************************************************************
1827 * VariantCopyInd [OLEAUT32.11]
1829 * Frees up the destination variant and makes a copy of the source. If
1830 * the source is of type VT_BYREF it performs the necessary indirections.
1832 HRESULT WINAPI
VariantCopyInd(VARIANT
* pvargDest
, VARIANTARG
* pvargSrc
)
1836 TRACE("(%p, %p)\n", pvargDest
, pvargSrc
);
1838 res
= ValidateVariantType( pvargSrc
->vt
);
1843 if( pvargSrc
->vt
& VT_BYREF
)
1846 VariantInit( &varg
);
1848 /* handle the in place copy.
1850 if( pvargDest
== pvargSrc
)
1852 /* we will use a copy of the source instead.
1854 res
= VariantCopy( &varg
, pvargSrc
);
1860 res
= VariantClear( pvargDest
);
1865 * The VT_ARRAY flag is another way to designate a safearray variant.
1867 if ( pvargSrc
->vt
& VT_ARRAY
)
1869 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1873 /* In the case of by reference we need
1874 * to copy the date pointed to by the variant.
1877 /* Get the variant type.
1879 switch( pvargSrc
->vt
& VT_TYPEMASK
)
1882 pvargDest
->u
.bstrVal
= SysAllocString( *(pvargSrc
->u
.pbstrVal
) );
1884 case( VT_DISPATCH
):
1888 /* Prevent from cycling. According to tests on
1889 * VariantCopyInd in Windows and the documentation
1890 * this API dereferences the inner Variants to only one depth.
1891 * If the inner Variant itself contains an
1892 * other inner variant the E_INVALIDARG error is
1895 if( pvargSrc
->wReserved1
& PROCESSING_INNER_VARIANT
)
1897 /* If we get here we are attempting to deference
1898 * an inner variant that that is itself contained
1899 * in an inner variant so report E_INVALIDARG error.
1905 /* Set the processing inner variant flag.
1906 * We will set this flag in the inner variant
1907 * that will be passed to the VariantCopyInd function.
1909 (pvargSrc
->u
.pvarVal
)->wReserved1
|= PROCESSING_INNER_VARIANT
;
1911 /* Dereference the inner variant.
1913 res
= VariantCopyInd( pvargDest
, pvargSrc
->u
.pvarVal
);
1914 /* We must also copy its type, I think.
1916 pvargSrc
->vt
= pvargSrc
->u
.pvarVal
->vt
;
1922 case( VT_SAFEARRAY
):
1923 SafeArrayCopy(*pvargSrc
->u
.pparray
, &pvargDest
->u
.parray
);
1926 /* This is a by reference Variant which means that the union
1927 * part of the Variant contains a pointer to some data of
1928 * type "pvargSrc->vt & VT_TYPEMASK".
1929 * We will deference this data in a generic fashion using
1930 * the void pointer "Variant.u.byref".
1931 * We will copy this data into the union of the destination
1934 memcpy( &pvargDest
->u
, pvargSrc
->u
.byref
, SizeOfVariantData( pvargSrc
) );
1939 pvargDest
->vt
= pvargSrc
->vt
& VT_TYPEMASK
;
1943 /* this should not fail.
1945 VariantClear( &varg
);
1949 res
= VariantCopy( pvargDest
, pvargSrc
);
1955 /******************************************************************************
1956 * VariantChangeType [OLEAUT32.12]
1958 HRESULT WINAPI
VariantChangeType(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1959 USHORT wFlags
, VARTYPE vt
)
1961 return VariantChangeTypeEx( pvargDest
, pvargSrc
, 0, wFlags
, vt
);
1964 /******************************************************************************
1965 * VariantChangeTypeEx [OLEAUT32.147]
1967 HRESULT WINAPI
VariantChangeTypeEx(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1968 LCID lcid
, USHORT wFlags
, VARTYPE vt
)
1972 VariantInit( &varg
);
1974 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest
, pvargSrc
, lcid
, wFlags
, vt
);
1976 /* validate our source argument.
1978 res
= ValidateVariantType( pvargSrc
->vt
);
1980 /* validate the vartype.
1984 res
= ValidateVt( vt
);
1987 /* if we are doing an in-place conversion make a copy of the source.
1989 if( res
== S_OK
&& pvargDest
== pvargSrc
)
1991 res
= VariantCopy( &varg
, pvargSrc
);
1997 /* free up the destination variant.
1999 res
= VariantClear( pvargDest
);
2004 if( pvargSrc
->vt
& VT_BYREF
)
2006 /* Convert the source variant to a "byvalue" variant.
2009 VariantInit( &Variant
);
2010 res
= VariantCopyInd( &Variant
, pvargSrc
);
2013 res
= Coerce( pvargDest
, lcid
, wFlags
, &Variant
, vt
);
2014 /* this should not fail.
2016 VariantClear( &Variant
);
2022 /* Use the current "byvalue" source variant.
2024 res
= Coerce( pvargDest
, lcid
, wFlags
, pvargSrc
, vt
);
2027 /* this should not fail.
2029 VariantClear( &varg
);
2031 /* set the type of the destination
2042 /******************************************************************************
2043 * VarUI1FromI2 [OLEAUT32.130]
2045 HRESULT WINAPI
VarUI1FromI2(short sIn
, BYTE
* pbOut
)
2047 TRACE("( %d, %p ), stub\n", sIn
, pbOut
);
2049 /* Check range of value.
2051 if( sIn
< UI1_MIN
|| sIn
> UI1_MAX
)
2053 return DISP_E_OVERFLOW
;
2056 *pbOut
= (BYTE
) sIn
;
2061 /******************************************************************************
2062 * VarUI1FromI4 [OLEAUT32.131]
2064 HRESULT WINAPI
VarUI1FromI4(LONG lIn
, BYTE
* pbOut
)
2066 TRACE("( %ld, %p ), stub\n", lIn
, pbOut
);
2068 /* Check range of value.
2070 if( lIn
< UI1_MIN
|| lIn
> UI1_MAX
)
2072 return DISP_E_OVERFLOW
;
2075 *pbOut
= (BYTE
) lIn
;
2081 /******************************************************************************
2082 * VarUI1FromR4 [OLEAUT32.132]
2084 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
2086 TRACE("( %f, %p ), stub\n", fltIn
, pbOut
);
2088 /* Check range of value.
2090 fltIn
= round( fltIn
);
2091 if( fltIn
< UI1_MIN
|| fltIn
> UI1_MAX
)
2093 return DISP_E_OVERFLOW
;
2096 *pbOut
= (BYTE
) fltIn
;
2101 /******************************************************************************
2102 * VarUI1FromR8 [OLEAUT32.133]
2104 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
2106 TRACE("( %f, %p ), stub\n", dblIn
, pbOut
);
2108 /* Check range of value.
2110 dblIn
= round( dblIn
);
2111 if( dblIn
< UI1_MIN
|| dblIn
> UI1_MAX
)
2113 return DISP_E_OVERFLOW
;
2116 *pbOut
= (BYTE
) dblIn
;
2121 /******************************************************************************
2122 * VarUI1FromDate [OLEAUT32.135]
2124 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
2126 TRACE("( %f, %p ), stub\n", dateIn
, pbOut
);
2128 /* Check range of value.
2130 dateIn
= round( dateIn
);
2131 if( dateIn
< UI1_MIN
|| dateIn
> UI1_MAX
)
2133 return DISP_E_OVERFLOW
;
2136 *pbOut
= (BYTE
) dateIn
;
2141 /******************************************************************************
2142 * VarUI1FromBool [OLEAUT32.138]
2144 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
2146 TRACE("( %d, %p ), stub\n", boolIn
, pbOut
);
2148 *pbOut
= (BYTE
) boolIn
;
2153 /******************************************************************************
2154 * VarUI1FromI1 [OLEAUT32.237]
2156 HRESULT WINAPI
VarUI1FromI1(CHAR cIn
, BYTE
* pbOut
)
2158 TRACE("( %c, %p ), stub\n", cIn
, pbOut
);
2165 /******************************************************************************
2166 * VarUI1FromUI2 [OLEAUT32.238]
2168 HRESULT WINAPI
VarUI1FromUI2(USHORT uiIn
, BYTE
* pbOut
)
2170 TRACE("( %d, %p ), stub\n", uiIn
, pbOut
);
2172 /* Check range of value.
2174 if( uiIn
> UI1_MAX
)
2176 return DISP_E_OVERFLOW
;
2179 *pbOut
= (BYTE
) uiIn
;
2184 /******************************************************************************
2185 * VarUI1FromUI4 [OLEAUT32.239]
2187 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
2189 TRACE("( %ld, %p ), stub\n", ulIn
, pbOut
);
2191 /* Check range of value.
2193 if( ulIn
> UI1_MAX
)
2195 return DISP_E_OVERFLOW
;
2198 *pbOut
= (BYTE
) ulIn
;
2204 /******************************************************************************
2205 * VarUI1FromStr [OLEAUT32.54]
2207 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
2209 double dValue
= 0.0;
2210 LPSTR pNewString
= NULL
;
2212 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pbOut
);
2214 /* Check if we have a valid argument
2216 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2217 RemoveCharacterFromString( pNewString
, "," );
2218 if( IsValidRealString( pNewString
) == FALSE
)
2220 return DISP_E_TYPEMISMATCH
;
2223 /* Convert the valid string to a floating point number.
2225 dValue
= atof( pNewString
);
2227 /* We don't need the string anymore so free it.
2229 HeapFree( GetProcessHeap(), 0 , pNewString
);
2231 /* Check range of value.
2233 dValue
= round( dValue
);
2234 if( dValue
< UI1_MIN
|| dValue
> UI1_MAX
)
2236 return DISP_E_OVERFLOW
;
2239 *pbOut
= (BYTE
) dValue
;
2244 /**********************************************************************
2245 * VarUI1FromCy [OLEAUT32.134]
2246 * Convert currency to unsigned char
2248 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
) {
2249 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2251 if (t
> UI1_MAX
|| t
< UI1_MIN
) return DISP_E_OVERFLOW
;
2257 /******************************************************************************
2258 * VarI2FromUI1 [OLEAUT32.48]
2260 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, short* psOut
)
2262 TRACE("( 0x%08x, %p ), stub\n", bIn
, psOut
);
2264 *psOut
= (short) bIn
;
2269 /******************************************************************************
2270 * VarI2FromI4 [OLEAUT32.49]
2272 HRESULT WINAPI
VarI2FromI4(LONG lIn
, short* psOut
)
2274 TRACE("( %lx, %p ), stub\n", lIn
, psOut
);
2276 /* Check range of value.
2278 if( lIn
< I2_MIN
|| lIn
> I2_MAX
)
2280 return DISP_E_OVERFLOW
;
2283 *psOut
= (short) lIn
;
2288 /******************************************************************************
2289 * VarI2FromR4 [OLEAUT32.50]
2291 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, short* psOut
)
2293 TRACE("( %f, %p ), stub\n", fltIn
, psOut
);
2295 /* Check range of value.
2297 fltIn
= round( fltIn
);
2298 if( fltIn
< I2_MIN
|| fltIn
> I2_MAX
)
2300 return DISP_E_OVERFLOW
;
2303 *psOut
= (short) fltIn
;
2308 /******************************************************************************
2309 * VarI2FromR8 [OLEAUT32.51]
2311 HRESULT WINAPI
VarI2FromR8(double dblIn
, short* psOut
)
2313 TRACE("( %f, %p ), stub\n", dblIn
, psOut
);
2315 /* Check range of value.
2317 dblIn
= round( dblIn
);
2318 if( dblIn
< I2_MIN
|| dblIn
> I2_MAX
)
2320 return DISP_E_OVERFLOW
;
2323 *psOut
= (short) dblIn
;
2328 /******************************************************************************
2329 * VarI2FromDate [OLEAUT32.53]
2331 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, short* psOut
)
2333 TRACE("( %f, %p ), stub\n", dateIn
, psOut
);
2335 /* Check range of value.
2337 dateIn
= round( dateIn
);
2338 if( dateIn
< I2_MIN
|| dateIn
> I2_MAX
)
2340 return DISP_E_OVERFLOW
;
2343 *psOut
= (short) dateIn
;
2348 /******************************************************************************
2349 * VarI2FromBool [OLEAUT32.56]
2351 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, short* psOut
)
2353 TRACE("( %d, %p ), stub\n", boolIn
, psOut
);
2355 *psOut
= (short) boolIn
;
2360 /******************************************************************************
2361 * VarI2FromI1 [OLEAUT32.48]
2363 HRESULT WINAPI
VarI2FromI1(CHAR cIn
, short* psOut
)
2365 TRACE("( %c, %p ), stub\n", cIn
, psOut
);
2367 *psOut
= (short) cIn
;
2372 /******************************************************************************
2373 * VarI2FromUI2 [OLEAUT32.206]
2375 HRESULT WINAPI
VarI2FromUI2(USHORT uiIn
, short* psOut
)
2377 TRACE("( %d, %p ), stub\n", uiIn
, psOut
);
2379 /* Check range of value.
2383 return DISP_E_OVERFLOW
;
2386 *psOut
= (short) uiIn
;
2391 /******************************************************************************
2392 * VarI2FromUI4 [OLEAUT32.49]
2394 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, short* psOut
)
2396 TRACE("( %lx, %p ), stub\n", ulIn
, psOut
);
2398 /* Check range of value.
2400 if( ulIn
< I2_MIN
|| ulIn
> I2_MAX
)
2402 return DISP_E_OVERFLOW
;
2405 *psOut
= (short) ulIn
;
2410 /******************************************************************************
2411 * VarI2FromStr [OLEAUT32.54]
2413 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, short* psOut
)
2415 double dValue
= 0.0;
2416 LPSTR pNewString
= NULL
;
2418 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, psOut
);
2420 /* Check if we have a valid argument
2422 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2423 RemoveCharacterFromString( pNewString
, "," );
2424 if( IsValidRealString( pNewString
) == FALSE
)
2426 return DISP_E_TYPEMISMATCH
;
2429 /* Convert the valid string to a floating point number.
2431 dValue
= atof( pNewString
);
2433 /* We don't need the string anymore so free it.
2435 HeapFree( GetProcessHeap(), 0, pNewString
);
2437 /* Check range of value.
2439 dValue
= round( dValue
);
2440 if( dValue
< I2_MIN
|| dValue
> I2_MAX
)
2442 return DISP_E_OVERFLOW
;
2445 *psOut
= (short) dValue
;
2450 /**********************************************************************
2451 * VarI2FromCy [OLEAUT32.52]
2452 * Convert currency to signed short
2454 HRESULT WINAPI
VarI2FromCy(CY cyIn
, short* psOut
) {
2455 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2457 if (t
> I2_MAX
|| t
< I2_MIN
) return DISP_E_OVERFLOW
;
2463 /******************************************************************************
2464 * VarI4FromUI1 [OLEAUT32.58]
2466 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
* plOut
)
2468 TRACE("( %X, %p ), stub\n", bIn
, plOut
);
2470 *plOut
= (LONG
) bIn
;
2476 /******************************************************************************
2477 * VarI4FromR4 [OLEAUT32.60]
2479 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
* plOut
)
2481 TRACE("( %f, %p ), stub\n", fltIn
, plOut
);
2483 /* Check range of value.
2485 fltIn
= round( fltIn
);
2486 if( fltIn
< I4_MIN
|| fltIn
> I4_MAX
)
2488 return DISP_E_OVERFLOW
;
2491 *plOut
= (LONG
) fltIn
;
2496 /******************************************************************************
2497 * VarI4FromR8 [OLEAUT32.61]
2499 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
* plOut
)
2501 TRACE("( %f, %p ), stub\n", dblIn
, plOut
);
2503 /* Check range of value.
2505 dblIn
= round( dblIn
);
2506 if( dblIn
< I4_MIN
|| dblIn
> I4_MAX
)
2508 return DISP_E_OVERFLOW
;
2511 *plOut
= (LONG
) dblIn
;
2516 /******************************************************************************
2517 * VarI4FromDate [OLEAUT32.63]
2519 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
* plOut
)
2521 TRACE("( %f, %p ), stub\n", dateIn
, plOut
);
2523 /* Check range of value.
2525 dateIn
= round( dateIn
);
2526 if( dateIn
< I4_MIN
|| dateIn
> I4_MAX
)
2528 return DISP_E_OVERFLOW
;
2531 *plOut
= (LONG
) dateIn
;
2536 /******************************************************************************
2537 * VarI4FromBool [OLEAUT32.66]
2539 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
* plOut
)
2541 TRACE("( %d, %p ), stub\n", boolIn
, plOut
);
2543 *plOut
= (LONG
) boolIn
;
2548 /******************************************************************************
2549 * VarI4FromI1 [OLEAUT32.209]
2551 HRESULT WINAPI
VarI4FromI1(CHAR cIn
, LONG
* plOut
)
2553 TRACE("( %c, %p ), stub\n", cIn
, plOut
);
2555 *plOut
= (LONG
) cIn
;
2560 /******************************************************************************
2561 * VarI4FromUI2 [OLEAUT32.210]
2563 HRESULT WINAPI
VarI4FromUI2(USHORT uiIn
, LONG
* plOut
)
2565 TRACE("( %d, %p ), stub\n", uiIn
, plOut
);
2567 *plOut
= (LONG
) uiIn
;
2572 /******************************************************************************
2573 * VarI4FromUI4 [OLEAUT32.211]
2575 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
* plOut
)
2577 TRACE("( %lx, %p ), stub\n", ulIn
, plOut
);
2579 /* Check range of value.
2581 if( ulIn
< I4_MIN
|| ulIn
> I4_MAX
)
2583 return DISP_E_OVERFLOW
;
2586 *plOut
= (LONG
) ulIn
;
2591 /******************************************************************************
2592 * VarI4FromI2 [OLEAUT32.59]
2594 HRESULT WINAPI
VarI4FromI2(short sIn
, LONG
* plOut
)
2596 TRACE("( %d, %p ), stub\n", sIn
, plOut
);
2598 *plOut
= (LONG
) sIn
;
2603 /******************************************************************************
2604 * VarI4FromStr [OLEAUT32.64]
2606 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
* plOut
)
2608 double dValue
= 0.0;
2609 LPSTR pNewString
= NULL
;
2611 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, plOut
);
2613 /* Check if we have a valid argument
2615 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2616 RemoveCharacterFromString( pNewString
, "," );
2617 if( IsValidRealString( pNewString
) == FALSE
)
2619 return DISP_E_TYPEMISMATCH
;
2622 /* Convert the valid string to a floating point number.
2624 dValue
= atof( pNewString
);
2626 /* We don't need the string anymore so free it.
2628 HeapFree( GetProcessHeap(), 0, pNewString
);
2630 /* Check range of value.
2632 dValue
= round( dValue
);
2633 if( dValue
< I4_MIN
|| dValue
> I4_MAX
)
2635 return DISP_E_OVERFLOW
;
2638 *plOut
= (LONG
) dValue
;
2643 /**********************************************************************
2644 * VarI4FromCy [OLEAUT32.62]
2645 * Convert currency to signed long
2647 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
* plOut
) {
2648 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2650 if (t
> I4_MAX
|| t
< I4_MIN
) return DISP_E_OVERFLOW
;
2656 /******************************************************************************
2657 * VarR4FromUI1 [OLEAUT32.68]
2659 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, FLOAT
* pfltOut
)
2661 TRACE("( %X, %p ), stub\n", bIn
, pfltOut
);
2663 *pfltOut
= (FLOAT
) bIn
;
2668 /******************************************************************************
2669 * VarR4FromI2 [OLEAUT32.69]
2671 HRESULT WINAPI
VarR4FromI2(short sIn
, FLOAT
* pfltOut
)
2673 TRACE("( %d, %p ), stub\n", sIn
, pfltOut
);
2675 *pfltOut
= (FLOAT
) sIn
;
2680 /******************************************************************************
2681 * VarR4FromI4 [OLEAUT32.70]
2683 HRESULT WINAPI
VarR4FromI4(LONG lIn
, FLOAT
* pfltOut
)
2685 TRACE("( %lx, %p ), stub\n", lIn
, pfltOut
);
2687 *pfltOut
= (FLOAT
) lIn
;
2692 /******************************************************************************
2693 * VarR4FromR8 [OLEAUT32.71]
2695 HRESULT WINAPI
VarR4FromR8(double dblIn
, FLOAT
* pfltOut
)
2697 TRACE("( %f, %p ), stub\n", dblIn
, pfltOut
);
2699 /* Check range of value.
2701 if( dblIn
< -(FLT_MAX
) || dblIn
> FLT_MAX
)
2703 return DISP_E_OVERFLOW
;
2706 *pfltOut
= (FLOAT
) dblIn
;
2711 /******************************************************************************
2712 * VarR4FromDate [OLEAUT32.73]
2714 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, FLOAT
* pfltOut
)
2716 TRACE("( %f, %p ), stub\n", dateIn
, pfltOut
);
2718 /* Check range of value.
2720 if( dateIn
< -(FLT_MAX
) || dateIn
> FLT_MAX
)
2722 return DISP_E_OVERFLOW
;
2725 *pfltOut
= (FLOAT
) dateIn
;
2730 /******************************************************************************
2731 * VarR4FromBool [OLEAUT32.76]
2733 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, FLOAT
* pfltOut
)
2735 TRACE("( %d, %p ), stub\n", boolIn
, pfltOut
);
2737 *pfltOut
= (FLOAT
) boolIn
;
2742 /******************************************************************************
2743 * VarR4FromI1 [OLEAUT32.213]
2745 HRESULT WINAPI
VarR4FromI1(CHAR cIn
, FLOAT
* pfltOut
)
2747 TRACE("( %c, %p ), stub\n", cIn
, pfltOut
);
2749 *pfltOut
= (FLOAT
) cIn
;
2754 /******************************************************************************
2755 * VarR4FromUI2 [OLEAUT32.214]
2757 HRESULT WINAPI
VarR4FromUI2(USHORT uiIn
, FLOAT
* pfltOut
)
2759 TRACE("( %d, %p ), stub\n", uiIn
, pfltOut
);
2761 *pfltOut
= (FLOAT
) uiIn
;
2766 /******************************************************************************
2767 * VarR4FromUI4 [OLEAUT32.215]
2769 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, FLOAT
* pfltOut
)
2771 TRACE("( %ld, %p ), stub\n", ulIn
, pfltOut
);
2773 *pfltOut
= (FLOAT
) ulIn
;
2778 /******************************************************************************
2779 * VarR4FromStr [OLEAUT32.74]
2781 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, FLOAT
* pfltOut
)
2783 double dValue
= 0.0;
2784 LPSTR pNewString
= NULL
;
2786 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pfltOut
);
2788 /* Check if we have a valid argument
2790 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2791 RemoveCharacterFromString( pNewString
, "," );
2792 if( IsValidRealString( pNewString
) == FALSE
)
2794 return DISP_E_TYPEMISMATCH
;
2797 /* Convert the valid string to a floating point number.
2799 dValue
= atof( pNewString
);
2801 /* We don't need the string anymore so free it.
2803 HeapFree( GetProcessHeap(), 0, pNewString
);
2805 /* Check range of value.
2807 if( dValue
< -(FLT_MAX
) || dValue
> FLT_MAX
)
2809 return DISP_E_OVERFLOW
;
2812 *pfltOut
= (FLOAT
) dValue
;
2817 /**********************************************************************
2818 * VarR4FromCy [OLEAUT32.72]
2819 * Convert currency to float
2821 HRESULT WINAPI
VarR4FromCy(CY cyIn
, FLOAT
* pfltOut
) {
2822 *pfltOut
= (FLOAT
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2827 /******************************************************************************
2828 * VarR8FromUI1 [OLEAUT32.68]
2830 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double* pdblOut
)
2832 TRACE("( %d, %p ), stub\n", bIn
, pdblOut
);
2834 *pdblOut
= (double) bIn
;
2839 /******************************************************************************
2840 * VarR8FromI2 [OLEAUT32.69]
2842 HRESULT WINAPI
VarR8FromI2(short sIn
, double* pdblOut
)
2844 TRACE("( %d, %p ), stub\n", sIn
, pdblOut
);
2846 *pdblOut
= (double) sIn
;
2851 /******************************************************************************
2852 * VarR8FromI4 [OLEAUT32.70]
2854 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double* pdblOut
)
2856 TRACE("( %ld, %p ), stub\n", lIn
, pdblOut
);
2858 *pdblOut
= (double) lIn
;
2863 /******************************************************************************
2864 * VarR8FromR4 [OLEAUT32.81]
2866 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double* pdblOut
)
2868 TRACE("( %f, %p ), stub\n", fltIn
, pdblOut
);
2870 *pdblOut
= (double) fltIn
;
2875 /******************************************************************************
2876 * VarR8FromDate [OLEAUT32.83]
2878 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double* pdblOut
)
2880 TRACE("( %f, %p ), stub\n", dateIn
, pdblOut
);
2882 *pdblOut
= (double) dateIn
;
2887 /******************************************************************************
2888 * VarR8FromBool [OLEAUT32.86]
2890 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double* pdblOut
)
2892 TRACE("( %d, %p ), stub\n", boolIn
, pdblOut
);
2894 *pdblOut
= (double) boolIn
;
2899 /******************************************************************************
2900 * VarR8FromI1 [OLEAUT32.217]
2902 HRESULT WINAPI
VarR8FromI1(CHAR cIn
, double* pdblOut
)
2904 TRACE("( %c, %p ), stub\n", cIn
, pdblOut
);
2906 *pdblOut
= (double) cIn
;
2911 /******************************************************************************
2912 * VarR8FromUI2 [OLEAUT32.218]
2914 HRESULT WINAPI
VarR8FromUI2(USHORT uiIn
, double* pdblOut
)
2916 TRACE("( %d, %p ), stub\n", uiIn
, pdblOut
);
2918 *pdblOut
= (double) uiIn
;
2923 /******************************************************************************
2924 * VarR8FromUI4 [OLEAUT32.219]
2926 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double* pdblOut
)
2928 TRACE("( %ld, %p ), stub\n", ulIn
, pdblOut
);
2930 *pdblOut
= (double) ulIn
;
2935 /******************************************************************************
2936 * VarR8FromStr [OLEAUT32.84]
2938 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double* pdblOut
)
2940 double dValue
= 0.0;
2941 LPSTR pNewString
= NULL
;
2943 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pdblOut
);
2945 /* Check if we have a valid argument
2947 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2948 RemoveCharacterFromString( pNewString
, "," );
2949 if( IsValidRealString( pNewString
) == FALSE
)
2951 return DISP_E_TYPEMISMATCH
;
2954 /* Convert the valid string to a floating point number.
2956 dValue
= atof( pNewString
);
2958 /* We don't need the string anymore so free it.
2960 HeapFree( GetProcessHeap(), 0, pNewString
);
2967 /**********************************************************************
2968 * VarR8FromCy [OLEAUT32.82]
2969 * Convert currency to double
2971 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double* pdblOut
) {
2972 *pdblOut
= (double)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2977 /******************************************************************************
2978 * VarDateFromUI1 [OLEAUT32.]
2980 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
2982 TRACE("( %d, %p ), stub\n", bIn
, pdateOut
);
2984 *pdateOut
= (DATE
) bIn
;
2989 /******************************************************************************
2990 * VarDateFromI2 [OLEAUT32.222]
2992 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
2994 TRACE("( %d, %p ), stub\n", sIn
, pdateOut
);
2996 *pdateOut
= (DATE
) sIn
;
3001 /******************************************************************************
3002 * VarDateFromI4 [OLEAUT32.90]
3004 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
3006 TRACE("( %ld, %p ), stub\n", lIn
, pdateOut
);
3008 if( lIn
< DATE_MIN
|| lIn
> DATE_MAX
)
3010 return DISP_E_OVERFLOW
;
3013 *pdateOut
= (DATE
) lIn
;
3018 /******************************************************************************
3019 * VarDateFromR4 [OLEAUT32.91]
3021 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
3023 TRACE("( %f, %p ), stub\n", fltIn
, pdateOut
);
3025 if( ceil(fltIn
) < DATE_MIN
|| floor(fltIn
) > DATE_MAX
)
3027 return DISP_E_OVERFLOW
;
3030 *pdateOut
= (DATE
) fltIn
;
3035 /******************************************************************************
3036 * VarDateFromR8 [OLEAUT32.92]
3038 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
3040 TRACE("( %f, %p ), stub\n", dblIn
, pdateOut
);
3042 if( ceil(dblIn
) < DATE_MIN
|| floor(dblIn
) > DATE_MAX
)
3044 return DISP_E_OVERFLOW
;
3047 *pdateOut
= (DATE
) dblIn
;
3052 /******************************************************************************
3053 * VarDateFromStr [OLEAUT32.94]
3054 * The string representing the date is composed of two parts, a date and time.
3056 * The format of the time is has follows:
3057 * hh[:mm][:ss][AM|PM]
3058 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3059 * of space and/or tab characters, which are ignored.
3061 * The formats for the date part are has follows:
3065 * January dd[,] [yy]yy
3068 * Whitespace can be inserted anywhere between these tokens.
3070 * The formats for the date and time string are has follows.
3071 * date[whitespace][time]
3072 * [time][whitespace]date
3074 * These are the only characters allowed in a string representing a date and time:
3075 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3077 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
3082 memset( &TM
, 0, sizeof(TM
) );
3084 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pdateOut
);
3086 if( DateTimeStringToTm( strIn
, lcid
, &TM
) )
3088 if( TmToDATE( &TM
, pdateOut
) == FALSE
)
3095 ret
= DISP_E_TYPEMISMATCH
;
3102 /******************************************************************************
3103 * VarDateFromI1 [OLEAUT32.221]
3105 HRESULT WINAPI
VarDateFromI1(CHAR cIn
, DATE
* pdateOut
)
3107 TRACE("( %c, %p ), stub\n", cIn
, pdateOut
);
3109 *pdateOut
= (DATE
) cIn
;
3114 /******************************************************************************
3115 * VarDateFromUI2 [OLEAUT32.222]
3117 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
3119 TRACE("( %d, %p ), stub\n", uiIn
, pdateOut
);
3121 if( uiIn
> DATE_MAX
)
3123 return DISP_E_OVERFLOW
;
3126 *pdateOut
= (DATE
) uiIn
;
3131 /******************************************************************************
3132 * VarDateFromUI4 [OLEAUT32.223]
3134 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
3136 TRACE("( %ld, %p ), stub\n", ulIn
, pdateOut
);
3138 if( ulIn
< DATE_MIN
|| ulIn
> DATE_MAX
)
3140 return DISP_E_OVERFLOW
;
3143 *pdateOut
= (DATE
) ulIn
;
3148 /******************************************************************************
3149 * VarDateFromBool [OLEAUT32.96]
3151 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
3153 TRACE("( %d, %p ), stub\n", boolIn
, pdateOut
);
3155 *pdateOut
= (DATE
) boolIn
;
3160 /**********************************************************************
3161 * VarDateFromCy [OLEAUT32.93]
3162 * Convert currency to date
3164 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
) {
3165 *pdateOut
= (DATE
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3167 if (*pdateOut
> DATE_MAX
|| *pdateOut
< DATE_MIN
) return DISP_E_TYPEMISMATCH
;
3171 /******************************************************************************
3172 * VarBstrFromUI1 [OLEAUT32.108]
3174 HRESULT WINAPI
VarBstrFromUI1(BYTE bVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3176 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal
, lcid
, dwFlags
, pbstrOut
);
3177 sprintf( pBuffer
, "%d", bVal
);
3179 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3184 /******************************************************************************
3185 * VarBstrFromI2 [OLEAUT32.109]
3187 HRESULT WINAPI
VarBstrFromI2(short iVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3189 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal
, lcid
, dwFlags
, pbstrOut
);
3190 sprintf( pBuffer
, "%d", iVal
);
3191 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3196 /******************************************************************************
3197 * VarBstrFromI4 [OLEAUT32.110]
3199 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3201 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn
, lcid
, dwFlags
, pbstrOut
);
3203 sprintf( pBuffer
, "%ld", lIn
);
3204 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3209 /******************************************************************************
3210 * VarBstrFromR4 [OLEAUT32.111]
3212 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3214 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn
, lcid
, dwFlags
, pbstrOut
);
3216 sprintf( pBuffer
, "%.7g", fltIn
);
3217 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3222 /******************************************************************************
3223 * VarBstrFromR8 [OLEAUT32.112]
3225 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3227 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn
, lcid
, dwFlags
, pbstrOut
);
3229 sprintf( pBuffer
, "%.15g", dblIn
);
3230 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3235 /******************************************************************************
3236 * VarBstrFromCy [OLEAUT32.113]
3238 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
) {
3244 /******************************************************************************
3245 * VarBstrFromDate [OLEAUT32.114]
3247 * The date is implemented using an 8 byte floating-point number.
3248 * Days are represented by whole numbers increments starting with 0.00 has
3249 * being December 30 1899, midnight.
3250 * The hours are expressed as the fractional part of the number.
3251 * December 30 1899 at midnight = 0.00
3252 * January 1 1900 at midnight = 2.00
3253 * January 4 1900 at 6 AM = 5.25
3254 * January 4 1900 at noon = 5.50
3255 * December 29 1899 at midnight = -1.00
3256 * December 18 1899 at midnight = -12.00
3257 * December 18 1899 at 6AM = -12.25
3258 * December 18 1899 at 6PM = -12.75
3259 * December 19 1899 at midnight = -11.00
3260 * The tm structure is as follows:
3262 * int tm_sec; seconds after the minute - [0,59]
3263 * int tm_min; minutes after the hour - [0,59]
3264 * int tm_hour; hours since midnight - [0,23]
3265 * int tm_mday; day of the month - [1,31]
3266 * int tm_mon; months since January - [0,11]
3267 * int tm_year; years
3268 * int tm_wday; days since Sunday - [0,6]
3269 * int tm_yday; days since January 1 - [0,365]
3270 * int tm_isdst; daylight savings time flag
3273 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3276 memset( &TM
, 0, sizeof(TM
) );
3278 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
3280 if( DateToTm( dateIn
, lcid
, &TM
) == FALSE
)
3282 return E_INVALIDARG
;
3285 if( dwFlags
& VAR_DATEVALUEONLY
)
3286 strftime( pBuffer
, BUFFER_MAX
, "%x", &TM
);
3287 else if( dwFlags
& VAR_TIMEVALUEONLY
)
3288 strftime( pBuffer
, BUFFER_MAX
, "%X", &TM
);
3290 strftime( pBuffer
, BUFFER_MAX
, "%x %X", &TM
);
3292 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3297 /******************************************************************************
3298 * VarBstrFromBool [OLEAUT32.116]
3300 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3302 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
3304 if( boolIn
== VARIANT_FALSE
)
3306 sprintf( pBuffer
, "False" );
3310 sprintf( pBuffer
, "True" );
3313 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3318 /******************************************************************************
3319 * VarBstrFromI1 [OLEAUT32.229]
3321 HRESULT WINAPI
VarBstrFromI1(CHAR cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3323 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn
, lcid
, dwFlags
, pbstrOut
);
3324 sprintf( pBuffer
, "%d", cIn
);
3325 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3330 /******************************************************************************
3331 * VarBstrFromUI2 [OLEAUT32.230]
3333 HRESULT WINAPI
VarBstrFromUI2(USHORT uiIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3335 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn
, lcid
, dwFlags
, pbstrOut
);
3336 sprintf( pBuffer
, "%d", uiIn
);
3337 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3342 /******************************************************************************
3343 * VarBstrFromUI4 [OLEAUT32.231]
3345 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3347 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn
, lcid
, dwFlags
, pbstrOut
);
3348 sprintf( pBuffer
, "%ld", ulIn
);
3349 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3354 /******************************************************************************
3355 * VarBoolFromUI1 [OLEAUT32.118]
3357 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
* pboolOut
)
3359 TRACE("( %d, %p ), stub\n", bIn
, pboolOut
);
3363 *pboolOut
= VARIANT_FALSE
;
3367 *pboolOut
= VARIANT_TRUE
;
3373 /******************************************************************************
3374 * VarBoolFromI2 [OLEAUT32.119]
3376 HRESULT WINAPI
VarBoolFromI2(short sIn
, VARIANT_BOOL
* pboolOut
)
3378 TRACE("( %d, %p ), stub\n", sIn
, pboolOut
);
3382 *pboolOut
= VARIANT_FALSE
;
3386 *pboolOut
= VARIANT_TRUE
;
3392 /******************************************************************************
3393 * VarBoolFromI4 [OLEAUT32.120]
3395 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
* pboolOut
)
3397 TRACE("( %ld, %p ), stub\n", lIn
, pboolOut
);
3401 *pboolOut
= VARIANT_FALSE
;
3405 *pboolOut
= VARIANT_TRUE
;
3411 /******************************************************************************
3412 * VarBoolFromR4 [OLEAUT32.121]
3414 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
* pboolOut
)
3416 TRACE("( %f, %p ), stub\n", fltIn
, pboolOut
);
3420 *pboolOut
= VARIANT_FALSE
;
3424 *pboolOut
= VARIANT_TRUE
;
3430 /******************************************************************************
3431 * VarBoolFromR8 [OLEAUT32.122]
3433 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
* pboolOut
)
3435 TRACE("( %f, %p ), stub\n", dblIn
, pboolOut
);
3439 *pboolOut
= VARIANT_FALSE
;
3443 *pboolOut
= VARIANT_TRUE
;
3449 /******************************************************************************
3450 * VarBoolFromDate [OLEAUT32.123]
3452 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
* pboolOut
)
3454 TRACE("( %f, %p ), stub\n", dateIn
, pboolOut
);
3458 *pboolOut
= VARIANT_FALSE
;
3462 *pboolOut
= VARIANT_TRUE
;
3468 /******************************************************************************
3469 * VarBoolFromStr [OLEAUT32.125]
3471 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
* pboolOut
)
3474 char* pNewString
= NULL
;
3476 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pboolOut
);
3478 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3480 if( pNewString
== NULL
|| strlen( pNewString
) == 0 )
3482 ret
= DISP_E_TYPEMISMATCH
;
3487 if( strncasecmp( pNewString
, "True", strlen( pNewString
) ) == 0 )
3489 *pboolOut
= VARIANT_TRUE
;
3491 else if( strncasecmp( pNewString
, "False", strlen( pNewString
) ) == 0 )
3493 *pboolOut
= VARIANT_FALSE
;
3497 /* Try converting the string to a floating point number.
3499 double dValue
= 0.0;
3500 HRESULT res
= VarR8FromStr( strIn
, lcid
, dwFlags
, &dValue
);
3503 ret
= DISP_E_TYPEMISMATCH
;
3505 else if( dValue
== 0.0 )
3507 *pboolOut
= VARIANT_FALSE
;
3511 *pboolOut
= VARIANT_TRUE
;
3516 HeapFree( GetProcessHeap(), 0, pNewString
);
3521 /******************************************************************************
3522 * VarBoolFromI1 [OLEAUT32.233]
3524 HRESULT WINAPI
VarBoolFromI1(CHAR cIn
, VARIANT_BOOL
* pboolOut
)
3526 TRACE("( %c, %p ), stub\n", cIn
, pboolOut
);
3530 *pboolOut
= VARIANT_FALSE
;
3534 *pboolOut
= VARIANT_TRUE
;
3540 /******************************************************************************
3541 * VarBoolFromUI2 [OLEAUT32.234]
3543 HRESULT WINAPI
VarBoolFromUI2(USHORT uiIn
, VARIANT_BOOL
* pboolOut
)
3545 TRACE("( %d, %p ), stub\n", uiIn
, pboolOut
);
3549 *pboolOut
= VARIANT_FALSE
;
3553 *pboolOut
= VARIANT_TRUE
;
3559 /******************************************************************************
3560 * VarBoolFromUI4 [OLEAUT32.235]
3562 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
* pboolOut
)
3564 TRACE("( %ld, %p ), stub\n", ulIn
, pboolOut
);
3568 *pboolOut
= VARIANT_FALSE
;
3572 *pboolOut
= VARIANT_TRUE
;
3578 /**********************************************************************
3579 * VarBoolFromCy [OLEAUT32.124]
3580 * Convert currency to boolean
3582 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
* pboolOut
) {
3583 if (cyIn
.s
.Hi
|| cyIn
.s
.Lo
) *pboolOut
= -1;
3589 /******************************************************************************
3590 * VarI1FromUI1 [OLEAUT32.244]
3592 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, CHAR
* pcOut
)
3594 TRACE("( %d, %p ), stub\n", bIn
, pcOut
);
3596 /* Check range of value.
3598 if( bIn
> CHAR_MAX
)
3600 return DISP_E_OVERFLOW
;
3603 *pcOut
= (CHAR
) bIn
;
3608 /******************************************************************************
3609 * VarI1FromI2 [OLEAUT32.245]
3611 HRESULT WINAPI
VarI1FromI2(short uiIn
, CHAR
* pcOut
)
3613 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3615 if( uiIn
> CHAR_MAX
)
3617 return DISP_E_OVERFLOW
;
3620 *pcOut
= (CHAR
) uiIn
;
3625 /******************************************************************************
3626 * VarI1FromI4 [OLEAUT32.246]
3628 HRESULT WINAPI
VarI1FromI4(LONG lIn
, CHAR
* pcOut
)
3630 TRACE("( %ld, %p ), stub\n", lIn
, pcOut
);
3632 if( lIn
< CHAR_MIN
|| lIn
> CHAR_MAX
)
3634 return DISP_E_OVERFLOW
;
3637 *pcOut
= (CHAR
) lIn
;
3642 /******************************************************************************
3643 * VarI1FromR4 [OLEAUT32.247]
3645 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, CHAR
* pcOut
)
3647 TRACE("( %f, %p ), stub\n", fltIn
, pcOut
);
3649 fltIn
= round( fltIn
);
3650 if( fltIn
< CHAR_MIN
|| fltIn
> CHAR_MAX
)
3652 return DISP_E_OVERFLOW
;
3655 *pcOut
= (CHAR
) fltIn
;
3660 /******************************************************************************
3661 * VarI1FromR8 [OLEAUT32.248]
3663 HRESULT WINAPI
VarI1FromR8(double dblIn
, CHAR
* pcOut
)
3665 TRACE("( %f, %p ), stub\n", dblIn
, pcOut
);
3667 dblIn
= round( dblIn
);
3668 if( dblIn
< CHAR_MIN
|| dblIn
> CHAR_MAX
)
3670 return DISP_E_OVERFLOW
;
3673 *pcOut
= (CHAR
) dblIn
;
3678 /******************************************************************************
3679 * VarI1FromDate [OLEAUT32.249]
3681 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, CHAR
* pcOut
)
3683 TRACE("( %f, %p ), stub\n", dateIn
, pcOut
);
3685 dateIn
= round( dateIn
);
3686 if( dateIn
< CHAR_MIN
|| dateIn
> CHAR_MAX
)
3688 return DISP_E_OVERFLOW
;
3691 *pcOut
= (CHAR
) dateIn
;
3696 /******************************************************************************
3697 * VarI1FromStr [OLEAUT32.251]
3699 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CHAR
* pcOut
)
3701 double dValue
= 0.0;
3702 LPSTR pNewString
= NULL
;
3704 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pcOut
);
3706 /* Check if we have a valid argument
3708 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3709 RemoveCharacterFromString( pNewString
, "," );
3710 if( IsValidRealString( pNewString
) == FALSE
)
3712 return DISP_E_TYPEMISMATCH
;
3715 /* Convert the valid string to a floating point number.
3717 dValue
= atof( pNewString
);
3719 /* We don't need the string anymore so free it.
3721 HeapFree( GetProcessHeap(), 0, pNewString
);
3723 /* Check range of value.
3725 dValue
= round( dValue
);
3726 if( dValue
< CHAR_MIN
|| dValue
> CHAR_MAX
)
3728 return DISP_E_OVERFLOW
;
3731 *pcOut
= (CHAR
) dValue
;
3736 /******************************************************************************
3737 * VarI1FromBool [OLEAUT32.253]
3739 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, CHAR
* pcOut
)
3741 TRACE("( %d, %p ), stub\n", boolIn
, pcOut
);
3743 *pcOut
= (CHAR
) boolIn
;
3748 /******************************************************************************
3749 * VarI1FromUI2 [OLEAUT32.254]
3751 HRESULT WINAPI
VarI1FromUI2(USHORT uiIn
, CHAR
* pcOut
)
3753 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3755 if( uiIn
> CHAR_MAX
)
3757 return DISP_E_OVERFLOW
;
3760 *pcOut
= (CHAR
) uiIn
;
3765 /******************************************************************************
3766 * VarI1FromUI4 [OLEAUT32.255]
3768 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, CHAR
* pcOut
)
3770 TRACE("( %ld, %p ), stub\n", ulIn
, pcOut
);
3772 if( ulIn
> CHAR_MAX
)
3774 return DISP_E_OVERFLOW
;
3777 *pcOut
= (CHAR
) ulIn
;
3782 /**********************************************************************
3783 * VarI1FromCy [OLEAUT32.250]
3784 * Convert currency to signed char
3786 HRESULT WINAPI
VarI1FromCy(CY cyIn
, CHAR
* pcOut
) {
3787 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3789 if (t
> CHAR_MAX
|| t
< CHAR_MIN
) return DISP_E_OVERFLOW
;
3795 /******************************************************************************
3796 * VarUI2FromUI1 [OLEAUT32.257]
3798 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* puiOut
)
3800 TRACE("( %d, %p ), stub\n", bIn
, puiOut
);
3802 *puiOut
= (USHORT
) bIn
;
3807 /******************************************************************************
3808 * VarUI2FromI2 [OLEAUT32.258]
3810 HRESULT WINAPI
VarUI2FromI2(short uiIn
, USHORT
* puiOut
)
3812 TRACE("( %d, %p ), stub\n", uiIn
, puiOut
);
3814 if( uiIn
< UI2_MIN
)
3816 return DISP_E_OVERFLOW
;
3819 *puiOut
= (USHORT
) uiIn
;
3824 /******************************************************************************
3825 * VarUI2FromI4 [OLEAUT32.259]
3827 HRESULT WINAPI
VarUI2FromI4(LONG lIn
, USHORT
* puiOut
)
3829 TRACE("( %ld, %p ), stub\n", lIn
, puiOut
);
3831 if( lIn
< UI2_MIN
|| lIn
> UI2_MAX
)
3833 return DISP_E_OVERFLOW
;
3836 *puiOut
= (USHORT
) lIn
;
3841 /******************************************************************************
3842 * VarUI2FromR4 [OLEAUT32.260]
3844 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* puiOut
)
3846 TRACE("( %f, %p ), stub\n", fltIn
, puiOut
);
3848 fltIn
= round( fltIn
);
3849 if( fltIn
< UI2_MIN
|| fltIn
> UI2_MAX
)
3851 return DISP_E_OVERFLOW
;
3854 *puiOut
= (USHORT
) fltIn
;
3859 /******************************************************************************
3860 * VarUI2FromR8 [OLEAUT32.261]
3862 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* puiOut
)
3864 TRACE("( %f, %p ), stub\n", dblIn
, puiOut
);
3866 dblIn
= round( dblIn
);
3867 if( dblIn
< UI2_MIN
|| dblIn
> UI2_MAX
)
3869 return DISP_E_OVERFLOW
;
3872 *puiOut
= (USHORT
) dblIn
;
3877 /******************************************************************************
3878 * VarUI2FromDate [OLEAUT32.262]
3880 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* puiOut
)
3882 TRACE("( %f, %p ), stub\n", dateIn
, puiOut
);
3884 dateIn
= round( dateIn
);
3885 if( dateIn
< UI2_MIN
|| dateIn
> UI2_MAX
)
3887 return DISP_E_OVERFLOW
;
3890 *puiOut
= (USHORT
) dateIn
;
3895 /******************************************************************************
3896 * VarUI2FromStr [OLEAUT32.264]
3898 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* puiOut
)
3900 double dValue
= 0.0;
3901 LPSTR pNewString
= NULL
;
3903 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, puiOut
);
3905 /* Check if we have a valid argument
3907 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3908 RemoveCharacterFromString( pNewString
, "," );
3909 if( IsValidRealString( pNewString
) == FALSE
)
3911 return DISP_E_TYPEMISMATCH
;
3914 /* Convert the valid string to a floating point number.
3916 dValue
= atof( pNewString
);
3918 /* We don't need the string anymore so free it.
3920 HeapFree( GetProcessHeap(), 0, pNewString
);
3922 /* Check range of value.
3924 dValue
= round( dValue
);
3925 if( dValue
< UI2_MIN
|| dValue
> UI2_MAX
)
3927 return DISP_E_OVERFLOW
;
3930 *puiOut
= (USHORT
) dValue
;
3935 /******************************************************************************
3936 * VarUI2FromBool [OLEAUT32.266]
3938 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* puiOut
)
3940 TRACE("( %d, %p ), stub\n", boolIn
, puiOut
);
3942 *puiOut
= (USHORT
) boolIn
;
3947 /******************************************************************************
3948 * VarUI2FromI1 [OLEAUT32.267]
3950 HRESULT WINAPI
VarUI2FromI1(CHAR cIn
, USHORT
* puiOut
)
3952 TRACE("( %c, %p ), stub\n", cIn
, puiOut
);
3954 *puiOut
= (USHORT
) cIn
;
3959 /******************************************************************************
3960 * VarUI2FromUI4 [OLEAUT32.268]
3962 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* puiOut
)
3964 TRACE("( %ld, %p ), stub\n", ulIn
, puiOut
);
3966 if( ulIn
< UI2_MIN
|| ulIn
> UI2_MAX
)
3968 return DISP_E_OVERFLOW
;
3971 *puiOut
= (USHORT
) ulIn
;
3976 /******************************************************************************
3977 * VarUI4FromStr [OLEAUT32.277]
3979 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
* pulOut
)
3981 double dValue
= 0.0;
3982 LPSTR pNewString
= NULL
;
3984 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pulOut
);
3986 /* Check if we have a valid argument
3988 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3989 RemoveCharacterFromString( pNewString
, "," );
3990 if( IsValidRealString( pNewString
) == FALSE
)
3992 return DISP_E_TYPEMISMATCH
;
3995 /* Convert the valid string to a floating point number.
3997 dValue
= atof( pNewString
);
3999 /* We don't need the string anymore so free it.
4001 HeapFree( GetProcessHeap(), 0, pNewString
);
4003 /* Check range of value.
4005 dValue
= round( dValue
);
4006 if( dValue
< UI4_MIN
|| dValue
> UI4_MAX
)
4008 return DISP_E_OVERFLOW
;
4011 *pulOut
= (ULONG
) dValue
;
4016 /**********************************************************************
4017 * VarUI2FromCy [OLEAUT32.263]
4018 * Convert currency to unsigned short
4020 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
) {
4021 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
4023 if (t
> UI2_MAX
|| t
< UI2_MIN
) return DISP_E_OVERFLOW
;
4025 *pusOut
= (USHORT
)t
;
4030 /******************************************************************************
4031 * VarUI4FromUI1 [OLEAUT32.270]
4033 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
* pulOut
)
4035 TRACE("( %d, %p ), stub\n", bIn
, pulOut
);
4037 *pulOut
= (USHORT
) bIn
;
4042 /******************************************************************************
4043 * VarUI4FromI2 [OLEAUT32.271]
4045 HRESULT WINAPI
VarUI4FromI2(short uiIn
, ULONG
* pulOut
)
4047 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4049 if( uiIn
< UI4_MIN
)
4051 return DISP_E_OVERFLOW
;
4054 *pulOut
= (ULONG
) uiIn
;
4059 /******************************************************************************
4060 * VarUI4FromI4 [OLEAUT32.272]
4062 HRESULT WINAPI
VarUI4FromI4(LONG lIn
, ULONG
* pulOut
)
4064 TRACE("( %ld, %p ), stub\n", lIn
, pulOut
);
4068 return DISP_E_OVERFLOW
;
4071 *pulOut
= (ULONG
) lIn
;
4076 /******************************************************************************
4077 * VarUI4FromR4 [OLEAUT32.273]
4079 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
* pulOut
)
4081 fltIn
= round( fltIn
);
4082 if( fltIn
< UI4_MIN
|| fltIn
> UI4_MAX
)
4084 return DISP_E_OVERFLOW
;
4087 *pulOut
= (ULONG
) fltIn
;
4092 /******************************************************************************
4093 * VarUI4FromR8 [OLEAUT32.274]
4095 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
* pulOut
)
4097 TRACE("( %f, %p ), stub\n", dblIn
, pulOut
);
4099 dblIn
= round( dblIn
);
4100 if( dblIn
< UI4_MIN
|| dblIn
> UI4_MAX
)
4102 return DISP_E_OVERFLOW
;
4105 *pulOut
= (ULONG
) dblIn
;
4110 /******************************************************************************
4111 * VarUI4FromDate [OLEAUT32.275]
4113 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
* pulOut
)
4115 TRACE("( %f, %p ), stub\n", dateIn
, pulOut
);
4117 dateIn
= round( dateIn
);
4118 if( dateIn
< UI4_MIN
|| dateIn
> UI4_MAX
)
4120 return DISP_E_OVERFLOW
;
4123 *pulOut
= (ULONG
) dateIn
;
4128 /******************************************************************************
4129 * VarUI4FromBool [OLEAUT32.279]
4131 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
* pulOut
)
4133 TRACE("( %d, %p ), stub\n", boolIn
, pulOut
);
4135 *pulOut
= (ULONG
) boolIn
;
4140 /******************************************************************************
4141 * VarUI4FromI1 [OLEAUT32.280]
4143 HRESULT WINAPI
VarUI4FromI1(CHAR cIn
, ULONG
* pulOut
)
4145 TRACE("( %c, %p ), stub\n", cIn
, pulOut
);
4147 *pulOut
= (ULONG
) cIn
;
4152 /******************************************************************************
4153 * VarUI4FromUI2 [OLEAUT32.281]
4155 HRESULT WINAPI
VarUI4FromUI2(USHORT uiIn
, ULONG
* pulOut
)
4157 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4159 *pulOut
= (ULONG
) uiIn
;
4164 /**********************************************************************
4165 * VarUI4FromCy [OLEAUT32.276]
4166 * Convert currency to unsigned long
4168 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
* pulOut
) {
4169 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
4171 if (t
> UI4_MAX
|| t
< UI4_MIN
) return DISP_E_OVERFLOW
;
4178 /**********************************************************************
4179 * VarCyFromUI1 [OLEAUT32.98]
4180 * Convert unsigned char to currency
4182 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pcyOut
) {
4184 pcyOut
->s
.Lo
= ((ULONG
)bIn
) * 10000;
4189 /**********************************************************************
4190 * VarCyFromI2 [OLEAUT32.99]
4191 * Convert signed short to currency
4193 HRESULT WINAPI
VarCyFromI2(short sIn
, CY
* pcyOut
) {
4194 if (sIn
< 0) pcyOut
->s
.Hi
= -1;
4195 else pcyOut
->s
.Hi
= 0;
4196 pcyOut
->s
.Lo
= ((ULONG
)sIn
) * 10000;
4201 /**********************************************************************
4202 * VarCyFromI4 [OLEAUT32.100]
4203 * Convert signed long to currency
4205 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pcyOut
) {
4206 double t
= (double)lIn
* (double)10000;
4207 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4208 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4209 if (lIn
< 0) pcyOut
->s
.Hi
--;
4214 /**********************************************************************
4215 * VarCyFromR4 [OLEAUT32.101]
4216 * Convert float to currency
4218 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pcyOut
) {
4219 double t
= round((double)fltIn
* (double)10000);
4220 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4221 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4222 if (fltIn
< 0) pcyOut
->s
.Hi
--;
4227 /**********************************************************************
4228 * VarCyFromR8 [OLEAUT32.102]
4229 * Convert double to currency
4231 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pcyOut
) {
4232 double t
= round(dblIn
* (double)10000);
4233 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4234 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4235 if (dblIn
< 0) pcyOut
->s
.Hi
--;
4240 /**********************************************************************
4241 * VarCyFromDate [OLEAUT32.103]
4242 * Convert date to currency
4244 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pcyOut
) {
4245 double t
= round((double)dateIn
* (double)10000);
4246 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4247 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4248 if (dateIn
< 0) pcyOut
->s
.Hi
--;
4253 /**********************************************************************
4254 * VarCyFromStr [OLEAUT32.104]
4256 HRESULT WINAPI
VarCyFromStr(OLECHAR
*strIn
, LCID lcid
, ULONG dwFlags
, CY
*pcyOut
) {
4262 /**********************************************************************
4263 * VarCyFromBool [OLEAUT32.106]
4264 * Convert boolean to currency
4266 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pcyOut
) {
4267 if (boolIn
< 0) pcyOut
->s
.Hi
= -1;
4268 else pcyOut
->s
.Hi
= 0;
4269 pcyOut
->s
.Lo
= (ULONG
)boolIn
* (ULONG
)10000;
4274 /**********************************************************************
4275 * VarCyFromI1 [OLEAUT32.225]
4276 * Convert signed char to currency
4278 HRESULT WINAPI
VarCyFromI1(signed char cIn
, CY
* pcyOut
) {
4279 if (cIn
< 0) pcyOut
->s
.Hi
= -1;
4280 else pcyOut
->s
.Hi
= 0;
4281 pcyOut
->s
.Lo
= (ULONG
)cIn
* (ULONG
)10000;
4286 /**********************************************************************
4287 * VarCyFromUI2 [OLEAUT32.226]
4288 * Convert unsigned short to currency
4290 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pcyOut
) {
4292 pcyOut
->s
.Lo
= (ULONG
)usIn
* (ULONG
)10000;
4297 /**********************************************************************
4298 * VarCyFromUI4 [OLEAUT32.227]
4299 * Convert unsigned long to currency
4301 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pcyOut
) {
4302 double t
= (double)ulIn
* (double)10000;
4303 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4304 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4310 /**********************************************************************
4311 * DosDateTimeToVariantTime [OLEAUT32.14]
4312 * Convert dos representation of time to the date and time representation
4313 * stored in a variant.
4315 INT WINAPI
DosDateTimeToVariantTime(USHORT wDosDate
, USHORT wDosTime
,
4320 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate
, wDosTime
, pvtime
);
4322 t
.tm_sec
= (wDosTime
& 0x001f) * 2;
4323 t
.tm_min
= (wDosTime
& 0x07e0) >> 5;
4324 t
.tm_hour
= (wDosTime
& 0xf800) >> 11;
4326 t
.tm_mday
= (wDosDate
& 0x001f);
4327 t
.tm_mon
= (wDosDate
& 0x01e0) >> 5;
4328 t
.tm_year
= ((wDosDate
& 0xfe00) >> 9) + 1980;
4330 return TmToDATE( &t
, pvtime
);