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
);
44 #define SYSDUPSTRING(str) SysAllocStringLen((str), SysStringLen(str))
48 # define FLT_MAX MAXFLOAT
50 # error "Can't find #define for MAXFLOAT/FLT_MAX"
56 static const char CHAR_MAX
= 127;
57 static const char CHAR_MIN
= -128;
58 static const BYTE UI1_MAX
= 255;
59 static const BYTE UI1_MIN
= 0;
60 static const unsigned short UI2_MAX
= 65535;
61 static const unsigned short UI2_MIN
= 0;
62 static const short I2_MAX
= 32767;
63 static const short I2_MIN
= -32768;
64 static const unsigned long UI4_MAX
= 4294967295U;
65 static const unsigned long UI4_MIN
= 0;
66 static const long I4_MAX
= 2147483647;
67 static const long I4_MIN
= -(2147483648U);
68 static const DATE DATE_MIN
= -657434;
69 static const DATE DATE_MAX
= 2958465;
72 /* This mask is used to set a flag in wReserved1 of
73 * the VARIANTARG structure. The flag indicates if
74 * the API function is using an inner variant or not.
76 #define PROCESSING_INNER_VARIANT 0x0001
78 /* General use buffer.
80 #define BUFFER_MAX 1024
81 static char pBuffer
[BUFFER_MAX
];
84 * Note a leap year is one that is a multiple of 4
85 * but not of a 100. Except if it is a multiple of
86 * 400 then it is a leap year.
88 /* According to postgeSQL date parsing functions there is
89 * a leap year when this expression is true.
90 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
91 * So according to this there is 365.2515 days in one year.
92 * One + every four years: 1/4 -> 365.25
93 * One - every 100 years: 1/100 -> 365.01
94 * One + every 400 years: 1/400 -> 365.0025
96 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
98 * ^^ Might this be the key to an easy way to factor large prime numbers?
99 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
101 static const double DAYS_IN_ONE_YEAR
= 365.2425;
103 /******************************************************************************
104 * DateTimeStringToTm [INTERNAL]
106 * Converts a string representation of a date and/or time to a tm structure.
108 * Note this function uses the postgresql date parsing functions found
109 * in the parsedt.c file.
111 * Returns TRUE if successful.
113 * Note: This function does not parse the day of the week,
114 * daylight savings time. It will only fill the followin fields in
115 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
117 ******************************************************************************/
118 static BOOL
DateTimeStringToTm( OLECHAR
* strIn
, DWORD dwFlags
, struct tm
* pTm
)
125 char *field
[MAXDATEFIELDS
];
126 int ftype
[MAXDATEFIELDS
];
127 char lowstr
[MAXDATELEN
+ 1];
128 char* strDateTime
= NULL
;
130 /* Convert the string to ASCII since this is the only format
131 * postgesql can handle.
133 strDateTime
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
135 if( strDateTime
!= NULL
)
137 /* Make sure we don't go over the maximum length
138 * accepted by postgesql.
140 if( strlen( strDateTime
) <= MAXDATELEN
)
142 if( ParseDateTime( strDateTime
, lowstr
, field
, ftype
, MAXDATEFIELDS
, &nf
) == 0 )
144 if( dwFlags
& VAR_DATEVALUEONLY
)
146 /* Get the date information.
147 * It returns 0 if date information was
148 * present and 1 if only time information was present.
149 * -1 if an error occures.
151 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) == 0 )
153 /* Eliminate the time information since we
154 * were asked to get date information only.
162 if( dwFlags
& VAR_TIMEVALUEONLY
)
164 /* Get time information only.
166 if( DecodeTimeOnly(field
, ftype
, nf
, &dtype
, pTm
, &fsec
) == 0 )
173 /* Get both date and time information.
174 * It returns 0 if date information was
175 * present and 1 if only time information was present.
176 * -1 if an error occures.
178 if( DecodeDateTime(field
, ftype
, nf
, &dtype
, pTm
, &fsec
, &tzp
) != -1 )
185 HeapFree( GetProcessHeap(), 0, strDateTime
);
196 /******************************************************************************
197 * TmToDATE [INTERNAL]
199 * The date is implemented using an 8 byte floating-point number.
200 * Days are represented by whole numbers increments starting with 0.00 has
201 * being December 30 1899, midnight.
202 * The hours are expressed as the fractional part of the number.
203 * December 30 1899 at midnight = 0.00
204 * January 1 1900 at midnight = 2.00
205 * January 4 1900 at 6 AM = 5.25
206 * January 4 1900 at noon = 5.50
207 * December 29 1899 at midnight = -1.00
208 * December 18 1899 at midnight = -12.00
209 * December 18 1899 at 6AM = -12.25
210 * December 18 1899 at 6PM = -12.75
211 * December 19 1899 at midnight = -11.00
212 * The tm structure is as follows:
214 * int tm_sec; seconds after the minute - [0,59]
215 * int tm_min; minutes after the hour - [0,59]
216 * int tm_hour; hours since midnight - [0,23]
217 * int tm_mday; day of the month - [1,31]
218 * int tm_mon; months since January - [0,11]
220 * int tm_wday; days since Sunday - [0,6]
221 * int tm_yday; days since January 1 - [0,365]
222 * int tm_isdst; daylight savings time flag
225 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
226 * and tm_isdst fields of the tm structure. And only converts years
229 * Returns TRUE if successful.
231 static BOOL
TmToDATE( struct tm
* pTm
, DATE
*pDateOut
)
233 if( (pTm
->tm_year
- 1900) >= 0 )
237 /* Start at 1. This is the way DATE is defined.
238 * January 1, 1900 at Midnight is 1.00.
239 * January 1, 1900 at 6AM is 1.25.
244 /* Add the number of days corresponding to
247 *pDateOut
+= (pTm
->tm_year
- 1900) * 365;
249 /* Add the leap days in the previous years between now and 1900.
250 * Note a leap year is one that is a multiple of 4
251 * but not of a 100. Except if it is a multiple of
252 * 400 then it is a leap year.
254 *pDateOut
+= ( (pTm
->tm_year
- 1) / 4 ) - ( 1900 / 4 );
255 *pDateOut
-= ( (pTm
->tm_year
- 1) / 100 ) - ( 1900 / 100 );
256 *pDateOut
+= ( (pTm
->tm_year
- 1) / 400 ) - ( 1900 / 400 );
258 /* Set the leap year flag if the
259 * current year specified by tm_year is a
260 * leap year. This will be used to add a day
263 if( isleap( pTm
->tm_year
) )
266 /* Add the number of days corresponding to
269 switch( pTm
->tm_mon
)
275 *pDateOut
+= ( 59 + leapYear
);
278 *pDateOut
+= ( 90 + leapYear
);
281 *pDateOut
+= ( 120 + leapYear
);
284 *pDateOut
+= ( 151 + leapYear
);
287 *pDateOut
+= ( 181 + leapYear
);
290 *pDateOut
+= ( 212 + leapYear
);
293 *pDateOut
+= ( 243 + leapYear
);
296 *pDateOut
+= ( 273 + leapYear
);
299 *pDateOut
+= ( 304 + leapYear
);
302 *pDateOut
+= ( 334 + leapYear
);
305 /* Add the number of days in this month.
307 *pDateOut
+= pTm
->tm_mday
;
309 /* Add the number of seconds, minutes, and hours
310 * to the DATE. Note these are the fracionnal part
311 * of the DATE so seconds / number of seconds in a day.
313 *pDateOut
+= pTm
->tm_hour
/ 24.0;
314 *pDateOut
+= pTm
->tm_min
/ 1440.0;
315 *pDateOut
+= pTm
->tm_sec
/ 86400.0;
321 /******************************************************************************
322 * DateToTm [INTERNAL]
324 * This function converts a windows DATE to a tm structure.
326 * It does not fill all the fields of the tm structure.
327 * Here is a list of the fields that are filled:
328 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
330 * Note this function does not support dates before the January 1, 1900
331 * or ( dateIn < 2.0 ).
333 * Returns TRUE if successful.
335 static BOOL
DateToTm( DATE dateIn
, DWORD dwFlags
, struct tm
* pTm
)
337 /* Do not process dates smaller than January 1, 1900.
338 * Which corresponds to 2.0 in the windows DATE format.
342 double decimalPart
= 0.0;
343 double wholePart
= 0.0;
345 memset(pTm
,0,sizeof(*pTm
));
347 /* Because of the nature of DATE format which
348 * associates 2.0 to January 1, 1900. We will
349 * remove 1.0 from the whole part of the DATE
350 * so that in the following code 1.0
351 * will correspond to January 1, 1900.
352 * This simplifies the processing of the DATE value.
356 wholePart
= (double) floor( dateIn
);
357 decimalPart
= fmod( dateIn
, wholePart
);
359 if( !(dwFlags
& VAR_TIMEVALUEONLY
) )
363 double yearsSince1900
= 0;
364 /* Start at 1900, this is where the DATE time 0.0 starts.
367 /* find in what year the day in the "wholePart" falls into.
368 * add the value to the year field.
370 yearsSince1900
= floor( (wholePart
/ DAYS_IN_ONE_YEAR
) + 0.001 );
371 pTm
->tm_year
+= yearsSince1900
;
372 /* determine if this is a leap year.
374 if( isleap( pTm
->tm_year
) )
380 /* find what day of that year the "wholePart" corresponds to.
381 * Note: nDay is in [1-366] format
383 nDay
= (int) ( wholePart
- floor( yearsSince1900
* DAYS_IN_ONE_YEAR
) );
384 /* Set the tm_yday value.
385 * Note: The day must be converted from [1-366] to [0-365]
387 /*pTm->tm_yday = nDay - 1;*/
388 /* find which month this day corresponds to.
395 else if( nDay
<= ( 59 + leapYear
) )
397 pTm
->tm_mday
= nDay
- 31;
400 else if( nDay
<= ( 90 + leapYear
) )
402 pTm
->tm_mday
= nDay
- ( 59 + leapYear
);
405 else if( nDay
<= ( 120 + leapYear
) )
407 pTm
->tm_mday
= nDay
- ( 90 + leapYear
);
410 else if( nDay
<= ( 151 + leapYear
) )
412 pTm
->tm_mday
= nDay
- ( 120 + leapYear
);
415 else if( nDay
<= ( 181 + leapYear
) )
417 pTm
->tm_mday
= nDay
- ( 151 + leapYear
);
420 else if( nDay
<= ( 212 + leapYear
) )
422 pTm
->tm_mday
= nDay
- ( 181 + leapYear
);
425 else if( nDay
<= ( 243 + leapYear
) )
427 pTm
->tm_mday
= nDay
- ( 212 + leapYear
);
430 else if( nDay
<= ( 273 + leapYear
) )
432 pTm
->tm_mday
= nDay
- ( 243 + leapYear
);
435 else if( nDay
<= ( 304 + leapYear
) )
437 pTm
->tm_mday
= nDay
- ( 273 + leapYear
);
440 else if( nDay
<= ( 334 + leapYear
) )
442 pTm
->tm_mday
= nDay
- ( 304 + leapYear
);
445 else if( nDay
<= ( 365 + leapYear
) )
447 pTm
->tm_mday
= nDay
- ( 334 + leapYear
);
451 if( !(dwFlags
& VAR_DATEVALUEONLY
) )
453 /* find the number of seconds in this day.
454 * fractional part times, hours, minutes, seconds.
456 pTm
->tm_hour
= (int) ( decimalPart
* 24 );
457 pTm
->tm_min
= (int) ( ( ( decimalPart
* 24 ) - pTm
->tm_hour
) * 60 );
458 pTm
->tm_sec
= (int) ( ( ( decimalPart
* 24 * 60 ) - ( pTm
->tm_hour
* 60 ) - pTm
->tm_min
) * 60 );
467 /******************************************************************************
468 * SizeOfVariantData [INTERNAL]
470 * This function finds the size of the data referenced by a Variant based
471 * the type "vt" of the Variant.
473 static int SizeOfVariantData( VARIANT
* parg
)
476 switch( V_VT(parg
) & VT_TYPEMASK
)
479 size
= sizeof(short);
491 size
= sizeof(unsigned short);
494 size
= sizeof(unsigned int);
497 size
= sizeof(unsigned long);
500 size
= sizeof(float);
503 size
= sizeof(double);
509 size
= sizeof(VARIANT_BOOL
);
512 size
= sizeof(void*);
519 FIXME("Add size information for type vt=%d\n", V_VT(parg
) & VT_TYPEMASK
);
525 /******************************************************************************
526 * StringDupAtoBstr [INTERNAL]
529 static BSTR
StringDupAtoBstr( char* strIn
)
532 OLECHAR
* pNewString
= NULL
;
533 pNewString
= HEAP_strdupAtoW( GetProcessHeap(), 0, strIn
);
534 bstr
= SysAllocString( pNewString
);
535 HeapFree( GetProcessHeap(), 0, pNewString
);
539 /******************************************************************************
542 * Round the double value to the nearest integer value.
544 static double round( double d
)
546 double decimals
= 0.0, integerValue
= 0.0, roundedValue
= 0.0;
547 BOOL bEvenNumber
= FALSE
;
550 /* Save the sign of the number
552 nSign
= (d
>= 0.0) ? 1 : -1;
555 /* Remove the decimals.
557 integerValue
= floor( d
);
559 /* Set the Even flag. This is used to round the number when
560 * the decimals are exactly 1/2. If the integer part is
561 * odd the number is rounded up. If the integer part
562 * is even the number is rounded down. Using this method
563 * numbers are rounded up|down half the time.
565 bEvenNumber
= (((short)fmod(integerValue
, 2)) == 0) ? TRUE
: FALSE
;
567 /* Remove the integral part of the number.
569 decimals
= d
- integerValue
;
571 /* Note: Ceil returns the smallest integer that is greater that x.
572 * and floor returns the largest integer that is less than or equal to x.
576 /* If the decimal part is greater than 1/2
578 roundedValue
= ceil( d
);
580 else if( decimals
< 0.5 )
582 /* If the decimal part is smaller than 1/2
584 roundedValue
= floor( d
);
588 /* the decimals are exactly 1/2 so round according to
589 * the bEvenNumber flag.
593 roundedValue
= floor( d
);
597 roundedValue
= ceil( d
);
601 return roundedValue
* nSign
;
604 /******************************************************************************
605 * RemoveCharacterFromString [INTERNAL]
607 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
609 static void RemoveCharacterFromString( LPSTR str
, LPSTR strOfCharToRemove
)
611 LPSTR pNewString
= NULL
;
612 LPSTR strToken
= NULL
;
615 /* Check if we have a valid argument
619 pNewString
= strdup( str
);
621 strToken
= strtok( pNewString
, strOfCharToRemove
);
622 while( strToken
!= NULL
) {
623 strcat( str
, strToken
);
624 strToken
= strtok( NULL
, strOfCharToRemove
);
631 /******************************************************************************
632 * GetValidRealString [INTERNAL]
634 * Checks if the string is of proper format to be converted to a real value.
636 static BOOL
IsValidRealString( LPSTR strRealString
)
638 /* Real values that have a decimal point are required to either have
639 * digits before or after the decimal point. We will assume that
640 * we do not have any digits at either position. If we do encounter
641 * some we will disable this flag.
643 BOOL bDigitsRequired
= TRUE
;
644 /* Processed fields in the string representation of the real number.
646 BOOL bWhiteSpaceProcessed
= FALSE
;
647 BOOL bFirstSignProcessed
= FALSE
;
648 BOOL bFirstDigitsProcessed
= FALSE
;
649 BOOL bDecimalPointProcessed
= FALSE
;
650 BOOL bSecondDigitsProcessed
= FALSE
;
651 BOOL bExponentProcessed
= FALSE
;
652 BOOL bSecondSignProcessed
= FALSE
;
653 BOOL bThirdDigitsProcessed
= FALSE
;
654 /* Assume string parameter "strRealString" is valid and try to disprove it.
656 BOOL bValidRealString
= TRUE
;
658 /* Used to count the number of tokens in the "strRealString".
660 LPSTR strToken
= NULL
;
664 /* Check if we have a valid argument
666 if( strRealString
== NULL
)
668 bValidRealString
= FALSE
;
671 if( bValidRealString
== TRUE
)
673 /* Make sure we only have ONE token in the string.
675 strToken
= strtok( strRealString
, " " );
676 while( strToken
!= NULL
) {
678 strToken
= strtok( NULL
, " " );
683 bValidRealString
= FALSE
;
688 /* Make sure this token contains only valid characters.
689 * The string argument to atof has the following form:
690 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
691 * Whitespace consists of space and|or <TAB> characters, which are ignored.
692 * Sign is either plus '+' or minus '-'.
693 * Digits are one or more decimal digits.
694 * Note: If no digits appear before the decimal point, at least one must
695 * appear after the decimal point.
696 * The decimal digits may be followed by an exponent.
697 * An Exponent consists of an introductory letter ( D, d, E, or e) and
698 * an optionally signed decimal integer.
700 pChar
= strRealString
;
701 while( bValidRealString
== TRUE
&& *pChar
!= '\0' )
709 if( bWhiteSpaceProcessed
||
710 bFirstSignProcessed
||
711 bFirstDigitsProcessed
||
712 bDecimalPointProcessed
||
713 bSecondDigitsProcessed
||
714 bExponentProcessed
||
715 bSecondSignProcessed
||
716 bThirdDigitsProcessed
)
718 bValidRealString
= FALSE
;
725 if( bFirstSignProcessed
== FALSE
)
727 if( bFirstDigitsProcessed
||
728 bDecimalPointProcessed
||
729 bSecondDigitsProcessed
||
730 bExponentProcessed
||
731 bSecondSignProcessed
||
732 bThirdDigitsProcessed
)
734 bValidRealString
= FALSE
;
736 bWhiteSpaceProcessed
= TRUE
;
737 bFirstSignProcessed
= TRUE
;
739 else if( bSecondSignProcessed
== FALSE
)
741 /* Note: The exponent must be present in
742 * order to accept the second sign...
744 if( bExponentProcessed
== FALSE
||
745 bThirdDigitsProcessed
||
748 bValidRealString
= FALSE
;
750 bFirstSignProcessed
= TRUE
;
751 bWhiteSpaceProcessed
= TRUE
;
752 bFirstDigitsProcessed
= TRUE
;
753 bDecimalPointProcessed
= TRUE
;
754 bSecondDigitsProcessed
= TRUE
;
755 bSecondSignProcessed
= TRUE
;
771 if( bFirstDigitsProcessed
== FALSE
)
773 if( bDecimalPointProcessed
||
774 bSecondDigitsProcessed
||
775 bExponentProcessed
||
776 bSecondSignProcessed
||
777 bThirdDigitsProcessed
)
779 bValidRealString
= FALSE
;
781 bFirstSignProcessed
= TRUE
;
782 bWhiteSpaceProcessed
= TRUE
;
783 /* We have found some digits before the decimal point
784 * so disable the "Digits required" flag.
786 bDigitsRequired
= FALSE
;
788 else if( bSecondDigitsProcessed
== FALSE
)
790 if( bExponentProcessed
||
791 bSecondSignProcessed
||
792 bThirdDigitsProcessed
)
794 bValidRealString
= FALSE
;
796 bFirstSignProcessed
= TRUE
;
797 bWhiteSpaceProcessed
= TRUE
;
798 bFirstDigitsProcessed
= TRUE
;
799 bDecimalPointProcessed
= TRUE
;
800 /* We have found some digits after the decimal point
801 * so disable the "Digits required" flag.
803 bDigitsRequired
= FALSE
;
805 else if( bThirdDigitsProcessed
== FALSE
)
807 /* Getting here means everything else should be processed.
808 * If we get anything else than a decimal following this
809 * digit it will be flagged by the other cases, so
810 * we do not really need to do anything in here.
814 /* If DecimalPoint...
817 if( bDecimalPointProcessed
||
818 bSecondDigitsProcessed
||
819 bExponentProcessed
||
820 bSecondSignProcessed
||
821 bThirdDigitsProcessed
)
823 bValidRealString
= FALSE
;
825 bFirstSignProcessed
= TRUE
;
826 bWhiteSpaceProcessed
= TRUE
;
827 bFirstDigitsProcessed
= TRUE
;
828 bDecimalPointProcessed
= TRUE
;
836 if( bExponentProcessed
||
837 bSecondSignProcessed
||
838 bThirdDigitsProcessed
||
841 bValidRealString
= FALSE
;
843 bFirstSignProcessed
= TRUE
;
844 bWhiteSpaceProcessed
= TRUE
;
845 bFirstDigitsProcessed
= TRUE
;
846 bDecimalPointProcessed
= TRUE
;
847 bSecondDigitsProcessed
= TRUE
;
848 bExponentProcessed
= TRUE
;
851 bValidRealString
= FALSE
;
854 /* Process next character.
859 /* If the required digits were not present we have an invalid
860 * string representation of a real number.
862 if( bDigitsRequired
== TRUE
)
864 bValidRealString
= FALSE
;
867 return bValidRealString
;
871 /******************************************************************************
874 * This function dispatches execution to the proper conversion API
875 * to do the necessary coercion.
877 * FIXME: Passing down dwFlags to the conversion functions is wrong, this
878 * is a different flagmask. Check MSDN.
880 static HRESULT
Coerce( VARIANTARG
* pd
, LCID lcid
, ULONG dwFlags
, VARIANTARG
* ps
, VARTYPE vt
)
883 unsigned short vtFrom
= 0;
884 vtFrom
= V_VT(ps
) & VT_TYPEMASK
;
887 /* Note: Since "long" and "int" values both have 4 bytes and are
888 * both signed integers "int" will be treated as "long" in the
890 * The same goes for their unsigned versions.
893 /* Trivial Case: If the coercion is from two types that are
894 * identical then we can blindly copy from one argument to another.*/
897 return VariantCopy(pd
,ps
);
900 /* Cases requiring thought*/
905 res
= VariantClear( pd
);
908 res
= VariantClear( pd
);
918 res
= VariantCopy( pd
, ps
);
921 res
= VarI1FromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,cVal
) );
925 res
= VarI1FromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,cVal
) );
928 res
= VarI1FromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,cVal
) );
931 res
= VarI1FromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,cVal
) );
935 res
= VarI1FromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,cVal
) );
938 res
= VarI1FromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,cVal
) );
941 res
= VarI1FromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,cVal
) );
944 res
= VarI1FromDate( V_UNION(ps
,date
), &V_UNION(pd
,cVal
) );
947 res
= VarI1FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,cVal
) );
950 res
= VarI1FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,cVal
) );
953 res
= VarI1FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,cVal
) );
956 /*res = VarI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cVal) );*/
958 /*res = VarI1FromDec( V_UNION(ps,decVal), &V_UNION(pd,cVal) );*/
961 res
= DISP_E_TYPEMISMATCH
;
962 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
971 res
= VarI2FromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,iVal
) );
974 res
= VariantCopy( pd
, ps
);
978 res
= VarI2FromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,iVal
) );
981 res
= VarI2FromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,iVal
) );
984 res
= VarI2FromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,iVal
) );
988 res
= VarI2FromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,iVal
) );
991 res
= VarI2FromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,iVal
) );
994 res
= VarI2FromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,iVal
) );
997 res
= VarI2FromDate( V_UNION(ps
,date
), &V_UNION(pd
,iVal
) );
1000 res
= VarI2FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,iVal
) );
1003 res
= VarI2FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,iVal
) );
1006 res
= VarI2FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,iVal
) );
1008 case( VT_DISPATCH
):
1009 /*res = VarI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,iVal) );*/
1011 /*res = VarI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,iVal) );*/
1014 res
= DISP_E_TYPEMISMATCH
;
1015 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1025 res
= VarI4FromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,lVal
) );
1028 res
= VarI4FromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,lVal
) );
1032 res
= VariantCopy( pd
, ps
);
1035 res
= VarI4FromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,lVal
) );
1038 res
= VarI4FromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,lVal
) );
1042 res
= VarI4FromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,lVal
) );
1045 res
= VarI4FromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,lVal
) );
1048 res
= VarI4FromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,lVal
) );
1051 res
= VarI4FromDate( V_UNION(ps
,date
), &V_UNION(pd
,lVal
) );
1054 res
= VarI4FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,lVal
) );
1057 res
= VarI4FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,lVal
) );
1060 res
= VarI4FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,lVal
) );
1062 case( VT_DISPATCH
):
1063 /*res = VarI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,lVal) );*/
1065 /*res = VarI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,lVal) );*/
1068 res
= DISP_E_TYPEMISMATCH
;
1069 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1078 res
= VarUI1FromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,bVal
) );
1081 res
= VarUI1FromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,bVal
) );
1085 res
= VarUI1FromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,bVal
) );
1088 res
= VariantCopy( pd
, ps
);
1091 res
= VarUI1FromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,bVal
) );
1095 res
= VarUI1FromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,bVal
) );
1098 res
= VarUI1FromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,bVal
) );
1101 res
= VarUI1FromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,bVal
) );
1104 res
= VarUI1FromDate( V_UNION(ps
,date
), &V_UNION(pd
,bVal
) );
1107 res
= VarUI1FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,bVal
) );
1110 res
= VarUI1FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,bVal
) );
1113 res
= VarUI1FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,bVal
) );
1115 case( VT_DISPATCH
):
1116 /*res = VarUI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,bVal) );*/
1118 /*res = VarUI1FromDec( V_UNION(ps,deiVal), &V_UNION(pd,bVal) );*/
1121 res
= DISP_E_TYPEMISMATCH
;
1122 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1131 res
= VarUI2FromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,uiVal
) );
1134 res
= VarUI2FromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,uiVal
) );
1138 res
= VarUI2FromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,uiVal
) );
1141 res
= VarUI2FromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,uiVal
) );
1144 res
= VariantCopy( pd
, ps
);
1148 res
= VarUI2FromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,uiVal
) );
1151 res
= VarUI2FromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,uiVal
) );
1154 res
= VarUI2FromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,uiVal
) );
1157 res
= VarUI2FromDate( V_UNION(ps
,date
), &V_UNION(pd
,uiVal
) );
1160 res
= VarUI2FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,uiVal
) );
1163 res
= VarUI2FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,uiVal
) );
1166 res
= VarUI2FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,uiVal
) );
1168 case( VT_DISPATCH
):
1169 /*res = VarUI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,uiVal) );*/
1171 /*res = VarUI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,uiVal) );*/
1174 res
= DISP_E_TYPEMISMATCH
;
1175 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1185 res
= VarUI4FromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,ulVal
) );
1188 res
= VarUI4FromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,ulVal
) );
1192 res
= VarUI4FromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,ulVal
) );
1195 res
= VarUI4FromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,ulVal
) );
1198 res
= VarUI4FromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,ulVal
) );
1201 res
= VariantCopy( pd
, ps
);
1204 res
= VarUI4FromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,ulVal
) );
1207 res
= VarUI4FromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,ulVal
) );
1210 res
= VarUI4FromDate( V_UNION(ps
,date
), &V_UNION(pd
,ulVal
) );
1213 res
= VarUI4FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,ulVal
) );
1216 res
= VarUI4FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,ulVal
) );
1219 res
= VarUI4FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,ulVal
) );
1221 case( VT_DISPATCH
):
1222 /*res = VarUI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,ulVal) );*/
1224 /*res = VarUI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,ulVal) );*/
1227 res
= DISP_E_TYPEMISMATCH
;
1228 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1237 res
= VarR4FromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,fltVal
) );
1240 res
= VarR4FromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,fltVal
) );
1244 res
= VarR4FromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,fltVal
) );
1247 res
= VarR4FromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,fltVal
) );
1250 res
= VarR4FromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,fltVal
) );
1254 res
= VarR4FromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,fltVal
) );
1257 res
= VariantCopy( pd
, ps
);
1260 res
= VarR4FromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,fltVal
) );
1263 res
= VarR4FromDate( V_UNION(ps
,date
), &V_UNION(pd
,fltVal
) );
1266 res
= VarR4FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,fltVal
) );
1269 res
= VarR4FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,fltVal
) );
1272 res
= VarR4FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,fltVal
) );
1274 case( VT_DISPATCH
):
1275 /*res = VarR4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,fltVal) );*/
1277 /*res = VarR4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,fltVal) );*/
1280 res
= DISP_E_TYPEMISMATCH
;
1281 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1290 res
= VarR8FromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,dblVal
) );
1293 res
= VarR8FromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,dblVal
) );
1297 res
= VarR8FromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,dblVal
) );
1300 res
= VarR8FromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,dblVal
) );
1303 res
= VarR8FromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,dblVal
) );
1307 res
= VarR8FromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,dblVal
) );
1310 res
= VarR8FromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,dblVal
) );
1313 res
= VariantCopy( pd
, ps
);
1316 res
= VarR8FromDate( V_UNION(ps
,date
), &V_UNION(pd
,dblVal
) );
1319 res
= VarR8FromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,dblVal
) );
1322 res
= VarR8FromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,dblVal
) );
1325 res
= VarR8FromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,dblVal
) );
1327 case( VT_DISPATCH
):
1328 /*res = VarR8FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,dblVal) );*/
1330 /*res = VarR8FromDec( V_UNION(ps,deiVal), &V_UNION(pd,dblVal) );*/
1333 res
= DISP_E_TYPEMISMATCH
;
1334 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1343 res
= VarDateFromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,date
) );
1346 res
= VarDateFromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,date
) );
1349 res
= VarDateFromInt( V_UNION(ps
,intVal
), &V_UNION(pd
,date
) );
1352 res
= VarDateFromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,date
) );
1355 res
= VarDateFromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,date
) );
1358 res
= VarDateFromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,date
) );
1361 res
= VarDateFromUint( V_UNION(ps
,uintVal
), &V_UNION(pd
,date
) );
1364 res
= VarDateFromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,date
) );
1367 res
= VarDateFromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,date
) );
1370 res
= VarDateFromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,date
) );
1373 res
= VariantCopy( pd
, ps
);
1376 res
= VarDateFromBool( V_UNION(ps
,boolVal
), &V_UNION(pd
,date
) );
1379 res
= VarDateFromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,date
) );
1382 res
= VarDateFromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,date
) );
1384 case( VT_DISPATCH
):
1385 /*res = VarDateFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,date) );*/
1387 /*res = VarDateFromDec( V_UNION(ps,deiVal), &V_UNION(pd,date) );*/
1390 res
= DISP_E_TYPEMISMATCH
;
1391 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1400 res
= VarBoolFromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,boolVal
) );
1403 res
= VarBoolFromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,boolVal
) );
1406 res
= VarBoolFromInt( V_UNION(ps
,intVal
), &V_UNION(pd
,boolVal
) );
1409 res
= VarBoolFromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,boolVal
) );
1412 res
= VarBoolFromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,boolVal
) );
1415 res
= VarBoolFromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,boolVal
) );
1418 res
= VarBoolFromUint( V_UNION(ps
,uintVal
), &V_UNION(pd
,boolVal
) );
1421 res
= VarBoolFromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,boolVal
) );
1424 res
= VarBoolFromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,boolVal
) );
1427 res
= VarBoolFromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,boolVal
) );
1430 res
= VarBoolFromDate( V_UNION(ps
,date
), &V_UNION(pd
,boolVal
) );
1433 res
= VariantCopy( pd
, ps
);
1436 res
= VarBoolFromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,boolVal
) );
1439 res
= VarBoolFromCy( V_UNION(ps
,cyVal
), &V_UNION(pd
,boolVal
) );
1441 case( VT_DISPATCH
):
1442 /*res = VarBoolFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,boolVal) );*/
1444 /*res = VarBoolFromDec( V_UNION(ps,deiVal), &V_UNION(pd,boolVal) );*/
1447 res
= DISP_E_TYPEMISMATCH
;
1448 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1457 if ((V_UNION(pd
,bstrVal
) = SysAllocStringLen(NULL
, 0)))
1460 res
= E_OUTOFMEMORY
;
1463 res
= VarBstrFromI1( V_UNION(ps
,cVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1466 res
= VarBstrFromI2( V_UNION(ps
,iVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1469 res
= VarBstrFromInt( V_UNION(ps
,intVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1472 res
= VarBstrFromI4( V_UNION(ps
,lVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1475 res
= VarBstrFromUI1( V_UNION(ps
,bVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1478 res
= VarBstrFromUI2( V_UNION(ps
,uiVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1481 res
= VarBstrFromUint( V_UNION(ps
,uintVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1484 res
= VarBstrFromUI4( V_UNION(ps
,ulVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1487 res
= VarBstrFromR4( V_UNION(ps
,fltVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1490 res
= VarBstrFromR8( V_UNION(ps
,dblVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1493 res
= VarBstrFromDate( V_UNION(ps
,date
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1496 res
= VarBstrFromBool( V_UNION(ps
,boolVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1499 res
= VariantCopy( pd
, ps
);
1502 res
= VarBstrFromCy( V_UNION(ps
,cyVal
), lcid
, 0, &V_UNION(pd
,bstrVal
) );
1504 case( VT_DISPATCH
):
1505 /*res = VarBstrFromDisp( V_UNION(ps,pdispVal), lcid, 0, &(pd,bstrVal) );*/
1507 /*res = VarBstrFromDec( V_UNION(ps,deiVal), lcid, 0, &(pd,bstrVal) );*/
1510 res
= DISP_E_TYPEMISMATCH
;
1511 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1520 res
= VarCyFromI1( V_UNION(ps
,cVal
), &V_UNION(pd
,cyVal
) );
1523 res
= VarCyFromI2( V_UNION(ps
,iVal
), &V_UNION(pd
,cyVal
) );
1526 res
= VarCyFromInt( V_UNION(ps
,intVal
), &V_UNION(pd
,cyVal
) );
1529 res
= VarCyFromI4( V_UNION(ps
,lVal
), &V_UNION(pd
,cyVal
) );
1532 res
= VarCyFromUI1( V_UNION(ps
,bVal
), &V_UNION(pd
,cyVal
) );
1535 res
= VarCyFromUI2( V_UNION(ps
,uiVal
), &V_UNION(pd
,cyVal
) );
1538 res
= VarCyFromUint( V_UNION(ps
,uintVal
), &V_UNION(pd
,cyVal
) );
1541 res
= VarCyFromUI4( V_UNION(ps
,ulVal
), &V_UNION(pd
,cyVal
) );
1544 res
= VarCyFromR4( V_UNION(ps
,fltVal
), &V_UNION(pd
,cyVal
) );
1547 res
= VarCyFromR8( V_UNION(ps
,dblVal
), &V_UNION(pd
,cyVal
) );
1550 res
= VarCyFromDate( V_UNION(ps
,date
), &V_UNION(pd
,cyVal
) );
1553 res
= VarCyFromBool( V_UNION(ps
,date
), &V_UNION(pd
,cyVal
) );
1556 res
= VariantCopy( pd
, ps
);
1559 res
= VarCyFromStr( V_UNION(ps
,bstrVal
), lcid
, 0, &V_UNION(pd
,cyVal
) );
1561 case( VT_DISPATCH
):
1562 /*res = VarCyFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cyVal) );*/
1564 /*res = VarCyFromDec( V_UNION(ps,deiVal), &V_UNION(pd,cyVal) );*/
1568 res
= DISP_E_TYPEMISMATCH
;
1569 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1575 res
= DISP_E_TYPEMISMATCH
;
1576 FIXME("Coercion from %d to %d\n", vtFrom
, vt
);
1583 /******************************************************************************
1584 * ValidateVtRange [INTERNAL]
1586 * Used internally by the hi-level Variant API to determine
1587 * if the vartypes are valid.
1589 static HRESULT WINAPI
ValidateVtRange( VARTYPE vt
)
1591 /* if by value we must make sure it is in the
1592 * range of the valid types.
1594 if( ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1596 return DISP_E_BADVARTYPE
;
1602 /******************************************************************************
1603 * ValidateVartype [INTERNAL]
1605 * Used internally by the hi-level Variant API to determine
1606 * if the vartypes are valid.
1608 static HRESULT WINAPI
ValidateVariantType( VARTYPE vt
)
1612 /* check if we have a valid argument.
1616 /* if by reference check that the type is in
1617 * the valid range and that it is not of empty or null type
1619 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1620 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1621 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1629 res
= ValidateVtRange( vt
);
1635 /******************************************************************************
1636 * ValidateVt [INTERNAL]
1638 * Used internally by the hi-level Variant API to determine
1639 * if the vartypes are valid.
1641 static HRESULT WINAPI
ValidateVt( VARTYPE vt
)
1645 /* check if we have a valid argument.
1649 /* if by reference check that the type is in
1650 * the valid range and that it is not of empty or null type
1652 if( ( vt
& VT_TYPEMASK
) == VT_EMPTY
||
1653 ( vt
& VT_TYPEMASK
) == VT_NULL
||
1654 ( vt
& VT_TYPEMASK
) > VT_MAXVALIDTYPE
)
1656 res
= DISP_E_BADVARTYPE
;
1662 res
= ValidateVtRange( vt
);
1672 /******************************************************************************
1673 * VariantInit [OLEAUT32.8]
1675 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1676 * contents of the Variant.
1678 void WINAPI
VariantInit(VARIANTARG
* pvarg
)
1680 TRACE("(%p)\n",pvarg
);
1682 memset(pvarg
, 0, sizeof (VARIANTARG
));
1683 V_VT(pvarg
) = VT_EMPTY
;
1688 /******************************************************************************
1689 * VariantClear [OLEAUT32.9]
1691 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1692 * sets the wReservedX field to 0. The current contents of the VARIANT are
1693 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1694 * released. If VT_ARRAY the array is freed.
1696 HRESULT WINAPI
VariantClear(VARIANTARG
* pvarg
)
1699 TRACE("(%p)\n",pvarg
);
1701 res
= ValidateVariantType( V_VT(pvarg
) );
1704 if( !( V_VT(pvarg
) & VT_BYREF
) )
1707 * The VT_ARRAY flag is a special case of a safe array.
1709 if ( (V_VT(pvarg
) & VT_ARRAY
) != 0)
1711 SafeArrayDestroy(V_UNION(pvarg
,parray
));
1715 switch( V_VT(pvarg
) & VT_TYPEMASK
)
1718 SysFreeString( V_UNION(pvarg
,bstrVal
) );
1720 case( VT_DISPATCH
):
1721 if(V_UNION(pvarg
,pdispVal
)!=NULL
)
1722 ICOM_CALL(Release
,V_UNION(pvarg
,pdispVal
));
1725 VariantClear(V_UNION(pvarg
,pvarVal
));
1728 if(V_UNION(pvarg
,punkVal
)!=NULL
)
1729 ICOM_CALL(Release
,V_UNION(pvarg
,punkVal
));
1731 case( VT_SAFEARRAY
):
1732 SafeArrayDestroy(V_UNION(pvarg
,parray
));
1741 * Empty all the fields and mark the type as empty.
1743 memset(pvarg
, 0, sizeof (VARIANTARG
));
1744 V_VT(pvarg
) = VT_EMPTY
;
1750 /******************************************************************************
1751 * VariantCopy [OLEAUT32.10]
1753 * Frees up the designation variant and makes a copy of the source.
1755 HRESULT WINAPI
VariantCopy(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
)
1759 TRACE("(%p, %p), vt=%d\n", pvargDest
, pvargSrc
, V_VT(pvargSrc
));
1761 res
= ValidateVariantType( V_VT(pvargSrc
) );
1763 /* If the pointer are to the same variant we don't need
1766 if( pvargDest
!= pvargSrc
&& res
== S_OK
)
1768 res
= VariantClear( pvargDest
);
1772 if( V_VT(pvargSrc
) & VT_BYREF
)
1774 /* In the case of byreference we only need
1775 * to copy the pointer.
1777 pvargDest
->n1
.n2
.n3
= pvargSrc
->n1
.n2
.n3
;
1778 V_VT(pvargDest
) = V_VT(pvargSrc
);
1783 * The VT_ARRAY flag is another way to designate a safe array.
1785 if (V_VT(pvargSrc
) & VT_ARRAY
)
1787 SafeArrayCopy(V_UNION(pvargSrc
,parray
), &V_UNION(pvargDest
,parray
));
1791 /* In the case of by value we need to
1792 * copy the actuall value. In the case of
1793 * VT_BSTR a copy of the string is made,
1794 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1795 * called to increment the object's reference count.
1797 switch( V_VT(pvargSrc
) & VT_TYPEMASK
)
1800 V_UNION(pvargDest
,bstrVal
) = SYSDUPSTRING( V_UNION(pvargSrc
,bstrVal
) );
1802 case( VT_DISPATCH
):
1803 V_UNION(pvargDest
,pdispVal
) = V_UNION(pvargSrc
,pdispVal
);
1804 if (V_UNION(pvargDest
,pdispVal
)!=NULL
)
1805 ICOM_CALL(AddRef
,V_UNION(pvargDest
,pdispVal
));
1808 VariantCopy(V_UNION(pvargDest
,pvarVal
),V_UNION(pvargSrc
,pvarVal
));
1811 V_UNION(pvargDest
,punkVal
) = V_UNION(pvargSrc
,punkVal
);
1812 if (V_UNION(pvargDest
,pdispVal
)!=NULL
)
1813 ICOM_CALL(AddRef
,V_UNION(pvargDest
,punkVal
));
1815 case( VT_SAFEARRAY
):
1816 SafeArrayCopy(V_UNION(pvargSrc
,parray
), &V_UNION(pvargDest
,parray
));
1819 pvargDest
->n1
.n2
.n3
= pvargSrc
->n1
.n2
.n3
;
1824 V_VT(pvargDest
) = V_VT(pvargSrc
);
1833 /******************************************************************************
1834 * VariantCopyInd [OLEAUT32.11]
1836 * Frees up the destination variant and makes a copy of the source. If
1837 * the source is of type VT_BYREF it performs the necessary indirections.
1839 HRESULT WINAPI
VariantCopyInd(VARIANT
* pvargDest
, VARIANTARG
* pvargSrc
)
1843 TRACE("(%p, %p)\n", pvargDest
, pvargSrc
);
1845 res
= ValidateVariantType( V_VT(pvargSrc
) );
1850 if( V_VT(pvargSrc
) & VT_BYREF
)
1853 VariantInit( &varg
);
1855 /* handle the in place copy.
1857 if( pvargDest
== pvargSrc
)
1859 /* we will use a copy of the source instead.
1861 res
= VariantCopy( &varg
, pvargSrc
);
1867 res
= VariantClear( pvargDest
);
1872 * The VT_ARRAY flag is another way to designate a safearray variant.
1874 if ( V_VT(pvargSrc
) & VT_ARRAY
)
1876 SafeArrayCopy(*V_UNION(pvargSrc
,pparray
), &V_UNION(pvargDest
,parray
));
1880 /* In the case of by reference we need
1881 * to copy the date pointed to by the variant.
1884 /* Get the variant type.
1886 switch( V_VT(pvargSrc
) & VT_TYPEMASK
)
1889 V_UNION(pvargDest
,bstrVal
) = SYSDUPSTRING( *(V_UNION(pvargSrc
,pbstrVal
)) );
1891 case( VT_DISPATCH
):
1895 /* Prevent from cycling. According to tests on
1896 * VariantCopyInd in Windows and the documentation
1897 * this API dereferences the inner Variants to only one depth.
1898 * If the inner Variant itself contains an
1899 * other inner variant the E_INVALIDARG error is
1902 if( pvargSrc
->n1
.n2
.wReserved1
& PROCESSING_INNER_VARIANT
)
1904 /* If we get here we are attempting to deference
1905 * an inner variant that that is itself contained
1906 * in an inner variant so report E_INVALIDARG error.
1912 /* Set the processing inner variant flag.
1913 * We will set this flag in the inner variant
1914 * that will be passed to the VariantCopyInd function.
1916 (V_UNION(pvargSrc
,pvarVal
))->n1
.n2
.wReserved1
|= PROCESSING_INNER_VARIANT
;
1918 /* Dereference the inner variant.
1920 res
= VariantCopyInd( pvargDest
, V_UNION(pvargSrc
,pvarVal
) );
1921 /* We must also copy its type, I think.
1923 V_VT(pvargSrc
) = V_VT(V_UNION(pvargSrc
,pvarVal
));
1929 case( VT_SAFEARRAY
):
1930 SafeArrayCopy(*V_UNION(pvargSrc
,pparray
), &V_UNION(pvargDest
,parray
));
1933 /* This is a by reference Variant which means that the union
1934 * part of the Variant contains a pointer to some data of
1935 * type "V_VT(pvargSrc) & VT_TYPEMASK".
1936 * We will deference this data in a generic fashion using
1937 * the void pointer "Variant.u.byref".
1938 * We will copy this data into the union of the destination
1941 memcpy( &pvargDest
->n1
.n2
, V_UNION(pvargSrc
,byref
), SizeOfVariantData( pvargSrc
) );
1946 V_VT(pvargDest
) = V_VT(pvargSrc
) & VT_TYPEMASK
;
1950 /* this should not fail.
1952 VariantClear( &varg
);
1956 res
= VariantCopy( pvargDest
, pvargSrc
);
1962 /******************************************************************************
1963 * VariantChangeType [OLEAUT32.12]
1965 HRESULT WINAPI
VariantChangeType(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1966 USHORT wFlags
, VARTYPE vt
)
1968 return VariantChangeTypeEx( pvargDest
, pvargSrc
, 0, wFlags
, vt
);
1971 /******************************************************************************
1972 * VariantChangeTypeEx [OLEAUT32.147]
1974 HRESULT WINAPI
VariantChangeTypeEx(VARIANTARG
* pvargDest
, VARIANTARG
* pvargSrc
,
1975 LCID lcid
, USHORT wFlags
, VARTYPE vt
)
1979 VariantInit( &varg
);
1981 TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest
, pvargSrc
, lcid
, wFlags
, vt
, V_VT(pvargSrc
));
1983 /* validate our source argument.
1985 res
= ValidateVariantType( V_VT(pvargSrc
) );
1987 /* validate the vartype.
1991 res
= ValidateVt( vt
);
1994 /* if we are doing an in-place conversion make a copy of the source.
1996 if( res
== S_OK
&& pvargDest
== pvargSrc
)
1998 res
= VariantCopy( &varg
, pvargSrc
);
2004 /* free up the destination variant.
2006 res
= VariantClear( pvargDest
);
2011 if( V_VT(pvargSrc
) & VT_BYREF
)
2013 /* Convert the source variant to a "byvalue" variant.
2016 VariantInit( &Variant
);
2017 res
= VariantCopyInd( &Variant
, pvargSrc
);
2020 res
= Coerce( pvargDest
, lcid
, wFlags
, &Variant
, vt
);
2021 /* this should not fail.
2023 VariantClear( &Variant
);
2029 /* Use the current "byvalue" source variant.
2031 res
= Coerce( pvargDest
, lcid
, wFlags
, pvargSrc
, vt
);
2034 /* this should not fail.
2036 VariantClear( &varg
);
2038 /* set the type of the destination
2041 V_VT(pvargDest
) = vt
;
2049 /******************************************************************************
2050 * VarUI1FromI2 [OLEAUT32.130]
2052 HRESULT WINAPI
VarUI1FromI2(short sIn
, BYTE
* pbOut
)
2054 TRACE("( %d, %p ), stub\n", sIn
, pbOut
);
2056 /* Check range of value.
2058 if( sIn
< UI1_MIN
|| sIn
> UI1_MAX
)
2060 return DISP_E_OVERFLOW
;
2063 *pbOut
= (BYTE
) sIn
;
2068 /******************************************************************************
2069 * VarUI1FromI4 [OLEAUT32.131]
2071 HRESULT WINAPI
VarUI1FromI4(LONG lIn
, BYTE
* pbOut
)
2073 TRACE("( %ld, %p ), stub\n", lIn
, pbOut
);
2075 /* Check range of value.
2077 if( lIn
< UI1_MIN
|| lIn
> UI1_MAX
)
2079 return DISP_E_OVERFLOW
;
2082 *pbOut
= (BYTE
) lIn
;
2088 /******************************************************************************
2089 * VarUI1FromR4 [OLEAUT32.132]
2091 HRESULT WINAPI
VarUI1FromR4(FLOAT fltIn
, BYTE
* pbOut
)
2093 TRACE("( %f, %p ), stub\n", fltIn
, pbOut
);
2095 /* Check range of value.
2097 fltIn
= round( fltIn
);
2098 if( fltIn
< UI1_MIN
|| fltIn
> UI1_MAX
)
2100 return DISP_E_OVERFLOW
;
2103 *pbOut
= (BYTE
) fltIn
;
2108 /******************************************************************************
2109 * VarUI1FromR8 [OLEAUT32.133]
2111 HRESULT WINAPI
VarUI1FromR8(double dblIn
, BYTE
* pbOut
)
2113 TRACE("( %f, %p ), stub\n", dblIn
, pbOut
);
2115 /* Check range of value.
2117 dblIn
= round( dblIn
);
2118 if( dblIn
< UI1_MIN
|| dblIn
> UI1_MAX
)
2120 return DISP_E_OVERFLOW
;
2123 *pbOut
= (BYTE
) dblIn
;
2128 /******************************************************************************
2129 * VarUI1FromDate [OLEAUT32.135]
2131 HRESULT WINAPI
VarUI1FromDate(DATE dateIn
, BYTE
* pbOut
)
2133 TRACE("( %f, %p ), stub\n", dateIn
, pbOut
);
2135 /* Check range of value.
2137 dateIn
= round( dateIn
);
2138 if( dateIn
< UI1_MIN
|| dateIn
> UI1_MAX
)
2140 return DISP_E_OVERFLOW
;
2143 *pbOut
= (BYTE
) dateIn
;
2148 /******************************************************************************
2149 * VarUI1FromBool [OLEAUT32.138]
2151 HRESULT WINAPI
VarUI1FromBool(VARIANT_BOOL boolIn
, BYTE
* pbOut
)
2153 TRACE("( %d, %p ), stub\n", boolIn
, pbOut
);
2155 *pbOut
= (BYTE
) boolIn
;
2160 /******************************************************************************
2161 * VarUI1FromI1 [OLEAUT32.237]
2163 HRESULT WINAPI
VarUI1FromI1(CHAR cIn
, BYTE
* pbOut
)
2165 TRACE("( %c, %p ), stub\n", cIn
, pbOut
);
2172 /******************************************************************************
2173 * VarUI1FromUI2 [OLEAUT32.238]
2175 HRESULT WINAPI
VarUI1FromUI2(USHORT uiIn
, BYTE
* pbOut
)
2177 TRACE("( %d, %p ), stub\n", uiIn
, pbOut
);
2179 /* Check range of value.
2181 if( uiIn
> UI1_MAX
)
2183 return DISP_E_OVERFLOW
;
2186 *pbOut
= (BYTE
) uiIn
;
2191 /******************************************************************************
2192 * VarUI1FromUI4 [OLEAUT32.239]
2194 HRESULT WINAPI
VarUI1FromUI4(ULONG ulIn
, BYTE
* pbOut
)
2196 TRACE("( %ld, %p ), stub\n", ulIn
, pbOut
);
2198 /* Check range of value.
2200 if( ulIn
> UI1_MAX
)
2202 return DISP_E_OVERFLOW
;
2205 *pbOut
= (BYTE
) ulIn
;
2211 /******************************************************************************
2212 * VarUI1FromStr [OLEAUT32.136]
2214 HRESULT WINAPI
VarUI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, BYTE
* pbOut
)
2216 double dValue
= 0.0;
2217 LPSTR pNewString
= NULL
;
2219 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pbOut
);
2221 /* Check if we have a valid argument
2223 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2224 RemoveCharacterFromString( pNewString
, "," );
2225 if( IsValidRealString( pNewString
) == FALSE
)
2227 return DISP_E_TYPEMISMATCH
;
2230 /* Convert the valid string to a floating point number.
2232 dValue
= atof( pNewString
);
2234 /* We don't need the string anymore so free it.
2236 HeapFree( GetProcessHeap(), 0 , pNewString
);
2238 /* Check range of value.
2240 dValue
= round( dValue
);
2241 if( dValue
< UI1_MIN
|| dValue
> UI1_MAX
)
2243 return DISP_E_OVERFLOW
;
2246 *pbOut
= (BYTE
) dValue
;
2251 /**********************************************************************
2252 * VarUI1FromCy [OLEAUT32.134]
2253 * Convert currency to unsigned char
2255 HRESULT WINAPI
VarUI1FromCy(CY cyIn
, BYTE
* pbOut
) {
2256 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2258 if (t
> UI1_MAX
|| t
< UI1_MIN
) return DISP_E_OVERFLOW
;
2264 /******************************************************************************
2265 * VarI2FromUI1 [OLEAUT32.48]
2267 HRESULT WINAPI
VarI2FromUI1(BYTE bIn
, short* psOut
)
2269 TRACE("( 0x%08x, %p ), stub\n", bIn
, psOut
);
2271 *psOut
= (short) bIn
;
2276 /******************************************************************************
2277 * VarI2FromI4 [OLEAUT32.49]
2279 HRESULT WINAPI
VarI2FromI4(LONG lIn
, short* psOut
)
2281 TRACE("( %lx, %p ), stub\n", lIn
, psOut
);
2283 /* Check range of value.
2285 if( lIn
< I2_MIN
|| lIn
> I2_MAX
)
2287 return DISP_E_OVERFLOW
;
2290 *psOut
= (short) lIn
;
2295 /******************************************************************************
2296 * VarI2FromR4 [OLEAUT32.50]
2298 HRESULT WINAPI
VarI2FromR4(FLOAT fltIn
, short* psOut
)
2300 TRACE("( %f, %p ), stub\n", fltIn
, psOut
);
2302 /* Check range of value.
2304 fltIn
= round( fltIn
);
2305 if( fltIn
< I2_MIN
|| fltIn
> I2_MAX
)
2307 return DISP_E_OVERFLOW
;
2310 *psOut
= (short) fltIn
;
2315 /******************************************************************************
2316 * VarI2FromR8 [OLEAUT32.51]
2318 HRESULT WINAPI
VarI2FromR8(double dblIn
, short* psOut
)
2320 TRACE("( %f, %p ), stub\n", dblIn
, psOut
);
2322 /* Check range of value.
2324 dblIn
= round( dblIn
);
2325 if( dblIn
< I2_MIN
|| dblIn
> I2_MAX
)
2327 return DISP_E_OVERFLOW
;
2330 *psOut
= (short) dblIn
;
2335 /******************************************************************************
2336 * VarI2FromDate [OLEAUT32.53]
2338 HRESULT WINAPI
VarI2FromDate(DATE dateIn
, short* psOut
)
2340 TRACE("( %f, %p ), stub\n", dateIn
, psOut
);
2342 /* Check range of value.
2344 dateIn
= round( dateIn
);
2345 if( dateIn
< I2_MIN
|| dateIn
> I2_MAX
)
2347 return DISP_E_OVERFLOW
;
2350 *psOut
= (short) dateIn
;
2355 /******************************************************************************
2356 * VarI2FromBool [OLEAUT32.56]
2358 HRESULT WINAPI
VarI2FromBool(VARIANT_BOOL boolIn
, short* psOut
)
2360 TRACE("( %d, %p ), stub\n", boolIn
, psOut
);
2362 *psOut
= (short) boolIn
;
2367 /******************************************************************************
2368 * VarI2FromI1 [OLEAUT32.205]
2370 HRESULT WINAPI
VarI2FromI1(CHAR cIn
, short* psOut
)
2372 TRACE("( %c, %p ), stub\n", cIn
, psOut
);
2374 *psOut
= (short) cIn
;
2379 /******************************************************************************
2380 * VarI2FromUI2 [OLEAUT32.206]
2382 HRESULT WINAPI
VarI2FromUI2(USHORT uiIn
, short* psOut
)
2384 TRACE("( %d, %p ), stub\n", uiIn
, psOut
);
2386 /* Check range of value.
2390 return DISP_E_OVERFLOW
;
2393 *psOut
= (short) uiIn
;
2398 /******************************************************************************
2399 * VarI2FromUI4 [OLEAUT32.207]
2401 HRESULT WINAPI
VarI2FromUI4(ULONG ulIn
, short* psOut
)
2403 TRACE("( %lx, %p ), stub\n", ulIn
, psOut
);
2405 /* Check range of value.
2407 if( ulIn
< I2_MIN
|| ulIn
> I2_MAX
)
2409 return DISP_E_OVERFLOW
;
2412 *psOut
= (short) ulIn
;
2417 /******************************************************************************
2418 * VarI2FromStr [OLEAUT32.54]
2420 HRESULT WINAPI
VarI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, short* psOut
)
2422 double dValue
= 0.0;
2423 LPSTR pNewString
= NULL
;
2425 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, psOut
);
2427 /* Check if we have a valid argument
2429 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2430 RemoveCharacterFromString( pNewString
, "," );
2431 if( IsValidRealString( pNewString
) == FALSE
)
2433 return DISP_E_TYPEMISMATCH
;
2436 /* Convert the valid string to a floating point number.
2438 dValue
= atof( pNewString
);
2440 /* We don't need the string anymore so free it.
2442 HeapFree( GetProcessHeap(), 0, pNewString
);
2444 /* Check range of value.
2446 dValue
= round( dValue
);
2447 if( dValue
< I2_MIN
|| dValue
> I2_MAX
)
2449 return DISP_E_OVERFLOW
;
2452 *psOut
= (short) dValue
;
2457 /**********************************************************************
2458 * VarI2FromCy [OLEAUT32.52]
2459 * Convert currency to signed short
2461 HRESULT WINAPI
VarI2FromCy(CY cyIn
, short* psOut
) {
2462 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2464 if (t
> I2_MAX
|| t
< I2_MIN
) return DISP_E_OVERFLOW
;
2470 /******************************************************************************
2471 * VarI4FromUI1 [OLEAUT32.58]
2473 HRESULT WINAPI
VarI4FromUI1(BYTE bIn
, LONG
* plOut
)
2475 TRACE("( %X, %p ), stub\n", bIn
, plOut
);
2477 *plOut
= (LONG
) bIn
;
2483 /******************************************************************************
2484 * VarI4FromR4 [OLEAUT32.60]
2486 HRESULT WINAPI
VarI4FromR4(FLOAT fltIn
, LONG
* plOut
)
2488 TRACE("( %f, %p ), stub\n", fltIn
, plOut
);
2490 /* Check range of value.
2492 fltIn
= round( fltIn
);
2493 if( fltIn
< I4_MIN
|| fltIn
> I4_MAX
)
2495 return DISP_E_OVERFLOW
;
2498 *plOut
= (LONG
) fltIn
;
2503 /******************************************************************************
2504 * VarI4FromR8 [OLEAUT32.61]
2506 HRESULT WINAPI
VarI4FromR8(double dblIn
, LONG
* plOut
)
2508 TRACE("( %f, %p ), stub\n", dblIn
, plOut
);
2510 /* Check range of value.
2512 dblIn
= round( dblIn
);
2513 if( dblIn
< I4_MIN
|| dblIn
> I4_MAX
)
2515 return DISP_E_OVERFLOW
;
2518 *plOut
= (LONG
) dblIn
;
2523 /******************************************************************************
2524 * VarI4FromDate [OLEAUT32.63]
2526 HRESULT WINAPI
VarI4FromDate(DATE dateIn
, LONG
* plOut
)
2528 TRACE("( %f, %p ), stub\n", dateIn
, plOut
);
2530 /* Check range of value.
2532 dateIn
= round( dateIn
);
2533 if( dateIn
< I4_MIN
|| dateIn
> I4_MAX
)
2535 return DISP_E_OVERFLOW
;
2538 *plOut
= (LONG
) dateIn
;
2543 /******************************************************************************
2544 * VarI4FromBool [OLEAUT32.66]
2546 HRESULT WINAPI
VarI4FromBool(VARIANT_BOOL boolIn
, LONG
* plOut
)
2548 TRACE("( %d, %p ), stub\n", boolIn
, plOut
);
2550 *plOut
= (LONG
) boolIn
;
2555 /******************************************************************************
2556 * VarI4FromI1 [OLEAUT32.209]
2558 HRESULT WINAPI
VarI4FromI1(CHAR cIn
, LONG
* plOut
)
2560 TRACE("( %c, %p ), stub\n", cIn
, plOut
);
2562 *plOut
= (LONG
) cIn
;
2567 /******************************************************************************
2568 * VarI4FromUI2 [OLEAUT32.210]
2570 HRESULT WINAPI
VarI4FromUI2(USHORT uiIn
, LONG
* plOut
)
2572 TRACE("( %d, %p ), stub\n", uiIn
, plOut
);
2574 *plOut
= (LONG
) uiIn
;
2579 /******************************************************************************
2580 * VarI4FromUI4 [OLEAUT32.211]
2582 HRESULT WINAPI
VarI4FromUI4(ULONG ulIn
, LONG
* plOut
)
2584 TRACE("( %lx, %p ), stub\n", ulIn
, plOut
);
2586 /* Check range of value.
2588 if( ulIn
< I4_MIN
|| ulIn
> I4_MAX
)
2590 return DISP_E_OVERFLOW
;
2593 *plOut
= (LONG
) ulIn
;
2598 /******************************************************************************
2599 * VarI4FromI2 [OLEAUT32.59]
2601 HRESULT WINAPI
VarI4FromI2(short sIn
, LONG
* plOut
)
2603 TRACE("( %d, %p ), stub\n", sIn
, plOut
);
2605 *plOut
= (LONG
) sIn
;
2610 /******************************************************************************
2611 * VarI4FromStr [OLEAUT32.64]
2613 HRESULT WINAPI
VarI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, LONG
* plOut
)
2615 double dValue
= 0.0;
2616 LPSTR pNewString
= NULL
;
2618 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn
, lcid
, dwFlags
, plOut
);
2620 /* Check if we have a valid argument
2622 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2623 RemoveCharacterFromString( pNewString
, "," );
2624 if( IsValidRealString( pNewString
) == FALSE
)
2626 return DISP_E_TYPEMISMATCH
;
2629 /* Convert the valid string to a floating point number.
2631 dValue
= atof( pNewString
);
2633 /* We don't need the string anymore so free it.
2635 HeapFree( GetProcessHeap(), 0, pNewString
);
2637 /* Check range of value.
2639 dValue
= round( dValue
);
2640 if( dValue
< I4_MIN
|| dValue
> I4_MAX
)
2642 return DISP_E_OVERFLOW
;
2645 *plOut
= (LONG
) dValue
;
2650 /**********************************************************************
2651 * VarI4FromCy [OLEAUT32.62]
2652 * Convert currency to signed long
2654 HRESULT WINAPI
VarI4FromCy(CY cyIn
, LONG
* plOut
) {
2655 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2657 if (t
> I4_MAX
|| t
< I4_MIN
) return DISP_E_OVERFLOW
;
2663 /******************************************************************************
2664 * VarR4FromUI1 [OLEAUT32.68]
2666 HRESULT WINAPI
VarR4FromUI1(BYTE bIn
, FLOAT
* pfltOut
)
2668 TRACE("( %X, %p ), stub\n", bIn
, pfltOut
);
2670 *pfltOut
= (FLOAT
) bIn
;
2675 /******************************************************************************
2676 * VarR4FromI2 [OLEAUT32.69]
2678 HRESULT WINAPI
VarR4FromI2(short sIn
, FLOAT
* pfltOut
)
2680 TRACE("( %d, %p ), stub\n", sIn
, pfltOut
);
2682 *pfltOut
= (FLOAT
) sIn
;
2687 /******************************************************************************
2688 * VarR4FromI4 [OLEAUT32.70]
2690 HRESULT WINAPI
VarR4FromI4(LONG lIn
, FLOAT
* pfltOut
)
2692 TRACE("( %lx, %p ), stub\n", lIn
, pfltOut
);
2694 *pfltOut
= (FLOAT
) lIn
;
2699 /******************************************************************************
2700 * VarR4FromR8 [OLEAUT32.71]
2702 HRESULT WINAPI
VarR4FromR8(double dblIn
, FLOAT
* pfltOut
)
2704 TRACE("( %f, %p ), stub\n", dblIn
, pfltOut
);
2706 /* Check range of value.
2708 if( dblIn
< -(FLT_MAX
) || dblIn
> FLT_MAX
)
2710 return DISP_E_OVERFLOW
;
2713 *pfltOut
= (FLOAT
) dblIn
;
2718 /******************************************************************************
2719 * VarR4FromDate [OLEAUT32.73]
2721 HRESULT WINAPI
VarR4FromDate(DATE dateIn
, FLOAT
* pfltOut
)
2723 TRACE("( %f, %p ), stub\n", dateIn
, pfltOut
);
2725 /* Check range of value.
2727 if( dateIn
< -(FLT_MAX
) || dateIn
> FLT_MAX
)
2729 return DISP_E_OVERFLOW
;
2732 *pfltOut
= (FLOAT
) dateIn
;
2737 /******************************************************************************
2738 * VarR4FromBool [OLEAUT32.76]
2740 HRESULT WINAPI
VarR4FromBool(VARIANT_BOOL boolIn
, FLOAT
* pfltOut
)
2742 TRACE("( %d, %p ), stub\n", boolIn
, pfltOut
);
2744 *pfltOut
= (FLOAT
) boolIn
;
2749 /******************************************************************************
2750 * VarR4FromI1 [OLEAUT32.213]
2752 HRESULT WINAPI
VarR4FromI1(CHAR cIn
, FLOAT
* pfltOut
)
2754 TRACE("( %c, %p ), stub\n", cIn
, pfltOut
);
2756 *pfltOut
= (FLOAT
) cIn
;
2761 /******************************************************************************
2762 * VarR4FromUI2 [OLEAUT32.214]
2764 HRESULT WINAPI
VarR4FromUI2(USHORT uiIn
, FLOAT
* pfltOut
)
2766 TRACE("( %d, %p ), stub\n", uiIn
, pfltOut
);
2768 *pfltOut
= (FLOAT
) uiIn
;
2773 /******************************************************************************
2774 * VarR4FromUI4 [OLEAUT32.215]
2776 HRESULT WINAPI
VarR4FromUI4(ULONG ulIn
, FLOAT
* pfltOut
)
2778 TRACE("( %ld, %p ), stub\n", ulIn
, pfltOut
);
2780 *pfltOut
= (FLOAT
) ulIn
;
2785 /******************************************************************************
2786 * VarR4FromStr [OLEAUT32.74]
2788 HRESULT WINAPI
VarR4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, FLOAT
* pfltOut
)
2790 double dValue
= 0.0;
2791 LPSTR pNewString
= NULL
;
2793 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pfltOut
);
2795 /* Check if we have a valid argument
2797 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2798 RemoveCharacterFromString( pNewString
, "," );
2799 if( IsValidRealString( pNewString
) == FALSE
)
2801 return DISP_E_TYPEMISMATCH
;
2804 /* Convert the valid string to a floating point number.
2806 dValue
= atof( pNewString
);
2808 /* We don't need the string anymore so free it.
2810 HeapFree( GetProcessHeap(), 0, pNewString
);
2812 /* Check range of value.
2814 if( dValue
< -(FLT_MAX
) || dValue
> FLT_MAX
)
2816 return DISP_E_OVERFLOW
;
2819 *pfltOut
= (FLOAT
) dValue
;
2824 /**********************************************************************
2825 * VarR4FromCy [OLEAUT32.72]
2826 * Convert currency to float
2828 HRESULT WINAPI
VarR4FromCy(CY cyIn
, FLOAT
* pfltOut
) {
2829 *pfltOut
= (FLOAT
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2834 /******************************************************************************
2835 * VarR8FromUI1 [OLEAUT32.78]
2837 HRESULT WINAPI
VarR8FromUI1(BYTE bIn
, double* pdblOut
)
2839 TRACE("( %d, %p ), stub\n", bIn
, pdblOut
);
2841 *pdblOut
= (double) bIn
;
2846 /******************************************************************************
2847 * VarR8FromI2 [OLEAUT32.79]
2849 HRESULT WINAPI
VarR8FromI2(short sIn
, double* pdblOut
)
2851 TRACE("( %d, %p ), stub\n", sIn
, pdblOut
);
2853 *pdblOut
= (double) sIn
;
2858 /******************************************************************************
2859 * VarR8FromI4 [OLEAUT32.80]
2861 HRESULT WINAPI
VarR8FromI4(LONG lIn
, double* pdblOut
)
2863 TRACE("( %ld, %p ), stub\n", lIn
, pdblOut
);
2865 *pdblOut
= (double) lIn
;
2870 /******************************************************************************
2871 * VarR8FromR4 [OLEAUT32.81]
2873 HRESULT WINAPI
VarR8FromR4(FLOAT fltIn
, double* pdblOut
)
2875 TRACE("( %f, %p ), stub\n", fltIn
, pdblOut
);
2877 *pdblOut
= (double) fltIn
;
2882 /******************************************************************************
2883 * VarR8FromDate [OLEAUT32.83]
2885 HRESULT WINAPI
VarR8FromDate(DATE dateIn
, double* pdblOut
)
2887 TRACE("( %f, %p ), stub\n", dateIn
, pdblOut
);
2889 *pdblOut
= (double) dateIn
;
2894 /******************************************************************************
2895 * VarR8FromBool [OLEAUT32.86]
2897 HRESULT WINAPI
VarR8FromBool(VARIANT_BOOL boolIn
, double* pdblOut
)
2899 TRACE("( %d, %p ), stub\n", boolIn
, pdblOut
);
2901 *pdblOut
= (double) boolIn
;
2906 /******************************************************************************
2907 * VarR8FromI1 [OLEAUT32.217]
2909 HRESULT WINAPI
VarR8FromI1(CHAR cIn
, double* pdblOut
)
2911 TRACE("( %c, %p ), stub\n", cIn
, pdblOut
);
2913 *pdblOut
= (double) cIn
;
2918 /******************************************************************************
2919 * VarR8FromUI2 [OLEAUT32.218]
2921 HRESULT WINAPI
VarR8FromUI2(USHORT uiIn
, double* pdblOut
)
2923 TRACE("( %d, %p ), stub\n", uiIn
, pdblOut
);
2925 *pdblOut
= (double) uiIn
;
2930 /******************************************************************************
2931 * VarR8FromUI4 [OLEAUT32.219]
2933 HRESULT WINAPI
VarR8FromUI4(ULONG ulIn
, double* pdblOut
)
2935 TRACE("( %ld, %p ), stub\n", ulIn
, pdblOut
);
2937 *pdblOut
= (double) ulIn
;
2942 /******************************************************************************
2943 * VarR8FromStr [OLEAUT32.84]
2945 HRESULT WINAPI
VarR8FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, double* pdblOut
)
2947 double dValue
= 0.0;
2948 LPSTR pNewString
= NULL
;
2950 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pdblOut
);
2952 /* Check if we have a valid argument
2954 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
2955 RemoveCharacterFromString( pNewString
, "," );
2956 if( IsValidRealString( pNewString
) == FALSE
)
2958 return DISP_E_TYPEMISMATCH
;
2961 /* Convert the valid string to a floating point number.
2963 dValue
= atof( pNewString
);
2965 /* We don't need the string anymore so free it.
2967 HeapFree( GetProcessHeap(), 0, pNewString
);
2974 /**********************************************************************
2975 * VarR8FromCy [OLEAUT32.82]
2976 * Convert currency to double
2978 HRESULT WINAPI
VarR8FromCy(CY cyIn
, double* pdblOut
) {
2979 *pdblOut
= (double)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
2984 /******************************************************************************
2985 * VarDateFromUI1 [OLEAUT32.88]
2987 HRESULT WINAPI
VarDateFromUI1(BYTE bIn
, DATE
* pdateOut
)
2989 TRACE("( %d, %p ), stub\n", bIn
, pdateOut
);
2991 *pdateOut
= (DATE
) bIn
;
2996 /******************************************************************************
2997 * VarDateFromI2 [OLEAUT32.89]
2999 HRESULT WINAPI
VarDateFromI2(short sIn
, DATE
* pdateOut
)
3001 TRACE("( %d, %p ), stub\n", sIn
, pdateOut
);
3003 *pdateOut
= (DATE
) sIn
;
3008 /******************************************************************************
3009 * VarDateFromI4 [OLEAUT32.90]
3011 HRESULT WINAPI
VarDateFromI4(LONG lIn
, DATE
* pdateOut
)
3013 TRACE("( %ld, %p ), stub\n", lIn
, pdateOut
);
3015 if( lIn
< DATE_MIN
|| lIn
> DATE_MAX
)
3017 return DISP_E_OVERFLOW
;
3020 *pdateOut
= (DATE
) lIn
;
3025 /******************************************************************************
3026 * VarDateFromR4 [OLEAUT32.91]
3028 HRESULT WINAPI
VarDateFromR4(FLOAT fltIn
, DATE
* pdateOut
)
3030 TRACE("( %f, %p ), stub\n", fltIn
, pdateOut
);
3032 if( ceil(fltIn
) < DATE_MIN
|| floor(fltIn
) > DATE_MAX
)
3034 return DISP_E_OVERFLOW
;
3037 *pdateOut
= (DATE
) fltIn
;
3042 /******************************************************************************
3043 * VarDateFromR8 [OLEAUT32.92]
3045 HRESULT WINAPI
VarDateFromR8(double dblIn
, DATE
* pdateOut
)
3047 TRACE("( %f, %p ), stub\n", dblIn
, pdateOut
);
3049 if( ceil(dblIn
) < DATE_MIN
|| floor(dblIn
) > DATE_MAX
)
3051 return DISP_E_OVERFLOW
;
3054 *pdateOut
= (DATE
) dblIn
;
3059 /******************************************************************************
3060 * VarDateFromStr [OLEAUT32.94]
3061 * The string representing the date is composed of two parts, a date and time.
3063 * The format of the time is has follows:
3064 * hh[:mm][:ss][AM|PM]
3065 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3066 * of space and/or tab characters, which are ignored.
3068 * The formats for the date part are has follows:
3072 * January dd[,] [yy]yy
3075 * Whitespace can be inserted anywhere between these tokens.
3077 * The formats for the date and time string are has follows.
3078 * date[whitespace][time]
3079 * [time][whitespace]date
3081 * These are the only characters allowed in a string representing a date and time:
3082 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3084 HRESULT WINAPI
VarDateFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, DATE
* pdateOut
)
3089 memset( &TM
, 0, sizeof(TM
) );
3091 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn
, lcid
, dwFlags
, pdateOut
);
3093 if( DateTimeStringToTm( strIn
, dwFlags
, &TM
) )
3095 if( TmToDATE( &TM
, pdateOut
) == FALSE
)
3102 ret
= DISP_E_TYPEMISMATCH
;
3109 /******************************************************************************
3110 * VarDateFromI1 [OLEAUT32.221]
3112 HRESULT WINAPI
VarDateFromI1(CHAR cIn
, DATE
* pdateOut
)
3114 TRACE("( %c, %p ), stub\n", cIn
, pdateOut
);
3116 *pdateOut
= (DATE
) cIn
;
3121 /******************************************************************************
3122 * VarDateFromUI2 [OLEAUT32.222]
3124 HRESULT WINAPI
VarDateFromUI2(USHORT uiIn
, DATE
* pdateOut
)
3126 TRACE("( %d, %p ), stub\n", uiIn
, pdateOut
);
3128 if( uiIn
> DATE_MAX
)
3130 return DISP_E_OVERFLOW
;
3133 *pdateOut
= (DATE
) uiIn
;
3138 /******************************************************************************
3139 * VarDateFromUI4 [OLEAUT32.223]
3141 HRESULT WINAPI
VarDateFromUI4(ULONG ulIn
, DATE
* pdateOut
)
3143 TRACE("( %ld, %p ), stub\n", ulIn
, pdateOut
);
3145 if( ulIn
< DATE_MIN
|| ulIn
> DATE_MAX
)
3147 return DISP_E_OVERFLOW
;
3150 *pdateOut
= (DATE
) ulIn
;
3155 /******************************************************************************
3156 * VarDateFromBool [OLEAUT32.96]
3158 HRESULT WINAPI
VarDateFromBool(VARIANT_BOOL boolIn
, DATE
* pdateOut
)
3160 TRACE("( %d, %p ), stub\n", boolIn
, pdateOut
);
3162 *pdateOut
= (DATE
) boolIn
;
3167 /**********************************************************************
3168 * VarDateFromCy [OLEAUT32.93]
3169 * Convert currency to date
3171 HRESULT WINAPI
VarDateFromCy(CY cyIn
, DATE
* pdateOut
) {
3172 *pdateOut
= (DATE
)((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3174 if (*pdateOut
> DATE_MAX
|| *pdateOut
< DATE_MIN
) return DISP_E_TYPEMISMATCH
;
3178 /******************************************************************************
3179 * VarBstrFromUI1 [OLEAUT32.108]
3181 HRESULT WINAPI
VarBstrFromUI1(BYTE bVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3183 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal
, lcid
, dwFlags
, pbstrOut
);
3184 sprintf( pBuffer
, "%d", bVal
);
3186 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3191 /******************************************************************************
3192 * VarBstrFromI2 [OLEAUT32.109]
3194 HRESULT WINAPI
VarBstrFromI2(short iVal
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3196 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal
, lcid
, dwFlags
, pbstrOut
);
3197 sprintf( pBuffer
, "%d", iVal
);
3198 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3203 /******************************************************************************
3204 * VarBstrFromI4 [OLEAUT32.110]
3206 HRESULT WINAPI
VarBstrFromI4(LONG lIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3208 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn
, lcid
, dwFlags
, pbstrOut
);
3210 sprintf( pBuffer
, "%ld", lIn
);
3211 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3216 /******************************************************************************
3217 * VarBstrFromR4 [OLEAUT32.111]
3219 HRESULT WINAPI
VarBstrFromR4(FLOAT fltIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3221 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn
, lcid
, dwFlags
, pbstrOut
);
3223 sprintf( pBuffer
, "%.7g", fltIn
);
3224 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3229 /******************************************************************************
3230 * VarBstrFromR8 [OLEAUT32.112]
3232 HRESULT WINAPI
VarBstrFromR8(double dblIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3234 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn
, lcid
, dwFlags
, pbstrOut
);
3236 sprintf( pBuffer
, "%.15g", dblIn
);
3237 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3242 /******************************************************************************
3243 * VarBstrFromCy [OLEAUT32.113]
3245 HRESULT WINAPI
VarBstrFromCy(CY cyIn
, LCID lcid
, ULONG dwFlags
, BSTR
*pbstrOut
) {
3251 /******************************************************************************
3252 * VarBstrFromDate [OLEAUT32.114]
3254 * The date is implemented using an 8 byte floating-point number.
3255 * Days are represented by whole numbers increments starting with 0.00 as
3256 * being December 30 1899, midnight.
3257 * The hours are expressed as the fractional part of the number.
3258 * December 30 1899 at midnight = 0.00
3259 * January 1 1900 at midnight = 2.00
3260 * January 4 1900 at 6 AM = 5.25
3261 * January 4 1900 at noon = 5.50
3262 * December 29 1899 at midnight = -1.00
3263 * December 18 1899 at midnight = -12.00
3264 * December 18 1899 at 6AM = -12.25
3265 * December 18 1899 at 6PM = -12.75
3266 * December 19 1899 at midnight = -11.00
3267 * The tm structure is as follows:
3269 * int tm_sec; seconds after the minute - [0,59]
3270 * int tm_min; minutes after the hour - [0,59]
3271 * int tm_hour; hours since midnight - [0,23]
3272 * int tm_mday; day of the month - [1,31]
3273 * int tm_mon; months since January - [0,11]
3274 * int tm_year; years
3275 * int tm_wday; days since Sunday - [0,6]
3276 * int tm_yday; days since January 1 - [0,365]
3277 * int tm_isdst; daylight savings time flag
3280 HRESULT WINAPI
VarBstrFromDate(DATE dateIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3283 memset( &TM
, 0, sizeof(TM
) );
3285 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn
, lcid
, dwFlags
, pbstrOut
);
3287 if( DateToTm( dateIn
, dwFlags
, &TM
) == FALSE
)
3289 return E_INVALIDARG
;
3292 if( dwFlags
& VAR_DATEVALUEONLY
)
3293 strftime( pBuffer
, BUFFER_MAX
, "%x", &TM
);
3294 else if( dwFlags
& VAR_TIMEVALUEONLY
)
3295 strftime( pBuffer
, BUFFER_MAX
, "%X", &TM
);
3297 strftime( pBuffer
, BUFFER_MAX
, "%x %X", &TM
);
3299 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3304 /******************************************************************************
3305 * VarBstrFromBool [OLEAUT32.116]
3307 HRESULT WINAPI
VarBstrFromBool(VARIANT_BOOL boolIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3309 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn
, lcid
, dwFlags
, pbstrOut
);
3311 if( boolIn
== VARIANT_FALSE
)
3313 sprintf( pBuffer
, "False" );
3317 sprintf( pBuffer
, "True" );
3320 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3325 /******************************************************************************
3326 * VarBstrFromI1 [OLEAUT32.229]
3328 HRESULT WINAPI
VarBstrFromI1(CHAR cIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3330 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn
, lcid
, dwFlags
, pbstrOut
);
3331 sprintf( pBuffer
, "%d", cIn
);
3332 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3337 /******************************************************************************
3338 * VarBstrFromUI2 [OLEAUT32.230]
3340 HRESULT WINAPI
VarBstrFromUI2(USHORT uiIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3342 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn
, lcid
, dwFlags
, pbstrOut
);
3343 sprintf( pBuffer
, "%d", uiIn
);
3344 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3349 /******************************************************************************
3350 * VarBstrFromUI4 [OLEAUT32.231]
3352 HRESULT WINAPI
VarBstrFromUI4(ULONG ulIn
, LCID lcid
, ULONG dwFlags
, BSTR
* pbstrOut
)
3354 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn
, lcid
, dwFlags
, pbstrOut
);
3355 sprintf( pBuffer
, "%ld", ulIn
);
3356 *pbstrOut
= StringDupAtoBstr( pBuffer
);
3361 /******************************************************************************
3362 * VarBoolFromUI1 [OLEAUT32.118]
3364 HRESULT WINAPI
VarBoolFromUI1(BYTE bIn
, VARIANT_BOOL
* pboolOut
)
3366 TRACE("( %d, %p ), stub\n", bIn
, pboolOut
);
3370 *pboolOut
= VARIANT_FALSE
;
3374 *pboolOut
= VARIANT_TRUE
;
3380 /******************************************************************************
3381 * VarBoolFromI2 [OLEAUT32.119]
3383 HRESULT WINAPI
VarBoolFromI2(short sIn
, VARIANT_BOOL
* pboolOut
)
3385 TRACE("( %d, %p ), stub\n", sIn
, pboolOut
);
3389 *pboolOut
= VARIANT_FALSE
;
3393 *pboolOut
= VARIANT_TRUE
;
3399 /******************************************************************************
3400 * VarBoolFromI4 [OLEAUT32.120]
3402 HRESULT WINAPI
VarBoolFromI4(LONG lIn
, VARIANT_BOOL
* pboolOut
)
3404 TRACE("( %ld, %p ), stub\n", lIn
, pboolOut
);
3408 *pboolOut
= VARIANT_FALSE
;
3412 *pboolOut
= VARIANT_TRUE
;
3418 /******************************************************************************
3419 * VarBoolFromR4 [OLEAUT32.121]
3421 HRESULT WINAPI
VarBoolFromR4(FLOAT fltIn
, VARIANT_BOOL
* pboolOut
)
3423 TRACE("( %f, %p ), stub\n", fltIn
, pboolOut
);
3427 *pboolOut
= VARIANT_FALSE
;
3431 *pboolOut
= VARIANT_TRUE
;
3437 /******************************************************************************
3438 * VarBoolFromR8 [OLEAUT32.122]
3440 HRESULT WINAPI
VarBoolFromR8(double dblIn
, VARIANT_BOOL
* pboolOut
)
3442 TRACE("( %f, %p ), stub\n", dblIn
, pboolOut
);
3446 *pboolOut
= VARIANT_FALSE
;
3450 *pboolOut
= VARIANT_TRUE
;
3456 /******************************************************************************
3457 * VarBoolFromDate [OLEAUT32.123]
3459 HRESULT WINAPI
VarBoolFromDate(DATE dateIn
, VARIANT_BOOL
* pboolOut
)
3461 TRACE("( %f, %p ), stub\n", dateIn
, pboolOut
);
3465 *pboolOut
= VARIANT_FALSE
;
3469 *pboolOut
= VARIANT_TRUE
;
3475 /******************************************************************************
3476 * VarBoolFromStr [OLEAUT32.125]
3478 HRESULT WINAPI
VarBoolFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, VARIANT_BOOL
* pboolOut
)
3481 char* pNewString
= NULL
;
3483 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pboolOut
);
3485 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3487 if( pNewString
== NULL
|| strlen( pNewString
) == 0 )
3489 ret
= DISP_E_TYPEMISMATCH
;
3494 if( strncasecmp( pNewString
, "True", strlen( pNewString
) ) == 0 )
3496 *pboolOut
= VARIANT_TRUE
;
3498 else if( strncasecmp( pNewString
, "False", strlen( pNewString
) ) == 0 )
3500 *pboolOut
= VARIANT_FALSE
;
3504 /* Try converting the string to a floating point number.
3506 double dValue
= 0.0;
3507 HRESULT res
= VarR8FromStr( strIn
, lcid
, dwFlags
, &dValue
);
3510 ret
= DISP_E_TYPEMISMATCH
;
3512 else if( dValue
== 0.0 )
3514 *pboolOut
= VARIANT_FALSE
;
3518 *pboolOut
= VARIANT_TRUE
;
3523 HeapFree( GetProcessHeap(), 0, pNewString
);
3528 /******************************************************************************
3529 * VarBoolFromI1 [OLEAUT32.233]
3531 HRESULT WINAPI
VarBoolFromI1(CHAR cIn
, VARIANT_BOOL
* pboolOut
)
3533 TRACE("( %c, %p ), stub\n", cIn
, pboolOut
);
3537 *pboolOut
= VARIANT_FALSE
;
3541 *pboolOut
= VARIANT_TRUE
;
3547 /******************************************************************************
3548 * VarBoolFromUI2 [OLEAUT32.234]
3550 HRESULT WINAPI
VarBoolFromUI2(USHORT uiIn
, VARIANT_BOOL
* pboolOut
)
3552 TRACE("( %d, %p ), stub\n", uiIn
, pboolOut
);
3556 *pboolOut
= VARIANT_FALSE
;
3560 *pboolOut
= VARIANT_TRUE
;
3566 /******************************************************************************
3567 * VarBoolFromUI4 [OLEAUT32.235]
3569 HRESULT WINAPI
VarBoolFromUI4(ULONG ulIn
, VARIANT_BOOL
* pboolOut
)
3571 TRACE("( %ld, %p ), stub\n", ulIn
, pboolOut
);
3575 *pboolOut
= VARIANT_FALSE
;
3579 *pboolOut
= VARIANT_TRUE
;
3585 /**********************************************************************
3586 * VarBoolFromCy [OLEAUT32.124]
3587 * Convert currency to boolean
3589 HRESULT WINAPI
VarBoolFromCy(CY cyIn
, VARIANT_BOOL
* pboolOut
) {
3590 if (cyIn
.s
.Hi
|| cyIn
.s
.Lo
) *pboolOut
= -1;
3596 /******************************************************************************
3597 * VarI1FromUI1 [OLEAUT32.244]
3599 HRESULT WINAPI
VarI1FromUI1(BYTE bIn
, CHAR
* pcOut
)
3601 TRACE("( %d, %p ), stub\n", bIn
, pcOut
);
3603 /* Check range of value.
3605 if( bIn
> CHAR_MAX
)
3607 return DISP_E_OVERFLOW
;
3610 *pcOut
= (CHAR
) bIn
;
3615 /******************************************************************************
3616 * VarI1FromI2 [OLEAUT32.245]
3618 HRESULT WINAPI
VarI1FromI2(short uiIn
, CHAR
* pcOut
)
3620 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3622 if( uiIn
> CHAR_MAX
)
3624 return DISP_E_OVERFLOW
;
3627 *pcOut
= (CHAR
) uiIn
;
3632 /******************************************************************************
3633 * VarI1FromI4 [OLEAUT32.246]
3635 HRESULT WINAPI
VarI1FromI4(LONG lIn
, CHAR
* pcOut
)
3637 TRACE("( %ld, %p ), stub\n", lIn
, pcOut
);
3639 if( lIn
< CHAR_MIN
|| lIn
> CHAR_MAX
)
3641 return DISP_E_OVERFLOW
;
3644 *pcOut
= (CHAR
) lIn
;
3649 /******************************************************************************
3650 * VarI1FromR4 [OLEAUT32.247]
3652 HRESULT WINAPI
VarI1FromR4(FLOAT fltIn
, CHAR
* pcOut
)
3654 TRACE("( %f, %p ), stub\n", fltIn
, pcOut
);
3656 fltIn
= round( fltIn
);
3657 if( fltIn
< CHAR_MIN
|| fltIn
> CHAR_MAX
)
3659 return DISP_E_OVERFLOW
;
3662 *pcOut
= (CHAR
) fltIn
;
3667 /******************************************************************************
3668 * VarI1FromR8 [OLEAUT32.248]
3670 HRESULT WINAPI
VarI1FromR8(double dblIn
, CHAR
* pcOut
)
3672 TRACE("( %f, %p ), stub\n", dblIn
, pcOut
);
3674 dblIn
= round( dblIn
);
3675 if( dblIn
< CHAR_MIN
|| dblIn
> CHAR_MAX
)
3677 return DISP_E_OVERFLOW
;
3680 *pcOut
= (CHAR
) dblIn
;
3685 /******************************************************************************
3686 * VarI1FromDate [OLEAUT32.249]
3688 HRESULT WINAPI
VarI1FromDate(DATE dateIn
, CHAR
* pcOut
)
3690 TRACE("( %f, %p ), stub\n", dateIn
, pcOut
);
3692 dateIn
= round( dateIn
);
3693 if( dateIn
< CHAR_MIN
|| dateIn
> CHAR_MAX
)
3695 return DISP_E_OVERFLOW
;
3698 *pcOut
= (CHAR
) dateIn
;
3703 /******************************************************************************
3704 * VarI1FromStr [OLEAUT32.251]
3706 HRESULT WINAPI
VarI1FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, CHAR
* pcOut
)
3708 double dValue
= 0.0;
3709 LPSTR pNewString
= NULL
;
3711 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pcOut
);
3713 /* Check if we have a valid argument
3715 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3716 RemoveCharacterFromString( pNewString
, "," );
3717 if( IsValidRealString( pNewString
) == FALSE
)
3719 return DISP_E_TYPEMISMATCH
;
3722 /* Convert the valid string to a floating point number.
3724 dValue
= atof( pNewString
);
3726 /* We don't need the string anymore so free it.
3728 HeapFree( GetProcessHeap(), 0, pNewString
);
3730 /* Check range of value.
3732 dValue
= round( dValue
);
3733 if( dValue
< CHAR_MIN
|| dValue
> CHAR_MAX
)
3735 return DISP_E_OVERFLOW
;
3738 *pcOut
= (CHAR
) dValue
;
3743 /******************************************************************************
3744 * VarI1FromBool [OLEAUT32.253]
3746 HRESULT WINAPI
VarI1FromBool(VARIANT_BOOL boolIn
, CHAR
* pcOut
)
3748 TRACE("( %d, %p ), stub\n", boolIn
, pcOut
);
3750 *pcOut
= (CHAR
) boolIn
;
3755 /******************************************************************************
3756 * VarI1FromUI2 [OLEAUT32.254]
3758 HRESULT WINAPI
VarI1FromUI2(USHORT uiIn
, CHAR
* pcOut
)
3760 TRACE("( %d, %p ), stub\n", uiIn
, pcOut
);
3762 if( uiIn
> CHAR_MAX
)
3764 return DISP_E_OVERFLOW
;
3767 *pcOut
= (CHAR
) uiIn
;
3772 /******************************************************************************
3773 * VarI1FromUI4 [OLEAUT32.255]
3775 HRESULT WINAPI
VarI1FromUI4(ULONG ulIn
, CHAR
* pcOut
)
3777 TRACE("( %ld, %p ), stub\n", ulIn
, pcOut
);
3779 if( ulIn
> CHAR_MAX
)
3781 return DISP_E_OVERFLOW
;
3784 *pcOut
= (CHAR
) ulIn
;
3789 /**********************************************************************
3790 * VarI1FromCy [OLEAUT32.250]
3791 * Convert currency to signed char
3793 HRESULT WINAPI
VarI1FromCy(CY cyIn
, CHAR
* pcOut
) {
3794 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
3796 if (t
> CHAR_MAX
|| t
< CHAR_MIN
) return DISP_E_OVERFLOW
;
3802 /******************************************************************************
3803 * VarUI2FromUI1 [OLEAUT32.257]
3805 HRESULT WINAPI
VarUI2FromUI1(BYTE bIn
, USHORT
* puiOut
)
3807 TRACE("( %d, %p ), stub\n", bIn
, puiOut
);
3809 *puiOut
= (USHORT
) bIn
;
3814 /******************************************************************************
3815 * VarUI2FromI2 [OLEAUT32.258]
3817 HRESULT WINAPI
VarUI2FromI2(short uiIn
, USHORT
* puiOut
)
3819 TRACE("( %d, %p ), stub\n", uiIn
, puiOut
);
3821 if( uiIn
< UI2_MIN
)
3823 return DISP_E_OVERFLOW
;
3826 *puiOut
= (USHORT
) uiIn
;
3831 /******************************************************************************
3832 * VarUI2FromI4 [OLEAUT32.259]
3834 HRESULT WINAPI
VarUI2FromI4(LONG lIn
, USHORT
* puiOut
)
3836 TRACE("( %ld, %p ), stub\n", lIn
, puiOut
);
3838 if( lIn
< UI2_MIN
|| lIn
> UI2_MAX
)
3840 return DISP_E_OVERFLOW
;
3843 *puiOut
= (USHORT
) lIn
;
3848 /******************************************************************************
3849 * VarUI2FromR4 [OLEAUT32.260]
3851 HRESULT WINAPI
VarUI2FromR4(FLOAT fltIn
, USHORT
* puiOut
)
3853 TRACE("( %f, %p ), stub\n", fltIn
, puiOut
);
3855 fltIn
= round( fltIn
);
3856 if( fltIn
< UI2_MIN
|| fltIn
> UI2_MAX
)
3858 return DISP_E_OVERFLOW
;
3861 *puiOut
= (USHORT
) fltIn
;
3866 /******************************************************************************
3867 * VarUI2FromR8 [OLEAUT32.261]
3869 HRESULT WINAPI
VarUI2FromR8(double dblIn
, USHORT
* puiOut
)
3871 TRACE("( %f, %p ), stub\n", dblIn
, puiOut
);
3873 dblIn
= round( dblIn
);
3874 if( dblIn
< UI2_MIN
|| dblIn
> UI2_MAX
)
3876 return DISP_E_OVERFLOW
;
3879 *puiOut
= (USHORT
) dblIn
;
3884 /******************************************************************************
3885 * VarUI2FromDate [OLEAUT32.262]
3887 HRESULT WINAPI
VarUI2FromDate(DATE dateIn
, USHORT
* puiOut
)
3889 TRACE("( %f, %p ), stub\n", dateIn
, puiOut
);
3891 dateIn
= round( dateIn
);
3892 if( dateIn
< UI2_MIN
|| dateIn
> UI2_MAX
)
3894 return DISP_E_OVERFLOW
;
3897 *puiOut
= (USHORT
) dateIn
;
3902 /******************************************************************************
3903 * VarUI2FromStr [OLEAUT32.264]
3905 HRESULT WINAPI
VarUI2FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, USHORT
* puiOut
)
3907 double dValue
= 0.0;
3908 LPSTR pNewString
= NULL
;
3910 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, puiOut
);
3912 /* Check if we have a valid argument
3914 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3915 RemoveCharacterFromString( pNewString
, "," );
3916 if( IsValidRealString( pNewString
) == FALSE
)
3918 return DISP_E_TYPEMISMATCH
;
3921 /* Convert the valid string to a floating point number.
3923 dValue
= atof( pNewString
);
3925 /* We don't need the string anymore so free it.
3927 HeapFree( GetProcessHeap(), 0, pNewString
);
3929 /* Check range of value.
3931 dValue
= round( dValue
);
3932 if( dValue
< UI2_MIN
|| dValue
> UI2_MAX
)
3934 return DISP_E_OVERFLOW
;
3937 *puiOut
= (USHORT
) dValue
;
3942 /******************************************************************************
3943 * VarUI2FromBool [OLEAUT32.266]
3945 HRESULT WINAPI
VarUI2FromBool(VARIANT_BOOL boolIn
, USHORT
* puiOut
)
3947 TRACE("( %d, %p ), stub\n", boolIn
, puiOut
);
3949 *puiOut
= (USHORT
) boolIn
;
3954 /******************************************************************************
3955 * VarUI2FromI1 [OLEAUT32.267]
3957 HRESULT WINAPI
VarUI2FromI1(CHAR cIn
, USHORT
* puiOut
)
3959 TRACE("( %c, %p ), stub\n", cIn
, puiOut
);
3961 *puiOut
= (USHORT
) cIn
;
3966 /******************************************************************************
3967 * VarUI2FromUI4 [OLEAUT32.268]
3969 HRESULT WINAPI
VarUI2FromUI4(ULONG ulIn
, USHORT
* puiOut
)
3971 TRACE("( %ld, %p ), stub\n", ulIn
, puiOut
);
3973 if( ulIn
< UI2_MIN
|| ulIn
> UI2_MAX
)
3975 return DISP_E_OVERFLOW
;
3978 *puiOut
= (USHORT
) ulIn
;
3983 /******************************************************************************
3984 * VarUI4FromStr [OLEAUT32.277]
3986 HRESULT WINAPI
VarUI4FromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
, ULONG
* pulOut
)
3988 double dValue
= 0.0;
3989 LPSTR pNewString
= NULL
;
3991 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn
, lcid
, dwFlags
, pulOut
);
3993 /* Check if we have a valid argument
3995 pNewString
= HEAP_strdupWtoA( GetProcessHeap(), 0, strIn
);
3996 RemoveCharacterFromString( pNewString
, "," );
3997 if( IsValidRealString( pNewString
) == FALSE
)
3999 return DISP_E_TYPEMISMATCH
;
4002 /* Convert the valid string to a floating point number.
4004 dValue
= atof( pNewString
);
4006 /* We don't need the string anymore so free it.
4008 HeapFree( GetProcessHeap(), 0, pNewString
);
4010 /* Check range of value.
4012 dValue
= round( dValue
);
4013 if( dValue
< UI4_MIN
|| dValue
> UI4_MAX
)
4015 return DISP_E_OVERFLOW
;
4018 *pulOut
= (ULONG
) dValue
;
4023 /**********************************************************************
4024 * VarUI2FromCy [OLEAUT32.263]
4025 * Convert currency to unsigned short
4027 HRESULT WINAPI
VarUI2FromCy(CY cyIn
, USHORT
* pusOut
) {
4028 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
4030 if (t
> UI2_MAX
|| t
< UI2_MIN
) return DISP_E_OVERFLOW
;
4032 *pusOut
= (USHORT
)t
;
4037 /******************************************************************************
4038 * VarUI4FromUI1 [OLEAUT32.270]
4040 HRESULT WINAPI
VarUI4FromUI1(BYTE bIn
, ULONG
* pulOut
)
4042 TRACE("( %d, %p ), stub\n", bIn
, pulOut
);
4044 *pulOut
= (USHORT
) bIn
;
4049 /******************************************************************************
4050 * VarUI4FromI2 [OLEAUT32.271]
4052 HRESULT WINAPI
VarUI4FromI2(short uiIn
, ULONG
* pulOut
)
4054 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4056 if( uiIn
< UI4_MIN
)
4058 return DISP_E_OVERFLOW
;
4061 *pulOut
= (ULONG
) uiIn
;
4066 /******************************************************************************
4067 * VarUI4FromI4 [OLEAUT32.272]
4069 HRESULT WINAPI
VarUI4FromI4(LONG lIn
, ULONG
* pulOut
)
4071 TRACE("( %ld, %p ), stub\n", lIn
, pulOut
);
4075 return DISP_E_OVERFLOW
;
4078 *pulOut
= (ULONG
) lIn
;
4083 /******************************************************************************
4084 * VarUI4FromR4 [OLEAUT32.273]
4086 HRESULT WINAPI
VarUI4FromR4(FLOAT fltIn
, ULONG
* pulOut
)
4088 fltIn
= round( fltIn
);
4089 if( fltIn
< UI4_MIN
|| fltIn
> UI4_MAX
)
4091 return DISP_E_OVERFLOW
;
4094 *pulOut
= (ULONG
) fltIn
;
4099 /******************************************************************************
4100 * VarUI4FromR8 [OLEAUT32.274]
4102 HRESULT WINAPI
VarUI4FromR8(double dblIn
, ULONG
* pulOut
)
4104 TRACE("( %f, %p ), stub\n", dblIn
, pulOut
);
4106 dblIn
= round( dblIn
);
4107 if( dblIn
< UI4_MIN
|| dblIn
> UI4_MAX
)
4109 return DISP_E_OVERFLOW
;
4112 *pulOut
= (ULONG
) dblIn
;
4117 /******************************************************************************
4118 * VarUI4FromDate [OLEAUT32.275]
4120 HRESULT WINAPI
VarUI4FromDate(DATE dateIn
, ULONG
* pulOut
)
4122 TRACE("( %f, %p ), stub\n", dateIn
, pulOut
);
4124 dateIn
= round( dateIn
);
4125 if( dateIn
< UI4_MIN
|| dateIn
> UI4_MAX
)
4127 return DISP_E_OVERFLOW
;
4130 *pulOut
= (ULONG
) dateIn
;
4135 /******************************************************************************
4136 * VarUI4FromBool [OLEAUT32.279]
4138 HRESULT WINAPI
VarUI4FromBool(VARIANT_BOOL boolIn
, ULONG
* pulOut
)
4140 TRACE("( %d, %p ), stub\n", boolIn
, pulOut
);
4142 *pulOut
= (ULONG
) boolIn
;
4147 /******************************************************************************
4148 * VarUI4FromI1 [OLEAUT32.280]
4150 HRESULT WINAPI
VarUI4FromI1(CHAR cIn
, ULONG
* pulOut
)
4152 TRACE("( %c, %p ), stub\n", cIn
, pulOut
);
4154 *pulOut
= (ULONG
) cIn
;
4159 /******************************************************************************
4160 * VarUI4FromUI2 [OLEAUT32.281]
4162 HRESULT WINAPI
VarUI4FromUI2(USHORT uiIn
, ULONG
* pulOut
)
4164 TRACE("( %d, %p ), stub\n", uiIn
, pulOut
);
4166 *pulOut
= (ULONG
) uiIn
;
4171 /**********************************************************************
4172 * VarUI4FromCy [OLEAUT32.276]
4173 * Convert currency to unsigned long
4175 HRESULT WINAPI
VarUI4FromCy(CY cyIn
, ULONG
* pulOut
) {
4176 double t
= round((((double)cyIn
.s
.Hi
* 4294967296.0) + (double)cyIn
.s
.Lo
) / 10000);
4178 if (t
> UI4_MAX
|| t
< UI4_MIN
) return DISP_E_OVERFLOW
;
4185 /**********************************************************************
4186 * VarCyFromUI1 [OLEAUT32.98]
4187 * Convert unsigned char to currency
4189 HRESULT WINAPI
VarCyFromUI1(BYTE bIn
, CY
* pcyOut
) {
4191 pcyOut
->s
.Lo
= ((ULONG
)bIn
) * 10000;
4196 /**********************************************************************
4197 * VarCyFromI2 [OLEAUT32.99]
4198 * Convert signed short to currency
4200 HRESULT WINAPI
VarCyFromI2(short sIn
, CY
* pcyOut
) {
4201 if (sIn
< 0) pcyOut
->s
.Hi
= -1;
4202 else pcyOut
->s
.Hi
= 0;
4203 pcyOut
->s
.Lo
= ((ULONG
)sIn
) * 10000;
4208 /**********************************************************************
4209 * VarCyFromI4 [OLEAUT32.100]
4210 * Convert signed long to currency
4212 HRESULT WINAPI
VarCyFromI4(LONG lIn
, CY
* pcyOut
) {
4213 double t
= (double)lIn
* (double)10000;
4214 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4215 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4216 if (lIn
< 0) pcyOut
->s
.Hi
--;
4221 /**********************************************************************
4222 * VarCyFromR4 [OLEAUT32.101]
4223 * Convert float to currency
4225 HRESULT WINAPI
VarCyFromR4(FLOAT fltIn
, CY
* pcyOut
) {
4226 double t
= round((double)fltIn
* (double)10000);
4227 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4228 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4229 if (fltIn
< 0) pcyOut
->s
.Hi
--;
4234 /**********************************************************************
4235 * VarCyFromR8 [OLEAUT32.102]
4236 * Convert double to currency
4238 HRESULT WINAPI
VarCyFromR8(double dblIn
, CY
* pcyOut
) {
4239 double t
= round(dblIn
* (double)10000);
4240 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4241 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4242 if (dblIn
< 0) pcyOut
->s
.Hi
--;
4247 /**********************************************************************
4248 * VarCyFromDate [OLEAUT32.103]
4249 * Convert date to currency
4251 HRESULT WINAPI
VarCyFromDate(DATE dateIn
, CY
* pcyOut
) {
4252 double t
= round((double)dateIn
* (double)10000);
4253 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4254 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4255 if (dateIn
< 0) pcyOut
->s
.Hi
--;
4260 /**********************************************************************
4261 * VarCyFromStr [OLEAUT32.104]
4263 HRESULT WINAPI
VarCyFromStr(OLECHAR
*strIn
, LCID lcid
, ULONG dwFlags
, CY
*pcyOut
) {
4269 /**********************************************************************
4270 * VarCyFromBool [OLEAUT32.106]
4271 * Convert boolean to currency
4273 HRESULT WINAPI
VarCyFromBool(VARIANT_BOOL boolIn
, CY
* pcyOut
) {
4274 if (boolIn
< 0) pcyOut
->s
.Hi
= -1;
4275 else pcyOut
->s
.Hi
= 0;
4276 pcyOut
->s
.Lo
= (ULONG
)boolIn
* (ULONG
)10000;
4281 /**********************************************************************
4282 * VarCyFromI1 [OLEAUT32.225]
4283 * Convert signed char to currency
4285 HRESULT WINAPI
VarCyFromI1(signed char cIn
, CY
* pcyOut
) {
4286 if (cIn
< 0) pcyOut
->s
.Hi
= -1;
4287 else pcyOut
->s
.Hi
= 0;
4288 pcyOut
->s
.Lo
= (ULONG
)cIn
* (ULONG
)10000;
4293 /**********************************************************************
4294 * VarCyFromUI2 [OLEAUT32.226]
4295 * Convert unsigned short to currency
4297 HRESULT WINAPI
VarCyFromUI2(USHORT usIn
, CY
* pcyOut
) {
4299 pcyOut
->s
.Lo
= (ULONG
)usIn
* (ULONG
)10000;
4304 /**********************************************************************
4305 * VarCyFromUI4 [OLEAUT32.227]
4306 * Convert unsigned long to currency
4308 HRESULT WINAPI
VarCyFromUI4(ULONG ulIn
, CY
* pcyOut
) {
4309 double t
= (double)ulIn
* (double)10000;
4310 pcyOut
->s
.Hi
= (LONG
)(t
/ (double)4294967296.0);
4311 pcyOut
->s
.Lo
= (ULONG
)fmod(t
, (double)4294967296.0);
4317 /**********************************************************************
4318 * DosDateTimeToVariantTime [OLEAUT32.14]
4319 * Convert dos representation of time to the date and time representation
4320 * stored in a variant.
4322 INT WINAPI
DosDateTimeToVariantTime(USHORT wDosDate
, USHORT wDosTime
,
4327 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate
, wDosTime
, pvtime
);
4329 t
.tm_sec
= (wDosTime
& 0x001f) * 2;
4330 t
.tm_min
= (wDosTime
& 0x07e0) >> 5;
4331 t
.tm_hour
= (wDosTime
& 0xf800) >> 11;
4333 t
.tm_mday
= (wDosDate
& 0x001f);
4334 t
.tm_mon
= (wDosDate
& 0x01e0) >> 5;
4335 t
.tm_year
= ((wDosDate
& 0xfe00) >> 9) + 1980;
4337 return TmToDATE( &t
, pvtime
);
4341 /**********************************************************************
4342 * VarParseNumFromStr [OLEAUT32.46]
4344 HRESULT WINAPI
VarParseNumFromStr(OLECHAR
* strIn
, LCID lcid
, ULONG dwFlags
,
4345 NUMPARSE
* pnumprs
, BYTE
* rgbDig
)
4349 FIXME("(%s,flags=%lx,....), partial stub!\n",debugstr_w(strIn
),dwFlags
);
4350 FIXME("numparse: cDig=%d, InFlags=%lx\n",pnumprs
->cDig
,pnumprs
->dwInFlags
);
4352 /* The other struct components are to be set by us */
4354 memset(rgbDig
,0,pnumprs
->cDig
);
4357 for (i
=0; strIn
[i
] ;i
++) {
4358 if ((strIn
[i
]>='0') && (strIn
[i
]<='9')) {
4359 if (pnumprs
->cDig
> cDig
) {
4360 *(rgbDig
++)=strIn
[i
]-'0';
4366 pnumprs
->cDig
= cDig
;
4368 /* FIXME: Just patching some values in */
4369 pnumprs
->nPwr10
= 0;
4370 pnumprs
->nBaseShift
= 0;
4371 pnumprs
->cchUsed
= lastent
;
4372 pnumprs
->dwOutFlags
= NUMPRS_DECIMAL
;
4377 /**********************************************************************
4378 * VarNumFromParseNum [OLEAUT32.47]
4380 HRESULT WINAPI
VarNumFromParseNum(NUMPARSE
* pnumprs
, BYTE
* rgbDig
,
4381 ULONG dwVtBits
, VARIANT
* pvar
)
4385 FIXME("(,dwVtBits=%lx,....), partial stub!\n",dwVtBits
);
4388 for (i
=0;i
<pnumprs
->cDig
;i
++)
4389 xint
= xint
*10 + rgbDig
[i
];
4392 if (dwVtBits
& VTBIT_I4
) {
4394 V_UNION(pvar
,intVal
) = xint
;
4397 if (dwVtBits
& VTBIT_R8
) {
4399 V_UNION(pvar
,dblVal
) = xint
;
4402 FIXME("vtbitmask is unsupported %lx\n",dwVtBits
);
4408 /**********************************************************************
4409 * VariantTimeToDosDateTime [OLEAUT32.13]
4410 * Convert variant representation of time to the date and time representation
4413 INT WINAPI
VariantTimeToDosDateTime(DATE pvtime
, USHORT
*wDosDate
, USHORT
*wDosTime
)
4419 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", *wDosDate
, *wDosTime
, &pvtime
);
4421 if (DateToTm(pvtime
, 0, &t
) < 0) return 0;
4423 *wDosTime
= *wDosTime
| (t
.tm_sec
/ 2);
4424 *wDosTime
= *wDosTime
| (t
.tm_min
<< 5);
4425 *wDosTime
= *wDosTime
| (t
.tm_hour
<< 11);
4427 *wDosDate
= *wDosDate
| t
.tm_mday
;
4428 *wDosDate
= *wDosDate
| t
.tm_mon
<< 5;
4429 *wDosDate
= *wDosDate
| ((t
.tm_year
- 1980) << 9) ;
4435 /***********************************************************************
4436 * SystemTimeToVariantTime [OLEAUT32.184]
4438 HRESULT WINAPI
SystemTimeToVariantTime( LPSYSTEMTIME lpSystemTime
, double *pvtime
)
4440 static const BYTE Days_Per_Month
[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4441 static const BYTE Days_Per_Month_LY
[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4445 TRACE(" %d/%d/%d %d:%d:%d\n",
4446 lpSystemTime
->wMonth
, lpSystemTime
->wDay
,
4447 lpSystemTime
->wYear
, lpSystemTime
->wHour
,
4448 lpSystemTime
->wMinute
, lpSystemTime
->wSecond
);
4450 if (lpSystemTime
->wYear
>= 1900)
4452 t
.tm_sec
= lpSystemTime
->wSecond
;
4453 t
.tm_min
= lpSystemTime
->wMinute
;
4454 t
.tm_hour
= lpSystemTime
->wHour
;
4456 t
.tm_mday
= lpSystemTime
->wDay
;
4457 t
.tm_mon
= lpSystemTime
->wMonth
;
4458 t
.tm_year
= lpSystemTime
->wYear
;
4460 return TmToDATE( &t
, pvtime
);
4464 t
.tm_sec
= lpSystemTime
->wSecond
;
4465 t
.tm_min
= lpSystemTime
->wMinute
;
4466 t
.tm_hour
= lpSystemTime
->wHour
;
4468 if (isleap(lpSystemTime
->wYear
) )
4469 t
.tm_mday
= Days_Per_Month_LY
[13 - lpSystemTime
->wMonth
] - lpSystemTime
->wDay
;
4471 t
.tm_mday
= Days_Per_Month
[13 - lpSystemTime
->wMonth
] - lpSystemTime
->wDay
;
4473 t
.tm_mon
= 13 - lpSystemTime
->wMonth
;
4474 t
.tm_year
= 1900 + 1899 - lpSystemTime
->wYear
;
4476 TmToDATE( &t
, pvtime
);
4486 /***********************************************************************
4487 * VariantTimeToSystemTime [OLEAUT32.185]
4489 HRESULT WINAPI
VariantTimeToSystemTime( double vtime
, LPSYSTEMTIME lpSystemTime
)
4491 double t
= 0, timeofday
= 0;
4493 static const BYTE Days_Per_Month
[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4494 static const BYTE Days_Per_Month_LY
[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4496 /* The Month_Code is used to find the Day of the Week (LY = LeapYear)*/
4497 static const BYTE Month_Code
[] = {0, 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4498 static const BYTE Month_Code_LY
[] = {0, 0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4500 /* The Century_Code is used to find the Day of the Week */
4501 static const BYTE Century_Code
[] = {0, 6, 4, 2};
4505 TRACE(" Variant = %f SYSTEMTIME ptr %p", vtime
, lpSystemTime
);
4510 if (DateToTm(vtime
, 0, &r
) <= 0) return 0;
4512 lpSystemTime
->wSecond
= r
.tm_sec
;
4513 lpSystemTime
->wMinute
= r
.tm_min
;
4514 lpSystemTime
->wHour
= r
.tm_hour
;
4515 lpSystemTime
->wDay
= r
.tm_mday
;
4516 lpSystemTime
->wMonth
= r
.tm_mon
;
4518 if (lpSystemTime
->wMonth
== 12)
4519 lpSystemTime
->wMonth
= 1;
4521 lpSystemTime
->wMonth
++;
4523 lpSystemTime
->wYear
= r
.tm_year
;
4529 if (DateToTm(vtime
, 0, &r
) <= 0) return 0;
4531 lpSystemTime
->wSecond
= r
.tm_sec
;
4532 lpSystemTime
->wMinute
= r
.tm_min
;
4533 lpSystemTime
->wHour
= r
.tm_hour
;
4535 lpSystemTime
->wMonth
= 13 - r
.tm_mon
;
4537 if (lpSystemTime
->wMonth
== 1)
4538 lpSystemTime
->wMonth
= 12;
4540 lpSystemTime
->wMonth
--;
4542 lpSystemTime
->wYear
= 1899 - (r
.tm_year
- 1900);
4544 if (!isleap(lpSystemTime
->wYear
) )
4545 lpSystemTime
->wDay
= Days_Per_Month
[13 - lpSystemTime
->wMonth
] - r
.tm_mday
;
4547 lpSystemTime
->wDay
= Days_Per_Month_LY
[13 - lpSystemTime
->wMonth
] - r
.tm_mday
;
4552 if (!isleap(lpSystemTime
->wYear
))
4555 (Century_Code+Month_Code+Year_Code+Day) % 7
4557 The century code repeats every 400 years , so the array
4558 works out like this,
4560 Century_Code[0] is for 16th/20th Centry
4561 Century_Code[1] is for 17th/21th Centry
4562 Century_Code[2] is for 18th/22th Centry
4563 Century_Code[3] is for 19th/23th Centry
4565 The year code is found with the formula (year + (year / 4))
4566 the "year" must be between 0 and 99 .
4568 The Month Code (Month_Code[1]) starts with January and
4572 lpSystemTime
->wDayOfWeek
= (
4573 Century_Code
[(( (lpSystemTime
->wYear
+100) - lpSystemTime
->wYear
%100) /100) %4]+
4574 ((lpSystemTime
->wYear
%100)+(lpSystemTime
->wYear
%100)/4)+
4575 Month_Code
[lpSystemTime
->wMonth
]+
4576 lpSystemTime
->wDay
) % 7;
4578 if (lpSystemTime
->wDayOfWeek
== 0) lpSystemTime
->wDayOfWeek
= 7;
4579 else lpSystemTime
->wDayOfWeek
-= 1;
4583 lpSystemTime
->wDayOfWeek
= (
4584 Century_Code
[(((lpSystemTime
->wYear
+100) - lpSystemTime
->wYear
%100)/100)%4]+
4585 ((lpSystemTime
->wYear
%100)+(lpSystemTime
->wYear
%100)/4)+
4586 Month_Code_LY
[lpSystemTime
->wMonth
]+
4587 lpSystemTime
->wDay
) % 7;
4589 if (lpSystemTime
->wDayOfWeek
== 0) lpSystemTime
->wDayOfWeek
= 7;
4590 else lpSystemTime
->wDayOfWeek
-= 1;
4594 timeofday
= vtime
- t
;
4596 lpSystemTime
->wMilliseconds
= (timeofday
4597 - lpSystemTime
->wHour
*(1/24)
4598 - lpSystemTime
->wMinute
*(1/1440)
4599 - lpSystemTime
->wSecond
*(1/86400) )*(1/5184000);
4604 /***********************************************************************
4605 * VarUdateFromDate [OLEAUT32.331]
4607 HRESULT WINAPI
VarUdateFromDate( DATE datein
, ULONG dwFlags
, UDATE
*pudateout
)
4610 static const BYTE Days_Per_Month
[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4611 static const BYTE Days_Per_Month_LY
[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4613 TRACE("DATE = %f\n", (double)datein
);
4614 i
= VariantTimeToSystemTime(datein
, &(pudateout
->st
) );
4618 pudateout
->wDayOfYear
= 0;
4620 if (isleap(pudateout
->st
.wYear
))
4622 for (i
=1; i
<pudateout
->st
.wMonth
; i
++)
4623 pudateout
->wDayOfYear
+= Days_Per_Month
[i
];
4627 for (i
=1; i
<pudateout
->st
.wMonth
; i
++)
4628 pudateout
->wDayOfYear
+= Days_Per_Month_LY
[i
];
4631 pudateout
->wDayOfYear
+= pudateout
->st
.wDay
;
4632 dwFlags
= 0; /*VAR_VALIDDATE*/
4639 /***********************************************************************
4640 * VarDateFromUdate [OLEAUT32.330]
4642 HRESULT WINAPI
VarDateFromUdate(UDATE
*pudateout
,
4643 ULONG dwFlags
, DATE
*datein
)
4647 TRACE(" %d/%d/%d %d:%d:%d\n",
4648 pudateout
->st
.wMonth
, pudateout
->st
.wDay
,
4649 pudateout
->st
.wYear
, pudateout
->st
.wHour
,
4650 pudateout
->st
.wMinute
, pudateout
->st
.wSecond
);
4653 i
= SystemTimeToVariantTime(&(pudateout
->st
), &t
);
4656 if (i
) dwFlags
= 0; /*VAR_VALIDDATE*/
4663 /**********************************************************************
4664 * VarBstrCmp [OLEAUT32.440]
4667 * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS
4668 * NORM_IGNORESTRINGWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA
4671 HRESULT WINAPI
VarBstrCmp(BSTR left
, BSTR right
, LCID lcid
, DWORD flags
)
4675 FIXME("( %s %s %ld %lx ) partial stub\n", debugstr_w(left
), debugstr_w(right
), lcid
, flags
);
4677 if((!left
) || (!right
))
4680 if(flags
&NORM_IGNORECASE
)
4681 r
= lstrcmpiW(left
,right
);
4683 r
= lstrcmpW(left
,right
);
4693 /**********************************************************************
4694 * VarBstrCat [OLEAUT32.439]
4696 HRESULT WINAPI
VarBstrCat(BSTR left
, BSTR right
, BSTR
*out
)
4700 TRACE("( %s %s %p )\n", debugstr_w(left
), debugstr_w(right
), out
);
4702 if( (!left
) || (!right
) || (!out
) )
4705 result
= SysAllocStringLen(left
, lstrlenW(left
)+lstrlenW(right
));
4706 lstrcatW(result
,right
);