Fixed ANSI C violations.
[wine/testsucceed.git] / dlls / oleaut32 / variant.c
blobaa749feef883c8f7db13eab960d0a24c803fd4d7
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.001
92 * One + every 400 years: 1/400 -> 365.0025
94 static const double DAYS_IN_ONE_YEAR = 365.2515;
98 /******************************************************************************
99 * DateTimeStringToTm [INTERNAL]
101 * Converts a string representation of a date and/or time to a tm structure.
103 * Note this function uses the postgresql date parsing functions found
104 * in the parsedt.c file.
106 * Returns TRUE if successfull.
108 * Note: This function does not parse the day of the week,
109 * daylight savings time. It will only fill the followin fields in
110 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
112 ******************************************************************************/
113 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
115 BOOL res = FALSE;
116 double fsec;
117 int tzp;
118 int dtype;
119 int nf;
120 char *field[MAXDATEFIELDS];
121 int ftype[MAXDATEFIELDS];
122 char lowstr[MAXDATELEN + 1];
123 char* strDateTime = NULL;
125 /* Convert the string to ASCII since this is the only format
126 * postgesql can handle.
128 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
130 if( strDateTime != NULL )
132 /* Make sure we don't go over the maximum length
133 * accepted by postgesql.
135 if( strlen( strDateTime ) <= MAXDATELEN )
137 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
139 if( lcid & VAR_DATEVALUEONLY )
141 /* Get the date information.
142 * It returns 0 if date information was
143 * present and 1 if only time information was present.
144 * -1 if an error occures.
146 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
148 /* Eliminate the time information since we
149 * were asked to get date information only.
151 pTm->tm_sec = 0;
152 pTm->tm_min = 0;
153 pTm->tm_hour = 0;
154 res = TRUE;
157 if( lcid & VAR_TIMEVALUEONLY )
159 /* Get time information only.
161 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
163 res = TRUE;
166 else
168 /* Get both date and time information.
169 * It returns 0 if date information was
170 * present and 1 if only time information was present.
171 * -1 if an error occures.
173 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
175 res = TRUE;
180 HeapFree( GetProcessHeap(), 0, strDateTime );
183 return res;
191 /******************************************************************************
192 * TmToDATE [INTERNAL]
194 * The date is implemented using an 8 byte floating-point number.
195 * Days are represented by whole numbers increments starting with 0.00 has
196 * being December 30 1899, midnight.
197 * The hours are expressed as the fractional part of the number.
198 * December 30 1899 at midnight = 0.00
199 * January 1 1900 at midnight = 2.00
200 * January 4 1900 at 6 AM = 5.25
201 * January 4 1900 at noon = 5.50
202 * December 29 1899 at midnight = -1.00
203 * December 18 1899 at midnight = -12.00
204 * December 18 1899 at 6AM = -12.25
205 * December 18 1899 at 6PM = -12.75
206 * December 19 1899 at midnight = -11.00
207 * The tm structure is as follows:
208 * struct tm {
209 * int tm_sec; seconds after the minute - [0,59]
210 * int tm_min; minutes after the hour - [0,59]
211 * int tm_hour; hours since midnight - [0,23]
212 * int tm_mday; day of the month - [1,31]
213 * int tm_mon; months since January - [0,11]
214 * int tm_year; years
215 * int tm_wday; days since Sunday - [0,6]
216 * int tm_yday; days since January 1 - [0,365]
217 * int tm_isdst; daylight savings time flag
218 * };
220 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
221 * and tm_isdst fields of the tm structure. And only converts years
222 * after 1900.
224 * Returns TRUE if successfull.
226 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
228 if( (pTm->tm_year - 1900) >= 0 )
230 int leapYear = 0;
232 /* Start at 1. This is the way DATE is defined.
233 * January 1, 1900 at Midnight is 1.00.
234 * January 1, 1900 at 6AM is 1.25.
235 * and so on.
237 *pDateOut = 1;
239 /* Add the number of days corresponding to
240 * tm_year.
242 *pDateOut += (pTm->tm_year - 1900) * 365;
244 /* Add the leap days in the previous years between now and 1900.
245 * Note a leap year is one that is a multiple of 4
246 * but not of a 100. Except if it is a multiple of
247 * 400 then it is a leap year.
249 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
250 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
251 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
253 /* Set the leap year flag if the
254 * current year specified by tm_year is a
255 * leap year. This will be used to add a day
256 * to the day count.
258 if( isleap( pTm->tm_year ) )
259 leapYear = 1;
261 /* Add the number of days corresponding to
262 * the month.
264 switch( pTm->tm_mon )
266 case 2:
267 *pDateOut += 31;
268 break;
269 case 3:
270 *pDateOut += ( 59 + leapYear );
271 break;
272 case 4:
273 *pDateOut += ( 90 + leapYear );
274 break;
275 case 5:
276 *pDateOut += ( 120 + leapYear );
277 break;
278 case 6:
279 *pDateOut += ( 151 + leapYear );
280 break;
281 case 7:
282 *pDateOut += ( 181 + leapYear );
283 break;
284 case 8:
285 *pDateOut += ( 212 + leapYear );
286 break;
287 case 9:
288 *pDateOut += ( 243 + leapYear );
289 break;
290 case 10:
291 *pDateOut += ( 273 + leapYear );
292 break;
293 case 11:
294 *pDateOut += ( 304 + leapYear );
295 break;
296 case 12:
297 *pDateOut += ( 334 + leapYear );
298 break;
300 /* Add the number of days in this month.
302 *pDateOut += pTm->tm_mday;
304 /* Add the number of seconds, minutes, and hours
305 * to the DATE. Note these are the fracionnal part
306 * of the DATE so seconds / number of seconds in a day.
308 *pDateOut += pTm->tm_hour / 24.0;
309 *pDateOut += pTm->tm_min / 1440.0;
310 *pDateOut += pTm->tm_sec / 86400.0;
311 return TRUE;
313 return FALSE;
316 /******************************************************************************
317 * DateToTm [INTERNAL]
319 * This function converst a windows DATE to a tm structure.
321 * It does not fill all the fields of the tm structure.
322 * Here is a list of the fields that are filled:
323 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
325 * Note this function does not support dates before the January 1, 1900
326 * or ( dateIn < 2.0 ).
328 * Returns TRUE if successfull.
330 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
332 /* Do not process dates smaller than January 1, 1900.
333 * Which corresponds to 2.0 in the windows DATE format.
335 if( dateIn >= 2.0 )
337 double decimalPart = 0.0;
338 double wholePart = 0.0;
340 memset(pTm,0,sizeof(*pTm));
342 /* Because of the nature of DATE format witch
343 * associates 2.0 to January 1, 1900. We will
344 * remove 1.0 from the whole part of the DATE
345 * so that in the following code 1.0
346 * will correspond to January 1, 1900.
347 * This simplyfies the processing of the DATE value.
349 dateIn -= 1.0;
351 wholePart = (double) floor( dateIn );
352 decimalPart = fmod( dateIn, wholePart );
354 if( !(lcid & VAR_TIMEVALUEONLY) )
356 int nDay = 0;
357 int leapYear = 0;
358 double yearsSince1900 = 0;
359 /* Start at 1900, this where the DATE time 0.0 starts.
361 pTm->tm_year = 1900;
362 /* find in what year the day in the "wholePart" falls into.
363 * add the value to the year field.
365 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
366 pTm->tm_year += yearsSince1900;
367 /* determine if this is a leap year.
369 if( isleap( pTm->tm_year ) )
371 leapYear = 1;
372 wholePart++;
375 /* find what day of that year does the "wholePart" corresponds to.
376 * Note: nDay is in [1-366] format
378 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
379 /* Set the tm_yday value.
380 * Note: The day is must be converted from [1-366] to [0-365]
382 /*pTm->tm_yday = nDay - 1;*/
383 /* find which mount this day corresponds to.
385 if( nDay <= 31 )
387 pTm->tm_mday = nDay;
388 pTm->tm_mon = 0;
390 else if( nDay <= ( 59 + leapYear ) )
392 pTm->tm_mday = nDay - 31;
393 pTm->tm_mon = 1;
395 else if( nDay <= ( 90 + leapYear ) )
397 pTm->tm_mday = nDay - ( 59 + leapYear );
398 pTm->tm_mon = 2;
400 else if( nDay <= ( 120 + leapYear ) )
402 pTm->tm_mday = nDay - ( 90 + leapYear );
403 pTm->tm_mon = 3;
405 else if( nDay <= ( 151 + leapYear ) )
407 pTm->tm_mday = nDay - ( 120 + leapYear );
408 pTm->tm_mon = 4;
410 else if( nDay <= ( 181 + leapYear ) )
412 pTm->tm_mday = nDay - ( 151 + leapYear );
413 pTm->tm_mon = 5;
415 else if( nDay <= ( 212 + leapYear ) )
417 pTm->tm_mday = nDay - ( 181 + leapYear );
418 pTm->tm_mon = 6;
420 else if( nDay <= ( 243 + leapYear ) )
422 pTm->tm_mday = nDay - ( 212 + leapYear );
423 pTm->tm_mon = 7;
425 else if( nDay <= ( 273 + leapYear ) )
427 pTm->tm_mday = nDay - ( 243 + leapYear );
428 pTm->tm_mon = 8;
430 else if( nDay <= ( 304 + leapYear ) )
432 pTm->tm_mday = nDay - ( 273 + leapYear );
433 pTm->tm_mon = 9;
435 else if( nDay <= ( 334 + leapYear ) )
437 pTm->tm_mday = nDay - ( 304 + leapYear );
438 pTm->tm_mon = 10;
440 else if( nDay <= ( 365 + leapYear ) )
442 pTm->tm_mday = nDay - ( 334 + leapYear );
443 pTm->tm_mon = 11;
446 if( !(lcid & VAR_DATEVALUEONLY) )
448 /* find the number of seconds in this day.
449 * fractional part times, hours, minutes, seconds.
451 pTm->tm_hour = (int) ( decimalPart * 24 );
452 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
453 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
455 return TRUE;
457 return FALSE;
462 /******************************************************************************
463 * SizeOfVariantData [INTERNAL]
465 * This function finds the size of the data referenced by a Variant based
466 * the type "vt" of the Variant.
468 static int SizeOfVariantData( VARIANT* parg )
470 int size = 0;
471 switch( parg->vt & VT_TYPEMASK )
473 case( VT_I2 ):
474 size = sizeof(short);
475 break;
476 case( VT_INT ):
477 size = sizeof(int);
478 break;
479 case( VT_I4 ):
480 size = sizeof(long);
481 break;
482 case( VT_UI1 ):
483 size = sizeof(BYTE);
484 break;
485 case( VT_UI2 ):
486 size = sizeof(unsigned short);
487 break;
488 case( VT_UINT ):
489 size = sizeof(unsigned int);
490 break;
491 case( VT_UI4 ):
492 size = sizeof(unsigned long);
493 break;
494 case( VT_R4 ):
495 size = sizeof(float);
496 break;
497 case( VT_R8 ):
498 size = sizeof(double);
499 break;
500 case( VT_DATE ):
501 size = sizeof(DATE);
502 break;
503 case( VT_BOOL ):
504 size = sizeof(VARIANT_BOOL);
505 break;
506 case( VT_BSTR ):
507 size = sizeof(void*);
508 break;
509 case( VT_CY ):
510 case( VT_DISPATCH ):
511 case( VT_UNKNOWN ):
512 case( VT_DECIMAL ):
513 default:
514 FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
515 break;
518 return size;
520 /******************************************************************************
521 * StringDupAtoBstr [INTERNAL]
524 static BSTR StringDupAtoBstr( char* strIn )
526 BSTR bstr = NULL;
527 OLECHAR* pNewString = NULL;
528 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
529 bstr = SysAllocString( pNewString );
530 HeapFree( GetProcessHeap(), 0, pNewString );
531 return bstr;
534 /******************************************************************************
535 * round [INTERNAL]
537 * Round the double value to the nearest integer value.
539 static double round( double d )
541 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
542 BOOL bEvenNumber = FALSE;
543 int nSign = 0;
545 /* Save the sign of the number
547 nSign = (d >= 0.0) ? 1 : -1;
548 d = fabs( d );
550 /* Remove the decimals.
552 integerValue = floor( d );
554 /* Set the Even flag. This is used to round the number when
555 * the decimals are exactly 1/2. If the integer part is
556 * odd the number is rounded up. If the integer part
557 * is even the number is rounded down. Using this method
558 * numbers are rounded up|down half the time.
560 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
562 /* Remove the integral part of the number.
564 decimals = d - integerValue;
566 /* Note: Ceil returns the smallest integer that is greater that x.
567 * and floor returns the largest integer that is less than or equal to x.
569 if( decimals > 0.5 )
571 /* If the decimal part is greater than 1/2
573 roundedValue = ceil( d );
575 else if( decimals < 0.5 )
577 /* If the decimal part is smaller than 1/2
579 roundedValue = floor( d );
581 else
583 /* the decimals are exactly 1/2 so round according to
584 * the bEvenNumber flag.
586 if( bEvenNumber )
588 roundedValue = floor( d );
590 else
592 roundedValue = ceil( d );
596 return roundedValue * nSign;
599 /******************************************************************************
600 * RemoveCharacterFromString [INTERNAL]
602 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
604 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
606 LPSTR pNewString = NULL;
607 LPSTR strToken = NULL;
610 /* Check if we have a valid argument
612 if( str != NULL )
614 pNewString = strdup( str );
615 str[0] = '\0';
616 strToken = strtok( pNewString, strOfCharToRemove );
617 while( strToken != NULL ) {
618 strcat( str, strToken );
619 strToken = strtok( NULL, strOfCharToRemove );
621 free( pNewString );
623 return;
626 /******************************************************************************
627 * GetValidRealString [INTERNAL]
629 * Checks if the string is of proper format to be converted to a real value.
631 static BOOL IsValidRealString( LPSTR strRealString )
633 /* Real values that have a decimal point are required to either have
634 * digits before or after the decimal point. We will assume that
635 * we do not have any digits at either position. If we do encounter
636 * some we will disable this flag.
638 BOOL bDigitsRequired = TRUE;
639 /* Processed fields in the string representation of the real number.
641 BOOL bWhiteSpaceProcessed = FALSE;
642 BOOL bFirstSignProcessed = FALSE;
643 BOOL bFirstDigitsProcessed = FALSE;
644 BOOL bDecimalPointProcessed = FALSE;
645 BOOL bSecondDigitsProcessed = FALSE;
646 BOOL bExponentProcessed = FALSE;
647 BOOL bSecondSignProcessed = FALSE;
648 BOOL bThirdDigitsProcessed = FALSE;
649 /* Assume string parameter "strRealString" is valid and try to disprove it.
651 BOOL bValidRealString = TRUE;
653 /* Used to count the number of tokens in the "strRealString".
655 LPSTR strToken = NULL;
656 int nTokens = 0;
657 LPSTR pChar = NULL;
659 /* Check if we have a valid argument
661 if( strRealString == NULL )
663 bValidRealString = FALSE;
666 if( bValidRealString == TRUE )
668 /* Make sure we only have ONE token in the string.
670 strToken = strtok( strRealString, " " );
671 while( strToken != NULL ) {
672 nTokens++;
673 strToken = strtok( NULL, " " );
676 if( nTokens != 1 )
678 bValidRealString = FALSE;
683 /* Make sure this token contains only valid characters.
684 * The string argument to atof has the following form:
685 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
686 * Whitespace consists of space and|or <TAB> characters, which are ignored.
687 * Sign is either plus '+' or minus '-'.
688 * Digits are one or more decimal digits.
689 * Note: If no digits appear before the decimal point, at least one must
690 * appear after the decimal point.
691 * The decimal digits may be followed by an exponent.
692 * An Exponent consists of an introductory letter ( D, d, E, or e) and
693 * an optionally signed decimal integer.
695 pChar = strRealString;
696 while( bValidRealString == TRUE && *pChar != '\0' )
698 switch( *pChar )
700 /* If whitespace...
702 case ' ':
703 case '\t':
704 if( bWhiteSpaceProcessed ||
705 bFirstSignProcessed ||
706 bFirstDigitsProcessed ||
707 bDecimalPointProcessed ||
708 bSecondDigitsProcessed ||
709 bExponentProcessed ||
710 bSecondSignProcessed ||
711 bThirdDigitsProcessed )
713 bValidRealString = FALSE;
715 break;
716 /* If sign...
718 case '+':
719 case '-':
720 if( bFirstSignProcessed == FALSE )
722 if( bFirstDigitsProcessed ||
723 bDecimalPointProcessed ||
724 bSecondDigitsProcessed ||
725 bExponentProcessed ||
726 bSecondSignProcessed ||
727 bThirdDigitsProcessed )
729 bValidRealString = FALSE;
731 bWhiteSpaceProcessed = TRUE;
732 bFirstSignProcessed = TRUE;
734 else if( bSecondSignProcessed == FALSE )
736 /* Note: The exponent must be present in
737 * order to accept the second sign...
739 if( bExponentProcessed == FALSE ||
740 bThirdDigitsProcessed ||
741 bDigitsRequired )
743 bValidRealString = FALSE;
745 bFirstSignProcessed = TRUE;
746 bWhiteSpaceProcessed = TRUE;
747 bFirstDigitsProcessed = TRUE;
748 bDecimalPointProcessed = TRUE;
749 bSecondDigitsProcessed = TRUE;
750 bSecondSignProcessed = TRUE;
752 break;
754 /* If decimals...
756 case '0':
757 case '1':
758 case '2':
759 case '3':
760 case '4':
761 case '5':
762 case '6':
763 case '7':
764 case '8':
765 case '9':
766 if( bFirstDigitsProcessed == FALSE )
768 if( bDecimalPointProcessed ||
769 bSecondDigitsProcessed ||
770 bExponentProcessed ||
771 bSecondSignProcessed ||
772 bThirdDigitsProcessed )
774 bValidRealString = FALSE;
776 bFirstSignProcessed = TRUE;
777 bWhiteSpaceProcessed = TRUE;
778 /* We have found some digits before the decimal point
779 * so disable the "Digits required" flag.
781 bDigitsRequired = FALSE;
783 else if( bSecondDigitsProcessed == FALSE )
785 if( bExponentProcessed ||
786 bSecondSignProcessed ||
787 bThirdDigitsProcessed )
789 bValidRealString = FALSE;
791 bFirstSignProcessed = TRUE;
792 bWhiteSpaceProcessed = TRUE;
793 bFirstDigitsProcessed = TRUE;
794 bDecimalPointProcessed = TRUE;
795 /* We have found some digits after the decimal point
796 * so disable the "Digits required" flag.
798 bDigitsRequired = FALSE;
800 else if( bThirdDigitsProcessed == FALSE )
802 /* Getting here means everything else should be processed.
803 * If we get anything else than a decimal following this
804 * digit it will be flagged by the other cases, so
805 * we do not really need to do anything in here.
808 break;
809 /* If DecimalPoint...
811 case '.':
812 if( bDecimalPointProcessed ||
813 bSecondDigitsProcessed ||
814 bExponentProcessed ||
815 bSecondSignProcessed ||
816 bThirdDigitsProcessed )
818 bValidRealString = FALSE;
820 bFirstSignProcessed = TRUE;
821 bWhiteSpaceProcessed = TRUE;
822 bFirstDigitsProcessed = TRUE;
823 bDecimalPointProcessed = TRUE;
824 break;
825 /* If Exponent...
827 case 'e':
828 case 'E':
829 case 'd':
830 case 'D':
831 if( bExponentProcessed ||
832 bSecondSignProcessed ||
833 bThirdDigitsProcessed ||
834 bDigitsRequired )
836 bValidRealString = FALSE;
838 bFirstSignProcessed = TRUE;
839 bWhiteSpaceProcessed = TRUE;
840 bFirstDigitsProcessed = TRUE;
841 bDecimalPointProcessed = TRUE;
842 bSecondDigitsProcessed = TRUE;
843 bExponentProcessed = TRUE;
844 break;
845 default:
846 bValidRealString = FALSE;
847 break;
849 /* Process next character.
851 pChar++;
854 /* If the required digits were not present we have an invalid
855 * string representation of a real number.
857 if( bDigitsRequired == TRUE )
859 bValidRealString = FALSE;
862 return bValidRealString;
866 /******************************************************************************
867 * Coerce [INTERNAL]
869 * This function dispatches execution to the proper conversion API
870 * to do the necessary coercion.
872 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
874 HRESULT res = S_OK;
875 unsigned short vtFrom = 0;
876 vtFrom = ps->vt & VT_TYPEMASK;
878 /* Note: Since "long" and "int" values both have 4 bytes and are
879 * both signed integers "int" will be treated as "long" in the
880 * following code.
881 * The same goes for their unsigned versions.
884 /* Trivial Case: If the coercion is from two types that are
885 * identical then we can blindly copy from one argument to another.*/
886 if ((vt==vtFrom))
888 return VariantCopy(pd,ps);
891 /* Cases requiring thought*/
892 switch( vt )
895 case( VT_EMPTY ):
896 res = VariantClear( pd );
897 break;
898 case( VT_NULL ):
899 res = VariantClear( pd );
900 if( res == S_OK )
902 pd->vt = VT_NULL;
904 break;
905 case( VT_I1 ):
906 switch( vtFrom )
908 case( VT_I1 ):
909 res = VariantCopy( pd, ps );
910 break;
911 case( VT_I2 ):
912 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
913 break;
914 case( VT_INT ):
915 case( VT_I4 ):
916 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
917 break;
918 case( VT_UI1 ):
919 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
920 break;
921 case( VT_UI2 ):
922 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
923 break;
924 case( VT_UINT ):
925 case( VT_UI4 ):
926 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
927 break;
928 case( VT_R4 ):
929 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
930 break;
931 case( VT_R8 ):
932 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
933 break;
934 case( VT_DATE ):
935 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
936 break;
937 case( VT_BOOL ):
938 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
939 break;
940 case( VT_BSTR ):
941 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
942 break;
943 case( VT_CY ):
944 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
945 case( VT_DISPATCH ):
946 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
947 case( VT_UNKNOWN ):
948 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
949 case( VT_DECIMAL ):
950 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
951 default:
952 res = DISP_E_TYPEMISMATCH;
953 FIXME("Coercion from %d to %d\n", vtFrom, vt );
954 break;
956 break;
958 case( VT_I2 ):
959 switch( vtFrom )
961 case( VT_I1 ):
962 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
963 break;
964 case( VT_I2 ):
965 res = VariantCopy( pd, ps );
966 break;
967 case( VT_INT ):
968 case( VT_I4 ):
969 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
970 break;
971 case( VT_UI1 ):
972 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
973 break;
974 case( VT_UI2 ):
975 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
976 break;
977 case( VT_UINT ):
978 case( VT_UI4 ):
979 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
980 break;
981 case( VT_R4 ):
982 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
983 break;
984 case( VT_R8 ):
985 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
986 break;
987 case( VT_DATE ):
988 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
989 break;
990 case( VT_BOOL ):
991 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
992 break;
993 case( VT_BSTR ):
994 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
995 break;
996 case( VT_CY ):
997 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
998 case( VT_DISPATCH ):
999 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1000 case( VT_UNKNOWN ):
1001 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
1002 case( VT_DECIMAL ):
1003 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
1004 default:
1005 res = DISP_E_TYPEMISMATCH;
1006 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1007 break;
1009 break;
1011 case( VT_INT ):
1012 case( VT_I4 ):
1013 switch( vtFrom )
1015 case( VT_I1 ):
1016 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1017 break;
1018 case( VT_I2 ):
1019 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1020 break;
1021 case( VT_INT ):
1022 case( VT_I4 ):
1023 res = VariantCopy( pd, ps );
1024 break;
1025 case( VT_UI1 ):
1026 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1027 break;
1028 case( VT_UI2 ):
1029 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1030 break;
1031 case( VT_UINT ):
1032 case( VT_UI4 ):
1033 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1034 break;
1035 case( VT_R4 ):
1036 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1037 break;
1038 case( VT_R8 ):
1039 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1040 break;
1041 case( VT_DATE ):
1042 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1043 break;
1044 case( VT_BOOL ):
1045 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1046 break;
1047 case( VT_BSTR ):
1048 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1049 break;
1050 case( VT_CY ):
1051 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1052 case( VT_DISPATCH ):
1053 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1054 case( VT_UNKNOWN ):
1055 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1056 case( VT_DECIMAL ):
1057 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1058 default:
1059 res = DISP_E_TYPEMISMATCH;
1060 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1061 break;
1063 break;
1065 case( VT_UI1 ):
1066 switch( vtFrom )
1068 case( VT_I1 ):
1069 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1070 break;
1071 case( VT_I2 ):
1072 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1073 break;
1074 case( VT_INT ):
1075 case( VT_I4 ):
1076 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1077 break;
1078 case( VT_UI1 ):
1079 res = VariantCopy( pd, ps );
1080 break;
1081 case( VT_UI2 ):
1082 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1083 break;
1084 case( VT_UINT ):
1085 case( VT_UI4 ):
1086 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1087 break;
1088 case( VT_R4 ):
1089 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1090 break;
1091 case( VT_R8 ):
1092 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1093 break;
1094 case( VT_DATE ):
1095 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1096 break;
1097 case( VT_BOOL ):
1098 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1099 break;
1100 case( VT_BSTR ):
1101 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1102 break;
1103 case( VT_CY ):
1104 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1105 case( VT_DISPATCH ):
1106 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1107 case( VT_UNKNOWN ):
1108 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1109 case( VT_DECIMAL ):
1110 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1111 default:
1112 res = DISP_E_TYPEMISMATCH;
1113 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1114 break;
1116 break;
1118 case( VT_UI2 ):
1119 switch( vtFrom )
1121 case( VT_I1 ):
1122 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1123 break;
1124 case( VT_I2 ):
1125 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1126 break;
1127 case( VT_INT ):
1128 case( VT_I4 ):
1129 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1130 break;
1131 case( VT_UI1 ):
1132 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1133 break;
1134 case( VT_UI2 ):
1135 res = VariantCopy( pd, ps );
1136 break;
1137 case( VT_UINT ):
1138 case( VT_UI4 ):
1139 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1140 break;
1141 case( VT_R4 ):
1142 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1143 break;
1144 case( VT_R8 ):
1145 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1146 break;
1147 case( VT_DATE ):
1148 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1149 break;
1150 case( VT_BOOL ):
1151 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1152 break;
1153 case( VT_BSTR ):
1154 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1155 break;
1156 case( VT_CY ):
1157 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1158 case( VT_DISPATCH ):
1159 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1160 case( VT_UNKNOWN ):
1161 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1162 case( VT_DECIMAL ):
1163 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1164 default:
1165 res = DISP_E_TYPEMISMATCH;
1166 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1167 break;
1169 break;
1171 case( VT_UINT ):
1172 case( VT_UI4 ):
1173 switch( vtFrom )
1175 case( VT_I1 ):
1176 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1177 break;
1178 case( VT_I2 ):
1179 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1180 break;
1181 case( VT_INT ):
1182 case( VT_I4 ):
1183 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1184 break;
1185 case( VT_UI1 ):
1186 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1187 break;
1188 case( VT_UI2 ):
1189 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1190 break;
1191 case( VT_UI4 ):
1192 res = VariantCopy( pd, ps );
1193 break;
1194 case( VT_R4 ):
1195 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1196 break;
1197 case( VT_R8 ):
1198 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1199 break;
1200 case( VT_DATE ):
1201 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1202 break;
1203 case( VT_BOOL ):
1204 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1205 break;
1206 case( VT_BSTR ):
1207 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1208 break;
1209 case( VT_CY ):
1210 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1211 case( VT_DISPATCH ):
1212 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1213 case( VT_UNKNOWN ):
1214 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1215 case( VT_DECIMAL ):
1216 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1217 default:
1218 res = DISP_E_TYPEMISMATCH;
1219 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1220 break;
1222 break;
1224 case( VT_R4 ):
1225 switch( vtFrom )
1227 case( VT_I1 ):
1228 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1229 break;
1230 case( VT_I2 ):
1231 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1232 break;
1233 case( VT_INT ):
1234 case( VT_I4 ):
1235 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1236 break;
1237 case( VT_UI1 ):
1238 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1239 break;
1240 case( VT_UI2 ):
1241 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1242 break;
1243 case( VT_UINT ):
1244 case( VT_UI4 ):
1245 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1246 break;
1247 case( VT_R4 ):
1248 res = VariantCopy( pd, ps );
1249 break;
1250 case( VT_R8 ):
1251 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1252 break;
1253 case( VT_DATE ):
1254 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1255 break;
1256 case( VT_BOOL ):
1257 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1258 break;
1259 case( VT_BSTR ):
1260 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1261 break;
1262 case( VT_CY ):
1263 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1264 case( VT_DISPATCH ):
1265 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1266 case( VT_UNKNOWN ):
1267 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1268 case( VT_DECIMAL ):
1269 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1270 default:
1271 res = DISP_E_TYPEMISMATCH;
1272 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1273 break;
1275 break;
1277 case( VT_R8 ):
1278 switch( vtFrom )
1280 case( VT_I1 ):
1281 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1282 break;
1283 case( VT_I2 ):
1284 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1285 break;
1286 case( VT_INT ):
1287 case( VT_I4 ):
1288 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1289 break;
1290 case( VT_UI1 ):
1291 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1292 break;
1293 case( VT_UI2 ):
1294 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1295 break;
1296 case( VT_UINT ):
1297 case( VT_UI4 ):
1298 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1299 break;
1300 case( VT_R4 ):
1301 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1302 break;
1303 case( VT_R8 ):
1304 res = VariantCopy( pd, ps );
1305 break;
1306 case( VT_DATE ):
1307 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1308 break;
1309 case( VT_BOOL ):
1310 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1311 break;
1312 case( VT_BSTR ):
1313 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1314 break;
1315 case( VT_CY ):
1316 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1317 case( VT_DISPATCH ):
1318 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1319 case( VT_UNKNOWN ):
1320 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1321 case( VT_DECIMAL ):
1322 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1323 default:
1324 res = DISP_E_TYPEMISMATCH;
1325 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1326 break;
1328 break;
1330 case( VT_DATE ):
1331 switch( vtFrom )
1333 case( VT_I1 ):
1334 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1335 break;
1336 case( VT_I2 ):
1337 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1338 break;
1339 case( VT_INT ):
1340 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1341 break;
1342 case( VT_I4 ):
1343 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1344 break;
1345 case( VT_UI1 ):
1346 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1347 break;
1348 case( VT_UI2 ):
1349 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1350 break;
1351 case( VT_UINT ):
1352 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1353 break;
1354 case( VT_UI4 ):
1355 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1356 break;
1357 case( VT_R4 ):
1358 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1359 break;
1360 case( VT_R8 ):
1361 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1362 break;
1363 case( VT_DATE ):
1364 res = VariantCopy( pd, ps );
1365 break;
1366 case( VT_BOOL ):
1367 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1368 break;
1369 case( VT_BSTR ):
1370 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1371 break;
1372 case( VT_CY ):
1373 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1374 case( VT_DISPATCH ):
1375 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1376 case( VT_UNKNOWN ):
1377 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1378 case( VT_DECIMAL ):
1379 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1380 default:
1381 res = DISP_E_TYPEMISMATCH;
1382 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1383 break;
1385 break;
1387 case( VT_BOOL ):
1388 switch( vtFrom )
1390 case( VT_I1 ):
1391 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1392 break;
1393 case( VT_I2 ):
1394 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1395 break;
1396 case( VT_INT ):
1397 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1398 break;
1399 case( VT_I4 ):
1400 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1401 break;
1402 case( VT_UI1 ):
1403 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1404 break;
1405 case( VT_UI2 ):
1406 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1407 break;
1408 case( VT_UINT ):
1409 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1410 break;
1411 case( VT_UI4 ):
1412 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1413 break;
1414 case( VT_R4 ):
1415 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1416 break;
1417 case( VT_R8 ):
1418 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1419 break;
1420 case( VT_DATE ):
1421 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1422 break;
1423 case( VT_BOOL ):
1424 res = VariantCopy( pd, ps );
1425 break;
1426 case( VT_BSTR ):
1427 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1428 break;
1429 case( VT_CY ):
1430 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1431 case( VT_DISPATCH ):
1432 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1433 case( VT_UNKNOWN ):
1434 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1435 case( VT_DECIMAL ):
1436 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1437 default:
1438 res = DISP_E_TYPEMISMATCH;
1439 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1440 break;
1442 break;
1444 case( VT_BSTR ):
1445 switch( vtFrom )
1447 case( VT_I1 ):
1448 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1449 break;
1450 case( VT_I2 ):
1451 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1452 break;
1453 case( VT_INT ):
1454 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1455 break;
1456 case( VT_I4 ):
1457 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1458 break;
1459 case( VT_UI1 ):
1460 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1461 break;
1462 case( VT_UI2 ):
1463 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1464 break;
1465 case( VT_UINT ):
1466 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1467 break;
1468 case( VT_UI4 ):
1469 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1470 break;
1471 case( VT_R4 ):
1472 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1473 break;
1474 case( VT_R8 ):
1475 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1476 break;
1477 case( VT_DATE ):
1478 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1479 break;
1480 case( VT_BOOL ):
1481 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1482 break;
1483 case( VT_BSTR ):
1484 res = VariantCopy( pd, ps );
1485 break;
1486 case( VT_CY ):
1487 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1488 case( VT_DISPATCH ):
1489 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1490 case( VT_UNKNOWN ):
1491 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1492 case( VT_DECIMAL ):
1493 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1494 default:
1495 res = DISP_E_TYPEMISMATCH;
1496 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1497 break;
1499 break;
1501 case( VT_CY ):
1502 switch( vtFrom )
1504 case( VT_I1 ):
1505 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1506 break;
1507 case( VT_I2 ):
1508 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1509 break;
1510 case( VT_INT ):
1511 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1512 break;
1513 case( VT_I4 ):
1514 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1515 break;
1516 case( VT_UI1 ):
1517 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1518 break;
1519 case( VT_UI2 ):
1520 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1521 break;
1522 case( VT_UINT ):
1523 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1524 break;
1525 case( VT_UI4 ):
1526 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1527 break;
1528 case( VT_R4 ):
1529 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1530 break;
1531 case( VT_R8 ):
1532 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1533 break;
1534 case( VT_DATE ):
1535 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1536 break;
1537 case( VT_BOOL ):
1538 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1539 break;
1540 case( VT_CY ):
1541 res = VariantCopy( pd, ps );
1542 break;
1543 case( VT_BSTR ):
1544 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1545 case( VT_DISPATCH ):
1546 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1547 case( VT_UNKNOWN ):
1548 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1549 case( VT_DECIMAL ):
1550 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1551 default:
1552 res = DISP_E_TYPEMISMATCH;
1553 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1554 break;
1556 break;
1558 default:
1559 res = DISP_E_TYPEMISMATCH;
1560 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1561 break;
1564 return res;
1567 /******************************************************************************
1568 * ValidateVtRange [INTERNAL]
1570 * Used internally by the hi-level Variant API to determine
1571 * if the vartypes are valid.
1573 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1575 /* if by value we must make sure it is in the
1576 * range of the valid types.
1578 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1580 return DISP_E_BADVARTYPE;
1582 return S_OK;
1586 /******************************************************************************
1587 * ValidateVartype [INTERNAL]
1589 * Used internally by the hi-level Variant API to determine
1590 * if the vartypes are valid.
1592 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1594 HRESULT res = S_OK;
1596 /* check if we have a valid argument.
1598 if( vt & VT_BYREF )
1600 /* if by reference check that the type is in
1601 * the valid range and that it is not of empty or null type
1603 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1604 ( vt & VT_TYPEMASK ) == VT_NULL ||
1605 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1607 res = E_INVALIDARG;
1611 else
1613 res = ValidateVtRange( vt );
1616 return res;
1619 /******************************************************************************
1620 * ValidateVt [INTERNAL]
1622 * Used internally by the hi-level Variant API to determine
1623 * if the vartypes are valid.
1625 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1627 HRESULT res = S_OK;
1629 /* check if we have a valid argument.
1631 if( vt & VT_BYREF )
1633 /* if by reference check that the type is in
1634 * the valid range and that it is not of empty or null type
1636 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1637 ( vt & VT_TYPEMASK ) == VT_NULL ||
1638 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1640 res = DISP_E_BADVARTYPE;
1644 else
1646 res = ValidateVtRange( vt );
1649 return res;
1656 /******************************************************************************
1657 * VariantInit32 [OLEAUT32.8]
1659 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1660 * contents of the Variant.
1662 void WINAPI VariantInit(VARIANTARG* pvarg)
1664 TRACE("(%p),stub\n",pvarg);
1666 memset(pvarg, 0, sizeof (VARIANTARG));
1667 pvarg->vt = VT_EMPTY;
1669 return;
1672 /******************************************************************************
1673 * VariantClear32 [OLEAUT32.9]
1675 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1676 * sets the wReservedX field to 0. The current contents of the VARIANT are
1677 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1678 * released. If VT_ARRAY the array is freed.
1680 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1682 HRESULT res = S_OK;
1683 TRACE("(%p)\n",pvarg);
1685 res = ValidateVariantType( pvarg->vt );
1686 if( res == S_OK )
1688 if( !( pvarg->vt & VT_BYREF ) )
1691 * The VT_ARRAY flag is a special case of a safe array.
1693 if ( (pvarg->vt & VT_ARRAY) != 0)
1695 SafeArrayDestroy(pvarg->u.parray);
1697 else
1699 switch( pvarg->vt & VT_TYPEMASK )
1701 case( VT_BSTR ):
1702 SysFreeString( pvarg->u.bstrVal );
1703 break;
1704 case( VT_DISPATCH ):
1705 if(pvarg->u.pdispVal!=NULL)
1706 ICOM_CALL(Release,pvarg->u.pdispVal);
1707 break;
1708 case( VT_VARIANT ):
1709 VariantClear(pvarg->u.pvarVal);
1710 break;
1711 case( VT_UNKNOWN ):
1712 if(pvarg->u.punkVal!=NULL)
1713 ICOM_CALL(Release,pvarg->u.punkVal);
1714 break;
1715 case( VT_SAFEARRAY ):
1716 SafeArrayDestroy(pvarg->u.parray);
1717 break;
1718 default:
1719 break;
1725 * Empty all the fields and mark the type as empty.
1727 memset(pvarg, 0, sizeof (VARIANTARG));
1728 pvarg->vt = VT_EMPTY;
1731 return res;
1734 /******************************************************************************
1735 * VariantCopy32 [OLEAUT32.10]
1737 * Frees up the designation variant and makes a copy of the source.
1739 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1741 HRESULT res = S_OK;
1743 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1745 res = ValidateVariantType( pvargSrc->vt );
1747 /* If the pointer are to the same variant we don't need
1748 * to do anything.
1750 if( pvargDest != pvargSrc && res == S_OK )
1752 res = VariantClear( pvargDest );
1754 if( res == S_OK )
1756 if( pvargSrc->vt & VT_BYREF )
1758 /* In the case of byreference we only need
1759 * to copy the pointer.
1761 pvargDest->u = pvargSrc->u;
1762 pvargDest->vt = pvargSrc->vt;
1764 else
1767 * The VT_ARRAY flag is another way to designate a safe array.
1769 if (pvargSrc->vt & VT_ARRAY)
1771 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1773 else
1775 /* In the case of by value we need to
1776 * copy the actuall value. In the case of
1777 * VT_BSTR a copy of the string is made,
1778 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1779 * called to increment the object's reference count.
1781 switch( pvargSrc->vt & VT_TYPEMASK )
1783 case( VT_BSTR ):
1784 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1785 break;
1786 case( VT_DISPATCH ):
1787 pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1788 if (pvargDest->u.pdispVal!=NULL)
1789 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1790 break;
1791 case( VT_VARIANT ):
1792 VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1793 break;
1794 case( VT_UNKNOWN ):
1795 pvargDest->u.punkVal = pvargSrc->u.punkVal;
1796 if (pvargDest->u.pdispVal!=NULL)
1797 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1798 break;
1799 case( VT_SAFEARRAY ):
1800 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1801 break;
1802 default:
1803 pvargDest->u = pvargSrc->u;
1804 break;
1808 pvargDest->vt = pvargSrc->vt;
1813 return res;
1817 /******************************************************************************
1818 * VariantCopyInd32 [OLEAUT32.11]
1820 * Frees up the destination variant and makes a copy of the source. If
1821 * the source is of type VT_BYREF it performs the necessary indirections.
1823 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1825 HRESULT res = S_OK;
1827 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1829 res = ValidateVariantType( pvargSrc->vt );
1831 if( res != S_OK )
1832 return res;
1834 if( pvargSrc->vt & VT_BYREF )
1836 VARIANTARG varg;
1837 VariantInit( &varg );
1839 /* handle the in place copy.
1841 if( pvargDest == pvargSrc )
1843 /* we will use a copy of the source instead.
1845 res = VariantCopy( &varg, pvargSrc );
1846 pvargSrc = &varg;
1849 if( res == S_OK )
1851 res = VariantClear( pvargDest );
1853 if( res == S_OK )
1856 * The VT_ARRAY flag is another way to designate a safearray variant.
1858 if ( pvargSrc->vt & VT_ARRAY)
1860 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1862 else
1864 /* In the case of by reference we need
1865 * to copy the date pointed to by the variant.
1868 /* Get the variant type.
1870 switch( pvargSrc->vt & VT_TYPEMASK )
1872 case( VT_BSTR ):
1873 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1874 break;
1875 case( VT_DISPATCH ):
1876 break;
1877 case( VT_VARIANT ):
1879 /* Prevent from cycling. According to tests on
1880 * VariantCopyInd in Windows and the documentation
1881 * this API dereferences the inner Variants to only one depth.
1882 * If the inner Variant itself contains an
1883 * other inner variant the E_INVALIDARG error is
1884 * returned.
1886 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1888 /* If we get here we are attempting to deference
1889 * an inner variant that that is itself contained
1890 * in an inner variant so report E_INVALIDARG error.
1892 res = E_INVALIDARG;
1894 else
1896 /* Set the processing inner variant flag.
1897 * We will set this flag in the inner variant
1898 * that will be passed to the VariantCopyInd function.
1900 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1902 /* Dereference the inner variant.
1904 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1907 break;
1908 case( VT_UNKNOWN ):
1909 break;
1910 case( VT_SAFEARRAY ):
1911 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1912 break;
1913 default:
1914 /* This is a by reference Variant which means that the union
1915 * part of the Variant contains a pointer to some data of
1916 * type "pvargSrc->vt & VT_TYPEMASK".
1917 * We will deference this data in a generic fashion using
1918 * the void pointer "Variant.u.byref".
1919 * We will copy this data into the union of the destination
1920 * Variant.
1922 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1923 break;
1927 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1931 /* this should not fail.
1933 VariantClear( &varg );
1935 else
1937 res = VariantCopy( pvargDest, pvargSrc );
1940 return res;
1943 /******************************************************************************
1944 * VariantChangeType32 [OLEAUT32.12]
1946 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1947 USHORT wFlags, VARTYPE vt)
1949 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1952 /******************************************************************************
1953 * VariantChangeTypeEx32 [OLEAUT32.147]
1955 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1956 LCID lcid, USHORT wFlags, VARTYPE vt)
1958 HRESULT res = S_OK;
1959 VARIANTARG varg;
1960 VariantInit( &varg );
1962 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1964 /* validate our source argument.
1966 res = ValidateVariantType( pvargSrc->vt );
1968 /* validate the vartype.
1970 if( res == S_OK )
1972 res = ValidateVt( vt );
1975 /* if we are doing an in-place conversion make a copy of the source.
1977 if( res == S_OK && pvargDest == pvargSrc )
1979 res = VariantCopy( &varg, pvargSrc );
1980 pvargSrc = &varg;
1983 if( res == S_OK )
1985 /* free up the destination variant.
1987 res = VariantClear( pvargDest );
1990 if( res == S_OK )
1992 if( pvargSrc->vt & VT_BYREF )
1994 /* Convert the source variant to a "byvalue" variant.
1996 VARIANTARG Variant;
1997 VariantInit( &Variant );
1998 res = VariantCopyInd( &Variant, pvargSrc );
1999 if( res == S_OK )
2001 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2002 /* this should not fail.
2004 VariantClear( &Variant );
2008 else
2010 /* Use the current "byvalue" source variant.
2012 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2015 /* this should not fail.
2017 VariantClear( &varg );
2019 /* set the type of the destination
2021 if ( res == S_OK )
2022 pvargDest->vt = vt;
2024 return res;
2030 /******************************************************************************
2031 * VarUI1FromI232 [OLEAUT32.130]
2033 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2035 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2037 /* Check range of value.
2039 if( sIn < UI1_MIN || sIn > UI1_MAX )
2041 return DISP_E_OVERFLOW;
2044 *pbOut = (BYTE) sIn;
2046 return S_OK;
2049 /******************************************************************************
2050 * VarUI1FromI432 [OLEAUT32.131]
2052 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2054 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2056 /* Check range of value.
2058 if( lIn < UI1_MIN || lIn > UI1_MAX )
2060 return DISP_E_OVERFLOW;
2063 *pbOut = (BYTE) lIn;
2065 return S_OK;
2069 /******************************************************************************
2070 * VarUI1FromR432 [OLEAUT32.132]
2072 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2074 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2076 /* Check range of value.
2078 fltIn = round( fltIn );
2079 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2081 return DISP_E_OVERFLOW;
2084 *pbOut = (BYTE) fltIn;
2086 return S_OK;
2089 /******************************************************************************
2090 * VarUI1FromR832 [OLEAUT32.133]
2092 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2094 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2096 /* Check range of value.
2098 dblIn = round( dblIn );
2099 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2101 return DISP_E_OVERFLOW;
2104 *pbOut = (BYTE) dblIn;
2106 return S_OK;
2109 /******************************************************************************
2110 * VarUI1FromDate32 [OLEAUT32.135]
2112 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2114 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2116 /* Check range of value.
2118 dateIn = round( dateIn );
2119 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2121 return DISP_E_OVERFLOW;
2124 *pbOut = (BYTE) dateIn;
2126 return S_OK;
2129 /******************************************************************************
2130 * VarUI1FromBool32 [OLEAUT32.138]
2132 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2134 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2136 *pbOut = (BYTE) boolIn;
2138 return S_OK;
2141 /******************************************************************************
2142 * VarUI1FromI132 [OLEAUT32.237]
2144 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2146 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2148 *pbOut = cIn;
2150 return S_OK;
2153 /******************************************************************************
2154 * VarUI1FromUI232 [OLEAUT32.238]
2156 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2158 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2160 /* Check range of value.
2162 if( uiIn > UI1_MAX )
2164 return DISP_E_OVERFLOW;
2167 *pbOut = (BYTE) uiIn;
2169 return S_OK;
2172 /******************************************************************************
2173 * VarUI1FromUI432 [OLEAUT32.239]
2175 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2177 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2179 /* Check range of value.
2181 if( ulIn > UI1_MAX )
2183 return DISP_E_OVERFLOW;
2186 *pbOut = (BYTE) ulIn;
2188 return S_OK;
2192 /******************************************************************************
2193 * VarUI1FromStr32 [OLEAUT32.54]
2195 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2197 double dValue = 0.0;
2198 LPSTR pNewString = NULL;
2200 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2202 /* Check if we have a valid argument
2204 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2205 RemoveCharacterFromString( pNewString, "," );
2206 if( IsValidRealString( pNewString ) == FALSE )
2208 return DISP_E_TYPEMISMATCH;
2211 /* Convert the valid string to a floating point number.
2213 dValue = atof( pNewString );
2215 /* We don't need the string anymore so free it.
2217 HeapFree( GetProcessHeap(), 0 , pNewString );
2219 /* Check range of value.
2221 dValue = round( dValue );
2222 if( dValue < UI1_MIN || dValue > UI1_MAX )
2224 return DISP_E_OVERFLOW;
2227 *pbOut = (BYTE) dValue;
2229 return S_OK;
2232 /**********************************************************************
2233 * VarUI1FromCy32 [OLEAUT32.134]
2234 * Convert currency to unsigned char
2236 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2237 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2239 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2241 *pbOut = (BYTE)t;
2242 return S_OK;
2245 /******************************************************************************
2246 * VarI2FromUI132 [OLEAUT32.48]
2248 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2250 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2252 *psOut = (short) bIn;
2254 return S_OK;
2257 /******************************************************************************
2258 * VarI2FromI432 [OLEAUT32.49]
2260 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2262 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2264 /* Check range of value.
2266 if( lIn < I2_MIN || lIn > I2_MAX )
2268 return DISP_E_OVERFLOW;
2271 *psOut = (short) lIn;
2273 return S_OK;
2276 /******************************************************************************
2277 * VarI2FromR432 [OLEAUT32.50]
2279 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2281 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2283 /* Check range of value.
2285 fltIn = round( fltIn );
2286 if( fltIn < I2_MIN || fltIn > I2_MAX )
2288 return DISP_E_OVERFLOW;
2291 *psOut = (short) fltIn;
2293 return S_OK;
2296 /******************************************************************************
2297 * VarI2FromR832 [OLEAUT32.51]
2299 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2301 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2303 /* Check range of value.
2305 dblIn = round( dblIn );
2306 if( dblIn < I2_MIN || dblIn > I2_MAX )
2308 return DISP_E_OVERFLOW;
2311 *psOut = (short) dblIn;
2313 return S_OK;
2316 /******************************************************************************
2317 * VarI2FromDate32 [OLEAUT32.53]
2319 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2321 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2323 /* Check range of value.
2325 dateIn = round( dateIn );
2326 if( dateIn < I2_MIN || dateIn > I2_MAX )
2328 return DISP_E_OVERFLOW;
2331 *psOut = (short) dateIn;
2333 return S_OK;
2336 /******************************************************************************
2337 * VarI2FromBool32 [OLEAUT32.56]
2339 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2341 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2343 *psOut = (short) boolIn;
2345 return S_OK;
2348 /******************************************************************************
2349 * VarI2FromI132 [OLEAUT32.48]
2351 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2353 TRACE("( %c, %p ), stub\n", cIn, psOut );
2355 *psOut = (short) cIn;
2357 return S_OK;
2360 /******************************************************************************
2361 * VarI2FromUI232 [OLEAUT32.206]
2363 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2365 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2367 /* Check range of value.
2369 if( uiIn > I2_MAX )
2371 return DISP_E_OVERFLOW;
2374 *psOut = (short) uiIn;
2376 return S_OK;
2379 /******************************************************************************
2380 * VarI2FromUI432 [OLEAUT32.49]
2382 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2384 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2386 /* Check range of value.
2388 if( ulIn < I2_MIN || ulIn > I2_MAX )
2390 return DISP_E_OVERFLOW;
2393 *psOut = (short) ulIn;
2395 return S_OK;
2398 /******************************************************************************
2399 * VarI2FromStr32 [OLEAUT32.54]
2401 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2403 double dValue = 0.0;
2404 LPSTR pNewString = NULL;
2406 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2408 /* Check if we have a valid argument
2410 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2411 RemoveCharacterFromString( pNewString, "," );
2412 if( IsValidRealString( pNewString ) == FALSE )
2414 return DISP_E_TYPEMISMATCH;
2417 /* Convert the valid string to a floating point number.
2419 dValue = atof( pNewString );
2421 /* We don't need the string anymore so free it.
2423 HeapFree( GetProcessHeap(), 0, pNewString );
2425 /* Check range of value.
2427 dValue = round( dValue );
2428 if( dValue < I2_MIN || dValue > I2_MAX )
2430 return DISP_E_OVERFLOW;
2433 *psOut = (short) dValue;
2435 return S_OK;
2438 /**********************************************************************
2439 * VarI2FromCy32 [OLEAUT32.52]
2440 * Convert currency to signed short
2442 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2443 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2445 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2447 *psOut = (SHORT)t;
2448 return S_OK;
2451 /******************************************************************************
2452 * VarI4FromUI132 [OLEAUT32.58]
2454 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2456 TRACE("( %X, %p ), stub\n", bIn, plOut );
2458 *plOut = (LONG) bIn;
2460 return S_OK;
2464 /******************************************************************************
2465 * VarI4FromR432 [OLEAUT32.60]
2467 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2469 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2471 /* Check range of value.
2473 fltIn = round( fltIn );
2474 if( fltIn < I4_MIN || fltIn > I4_MAX )
2476 return DISP_E_OVERFLOW;
2479 *plOut = (LONG) fltIn;
2481 return S_OK;
2484 /******************************************************************************
2485 * VarI4FromR832 [OLEAUT32.61]
2487 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2489 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2491 /* Check range of value.
2493 dblIn = round( dblIn );
2494 if( dblIn < I4_MIN || dblIn > I4_MAX )
2496 return DISP_E_OVERFLOW;
2499 *plOut = (LONG) dblIn;
2501 return S_OK;
2504 /******************************************************************************
2505 * VarI4FromDate32 [OLEAUT32.63]
2507 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2509 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2511 /* Check range of value.
2513 dateIn = round( dateIn );
2514 if( dateIn < I4_MIN || dateIn > I4_MAX )
2516 return DISP_E_OVERFLOW;
2519 *plOut = (LONG) dateIn;
2521 return S_OK;
2524 /******************************************************************************
2525 * VarI4FromBool32 [OLEAUT32.66]
2527 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2529 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2531 *plOut = (LONG) boolIn;
2533 return S_OK;
2536 /******************************************************************************
2537 * VarI4FromI132 [OLEAUT32.209]
2539 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2541 TRACE("( %c, %p ), stub\n", cIn, plOut );
2543 *plOut = (LONG) cIn;
2545 return S_OK;
2548 /******************************************************************************
2549 * VarI4FromUI232 [OLEAUT32.210]
2551 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2553 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2555 *plOut = (LONG) uiIn;
2557 return S_OK;
2560 /******************************************************************************
2561 * VarI4FromUI432 [OLEAUT32.211]
2563 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2565 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2567 /* Check range of value.
2569 if( ulIn < I4_MIN || ulIn > I4_MAX )
2571 return DISP_E_OVERFLOW;
2574 *plOut = (LONG) ulIn;
2576 return S_OK;
2579 /******************************************************************************
2580 * VarI4FromI232 [OLEAUT32.59]
2582 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2584 TRACE("( %d, %p ), stub\n", sIn, plOut );
2586 *plOut = (LONG) sIn;
2588 return S_OK;
2591 /******************************************************************************
2592 * VarI4FromStr32 [OLEAUT32.64]
2594 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2596 double dValue = 0.0;
2597 LPSTR pNewString = NULL;
2599 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2601 /* Check if we have a valid argument
2603 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2604 RemoveCharacterFromString( pNewString, "," );
2605 if( IsValidRealString( pNewString ) == FALSE )
2607 return DISP_E_TYPEMISMATCH;
2610 /* Convert the valid string to a floating point number.
2612 dValue = atof( pNewString );
2614 /* We don't need the string anymore so free it.
2616 HeapFree( GetProcessHeap(), 0, pNewString );
2618 /* Check range of value.
2620 dValue = round( dValue );
2621 if( dValue < I4_MIN || dValue > I4_MAX )
2623 return DISP_E_OVERFLOW;
2626 *plOut = (LONG) dValue;
2628 return S_OK;
2631 /**********************************************************************
2632 * VarI4FromCy32 [OLEAUT32.62]
2633 * Convert currency to signed long
2635 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2636 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2638 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2640 *plOut = (LONG)t;
2641 return S_OK;
2644 /******************************************************************************
2645 * VarR4FromUI132 [OLEAUT32.68]
2647 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2649 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2651 *pfltOut = (FLOAT) bIn;
2653 return S_OK;
2656 /******************************************************************************
2657 * VarR4FromI232 [OLEAUT32.69]
2659 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2661 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2663 *pfltOut = (FLOAT) sIn;
2665 return S_OK;
2668 /******************************************************************************
2669 * VarR4FromI432 [OLEAUT32.70]
2671 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2673 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2675 *pfltOut = (FLOAT) lIn;
2677 return S_OK;
2680 /******************************************************************************
2681 * VarR4FromR832 [OLEAUT32.71]
2683 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2685 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2687 /* Check range of value.
2689 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2691 return DISP_E_OVERFLOW;
2694 *pfltOut = (FLOAT) dblIn;
2696 return S_OK;
2699 /******************************************************************************
2700 * VarR4FromDate32 [OLEAUT32.73]
2702 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2704 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2706 /* Check range of value.
2708 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2710 return DISP_E_OVERFLOW;
2713 *pfltOut = (FLOAT) dateIn;
2715 return S_OK;
2718 /******************************************************************************
2719 * VarR4FromBool32 [OLEAUT32.76]
2721 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2723 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2725 *pfltOut = (FLOAT) boolIn;
2727 return S_OK;
2730 /******************************************************************************
2731 * VarR4FromI132 [OLEAUT32.213]
2733 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2735 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2737 *pfltOut = (FLOAT) cIn;
2739 return S_OK;
2742 /******************************************************************************
2743 * VarR4FromUI232 [OLEAUT32.214]
2745 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2747 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2749 *pfltOut = (FLOAT) uiIn;
2751 return S_OK;
2754 /******************************************************************************
2755 * VarR4FromUI432 [OLEAUT32.215]
2757 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2759 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2761 *pfltOut = (FLOAT) ulIn;
2763 return S_OK;
2766 /******************************************************************************
2767 * VarR4FromStr32 [OLEAUT32.74]
2769 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2771 double dValue = 0.0;
2772 LPSTR pNewString = NULL;
2774 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2776 /* Check if we have a valid argument
2778 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2779 RemoveCharacterFromString( pNewString, "," );
2780 if( IsValidRealString( pNewString ) == FALSE )
2782 return DISP_E_TYPEMISMATCH;
2785 /* Convert the valid string to a floating point number.
2787 dValue = atof( pNewString );
2789 /* We don't need the string anymore so free it.
2791 HeapFree( GetProcessHeap(), 0, pNewString );
2793 /* Check range of value.
2795 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2797 return DISP_E_OVERFLOW;
2800 *pfltOut = (FLOAT) dValue;
2802 return S_OK;
2805 /**********************************************************************
2806 * VarR4FromCy32 [OLEAUT32.72]
2807 * Convert currency to float
2809 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2810 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2812 return S_OK;
2815 /******************************************************************************
2816 * VarR8FromUI132 [OLEAUT32.68]
2818 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2820 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2822 *pdblOut = (double) bIn;
2824 return S_OK;
2827 /******************************************************************************
2828 * VarR8FromI232 [OLEAUT32.69]
2830 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2832 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2834 *pdblOut = (double) sIn;
2836 return S_OK;
2839 /******************************************************************************
2840 * VarR8FromI432 [OLEAUT32.70]
2842 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2844 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2846 *pdblOut = (double) lIn;
2848 return S_OK;
2851 /******************************************************************************
2852 * VarR8FromR432 [OLEAUT32.81]
2854 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2856 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2858 *pdblOut = (double) fltIn;
2860 return S_OK;
2863 /******************************************************************************
2864 * VarR8FromDate32 [OLEAUT32.83]
2866 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2868 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2870 *pdblOut = (double) dateIn;
2872 return S_OK;
2875 /******************************************************************************
2876 * VarR8FromBool32 [OLEAUT32.86]
2878 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2880 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2882 *pdblOut = (double) boolIn;
2884 return S_OK;
2887 /******************************************************************************
2888 * VarR8FromI132 [OLEAUT32.217]
2890 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2892 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2894 *pdblOut = (double) cIn;
2896 return S_OK;
2899 /******************************************************************************
2900 * VarR8FromUI232 [OLEAUT32.218]
2902 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2904 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2906 *pdblOut = (double) uiIn;
2908 return S_OK;
2911 /******************************************************************************
2912 * VarR8FromUI432 [OLEAUT32.219]
2914 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2916 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2918 *pdblOut = (double) ulIn;
2920 return S_OK;
2923 /******************************************************************************
2924 * VarR8FromStr32 [OLEAUT32.84]
2926 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2928 double dValue = 0.0;
2929 LPSTR pNewString = NULL;
2931 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2933 /* Check if we have a valid argument
2935 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2936 RemoveCharacterFromString( pNewString, "," );
2937 if( IsValidRealString( pNewString ) == FALSE )
2939 return DISP_E_TYPEMISMATCH;
2942 /* Convert the valid string to a floating point number.
2944 dValue = atof( pNewString );
2946 /* We don't need the string anymore so free it.
2948 HeapFree( GetProcessHeap(), 0, pNewString );
2950 *pdblOut = dValue;
2952 return S_OK;
2955 /**********************************************************************
2956 * VarR8FromCy32 [OLEAUT32.82]
2957 * Convert currency to double
2959 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2960 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2962 return S_OK;
2965 /******************************************************************************
2966 * VarDateFromUI132 [OLEAUT32.]
2968 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2970 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2972 *pdateOut = (DATE) bIn;
2974 return S_OK;
2977 /******************************************************************************
2978 * VarDateFromI232 [OLEAUT32.222]
2980 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2982 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2984 *pdateOut = (DATE) sIn;
2986 return S_OK;
2989 /******************************************************************************
2990 * VarDateFromI432 [OLEAUT32.90]
2992 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
2994 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
2996 if( lIn < DATE_MIN || lIn > DATE_MAX )
2998 return DISP_E_OVERFLOW;
3001 *pdateOut = (DATE) lIn;
3003 return S_OK;
3006 /******************************************************************************
3007 * VarDateFromR432 [OLEAUT32.91]
3009 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3011 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3013 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3015 return DISP_E_OVERFLOW;
3018 *pdateOut = (DATE) fltIn;
3020 return S_OK;
3023 /******************************************************************************
3024 * VarDateFromR832 [OLEAUT32.92]
3026 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3028 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3030 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3032 return DISP_E_OVERFLOW;
3035 *pdateOut = (DATE) dblIn;
3037 return S_OK;
3040 /******************************************************************************
3041 * VarDateFromStr32 [OLEAUT32.94]
3042 * The string representing the date is composed of two parts, a date and time.
3044 * The format of the time is has follows:
3045 * hh[:mm][:ss][AM|PM]
3046 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3047 * of space and/or tab characters, which are ignored.
3049 * The formats for the date part are has follows:
3050 * mm/[dd/][yy]yy
3051 * [dd/]mm/[yy]yy
3052 * [yy]yy/mm/dd
3053 * January dd[,] [yy]yy
3054 * dd January [yy]yy
3055 * [yy]yy January dd
3056 * Whitespace can be inserted anywhere between these tokens.
3058 * The formats for the date and time string are has follows.
3059 * date[whitespace][time]
3060 * [time][whitespace]date
3062 * These are the only characters allowed in a string representing a date and time:
3063 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3065 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3067 HRESULT ret = S_OK;
3068 struct tm TM = { 0,0,0,0,0,0,0,0,0 };
3070 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3072 if( DateTimeStringToTm( strIn, lcid, &TM ) )
3074 if( TmToDATE( &TM, pdateOut ) == FALSE )
3076 ret = E_INVALIDARG;
3079 else
3081 ret = DISP_E_TYPEMISMATCH;
3085 return ret;
3088 /******************************************************************************
3089 * VarDateFromI132 [OLEAUT32.221]
3091 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3093 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3095 *pdateOut = (DATE) cIn;
3097 return S_OK;
3100 /******************************************************************************
3101 * VarDateFromUI232 [OLEAUT32.222]
3103 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3105 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3107 if( uiIn > DATE_MAX )
3109 return DISP_E_OVERFLOW;
3112 *pdateOut = (DATE) uiIn;
3114 return S_OK;
3117 /******************************************************************************
3118 * VarDateFromUI432 [OLEAUT32.223]
3120 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3122 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3124 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3126 return DISP_E_OVERFLOW;
3129 *pdateOut = (DATE) ulIn;
3131 return S_OK;
3134 /******************************************************************************
3135 * VarDateFromBool32 [OLEAUT32.96]
3137 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3139 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3141 *pdateOut = (DATE) boolIn;
3143 return S_OK;
3146 /**********************************************************************
3147 * VarDateFromCy32 [OLEAUT32.93]
3148 * Convert currency to date
3150 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3151 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3153 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3154 return S_OK;
3157 /******************************************************************************
3158 * VarBstrFromUI132 [OLEAUT32.108]
3160 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3162 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3163 sprintf( pBuffer, "%d", bVal );
3165 *pbstrOut = StringDupAtoBstr( pBuffer );
3167 return S_OK;
3170 /******************************************************************************
3171 * VarBstrFromI232 [OLEAUT32.109]
3173 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3175 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3176 sprintf( pBuffer, "%d", iVal );
3177 *pbstrOut = StringDupAtoBstr( pBuffer );
3179 return S_OK;
3182 /******************************************************************************
3183 * VarBstrFromI432 [OLEAUT32.110]
3185 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3187 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3189 sprintf( pBuffer, "%ld", lIn );
3190 *pbstrOut = StringDupAtoBstr( pBuffer );
3192 return S_OK;
3195 /******************************************************************************
3196 * VarBstrFromR432 [OLEAUT32.111]
3198 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3200 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3202 sprintf( pBuffer, "%.7g", fltIn );
3203 *pbstrOut = StringDupAtoBstr( pBuffer );
3205 return S_OK;
3208 /******************************************************************************
3209 * VarBstrFromR832 [OLEAUT32.112]
3211 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3213 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3215 sprintf( pBuffer, "%.15g", dblIn );
3216 *pbstrOut = StringDupAtoBstr( pBuffer );
3218 return S_OK;
3221 /******************************************************************************
3222 * VarBstrFromCy [OLEAUT32.113]
3224 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3225 /* FIXME */
3226 return E_NOTIMPL;
3230 /******************************************************************************
3231 * VarBstrFromDate32 [OLEAUT32.114]
3233 * The date is implemented using an 8 byte floating-point number.
3234 * Days are represented by whole numbers increments starting with 0.00 has
3235 * being December 30 1899, midnight.
3236 * The hours are expressed as the fractional part of the number.
3237 * December 30 1899 at midnight = 0.00
3238 * January 1 1900 at midnight = 2.00
3239 * January 4 1900 at 6 AM = 5.25
3240 * January 4 1900 at noon = 5.50
3241 * December 29 1899 at midnight = -1.00
3242 * December 18 1899 at midnight = -12.00
3243 * December 18 1899 at 6AM = -12.25
3244 * December 18 1899 at 6PM = -12.75
3245 * December 19 1899 at midnight = -11.00
3246 * The tm structure is as follows:
3247 * struct tm {
3248 * int tm_sec; seconds after the minute - [0,59]
3249 * int tm_min; minutes after the hour - [0,59]
3250 * int tm_hour; hours since midnight - [0,23]
3251 * int tm_mday; day of the month - [1,31]
3252 * int tm_mon; months since January - [0,11]
3253 * int tm_year; years
3254 * int tm_wday; days since Sunday - [0,6]
3255 * int tm_yday; days since January 1 - [0,365]
3256 * int tm_isdst; daylight savings time flag
3257 * };
3259 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3261 struct tm TM = {0,0,0,0,0,0,0,0,0};
3263 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3265 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3267 return E_INVALIDARG;
3270 if( dwFlags & VAR_DATEVALUEONLY )
3271 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3272 else if( dwFlags & VAR_TIMEVALUEONLY )
3273 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3274 else
3275 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3277 *pbstrOut = StringDupAtoBstr( pBuffer );
3279 return S_OK;
3282 /******************************************************************************
3283 * VarBstrFromBool32 [OLEAUT32.116]
3285 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3287 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3289 if( boolIn == VARIANT_FALSE )
3291 sprintf( pBuffer, "False" );
3293 else
3295 sprintf( pBuffer, "True" );
3298 *pbstrOut = StringDupAtoBstr( pBuffer );
3300 return S_OK;
3303 /******************************************************************************
3304 * VarBstrFromI132 [OLEAUT32.229]
3306 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3308 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3309 sprintf( pBuffer, "%d", cIn );
3310 *pbstrOut = StringDupAtoBstr( pBuffer );
3312 return S_OK;
3315 /******************************************************************************
3316 * VarBstrFromUI232 [OLEAUT32.230]
3318 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3320 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3321 sprintf( pBuffer, "%d", uiIn );
3322 *pbstrOut = StringDupAtoBstr( pBuffer );
3324 return S_OK;
3327 /******************************************************************************
3328 * VarBstrFromUI432 [OLEAUT32.231]
3330 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3332 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3333 sprintf( pBuffer, "%ld", ulIn );
3334 *pbstrOut = StringDupAtoBstr( pBuffer );
3336 return S_OK;
3339 /******************************************************************************
3340 * VarBoolFromUI132 [OLEAUT32.118]
3342 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3344 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3346 if( bIn == 0 )
3348 *pboolOut = VARIANT_FALSE;
3350 else
3352 *pboolOut = VARIANT_TRUE;
3355 return S_OK;
3358 /******************************************************************************
3359 * VarBoolFromI232 [OLEAUT32.119]
3361 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3363 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3365 if( sIn == 0 )
3367 *pboolOut = VARIANT_FALSE;
3369 else
3371 *pboolOut = VARIANT_TRUE;
3374 return S_OK;
3377 /******************************************************************************
3378 * VarBoolFromI432 [OLEAUT32.120]
3380 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3382 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3384 if( lIn == 0 )
3386 *pboolOut = VARIANT_FALSE;
3388 else
3390 *pboolOut = VARIANT_TRUE;
3393 return S_OK;
3396 /******************************************************************************
3397 * VarBoolFromR432 [OLEAUT32.121]
3399 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3401 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3403 if( fltIn == 0.0 )
3405 *pboolOut = VARIANT_FALSE;
3407 else
3409 *pboolOut = VARIANT_TRUE;
3412 return S_OK;
3415 /******************************************************************************
3416 * VarBoolFromR832 [OLEAUT32.122]
3418 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3420 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3422 if( dblIn == 0.0 )
3424 *pboolOut = VARIANT_FALSE;
3426 else
3428 *pboolOut = VARIANT_TRUE;
3431 return S_OK;
3434 /******************************************************************************
3435 * VarBoolFromDate32 [OLEAUT32.123]
3437 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3439 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3441 if( dateIn == 0.0 )
3443 *pboolOut = VARIANT_FALSE;
3445 else
3447 *pboolOut = VARIANT_TRUE;
3450 return S_OK;
3453 /******************************************************************************
3454 * VarBoolFromStr32 [OLEAUT32.125]
3456 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3458 HRESULT ret = S_OK;
3459 char* pNewString = NULL;
3461 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3463 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3465 if( pNewString == NULL || strlen( pNewString ) == 0 )
3467 ret = DISP_E_TYPEMISMATCH;
3470 if( ret == S_OK )
3472 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3474 *pboolOut = VARIANT_TRUE;
3476 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3478 *pboolOut = VARIANT_FALSE;
3480 else
3482 /* Try converting the string to a floating point number.
3484 double dValue = 0.0;
3485 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3486 if( res != S_OK )
3488 ret = DISP_E_TYPEMISMATCH;
3490 else if( dValue == 0.0 )
3492 *pboolOut = VARIANT_FALSE;
3494 else
3496 *pboolOut = VARIANT_TRUE;
3501 HeapFree( GetProcessHeap(), 0, pNewString );
3503 return ret;
3506 /******************************************************************************
3507 * VarBoolFromI132 [OLEAUT32.233]
3509 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3511 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3513 if( cIn == 0 )
3515 *pboolOut = VARIANT_FALSE;
3517 else
3519 *pboolOut = VARIANT_TRUE;
3522 return S_OK;
3525 /******************************************************************************
3526 * VarBoolFromUI232 [OLEAUT32.234]
3528 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3530 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3532 if( uiIn == 0 )
3534 *pboolOut = VARIANT_FALSE;
3536 else
3538 *pboolOut = VARIANT_TRUE;
3541 return S_OK;
3544 /******************************************************************************
3545 * VarBoolFromUI432 [OLEAUT32.235]
3547 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3549 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3551 if( ulIn == 0 )
3553 *pboolOut = VARIANT_FALSE;
3555 else
3557 *pboolOut = VARIANT_TRUE;
3560 return S_OK;
3563 /**********************************************************************
3564 * VarBoolFromCy32 [OLEAUT32.124]
3565 * Convert currency to boolean
3567 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3568 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3569 else *pboolOut = 0;
3571 return S_OK;
3574 /******************************************************************************
3575 * VarI1FromUI132 [OLEAUT32.244]
3577 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3579 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3581 /* Check range of value.
3583 if( bIn > CHAR_MAX )
3585 return DISP_E_OVERFLOW;
3588 *pcOut = (CHAR) bIn;
3590 return S_OK;
3593 /******************************************************************************
3594 * VarI1FromI232 [OLEAUT32.245]
3596 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3598 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3600 if( uiIn > CHAR_MAX )
3602 return DISP_E_OVERFLOW;
3605 *pcOut = (CHAR) uiIn;
3607 return S_OK;
3610 /******************************************************************************
3611 * VarI1FromI432 [OLEAUT32.246]
3613 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3615 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3617 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3619 return DISP_E_OVERFLOW;
3622 *pcOut = (CHAR) lIn;
3624 return S_OK;
3627 /******************************************************************************
3628 * VarI1FromR432 [OLEAUT32.247]
3630 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3632 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3634 fltIn = round( fltIn );
3635 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3637 return DISP_E_OVERFLOW;
3640 *pcOut = (CHAR) fltIn;
3642 return S_OK;
3645 /******************************************************************************
3646 * VarI1FromR832 [OLEAUT32.248]
3648 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3650 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3652 dblIn = round( dblIn );
3653 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3655 return DISP_E_OVERFLOW;
3658 *pcOut = (CHAR) dblIn;
3660 return S_OK;
3663 /******************************************************************************
3664 * VarI1FromDate32 [OLEAUT32.249]
3666 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3668 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3670 dateIn = round( dateIn );
3671 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3673 return DISP_E_OVERFLOW;
3676 *pcOut = (CHAR) dateIn;
3678 return S_OK;
3681 /******************************************************************************
3682 * VarI1FromStr32 [OLEAUT32.251]
3684 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3686 double dValue = 0.0;
3687 LPSTR pNewString = NULL;
3689 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3691 /* Check if we have a valid argument
3693 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3694 RemoveCharacterFromString( pNewString, "," );
3695 if( IsValidRealString( pNewString ) == FALSE )
3697 return DISP_E_TYPEMISMATCH;
3700 /* Convert the valid string to a floating point number.
3702 dValue = atof( pNewString );
3704 /* We don't need the string anymore so free it.
3706 HeapFree( GetProcessHeap(), 0, pNewString );
3708 /* Check range of value.
3710 dValue = round( dValue );
3711 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3713 return DISP_E_OVERFLOW;
3716 *pcOut = (CHAR) dValue;
3718 return S_OK;
3721 /******************************************************************************
3722 * VarI1FromBool32 [OLEAUT32.253]
3724 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3726 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3728 *pcOut = (CHAR) boolIn;
3730 return S_OK;
3733 /******************************************************************************
3734 * VarI1FromUI232 [OLEAUT32.254]
3736 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3738 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3740 if( uiIn > CHAR_MAX )
3742 return DISP_E_OVERFLOW;
3745 *pcOut = (CHAR) uiIn;
3747 return S_OK;
3750 /******************************************************************************
3751 * VarI1FromUI432 [OLEAUT32.255]
3753 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3755 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3757 if( ulIn > CHAR_MAX )
3759 return DISP_E_OVERFLOW;
3762 *pcOut = (CHAR) ulIn;
3764 return S_OK;
3767 /**********************************************************************
3768 * VarI1FromCy32 [OLEAUT32.250]
3769 * Convert currency to signed char
3771 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3772 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3774 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3776 *pcOut = (CHAR)t;
3777 return S_OK;
3780 /******************************************************************************
3781 * VarUI2FromUI132 [OLEAUT32.257]
3783 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3785 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3787 *puiOut = (USHORT) bIn;
3789 return S_OK;
3792 /******************************************************************************
3793 * VarUI2FromI232 [OLEAUT32.258]
3795 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3797 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3799 if( uiIn < UI2_MIN )
3801 return DISP_E_OVERFLOW;
3804 *puiOut = (USHORT) uiIn;
3806 return S_OK;
3809 /******************************************************************************
3810 * VarUI2FromI432 [OLEAUT32.259]
3812 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3814 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3816 if( lIn < UI2_MIN || lIn > UI2_MAX )
3818 return DISP_E_OVERFLOW;
3821 *puiOut = (USHORT) lIn;
3823 return S_OK;
3826 /******************************************************************************
3827 * VarUI2FromR432 [OLEAUT32.260]
3829 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3831 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3833 fltIn = round( fltIn );
3834 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3836 return DISP_E_OVERFLOW;
3839 *puiOut = (USHORT) fltIn;
3841 return S_OK;
3844 /******************************************************************************
3845 * VarUI2FromR832 [OLEAUT32.261]
3847 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3849 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3851 dblIn = round( dblIn );
3852 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3854 return DISP_E_OVERFLOW;
3857 *puiOut = (USHORT) dblIn;
3859 return S_OK;
3862 /******************************************************************************
3863 * VarUI2FromDate32 [OLEAUT32.262]
3865 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3867 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3869 dateIn = round( dateIn );
3870 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3872 return DISP_E_OVERFLOW;
3875 *puiOut = (USHORT) dateIn;
3877 return S_OK;
3880 /******************************************************************************
3881 * VarUI2FromStr32 [OLEAUT32.264]
3883 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3885 double dValue = 0.0;
3886 LPSTR pNewString = NULL;
3888 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3890 /* Check if we have a valid argument
3892 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3893 RemoveCharacterFromString( pNewString, "," );
3894 if( IsValidRealString( pNewString ) == FALSE )
3896 return DISP_E_TYPEMISMATCH;
3899 /* Convert the valid string to a floating point number.
3901 dValue = atof( pNewString );
3903 /* We don't need the string anymore so free it.
3905 HeapFree( GetProcessHeap(), 0, pNewString );
3907 /* Check range of value.
3909 dValue = round( dValue );
3910 if( dValue < UI2_MIN || dValue > UI2_MAX )
3912 return DISP_E_OVERFLOW;
3915 *puiOut = (USHORT) dValue;
3917 return S_OK;
3920 /******************************************************************************
3921 * VarUI2FromBool32 [OLEAUT32.266]
3923 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3925 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3927 *puiOut = (USHORT) boolIn;
3929 return S_OK;
3932 /******************************************************************************
3933 * VarUI2FromI132 [OLEAUT32.267]
3935 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3937 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3939 *puiOut = (USHORT) cIn;
3941 return S_OK;
3944 /******************************************************************************
3945 * VarUI2FromUI432 [OLEAUT32.268]
3947 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3949 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3951 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3953 return DISP_E_OVERFLOW;
3956 *puiOut = (USHORT) ulIn;
3958 return S_OK;
3961 /******************************************************************************
3962 * VarUI4FromStr32 [OLEAUT32.277]
3964 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3966 double dValue = 0.0;
3967 LPSTR pNewString = NULL;
3969 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3971 /* Check if we have a valid argument
3973 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3974 RemoveCharacterFromString( pNewString, "," );
3975 if( IsValidRealString( pNewString ) == FALSE )
3977 return DISP_E_TYPEMISMATCH;
3980 /* Convert the valid string to a floating point number.
3982 dValue = atof( pNewString );
3984 /* We don't need the string anymore so free it.
3986 HeapFree( GetProcessHeap(), 0, pNewString );
3988 /* Check range of value.
3990 dValue = round( dValue );
3991 if( dValue < UI4_MIN || dValue > UI4_MAX )
3993 return DISP_E_OVERFLOW;
3996 *pulOut = (ULONG) dValue;
3998 return S_OK;
4001 /**********************************************************************
4002 * VarUI2FromCy32 [OLEAUT32.263]
4003 * Convert currency to unsigned short
4005 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4006 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4008 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4010 *pusOut = (USHORT)t;
4012 return S_OK;
4015 /******************************************************************************
4016 * VarUI4FromUI132 [OLEAUT32.270]
4018 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4020 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4022 *pulOut = (USHORT) bIn;
4024 return S_OK;
4027 /******************************************************************************
4028 * VarUI4FromI232 [OLEAUT32.271]
4030 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4032 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4034 if( uiIn < UI4_MIN )
4036 return DISP_E_OVERFLOW;
4039 *pulOut = (ULONG) uiIn;
4041 return S_OK;
4044 /******************************************************************************
4045 * VarUI4FromI432 [OLEAUT32.272]
4047 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4049 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4051 if( lIn < UI4_MIN )
4053 return DISP_E_OVERFLOW;
4056 *pulOut = (ULONG) lIn;
4058 return S_OK;
4061 /******************************************************************************
4062 * VarUI4FromR432 [OLEAUT32.273]
4064 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4066 fltIn = round( fltIn );
4067 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4069 return DISP_E_OVERFLOW;
4072 *pulOut = (ULONG) fltIn;
4074 return S_OK;
4077 /******************************************************************************
4078 * VarUI4FromR832 [OLEAUT32.274]
4080 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4082 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4084 dblIn = round( dblIn );
4085 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4087 return DISP_E_OVERFLOW;
4090 *pulOut = (ULONG) dblIn;
4092 return S_OK;
4095 /******************************************************************************
4096 * VarUI4FromDate32 [OLEAUT32.275]
4098 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4100 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4102 dateIn = round( dateIn );
4103 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4105 return DISP_E_OVERFLOW;
4108 *pulOut = (ULONG) dateIn;
4110 return S_OK;
4113 /******************************************************************************
4114 * VarUI4FromBool32 [OLEAUT32.279]
4116 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4118 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4120 *pulOut = (ULONG) boolIn;
4122 return S_OK;
4125 /******************************************************************************
4126 * VarUI4FromI132 [OLEAUT32.280]
4128 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4130 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4132 *pulOut = (ULONG) cIn;
4134 return S_OK;
4137 /******************************************************************************
4138 * VarUI4FromUI232 [OLEAUT32.281]
4140 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4142 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4144 *pulOut = (ULONG) uiIn;
4146 return S_OK;
4149 /**********************************************************************
4150 * VarUI4FromCy32 [OLEAUT32.276]
4151 * Convert currency to unsigned long
4153 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4154 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4156 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4158 *pulOut = (ULONG)t;
4160 return S_OK;
4163 /**********************************************************************
4164 * VarCyFromUI132 [OLEAUT32.98]
4165 * Convert unsigned char to currency
4167 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4168 pcyOut->s.Hi = 0;
4169 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4171 return S_OK;
4174 /**********************************************************************
4175 * VarCyFromI232 [OLEAUT32.99]
4176 * Convert signed short to currency
4178 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4179 if (sIn < 0) pcyOut->s.Hi = -1;
4180 else pcyOut->s.Hi = 0;
4181 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4183 return S_OK;
4186 /**********************************************************************
4187 * VarCyFromI432 [OLEAUT32.100]
4188 * Convert signed long to currency
4190 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4191 double t = (double)lIn * (double)10000;
4192 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4193 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4194 if (lIn < 0) pcyOut->s.Hi--;
4196 return S_OK;
4199 /**********************************************************************
4200 * VarCyFromR432 [OLEAUT32.101]
4201 * Convert float to currency
4203 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4204 double t = round((double)fltIn * (double)10000);
4205 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4206 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4207 if (fltIn < 0) pcyOut->s.Hi--;
4209 return S_OK;
4212 /**********************************************************************
4213 * VarCyFromR832 [OLEAUT32.102]
4214 * Convert double to currency
4216 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4217 double t = round(dblIn * (double)10000);
4218 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4219 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4220 if (dblIn < 0) pcyOut->s.Hi--;
4222 return S_OK;
4225 /**********************************************************************
4226 * VarCyFromDate32 [OLEAUT32.103]
4227 * Convert date to currency
4229 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4230 double t = round((double)dateIn * (double)10000);
4231 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4232 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4233 if (dateIn < 0) pcyOut->s.Hi--;
4235 return S_OK;
4238 /**********************************************************************
4239 * VarCyFromDate32 [OLEAUT32.104]
4241 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4242 /* FIXME */
4243 return E_NOTIMPL;
4247 /**********************************************************************
4248 * VarCyFromBool32 [OLEAUT32.106]
4249 * Convert boolean to currency
4251 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4252 if (boolIn < 0) pcyOut->s.Hi = -1;
4253 else pcyOut->s.Hi = 0;
4254 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4256 return S_OK;
4259 /**********************************************************************
4260 * VarCyFromI132 [OLEAUT32.225]
4261 * Convert signed char to currency
4263 HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4264 if (cIn < 0) pcyOut->s.Hi = -1;
4265 else pcyOut->s.Hi = 0;
4266 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4268 return S_OK;
4271 /**********************************************************************
4272 * VarCyFromUI232 [OLEAUT32.226]
4273 * Convert unsigned short to currency
4275 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4276 pcyOut->s.Hi = 0;
4277 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4279 return S_OK;
4282 /**********************************************************************
4283 * VarCyFromUI432 [OLEAUT32.227]
4284 * Convert unsigned long to currency
4286 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4287 double t = (double)ulIn * (double)10000;
4288 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4289 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4291 return S_OK;
4295 /**********************************************************************
4296 * DosDateTimeToVariantTime [OLEAUT32.14]
4297 * Convert dos representation of time to the date and time representation
4298 * stored in a variant.
4300 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4301 DATE *pvtime)
4303 struct tm t;
4305 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4307 t.tm_sec = (wDosTime & 0x001f) * 2;
4308 t.tm_min = (wDosTime & 0x07e0) >> 5;
4309 t.tm_hour = (wDosTime & 0xf800) >> 11;
4311 t.tm_mday = (wDosDate & 0x001f);
4312 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4313 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4315 return TmToDATE( &t, pvtime );