Account for the trailing NULL in GetLogicalDriveStringsA.
[wine.git] / dlls / oleaut32 / variant.c
blobb3a81d89657c79d59b715a8097b83664814a43da
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 "windef.h"
24 #include "oleauto.h"
25 #include "heap.h"
26 #include "debugtools.h"
27 #include "winerror.h"
28 #include "parsedt.h"
30 DEFAULT_DEBUG_CHANNEL(ole)
32 #include <string.h>
33 #include <stdlib.h>
34 #include <math.h>
35 #include <time.h>
37 #ifdef HAVE_FLOAT_H
38 # include <float.h>
39 #endif
41 #ifndef FLT_MAX
42 # ifdef MAXFLOAT
43 # define FLT_MAX MAXFLOAT
44 # else
45 # error "Can't find #define for MAXFLOAT/FLT_MAX"
46 # endif
47 #endif
49 #undef CHAR_MAX
50 #undef CHAR_MIN
51 static const char CHAR_MAX = 127;
52 static const char CHAR_MIN = -128;
53 static const BYTE UI1_MAX = 255;
54 static const BYTE UI1_MIN = 0;
55 static const unsigned short UI2_MAX = 65535;
56 static const unsigned short UI2_MIN = 0;
57 static const short I2_MAX = 32767;
58 static const short I2_MIN = -32768;
59 static const unsigned long UI4_MAX = 4294967295U;
60 static const unsigned long UI4_MIN = 0;
61 static const long I4_MAX = 2147483647;
62 static const long I4_MIN = -(2147483648U);
63 static const DATE DATE_MIN = -657434;
64 static const DATE DATE_MAX = 2958465;
67 /* This mask is used to set a flag in wReserved1 of
68 * the VARIANTARG structure. The flag indicates if
69 * the API function is using an inner variant or not.
71 #define PROCESSING_INNER_VARIANT 0x0001
73 /* General use buffer.
75 #define BUFFER_MAX 1024
76 static char pBuffer[BUFFER_MAX];
79 * Note a leap year is one that is a multiple of 4
80 * but not of a 100. Except if it is a multiple of
81 * 400 then it is a leap year.
83 /* According to postgeSQL date parsing functions there is
84 * a leap year when this expression is true.
85 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
86 * So according to this there is 365.2515 days in one year.
87 * One + every four years: 1/4 -> 365.25
88 * One - every 100 years: 1/100 -> 365.001
89 * One + every 400 years: 1/400 -> 365.0025
91 static const double DAYS_IN_ONE_YEAR = 365.2515;
95 /******************************************************************************
96 * DateTimeStringToTm [INTERNAL]
98 * Converts a string representation of a date and/or time to a tm structure.
100 * Note this function uses the postgresql date parsing functions found
101 * in the parsedt.c file.
103 * Returns TRUE if successfull.
105 * Note: This function does not parse the day of the week,
106 * daylight savings time. It will only fill the followin fields in
107 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
109 ******************************************************************************/
110 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
112 BOOL res = FALSE;
113 double fsec;
114 int tzp;
115 int dtype;
116 int nf;
117 char *field[MAXDATEFIELDS];
118 int ftype[MAXDATEFIELDS];
119 char lowstr[MAXDATELEN + 1];
120 char* strDateTime = NULL;
122 /* Convert the string to ASCII since this is the only format
123 * postgesql can handle.
125 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
127 if( strDateTime != NULL )
129 /* Make sure we don't go over the maximum length
130 * accepted by postgesql.
132 if( strlen( strDateTime ) <= MAXDATELEN )
134 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
136 if( lcid & VAR_DATEVALUEONLY )
138 /* Get the date information.
139 * It returns 0 if date information was
140 * present and 1 if only time information was present.
141 * -1 if an error occures.
143 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
145 /* Eliminate the time information since we
146 * were asked to get date information only.
148 pTm->tm_sec = 0;
149 pTm->tm_min = 0;
150 pTm->tm_hour = 0;
151 res = TRUE;
154 if( lcid & VAR_TIMEVALUEONLY )
156 /* Get time information only.
158 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
160 res = TRUE;
163 else
165 /* Get both date and time information.
166 * It returns 0 if date information was
167 * present and 1 if only time information was present.
168 * -1 if an error occures.
170 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
172 res = TRUE;
177 HeapFree( GetProcessHeap(), 0, strDateTime );
180 return res;
188 /******************************************************************************
189 * TmToDATE [INTERNAL]
191 * The date is implemented using an 8 byte floating-point number.
192 * Days are represented by whole numbers increments starting with 0.00 has
193 * being December 30 1899, midnight.
194 * The hours are expressed as the fractional part of the number.
195 * December 30 1899 at midnight = 0.00
196 * January 1 1900 at midnight = 2.00
197 * January 4 1900 at 6 AM = 5.25
198 * January 4 1900 at noon = 5.50
199 * December 29 1899 at midnight = -1.00
200 * December 18 1899 at midnight = -12.00
201 * December 18 1899 at 6AM = -12.25
202 * December 18 1899 at 6PM = -12.75
203 * December 19 1899 at midnight = -11.00
204 * The tm structure is as follows:
205 * struct tm {
206 * int tm_sec; seconds after the minute - [0,59]
207 * int tm_min; minutes after the hour - [0,59]
208 * int tm_hour; hours since midnight - [0,23]
209 * int tm_mday; day of the month - [1,31]
210 * int tm_mon; months since January - [0,11]
211 * int tm_year; years
212 * int tm_wday; days since Sunday - [0,6]
213 * int tm_yday; days since January 1 - [0,365]
214 * int tm_isdst; daylight savings time flag
215 * };
217 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
218 * and tm_isdst fields of the tm structure. And only converts years
219 * after 1900.
221 * Returns TRUE if successfull.
223 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
225 if( (pTm->tm_year - 1900) >= 0 )
227 int leapYear = 0;
229 /* Start at 1. This is the way DATE is defined.
230 * January 1, 1900 at Midnight is 1.00.
231 * January 1, 1900 at 6AM is 1.25.
232 * and so on.
234 *pDateOut = 1;
236 /* Add the number of days corresponding to
237 * tm_year.
239 *pDateOut += (pTm->tm_year - 1900) * 365;
241 /* Add the leap days in the previous years between now and 1900.
242 * Note a leap year is one that is a multiple of 4
243 * but not of a 100. Except if it is a multiple of
244 * 400 then it is a leap year.
246 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
247 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
248 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
250 /* Set the leap year flag if the
251 * current year specified by tm_year is a
252 * leap year. This will be used to add a day
253 * to the day count.
255 if( isleap( pTm->tm_year ) )
256 leapYear = 1;
258 /* Add the number of days corresponding to
259 * the month.
261 switch( pTm->tm_mon )
263 case 2:
264 *pDateOut += 31;
265 break;
266 case 3:
267 *pDateOut += ( 59 + leapYear );
268 break;
269 case 4:
270 *pDateOut += ( 90 + leapYear );
271 break;
272 case 5:
273 *pDateOut += ( 120 + leapYear );
274 break;
275 case 6:
276 *pDateOut += ( 151 + leapYear );
277 break;
278 case 7:
279 *pDateOut += ( 181 + leapYear );
280 break;
281 case 8:
282 *pDateOut += ( 212 + leapYear );
283 break;
284 case 9:
285 *pDateOut += ( 243 + leapYear );
286 break;
287 case 10:
288 *pDateOut += ( 273 + leapYear );
289 break;
290 case 11:
291 *pDateOut += ( 304 + leapYear );
292 break;
293 case 12:
294 *pDateOut += ( 334 + leapYear );
295 break;
297 /* Add the number of days in this month.
299 *pDateOut += pTm->tm_mday;
301 /* Add the number of seconds, minutes, and hours
302 * to the DATE. Note these are the fracionnal part
303 * of the DATE so seconds / number of seconds in a day.
305 *pDateOut += pTm->tm_hour / 24.0;
306 *pDateOut += pTm->tm_min / 1440.0;
307 *pDateOut += pTm->tm_sec / 86400.0;
308 return TRUE;
310 return FALSE;
313 /******************************************************************************
314 * DateToTm [INTERNAL]
316 * This function converst a windows DATE to a tm structure.
318 * It does not fill all the fields of the tm structure.
319 * Here is a list of the fields that are filled:
320 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
322 * Note this function does not support dates before the January 1, 1900
323 * or ( dateIn < 2.0 ).
325 * Returns TRUE if successfull.
327 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
329 /* Do not process dates smaller than January 1, 1900.
330 * Which corresponds to 2.0 in the windows DATE format.
332 if( dateIn >= 2.0 )
334 double decimalPart = 0.0;
335 double wholePart = 0.0;
337 memset(pTm,0,sizeof(*pTm));
339 /* Because of the nature of DATE format witch
340 * associates 2.0 to January 1, 1900. We will
341 * remove 1.0 from the whole part of the DATE
342 * so that in the following code 1.0
343 * will correspond to January 1, 1900.
344 * This simplyfies the processing of the DATE value.
346 dateIn -= 1.0;
348 wholePart = (double) floor( dateIn );
349 decimalPart = fmod( dateIn, wholePart );
351 if( !(lcid & VAR_TIMEVALUEONLY) )
353 int nDay = 0;
354 int leapYear = 0;
355 double yearsSince1900 = 0;
356 /* Start at 1900, this where the DATE time 0.0 starts.
358 pTm->tm_year = 1900;
359 /* find in what year the day in the "wholePart" falls into.
360 * add the value to the year field.
362 yearsSince1900 = floor( wholePart / DAYS_IN_ONE_YEAR );
363 pTm->tm_year += yearsSince1900;
364 /* determine if this is a leap year.
366 if( isleap( pTm->tm_year ) )
367 leapYear = 1;
368 /* find what day of that year does the "wholePart" corresponds to.
369 * Note: nDay is in [1-366] format
371 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
372 /* Set the tm_yday value.
373 * Note: The day is must be converted from [1-366] to [0-365]
375 /*pTm->tm_yday = nDay - 1;*/
376 /* find which mount this day corresponds to.
378 if( nDay <= 31 )
380 pTm->tm_mday = nDay;
381 pTm->tm_mon = 0;
383 else if( nDay <= ( 59 + leapYear ) )
385 pTm->tm_mday = nDay - 31;
386 pTm->tm_mon = 1;
388 else if( nDay <= ( 90 + leapYear ) )
390 pTm->tm_mday = nDay - ( 59 + leapYear );
391 pTm->tm_mon = 2;
393 else if( nDay <= ( 120 + leapYear ) )
395 pTm->tm_mday = nDay - ( 90 + leapYear );
396 pTm->tm_mon = 3;
398 else if( nDay <= ( 151 + leapYear ) )
400 pTm->tm_mday = nDay - ( 120 + leapYear );
401 pTm->tm_mon = 4;
403 else if( nDay <= ( 181 + leapYear ) )
405 pTm->tm_mday = nDay - ( 151 + leapYear );
406 pTm->tm_mon = 5;
408 else if( nDay <= ( 212 + leapYear ) )
410 pTm->tm_mday = nDay - ( 181 + leapYear );
411 pTm->tm_mon = 6;
413 else if( nDay <= ( 243 + leapYear ) )
415 pTm->tm_mday = nDay - ( 212 + leapYear );
416 pTm->tm_mon = 7;
418 else if( nDay <= ( 273 + leapYear ) )
420 pTm->tm_mday = nDay - ( 243 + leapYear );
421 pTm->tm_mon = 8;
423 else if( nDay <= ( 304 + leapYear ) )
425 pTm->tm_mday = nDay - ( 273 + leapYear );
426 pTm->tm_mon = 9;
428 else if( nDay <= ( 334 + leapYear ) )
430 pTm->tm_mday = nDay - ( 304 + leapYear );
431 pTm->tm_mon = 10;
433 else if( nDay <= ( 365 + leapYear ) )
435 pTm->tm_mday = nDay - ( 334 + leapYear );
436 pTm->tm_mon = 11;
439 if( !(lcid & VAR_DATEVALUEONLY) )
441 /* find the number of seconds in this day.
442 * fractional part times, hours, minutes, seconds.
444 pTm->tm_hour = (int) ( decimalPart * 24 );
445 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
446 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
448 return TRUE;
450 return FALSE;
455 /******************************************************************************
456 * SizeOfVariantData [INTERNAL]
458 * This function finds the size of the data referenced by a Variant based
459 * the type "vt" of the Variant.
461 static int SizeOfVariantData( VARIANT* parg )
463 int size = 0;
464 switch( parg->vt & VT_TYPEMASK )
466 case( VT_I2 ):
467 size = sizeof(short);
468 break;
469 case( VT_INT ):
470 size = sizeof(int);
471 break;
472 case( VT_I4 ):
473 size = sizeof(long);
474 break;
475 case( VT_UI1 ):
476 size = sizeof(BYTE);
477 break;
478 case( VT_UI2 ):
479 size = sizeof(unsigned short);
480 break;
481 case( VT_UINT ):
482 size = sizeof(unsigned int);
483 break;
484 case( VT_UI4 ):
485 size = sizeof(unsigned long);
486 break;
487 case( VT_R4 ):
488 size = sizeof(float);
489 break;
490 case( VT_R8 ):
491 size = sizeof(double);
492 break;
493 case( VT_DATE ):
494 size = sizeof(DATE);
495 break;
496 case( VT_BOOL ):
497 size = sizeof(VARIANT_BOOL);
498 break;
499 case( VT_BSTR ):
500 size = sizeof(void*);
501 break;
502 case( VT_CY ):
503 case( VT_DISPATCH ):
504 case( VT_UNKNOWN ):
505 case( VT_DECIMAL ):
506 default:
507 FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
508 break;
511 return size;
513 /******************************************************************************
514 * StringDupAtoBstr [INTERNAL]
517 static BSTR StringDupAtoBstr( char* strIn )
519 BSTR bstr = NULL;
520 OLECHAR* pNewString = NULL;
521 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
522 bstr = SysAllocString( pNewString );
523 HeapFree( GetProcessHeap(), 0, pNewString );
524 return bstr;
527 /******************************************************************************
528 * round [INTERNAL]
530 * Round the double value to the nearest integer value.
532 static double round( double d )
534 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
535 BOOL bEvenNumber = FALSE;
536 int nSign = 0;
538 /* Save the sign of the number
540 nSign = (d >= 0.0) ? 1 : -1;
541 d = fabs( d );
543 /* Remove the decimals.
545 integerValue = floor( d );
547 /* Set the Even flag. This is used to round the number when
548 * the decimals are exactly 1/2. If the integer part is
549 * odd the number is rounded up. If the integer part
550 * is even the number is rounded down. Using this method
551 * numbers are rounded up|down half the time.
553 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
555 /* Remove the integral part of the number.
557 decimals = d - integerValue;
559 /* Note: Ceil returns the smallest integer that is greater that x.
560 * and floor returns the largest integer that is less than or equal to x.
562 if( decimals > 0.5 )
564 /* If the decimal part is greater than 1/2
566 roundedValue = ceil( d );
568 else if( decimals < 0.5 )
570 /* If the decimal part is smaller than 1/2
572 roundedValue = floor( d );
574 else
576 /* the decimals are exactly 1/2 so round according to
577 * the bEvenNumber flag.
579 if( bEvenNumber )
581 roundedValue = floor( d );
583 else
585 roundedValue = ceil( d );
589 return roundedValue * nSign;
592 /******************************************************************************
593 * RemoveCharacterFromString [INTERNAL]
595 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
597 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
599 LPSTR pNewString = NULL;
600 LPSTR strToken = NULL;
603 /* Check if we have a valid argument
605 if( str != NULL )
607 pNewString = strdup( str );
608 str[0] = '\0';
609 strToken = strtok( pNewString, strOfCharToRemove );
610 while( strToken != NULL ) {
611 strcat( str, strToken );
612 strToken = strtok( NULL, strOfCharToRemove );
614 free( pNewString );
616 return;
619 /******************************************************************************
620 * GetValidRealString [INTERNAL]
622 * Checks if the string is of proper format to be converted to a real value.
624 static BOOL IsValidRealString( LPSTR strRealString )
626 /* Real values that have a decimal point are required to either have
627 * digits before or after the decimal point. We will assume that
628 * we do not have any digits at either position. If we do encounter
629 * some we will disable this flag.
631 BOOL bDigitsRequired = TRUE;
632 /* Processed fields in the string representation of the real number.
634 BOOL bWhiteSpaceProcessed = FALSE;
635 BOOL bFirstSignProcessed = FALSE;
636 BOOL bFirstDigitsProcessed = FALSE;
637 BOOL bDecimalPointProcessed = FALSE;
638 BOOL bSecondDigitsProcessed = FALSE;
639 BOOL bExponentProcessed = FALSE;
640 BOOL bSecondSignProcessed = FALSE;
641 BOOL bThirdDigitsProcessed = FALSE;
642 /* Assume string parameter "strRealString" is valid and try to disprove it.
644 BOOL bValidRealString = TRUE;
646 /* Used to count the number of tokens in the "strRealString".
648 LPSTR strToken = NULL;
649 int nTokens = 0;
650 LPSTR pChar = NULL;
652 /* Check if we have a valid argument
654 if( strRealString == NULL )
656 bValidRealString = FALSE;
659 if( bValidRealString == TRUE )
661 /* Make sure we only have ONE token in the string.
663 strToken = strtok( strRealString, " " );
664 while( strToken != NULL ) {
665 nTokens++;
666 strToken = strtok( NULL, " " );
669 if( nTokens != 1 )
671 bValidRealString = FALSE;
676 /* Make sure this token contains only valid characters.
677 * The string argument to atof has the following form:
678 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
679 * Whitespace consists of space and|or <TAB> characters, which are ignored.
680 * Sign is either plus '+' or minus '-'.
681 * Digits are one or more decimal digits.
682 * Note: If no digits appear before the decimal point, at least one must
683 * appear after the decimal point.
684 * The decimal digits may be followed by an exponent.
685 * An Exponent consists of an introductory letter ( D, d, E, or e) and
686 * an optionally signed decimal integer.
688 pChar = strRealString;
689 while( bValidRealString == TRUE && *pChar != '\0' )
691 switch( *pChar )
693 /* If whitespace...
695 case ' ':
696 case '\t':
697 if( bWhiteSpaceProcessed ||
698 bFirstSignProcessed ||
699 bFirstDigitsProcessed ||
700 bDecimalPointProcessed ||
701 bSecondDigitsProcessed ||
702 bExponentProcessed ||
703 bSecondSignProcessed ||
704 bThirdDigitsProcessed )
706 bValidRealString = FALSE;
708 break;
709 /* If sign...
711 case '+':
712 case '-':
713 if( bFirstSignProcessed == FALSE )
715 if( bFirstDigitsProcessed ||
716 bDecimalPointProcessed ||
717 bSecondDigitsProcessed ||
718 bExponentProcessed ||
719 bSecondSignProcessed ||
720 bThirdDigitsProcessed )
722 bValidRealString = FALSE;
724 bWhiteSpaceProcessed = TRUE;
725 bFirstSignProcessed = TRUE;
727 else if( bSecondSignProcessed == FALSE )
729 /* Note: The exponent must be present in
730 * order to accept the second sign...
732 if( bExponentProcessed == FALSE ||
733 bThirdDigitsProcessed ||
734 bDigitsRequired )
736 bValidRealString = FALSE;
738 bFirstSignProcessed = TRUE;
739 bWhiteSpaceProcessed = TRUE;
740 bFirstDigitsProcessed = TRUE;
741 bDecimalPointProcessed = TRUE;
742 bSecondDigitsProcessed = TRUE;
743 bSecondSignProcessed = TRUE;
745 break;
747 /* If decimals...
749 case '0':
750 case '1':
751 case '2':
752 case '3':
753 case '4':
754 case '5':
755 case '6':
756 case '7':
757 case '8':
758 case '9':
759 if( bFirstDigitsProcessed == FALSE )
761 if( bDecimalPointProcessed ||
762 bSecondDigitsProcessed ||
763 bExponentProcessed ||
764 bSecondSignProcessed ||
765 bThirdDigitsProcessed )
767 bValidRealString = FALSE;
769 bFirstSignProcessed = TRUE;
770 bWhiteSpaceProcessed = TRUE;
771 /* We have found some digits before the decimal point
772 * so disable the "Digits required" flag.
774 bDigitsRequired = FALSE;
776 else if( bSecondDigitsProcessed == FALSE )
778 if( bExponentProcessed ||
779 bSecondSignProcessed ||
780 bThirdDigitsProcessed )
782 bValidRealString = FALSE;
784 bFirstSignProcessed = TRUE;
785 bWhiteSpaceProcessed = TRUE;
786 bFirstDigitsProcessed = TRUE;
787 bDecimalPointProcessed = TRUE;
788 /* We have found some digits after the decimal point
789 * so disable the "Digits required" flag.
791 bDigitsRequired = FALSE;
793 else if( bThirdDigitsProcessed == FALSE )
795 /* Getting here means everything else should be processed.
796 * If we get anything else than a decimal following this
797 * digit it will be flagged by the other cases, so
798 * we do not really need to do anything in here.
801 break;
802 /* If DecimalPoint...
804 case '.':
805 if( bDecimalPointProcessed ||
806 bSecondDigitsProcessed ||
807 bExponentProcessed ||
808 bSecondSignProcessed ||
809 bThirdDigitsProcessed )
811 bValidRealString = FALSE;
813 bFirstSignProcessed = TRUE;
814 bWhiteSpaceProcessed = TRUE;
815 bFirstDigitsProcessed = TRUE;
816 bDecimalPointProcessed = TRUE;
817 break;
818 /* If Exponent...
820 case 'e':
821 case 'E':
822 case 'd':
823 case 'D':
824 if( bExponentProcessed ||
825 bSecondSignProcessed ||
826 bThirdDigitsProcessed ||
827 bDigitsRequired )
829 bValidRealString = FALSE;
831 bFirstSignProcessed = TRUE;
832 bWhiteSpaceProcessed = TRUE;
833 bFirstDigitsProcessed = TRUE;
834 bDecimalPointProcessed = TRUE;
835 bSecondDigitsProcessed = TRUE;
836 bExponentProcessed = TRUE;
837 break;
838 default:
839 bValidRealString = FALSE;
840 break;
842 /* Process next character.
844 pChar++;
847 /* If the required digits were not present we have an invalid
848 * string representation of a real number.
850 if( bDigitsRequired == TRUE )
852 bValidRealString = FALSE;
855 return bValidRealString;
859 /******************************************************************************
860 * Coerce [INTERNAL]
862 * This function dispatches execution to the proper conversion API
863 * to do the necessary coercion.
865 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
867 HRESULT res = S_OK;
868 unsigned short vtFrom = 0;
869 vtFrom = ps->vt & VT_TYPEMASK;
871 /* Note: Since "long" and "int" values both have 4 bytes and are both signed integers
872 * "int" will be treated as "long" in the following code.
873 * The same goes for there unsigned versions.
876 switch( vt )
879 case( VT_EMPTY ):
880 res = VariantClear( pd );
881 break;
882 case( VT_NULL ):
883 res = VariantClear( pd );
884 if( res == S_OK )
886 pd->vt = VT_NULL;
888 break;
889 case( VT_I1 ):
890 switch( vtFrom )
892 case( VT_I1 ):
893 res = VariantCopy( pd, ps );
894 break;
895 case( VT_I2 ):
896 res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
897 break;
898 case( VT_INT ):
899 case( VT_I4 ):
900 res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
901 break;
902 case( VT_UI1 ):
903 res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
904 break;
905 case( VT_UI2 ):
906 res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
907 break;
908 case( VT_UINT ):
909 case( VT_UI4 ):
910 res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
911 break;
912 case( VT_R4 ):
913 res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
914 break;
915 case( VT_R8 ):
916 res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
917 break;
918 case( VT_DATE ):
919 res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
920 break;
921 case( VT_BOOL ):
922 res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
923 break;
924 case( VT_BSTR ):
925 res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
926 break;
927 case( VT_CY ):
928 res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
929 case( VT_DISPATCH ):
930 /*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
931 case( VT_UNKNOWN ):
932 /*res = VarI1From32( ps->u.lVal, &(pd->u.cVal) );*/
933 case( VT_DECIMAL ):
934 /*res = VarI1FromDec32( ps->u.decVal, &(pd->u.cVal) );*/
935 default:
936 res = DISP_E_TYPEMISMATCH;
937 FIXME("Coercion from %d to %d\n", vtFrom, vt );
938 break;
940 break;
942 case( VT_I2 ):
943 switch( vtFrom )
945 case( VT_I1 ):
946 res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
947 break;
948 case( VT_I2 ):
949 res = VariantCopy( pd, ps );
950 break;
951 case( VT_INT ):
952 case( VT_I4 ):
953 res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
954 break;
955 case( VT_UI1 ):
956 res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
957 break;
958 case( VT_UI2 ):
959 res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
960 break;
961 case( VT_UINT ):
962 case( VT_UI4 ):
963 res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
964 break;
965 case( VT_R4 ):
966 res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
967 break;
968 case( VT_R8 ):
969 res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
970 break;
971 case( VT_DATE ):
972 res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
973 break;
974 case( VT_BOOL ):
975 res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
976 break;
977 case( VT_BSTR ):
978 res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
979 break;
980 case( VT_CY ):
981 res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
982 case( VT_DISPATCH ):
983 /*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
984 case( VT_UNKNOWN ):
985 /*res = VarI2From32( ps->u.lVal, &(pd->u.iVal) );*/
986 case( VT_DECIMAL ):
987 /*res = VarI2FromDec32( ps->u.deiVal, &(pd->u.iVal) );*/
988 default:
989 res = DISP_E_TYPEMISMATCH;
990 FIXME("Coercion from %d to %d\n", vtFrom, vt );
991 break;
993 break;
995 case( VT_INT ):
996 case( VT_I4 ):
997 switch( vtFrom )
999 case( VT_I1 ):
1000 res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1001 break;
1002 case( VT_I2 ):
1003 res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1004 break;
1005 case( VT_INT ):
1006 case( VT_I4 ):
1007 res = VariantCopy( pd, ps );
1008 break;
1009 case( VT_UI1 ):
1010 res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1011 break;
1012 case( VT_UI2 ):
1013 res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1014 break;
1015 case( VT_UINT ):
1016 case( VT_UI4 ):
1017 res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1018 break;
1019 case( VT_R4 ):
1020 res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1021 break;
1022 case( VT_R8 ):
1023 res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1024 break;
1025 case( VT_DATE ):
1026 res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1027 break;
1028 case( VT_BOOL ):
1029 res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1030 break;
1031 case( VT_BSTR ):
1032 res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1033 break;
1034 case( VT_CY ):
1035 res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1036 case( VT_DISPATCH ):
1037 /*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1038 case( VT_UNKNOWN ):
1039 /*res = VarI4From32( ps->u.lVal, &(pd->u.lVal) );*/
1040 case( VT_DECIMAL ):
1041 /*res = VarI4FromDec32( ps->u.deiVal, &(pd->u.lVal) );*/
1042 default:
1043 res = DISP_E_TYPEMISMATCH;
1044 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1045 break;
1047 break;
1049 case( VT_UI1 ):
1050 switch( vtFrom )
1052 case( VT_I1 ):
1053 res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1054 break;
1055 case( VT_I2 ):
1056 res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1057 break;
1058 case( VT_INT ):
1059 case( VT_I4 ):
1060 res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1061 break;
1062 case( VT_UI1 ):
1063 res = VariantCopy( pd, ps );
1064 break;
1065 case( VT_UI2 ):
1066 res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1067 break;
1068 case( VT_UINT ):
1069 case( VT_UI4 ):
1070 res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1071 break;
1072 case( VT_R4 ):
1073 res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1074 break;
1075 case( VT_R8 ):
1076 res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1077 break;
1078 case( VT_DATE ):
1079 res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1080 break;
1081 case( VT_BOOL ):
1082 res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1083 break;
1084 case( VT_BSTR ):
1085 res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1086 break;
1087 case( VT_CY ):
1088 res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1089 case( VT_DISPATCH ):
1090 /*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1091 case( VT_UNKNOWN ):
1092 /*res = VarUI1From32( ps->u.lVal, &(pd->u.bVal) );*/
1093 case( VT_DECIMAL ):
1094 /*res = VarUI1FromDec32( ps->u.deiVal, &(pd->u.bVal) );*/
1095 default:
1096 res = DISP_E_TYPEMISMATCH;
1097 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1098 break;
1100 break;
1102 case( VT_UI2 ):
1103 switch( vtFrom )
1105 case( VT_I1 ):
1106 res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1107 break;
1108 case( VT_I2 ):
1109 res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1110 break;
1111 case( VT_INT ):
1112 case( VT_I4 ):
1113 res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1114 break;
1115 case( VT_UI1 ):
1116 res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1117 break;
1118 case( VT_UI2 ):
1119 res = VariantCopy( pd, ps );
1120 break;
1121 case( VT_UINT ):
1122 case( VT_UI4 ):
1123 res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1124 break;
1125 case( VT_R4 ):
1126 res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1127 break;
1128 case( VT_R8 ):
1129 res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1130 break;
1131 case( VT_DATE ):
1132 res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1133 break;
1134 case( VT_BOOL ):
1135 res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1136 break;
1137 case( VT_BSTR ):
1138 res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1139 break;
1140 case( VT_CY ):
1141 res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1142 case( VT_DISPATCH ):
1143 /*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1144 case( VT_UNKNOWN ):
1145 /*res = VarUI2From32( ps->u.lVal, &(pd->u.uiVal) );*/
1146 case( VT_DECIMAL ):
1147 /*res = VarUI2FromDec32( ps->u.deiVal, &(pd->u.uiVal) );*/
1148 default:
1149 res = DISP_E_TYPEMISMATCH;
1150 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1151 break;
1153 break;
1155 case( VT_UINT ):
1156 case( VT_UI4 ):
1157 switch( vtFrom )
1159 case( VT_I1 ):
1160 res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1161 break;
1162 case( VT_I2 ):
1163 res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1164 break;
1165 case( VT_INT ):
1166 case( VT_I4 ):
1167 res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1168 break;
1169 case( VT_UI1 ):
1170 res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1171 break;
1172 case( VT_UI2 ):
1173 res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1174 break;
1175 case( VT_UI4 ):
1176 res = VariantCopy( pd, ps );
1177 break;
1178 case( VT_R4 ):
1179 res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1180 break;
1181 case( VT_R8 ):
1182 res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1183 break;
1184 case( VT_DATE ):
1185 res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1186 break;
1187 case( VT_BOOL ):
1188 res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1189 break;
1190 case( VT_BSTR ):
1191 res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1192 break;
1193 case( VT_CY ):
1194 res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1195 case( VT_DISPATCH ):
1196 /*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1197 case( VT_UNKNOWN ):
1198 /*res = VarUI4From32( ps->u.lVal, &(pd->u.ulVal) );*/
1199 case( VT_DECIMAL ):
1200 /*res = VarUI4FromDec32( ps->u.deiVal, &(pd->u.ulVal) );*/
1201 default:
1202 res = DISP_E_TYPEMISMATCH;
1203 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1204 break;
1206 break;
1208 case( VT_R4 ):
1209 switch( vtFrom )
1211 case( VT_I1 ):
1212 res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1213 break;
1214 case( VT_I2 ):
1215 res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1216 break;
1217 case( VT_INT ):
1218 case( VT_I4 ):
1219 res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1220 break;
1221 case( VT_UI1 ):
1222 res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1223 break;
1224 case( VT_UI2 ):
1225 res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1226 break;
1227 case( VT_UINT ):
1228 case( VT_UI4 ):
1229 res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1230 break;
1231 case( VT_R4 ):
1232 res = VariantCopy( pd, ps );
1233 break;
1234 case( VT_R8 ):
1235 res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1236 break;
1237 case( VT_DATE ):
1238 res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1239 break;
1240 case( VT_BOOL ):
1241 res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1242 break;
1243 case( VT_BSTR ):
1244 res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1245 break;
1246 case( VT_CY ):
1247 res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1248 case( VT_DISPATCH ):
1249 /*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1250 case( VT_UNKNOWN ):
1251 /*res = VarR4From32( ps->u.lVal, &(pd->u.fltVal) );*/
1252 case( VT_DECIMAL ):
1253 /*res = VarR4FromDec32( ps->u.deiVal, &(pd->u.fltVal) );*/
1254 default:
1255 res = DISP_E_TYPEMISMATCH;
1256 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1257 break;
1259 break;
1261 case( VT_R8 ):
1262 switch( vtFrom )
1264 case( VT_I1 ):
1265 res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1266 break;
1267 case( VT_I2 ):
1268 res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1269 break;
1270 case( VT_INT ):
1271 case( VT_I4 ):
1272 res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1273 break;
1274 case( VT_UI1 ):
1275 res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1276 break;
1277 case( VT_UI2 ):
1278 res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1279 break;
1280 case( VT_UINT ):
1281 case( VT_UI4 ):
1282 res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1283 break;
1284 case( VT_R4 ):
1285 res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1286 break;
1287 case( VT_R8 ):
1288 res = VariantCopy( pd, ps );
1289 break;
1290 case( VT_DATE ):
1291 res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1292 break;
1293 case( VT_BOOL ):
1294 res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1295 break;
1296 case( VT_BSTR ):
1297 res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1298 break;
1299 case( VT_CY ):
1300 res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1301 case( VT_DISPATCH ):
1302 /*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1303 case( VT_UNKNOWN ):
1304 /*res = VarR8From32( ps->u.lVal, &(pd->u.dblVal) );*/
1305 case( VT_DECIMAL ):
1306 /*res = VarR8FromDec32( ps->u.deiVal, &(pd->u.dblVal) );*/
1307 default:
1308 res = DISP_E_TYPEMISMATCH;
1309 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1310 break;
1312 break;
1314 case( VT_DATE ):
1315 switch( vtFrom )
1317 case( VT_I1 ):
1318 res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1319 break;
1320 case( VT_I2 ):
1321 res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1322 break;
1323 case( VT_INT ):
1324 res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1325 break;
1326 case( VT_I4 ):
1327 res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1328 break;
1329 case( VT_UI1 ):
1330 res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1331 break;
1332 case( VT_UI2 ):
1333 res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1334 break;
1335 case( VT_UINT ):
1336 res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1337 break;
1338 case( VT_UI4 ):
1339 res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1340 break;
1341 case( VT_R4 ):
1342 res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1343 break;
1344 case( VT_R8 ):
1345 res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1346 break;
1347 case( VT_DATE ):
1348 res = VariantCopy( pd, ps );
1349 break;
1350 case( VT_BOOL ):
1351 res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1352 break;
1353 case( VT_BSTR ):
1354 res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1355 break;
1356 case( VT_CY ):
1357 res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1358 case( VT_DISPATCH ):
1359 /*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1360 case( VT_UNKNOWN ):
1361 /*res = VarDateFrom32( ps->u.lVal, &(pd->u.date) );*/
1362 case( VT_DECIMAL ):
1363 /*res = VarDateFromDec32( ps->u.deiVal, &(pd->u.date) );*/
1364 default:
1365 res = DISP_E_TYPEMISMATCH;
1366 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1367 break;
1369 break;
1371 case( VT_BOOL ):
1372 switch( vtFrom )
1374 case( VT_I1 ):
1375 res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1376 break;
1377 case( VT_I2 ):
1378 res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1379 break;
1380 case( VT_INT ):
1381 res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1382 break;
1383 case( VT_I4 ):
1384 res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1385 break;
1386 case( VT_UI1 ):
1387 res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1388 break;
1389 case( VT_UI2 ):
1390 res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1391 break;
1392 case( VT_UINT ):
1393 res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1394 break;
1395 case( VT_UI4 ):
1396 res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1397 break;
1398 case( VT_R4 ):
1399 res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1400 break;
1401 case( VT_R8 ):
1402 res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1403 break;
1404 case( VT_DATE ):
1405 res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1406 break;
1407 case( VT_BOOL ):
1408 res = VariantCopy( pd, ps );
1409 break;
1410 case( VT_BSTR ):
1411 res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1412 break;
1413 case( VT_CY ):
1414 res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1415 case( VT_DISPATCH ):
1416 /*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1417 case( VT_UNKNOWN ):
1418 /*res = VarBoolFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1419 case( VT_DECIMAL ):
1420 /*res = VarBoolFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1421 default:
1422 res = DISP_E_TYPEMISMATCH;
1423 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1424 break;
1426 break;
1428 case( VT_BSTR ):
1429 switch( vtFrom )
1431 case( VT_I1 ):
1432 res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1433 break;
1434 case( VT_I2 ):
1435 res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1436 break;
1437 case( VT_INT ):
1438 res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1439 break;
1440 case( VT_I4 ):
1441 res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1442 break;
1443 case( VT_UI1 ):
1444 res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1445 break;
1446 case( VT_UI2 ):
1447 res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1448 break;
1449 case( VT_UINT ):
1450 res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1451 break;
1452 case( VT_UI4 ):
1453 res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1454 break;
1455 case( VT_R4 ):
1456 res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1457 break;
1458 case( VT_R8 ):
1459 res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1460 break;
1461 case( VT_DATE ):
1462 res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1463 break;
1464 case( VT_BOOL ):
1465 res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1466 break;
1467 case( VT_BSTR ):
1468 res = VariantCopy( pd, ps );
1469 break;
1470 case( VT_CY ):
1471 /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1472 case( VT_DISPATCH ):
1473 /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1474 case( VT_UNKNOWN ):
1475 /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1476 case( VT_DECIMAL ):
1477 /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1478 default:
1479 res = DISP_E_TYPEMISMATCH;
1480 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1481 break;
1483 break;
1485 case( VT_CY ):
1486 switch( vtFrom )
1488 case( VT_I1 ):
1489 res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1490 break;
1491 case( VT_I2 ):
1492 res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1493 break;
1494 case( VT_INT ):
1495 res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1496 break;
1497 case( VT_I4 ):
1498 res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1499 break;
1500 case( VT_UI1 ):
1501 res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1502 break;
1503 case( VT_UI2 ):
1504 res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1505 break;
1506 case( VT_UINT ):
1507 res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1508 break;
1509 case( VT_UI4 ):
1510 res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1511 break;
1512 case( VT_R4 ):
1513 res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1514 break;
1515 case( VT_R8 ):
1516 res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1517 break;
1518 case( VT_DATE ):
1519 res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1520 break;
1521 case( VT_BOOL ):
1522 res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1523 break;
1524 case( VT_CY ):
1525 res = VariantCopy( pd, ps );
1526 break;
1527 case( VT_BSTR ):
1528 /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1529 case( VT_DISPATCH ):
1530 /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1531 case( VT_UNKNOWN ):
1532 /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1533 case( VT_DECIMAL ):
1534 /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1535 default:
1536 res = DISP_E_TYPEMISMATCH;
1537 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1538 break;
1540 break;
1542 default:
1543 res = DISP_E_TYPEMISMATCH;
1544 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1545 break;
1548 return res;
1551 /******************************************************************************
1552 * ValidateVtRange [INTERNAL]
1554 * Used internally by the hi-level Variant API to determine
1555 * if the vartypes are valid.
1557 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1559 /* if by value we must make sure it is in the
1560 * range of the valid types.
1562 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1564 return DISP_E_BADVARTYPE;
1566 return S_OK;
1570 /******************************************************************************
1571 * ValidateVartype [INTERNAL]
1573 * Used internally by the hi-level Variant API to determine
1574 * if the vartypes are valid.
1576 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1578 HRESULT res = S_OK;
1580 /* check if we have a valid argument.
1582 if( vt & VT_BYREF )
1584 /* if by reference check that the type is in
1585 * the valid range and that it is not of empty or null type
1587 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1588 ( vt & VT_TYPEMASK ) == VT_NULL ||
1589 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1591 res = E_INVALIDARG;
1595 else
1597 res = ValidateVtRange( vt );
1600 return res;
1603 /******************************************************************************
1604 * ValidateVt [INTERNAL]
1606 * Used internally by the hi-level Variant API to determine
1607 * if the vartypes are valid.
1609 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1611 HRESULT res = S_OK;
1613 /* check if we have a valid argument.
1615 if( vt & VT_BYREF )
1617 /* if by reference check that the type is in
1618 * the valid range and that it is not of empty or null type
1620 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1621 ( vt & VT_TYPEMASK ) == VT_NULL ||
1622 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1624 res = DISP_E_BADVARTYPE;
1628 else
1630 res = ValidateVtRange( vt );
1633 return res;
1640 /******************************************************************************
1641 * VariantInit32 [OLEAUT32.8]
1643 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1644 * contents of the Variant.
1646 void WINAPI VariantInit(VARIANTARG* pvarg)
1648 TRACE("(%p),stub\n",pvarg);
1650 memset(pvarg, 0, sizeof (VARIANTARG));
1651 pvarg->vt = VT_EMPTY;
1653 return;
1656 /******************************************************************************
1657 * VariantClear32 [OLEAUT32.9]
1659 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1660 * sets the wReservedX field to 0. The current contents of the VARIANT are
1661 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1662 * released. If VT_ARRAY the array is freed.
1664 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1666 HRESULT res = S_OK;
1667 TRACE("(%p)\n",pvarg);
1669 res = ValidateVariantType( pvarg->vt );
1670 if( res == S_OK )
1672 if( !( pvarg->vt & VT_BYREF ) )
1675 * The VT_ARRAY flag is a special case of a safe array.
1677 if ( (pvarg->vt & VT_ARRAY) != 0)
1679 SafeArrayDestroy(pvarg->u.parray);
1681 else
1683 switch( pvarg->vt & VT_TYPEMASK )
1685 case( VT_BSTR ):
1686 SysFreeString( pvarg->u.bstrVal );
1687 break;
1688 case( VT_DISPATCH ):
1689 break;
1690 case( VT_VARIANT ):
1691 break;
1692 case( VT_UNKNOWN ):
1693 break;
1694 case( VT_SAFEARRAY ):
1695 SafeArrayDestroy(pvarg->u.parray);
1696 break;
1697 default:
1698 break;
1704 * Empty all the fields and mark the type as empty.
1706 memset(pvarg, 0, sizeof (VARIANTARG));
1707 pvarg->vt = VT_EMPTY;
1710 return res;
1713 /******************************************************************************
1714 * VariantCopy32 [OLEAUT32.10]
1716 * Frees up the designation variant and makes a copy of the source.
1718 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1720 HRESULT res = S_OK;
1722 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1724 res = ValidateVariantType( pvargSrc->vt );
1726 /* If the pointer are to the same variant we don't need
1727 * to do anything.
1729 if( pvargDest != pvargSrc && res == S_OK )
1731 res = VariantClear( pvargDest );
1733 if( res == S_OK )
1735 if( pvargSrc->vt & VT_BYREF )
1737 /* In the case of byreference we only need
1738 * to copy the pointer.
1740 pvargDest->u = pvargSrc->u;
1741 pvargDest->vt = pvargSrc->vt;
1743 else
1746 * The VT_ARRAY flag is another way to designate a safe array.
1748 if (pvargSrc->vt & VT_ARRAY)
1750 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1752 else
1754 /* In the case of by value we need to
1755 * copy the actuall value. In the case of
1756 * VT_BSTR a copy of the string is made,
1757 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1758 * called to increment the object's reference count.
1760 switch( pvargSrc->vt & VT_TYPEMASK )
1762 case( VT_BSTR ):
1763 pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1764 break;
1765 case( VT_DISPATCH ):
1766 break;
1767 case( VT_VARIANT ):
1768 break;
1769 case( VT_UNKNOWN ):
1770 break;
1771 case( VT_SAFEARRAY ):
1772 SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1773 break;
1774 default:
1775 pvargDest->u = pvargSrc->u;
1776 break;
1780 pvargDest->vt = pvargSrc->vt;
1785 return res;
1789 /******************************************************************************
1790 * VariantCopyInd32 [OLEAUT32.11]
1792 * Frees up the destination variant and makes a copy of the source. If
1793 * the source is of type VT_BYREF it performs the necessary indirections.
1795 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1797 HRESULT res = S_OK;
1799 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1801 res = ValidateVariantType( pvargSrc->vt );
1803 if( res != S_OK )
1804 return res;
1806 if( pvargSrc->vt & VT_BYREF )
1808 VARIANTARG varg;
1809 VariantInit( &varg );
1811 /* handle the in place copy.
1813 if( pvargDest == pvargSrc )
1815 /* we will use a copy of the source instead.
1817 res = VariantCopy( &varg, pvargSrc );
1818 pvargSrc = &varg;
1821 if( res == S_OK )
1823 res = VariantClear( pvargDest );
1825 if( res == S_OK )
1828 * The VT_ARRAY flag is another way to designate a safearray variant.
1830 if ( pvargSrc->vt & VT_ARRAY)
1832 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1834 else
1836 /* In the case of by reference we need
1837 * to copy the date pointed to by the variant.
1840 /* Get the variant type.
1842 switch( pvargSrc->vt & VT_TYPEMASK )
1844 case( VT_BSTR ):
1845 pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1846 break;
1847 case( VT_DISPATCH ):
1848 break;
1849 case( VT_VARIANT ):
1851 /* Prevent from cycling. According to tests on
1852 * VariantCopyInd in Windows and the documentation
1853 * this API dereferences the inner Variants to only one depth.
1854 * If the inner Variant itself contains an
1855 * other inner variant the E_INVALIDARG error is
1856 * returned.
1858 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1860 /* If we get here we are attempting to deference
1861 * an inner variant that that is itself contained
1862 * in an inner variant so report E_INVALIDARG error.
1864 res = E_INVALIDARG;
1866 else
1868 /* Set the processing inner variant flag.
1869 * We will set this flag in the inner variant
1870 * that will be passed to the VariantCopyInd function.
1872 (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1874 /* Dereference the inner variant.
1876 res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1879 break;
1880 case( VT_UNKNOWN ):
1881 break;
1882 case( VT_SAFEARRAY ):
1883 SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1884 break;
1885 default:
1886 /* This is a by reference Variant which means that the union
1887 * part of the Variant contains a pointer to some data of
1888 * type "pvargSrc->vt & VT_TYPEMASK".
1889 * We will deference this data in a generic fashion using
1890 * the void pointer "Variant.u.byref".
1891 * We will copy this data into the union of the destination
1892 * Variant.
1894 memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1895 break;
1899 pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1903 /* this should not fail.
1905 VariantClear( &varg );
1907 else
1909 res = VariantCopy( pvargDest, pvargSrc );
1912 return res;
1915 /******************************************************************************
1916 * VariantChangeType32 [OLEAUT32.12]
1918 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1919 USHORT wFlags, VARTYPE vt)
1921 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1924 /******************************************************************************
1925 * VariantChangeTypeEx32 [OLEAUT32.147]
1927 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1928 LCID lcid, USHORT wFlags, VARTYPE vt)
1930 HRESULT res = S_OK;
1931 VARIANTARG varg;
1932 VariantInit( &varg );
1934 TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1936 /* validate our source argument.
1938 res = ValidateVariantType( pvargSrc->vt );
1940 /* validate the vartype.
1942 if( res == S_OK )
1944 res = ValidateVt( vt );
1947 /* if we are doing an in-place conversion make a copy of the source.
1949 if( res == S_OK && pvargDest == pvargSrc )
1951 res = VariantCopy( &varg, pvargSrc );
1952 pvargSrc = &varg;
1955 if( res == S_OK )
1957 /* free up the destination variant.
1959 res = VariantClear( pvargDest );
1962 if( res == S_OK )
1964 if( pvargSrc->vt & VT_BYREF )
1966 /* Convert the source variant to a "byvalue" variant.
1968 VARIANTARG Variant;
1969 VariantInit( &Variant );
1970 res = VariantCopyInd( &Variant, pvargSrc );
1971 if( res == S_OK )
1973 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
1974 /* this should not fail.
1976 VariantClear( &Variant );
1980 else
1982 /* Use the current "byvalue" source variant.
1984 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
1987 /* this should not fail.
1989 VariantClear( &varg );
1991 /* set the type of the destination
1993 if ( res == S_OK )
1994 pvargDest->vt = vt;
1996 return res;
2002 /******************************************************************************
2003 * VarUI1FromI232 [OLEAUT32.130]
2005 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2007 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2009 /* Check range of value.
2011 if( sIn < UI1_MIN || sIn > UI1_MAX )
2013 return DISP_E_OVERFLOW;
2016 *pbOut = (BYTE) sIn;
2018 return S_OK;
2021 /******************************************************************************
2022 * VarUI1FromI432 [OLEAUT32.131]
2024 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2026 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2028 /* Check range of value.
2030 if( lIn < UI1_MIN || lIn > UI1_MAX )
2032 return DISP_E_OVERFLOW;
2035 *pbOut = (BYTE) lIn;
2037 return S_OK;
2041 /******************************************************************************
2042 * VarUI1FromR432 [OLEAUT32.132]
2044 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2046 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2048 /* Check range of value.
2050 fltIn = round( fltIn );
2051 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2053 return DISP_E_OVERFLOW;
2056 *pbOut = (BYTE) fltIn;
2058 return S_OK;
2061 /******************************************************************************
2062 * VarUI1FromR832 [OLEAUT32.133]
2064 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2066 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2068 /* Check range of value.
2070 dblIn = round( dblIn );
2071 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2073 return DISP_E_OVERFLOW;
2076 *pbOut = (BYTE) dblIn;
2078 return S_OK;
2081 /******************************************************************************
2082 * VarUI1FromDate32 [OLEAUT32.135]
2084 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2086 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2088 /* Check range of value.
2090 dateIn = round( dateIn );
2091 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2093 return DISP_E_OVERFLOW;
2096 *pbOut = (BYTE) dateIn;
2098 return S_OK;
2101 /******************************************************************************
2102 * VarUI1FromBool32 [OLEAUT32.138]
2104 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2106 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2108 *pbOut = (BYTE) boolIn;
2110 return S_OK;
2113 /******************************************************************************
2114 * VarUI1FromI132 [OLEAUT32.237]
2116 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2118 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2120 *pbOut = cIn;
2122 return S_OK;
2125 /******************************************************************************
2126 * VarUI1FromUI232 [OLEAUT32.238]
2128 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2130 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2132 /* Check range of value.
2134 if( uiIn > UI1_MAX )
2136 return DISP_E_OVERFLOW;
2139 *pbOut = (BYTE) uiIn;
2141 return S_OK;
2144 /******************************************************************************
2145 * VarUI1FromUI432 [OLEAUT32.239]
2147 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2149 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2151 /* Check range of value.
2153 if( ulIn > UI1_MAX )
2155 return DISP_E_OVERFLOW;
2158 *pbOut = (BYTE) ulIn;
2160 return S_OK;
2164 /******************************************************************************
2165 * VarUI1FromStr32 [OLEAUT32.54]
2167 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2169 double dValue = 0.0;
2170 LPSTR pNewString = NULL;
2172 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2174 /* Check if we have a valid argument
2176 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2177 RemoveCharacterFromString( pNewString, "," );
2178 if( IsValidRealString( pNewString ) == FALSE )
2180 return DISP_E_TYPEMISMATCH;
2183 /* Convert the valid string to a floating point number.
2185 dValue = atof( pNewString );
2187 /* We don't need the string anymore so free it.
2189 HeapFree( GetProcessHeap(), 0 , pNewString );
2191 /* Check range of value.
2193 dValue = round( dValue );
2194 if( dValue < UI1_MIN || dValue > UI1_MAX )
2196 return DISP_E_OVERFLOW;
2199 *pbOut = (BYTE) dValue;
2201 return S_OK;
2204 /**********************************************************************
2205 * VarUI1FromCy32 [OLEAUT32.134]
2206 * Convert currency to unsigned char
2208 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2209 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2211 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2213 *pbOut = (BYTE)t;
2214 return S_OK;
2217 /******************************************************************************
2218 * VarI2FromUI132 [OLEAUT32.48]
2220 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2222 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2224 *psOut = (short) bIn;
2226 return S_OK;
2229 /******************************************************************************
2230 * VarI2FromI432 [OLEAUT32.49]
2232 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2234 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2236 /* Check range of value.
2238 if( lIn < I2_MIN || lIn > I2_MAX )
2240 return DISP_E_OVERFLOW;
2243 *psOut = (short) lIn;
2245 return S_OK;
2248 /******************************************************************************
2249 * VarI2FromR432 [OLEAUT32.50]
2251 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2253 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2255 /* Check range of value.
2257 fltIn = round( fltIn );
2258 if( fltIn < I2_MIN || fltIn > I2_MAX )
2260 return DISP_E_OVERFLOW;
2263 *psOut = (short) fltIn;
2265 return S_OK;
2268 /******************************************************************************
2269 * VarI2FromR832 [OLEAUT32.51]
2271 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2273 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2275 /* Check range of value.
2277 dblIn = round( dblIn );
2278 if( dblIn < I2_MIN || dblIn > I2_MAX )
2280 return DISP_E_OVERFLOW;
2283 *psOut = (short) dblIn;
2285 return S_OK;
2288 /******************************************************************************
2289 * VarI2FromDate32 [OLEAUT32.53]
2291 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2293 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2295 /* Check range of value.
2297 dateIn = round( dateIn );
2298 if( dateIn < I2_MIN || dateIn > I2_MAX )
2300 return DISP_E_OVERFLOW;
2303 *psOut = (short) dateIn;
2305 return S_OK;
2308 /******************************************************************************
2309 * VarI2FromBool32 [OLEAUT32.56]
2311 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2313 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2315 *psOut = (short) boolIn;
2317 return S_OK;
2320 /******************************************************************************
2321 * VarI2FromI132 [OLEAUT32.48]
2323 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2325 TRACE("( %c, %p ), stub\n", cIn, psOut );
2327 *psOut = (short) cIn;
2329 return S_OK;
2332 /******************************************************************************
2333 * VarI2FromUI232 [OLEAUT32.206]
2335 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2337 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2339 /* Check range of value.
2341 if( uiIn > I2_MAX )
2343 return DISP_E_OVERFLOW;
2346 *psOut = (short) uiIn;
2348 return S_OK;
2351 /******************************************************************************
2352 * VarI2FromUI432 [OLEAUT32.49]
2354 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2356 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2358 /* Check range of value.
2360 if( ulIn < I2_MIN || ulIn > I2_MAX )
2362 return DISP_E_OVERFLOW;
2365 *psOut = (short) ulIn;
2367 return S_OK;
2370 /******************************************************************************
2371 * VarI2FromStr32 [OLEAUT32.54]
2373 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2375 double dValue = 0.0;
2376 LPSTR pNewString = NULL;
2378 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2380 /* Check if we have a valid argument
2382 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2383 RemoveCharacterFromString( pNewString, "," );
2384 if( IsValidRealString( pNewString ) == FALSE )
2386 return DISP_E_TYPEMISMATCH;
2389 /* Convert the valid string to a floating point number.
2391 dValue = atof( pNewString );
2393 /* We don't need the string anymore so free it.
2395 HeapFree( GetProcessHeap(), 0, pNewString );
2397 /* Check range of value.
2399 dValue = round( dValue );
2400 if( dValue < I2_MIN || dValue > I2_MAX )
2402 return DISP_E_OVERFLOW;
2405 *psOut = (short) dValue;
2407 return S_OK;
2410 /**********************************************************************
2411 * VarI2FromCy32 [OLEAUT32.52]
2412 * Convert currency to signed short
2414 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2415 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2417 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2419 *psOut = (SHORT)t;
2420 return S_OK;
2423 /******************************************************************************
2424 * VarI4FromUI132 [OLEAUT32.58]
2426 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2428 TRACE("( %X, %p ), stub\n", bIn, plOut );
2430 *plOut = (LONG) bIn;
2432 return S_OK;
2436 /******************************************************************************
2437 * VarI4FromR432 [OLEAUT32.60]
2439 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2441 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2443 /* Check range of value.
2445 fltIn = round( fltIn );
2446 if( fltIn < I4_MIN || fltIn > I4_MAX )
2448 return DISP_E_OVERFLOW;
2451 *plOut = (LONG) fltIn;
2453 return S_OK;
2456 /******************************************************************************
2457 * VarI4FromR832 [OLEAUT32.61]
2459 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2461 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2463 /* Check range of value.
2465 dblIn = round( dblIn );
2466 if( dblIn < I4_MIN || dblIn > I4_MAX )
2468 return DISP_E_OVERFLOW;
2471 *plOut = (LONG) dblIn;
2473 return S_OK;
2476 /******************************************************************************
2477 * VarI4FromDate32 [OLEAUT32.63]
2479 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2481 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2483 /* Check range of value.
2485 dateIn = round( dateIn );
2486 if( dateIn < I4_MIN || dateIn > I4_MAX )
2488 return DISP_E_OVERFLOW;
2491 *plOut = (LONG) dateIn;
2493 return S_OK;
2496 /******************************************************************************
2497 * VarI4FromBool32 [OLEAUT32.66]
2499 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2501 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2503 *plOut = (LONG) boolIn;
2505 return S_OK;
2508 /******************************************************************************
2509 * VarI4FromI132 [OLEAUT32.209]
2511 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2513 TRACE("( %c, %p ), stub\n", cIn, plOut );
2515 *plOut = (LONG) cIn;
2517 return S_OK;
2520 /******************************************************************************
2521 * VarI4FromUI232 [OLEAUT32.210]
2523 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2525 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2527 *plOut = (LONG) uiIn;
2529 return S_OK;
2532 /******************************************************************************
2533 * VarI4FromUI432 [OLEAUT32.211]
2535 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2537 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2539 /* Check range of value.
2541 if( ulIn < I4_MIN || ulIn > I4_MAX )
2543 return DISP_E_OVERFLOW;
2546 *plOut = (LONG) ulIn;
2548 return S_OK;
2551 /******************************************************************************
2552 * VarI4FromI232 [OLEAUT32.59]
2554 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2556 TRACE("( %d, %p ), stub\n", sIn, plOut );
2558 *plOut = (LONG) sIn;
2560 return S_OK;
2563 /******************************************************************************
2564 * VarI4FromStr32 [OLEAUT32.64]
2566 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2568 double dValue = 0.0;
2569 LPSTR pNewString = NULL;
2571 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2573 /* Check if we have a valid argument
2575 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2576 RemoveCharacterFromString( pNewString, "," );
2577 if( IsValidRealString( pNewString ) == FALSE )
2579 return DISP_E_TYPEMISMATCH;
2582 /* Convert the valid string to a floating point number.
2584 dValue = atof( pNewString );
2586 /* We don't need the string anymore so free it.
2588 HeapFree( GetProcessHeap(), 0, pNewString );
2590 /* Check range of value.
2592 dValue = round( dValue );
2593 if( dValue < I4_MIN || dValue > I4_MAX )
2595 return DISP_E_OVERFLOW;
2598 *plOut = (LONG) dValue;
2600 return S_OK;
2603 /**********************************************************************
2604 * VarI4FromCy32 [OLEAUT32.62]
2605 * Convert currency to signed long
2607 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2608 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2610 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2612 *plOut = (LONG)t;
2613 return S_OK;
2616 /******************************************************************************
2617 * VarR4FromUI132 [OLEAUT32.68]
2619 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2621 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2623 *pfltOut = (FLOAT) bIn;
2625 return S_OK;
2628 /******************************************************************************
2629 * VarR4FromI232 [OLEAUT32.69]
2631 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2633 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2635 *pfltOut = (FLOAT) sIn;
2637 return S_OK;
2640 /******************************************************************************
2641 * VarR4FromI432 [OLEAUT32.70]
2643 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2645 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2647 *pfltOut = (FLOAT) lIn;
2649 return S_OK;
2652 /******************************************************************************
2653 * VarR4FromR832 [OLEAUT32.71]
2655 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2657 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2659 /* Check range of value.
2661 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2663 return DISP_E_OVERFLOW;
2666 *pfltOut = (FLOAT) dblIn;
2668 return S_OK;
2671 /******************************************************************************
2672 * VarR4FromDate32 [OLEAUT32.73]
2674 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2676 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2678 /* Check range of value.
2680 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2682 return DISP_E_OVERFLOW;
2685 *pfltOut = (FLOAT) dateIn;
2687 return S_OK;
2690 /******************************************************************************
2691 * VarR4FromBool32 [OLEAUT32.76]
2693 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2695 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2697 *pfltOut = (FLOAT) boolIn;
2699 return S_OK;
2702 /******************************************************************************
2703 * VarR4FromI132 [OLEAUT32.213]
2705 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2707 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2709 *pfltOut = (FLOAT) cIn;
2711 return S_OK;
2714 /******************************************************************************
2715 * VarR4FromUI232 [OLEAUT32.214]
2717 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2719 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2721 *pfltOut = (FLOAT) uiIn;
2723 return S_OK;
2726 /******************************************************************************
2727 * VarR4FromUI432 [OLEAUT32.215]
2729 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2731 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2733 *pfltOut = (FLOAT) ulIn;
2735 return S_OK;
2738 /******************************************************************************
2739 * VarR4FromStr32 [OLEAUT32.74]
2741 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2743 double dValue = 0.0;
2744 LPSTR pNewString = NULL;
2746 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2748 /* Check if we have a valid argument
2750 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2751 RemoveCharacterFromString( pNewString, "," );
2752 if( IsValidRealString( pNewString ) == FALSE )
2754 return DISP_E_TYPEMISMATCH;
2757 /* Convert the valid string to a floating point number.
2759 dValue = atof( pNewString );
2761 /* We don't need the string anymore so free it.
2763 HeapFree( GetProcessHeap(), 0, pNewString );
2765 /* Check range of value.
2767 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2769 return DISP_E_OVERFLOW;
2772 *pfltOut = (FLOAT) dValue;
2774 return S_OK;
2777 /**********************************************************************
2778 * VarR4FromCy32 [OLEAUT32.72]
2779 * Convert currency to float
2781 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2782 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2784 return S_OK;
2787 /******************************************************************************
2788 * VarR8FromUI132 [OLEAUT32.68]
2790 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2792 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2794 *pdblOut = (double) bIn;
2796 return S_OK;
2799 /******************************************************************************
2800 * VarR8FromI232 [OLEAUT32.69]
2802 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2804 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2806 *pdblOut = (double) sIn;
2808 return S_OK;
2811 /******************************************************************************
2812 * VarR8FromI432 [OLEAUT32.70]
2814 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2816 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2818 *pdblOut = (double) lIn;
2820 return S_OK;
2823 /******************************************************************************
2824 * VarR8FromR432 [OLEAUT32.81]
2826 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2828 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2830 *pdblOut = (double) fltIn;
2832 return S_OK;
2835 /******************************************************************************
2836 * VarR8FromDate32 [OLEAUT32.83]
2838 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2840 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2842 *pdblOut = (double) dateIn;
2844 return S_OK;
2847 /******************************************************************************
2848 * VarR8FromBool32 [OLEAUT32.86]
2850 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2852 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2854 *pdblOut = (double) boolIn;
2856 return S_OK;
2859 /******************************************************************************
2860 * VarR8FromI132 [OLEAUT32.217]
2862 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2864 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2866 *pdblOut = (double) cIn;
2868 return S_OK;
2871 /******************************************************************************
2872 * VarR8FromUI232 [OLEAUT32.218]
2874 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2876 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2878 *pdblOut = (double) uiIn;
2880 return S_OK;
2883 /******************************************************************************
2884 * VarR8FromUI432 [OLEAUT32.219]
2886 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2888 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2890 *pdblOut = (double) ulIn;
2892 return S_OK;
2895 /******************************************************************************
2896 * VarR8FromStr32 [OLEAUT32.84]
2898 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2900 double dValue = 0.0;
2901 LPSTR pNewString = NULL;
2903 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2905 /* Check if we have a valid argument
2907 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2908 RemoveCharacterFromString( pNewString, "," );
2909 if( IsValidRealString( pNewString ) == FALSE )
2911 return DISP_E_TYPEMISMATCH;
2914 /* Convert the valid string to a floating point number.
2916 dValue = atof( pNewString );
2918 /* We don't need the string anymore so free it.
2920 HeapFree( GetProcessHeap(), 0, pNewString );
2922 *pdblOut = dValue;
2924 return S_OK;
2927 /**********************************************************************
2928 * VarR8FromCy32 [OLEAUT32.82]
2929 * Convert currency to double
2931 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2932 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2934 return S_OK;
2937 /******************************************************************************
2938 * VarDateFromUI132 [OLEAUT32.]
2940 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2942 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2944 *pdateOut = (DATE) bIn;
2946 return S_OK;
2949 /******************************************************************************
2950 * VarDateFromI232 [OLEAUT32.222]
2952 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2954 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2956 *pdateOut = (DATE) sIn;
2958 return S_OK;
2961 /******************************************************************************
2962 * VarDateFromI432 [OLEAUT32.90]
2964 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
2966 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
2968 if( lIn < DATE_MIN || lIn > DATE_MAX )
2970 return DISP_E_OVERFLOW;
2973 *pdateOut = (DATE) lIn;
2975 return S_OK;
2978 /******************************************************************************
2979 * VarDateFromR432 [OLEAUT32.91]
2981 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
2983 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
2985 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
2987 return DISP_E_OVERFLOW;
2990 *pdateOut = (DATE) fltIn;
2992 return S_OK;
2995 /******************************************************************************
2996 * VarDateFromR832 [OLEAUT32.92]
2998 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3000 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3002 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3004 return DISP_E_OVERFLOW;
3007 *pdateOut = (DATE) dblIn;
3009 return S_OK;
3012 /******************************************************************************
3013 * VarDateFromStr32 [OLEAUT32.94]
3014 * The string representing the date is composed of two parts, a date and time.
3016 * The format of the time is has follows:
3017 * hh[:mm][:ss][AM|PM]
3018 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3019 * of space and/or tab characters, which are ignored.
3021 * The formats for the date part are has follows:
3022 * mm/[dd/][yy]yy
3023 * [dd/]mm/[yy]yy
3024 * [yy]yy/mm/dd
3025 * January dd[,] [yy]yy
3026 * dd January [yy]yy
3027 * [yy]yy January dd
3028 * Whitespace can be inserted anywhere between these tokens.
3030 * The formats for the date and time string are has follows.
3031 * date[whitespace][time]
3032 * [time][whitespace]date
3034 * These are the only characters allowed in a string representing a date and time:
3035 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3037 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3039 HRESULT ret = S_OK;
3040 struct tm TM = { 0,0,0,0,0,0,0,0,0 };
3042 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3044 if( DateTimeStringToTm( strIn, lcid, &TM ) )
3046 if( TmToDATE( &TM, pdateOut ) == FALSE )
3048 ret = E_INVALIDARG;
3051 else
3053 ret = DISP_E_TYPEMISMATCH;
3057 return ret;
3060 /******************************************************************************
3061 * VarDateFromI132 [OLEAUT32.221]
3063 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3065 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3067 *pdateOut = (DATE) cIn;
3069 return S_OK;
3072 /******************************************************************************
3073 * VarDateFromUI232 [OLEAUT32.222]
3075 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3077 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3079 if( uiIn > DATE_MAX )
3081 return DISP_E_OVERFLOW;
3084 *pdateOut = (DATE) uiIn;
3086 return S_OK;
3089 /******************************************************************************
3090 * VarDateFromUI432 [OLEAUT32.223]
3092 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3094 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3096 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3098 return DISP_E_OVERFLOW;
3101 *pdateOut = (DATE) ulIn;
3103 return S_OK;
3106 /******************************************************************************
3107 * VarDateFromBool32 [OLEAUT32.96]
3109 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3111 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3113 *pdateOut = (DATE) boolIn;
3115 return S_OK;
3118 /**********************************************************************
3119 * VarDateFromCy32 [OLEAUT32.93]
3120 * Convert currency to date
3122 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3123 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3125 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3126 return S_OK;
3129 /******************************************************************************
3130 * VarBstrFromUI132 [OLEAUT32.108]
3132 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3134 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3135 sprintf( pBuffer, "%d", bVal );
3137 *pbstrOut = StringDupAtoBstr( pBuffer );
3139 return S_OK;
3142 /******************************************************************************
3143 * VarBstrFromI232 [OLEAUT32.109]
3145 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3147 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3148 sprintf( pBuffer, "%d", iVal );
3149 *pbstrOut = StringDupAtoBstr( pBuffer );
3151 return S_OK;
3154 /******************************************************************************
3155 * VarBstrFromI432 [OLEAUT32.110]
3157 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3159 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3161 sprintf( pBuffer, "%ld", lIn );
3162 *pbstrOut = StringDupAtoBstr( pBuffer );
3164 return S_OK;
3167 /******************************************************************************
3168 * VarBstrFromR432 [OLEAUT32.111]
3170 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3172 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3174 sprintf( pBuffer, "%.7g", fltIn );
3175 *pbstrOut = StringDupAtoBstr( pBuffer );
3177 return S_OK;
3180 /******************************************************************************
3181 * VarBstrFromR832 [OLEAUT32.112]
3183 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3185 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3187 sprintf( pBuffer, "%.15g", dblIn );
3188 *pbstrOut = StringDupAtoBstr( pBuffer );
3190 return S_OK;
3193 /******************************************************************************
3194 * VarBstrFromCy [OLEAUT32.113]
3196 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3197 /* FIXME */
3198 return E_NOTIMPL;
3202 /******************************************************************************
3203 * VarBstrFromDate32 [OLEAUT32.114]
3205 * The date is implemented using an 8 byte floating-point number.
3206 * Days are represented by whole numbers increments starting with 0.00 has
3207 * being December 30 1899, midnight.
3208 * The hours are expressed as the fractional part of the number.
3209 * December 30 1899 at midnight = 0.00
3210 * January 1 1900 at midnight = 2.00
3211 * January 4 1900 at 6 AM = 5.25
3212 * January 4 1900 at noon = 5.50
3213 * December 29 1899 at midnight = -1.00
3214 * December 18 1899 at midnight = -12.00
3215 * December 18 1899 at 6AM = -12.25
3216 * December 18 1899 at 6PM = -12.75
3217 * December 19 1899 at midnight = -11.00
3218 * The tm structure is as follows:
3219 * struct tm {
3220 * int tm_sec; seconds after the minute - [0,59]
3221 * int tm_min; minutes after the hour - [0,59]
3222 * int tm_hour; hours since midnight - [0,23]
3223 * int tm_mday; day of the month - [1,31]
3224 * int tm_mon; months since January - [0,11]
3225 * int tm_year; years
3226 * int tm_wday; days since Sunday - [0,6]
3227 * int tm_yday; days since January 1 - [0,365]
3228 * int tm_isdst; daylight savings time flag
3229 * };
3231 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3233 struct tm TM = {0,0,0,0,0,0,0,0,0};
3235 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3237 if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3239 return E_INVALIDARG;
3242 if( lcid & VAR_DATEVALUEONLY )
3243 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3244 else if( lcid & VAR_TIMEVALUEONLY )
3245 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3246 else
3247 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3249 *pbstrOut = StringDupAtoBstr( pBuffer );
3251 return S_OK;
3254 /******************************************************************************
3255 * VarBstrFromBool32 [OLEAUT32.116]
3257 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3259 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3261 if( boolIn == VARIANT_FALSE )
3263 sprintf( pBuffer, "False" );
3265 else
3267 sprintf( pBuffer, "True" );
3270 *pbstrOut = StringDupAtoBstr( pBuffer );
3272 return S_OK;
3275 /******************************************************************************
3276 * VarBstrFromI132 [OLEAUT32.229]
3278 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3280 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3281 sprintf( pBuffer, "%d", cIn );
3282 *pbstrOut = StringDupAtoBstr( pBuffer );
3284 return S_OK;
3287 /******************************************************************************
3288 * VarBstrFromUI232 [OLEAUT32.230]
3290 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3292 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3293 sprintf( pBuffer, "%d", uiIn );
3294 *pbstrOut = StringDupAtoBstr( pBuffer );
3296 return S_OK;
3299 /******************************************************************************
3300 * VarBstrFromUI432 [OLEAUT32.231]
3302 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3304 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3305 sprintf( pBuffer, "%ld", ulIn );
3306 *pbstrOut = StringDupAtoBstr( pBuffer );
3308 return S_OK;
3311 /******************************************************************************
3312 * VarBoolFromUI132 [OLEAUT32.118]
3314 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3316 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3318 if( bIn == 0 )
3320 *pboolOut = VARIANT_FALSE;
3322 else
3324 *pboolOut = VARIANT_TRUE;
3327 return S_OK;
3330 /******************************************************************************
3331 * VarBoolFromI232 [OLEAUT32.119]
3333 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3335 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3337 if( sIn == 0 )
3339 *pboolOut = VARIANT_FALSE;
3341 else
3343 *pboolOut = VARIANT_TRUE;
3346 return S_OK;
3349 /******************************************************************************
3350 * VarBoolFromI432 [OLEAUT32.120]
3352 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3354 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3356 if( lIn == 0 )
3358 *pboolOut = VARIANT_FALSE;
3360 else
3362 *pboolOut = VARIANT_TRUE;
3365 return S_OK;
3368 /******************************************************************************
3369 * VarBoolFromR432 [OLEAUT32.121]
3371 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3373 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3375 if( fltIn == 0.0 )
3377 *pboolOut = VARIANT_FALSE;
3379 else
3381 *pboolOut = VARIANT_TRUE;
3384 return S_OK;
3387 /******************************************************************************
3388 * VarBoolFromR832 [OLEAUT32.122]
3390 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3392 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3394 if( dblIn == 0.0 )
3396 *pboolOut = VARIANT_FALSE;
3398 else
3400 *pboolOut = VARIANT_TRUE;
3403 return S_OK;
3406 /******************************************************************************
3407 * VarBoolFromDate32 [OLEAUT32.123]
3409 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3411 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3413 if( dateIn == 0.0 )
3415 *pboolOut = VARIANT_FALSE;
3417 else
3419 *pboolOut = VARIANT_TRUE;
3422 return S_OK;
3425 /******************************************************************************
3426 * VarBoolFromStr32 [OLEAUT32.125]
3428 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3430 HRESULT ret = S_OK;
3431 char* pNewString = NULL;
3433 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3435 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3437 if( pNewString == NULL || strlen( pNewString ) == 0 )
3439 ret = DISP_E_TYPEMISMATCH;
3442 if( ret == S_OK )
3444 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3446 *pboolOut = VARIANT_TRUE;
3448 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3450 *pboolOut = VARIANT_FALSE;
3452 else
3454 /* Try converting the string to a floating point number.
3456 double dValue = 0.0;
3457 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3458 if( res != S_OK )
3460 ret = DISP_E_TYPEMISMATCH;
3462 else if( dValue == 0.0 )
3464 *pboolOut = VARIANT_FALSE;
3466 else
3468 *pboolOut = VARIANT_TRUE;
3473 HeapFree( GetProcessHeap(), 0, pNewString );
3475 return ret;
3478 /******************************************************************************
3479 * VarBoolFromI132 [OLEAUT32.233]
3481 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3483 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3485 if( cIn == 0 )
3487 *pboolOut = VARIANT_FALSE;
3489 else
3491 *pboolOut = VARIANT_TRUE;
3494 return S_OK;
3497 /******************************************************************************
3498 * VarBoolFromUI232 [OLEAUT32.234]
3500 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3502 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3504 if( uiIn == 0 )
3506 *pboolOut = VARIANT_FALSE;
3508 else
3510 *pboolOut = VARIANT_TRUE;
3513 return S_OK;
3516 /******************************************************************************
3517 * VarBoolFromUI432 [OLEAUT32.235]
3519 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3521 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3523 if( ulIn == 0 )
3525 *pboolOut = VARIANT_FALSE;
3527 else
3529 *pboolOut = VARIANT_TRUE;
3532 return S_OK;
3535 /**********************************************************************
3536 * VarBoolFromCy32 [OLEAUT32.124]
3537 * Convert currency to boolean
3539 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3540 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3541 else *pboolOut = 0;
3543 return S_OK;
3546 /******************************************************************************
3547 * VarI1FromUI132 [OLEAUT32.244]
3549 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3551 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3553 /* Check range of value.
3555 if( bIn > CHAR_MAX )
3557 return DISP_E_OVERFLOW;
3560 *pcOut = (CHAR) bIn;
3562 return S_OK;
3565 /******************************************************************************
3566 * VarI1FromI232 [OLEAUT32.245]
3568 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3570 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3572 if( uiIn > CHAR_MAX )
3574 return DISP_E_OVERFLOW;
3577 *pcOut = (CHAR) uiIn;
3579 return S_OK;
3582 /******************************************************************************
3583 * VarI1FromI432 [OLEAUT32.246]
3585 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3587 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3589 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3591 return DISP_E_OVERFLOW;
3594 *pcOut = (CHAR) lIn;
3596 return S_OK;
3599 /******************************************************************************
3600 * VarI1FromR432 [OLEAUT32.247]
3602 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3604 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3606 fltIn = round( fltIn );
3607 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3609 return DISP_E_OVERFLOW;
3612 *pcOut = (CHAR) fltIn;
3614 return S_OK;
3617 /******************************************************************************
3618 * VarI1FromR832 [OLEAUT32.248]
3620 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3622 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3624 dblIn = round( dblIn );
3625 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3627 return DISP_E_OVERFLOW;
3630 *pcOut = (CHAR) dblIn;
3632 return S_OK;
3635 /******************************************************************************
3636 * VarI1FromDate32 [OLEAUT32.249]
3638 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3640 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3642 dateIn = round( dateIn );
3643 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3645 return DISP_E_OVERFLOW;
3648 *pcOut = (CHAR) dateIn;
3650 return S_OK;
3653 /******************************************************************************
3654 * VarI1FromStr32 [OLEAUT32.251]
3656 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3658 double dValue = 0.0;
3659 LPSTR pNewString = NULL;
3661 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3663 /* Check if we have a valid argument
3665 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3666 RemoveCharacterFromString( pNewString, "," );
3667 if( IsValidRealString( pNewString ) == FALSE )
3669 return DISP_E_TYPEMISMATCH;
3672 /* Convert the valid string to a floating point number.
3674 dValue = atof( pNewString );
3676 /* We don't need the string anymore so free it.
3678 HeapFree( GetProcessHeap(), 0, pNewString );
3680 /* Check range of value.
3682 dValue = round( dValue );
3683 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3685 return DISP_E_OVERFLOW;
3688 *pcOut = (CHAR) dValue;
3690 return S_OK;
3693 /******************************************************************************
3694 * VarI1FromBool32 [OLEAUT32.253]
3696 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3698 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3700 *pcOut = (CHAR) boolIn;
3702 return S_OK;
3705 /******************************************************************************
3706 * VarI1FromUI232 [OLEAUT32.254]
3708 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3710 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3712 if( uiIn > CHAR_MAX )
3714 return DISP_E_OVERFLOW;
3717 *pcOut = (CHAR) uiIn;
3719 return S_OK;
3722 /******************************************************************************
3723 * VarI1FromUI432 [OLEAUT32.255]
3725 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3727 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3729 if( ulIn > CHAR_MAX )
3731 return DISP_E_OVERFLOW;
3734 *pcOut = (CHAR) ulIn;
3736 return S_OK;
3739 /**********************************************************************
3740 * VarI1FromCy32 [OLEAUT32.250]
3741 * Convert currency to signed char
3743 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3744 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3746 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3748 *pcOut = (CHAR)t;
3749 return S_OK;
3752 /******************************************************************************
3753 * VarUI2FromUI132 [OLEAUT32.257]
3755 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3757 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3759 *puiOut = (USHORT) bIn;
3761 return S_OK;
3764 /******************************************************************************
3765 * VarUI2FromI232 [OLEAUT32.258]
3767 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3769 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3771 if( uiIn < UI2_MIN )
3773 return DISP_E_OVERFLOW;
3776 *puiOut = (USHORT) uiIn;
3778 return S_OK;
3781 /******************************************************************************
3782 * VarUI2FromI432 [OLEAUT32.259]
3784 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3786 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3788 if( lIn < UI2_MIN || lIn > UI2_MAX )
3790 return DISP_E_OVERFLOW;
3793 *puiOut = (USHORT) lIn;
3795 return S_OK;
3798 /******************************************************************************
3799 * VarUI2FromR432 [OLEAUT32.260]
3801 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3803 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3805 fltIn = round( fltIn );
3806 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3808 return DISP_E_OVERFLOW;
3811 *puiOut = (USHORT) fltIn;
3813 return S_OK;
3816 /******************************************************************************
3817 * VarUI2FromR832 [OLEAUT32.261]
3819 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3821 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3823 dblIn = round( dblIn );
3824 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3826 return DISP_E_OVERFLOW;
3829 *puiOut = (USHORT) dblIn;
3831 return S_OK;
3834 /******************************************************************************
3835 * VarUI2FromDate32 [OLEAUT32.262]
3837 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3839 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3841 dateIn = round( dateIn );
3842 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3844 return DISP_E_OVERFLOW;
3847 *puiOut = (USHORT) dateIn;
3849 return S_OK;
3852 /******************************************************************************
3853 * VarUI2FromStr32 [OLEAUT32.264]
3855 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3857 double dValue = 0.0;
3858 LPSTR pNewString = NULL;
3860 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3862 /* Check if we have a valid argument
3864 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3865 RemoveCharacterFromString( pNewString, "," );
3866 if( IsValidRealString( pNewString ) == FALSE )
3868 return DISP_E_TYPEMISMATCH;
3871 /* Convert the valid string to a floating point number.
3873 dValue = atof( pNewString );
3875 /* We don't need the string anymore so free it.
3877 HeapFree( GetProcessHeap(), 0, pNewString );
3879 /* Check range of value.
3881 dValue = round( dValue );
3882 if( dValue < UI2_MIN || dValue > UI2_MAX )
3884 return DISP_E_OVERFLOW;
3887 *puiOut = (USHORT) dValue;
3889 return S_OK;
3892 /******************************************************************************
3893 * VarUI2FromBool32 [OLEAUT32.266]
3895 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3897 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3899 *puiOut = (USHORT) boolIn;
3901 return S_OK;
3904 /******************************************************************************
3905 * VarUI2FromI132 [OLEAUT32.267]
3907 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3909 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3911 *puiOut = (USHORT) cIn;
3913 return S_OK;
3916 /******************************************************************************
3917 * VarUI2FromUI432 [OLEAUT32.268]
3919 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3921 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3923 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3925 return DISP_E_OVERFLOW;
3928 *puiOut = (USHORT) ulIn;
3930 return S_OK;
3933 /******************************************************************************
3934 * VarUI4FromStr32 [OLEAUT32.277]
3936 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3938 double dValue = 0.0;
3939 LPSTR pNewString = NULL;
3941 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3943 /* Check if we have a valid argument
3945 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3946 RemoveCharacterFromString( pNewString, "," );
3947 if( IsValidRealString( pNewString ) == FALSE )
3949 return DISP_E_TYPEMISMATCH;
3952 /* Convert the valid string to a floating point number.
3954 dValue = atof( pNewString );
3956 /* We don't need the string anymore so free it.
3958 HeapFree( GetProcessHeap(), 0, pNewString );
3960 /* Check range of value.
3962 dValue = round( dValue );
3963 if( dValue < UI4_MIN || dValue > UI4_MAX )
3965 return DISP_E_OVERFLOW;
3968 *pulOut = (ULONG) dValue;
3970 return S_OK;
3973 /**********************************************************************
3974 * VarUI2FromCy32 [OLEAUT32.263]
3975 * Convert currency to unsigned short
3977 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
3978 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3980 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
3982 *pusOut = (USHORT)t;
3984 return S_OK;
3987 /******************************************************************************
3988 * VarUI4FromUI132 [OLEAUT32.270]
3990 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
3992 TRACE("( %d, %p ), stub\n", bIn, pulOut );
3994 *pulOut = (USHORT) bIn;
3996 return S_OK;
3999 /******************************************************************************
4000 * VarUI4FromI232 [OLEAUT32.271]
4002 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4004 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4006 if( uiIn < UI4_MIN )
4008 return DISP_E_OVERFLOW;
4011 *pulOut = (ULONG) uiIn;
4013 return S_OK;
4016 /******************************************************************************
4017 * VarUI4FromI432 [OLEAUT32.272]
4019 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4021 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4023 if( lIn < UI4_MIN )
4025 return DISP_E_OVERFLOW;
4028 *pulOut = (ULONG) lIn;
4030 return S_OK;
4033 /******************************************************************************
4034 * VarUI4FromR432 [OLEAUT32.273]
4036 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4038 fltIn = round( fltIn );
4039 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4041 return DISP_E_OVERFLOW;
4044 *pulOut = (ULONG) fltIn;
4046 return S_OK;
4049 /******************************************************************************
4050 * VarUI4FromR832 [OLEAUT32.274]
4052 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4054 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4056 dblIn = round( dblIn );
4057 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4059 return DISP_E_OVERFLOW;
4062 *pulOut = (ULONG) dblIn;
4064 return S_OK;
4067 /******************************************************************************
4068 * VarUI4FromDate32 [OLEAUT32.275]
4070 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4072 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4074 dateIn = round( dateIn );
4075 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4077 return DISP_E_OVERFLOW;
4080 *pulOut = (ULONG) dateIn;
4082 return S_OK;
4085 /******************************************************************************
4086 * VarUI4FromBool32 [OLEAUT32.279]
4088 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4090 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4092 *pulOut = (ULONG) boolIn;
4094 return S_OK;
4097 /******************************************************************************
4098 * VarUI4FromI132 [OLEAUT32.280]
4100 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4102 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4104 *pulOut = (ULONG) cIn;
4106 return S_OK;
4109 /******************************************************************************
4110 * VarUI4FromUI232 [OLEAUT32.281]
4112 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4114 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4116 *pulOut = (ULONG) uiIn;
4118 return S_OK;
4121 /**********************************************************************
4122 * VarUI4FromCy32 [OLEAUT32.276]
4123 * Convert currency to unsigned long
4125 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4126 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4128 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4130 *pulOut = (ULONG)t;
4132 return S_OK;
4135 /**********************************************************************
4136 * VarCyFromUI132 [OLEAUT32.98]
4137 * Convert unsigned char to currency
4139 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4140 pcyOut->s.Hi = 0;
4141 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4143 return S_OK;
4146 /**********************************************************************
4147 * VarCyFromI232 [OLEAUT32.99]
4148 * Convert signed short to currency
4150 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4151 if (sIn < 0) pcyOut->s.Hi = -1;
4152 else pcyOut->s.Hi = 0;
4153 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4155 return S_OK;
4158 /**********************************************************************
4159 * VarCyFromI432 [OLEAUT32.100]
4160 * Convert signed long to currency
4162 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4163 double t = (double)lIn * (double)10000;
4164 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4165 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4166 if (lIn < 0) pcyOut->s.Hi--;
4168 return S_OK;
4171 /**********************************************************************
4172 * VarCyFromR432 [OLEAUT32.101]
4173 * Convert float to currency
4175 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4176 double t = round((double)fltIn * (double)10000);
4177 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4178 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4179 if (fltIn < 0) pcyOut->s.Hi--;
4181 return S_OK;
4184 /**********************************************************************
4185 * VarCyFromR832 [OLEAUT32.102]
4186 * Convert double to currency
4188 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4189 double t = round(dblIn * (double)10000);
4190 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4191 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4192 if (dblIn < 0) pcyOut->s.Hi--;
4194 return S_OK;
4197 /**********************************************************************
4198 * VarCyFromDate32 [OLEAUT32.103]
4199 * Convert date to currency
4201 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4202 double t = round((double)dateIn * (double)10000);
4203 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4204 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4205 if (dateIn < 0) pcyOut->s.Hi--;
4207 return S_OK;
4210 /**********************************************************************
4211 * VarCyFromDate32 [OLEAUT32.104]
4213 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4214 /* FIXME */
4215 return E_NOTIMPL;
4219 /**********************************************************************
4220 * VarCyFromBool32 [OLEAUT32.106]
4221 * Convert boolean to currency
4223 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4224 if (boolIn < 0) pcyOut->s.Hi = -1;
4225 else pcyOut->s.Hi = 0;
4226 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4228 return S_OK;
4231 /**********************************************************************
4232 * VarCyFromI132 [OLEAUT32.225]
4233 * Convert signed char to currency
4235 HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4236 if (cIn < 0) pcyOut->s.Hi = -1;
4237 else pcyOut->s.Hi = 0;
4238 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4240 return S_OK;
4243 /**********************************************************************
4244 * VarCyFromUI232 [OLEAUT32.226]
4245 * Convert unsigned short to currency
4247 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4248 pcyOut->s.Hi = 0;
4249 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4251 return S_OK;
4254 /**********************************************************************
4255 * VarCyFromUI432 [OLEAUT32.227]
4256 * Convert unsigned long to currency
4258 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4259 double t = (double)ulIn * (double)10000;
4260 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4261 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4263 return S_OK;
4267 /**********************************************************************
4268 * DosDateTimeToVariantTime [OLEAUT32.14]
4269 * Convert dos representation of time to the date and time representation
4270 * stored in a variant.
4272 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4273 DATE *pvtime)
4275 struct tm t;
4277 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4279 t.tm_sec = (wDosTime & 0x001f) * 2;
4280 t.tm_min = (wDosTime & 0x07e0) >> 5;
4281 t.tm_hour = (wDosTime & 0xf800) >> 11;
4283 t.tm_mday = (wDosDate & 0x001f);
4284 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4285 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4287 return TmToDATE( &t, pvtime );