Removed a few inter-dll dependencies.
[wine/multimedia.git] / dlls / oleaut32 / variant.c
blob0895c547d1868f422906ffdfe268f017f5e26161
1 /*
2 * VARIANT
4 * Copyright 1998 Jean-Claude Cote
6 * NOTES
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.
12 * TODO:
13 * - The Variant APIs do not support international languages, currency
14 * types, number formating and calendar. They only support U.S. English format.
15 * - The Variant APIs do not the following types: IUknown, IDispatch, DECIMAL and SafeArray.
16 * The prototypes for these are commented out in the oleauto.h file. They need
17 * to be implemented and cases need to be added to the switches of the existing APIs.
18 * - The parsing of date for the VarDateFromStr is not complete.
19 * - The date manipulations do not support date prior to 1900.
20 * - The parsing does not accept has many formats has the Windows implementation.
23 #include "config.h"
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <time.h>
31 #ifdef HAVE_FLOAT_H
32 # include <float.h>
33 #endif
35 #include "windef.h"
36 #include "oleauto.h"
37 #include "heap.h"
38 #include "debugtools.h"
39 #include "winerror.h"
40 #include "parsedt.h"
42 DEFAULT_DEBUG_CHANNEL(ole);
44 #ifndef FLT_MAX
45 # ifdef MAXFLOAT
46 # define FLT_MAX MAXFLOAT
47 # else
48 # error "Can't find #define for MAXFLOAT/FLT_MAX"
49 # endif
50 #endif
52 #undef CHAR_MAX
53 #undef CHAR_MIN
54 static const char CHAR_MAX = 127;
55 static const char CHAR_MIN = -128;
56 static const BYTE UI1_MAX = 255;
57 static const BYTE UI1_MIN = 0;
58 static const unsigned short UI2_MAX = 65535;
59 static const unsigned short UI2_MIN = 0;
60 static const short I2_MAX = 32767;
61 static const short I2_MIN = -32768;
62 static const unsigned long UI4_MAX = 4294967295U;
63 static const unsigned long UI4_MIN = 0;
64 static const long I4_MAX = 2147483647;
65 static const long I4_MIN = -(2147483648U);
66 static const DATE DATE_MIN = -657434;
67 static const DATE DATE_MAX = 2958465;
70 /* This mask is used to set a flag in wReserved1 of
71 * the VARIANTARG structure. The flag indicates if
72 * the API function is using an inner variant or not.
74 #define PROCESSING_INNER_VARIANT 0x0001
76 /* General use buffer.
78 #define BUFFER_MAX 1024
79 static char pBuffer[BUFFER_MAX];
82 * Note a leap year is one that is a multiple of 4
83 * but not of a 100. Except if it is a multiple of
84 * 400 then it is a leap year.
86 /* According to postgeSQL date parsing functions there is
87 * a leap year when this expression is true.
88 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
89 * So according to this there is 365.2515 days in one year.
90 * One + every four years: 1/4 -> 365.25
91 * One - every 100 years: 1/100 -> 365.01
92 * One + every 400 years: 1/400 -> 365.0025
94 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
96 * ^^ Might this be the key to an easy way to factor large prime numbers?
97 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
99 static const double DAYS_IN_ONE_YEAR = 365.2425;
101 /******************************************************************************
102 * DateTimeStringToTm [INTERNAL]
104 * Converts a string representation of a date and/or time to a tm structure.
106 * Note this function uses the postgresql date parsing functions found
107 * in the parsedt.c file.
109 * Returns TRUE if successfull.
111 * Note: This function does not parse the day of the week,
112 * daylight savings time. It will only fill the followin fields in
113 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
115 ******************************************************************************/
116 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
118 BOOL res = FALSE;
119 double fsec;
120 int tzp;
121 int dtype;
122 int nf;
123 char *field[MAXDATEFIELDS];
124 int ftype[MAXDATEFIELDS];
125 char lowstr[MAXDATELEN + 1];
126 char* strDateTime = NULL;
128 /* Convert the string to ASCII since this is the only format
129 * postgesql can handle.
131 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
133 if( strDateTime != NULL )
135 /* Make sure we don't go over the maximum length
136 * accepted by postgesql.
138 if( strlen( strDateTime ) <= MAXDATELEN )
140 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
142 if( lcid & VAR_DATEVALUEONLY )
144 /* Get the date information.
145 * It returns 0 if date information was
146 * present and 1 if only time information was present.
147 * -1 if an error occures.
149 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
151 /* Eliminate the time information since we
152 * were asked to get date information only.
154 pTm->tm_sec = 0;
155 pTm->tm_min = 0;
156 pTm->tm_hour = 0;
157 res = TRUE;
160 if( lcid & VAR_TIMEVALUEONLY )
162 /* Get time information only.
164 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
166 res = TRUE;
169 else
171 /* Get both date and time information.
172 * It returns 0 if date information was
173 * present and 1 if only time information was present.
174 * -1 if an error occures.
176 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
178 res = TRUE;
183 HeapFree( GetProcessHeap(), 0, strDateTime );
186 return res;
194 /******************************************************************************
195 * TmToDATE [INTERNAL]
197 * The date is implemented using an 8 byte floating-point number.
198 * Days are represented by whole numbers increments starting with 0.00 has
199 * being December 30 1899, midnight.
200 * The hours are expressed as the fractional part of the number.
201 * December 30 1899 at midnight = 0.00
202 * January 1 1900 at midnight = 2.00
203 * January 4 1900 at 6 AM = 5.25
204 * January 4 1900 at noon = 5.50
205 * December 29 1899 at midnight = -1.00
206 * December 18 1899 at midnight = -12.00
207 * December 18 1899 at 6AM = -12.25
208 * December 18 1899 at 6PM = -12.75
209 * December 19 1899 at midnight = -11.00
210 * The tm structure is as follows:
211 * struct tm {
212 * int tm_sec; seconds after the minute - [0,59]
213 * int tm_min; minutes after the hour - [0,59]
214 * int tm_hour; hours since midnight - [0,23]
215 * int tm_mday; day of the month - [1,31]
216 * int tm_mon; months since January - [0,11]
217 * int tm_year; years
218 * int tm_wday; days since Sunday - [0,6]
219 * int tm_yday; days since January 1 - [0,365]
220 * int tm_isdst; daylight savings time flag
221 * };
223 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
224 * and tm_isdst fields of the tm structure. And only converts years
225 * after 1900.
227 * Returns TRUE if successfull.
229 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
231 if( (pTm->tm_year - 1900) >= 0 )
233 int leapYear = 0;
235 /* Start at 1. This is the way DATE is defined.
236 * January 1, 1900 at Midnight is 1.00.
237 * January 1, 1900 at 6AM is 1.25.
238 * and so on.
240 *pDateOut = 1;
242 /* Add the number of days corresponding to
243 * tm_year.
245 *pDateOut += (pTm->tm_year - 1900) * 365;
247 /* Add the leap days in the previous years between now and 1900.
248 * Note a leap year is one that is a multiple of 4
249 * but not of a 100. Except if it is a multiple of
250 * 400 then it is a leap year.
252 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
253 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
254 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
256 /* Set the leap year flag if the
257 * current year specified by tm_year is a
258 * leap year. This will be used to add a day
259 * to the day count.
261 if( isleap( pTm->tm_year ) )
262 leapYear = 1;
264 /* Add the number of days corresponding to
265 * the month.
267 switch( pTm->tm_mon )
269 case 2:
270 *pDateOut += 31;
271 break;
272 case 3:
273 *pDateOut += ( 59 + leapYear );
274 break;
275 case 4:
276 *pDateOut += ( 90 + leapYear );
277 break;
278 case 5:
279 *pDateOut += ( 120 + leapYear );
280 break;
281 case 6:
282 *pDateOut += ( 151 + leapYear );
283 break;
284 case 7:
285 *pDateOut += ( 181 + leapYear );
286 break;
287 case 8:
288 *pDateOut += ( 212 + leapYear );
289 break;
290 case 9:
291 *pDateOut += ( 243 + leapYear );
292 break;
293 case 10:
294 *pDateOut += ( 273 + leapYear );
295 break;
296 case 11:
297 *pDateOut += ( 304 + leapYear );
298 break;
299 case 12:
300 *pDateOut += ( 334 + leapYear );
301 break;
303 /* Add the number of days in this month.
305 *pDateOut += pTm->tm_mday;
307 /* Add the number of seconds, minutes, and hours
308 * to the DATE. Note these are the fracionnal part
309 * of the DATE so seconds / number of seconds in a day.
311 *pDateOut += pTm->tm_hour / 24.0;
312 *pDateOut += pTm->tm_min / 1440.0;
313 *pDateOut += pTm->tm_sec / 86400.0;
314 return TRUE;
316 return FALSE;
319 /******************************************************************************
320 * DateToTm [INTERNAL]
322 * This function converst a windows DATE to a tm structure.
324 * It does not fill all the fields of the tm structure.
325 * Here is a list of the fields that are filled:
326 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
328 * Note this function does not support dates before the January 1, 1900
329 * or ( dateIn < 2.0 ).
331 * Returns TRUE if successfull.
333 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
335 /* Do not process dates smaller than January 1, 1900.
336 * Which corresponds to 2.0 in the windows DATE format.
338 if( dateIn >= 2.0 )
340 double decimalPart = 0.0;
341 double wholePart = 0.0;
343 memset(pTm,0,sizeof(*pTm));
345 /* Because of the nature of DATE format witch
346 * associates 2.0 to January 1, 1900. We will
347 * remove 1.0 from the whole part of the DATE
348 * so that in the following code 1.0
349 * will correspond to January 1, 1900.
350 * This simplyfies the processing of the DATE value.
352 dateIn -= 1.0;
354 wholePart = (double) floor( dateIn );
355 decimalPart = fmod( dateIn, wholePart );
357 if( !(lcid & VAR_TIMEVALUEONLY) )
359 int nDay = 0;
360 int leapYear = 0;
361 double yearsSince1900 = 0;
362 /* Start at 1900, this where the DATE time 0.0 starts.
364 pTm->tm_year = 1900;
365 /* find in what year the day in the "wholePart" falls into.
366 * add the value to the year field.
368 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
369 pTm->tm_year += yearsSince1900;
370 /* determine if this is a leap year.
372 if( isleap( pTm->tm_year ) )
374 leapYear = 1;
375 wholePart++;
378 /* find what day of that year does the "wholePart" corresponds to.
379 * Note: nDay is in [1-366] format
381 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
382 /* Set the tm_yday value.
383 * Note: The day is must be converted from [1-366] to [0-365]
385 /*pTm->tm_yday = nDay - 1;*/
386 /* find which mount this day corresponds to.
388 if( nDay <= 31 )
390 pTm->tm_mday = nDay;
391 pTm->tm_mon = 0;
393 else if( nDay <= ( 59 + leapYear ) )
395 pTm->tm_mday = nDay - 31;
396 pTm->tm_mon = 1;
398 else if( nDay <= ( 90 + leapYear ) )
400 pTm->tm_mday = nDay - ( 59 + leapYear );
401 pTm->tm_mon = 2;
403 else if( nDay <= ( 120 + leapYear ) )
405 pTm->tm_mday = nDay - ( 90 + leapYear );
406 pTm->tm_mon = 3;
408 else if( nDay <= ( 151 + leapYear ) )
410 pTm->tm_mday = nDay - ( 120 + leapYear );
411 pTm->tm_mon = 4;
413 else if( nDay <= ( 181 + leapYear ) )
415 pTm->tm_mday = nDay - ( 151 + leapYear );
416 pTm->tm_mon = 5;
418 else if( nDay <= ( 212 + leapYear ) )
420 pTm->tm_mday = nDay - ( 181 + leapYear );
421 pTm->tm_mon = 6;
423 else if( nDay <= ( 243 + leapYear ) )
425 pTm->tm_mday = nDay - ( 212 + leapYear );
426 pTm->tm_mon = 7;
428 else if( nDay <= ( 273 + leapYear ) )
430 pTm->tm_mday = nDay - ( 243 + leapYear );
431 pTm->tm_mon = 8;
433 else if( nDay <= ( 304 + leapYear ) )
435 pTm->tm_mday = nDay - ( 273 + leapYear );
436 pTm->tm_mon = 9;
438 else if( nDay <= ( 334 + leapYear ) )
440 pTm->tm_mday = nDay - ( 304 + leapYear );
441 pTm->tm_mon = 10;
443 else if( nDay <= ( 365 + leapYear ) )
445 pTm->tm_mday = nDay - ( 334 + leapYear );
446 pTm->tm_mon = 11;
449 if( !(lcid & VAR_DATEVALUEONLY) )
451 /* find the number of seconds in this day.
452 * fractional part times, hours, minutes, seconds.
454 pTm->tm_hour = (int) ( decimalPart * 24 );
455 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
456 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
458 return TRUE;
460 return FALSE;
465 /******************************************************************************
466 * SizeOfVariantData [INTERNAL]
468 * This function finds the size of the data referenced by a Variant based
469 * the type "vt" of the Variant.
471 static int SizeOfVariantData( VARIANT* parg )
473 int size = 0;
474 switch( parg->vt & VT_TYPEMASK )
476 case( VT_I2 ):
477 size = sizeof(short);
478 break;
479 case( VT_INT ):
480 size = sizeof(int);
481 break;
482 case( VT_I4 ):
483 size = sizeof(long);
484 break;
485 case( VT_UI1 ):
486 size = sizeof(BYTE);
487 break;
488 case( VT_UI2 ):
489 size = sizeof(unsigned short);
490 break;
491 case( VT_UINT ):
492 size = sizeof(unsigned int);
493 break;
494 case( VT_UI4 ):
495 size = sizeof(unsigned long);
496 break;
497 case( VT_R4 ):
498 size = sizeof(float);
499 break;
500 case( VT_R8 ):
501 size = sizeof(double);
502 break;
503 case( VT_DATE ):
504 size = sizeof(DATE);
505 break;
506 case( VT_BOOL ):
507 size = sizeof(VARIANT_BOOL);
508 break;
509 case( VT_BSTR ):
510 size = sizeof(void*);
511 break;
512 case( VT_CY ):
513 case( VT_DISPATCH ):
514 case( VT_UNKNOWN ):
515 case( VT_DECIMAL ):
516 default:
517 FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
518 break;
521 return size;
523 /******************************************************************************
524 * StringDupAtoBstr [INTERNAL]
527 static BSTR StringDupAtoBstr( char* strIn )
529 BSTR bstr = NULL;
530 OLECHAR* pNewString = NULL;
531 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
532 bstr = SysAllocString( pNewString );
533 HeapFree( GetProcessHeap(), 0, pNewString );
534 return bstr;
537 /******************************************************************************
538 * round [INTERNAL]
540 * Round the double value to the nearest integer value.
542 static double round( double d )
544 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
545 BOOL bEvenNumber = FALSE;
546 int nSign = 0;
548 /* Save the sign of the number
550 nSign = (d >= 0.0) ? 1 : -1;
551 d = fabs( d );
553 /* Remove the decimals.
555 integerValue = floor( d );
557 /* Set the Even flag. This is used to round the number when
558 * the decimals are exactly 1/2. If the integer part is
559 * odd the number is rounded up. If the integer part
560 * is even the number is rounded down. Using this method
561 * numbers are rounded up|down half the time.
563 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
565 /* Remove the integral part of the number.
567 decimals = d - integerValue;
569 /* Note: Ceil returns the smallest integer that is greater that x.
570 * and floor returns the largest integer that is less than or equal to x.
572 if( decimals > 0.5 )
574 /* If the decimal part is greater than 1/2
576 roundedValue = ceil( d );
578 else if( decimals < 0.5 )
580 /* If the decimal part is smaller than 1/2
582 roundedValue = floor( d );
584 else
586 /* the decimals are exactly 1/2 so round according to
587 * the bEvenNumber flag.
589 if( bEvenNumber )
591 roundedValue = floor( d );
593 else
595 roundedValue = ceil( d );
599 return roundedValue * nSign;
602 /******************************************************************************
603 * RemoveCharacterFromString [INTERNAL]
605 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
607 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
609 LPSTR pNewString = NULL;
610 LPSTR strToken = NULL;
613 /* Check if we have a valid argument
615 if( str != NULL )
617 pNewString = strdup( str );
618 str[0] = '\0';
619 strToken = strtok( pNewString, strOfCharToRemove );
620 while( strToken != NULL ) {
621 strcat( str, strToken );
622 strToken = strtok( NULL, strOfCharToRemove );
624 free( pNewString );
626 return;
629 /******************************************************************************
630 * GetValidRealString [INTERNAL]
632 * Checks if the string is of proper format to be converted to a real value.
634 static BOOL IsValidRealString( LPSTR strRealString )
636 /* Real values that have a decimal point are required to either have
637 * digits before or after the decimal point. We will assume that
638 * we do not have any digits at either position. If we do encounter
639 * some we will disable this flag.
641 BOOL bDigitsRequired = TRUE;
642 /* Processed fields in the string representation of the real number.
644 BOOL bWhiteSpaceProcessed = FALSE;
645 BOOL bFirstSignProcessed = FALSE;
646 BOOL bFirstDigitsProcessed = FALSE;
647 BOOL bDecimalPointProcessed = FALSE;
648 BOOL bSecondDigitsProcessed = FALSE;
649 BOOL bExponentProcessed = FALSE;
650 BOOL bSecondSignProcessed = FALSE;
651 BOOL bThirdDigitsProcessed = FALSE;
652 /* Assume string parameter "strRealString" is valid and try to disprove it.
654 BOOL bValidRealString = TRUE;
656 /* Used to count the number of tokens in the "strRealString".
658 LPSTR strToken = NULL;
659 int nTokens = 0;
660 LPSTR pChar = NULL;
662 /* Check if we have a valid argument
664 if( strRealString == NULL )
666 bValidRealString = FALSE;
669 if( bValidRealString == TRUE )
671 /* Make sure we only have ONE token in the string.
673 strToken = strtok( strRealString, " " );
674 while( strToken != NULL ) {
675 nTokens++;
676 strToken = strtok( NULL, " " );
679 if( nTokens != 1 )
681 bValidRealString = FALSE;
686 /* Make sure this token contains only valid characters.
687 * The string argument to atof has the following form:
688 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
689 * Whitespace consists of space and|or <TAB> characters, which are ignored.
690 * Sign is either plus '+' or minus '-'.
691 * Digits are one or more decimal digits.
692 * Note: If no digits appear before the decimal point, at least one must
693 * appear after the decimal point.
694 * The decimal digits may be followed by an exponent.
695 * An Exponent consists of an introductory letter ( D, d, E, or e) and
696 * an optionally signed decimal integer.
698 pChar = strRealString;
699 while( bValidRealString == TRUE && *pChar != '\0' )
701 switch( *pChar )
703 /* If whitespace...
705 case ' ':
706 case '\t':
707 if( bWhiteSpaceProcessed ||
708 bFirstSignProcessed ||
709 bFirstDigitsProcessed ||
710 bDecimalPointProcessed ||
711 bSecondDigitsProcessed ||
712 bExponentProcessed ||
713 bSecondSignProcessed ||
714 bThirdDigitsProcessed )
716 bValidRealString = FALSE;
718 break;
719 /* If sign...
721 case '+':
722 case '-':
723 if( bFirstSignProcessed == FALSE )
725 if( bFirstDigitsProcessed ||
726 bDecimalPointProcessed ||
727 bSecondDigitsProcessed ||
728 bExponentProcessed ||
729 bSecondSignProcessed ||
730 bThirdDigitsProcessed )
732 bValidRealString = FALSE;
734 bWhiteSpaceProcessed = TRUE;
735 bFirstSignProcessed = TRUE;
737 else if( bSecondSignProcessed == FALSE )
739 /* Note: The exponent must be present in
740 * order to accept the second sign...
742 if( bExponentProcessed == FALSE ||
743 bThirdDigitsProcessed ||
744 bDigitsRequired )
746 bValidRealString = FALSE;
748 bFirstSignProcessed = TRUE;
749 bWhiteSpaceProcessed = TRUE;
750 bFirstDigitsProcessed = TRUE;
751 bDecimalPointProcessed = TRUE;
752 bSecondDigitsProcessed = TRUE;
753 bSecondSignProcessed = TRUE;
755 break;
757 /* If decimals...
759 case '0':
760 case '1':
761 case '2':
762 case '3':
763 case '4':
764 case '5':
765 case '6':
766 case '7':
767 case '8':
768 case '9':
769 if( bFirstDigitsProcessed == FALSE )
771 if( bDecimalPointProcessed ||
772 bSecondDigitsProcessed ||
773 bExponentProcessed ||
774 bSecondSignProcessed ||
775 bThirdDigitsProcessed )
777 bValidRealString = FALSE;
779 bFirstSignProcessed = TRUE;
780 bWhiteSpaceProcessed = TRUE;
781 /* We have found some digits before the decimal point
782 * so disable the "Digits required" flag.
784 bDigitsRequired = FALSE;
786 else if( bSecondDigitsProcessed == FALSE )
788 if( bExponentProcessed ||
789 bSecondSignProcessed ||
790 bThirdDigitsProcessed )
792 bValidRealString = FALSE;
794 bFirstSignProcessed = TRUE;
795 bWhiteSpaceProcessed = TRUE;
796 bFirstDigitsProcessed = TRUE;
797 bDecimalPointProcessed = TRUE;
798 /* We have found some digits after the decimal point
799 * so disable the "Digits required" flag.
801 bDigitsRequired = FALSE;
803 else if( bThirdDigitsProcessed == FALSE )
805 /* Getting here means everything else should be processed.
806 * If we get anything else than a decimal following this
807 * digit it will be flagged by the other cases, so
808 * we do not really need to do anything in here.
811 break;
812 /* If DecimalPoint...
814 case '.':
815 if( bDecimalPointProcessed ||
816 bSecondDigitsProcessed ||
817 bExponentProcessed ||
818 bSecondSignProcessed ||
819 bThirdDigitsProcessed )
821 bValidRealString = FALSE;
823 bFirstSignProcessed = TRUE;
824 bWhiteSpaceProcessed = TRUE;
825 bFirstDigitsProcessed = TRUE;
826 bDecimalPointProcessed = TRUE;
827 break;
828 /* If Exponent...
830 case 'e':
831 case 'E':
832 case 'd':
833 case 'D':
834 if( bExponentProcessed ||
835 bSecondSignProcessed ||
836 bThirdDigitsProcessed ||
837 bDigitsRequired )
839 bValidRealString = FALSE;
841 bFirstSignProcessed = TRUE;
842 bWhiteSpaceProcessed = TRUE;
843 bFirstDigitsProcessed = TRUE;
844 bDecimalPointProcessed = TRUE;
845 bSecondDigitsProcessed = TRUE;
846 bExponentProcessed = TRUE;
847 break;
848 default:
849 bValidRealString = FALSE;
850 break;
852 /* Process next character.
854 pChar++;
857 /* If the required digits were not present we have an invalid
858 * string representation of a real number.
860 if( bDigitsRequired == TRUE )
862 bValidRealString = FALSE;
865 return bValidRealString;
869 /******************************************************************************
870 * Coerce [INTERNAL]
872 * This function dispatches execution to the proper conversion API
873 * to do the necessary coercion.
875 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
877 HRESULT res = S_OK;
878 unsigned short vtFrom = 0;
879 vtFrom = ps->vt & VT_TYPEMASK;
881 /* Note: Since "long" and "int" values both have 4 bytes and are
882 * both signed integers "int" will be treated as "long" in the
883 * following code.
884 * The same goes for their unsigned versions.
887 /* Trivial Case: If the coercion is from two types that are
888 * identical then we can blindly copy from one argument to another.*/
889 if ((vt==vtFrom))
891 return VariantCopy(pd,ps);
894 /* Cases requiring thought*/
895 switch( vt )
898 case( VT_EMPTY ):
899 res = VariantClear( pd );
900 break;
901 case( VT_NULL ):
902 res = VariantClear( pd );
903 if( res == S_OK )
905 pd->vt = VT_NULL;
907 break;
908 case( VT_I1 ):
909 switch( vtFrom )
911 case( VT_I1 ):
912 res = VariantCopy( pd, ps );
913 break;
914 case( VT_I2 ):
915 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
916 break;
917 case( VT_INT ):
918 case( VT_I4 ):
919 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
920 break;
921 case( VT_UI1 ):
922 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
923 break;
924 case( VT_UI2 ):
925 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
926 break;
927 case( VT_UINT ):
928 case( VT_UI4 ):
929 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
930 break;
931 case( VT_R4 ):
932 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
933 break;
934 case( VT_R8 ):
935 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
936 break;
937 case( VT_DATE ):
938 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
939 break;
940 case( VT_BOOL ):
941 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
942 break;
943 case( VT_BSTR ):
944 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
945 break;
946 case( VT_CY ):
947 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
948 case( VT_DISPATCH ):
949 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
950 case( VT_UNKNOWN ):
951 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
952 case( VT_DECIMAL ):
953 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
954 default:
955 res = DISP_E_TYPEMISMATCH;
956 FIXME("Coercion from %d to %d\n", vtFrom, vt );
957 break;
959 break;
961 case( VT_I2 ):
962 switch( vtFrom )
964 case( VT_I1 ):
965 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
966 break;
967 case( VT_I2 ):
968 res = VariantCopy( pd, ps );
969 break;
970 case( VT_INT ):
971 case( VT_I4 ):
972 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
973 break;
974 case( VT_UI1 ):
975 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
976 break;
977 case( VT_UI2 ):
978 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
979 break;
980 case( VT_UINT ):
981 case( VT_UI4 ):
982 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
983 break;
984 case( VT_R4 ):
985 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
986 break;
987 case( VT_R8 ):
988 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
989 break;
990 case( VT_DATE ):
991 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
992 break;
993 case( VT_BOOL ):
994 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
995 break;
996 case( VT_BSTR ):
997 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
998 break;
999 case( VT_CY ):
1000 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
1001 case( VT_DISPATCH ):
1002 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1003 case( VT_UNKNOWN ):
1004 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
1005 case( VT_DECIMAL ):
1006 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
1007 default:
1008 res = DISP_E_TYPEMISMATCH;
1009 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1010 break;
1012 break;
1014 case( VT_INT ):
1015 case( VT_I4 ):
1016 switch( vtFrom )
1018 case( VT_I1 ):
1019 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1020 break;
1021 case( VT_I2 ):
1022 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1023 break;
1024 case( VT_INT ):
1025 case( VT_I4 ):
1026 res = VariantCopy( pd, ps );
1027 break;
1028 case( VT_UI1 ):
1029 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1030 break;
1031 case( VT_UI2 ):
1032 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1033 break;
1034 case( VT_UINT ):
1035 case( VT_UI4 ):
1036 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1037 break;
1038 case( VT_R4 ):
1039 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1040 break;
1041 case( VT_R8 ):
1042 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1043 break;
1044 case( VT_DATE ):
1045 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1046 break;
1047 case( VT_BOOL ):
1048 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1049 break;
1050 case( VT_BSTR ):
1051 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1052 break;
1053 case( VT_CY ):
1054 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1055 case( VT_DISPATCH ):
1056 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1057 case( VT_UNKNOWN ):
1058 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1059 case( VT_DECIMAL ):
1060 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1061 default:
1062 res = DISP_E_TYPEMISMATCH;
1063 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1064 break;
1066 break;
1068 case( VT_UI1 ):
1069 switch( vtFrom )
1071 case( VT_I1 ):
1072 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1073 break;
1074 case( VT_I2 ):
1075 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1076 break;
1077 case( VT_INT ):
1078 case( VT_I4 ):
1079 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1080 break;
1081 case( VT_UI1 ):
1082 res = VariantCopy( pd, ps );
1083 break;
1084 case( VT_UI2 ):
1085 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1086 break;
1087 case( VT_UINT ):
1088 case( VT_UI4 ):
1089 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1090 break;
1091 case( VT_R4 ):
1092 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1093 break;
1094 case( VT_R8 ):
1095 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1096 break;
1097 case( VT_DATE ):
1098 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1099 break;
1100 case( VT_BOOL ):
1101 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1102 break;
1103 case( VT_BSTR ):
1104 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1105 break;
1106 case( VT_CY ):
1107 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1108 case( VT_DISPATCH ):
1109 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1110 case( VT_UNKNOWN ):
1111 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1112 case( VT_DECIMAL ):
1113 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1114 default:
1115 res = DISP_E_TYPEMISMATCH;
1116 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1117 break;
1119 break;
1121 case( VT_UI2 ):
1122 switch( vtFrom )
1124 case( VT_I1 ):
1125 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1126 break;
1127 case( VT_I2 ):
1128 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1129 break;
1130 case( VT_INT ):
1131 case( VT_I4 ):
1132 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1133 break;
1134 case( VT_UI1 ):
1135 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1136 break;
1137 case( VT_UI2 ):
1138 res = VariantCopy( pd, ps );
1139 break;
1140 case( VT_UINT ):
1141 case( VT_UI4 ):
1142 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1143 break;
1144 case( VT_R4 ):
1145 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1146 break;
1147 case( VT_R8 ):
1148 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1149 break;
1150 case( VT_DATE ):
1151 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1152 break;
1153 case( VT_BOOL ):
1154 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1155 break;
1156 case( VT_BSTR ):
1157 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1158 break;
1159 case( VT_CY ):
1160 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1161 case( VT_DISPATCH ):
1162 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1163 case( VT_UNKNOWN ):
1164 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1165 case( VT_DECIMAL ):
1166 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1167 default:
1168 res = DISP_E_TYPEMISMATCH;
1169 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1170 break;
1172 break;
1174 case( VT_UINT ):
1175 case( VT_UI4 ):
1176 switch( vtFrom )
1178 case( VT_I1 ):
1179 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1180 break;
1181 case( VT_I2 ):
1182 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1183 break;
1184 case( VT_INT ):
1185 case( VT_I4 ):
1186 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1187 break;
1188 case( VT_UI1 ):
1189 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1190 break;
1191 case( VT_UI2 ):
1192 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1193 break;
1194 case( VT_UI4 ):
1195 res = VariantCopy( pd, ps );
1196 break;
1197 case( VT_R4 ):
1198 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1199 break;
1200 case( VT_R8 ):
1201 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1202 break;
1203 case( VT_DATE ):
1204 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1205 break;
1206 case( VT_BOOL ):
1207 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1208 break;
1209 case( VT_BSTR ):
1210 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1211 break;
1212 case( VT_CY ):
1213 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1214 case( VT_DISPATCH ):
1215 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1216 case( VT_UNKNOWN ):
1217 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1218 case( VT_DECIMAL ):
1219 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1220 default:
1221 res = DISP_E_TYPEMISMATCH;
1222 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1223 break;
1225 break;
1227 case( VT_R4 ):
1228 switch( vtFrom )
1230 case( VT_I1 ):
1231 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1232 break;
1233 case( VT_I2 ):
1234 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1235 break;
1236 case( VT_INT ):
1237 case( VT_I4 ):
1238 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1239 break;
1240 case( VT_UI1 ):
1241 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1242 break;
1243 case( VT_UI2 ):
1244 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1245 break;
1246 case( VT_UINT ):
1247 case( VT_UI4 ):
1248 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1249 break;
1250 case( VT_R4 ):
1251 res = VariantCopy( pd, ps );
1252 break;
1253 case( VT_R8 ):
1254 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1255 break;
1256 case( VT_DATE ):
1257 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1258 break;
1259 case( VT_BOOL ):
1260 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1261 break;
1262 case( VT_BSTR ):
1263 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1264 break;
1265 case( VT_CY ):
1266 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1267 case( VT_DISPATCH ):
1268 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1269 case( VT_UNKNOWN ):
1270 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1271 case( VT_DECIMAL ):
1272 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1273 default:
1274 res = DISP_E_TYPEMISMATCH;
1275 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1276 break;
1278 break;
1280 case( VT_R8 ):
1281 switch( vtFrom )
1283 case( VT_I1 ):
1284 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1285 break;
1286 case( VT_I2 ):
1287 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1288 break;
1289 case( VT_INT ):
1290 case( VT_I4 ):
1291 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1292 break;
1293 case( VT_UI1 ):
1294 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1295 break;
1296 case( VT_UI2 ):
1297 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1298 break;
1299 case( VT_UINT ):
1300 case( VT_UI4 ):
1301 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1302 break;
1303 case( VT_R4 ):
1304 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1305 break;
1306 case( VT_R8 ):
1307 res = VariantCopy( pd, ps );
1308 break;
1309 case( VT_DATE ):
1310 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1311 break;
1312 case( VT_BOOL ):
1313 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1314 break;
1315 case( VT_BSTR ):
1316 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1317 break;
1318 case( VT_CY ):
1319 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1320 case( VT_DISPATCH ):
1321 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1322 case( VT_UNKNOWN ):
1323 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1324 case( VT_DECIMAL ):
1325 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1326 default:
1327 res = DISP_E_TYPEMISMATCH;
1328 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1329 break;
1331 break;
1333 case( VT_DATE ):
1334 switch( vtFrom )
1336 case( VT_I1 ):
1337 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1338 break;
1339 case( VT_I2 ):
1340 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1341 break;
1342 case( VT_INT ):
1343 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1344 break;
1345 case( VT_I4 ):
1346 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1347 break;
1348 case( VT_UI1 ):
1349 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1350 break;
1351 case( VT_UI2 ):
1352 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1353 break;
1354 case( VT_UINT ):
1355 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1356 break;
1357 case( VT_UI4 ):
1358 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1359 break;
1360 case( VT_R4 ):
1361 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1362 break;
1363 case( VT_R8 ):
1364 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1365 break;
1366 case( VT_DATE ):
1367 res = VariantCopy( pd, ps );
1368 break;
1369 case( VT_BOOL ):
1370 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1371 break;
1372 case( VT_BSTR ):
1373 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1374 break;
1375 case( VT_CY ):
1376 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1377 case( VT_DISPATCH ):
1378 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1379 case( VT_UNKNOWN ):
1380 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1381 case( VT_DECIMAL ):
1382 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1383 default:
1384 res = DISP_E_TYPEMISMATCH;
1385 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1386 break;
1388 break;
1390 case( VT_BOOL ):
1391 switch( vtFrom )
1393 case( VT_I1 ):
1394 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1395 break;
1396 case( VT_I2 ):
1397 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1398 break;
1399 case( VT_INT ):
1400 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1401 break;
1402 case( VT_I4 ):
1403 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1404 break;
1405 case( VT_UI1 ):
1406 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1407 break;
1408 case( VT_UI2 ):
1409 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1410 break;
1411 case( VT_UINT ):
1412 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1413 break;
1414 case( VT_UI4 ):
1415 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1416 break;
1417 case( VT_R4 ):
1418 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1419 break;
1420 case( VT_R8 ):
1421 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1422 break;
1423 case( VT_DATE ):
1424 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1425 break;
1426 case( VT_BOOL ):
1427 res = VariantCopy( pd, ps );
1428 break;
1429 case( VT_BSTR ):
1430 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1431 break;
1432 case( VT_CY ):
1433 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1434 case( VT_DISPATCH ):
1435 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1436 case( VT_UNKNOWN ):
1437 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1438 case( VT_DECIMAL ):
1439 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1440 default:
1441 res = DISP_E_TYPEMISMATCH;
1442 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1443 break;
1445 break;
1447 case( VT_BSTR ):
1448 switch( vtFrom )
1450 case( VT_I1 ):
1451 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1452 break;
1453 case( VT_I2 ):
1454 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1455 break;
1456 case( VT_INT ):
1457 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1458 break;
1459 case( VT_I4 ):
1460 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1461 break;
1462 case( VT_UI1 ):
1463 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1464 break;
1465 case( VT_UI2 ):
1466 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1467 break;
1468 case( VT_UINT ):
1469 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1470 break;
1471 case( VT_UI4 ):
1472 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1473 break;
1474 case( VT_R4 ):
1475 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1476 break;
1477 case( VT_R8 ):
1478 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1479 break;
1480 case( VT_DATE ):
1481 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1482 break;
1483 case( VT_BOOL ):
1484 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1485 break;
1486 case( VT_BSTR ):
1487 res = VariantCopy( pd, ps );
1488 break;
1489 case( VT_CY ):
1490 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1491 case( VT_DISPATCH ):
1492 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1493 case( VT_UNKNOWN ):
1494 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1495 case( VT_DECIMAL ):
1496 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1497 default:
1498 res = DISP_E_TYPEMISMATCH;
1499 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1500 break;
1502 break;
1504 case( VT_CY ):
1505 switch( vtFrom )
1507 case( VT_I1 ):
1508 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1509 break;
1510 case( VT_I2 ):
1511 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1512 break;
1513 case( VT_INT ):
1514 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1515 break;
1516 case( VT_I4 ):
1517 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1518 break;
1519 case( VT_UI1 ):
1520 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1521 break;
1522 case( VT_UI2 ):
1523 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1524 break;
1525 case( VT_UINT ):
1526 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1527 break;
1528 case( VT_UI4 ):
1529 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1530 break;
1531 case( VT_R4 ):
1532 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1533 break;
1534 case( VT_R8 ):
1535 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1536 break;
1537 case( VT_DATE ):
1538 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1539 break;
1540 case( VT_BOOL ):
1541 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1542 break;
1543 case( VT_CY ):
1544 res = VariantCopy( pd, ps );
1545 break;
1546 case( VT_BSTR ):
1547 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1548 case( VT_DISPATCH ):
1549 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1550 case( VT_UNKNOWN ):
1551 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1552 case( VT_DECIMAL ):
1553 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1554 default:
1555 res = DISP_E_TYPEMISMATCH;
1556 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1557 break;
1559 break;
1561 default:
1562 res = DISP_E_TYPEMISMATCH;
1563 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1564 break;
1567 return res;
1570 /******************************************************************************
1571 * ValidateVtRange [INTERNAL]
1573 * Used internally by the hi-level Variant API to determine
1574 * if the vartypes are valid.
1576 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1578 /* if by value we must make sure it is in the
1579 * range of the valid types.
1581 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1583 return DISP_E_BADVARTYPE;
1585 return S_OK;
1589 /******************************************************************************
1590 * ValidateVartype [INTERNAL]
1592 * Used internally by the hi-level Variant API to determine
1593 * if the vartypes are valid.
1595 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1597 HRESULT res = S_OK;
1599 /* check if we have a valid argument.
1601 if( vt & VT_BYREF )
1603 /* if by reference check that the type is in
1604 * the valid range and that it is not of empty or null type
1606 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1607 ( vt & VT_TYPEMASK ) == VT_NULL ||
1608 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1610 res = E_INVALIDARG;
1614 else
1616 res = ValidateVtRange( vt );
1619 return res;
1622 /******************************************************************************
1623 * ValidateVt [INTERNAL]
1625 * Used internally by the hi-level Variant API to determine
1626 * if the vartypes are valid.
1628 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1630 HRESULT res = S_OK;
1632 /* check if we have a valid argument.
1634 if( vt & VT_BYREF )
1636 /* if by reference check that the type is in
1637 * the valid range and that it is not of empty or null type
1639 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1640 ( vt & VT_TYPEMASK ) == VT_NULL ||
1641 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1643 res = DISP_E_BADVARTYPE;
1647 else
1649 res = ValidateVtRange( vt );
1652 return res;
1659 /******************************************************************************
1660 * VariantInit [OLEAUT32.8]
1662 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1663 * contents of the Variant.
1665 void WINAPI VariantInit(VARIANTARG* pvarg)
1667 TRACE("(%p),stub\n",pvarg);
1669 memset(pvarg, 0, sizeof (VARIANTARG));
1670 pvarg->vt = VT_EMPTY;
1672 return;
1675 /******************************************************************************
1676 * VariantClear [OLEAUT32.9]
1678 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1679 * sets the wReservedX field to 0. The current contents of the VARIANT are
1680 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1681 * released. If VT_ARRAY the array is freed.
1683 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1685 HRESULT res = S_OK;
1686 TRACE("(%p)\n",pvarg);
1688 res = ValidateVariantType( pvarg->vt );
1689 if( res == S_OK )
1691 if( !( pvarg->vt & VT_BYREF ) )
1694 * The VT_ARRAY flag is a special case of a safe array.
1696 if ( (pvarg->vt & VT_ARRAY) != 0)
1698 SafeArrayDestroy(pvarg->u.parray);
1700 else
1702 switch( pvarg->vt & VT_TYPEMASK )
1704 case( VT_BSTR ):
1705 SysFreeString( pvarg->u.bstrVal );
1706 break;
1707 case( VT_DISPATCH ):
1708 if(pvarg->u.pdispVal!=NULL)
1709 ICOM_CALL(Release,pvarg->u.pdispVal);
1710 break;
1711 case( VT_VARIANT ):
1712 VariantClear(pvarg->u.pvarVal);
1713 break;
1714 case( VT_UNKNOWN ):
1715 if(pvarg->u.punkVal!=NULL)
1716 ICOM_CALL(Release,pvarg->u.punkVal);
1717 break;
1718 case( VT_SAFEARRAY ):
1719 SafeArrayDestroy(pvarg->u.parray);
1720 break;
1721 default:
1722 break;
1728 * Empty all the fields and mark the type as empty.
1730 memset(pvarg, 0, sizeof (VARIANTARG));
1731 pvarg->vt = VT_EMPTY;
1734 return res;
1737 /******************************************************************************
1738 * VariantCopy [OLEAUT32.10]
1740 * Frees up the designation variant and makes a copy of the source.
1742 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1744 HRESULT res = S_OK;
1746 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1748 res = ValidateVariantType( pvargSrc->vt );
1750 /* If the pointer are to the same variant we don't need
1751 * to do anything.
1753 if( pvargDest != pvargSrc && res == S_OK )
1755 res = VariantClear( pvargDest );
1757 if( res == S_OK )
1759 if( pvargSrc->vt & VT_BYREF )
1761 /* In the case of byreference we only need
1762 * to copy the pointer.
1764 pvargDest->u = pvargSrc->u;
1765 pvargDest->vt = pvargSrc->vt;
1767 else
1770 * The VT_ARRAY flag is another way to designate a safe array.
1772 if (pvargSrc->vt & VT_ARRAY)
1774 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1776 else
1778 /* In the case of by value we need to
1779 * copy the actuall value. In the case of
1780 * VT_BSTR a copy of the string is made,
1781 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1782 * called to increment the object's reference count.
1784 switch( pvargSrc->vt & VT_TYPEMASK )
1786 case( VT_BSTR ):
1787 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1788 break;
1789 case( VT_DISPATCH ):
1790 pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1791 if (pvargDest->u.pdispVal!=NULL)
1792 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1793 break;
1794 case( VT_VARIANT ):
1795 VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1796 break;
1797 case( VT_UNKNOWN ):
1798 pvargDest->u.punkVal = pvargSrc->u.punkVal;
1799 if (pvargDest->u.pdispVal!=NULL)
1800 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1801 break;
1802 case( VT_SAFEARRAY ):
1803 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1804 break;
1805 default:
1806 pvargDest->u = pvargSrc->u;
1807 break;
1811 pvargDest->vt = pvargSrc->vt;
1816 return res;
1820 /******************************************************************************
1821 * VariantCopyInd [OLEAUT32.11]
1823 * Frees up the destination variant and makes a copy of the source. If
1824 * the source is of type VT_BYREF it performs the necessary indirections.
1826 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1828 HRESULT res = S_OK;
1830 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1832 res = ValidateVariantType( pvargSrc->vt );
1834 if( res != S_OK )
1835 return res;
1837 if( pvargSrc->vt & VT_BYREF )
1839 VARIANTARG varg;
1840 VariantInit( &varg );
1842 /* handle the in place copy.
1844 if( pvargDest == pvargSrc )
1846 /* we will use a copy of the source instead.
1848 res = VariantCopy( &varg, pvargSrc );
1849 pvargSrc = &varg;
1852 if( res == S_OK )
1854 res = VariantClear( pvargDest );
1856 if( res == S_OK )
1859 * The VT_ARRAY flag is another way to designate a safearray variant.
1861 if ( pvargSrc->vt & VT_ARRAY)
1863 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1865 else
1867 /* In the case of by reference we need
1868 * to copy the date pointed to by the variant.
1871 /* Get the variant type.
1873 switch( pvargSrc->vt & VT_TYPEMASK )
1875 case( VT_BSTR ):
1876 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1877 break;
1878 case( VT_DISPATCH ):
1879 break;
1880 case( VT_VARIANT ):
1882 /* Prevent from cycling. According to tests on
1883 * VariantCopyInd in Windows and the documentation
1884 * this API dereferences the inner Variants to only one depth.
1885 * If the inner Variant itself contains an
1886 * other inner variant the E_INVALIDARG error is
1887 * returned.
1889 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1891 /* If we get here we are attempting to deference
1892 * an inner variant that that is itself contained
1893 * in an inner variant so report E_INVALIDARG error.
1895 res = E_INVALIDARG;
1897 else
1899 /* Set the processing inner variant flag.
1900 * We will set this flag in the inner variant
1901 * that will be passed to the VariantCopyInd function.
1903 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1905 /* Dereference the inner variant.
1907 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1908 /* We must also copy its type, I think.
1910 pvargSrc->vt = pvargSrc->u.pvarVal->vt;
1913 break;
1914 case( VT_UNKNOWN ):
1915 break;
1916 case( VT_SAFEARRAY ):
1917 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1918 break;
1919 default:
1920 /* This is a by reference Variant which means that the union
1921 * part of the Variant contains a pointer to some data of
1922 * type "pvargSrc->vt & VT_TYPEMASK".
1923 * We will deference this data in a generic fashion using
1924 * the void pointer "Variant.u.byref".
1925 * We will copy this data into the union of the destination
1926 * Variant.
1928 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1929 break;
1933 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1937 /* this should not fail.
1939 VariantClear( &varg );
1941 else
1943 res = VariantCopy( pvargDest, pvargSrc );
1946 return res;
1949 /******************************************************************************
1950 * VariantChangeType [OLEAUT32.12]
1952 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1953 USHORT wFlags, VARTYPE vt)
1955 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1958 /******************************************************************************
1959 * VariantChangeTypeEx [OLEAUT32.147]
1961 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1962 LCID lcid, USHORT wFlags, VARTYPE vt)
1964 HRESULT res = S_OK;
1965 VARIANTARG varg;
1966 VariantInit( &varg );
1968 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1970 /* validate our source argument.
1972 res = ValidateVariantType( pvargSrc->vt );
1974 /* validate the vartype.
1976 if( res == S_OK )
1978 res = ValidateVt( vt );
1981 /* if we are doing an in-place conversion make a copy of the source.
1983 if( res == S_OK && pvargDest == pvargSrc )
1985 res = VariantCopy( &varg, pvargSrc );
1986 pvargSrc = &varg;
1989 if( res == S_OK )
1991 /* free up the destination variant.
1993 res = VariantClear( pvargDest );
1996 if( res == S_OK )
1998 if( pvargSrc->vt & VT_BYREF )
2000 /* Convert the source variant to a "byvalue" variant.
2002 VARIANTARG Variant;
2003 VariantInit( &Variant );
2004 res = VariantCopyInd( &Variant, pvargSrc );
2005 if( res == S_OK )
2007 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2008 /* this should not fail.
2010 VariantClear( &Variant );
2014 else
2016 /* Use the current "byvalue" source variant.
2018 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2021 /* this should not fail.
2023 VariantClear( &varg );
2025 /* set the type of the destination
2027 if ( res == S_OK )
2028 pvargDest->vt = vt;
2030 return res;
2036 /******************************************************************************
2037 * VarUI1FromI2 [OLEAUT32.130]
2039 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2041 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2043 /* Check range of value.
2045 if( sIn < UI1_MIN || sIn > UI1_MAX )
2047 return DISP_E_OVERFLOW;
2050 *pbOut = (BYTE) sIn;
2052 return S_OK;
2055 /******************************************************************************
2056 * VarUI1FromI4 [OLEAUT32.131]
2058 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2060 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2062 /* Check range of value.
2064 if( lIn < UI1_MIN || lIn > UI1_MAX )
2066 return DISP_E_OVERFLOW;
2069 *pbOut = (BYTE) lIn;
2071 return S_OK;
2075 /******************************************************************************
2076 * VarUI1FromR4 [OLEAUT32.132]
2078 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2080 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2082 /* Check range of value.
2084 fltIn = round( fltIn );
2085 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2087 return DISP_E_OVERFLOW;
2090 *pbOut = (BYTE) fltIn;
2092 return S_OK;
2095 /******************************************************************************
2096 * VarUI1FromR8 [OLEAUT32.133]
2098 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2100 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2102 /* Check range of value.
2104 dblIn = round( dblIn );
2105 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2107 return DISP_E_OVERFLOW;
2110 *pbOut = (BYTE) dblIn;
2112 return S_OK;
2115 /******************************************************************************
2116 * VarUI1FromDate [OLEAUT32.135]
2118 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2120 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2122 /* Check range of value.
2124 dateIn = round( dateIn );
2125 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2127 return DISP_E_OVERFLOW;
2130 *pbOut = (BYTE) dateIn;
2132 return S_OK;
2135 /******************************************************************************
2136 * VarUI1FromBool [OLEAUT32.138]
2138 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2140 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2142 *pbOut = (BYTE) boolIn;
2144 return S_OK;
2147 /******************************************************************************
2148 * VarUI1FromI1 [OLEAUT32.237]
2150 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2152 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2154 *pbOut = cIn;
2156 return S_OK;
2159 /******************************************************************************
2160 * VarUI1FromUI2 [OLEAUT32.238]
2162 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2164 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2166 /* Check range of value.
2168 if( uiIn > UI1_MAX )
2170 return DISP_E_OVERFLOW;
2173 *pbOut = (BYTE) uiIn;
2175 return S_OK;
2178 /******************************************************************************
2179 * VarUI1FromUI4 [OLEAUT32.239]
2181 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2183 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2185 /* Check range of value.
2187 if( ulIn > UI1_MAX )
2189 return DISP_E_OVERFLOW;
2192 *pbOut = (BYTE) ulIn;
2194 return S_OK;
2198 /******************************************************************************
2199 * VarUI1FromStr [OLEAUT32.54]
2201 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2203 double dValue = 0.0;
2204 LPSTR pNewString = NULL;
2206 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2208 /* Check if we have a valid argument
2210 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2211 RemoveCharacterFromString( pNewString, "," );
2212 if( IsValidRealString( pNewString ) == FALSE )
2214 return DISP_E_TYPEMISMATCH;
2217 /* Convert the valid string to a floating point number.
2219 dValue = atof( pNewString );
2221 /* We don't need the string anymore so free it.
2223 HeapFree( GetProcessHeap(), 0 , pNewString );
2225 /* Check range of value.
2227 dValue = round( dValue );
2228 if( dValue < UI1_MIN || dValue > UI1_MAX )
2230 return DISP_E_OVERFLOW;
2233 *pbOut = (BYTE) dValue;
2235 return S_OK;
2238 /**********************************************************************
2239 * VarUI1FromCy [OLEAUT32.134]
2240 * Convert currency to unsigned char
2242 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2243 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2245 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2247 *pbOut = (BYTE)t;
2248 return S_OK;
2251 /******************************************************************************
2252 * VarI2FromUI1 [OLEAUT32.48]
2254 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2256 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2258 *psOut = (short) bIn;
2260 return S_OK;
2263 /******************************************************************************
2264 * VarI2FromI4 [OLEAUT32.49]
2266 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2268 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2270 /* Check range of value.
2272 if( lIn < I2_MIN || lIn > I2_MAX )
2274 return DISP_E_OVERFLOW;
2277 *psOut = (short) lIn;
2279 return S_OK;
2282 /******************************************************************************
2283 * VarI2FromR4 [OLEAUT32.50]
2285 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2287 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2289 /* Check range of value.
2291 fltIn = round( fltIn );
2292 if( fltIn < I2_MIN || fltIn > I2_MAX )
2294 return DISP_E_OVERFLOW;
2297 *psOut = (short) fltIn;
2299 return S_OK;
2302 /******************************************************************************
2303 * VarI2FromR8 [OLEAUT32.51]
2305 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2307 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2309 /* Check range of value.
2311 dblIn = round( dblIn );
2312 if( dblIn < I2_MIN || dblIn > I2_MAX )
2314 return DISP_E_OVERFLOW;
2317 *psOut = (short) dblIn;
2319 return S_OK;
2322 /******************************************************************************
2323 * VarI2FromDate [OLEAUT32.53]
2325 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2327 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2329 /* Check range of value.
2331 dateIn = round( dateIn );
2332 if( dateIn < I2_MIN || dateIn > I2_MAX )
2334 return DISP_E_OVERFLOW;
2337 *psOut = (short) dateIn;
2339 return S_OK;
2342 /******************************************************************************
2343 * VarI2FromBool [OLEAUT32.56]
2345 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2347 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2349 *psOut = (short) boolIn;
2351 return S_OK;
2354 /******************************************************************************
2355 * VarI2FromI1 [OLEAUT32.48]
2357 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2359 TRACE("( %c, %p ), stub\n", cIn, psOut );
2361 *psOut = (short) cIn;
2363 return S_OK;
2366 /******************************************************************************
2367 * VarI2FromUI2 [OLEAUT32.206]
2369 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2371 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2373 /* Check range of value.
2375 if( uiIn > I2_MAX )
2377 return DISP_E_OVERFLOW;
2380 *psOut = (short) uiIn;
2382 return S_OK;
2385 /******************************************************************************
2386 * VarI2FromUI4 [OLEAUT32.49]
2388 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2390 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2392 /* Check range of value.
2394 if( ulIn < I2_MIN || ulIn > I2_MAX )
2396 return DISP_E_OVERFLOW;
2399 *psOut = (short) ulIn;
2401 return S_OK;
2404 /******************************************************************************
2405 * VarI2FromStr [OLEAUT32.54]
2407 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2409 double dValue = 0.0;
2410 LPSTR pNewString = NULL;
2412 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2414 /* Check if we have a valid argument
2416 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2417 RemoveCharacterFromString( pNewString, "," );
2418 if( IsValidRealString( pNewString ) == FALSE )
2420 return DISP_E_TYPEMISMATCH;
2423 /* Convert the valid string to a floating point number.
2425 dValue = atof( pNewString );
2427 /* We don't need the string anymore so free it.
2429 HeapFree( GetProcessHeap(), 0, pNewString );
2431 /* Check range of value.
2433 dValue = round( dValue );
2434 if( dValue < I2_MIN || dValue > I2_MAX )
2436 return DISP_E_OVERFLOW;
2439 *psOut = (short) dValue;
2441 return S_OK;
2444 /**********************************************************************
2445 * VarI2FromCy [OLEAUT32.52]
2446 * Convert currency to signed short
2448 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2449 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2451 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2453 *psOut = (SHORT)t;
2454 return S_OK;
2457 /******************************************************************************
2458 * VarI4FromUI1 [OLEAUT32.58]
2460 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2462 TRACE("( %X, %p ), stub\n", bIn, plOut );
2464 *plOut = (LONG) bIn;
2466 return S_OK;
2470 /******************************************************************************
2471 * VarI4FromR4 [OLEAUT32.60]
2473 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2475 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2477 /* Check range of value.
2479 fltIn = round( fltIn );
2480 if( fltIn < I4_MIN || fltIn > I4_MAX )
2482 return DISP_E_OVERFLOW;
2485 *plOut = (LONG) fltIn;
2487 return S_OK;
2490 /******************************************************************************
2491 * VarI4FromR8 [OLEAUT32.61]
2493 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2495 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2497 /* Check range of value.
2499 dblIn = round( dblIn );
2500 if( dblIn < I4_MIN || dblIn > I4_MAX )
2502 return DISP_E_OVERFLOW;
2505 *plOut = (LONG) dblIn;
2507 return S_OK;
2510 /******************************************************************************
2511 * VarI4FromDate [OLEAUT32.63]
2513 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2515 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2517 /* Check range of value.
2519 dateIn = round( dateIn );
2520 if( dateIn < I4_MIN || dateIn > I4_MAX )
2522 return DISP_E_OVERFLOW;
2525 *plOut = (LONG) dateIn;
2527 return S_OK;
2530 /******************************************************************************
2531 * VarI4FromBool [OLEAUT32.66]
2533 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2535 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2537 *plOut = (LONG) boolIn;
2539 return S_OK;
2542 /******************************************************************************
2543 * VarI4FromI1 [OLEAUT32.209]
2545 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2547 TRACE("( %c, %p ), stub\n", cIn, plOut );
2549 *plOut = (LONG) cIn;
2551 return S_OK;
2554 /******************************************************************************
2555 * VarI4FromUI2 [OLEAUT32.210]
2557 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2559 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2561 *plOut = (LONG) uiIn;
2563 return S_OK;
2566 /******************************************************************************
2567 * VarI4FromUI4 [OLEAUT32.211]
2569 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2571 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2573 /* Check range of value.
2575 if( ulIn < I4_MIN || ulIn > I4_MAX )
2577 return DISP_E_OVERFLOW;
2580 *plOut = (LONG) ulIn;
2582 return S_OK;
2585 /******************************************************************************
2586 * VarI4FromI2 [OLEAUT32.59]
2588 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2590 TRACE("( %d, %p ), stub\n", sIn, plOut );
2592 *plOut = (LONG) sIn;
2594 return S_OK;
2597 /******************************************************************************
2598 * VarI4FromStr [OLEAUT32.64]
2600 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2602 double dValue = 0.0;
2603 LPSTR pNewString = NULL;
2605 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2607 /* Check if we have a valid argument
2609 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2610 RemoveCharacterFromString( pNewString, "," );
2611 if( IsValidRealString( pNewString ) == FALSE )
2613 return DISP_E_TYPEMISMATCH;
2616 /* Convert the valid string to a floating point number.
2618 dValue = atof( pNewString );
2620 /* We don't need the string anymore so free it.
2622 HeapFree( GetProcessHeap(), 0, pNewString );
2624 /* Check range of value.
2626 dValue = round( dValue );
2627 if( dValue < I4_MIN || dValue > I4_MAX )
2629 return DISP_E_OVERFLOW;
2632 *plOut = (LONG) dValue;
2634 return S_OK;
2637 /**********************************************************************
2638 * VarI4FromCy [OLEAUT32.62]
2639 * Convert currency to signed long
2641 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2642 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2644 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2646 *plOut = (LONG)t;
2647 return S_OK;
2650 /******************************************************************************
2651 * VarR4FromUI1 [OLEAUT32.68]
2653 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2655 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2657 *pfltOut = (FLOAT) bIn;
2659 return S_OK;
2662 /******************************************************************************
2663 * VarR4FromI2 [OLEAUT32.69]
2665 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2667 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2669 *pfltOut = (FLOAT) sIn;
2671 return S_OK;
2674 /******************************************************************************
2675 * VarR4FromI4 [OLEAUT32.70]
2677 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2679 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2681 *pfltOut = (FLOAT) lIn;
2683 return S_OK;
2686 /******************************************************************************
2687 * VarR4FromR8 [OLEAUT32.71]
2689 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2691 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2693 /* Check range of value.
2695 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2697 return DISP_E_OVERFLOW;
2700 *pfltOut = (FLOAT) dblIn;
2702 return S_OK;
2705 /******************************************************************************
2706 * VarR4FromDate [OLEAUT32.73]
2708 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2710 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2712 /* Check range of value.
2714 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2716 return DISP_E_OVERFLOW;
2719 *pfltOut = (FLOAT) dateIn;
2721 return S_OK;
2724 /******************************************************************************
2725 * VarR4FromBool [OLEAUT32.76]
2727 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2729 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2731 *pfltOut = (FLOAT) boolIn;
2733 return S_OK;
2736 /******************************************************************************
2737 * VarR4FromI1 [OLEAUT32.213]
2739 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2741 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2743 *pfltOut = (FLOAT) cIn;
2745 return S_OK;
2748 /******************************************************************************
2749 * VarR4FromUI2 [OLEAUT32.214]
2751 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2753 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2755 *pfltOut = (FLOAT) uiIn;
2757 return S_OK;
2760 /******************************************************************************
2761 * VarR4FromUI4 [OLEAUT32.215]
2763 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2765 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2767 *pfltOut = (FLOAT) ulIn;
2769 return S_OK;
2772 /******************************************************************************
2773 * VarR4FromStr [OLEAUT32.74]
2775 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2777 double dValue = 0.0;
2778 LPSTR pNewString = NULL;
2780 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2782 /* Check if we have a valid argument
2784 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2785 RemoveCharacterFromString( pNewString, "," );
2786 if( IsValidRealString( pNewString ) == FALSE )
2788 return DISP_E_TYPEMISMATCH;
2791 /* Convert the valid string to a floating point number.
2793 dValue = atof( pNewString );
2795 /* We don't need the string anymore so free it.
2797 HeapFree( GetProcessHeap(), 0, pNewString );
2799 /* Check range of value.
2801 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2803 return DISP_E_OVERFLOW;
2806 *pfltOut = (FLOAT) dValue;
2808 return S_OK;
2811 /**********************************************************************
2812 * VarR4FromCy [OLEAUT32.72]
2813 * Convert currency to float
2815 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2816 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2818 return S_OK;
2821 /******************************************************************************
2822 * VarR8FromUI1 [OLEAUT32.68]
2824 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2826 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2828 *pdblOut = (double) bIn;
2830 return S_OK;
2833 /******************************************************************************
2834 * VarR8FromI2 [OLEAUT32.69]
2836 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2838 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2840 *pdblOut = (double) sIn;
2842 return S_OK;
2845 /******************************************************************************
2846 * VarR8FromI4 [OLEAUT32.70]
2848 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2850 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2852 *pdblOut = (double) lIn;
2854 return S_OK;
2857 /******************************************************************************
2858 * VarR8FromR4 [OLEAUT32.81]
2860 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2862 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2864 *pdblOut = (double) fltIn;
2866 return S_OK;
2869 /******************************************************************************
2870 * VarR8FromDate [OLEAUT32.83]
2872 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2874 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2876 *pdblOut = (double) dateIn;
2878 return S_OK;
2881 /******************************************************************************
2882 * VarR8FromBool [OLEAUT32.86]
2884 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2886 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2888 *pdblOut = (double) boolIn;
2890 return S_OK;
2893 /******************************************************************************
2894 * VarR8FromI1 [OLEAUT32.217]
2896 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2898 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2900 *pdblOut = (double) cIn;
2902 return S_OK;
2905 /******************************************************************************
2906 * VarR8FromUI2 [OLEAUT32.218]
2908 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2910 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2912 *pdblOut = (double) uiIn;
2914 return S_OK;
2917 /******************************************************************************
2918 * VarR8FromUI4 [OLEAUT32.219]
2920 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2922 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2924 *pdblOut = (double) ulIn;
2926 return S_OK;
2929 /******************************************************************************
2930 * VarR8FromStr [OLEAUT32.84]
2932 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2934 double dValue = 0.0;
2935 LPSTR pNewString = NULL;
2937 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2939 /* Check if we have a valid argument
2941 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2942 RemoveCharacterFromString( pNewString, "," );
2943 if( IsValidRealString( pNewString ) == FALSE )
2945 return DISP_E_TYPEMISMATCH;
2948 /* Convert the valid string to a floating point number.
2950 dValue = atof( pNewString );
2952 /* We don't need the string anymore so free it.
2954 HeapFree( GetProcessHeap(), 0, pNewString );
2956 *pdblOut = dValue;
2958 return S_OK;
2961 /**********************************************************************
2962 * VarR8FromCy [OLEAUT32.82]
2963 * Convert currency to double
2965 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2966 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2968 return S_OK;
2971 /******************************************************************************
2972 * VarDateFromUI1 [OLEAUT32.]
2974 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2976 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2978 *pdateOut = (DATE) bIn;
2980 return S_OK;
2983 /******************************************************************************
2984 * VarDateFromI2 [OLEAUT32.222]
2986 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2988 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2990 *pdateOut = (DATE) sIn;
2992 return S_OK;
2995 /******************************************************************************
2996 * VarDateFromI4 [OLEAUT32.90]
2998 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
3000 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
3002 if( lIn < DATE_MIN || lIn > DATE_MAX )
3004 return DISP_E_OVERFLOW;
3007 *pdateOut = (DATE) lIn;
3009 return S_OK;
3012 /******************************************************************************
3013 * VarDateFromR4 [OLEAUT32.91]
3015 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3017 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3019 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3021 return DISP_E_OVERFLOW;
3024 *pdateOut = (DATE) fltIn;
3026 return S_OK;
3029 /******************************************************************************
3030 * VarDateFromR8 [OLEAUT32.92]
3032 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3034 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3036 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3038 return DISP_E_OVERFLOW;
3041 *pdateOut = (DATE) dblIn;
3043 return S_OK;
3046 /******************************************************************************
3047 * VarDateFromStr [OLEAUT32.94]
3048 * The string representing the date is composed of two parts, a date and time.
3050 * The format of the time is has follows:
3051 * hh[:mm][:ss][AM|PM]
3052 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3053 * of space and/or tab characters, which are ignored.
3055 * The formats for the date part are has follows:
3056 * mm/[dd/][yy]yy
3057 * [dd/]mm/[yy]yy
3058 * [yy]yy/mm/dd
3059 * January dd[,] [yy]yy
3060 * dd January [yy]yy
3061 * [yy]yy January dd
3062 * Whitespace can be inserted anywhere between these tokens.
3064 * The formats for the date and time string are has follows.
3065 * date[whitespace][time]
3066 * [time][whitespace]date
3068 * These are the only characters allowed in a string representing a date and time:
3069 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3071 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3073 HRESULT ret = S_OK;
3074 struct tm TM = { 0,0,0,0,0,0,0,0,0 };
3076 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3078 if( DateTimeStringToTm( strIn, lcid, &TM ) )
3080 if( TmToDATE( &TM, pdateOut ) == FALSE )
3082 ret = E_INVALIDARG;
3085 else
3087 ret = DISP_E_TYPEMISMATCH;
3091 return ret;
3094 /******************************************************************************
3095 * VarDateFromI1 [OLEAUT32.221]
3097 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3099 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3101 *pdateOut = (DATE) cIn;
3103 return S_OK;
3106 /******************************************************************************
3107 * VarDateFromUI2 [OLEAUT32.222]
3109 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3111 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3113 if( uiIn > DATE_MAX )
3115 return DISP_E_OVERFLOW;
3118 *pdateOut = (DATE) uiIn;
3120 return S_OK;
3123 /******************************************************************************
3124 * VarDateFromUI4 [OLEAUT32.223]
3126 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3128 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3130 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3132 return DISP_E_OVERFLOW;
3135 *pdateOut = (DATE) ulIn;
3137 return S_OK;
3140 /******************************************************************************
3141 * VarDateFromBool [OLEAUT32.96]
3143 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3145 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3147 *pdateOut = (DATE) boolIn;
3149 return S_OK;
3152 /**********************************************************************
3153 * VarDateFromCy [OLEAUT32.93]
3154 * Convert currency to date
3156 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3157 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3159 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3160 return S_OK;
3163 /******************************************************************************
3164 * VarBstrFromUI1 [OLEAUT32.108]
3166 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3168 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3169 sprintf( pBuffer, "%d", bVal );
3171 *pbstrOut = StringDupAtoBstr( pBuffer );
3173 return S_OK;
3176 /******************************************************************************
3177 * VarBstrFromI2 [OLEAUT32.109]
3179 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3181 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3182 sprintf( pBuffer, "%d", iVal );
3183 *pbstrOut = StringDupAtoBstr( pBuffer );
3185 return S_OK;
3188 /******************************************************************************
3189 * VarBstrFromI4 [OLEAUT32.110]
3191 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3193 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3195 sprintf( pBuffer, "%ld", lIn );
3196 *pbstrOut = StringDupAtoBstr( pBuffer );
3198 return S_OK;
3201 /******************************************************************************
3202 * VarBstrFromR4 [OLEAUT32.111]
3204 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3206 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3208 sprintf( pBuffer, "%.7g", fltIn );
3209 *pbstrOut = StringDupAtoBstr( pBuffer );
3211 return S_OK;
3214 /******************************************************************************
3215 * VarBstrFromR8 [OLEAUT32.112]
3217 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3219 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3221 sprintf( pBuffer, "%.15g", dblIn );
3222 *pbstrOut = StringDupAtoBstr( pBuffer );
3224 return S_OK;
3227 /******************************************************************************
3228 * VarBstrFromCy [OLEAUT32.113]
3230 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3231 /* FIXME */
3232 return E_NOTIMPL;
3236 /******************************************************************************
3237 * VarBstrFromDate [OLEAUT32.114]
3239 * The date is implemented using an 8 byte floating-point number.
3240 * Days are represented by whole numbers increments starting with 0.00 has
3241 * being December 30 1899, midnight.
3242 * The hours are expressed as the fractional part of the number.
3243 * December 30 1899 at midnight = 0.00
3244 * January 1 1900 at midnight = 2.00
3245 * January 4 1900 at 6 AM = 5.25
3246 * January 4 1900 at noon = 5.50
3247 * December 29 1899 at midnight = -1.00
3248 * December 18 1899 at midnight = -12.00
3249 * December 18 1899 at 6AM = -12.25
3250 * December 18 1899 at 6PM = -12.75
3251 * December 19 1899 at midnight = -11.00
3252 * The tm structure is as follows:
3253 * struct tm {
3254 * int tm_sec; seconds after the minute - [0,59]
3255 * int tm_min; minutes after the hour - [0,59]
3256 * int tm_hour; hours since midnight - [0,23]
3257 * int tm_mday; day of the month - [1,31]
3258 * int tm_mon; months since January - [0,11]
3259 * int tm_year; years
3260 * int tm_wday; days since Sunday - [0,6]
3261 * int tm_yday; days since January 1 - [0,365]
3262 * int tm_isdst; daylight savings time flag
3263 * };
3265 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3267 struct tm TM = {0,0,0,0,0,0,0,0,0};
3269 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3271 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3273 return E_INVALIDARG;
3276 if( dwFlags & VAR_DATEVALUEONLY )
3277 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3278 else if( dwFlags & VAR_TIMEVALUEONLY )
3279 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3280 else
3281 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3283 *pbstrOut = StringDupAtoBstr( pBuffer );
3285 return S_OK;
3288 /******************************************************************************
3289 * VarBstrFromBool [OLEAUT32.116]
3291 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3293 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3295 if( boolIn == VARIANT_FALSE )
3297 sprintf( pBuffer, "False" );
3299 else
3301 sprintf( pBuffer, "True" );
3304 *pbstrOut = StringDupAtoBstr( pBuffer );
3306 return S_OK;
3309 /******************************************************************************
3310 * VarBstrFromI1 [OLEAUT32.229]
3312 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3314 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3315 sprintf( pBuffer, "%d", cIn );
3316 *pbstrOut = StringDupAtoBstr( pBuffer );
3318 return S_OK;
3321 /******************************************************************************
3322 * VarBstrFromUI2 [OLEAUT32.230]
3324 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3326 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3327 sprintf( pBuffer, "%d", uiIn );
3328 *pbstrOut = StringDupAtoBstr( pBuffer );
3330 return S_OK;
3333 /******************************************************************************
3334 * VarBstrFromUI4 [OLEAUT32.231]
3336 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3338 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3339 sprintf( pBuffer, "%ld", ulIn );
3340 *pbstrOut = StringDupAtoBstr( pBuffer );
3342 return S_OK;
3345 /******************************************************************************
3346 * VarBoolFromUI1 [OLEAUT32.118]
3348 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3350 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3352 if( bIn == 0 )
3354 *pboolOut = VARIANT_FALSE;
3356 else
3358 *pboolOut = VARIANT_TRUE;
3361 return S_OK;
3364 /******************************************************************************
3365 * VarBoolFromI2 [OLEAUT32.119]
3367 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3369 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3371 if( sIn == 0 )
3373 *pboolOut = VARIANT_FALSE;
3375 else
3377 *pboolOut = VARIANT_TRUE;
3380 return S_OK;
3383 /******************************************************************************
3384 * VarBoolFromI4 [OLEAUT32.120]
3386 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3388 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3390 if( lIn == 0 )
3392 *pboolOut = VARIANT_FALSE;
3394 else
3396 *pboolOut = VARIANT_TRUE;
3399 return S_OK;
3402 /******************************************************************************
3403 * VarBoolFromR4 [OLEAUT32.121]
3405 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3407 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3409 if( fltIn == 0.0 )
3411 *pboolOut = VARIANT_FALSE;
3413 else
3415 *pboolOut = VARIANT_TRUE;
3418 return S_OK;
3421 /******************************************************************************
3422 * VarBoolFromR8 [OLEAUT32.122]
3424 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3426 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3428 if( dblIn == 0.0 )
3430 *pboolOut = VARIANT_FALSE;
3432 else
3434 *pboolOut = VARIANT_TRUE;
3437 return S_OK;
3440 /******************************************************************************
3441 * VarBoolFromDate [OLEAUT32.123]
3443 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3445 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3447 if( dateIn == 0.0 )
3449 *pboolOut = VARIANT_FALSE;
3451 else
3453 *pboolOut = VARIANT_TRUE;
3456 return S_OK;
3459 /******************************************************************************
3460 * VarBoolFromStr [OLEAUT32.125]
3462 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3464 HRESULT ret = S_OK;
3465 char* pNewString = NULL;
3467 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3469 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3471 if( pNewString == NULL || strlen( pNewString ) == 0 )
3473 ret = DISP_E_TYPEMISMATCH;
3476 if( ret == S_OK )
3478 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3480 *pboolOut = VARIANT_TRUE;
3482 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3484 *pboolOut = VARIANT_FALSE;
3486 else
3488 /* Try converting the string to a floating point number.
3490 double dValue = 0.0;
3491 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3492 if( res != S_OK )
3494 ret = DISP_E_TYPEMISMATCH;
3496 else if( dValue == 0.0 )
3498 *pboolOut = VARIANT_FALSE;
3500 else
3502 *pboolOut = VARIANT_TRUE;
3507 HeapFree( GetProcessHeap(), 0, pNewString );
3509 return ret;
3512 /******************************************************************************
3513 * VarBoolFromI1 [OLEAUT32.233]
3515 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3517 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3519 if( cIn == 0 )
3521 *pboolOut = VARIANT_FALSE;
3523 else
3525 *pboolOut = VARIANT_TRUE;
3528 return S_OK;
3531 /******************************************************************************
3532 * VarBoolFromUI2 [OLEAUT32.234]
3534 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3536 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3538 if( uiIn == 0 )
3540 *pboolOut = VARIANT_FALSE;
3542 else
3544 *pboolOut = VARIANT_TRUE;
3547 return S_OK;
3550 /******************************************************************************
3551 * VarBoolFromUI4 [OLEAUT32.235]
3553 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3555 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3557 if( ulIn == 0 )
3559 *pboolOut = VARIANT_FALSE;
3561 else
3563 *pboolOut = VARIANT_TRUE;
3566 return S_OK;
3569 /**********************************************************************
3570 * VarBoolFromCy [OLEAUT32.124]
3571 * Convert currency to boolean
3573 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3574 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3575 else *pboolOut = 0;
3577 return S_OK;
3580 /******************************************************************************
3581 * VarI1FromUI1 [OLEAUT32.244]
3583 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3585 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3587 /* Check range of value.
3589 if( bIn > CHAR_MAX )
3591 return DISP_E_OVERFLOW;
3594 *pcOut = (CHAR) bIn;
3596 return S_OK;
3599 /******************************************************************************
3600 * VarI1FromI2 [OLEAUT32.245]
3602 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3604 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3606 if( uiIn > CHAR_MAX )
3608 return DISP_E_OVERFLOW;
3611 *pcOut = (CHAR) uiIn;
3613 return S_OK;
3616 /******************************************************************************
3617 * VarI1FromI4 [OLEAUT32.246]
3619 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3621 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3623 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3625 return DISP_E_OVERFLOW;
3628 *pcOut = (CHAR) lIn;
3630 return S_OK;
3633 /******************************************************************************
3634 * VarI1FromR4 [OLEAUT32.247]
3636 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3638 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3640 fltIn = round( fltIn );
3641 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3643 return DISP_E_OVERFLOW;
3646 *pcOut = (CHAR) fltIn;
3648 return S_OK;
3651 /******************************************************************************
3652 * VarI1FromR8 [OLEAUT32.248]
3654 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3656 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3658 dblIn = round( dblIn );
3659 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3661 return DISP_E_OVERFLOW;
3664 *pcOut = (CHAR) dblIn;
3666 return S_OK;
3669 /******************************************************************************
3670 * VarI1FromDate [OLEAUT32.249]
3672 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3674 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3676 dateIn = round( dateIn );
3677 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3679 return DISP_E_OVERFLOW;
3682 *pcOut = (CHAR) dateIn;
3684 return S_OK;
3687 /******************************************************************************
3688 * VarI1FromStr [OLEAUT32.251]
3690 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3692 double dValue = 0.0;
3693 LPSTR pNewString = NULL;
3695 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3697 /* Check if we have a valid argument
3699 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3700 RemoveCharacterFromString( pNewString, "," );
3701 if( IsValidRealString( pNewString ) == FALSE )
3703 return DISP_E_TYPEMISMATCH;
3706 /* Convert the valid string to a floating point number.
3708 dValue = atof( pNewString );
3710 /* We don't need the string anymore so free it.
3712 HeapFree( GetProcessHeap(), 0, pNewString );
3714 /* Check range of value.
3716 dValue = round( dValue );
3717 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3719 return DISP_E_OVERFLOW;
3722 *pcOut = (CHAR) dValue;
3724 return S_OK;
3727 /******************************************************************************
3728 * VarI1FromBool [OLEAUT32.253]
3730 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3732 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3734 *pcOut = (CHAR) boolIn;
3736 return S_OK;
3739 /******************************************************************************
3740 * VarI1FromUI2 [OLEAUT32.254]
3742 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3744 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3746 if( uiIn > CHAR_MAX )
3748 return DISP_E_OVERFLOW;
3751 *pcOut = (CHAR) uiIn;
3753 return S_OK;
3756 /******************************************************************************
3757 * VarI1FromUI4 [OLEAUT32.255]
3759 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3761 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3763 if( ulIn > CHAR_MAX )
3765 return DISP_E_OVERFLOW;
3768 *pcOut = (CHAR) ulIn;
3770 return S_OK;
3773 /**********************************************************************
3774 * VarI1FromCy [OLEAUT32.250]
3775 * Convert currency to signed char
3777 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3778 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3780 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3782 *pcOut = (CHAR)t;
3783 return S_OK;
3786 /******************************************************************************
3787 * VarUI2FromUI1 [OLEAUT32.257]
3789 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3791 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3793 *puiOut = (USHORT) bIn;
3795 return S_OK;
3798 /******************************************************************************
3799 * VarUI2FromI2 [OLEAUT32.258]
3801 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3803 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3805 if( uiIn < UI2_MIN )
3807 return DISP_E_OVERFLOW;
3810 *puiOut = (USHORT) uiIn;
3812 return S_OK;
3815 /******************************************************************************
3816 * VarUI2FromI4 [OLEAUT32.259]
3818 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3820 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3822 if( lIn < UI2_MIN || lIn > UI2_MAX )
3824 return DISP_E_OVERFLOW;
3827 *puiOut = (USHORT) lIn;
3829 return S_OK;
3832 /******************************************************************************
3833 * VarUI2FromR4 [OLEAUT32.260]
3835 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3837 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3839 fltIn = round( fltIn );
3840 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3842 return DISP_E_OVERFLOW;
3845 *puiOut = (USHORT) fltIn;
3847 return S_OK;
3850 /******************************************************************************
3851 * VarUI2FromR8 [OLEAUT32.261]
3853 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3855 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3857 dblIn = round( dblIn );
3858 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3860 return DISP_E_OVERFLOW;
3863 *puiOut = (USHORT) dblIn;
3865 return S_OK;
3868 /******************************************************************************
3869 * VarUI2FromDate [OLEAUT32.262]
3871 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3873 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3875 dateIn = round( dateIn );
3876 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3878 return DISP_E_OVERFLOW;
3881 *puiOut = (USHORT) dateIn;
3883 return S_OK;
3886 /******************************************************************************
3887 * VarUI2FromStr [OLEAUT32.264]
3889 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3891 double dValue = 0.0;
3892 LPSTR pNewString = NULL;
3894 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3896 /* Check if we have a valid argument
3898 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3899 RemoveCharacterFromString( pNewString, "," );
3900 if( IsValidRealString( pNewString ) == FALSE )
3902 return DISP_E_TYPEMISMATCH;
3905 /* Convert the valid string to a floating point number.
3907 dValue = atof( pNewString );
3909 /* We don't need the string anymore so free it.
3911 HeapFree( GetProcessHeap(), 0, pNewString );
3913 /* Check range of value.
3915 dValue = round( dValue );
3916 if( dValue < UI2_MIN || dValue > UI2_MAX )
3918 return DISP_E_OVERFLOW;
3921 *puiOut = (USHORT) dValue;
3923 return S_OK;
3926 /******************************************************************************
3927 * VarUI2FromBool [OLEAUT32.266]
3929 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3931 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3933 *puiOut = (USHORT) boolIn;
3935 return S_OK;
3938 /******************************************************************************
3939 * VarUI2FromI1 [OLEAUT32.267]
3941 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3943 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3945 *puiOut = (USHORT) cIn;
3947 return S_OK;
3950 /******************************************************************************
3951 * VarUI2FromUI4 [OLEAUT32.268]
3953 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3955 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3957 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3959 return DISP_E_OVERFLOW;
3962 *puiOut = (USHORT) ulIn;
3964 return S_OK;
3967 /******************************************************************************
3968 * VarUI4FromStr [OLEAUT32.277]
3970 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3972 double dValue = 0.0;
3973 LPSTR pNewString = NULL;
3975 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3977 /* Check if we have a valid argument
3979 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3980 RemoveCharacterFromString( pNewString, "," );
3981 if( IsValidRealString( pNewString ) == FALSE )
3983 return DISP_E_TYPEMISMATCH;
3986 /* Convert the valid string to a floating point number.
3988 dValue = atof( pNewString );
3990 /* We don't need the string anymore so free it.
3992 HeapFree( GetProcessHeap(), 0, pNewString );
3994 /* Check range of value.
3996 dValue = round( dValue );
3997 if( dValue < UI4_MIN || dValue > UI4_MAX )
3999 return DISP_E_OVERFLOW;
4002 *pulOut = (ULONG) dValue;
4004 return S_OK;
4007 /**********************************************************************
4008 * VarUI2FromCy [OLEAUT32.263]
4009 * Convert currency to unsigned short
4011 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4012 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4014 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4016 *pusOut = (USHORT)t;
4018 return S_OK;
4021 /******************************************************************************
4022 * VarUI4FromUI1 [OLEAUT32.270]
4024 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4026 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4028 *pulOut = (USHORT) bIn;
4030 return S_OK;
4033 /******************************************************************************
4034 * VarUI4FromI2 [OLEAUT32.271]
4036 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4038 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4040 if( uiIn < UI4_MIN )
4042 return DISP_E_OVERFLOW;
4045 *pulOut = (ULONG) uiIn;
4047 return S_OK;
4050 /******************************************************************************
4051 * VarUI4FromI4 [OLEAUT32.272]
4053 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4055 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4057 if( lIn < UI4_MIN )
4059 return DISP_E_OVERFLOW;
4062 *pulOut = (ULONG) lIn;
4064 return S_OK;
4067 /******************************************************************************
4068 * VarUI4FromR4 [OLEAUT32.273]
4070 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4072 fltIn = round( fltIn );
4073 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4075 return DISP_E_OVERFLOW;
4078 *pulOut = (ULONG) fltIn;
4080 return S_OK;
4083 /******************************************************************************
4084 * VarUI4FromR8 [OLEAUT32.274]
4086 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4088 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4090 dblIn = round( dblIn );
4091 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4093 return DISP_E_OVERFLOW;
4096 *pulOut = (ULONG) dblIn;
4098 return S_OK;
4101 /******************************************************************************
4102 * VarUI4FromDate [OLEAUT32.275]
4104 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4106 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4108 dateIn = round( dateIn );
4109 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4111 return DISP_E_OVERFLOW;
4114 *pulOut = (ULONG) dateIn;
4116 return S_OK;
4119 /******************************************************************************
4120 * VarUI4FromBool [OLEAUT32.279]
4122 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4124 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4126 *pulOut = (ULONG) boolIn;
4128 return S_OK;
4131 /******************************************************************************
4132 * VarUI4FromI1 [OLEAUT32.280]
4134 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4136 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4138 *pulOut = (ULONG) cIn;
4140 return S_OK;
4143 /******************************************************************************
4144 * VarUI4FromUI2 [OLEAUT32.281]
4146 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4148 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4150 *pulOut = (ULONG) uiIn;
4152 return S_OK;
4155 /**********************************************************************
4156 * VarUI4FromCy [OLEAUT32.276]
4157 * Convert currency to unsigned long
4159 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4160 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4162 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4164 *pulOut = (ULONG)t;
4166 return S_OK;
4169 /**********************************************************************
4170 * VarCyFromUI1 [OLEAUT32.98]
4171 * Convert unsigned char to currency
4173 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4174 pcyOut->s.Hi = 0;
4175 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4177 return S_OK;
4180 /**********************************************************************
4181 * VarCyFromI2 [OLEAUT32.99]
4182 * Convert signed short to currency
4184 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4185 if (sIn < 0) pcyOut->s.Hi = -1;
4186 else pcyOut->s.Hi = 0;
4187 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4189 return S_OK;
4192 /**********************************************************************
4193 * VarCyFromI4 [OLEAUT32.100]
4194 * Convert signed long to currency
4196 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4197 double t = (double)lIn * (double)10000;
4198 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4199 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4200 if (lIn < 0) pcyOut->s.Hi--;
4202 return S_OK;
4205 /**********************************************************************
4206 * VarCyFromR4 [OLEAUT32.101]
4207 * Convert float to currency
4209 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4210 double t = round((double)fltIn * (double)10000);
4211 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4212 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4213 if (fltIn < 0) pcyOut->s.Hi--;
4215 return S_OK;
4218 /**********************************************************************
4219 * VarCyFromR8 [OLEAUT32.102]
4220 * Convert double to currency
4222 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4223 double t = round(dblIn * (double)10000);
4224 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4225 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4226 if (dblIn < 0) pcyOut->s.Hi--;
4228 return S_OK;
4231 /**********************************************************************
4232 * VarCyFromDate [OLEAUT32.103]
4233 * Convert date to currency
4235 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4236 double t = round((double)dateIn * (double)10000);
4237 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4238 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4239 if (dateIn < 0) pcyOut->s.Hi--;
4241 return S_OK;
4244 /**********************************************************************
4245 * VarCyFromStr [OLEAUT32.104]
4247 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4248 /* FIXME */
4249 return E_NOTIMPL;
4253 /**********************************************************************
4254 * VarCyFromBool [OLEAUT32.106]
4255 * Convert boolean to currency
4257 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4258 if (boolIn < 0) pcyOut->s.Hi = -1;
4259 else pcyOut->s.Hi = 0;
4260 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4262 return S_OK;
4265 /**********************************************************************
4266 * VarCyFromI1 [OLEAUT32.225]
4267 * Convert signed char to currency
4269 HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4270 if (cIn < 0) pcyOut->s.Hi = -1;
4271 else pcyOut->s.Hi = 0;
4272 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4274 return S_OK;
4277 /**********************************************************************
4278 * VarCyFromUI2 [OLEAUT32.226]
4279 * Convert unsigned short to currency
4281 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4282 pcyOut->s.Hi = 0;
4283 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4285 return S_OK;
4288 /**********************************************************************
4289 * VarCyFromUI4 [OLEAUT32.227]
4290 * Convert unsigned long to currency
4292 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4293 double t = (double)ulIn * (double)10000;
4294 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4295 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4297 return S_OK;
4301 /**********************************************************************
4302 * DosDateTimeToVariantTime [OLEAUT32.14]
4303 * Convert dos representation of time to the date and time representation
4304 * stored in a variant.
4306 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4307 DATE *pvtime)
4309 struct tm t;
4311 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4313 t.tm_sec = (wDosTime & 0x001f) * 2;
4314 t.tm_min = (wDosTime & 0x07e0) >> 5;
4315 t.tm_hour = (wDosTime & 0xf800) >> 11;
4317 t.tm_mday = (wDosDate & 0x001f);
4318 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4319 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4321 return TmToDATE( &t, pvtime );