Variants and safe arrays is now able to copy BSTR swith embedded null
[wine/wine-kai.git] / dlls / oleaut32 / variant.c
blob361f7c558fb81169a515acfe520d22d51b9457c7
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 dates prior to 1900.
20 * - The parsing does not accept as many formats as the Windows implementation.
23 #include "config.h"
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <time.h>
31 #ifdef HAVE_FLOAT_H
32 # include <float.h>
33 #endif
35 #include "windef.h"
36 #include "oleauto.h"
37 #include "heap.h"
38 #include "debugtools.h"
39 #include "winerror.h"
40 #include "parsedt.h"
42 DEFAULT_DEBUG_CHANNEL(ole);
44 #define SYSDUPSTRING(str) SysAllocStringLen((str), SysStringLen(str))
46 #ifndef FLT_MAX
47 # ifdef MAXFLOAT
48 # define FLT_MAX MAXFLOAT
49 # else
50 # error "Can't find #define for MAXFLOAT/FLT_MAX"
51 # endif
52 #endif
54 #undef CHAR_MAX
55 #undef CHAR_MIN
56 static const char CHAR_MAX = 127;
57 static const char CHAR_MIN = -128;
58 static const BYTE UI1_MAX = 255;
59 static const BYTE UI1_MIN = 0;
60 static const unsigned short UI2_MAX = 65535;
61 static const unsigned short UI2_MIN = 0;
62 static const short I2_MAX = 32767;
63 static const short I2_MIN = -32768;
64 static const unsigned long UI4_MAX = 4294967295U;
65 static const unsigned long UI4_MIN = 0;
66 static const long I4_MAX = 2147483647;
67 static const long I4_MIN = -(2147483648U);
68 static const DATE DATE_MIN = -657434;
69 static const DATE DATE_MAX = 2958465;
72 /* This mask is used to set a flag in wReserved1 of
73 * the VARIANTARG structure. The flag indicates if
74 * the API function is using an inner variant or not.
76 #define PROCESSING_INNER_VARIANT 0x0001
78 /* General use buffer.
80 #define BUFFER_MAX 1024
81 static char pBuffer[BUFFER_MAX];
84 * Note a leap year is one that is a multiple of 4
85 * but not of a 100. Except if it is a multiple of
86 * 400 then it is a leap year.
88 /* According to postgeSQL date parsing functions there is
89 * a leap year when this expression is true.
90 * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
91 * So according to this there is 365.2515 days in one year.
92 * One + every four years: 1/4 -> 365.25
93 * One - every 100 years: 1/100 -> 365.01
94 * One + every 400 years: 1/400 -> 365.0025
96 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
98 * ^^ Might this be the key to an easy way to factor large prime numbers?
99 * Let's try using arithmetic. <lawson_whitney@juno.com> 7 Mar 2000
101 static const double DAYS_IN_ONE_YEAR = 365.2425;
103 /******************************************************************************
104 * DateTimeStringToTm [INTERNAL]
106 * Converts a string representation of a date and/or time to a tm structure.
108 * Note this function uses the postgresql date parsing functions found
109 * in the parsedt.c file.
111 * Returns TRUE if successful.
113 * Note: This function does not parse the day of the week,
114 * daylight savings time. It will only fill the followin fields in
115 * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
117 ******************************************************************************/
118 static BOOL DateTimeStringToTm( OLECHAR* strIn, DWORD dwFlags, struct tm* pTm )
120 BOOL res = FALSE;
121 double fsec;
122 int tzp;
123 int dtype;
124 int nf;
125 char *field[MAXDATEFIELDS];
126 int ftype[MAXDATEFIELDS];
127 char lowstr[MAXDATELEN + 1];
128 char* strDateTime = NULL;
130 /* Convert the string to ASCII since this is the only format
131 * postgesql can handle.
133 strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
135 if( strDateTime != NULL )
137 /* Make sure we don't go over the maximum length
138 * accepted by postgesql.
140 if( strlen( strDateTime ) <= MAXDATELEN )
142 if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
144 if( dwFlags & VAR_DATEVALUEONLY )
146 /* Get the date information.
147 * It returns 0 if date information was
148 * present and 1 if only time information was present.
149 * -1 if an error occures.
151 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
153 /* Eliminate the time information since we
154 * were asked to get date information only.
156 pTm->tm_sec = 0;
157 pTm->tm_min = 0;
158 pTm->tm_hour = 0;
159 res = TRUE;
162 if( dwFlags & VAR_TIMEVALUEONLY )
164 /* Get time information only.
166 if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
168 res = TRUE;
171 else
173 /* Get both date and time information.
174 * It returns 0 if date information was
175 * present and 1 if only time information was present.
176 * -1 if an error occures.
178 if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
180 res = TRUE;
185 HeapFree( GetProcessHeap(), 0, strDateTime );
188 return res;
196 /******************************************************************************
197 * TmToDATE [INTERNAL]
199 * The date is implemented using an 8 byte floating-point number.
200 * Days are represented by whole numbers increments starting with 0.00 has
201 * being December 30 1899, midnight.
202 * The hours are expressed as the fractional part of the number.
203 * December 30 1899 at midnight = 0.00
204 * January 1 1900 at midnight = 2.00
205 * January 4 1900 at 6 AM = 5.25
206 * January 4 1900 at noon = 5.50
207 * December 29 1899 at midnight = -1.00
208 * December 18 1899 at midnight = -12.00
209 * December 18 1899 at 6AM = -12.25
210 * December 18 1899 at 6PM = -12.75
211 * December 19 1899 at midnight = -11.00
212 * The tm structure is as follows:
213 * struct tm {
214 * int tm_sec; seconds after the minute - [0,59]
215 * int tm_min; minutes after the hour - [0,59]
216 * int tm_hour; hours since midnight - [0,23]
217 * int tm_mday; day of the month - [1,31]
218 * int tm_mon; months since January - [0,11]
219 * int tm_year; years
220 * int tm_wday; days since Sunday - [0,6]
221 * int tm_yday; days since January 1 - [0,365]
222 * int tm_isdst; daylight savings time flag
223 * };
225 * Note: This function does not use the tm_wday, tm_yday, tm_wday,
226 * and tm_isdst fields of the tm structure. And only converts years
227 * after 1900.
229 * Returns TRUE if successful.
231 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
233 if( (pTm->tm_year - 1900) >= 0 )
235 int leapYear = 0;
237 /* Start at 1. This is the way DATE is defined.
238 * January 1, 1900 at Midnight is 1.00.
239 * January 1, 1900 at 6AM is 1.25.
240 * and so on.
242 *pDateOut = 1;
244 /* Add the number of days corresponding to
245 * tm_year.
247 *pDateOut += (pTm->tm_year - 1900) * 365;
249 /* Add the leap days in the previous years between now and 1900.
250 * Note a leap year is one that is a multiple of 4
251 * but not of a 100. Except if it is a multiple of
252 * 400 then it is a leap year.
254 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
255 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
256 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
258 /* Set the leap year flag if the
259 * current year specified by tm_year is a
260 * leap year. This will be used to add a day
261 * to the day count.
263 if( isleap( pTm->tm_year ) )
264 leapYear = 1;
266 /* Add the number of days corresponding to
267 * the month.
269 switch( pTm->tm_mon )
271 case 2:
272 *pDateOut += 31;
273 break;
274 case 3:
275 *pDateOut += ( 59 + leapYear );
276 break;
277 case 4:
278 *pDateOut += ( 90 + leapYear );
279 break;
280 case 5:
281 *pDateOut += ( 120 + leapYear );
282 break;
283 case 6:
284 *pDateOut += ( 151 + leapYear );
285 break;
286 case 7:
287 *pDateOut += ( 181 + leapYear );
288 break;
289 case 8:
290 *pDateOut += ( 212 + leapYear );
291 break;
292 case 9:
293 *pDateOut += ( 243 + leapYear );
294 break;
295 case 10:
296 *pDateOut += ( 273 + leapYear );
297 break;
298 case 11:
299 *pDateOut += ( 304 + leapYear );
300 break;
301 case 12:
302 *pDateOut += ( 334 + leapYear );
303 break;
305 /* Add the number of days in this month.
307 *pDateOut += pTm->tm_mday;
309 /* Add the number of seconds, minutes, and hours
310 * to the DATE. Note these are the fracionnal part
311 * of the DATE so seconds / number of seconds in a day.
313 *pDateOut += pTm->tm_hour / 24.0;
314 *pDateOut += pTm->tm_min / 1440.0;
315 *pDateOut += pTm->tm_sec / 86400.0;
316 return TRUE;
318 return FALSE;
321 /******************************************************************************
322 * DateToTm [INTERNAL]
324 * This function converts a windows DATE to a tm structure.
326 * It does not fill all the fields of the tm structure.
327 * Here is a list of the fields that are filled:
328 * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
330 * Note this function does not support dates before the January 1, 1900
331 * or ( dateIn < 2.0 ).
333 * Returns TRUE if successful.
335 static BOOL DateToTm( DATE dateIn, DWORD dwFlags, struct tm* pTm )
337 /* Do not process dates smaller than January 1, 1900.
338 * Which corresponds to 2.0 in the windows DATE format.
340 if( dateIn >= 2.0 )
342 double decimalPart = 0.0;
343 double wholePart = 0.0;
345 memset(pTm,0,sizeof(*pTm));
347 /* Because of the nature of DATE format which
348 * associates 2.0 to January 1, 1900. We will
349 * remove 1.0 from the whole part of the DATE
350 * so that in the following code 1.0
351 * will correspond to January 1, 1900.
352 * This simplifies the processing of the DATE value.
354 dateIn -= 1.0;
356 wholePart = (double) floor( dateIn );
357 decimalPart = fmod( dateIn, wholePart );
359 if( !(dwFlags & VAR_TIMEVALUEONLY) )
361 int nDay = 0;
362 int leapYear = 0;
363 double yearsSince1900 = 0;
364 /* Start at 1900, this is where the DATE time 0.0 starts.
366 pTm->tm_year = 1900;
367 /* find in what year the day in the "wholePart" falls into.
368 * add the value to the year field.
370 yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
371 pTm->tm_year += yearsSince1900;
372 /* determine if this is a leap year.
374 if( isleap( pTm->tm_year ) )
376 leapYear = 1;
377 wholePart++;
380 /* find what day of that year the "wholePart" corresponds to.
381 * Note: nDay is in [1-366] format
383 nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
384 /* Set the tm_yday value.
385 * Note: The day must be converted from [1-366] to [0-365]
387 /*pTm->tm_yday = nDay - 1;*/
388 /* find which month this day corresponds to.
390 if( nDay <= 31 )
392 pTm->tm_mday = nDay;
393 pTm->tm_mon = 0;
395 else if( nDay <= ( 59 + leapYear ) )
397 pTm->tm_mday = nDay - 31;
398 pTm->tm_mon = 1;
400 else if( nDay <= ( 90 + leapYear ) )
402 pTm->tm_mday = nDay - ( 59 + leapYear );
403 pTm->tm_mon = 2;
405 else if( nDay <= ( 120 + leapYear ) )
407 pTm->tm_mday = nDay - ( 90 + leapYear );
408 pTm->tm_mon = 3;
410 else if( nDay <= ( 151 + leapYear ) )
412 pTm->tm_mday = nDay - ( 120 + leapYear );
413 pTm->tm_mon = 4;
415 else if( nDay <= ( 181 + leapYear ) )
417 pTm->tm_mday = nDay - ( 151 + leapYear );
418 pTm->tm_mon = 5;
420 else if( nDay <= ( 212 + leapYear ) )
422 pTm->tm_mday = nDay - ( 181 + leapYear );
423 pTm->tm_mon = 6;
425 else if( nDay <= ( 243 + leapYear ) )
427 pTm->tm_mday = nDay - ( 212 + leapYear );
428 pTm->tm_mon = 7;
430 else if( nDay <= ( 273 + leapYear ) )
432 pTm->tm_mday = nDay - ( 243 + leapYear );
433 pTm->tm_mon = 8;
435 else if( nDay <= ( 304 + leapYear ) )
437 pTm->tm_mday = nDay - ( 273 + leapYear );
438 pTm->tm_mon = 9;
440 else if( nDay <= ( 334 + leapYear ) )
442 pTm->tm_mday = nDay - ( 304 + leapYear );
443 pTm->tm_mon = 10;
445 else if( nDay <= ( 365 + leapYear ) )
447 pTm->tm_mday = nDay - ( 334 + leapYear );
448 pTm->tm_mon = 11;
451 if( !(dwFlags & VAR_DATEVALUEONLY) )
453 /* find the number of seconds in this day.
454 * fractional part times, hours, minutes, seconds.
456 pTm->tm_hour = (int) ( decimalPart * 24 );
457 pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
458 pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
460 return TRUE;
462 return FALSE;
467 /******************************************************************************
468 * SizeOfVariantData [INTERNAL]
470 * This function finds the size of the data referenced by a Variant based
471 * the type "vt" of the Variant.
473 static int SizeOfVariantData( VARIANT* parg )
475 int size = 0;
476 switch( V_VT(parg) & VT_TYPEMASK )
478 case( VT_I2 ):
479 size = sizeof(short);
480 break;
481 case( VT_INT ):
482 size = sizeof(int);
483 break;
484 case( VT_I4 ):
485 size = sizeof(long);
486 break;
487 case( VT_UI1 ):
488 size = sizeof(BYTE);
489 break;
490 case( VT_UI2 ):
491 size = sizeof(unsigned short);
492 break;
493 case( VT_UINT ):
494 size = sizeof(unsigned int);
495 break;
496 case( VT_UI4 ):
497 size = sizeof(unsigned long);
498 break;
499 case( VT_R4 ):
500 size = sizeof(float);
501 break;
502 case( VT_R8 ):
503 size = sizeof(double);
504 break;
505 case( VT_DATE ):
506 size = sizeof(DATE);
507 break;
508 case( VT_BOOL ):
509 size = sizeof(VARIANT_BOOL);
510 break;
511 case( VT_BSTR ):
512 size = sizeof(void*);
513 break;
514 case( VT_CY ):
515 case( VT_DISPATCH ):
516 case( VT_UNKNOWN ):
517 case( VT_DECIMAL ):
518 default:
519 FIXME("Add size information for type vt=%d\n", V_VT(parg) & VT_TYPEMASK );
520 break;
523 return size;
525 /******************************************************************************
526 * StringDupAtoBstr [INTERNAL]
529 static BSTR StringDupAtoBstr( char* strIn )
531 BSTR bstr = NULL;
532 OLECHAR* pNewString = NULL;
533 pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
534 bstr = SysAllocString( pNewString );
535 HeapFree( GetProcessHeap(), 0, pNewString );
536 return bstr;
539 /******************************************************************************
540 * round [INTERNAL]
542 * Round the double value to the nearest integer value.
544 static double round( double d )
546 double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
547 BOOL bEvenNumber = FALSE;
548 int nSign = 0;
550 /* Save the sign of the number
552 nSign = (d >= 0.0) ? 1 : -1;
553 d = fabs( d );
555 /* Remove the decimals.
557 integerValue = floor( d );
559 /* Set the Even flag. This is used to round the number when
560 * the decimals are exactly 1/2. If the integer part is
561 * odd the number is rounded up. If the integer part
562 * is even the number is rounded down. Using this method
563 * numbers are rounded up|down half the time.
565 bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
567 /* Remove the integral part of the number.
569 decimals = d - integerValue;
571 /* Note: Ceil returns the smallest integer that is greater that x.
572 * and floor returns the largest integer that is less than or equal to x.
574 if( decimals > 0.5 )
576 /* If the decimal part is greater than 1/2
578 roundedValue = ceil( d );
580 else if( decimals < 0.5 )
582 /* If the decimal part is smaller than 1/2
584 roundedValue = floor( d );
586 else
588 /* the decimals are exactly 1/2 so round according to
589 * the bEvenNumber flag.
591 if( bEvenNumber )
593 roundedValue = floor( d );
595 else
597 roundedValue = ceil( d );
601 return roundedValue * nSign;
604 /******************************************************************************
605 * RemoveCharacterFromString [INTERNAL]
607 * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
609 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
611 LPSTR pNewString = NULL;
612 LPSTR strToken = NULL;
615 /* Check if we have a valid argument
617 if( str != NULL )
619 pNewString = strdup( str );
620 str[0] = '\0';
621 strToken = strtok( pNewString, strOfCharToRemove );
622 while( strToken != NULL ) {
623 strcat( str, strToken );
624 strToken = strtok( NULL, strOfCharToRemove );
626 free( pNewString );
628 return;
631 /******************************************************************************
632 * GetValidRealString [INTERNAL]
634 * Checks if the string is of proper format to be converted to a real value.
636 static BOOL IsValidRealString( LPSTR strRealString )
638 /* Real values that have a decimal point are required to either have
639 * digits before or after the decimal point. We will assume that
640 * we do not have any digits at either position. If we do encounter
641 * some we will disable this flag.
643 BOOL bDigitsRequired = TRUE;
644 /* Processed fields in the string representation of the real number.
646 BOOL bWhiteSpaceProcessed = FALSE;
647 BOOL bFirstSignProcessed = FALSE;
648 BOOL bFirstDigitsProcessed = FALSE;
649 BOOL bDecimalPointProcessed = FALSE;
650 BOOL bSecondDigitsProcessed = FALSE;
651 BOOL bExponentProcessed = FALSE;
652 BOOL bSecondSignProcessed = FALSE;
653 BOOL bThirdDigitsProcessed = FALSE;
654 /* Assume string parameter "strRealString" is valid and try to disprove it.
656 BOOL bValidRealString = TRUE;
658 /* Used to count the number of tokens in the "strRealString".
660 LPSTR strToken = NULL;
661 int nTokens = 0;
662 LPSTR pChar = NULL;
664 /* Check if we have a valid argument
666 if( strRealString == NULL )
668 bValidRealString = FALSE;
671 if( bValidRealString == TRUE )
673 /* Make sure we only have ONE token in the string.
675 strToken = strtok( strRealString, " " );
676 while( strToken != NULL ) {
677 nTokens++;
678 strToken = strtok( NULL, " " );
681 if( nTokens != 1 )
683 bValidRealString = FALSE;
688 /* Make sure this token contains only valid characters.
689 * The string argument to atof has the following form:
690 * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
691 * Whitespace consists of space and|or <TAB> characters, which are ignored.
692 * Sign is either plus '+' or minus '-'.
693 * Digits are one or more decimal digits.
694 * Note: If no digits appear before the decimal point, at least one must
695 * appear after the decimal point.
696 * The decimal digits may be followed by an exponent.
697 * An Exponent consists of an introductory letter ( D, d, E, or e) and
698 * an optionally signed decimal integer.
700 pChar = strRealString;
701 while( bValidRealString == TRUE && *pChar != '\0' )
703 switch( *pChar )
705 /* If whitespace...
707 case ' ':
708 case '\t':
709 if( bWhiteSpaceProcessed ||
710 bFirstSignProcessed ||
711 bFirstDigitsProcessed ||
712 bDecimalPointProcessed ||
713 bSecondDigitsProcessed ||
714 bExponentProcessed ||
715 bSecondSignProcessed ||
716 bThirdDigitsProcessed )
718 bValidRealString = FALSE;
720 break;
721 /* If sign...
723 case '+':
724 case '-':
725 if( bFirstSignProcessed == FALSE )
727 if( bFirstDigitsProcessed ||
728 bDecimalPointProcessed ||
729 bSecondDigitsProcessed ||
730 bExponentProcessed ||
731 bSecondSignProcessed ||
732 bThirdDigitsProcessed )
734 bValidRealString = FALSE;
736 bWhiteSpaceProcessed = TRUE;
737 bFirstSignProcessed = TRUE;
739 else if( bSecondSignProcessed == FALSE )
741 /* Note: The exponent must be present in
742 * order to accept the second sign...
744 if( bExponentProcessed == FALSE ||
745 bThirdDigitsProcessed ||
746 bDigitsRequired )
748 bValidRealString = FALSE;
750 bFirstSignProcessed = TRUE;
751 bWhiteSpaceProcessed = TRUE;
752 bFirstDigitsProcessed = TRUE;
753 bDecimalPointProcessed = TRUE;
754 bSecondDigitsProcessed = TRUE;
755 bSecondSignProcessed = TRUE;
757 break;
759 /* If decimals...
761 case '0':
762 case '1':
763 case '2':
764 case '3':
765 case '4':
766 case '5':
767 case '6':
768 case '7':
769 case '8':
770 case '9':
771 if( bFirstDigitsProcessed == FALSE )
773 if( bDecimalPointProcessed ||
774 bSecondDigitsProcessed ||
775 bExponentProcessed ||
776 bSecondSignProcessed ||
777 bThirdDigitsProcessed )
779 bValidRealString = FALSE;
781 bFirstSignProcessed = TRUE;
782 bWhiteSpaceProcessed = TRUE;
783 /* We have found some digits before the decimal point
784 * so disable the "Digits required" flag.
786 bDigitsRequired = FALSE;
788 else if( bSecondDigitsProcessed == FALSE )
790 if( bExponentProcessed ||
791 bSecondSignProcessed ||
792 bThirdDigitsProcessed )
794 bValidRealString = FALSE;
796 bFirstSignProcessed = TRUE;
797 bWhiteSpaceProcessed = TRUE;
798 bFirstDigitsProcessed = TRUE;
799 bDecimalPointProcessed = TRUE;
800 /* We have found some digits after the decimal point
801 * so disable the "Digits required" flag.
803 bDigitsRequired = FALSE;
805 else if( bThirdDigitsProcessed == FALSE )
807 /* Getting here means everything else should be processed.
808 * If we get anything else than a decimal following this
809 * digit it will be flagged by the other cases, so
810 * we do not really need to do anything in here.
813 break;
814 /* If DecimalPoint...
816 case '.':
817 if( bDecimalPointProcessed ||
818 bSecondDigitsProcessed ||
819 bExponentProcessed ||
820 bSecondSignProcessed ||
821 bThirdDigitsProcessed )
823 bValidRealString = FALSE;
825 bFirstSignProcessed = TRUE;
826 bWhiteSpaceProcessed = TRUE;
827 bFirstDigitsProcessed = TRUE;
828 bDecimalPointProcessed = TRUE;
829 break;
830 /* If Exponent...
832 case 'e':
833 case 'E':
834 case 'd':
835 case 'D':
836 if( bExponentProcessed ||
837 bSecondSignProcessed ||
838 bThirdDigitsProcessed ||
839 bDigitsRequired )
841 bValidRealString = FALSE;
843 bFirstSignProcessed = TRUE;
844 bWhiteSpaceProcessed = TRUE;
845 bFirstDigitsProcessed = TRUE;
846 bDecimalPointProcessed = TRUE;
847 bSecondDigitsProcessed = TRUE;
848 bExponentProcessed = TRUE;
849 break;
850 default:
851 bValidRealString = FALSE;
852 break;
854 /* Process next character.
856 pChar++;
859 /* If the required digits were not present we have an invalid
860 * string representation of a real number.
862 if( bDigitsRequired == TRUE )
864 bValidRealString = FALSE;
867 return bValidRealString;
871 /******************************************************************************
872 * Coerce [INTERNAL]
874 * This function dispatches execution to the proper conversion API
875 * to do the necessary coercion.
877 * FIXME: Passing down dwFlags to the conversion functions is wrong, this
878 * is a different flagmask. Check MSDN.
880 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
882 HRESULT res = S_OK;
883 unsigned short vtFrom = 0;
884 vtFrom = V_VT(ps) & VT_TYPEMASK;
887 /* Note: Since "long" and "int" values both have 4 bytes and are
888 * both signed integers "int" will be treated as "long" in the
889 * following code.
890 * The same goes for their unsigned versions.
893 /* Trivial Case: If the coercion is from two types that are
894 * identical then we can blindly copy from one argument to another.*/
895 if ((vt==vtFrom))
897 return VariantCopy(pd,ps);
900 /* Cases requiring thought*/
901 switch( vt )
904 case( VT_EMPTY ):
905 res = VariantClear( pd );
906 break;
907 case( VT_NULL ):
908 res = VariantClear( pd );
909 if( res == S_OK )
911 V_VT(pd) = VT_NULL;
913 break;
914 case( VT_I1 ):
915 switch( vtFrom )
917 case( VT_I1 ):
918 res = VariantCopy( pd, ps );
919 break;
920 case( VT_I2 ):
921 res = VarI1FromI2( V_UNION(ps,iVal), &V_UNION(pd,cVal) );
922 break;
923 case( VT_INT ):
924 case( VT_I4 ):
925 res = VarI1FromI4( V_UNION(ps,lVal), &V_UNION(pd,cVal) );
926 break;
927 case( VT_UI1 ):
928 res = VarI1FromUI1( V_UNION(ps,bVal), &V_UNION(pd,cVal) );
929 break;
930 case( VT_UI2 ):
931 res = VarI1FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,cVal) );
932 break;
933 case( VT_UINT ):
934 case( VT_UI4 ):
935 res = VarI1FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,cVal) );
936 break;
937 case( VT_R4 ):
938 res = VarI1FromR4( V_UNION(ps,fltVal), &V_UNION(pd,cVal) );
939 break;
940 case( VT_R8 ):
941 res = VarI1FromR8( V_UNION(ps,dblVal), &V_UNION(pd,cVal) );
942 break;
943 case( VT_DATE ):
944 res = VarI1FromDate( V_UNION(ps,date), &V_UNION(pd,cVal) );
945 break;
946 case( VT_BOOL ):
947 res = VarI1FromBool( V_UNION(ps,boolVal), &V_UNION(pd,cVal) );
948 break;
949 case( VT_BSTR ):
950 res = VarI1FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,cVal) );
951 break;
952 case( VT_CY ):
953 res = VarI1FromCy( V_UNION(ps,cyVal), &V_UNION(pd,cVal) );
954 break;
955 case( VT_DISPATCH ):
956 /*res = VarI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cVal) );*/
957 case( VT_DECIMAL ):
958 /*res = VarI1FromDec( V_UNION(ps,decVal), &V_UNION(pd,cVal) );*/
959 case( VT_UNKNOWN ):
960 default:
961 res = DISP_E_TYPEMISMATCH;
962 FIXME("Coercion from %d to %d\n", vtFrom, vt );
963 break;
965 break;
967 case( VT_I2 ):
968 switch( vtFrom )
970 case( VT_I1 ):
971 res = VarI2FromI1( V_UNION(ps,cVal), &V_UNION(pd,iVal) );
972 break;
973 case( VT_I2 ):
974 res = VariantCopy( pd, ps );
975 break;
976 case( VT_INT ):
977 case( VT_I4 ):
978 res = VarI2FromI4( V_UNION(ps,lVal), &V_UNION(pd,iVal) );
979 break;
980 case( VT_UI1 ):
981 res = VarI2FromUI1( V_UNION(ps,bVal), &V_UNION(pd,iVal) );
982 break;
983 case( VT_UI2 ):
984 res = VarI2FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,iVal) );
985 break;
986 case( VT_UINT ):
987 case( VT_UI4 ):
988 res = VarI2FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,iVal) );
989 break;
990 case( VT_R4 ):
991 res = VarI2FromR4( V_UNION(ps,fltVal), &V_UNION(pd,iVal) );
992 break;
993 case( VT_R8 ):
994 res = VarI2FromR8( V_UNION(ps,dblVal), &V_UNION(pd,iVal) );
995 break;
996 case( VT_DATE ):
997 res = VarI2FromDate( V_UNION(ps,date), &V_UNION(pd,iVal) );
998 break;
999 case( VT_BOOL ):
1000 res = VarI2FromBool( V_UNION(ps,boolVal), &V_UNION(pd,iVal) );
1001 break;
1002 case( VT_BSTR ):
1003 res = VarI2FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,iVal) );
1004 break;
1005 case( VT_CY ):
1006 res = VarI2FromCy( V_UNION(ps,cyVal), &V_UNION(pd,iVal) );
1007 break;
1008 case( VT_DISPATCH ):
1009 /*res = VarI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,iVal) );*/
1010 case( VT_DECIMAL ):
1011 /*res = VarI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,iVal) );*/
1012 case( VT_UNKNOWN ):
1013 default:
1014 res = DISP_E_TYPEMISMATCH;
1015 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1016 break;
1018 break;
1020 case( VT_INT ):
1021 case( VT_I4 ):
1022 switch( vtFrom )
1024 case( VT_I1 ):
1025 res = VarI4FromI1( V_UNION(ps,cVal), &V_UNION(pd,lVal) );
1026 break;
1027 case( VT_I2 ):
1028 res = VarI4FromI2( V_UNION(ps,iVal), &V_UNION(pd,lVal) );
1029 break;
1030 case( VT_INT ):
1031 case( VT_I4 ):
1032 res = VariantCopy( pd, ps );
1033 break;
1034 case( VT_UI1 ):
1035 res = VarI4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,lVal) );
1036 break;
1037 case( VT_UI2 ):
1038 res = VarI4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,lVal) );
1039 break;
1040 case( VT_UINT ):
1041 case( VT_UI4 ):
1042 res = VarI4FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,lVal) );
1043 break;
1044 case( VT_R4 ):
1045 res = VarI4FromR4( V_UNION(ps,fltVal), &V_UNION(pd,lVal) );
1046 break;
1047 case( VT_R8 ):
1048 res = VarI4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,lVal) );
1049 break;
1050 case( VT_DATE ):
1051 res = VarI4FromDate( V_UNION(ps,date), &V_UNION(pd,lVal) );
1052 break;
1053 case( VT_BOOL ):
1054 res = VarI4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,lVal) );
1055 break;
1056 case( VT_BSTR ):
1057 res = VarI4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,lVal) );
1058 break;
1059 case( VT_CY ):
1060 res = VarI4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,lVal) );
1061 break;
1062 case( VT_DISPATCH ):
1063 /*res = VarI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,lVal) );*/
1064 case( VT_DECIMAL ):
1065 /*res = VarI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,lVal) );*/
1066 case( VT_UNKNOWN ):
1067 default:
1068 res = DISP_E_TYPEMISMATCH;
1069 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1070 break;
1072 break;
1074 case( VT_UI1 ):
1075 switch( vtFrom )
1077 case( VT_I1 ):
1078 res = VarUI1FromI1( V_UNION(ps,cVal), &V_UNION(pd,bVal) );
1079 break;
1080 case( VT_I2 ):
1081 res = VarUI1FromI2( V_UNION(ps,iVal), &V_UNION(pd,bVal) );
1082 break;
1083 case( VT_INT ):
1084 case( VT_I4 ):
1085 res = VarUI1FromI4( V_UNION(ps,lVal), &V_UNION(pd,bVal) );
1086 break;
1087 case( VT_UI1 ):
1088 res = VariantCopy( pd, ps );
1089 break;
1090 case( VT_UI2 ):
1091 res = VarUI1FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,bVal) );
1092 break;
1093 case( VT_UINT ):
1094 case( VT_UI4 ):
1095 res = VarUI1FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,bVal) );
1096 break;
1097 case( VT_R4 ):
1098 res = VarUI1FromR4( V_UNION(ps,fltVal), &V_UNION(pd,bVal) );
1099 break;
1100 case( VT_R8 ):
1101 res = VarUI1FromR8( V_UNION(ps,dblVal), &V_UNION(pd,bVal) );
1102 break;
1103 case( VT_DATE ):
1104 res = VarUI1FromDate( V_UNION(ps,date), &V_UNION(pd,bVal) );
1105 break;
1106 case( VT_BOOL ):
1107 res = VarUI1FromBool( V_UNION(ps,boolVal), &V_UNION(pd,bVal) );
1108 break;
1109 case( VT_BSTR ):
1110 res = VarUI1FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,bVal) );
1111 break;
1112 case( VT_CY ):
1113 res = VarUI1FromCy( V_UNION(ps,cyVal), &V_UNION(pd,bVal) );
1114 break;
1115 case( VT_DISPATCH ):
1116 /*res = VarUI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,bVal) );*/
1117 case( VT_DECIMAL ):
1118 /*res = VarUI1FromDec( V_UNION(ps,deiVal), &V_UNION(pd,bVal) );*/
1119 case( VT_UNKNOWN ):
1120 default:
1121 res = DISP_E_TYPEMISMATCH;
1122 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1123 break;
1125 break;
1127 case( VT_UI2 ):
1128 switch( vtFrom )
1130 case( VT_I1 ):
1131 res = VarUI2FromI1( V_UNION(ps,cVal), &V_UNION(pd,uiVal) );
1132 break;
1133 case( VT_I2 ):
1134 res = VarUI2FromI2( V_UNION(ps,iVal), &V_UNION(pd,uiVal) );
1135 break;
1136 case( VT_INT ):
1137 case( VT_I4 ):
1138 res = VarUI2FromI4( V_UNION(ps,lVal), &V_UNION(pd,uiVal) );
1139 break;
1140 case( VT_UI1 ):
1141 res = VarUI2FromUI1( V_UNION(ps,bVal), &V_UNION(pd,uiVal) );
1142 break;
1143 case( VT_UI2 ):
1144 res = VariantCopy( pd, ps );
1145 break;
1146 case( VT_UINT ):
1147 case( VT_UI4 ):
1148 res = VarUI2FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,uiVal) );
1149 break;
1150 case( VT_R4 ):
1151 res = VarUI2FromR4( V_UNION(ps,fltVal), &V_UNION(pd,uiVal) );
1152 break;
1153 case( VT_R8 ):
1154 res = VarUI2FromR8( V_UNION(ps,dblVal), &V_UNION(pd,uiVal) );
1155 break;
1156 case( VT_DATE ):
1157 res = VarUI2FromDate( V_UNION(ps,date), &V_UNION(pd,uiVal) );
1158 break;
1159 case( VT_BOOL ):
1160 res = VarUI2FromBool( V_UNION(ps,boolVal), &V_UNION(pd,uiVal) );
1161 break;
1162 case( VT_BSTR ):
1163 res = VarUI2FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,uiVal) );
1164 break;
1165 case( VT_CY ):
1166 res = VarUI2FromCy( V_UNION(ps,cyVal), &V_UNION(pd,uiVal) );
1167 break;
1168 case( VT_DISPATCH ):
1169 /*res = VarUI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,uiVal) );*/
1170 case( VT_DECIMAL ):
1171 /*res = VarUI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,uiVal) );*/
1172 case( VT_UNKNOWN ):
1173 default:
1174 res = DISP_E_TYPEMISMATCH;
1175 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1176 break;
1178 break;
1180 case( VT_UINT ):
1181 case( VT_UI4 ):
1182 switch( vtFrom )
1184 case( VT_I1 ):
1185 res = VarUI4FromI1( V_UNION(ps,cVal), &V_UNION(pd,ulVal) );
1186 break;
1187 case( VT_I2 ):
1188 res = VarUI4FromI2( V_UNION(ps,iVal), &V_UNION(pd,ulVal) );
1189 break;
1190 case( VT_INT ):
1191 case( VT_I4 ):
1192 res = VarUI4FromI4( V_UNION(ps,lVal), &V_UNION(pd,ulVal) );
1193 break;
1194 case( VT_UI1 ):
1195 res = VarUI4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,ulVal) );
1196 break;
1197 case( VT_UI2 ):
1198 res = VarUI4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,ulVal) );
1199 break;
1200 case( VT_UI4 ):
1201 res = VariantCopy( pd, ps );
1202 break;
1203 case( VT_R4 ):
1204 res = VarUI4FromR4( V_UNION(ps,fltVal), &V_UNION(pd,ulVal) );
1205 break;
1206 case( VT_R8 ):
1207 res = VarUI4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,ulVal) );
1208 break;
1209 case( VT_DATE ):
1210 res = VarUI4FromDate( V_UNION(ps,date), &V_UNION(pd,ulVal) );
1211 break;
1212 case( VT_BOOL ):
1213 res = VarUI4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,ulVal) );
1214 break;
1215 case( VT_BSTR ):
1216 res = VarUI4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,ulVal) );
1217 break;
1218 case( VT_CY ):
1219 res = VarUI4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,ulVal) );
1220 break;
1221 case( VT_DISPATCH ):
1222 /*res = VarUI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,ulVal) );*/
1223 case( VT_DECIMAL ):
1224 /*res = VarUI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,ulVal) );*/
1225 case( VT_UNKNOWN ):
1226 default:
1227 res = DISP_E_TYPEMISMATCH;
1228 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1229 break;
1231 break;
1233 case( VT_R4 ):
1234 switch( vtFrom )
1236 case( VT_I1 ):
1237 res = VarR4FromI1( V_UNION(ps,cVal), &V_UNION(pd,fltVal) );
1238 break;
1239 case( VT_I2 ):
1240 res = VarR4FromI2( V_UNION(ps,iVal), &V_UNION(pd,fltVal) );
1241 break;
1242 case( VT_INT ):
1243 case( VT_I4 ):
1244 res = VarR4FromI4( V_UNION(ps,lVal), &V_UNION(pd,fltVal) );
1245 break;
1246 case( VT_UI1 ):
1247 res = VarR4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,fltVal) );
1248 break;
1249 case( VT_UI2 ):
1250 res = VarR4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,fltVal) );
1251 break;
1252 case( VT_UINT ):
1253 case( VT_UI4 ):
1254 res = VarR4FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,fltVal) );
1255 break;
1256 case( VT_R4 ):
1257 res = VariantCopy( pd, ps );
1258 break;
1259 case( VT_R8 ):
1260 res = VarR4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,fltVal) );
1261 break;
1262 case( VT_DATE ):
1263 res = VarR4FromDate( V_UNION(ps,date), &V_UNION(pd,fltVal) );
1264 break;
1265 case( VT_BOOL ):
1266 res = VarR4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,fltVal) );
1267 break;
1268 case( VT_BSTR ):
1269 res = VarR4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,fltVal) );
1270 break;
1271 case( VT_CY ):
1272 res = VarR4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,fltVal) );
1273 break;
1274 case( VT_DISPATCH ):
1275 /*res = VarR4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,fltVal) );*/
1276 case( VT_DECIMAL ):
1277 /*res = VarR4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,fltVal) );*/
1278 case( VT_UNKNOWN ):
1279 default:
1280 res = DISP_E_TYPEMISMATCH;
1281 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1282 break;
1284 break;
1286 case( VT_R8 ):
1287 switch( vtFrom )
1289 case( VT_I1 ):
1290 res = VarR8FromI1( V_UNION(ps,cVal), &V_UNION(pd,dblVal) );
1291 break;
1292 case( VT_I2 ):
1293 res = VarR8FromI2( V_UNION(ps,iVal), &V_UNION(pd,dblVal) );
1294 break;
1295 case( VT_INT ):
1296 case( VT_I4 ):
1297 res = VarR8FromI4( V_UNION(ps,lVal), &V_UNION(pd,dblVal) );
1298 break;
1299 case( VT_UI1 ):
1300 res = VarR8FromUI1( V_UNION(ps,bVal), &V_UNION(pd,dblVal) );
1301 break;
1302 case( VT_UI2 ):
1303 res = VarR8FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,dblVal) );
1304 break;
1305 case( VT_UINT ):
1306 case( VT_UI4 ):
1307 res = VarR8FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,dblVal) );
1308 break;
1309 case( VT_R4 ):
1310 res = VarR8FromR4( V_UNION(ps,fltVal), &V_UNION(pd,dblVal) );
1311 break;
1312 case( VT_R8 ):
1313 res = VariantCopy( pd, ps );
1314 break;
1315 case( VT_DATE ):
1316 res = VarR8FromDate( V_UNION(ps,date), &V_UNION(pd,dblVal) );
1317 break;
1318 case( VT_BOOL ):
1319 res = VarR8FromBool( V_UNION(ps,boolVal), &V_UNION(pd,dblVal) );
1320 break;
1321 case( VT_BSTR ):
1322 res = VarR8FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,dblVal) );
1323 break;
1324 case( VT_CY ):
1325 res = VarR8FromCy( V_UNION(ps,cyVal), &V_UNION(pd,dblVal) );
1326 break;
1327 case( VT_DISPATCH ):
1328 /*res = VarR8FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,dblVal) );*/
1329 case( VT_DECIMAL ):
1330 /*res = VarR8FromDec( V_UNION(ps,deiVal), &V_UNION(pd,dblVal) );*/
1331 case( VT_UNKNOWN ):
1332 default:
1333 res = DISP_E_TYPEMISMATCH;
1334 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1335 break;
1337 break;
1339 case( VT_DATE ):
1340 switch( vtFrom )
1342 case( VT_I1 ):
1343 res = VarDateFromI1( V_UNION(ps,cVal), &V_UNION(pd,date) );
1344 break;
1345 case( VT_I2 ):
1346 res = VarDateFromI2( V_UNION(ps,iVal), &V_UNION(pd,date) );
1347 break;
1348 case( VT_INT ):
1349 res = VarDateFromInt( V_UNION(ps,intVal), &V_UNION(pd,date) );
1350 break;
1351 case( VT_I4 ):
1352 res = VarDateFromI4( V_UNION(ps,lVal), &V_UNION(pd,date) );
1353 break;
1354 case( VT_UI1 ):
1355 res = VarDateFromUI1( V_UNION(ps,bVal), &V_UNION(pd,date) );
1356 break;
1357 case( VT_UI2 ):
1358 res = VarDateFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,date) );
1359 break;
1360 case( VT_UINT ):
1361 res = VarDateFromUint( V_UNION(ps,uintVal), &V_UNION(pd,date) );
1362 break;
1363 case( VT_UI4 ):
1364 res = VarDateFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,date) );
1365 break;
1366 case( VT_R4 ):
1367 res = VarDateFromR4( V_UNION(ps,fltVal), &V_UNION(pd,date) );
1368 break;
1369 case( VT_R8 ):
1370 res = VarDateFromR8( V_UNION(ps,dblVal), &V_UNION(pd,date) );
1371 break;
1372 case( VT_DATE ):
1373 res = VariantCopy( pd, ps );
1374 break;
1375 case( VT_BOOL ):
1376 res = VarDateFromBool( V_UNION(ps,boolVal), &V_UNION(pd,date) );
1377 break;
1378 case( VT_BSTR ):
1379 res = VarDateFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,date) );
1380 break;
1381 case( VT_CY ):
1382 res = VarDateFromCy( V_UNION(ps,cyVal), &V_UNION(pd,date) );
1383 break;
1384 case( VT_DISPATCH ):
1385 /*res = VarDateFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,date) );*/
1386 case( VT_DECIMAL ):
1387 /*res = VarDateFromDec( V_UNION(ps,deiVal), &V_UNION(pd,date) );*/
1388 case( VT_UNKNOWN ):
1389 default:
1390 res = DISP_E_TYPEMISMATCH;
1391 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1392 break;
1394 break;
1396 case( VT_BOOL ):
1397 switch( vtFrom )
1399 case( VT_I1 ):
1400 res = VarBoolFromI1( V_UNION(ps,cVal), &V_UNION(pd,boolVal) );
1401 break;
1402 case( VT_I2 ):
1403 res = VarBoolFromI2( V_UNION(ps,iVal), &V_UNION(pd,boolVal) );
1404 break;
1405 case( VT_INT ):
1406 res = VarBoolFromInt( V_UNION(ps,intVal), &V_UNION(pd,boolVal) );
1407 break;
1408 case( VT_I4 ):
1409 res = VarBoolFromI4( V_UNION(ps,lVal), &V_UNION(pd,boolVal) );
1410 break;
1411 case( VT_UI1 ):
1412 res = VarBoolFromUI1( V_UNION(ps,bVal), &V_UNION(pd,boolVal) );
1413 break;
1414 case( VT_UI2 ):
1415 res = VarBoolFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,boolVal) );
1416 break;
1417 case( VT_UINT ):
1418 res = VarBoolFromUint( V_UNION(ps,uintVal), &V_UNION(pd,boolVal) );
1419 break;
1420 case( VT_UI4 ):
1421 res = VarBoolFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,boolVal) );
1422 break;
1423 case( VT_R4 ):
1424 res = VarBoolFromR4( V_UNION(ps,fltVal), &V_UNION(pd,boolVal) );
1425 break;
1426 case( VT_R8 ):
1427 res = VarBoolFromR8( V_UNION(ps,dblVal), &V_UNION(pd,boolVal) );
1428 break;
1429 case( VT_DATE ):
1430 res = VarBoolFromDate( V_UNION(ps,date), &V_UNION(pd,boolVal) );
1431 break;
1432 case( VT_BOOL ):
1433 res = VariantCopy( pd, ps );
1434 break;
1435 case( VT_BSTR ):
1436 res = VarBoolFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,boolVal) );
1437 break;
1438 case( VT_CY ):
1439 res = VarBoolFromCy( V_UNION(ps,cyVal), &V_UNION(pd,boolVal) );
1440 break;
1441 case( VT_DISPATCH ):
1442 /*res = VarBoolFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,boolVal) );*/
1443 case( VT_DECIMAL ):
1444 /*res = VarBoolFromDec( V_UNION(ps,deiVal), &V_UNION(pd,boolVal) );*/
1445 case( VT_UNKNOWN ):
1446 default:
1447 res = DISP_E_TYPEMISMATCH;
1448 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1449 break;
1451 break;
1453 case( VT_BSTR ):
1454 switch( vtFrom )
1456 case( VT_EMPTY ):
1457 if ((V_UNION(pd,bstrVal) = SysAllocStringLen(NULL, 0)))
1458 res = S_OK;
1459 else
1460 res = E_OUTOFMEMORY;
1461 break;
1462 case( VT_I1 ):
1463 res = VarBstrFromI1( V_UNION(ps,cVal), lcid, 0, &V_UNION(pd,bstrVal) );
1464 break;
1465 case( VT_I2 ):
1466 res = VarBstrFromI2( V_UNION(ps,iVal), lcid, 0, &V_UNION(pd,bstrVal) );
1467 break;
1468 case( VT_INT ):
1469 res = VarBstrFromInt( V_UNION(ps,intVal), lcid, 0, &V_UNION(pd,bstrVal) );
1470 break;
1471 case( VT_I4 ):
1472 res = VarBstrFromI4( V_UNION(ps,lVal), lcid, 0, &V_UNION(pd,bstrVal) );
1473 break;
1474 case( VT_UI1 ):
1475 res = VarBstrFromUI1( V_UNION(ps,bVal), lcid, 0, &V_UNION(pd,bstrVal) );
1476 break;
1477 case( VT_UI2 ):
1478 res = VarBstrFromUI2( V_UNION(ps,uiVal), lcid, 0, &V_UNION(pd,bstrVal) );
1479 break;
1480 case( VT_UINT ):
1481 res = VarBstrFromUint( V_UNION(ps,uintVal), lcid, 0, &V_UNION(pd,bstrVal) );
1482 break;
1483 case( VT_UI4 ):
1484 res = VarBstrFromUI4( V_UNION(ps,ulVal), lcid, 0, &V_UNION(pd,bstrVal) );
1485 break;
1486 case( VT_R4 ):
1487 res = VarBstrFromR4( V_UNION(ps,fltVal), lcid, 0, &V_UNION(pd,bstrVal) );
1488 break;
1489 case( VT_R8 ):
1490 res = VarBstrFromR8( V_UNION(ps,dblVal), lcid, 0, &V_UNION(pd,bstrVal) );
1491 break;
1492 case( VT_DATE ):
1493 res = VarBstrFromDate( V_UNION(ps,date), lcid, 0, &V_UNION(pd,bstrVal) );
1494 break;
1495 case( VT_BOOL ):
1496 res = VarBstrFromBool( V_UNION(ps,boolVal), lcid, 0, &V_UNION(pd,bstrVal) );
1497 break;
1498 case( VT_BSTR ):
1499 res = VariantCopy( pd, ps );
1500 break;
1501 case( VT_CY ):
1502 res = VarBstrFromCy( V_UNION(ps,cyVal), lcid, 0, &V_UNION(pd,bstrVal) );
1503 break;
1504 case( VT_DISPATCH ):
1505 /*res = VarBstrFromDisp( V_UNION(ps,pdispVal), lcid, 0, &(pd,bstrVal) );*/
1506 case( VT_DECIMAL ):
1507 /*res = VarBstrFromDec( V_UNION(ps,deiVal), lcid, 0, &(pd,bstrVal) );*/
1508 case( VT_UNKNOWN ):
1509 default:
1510 res = DISP_E_TYPEMISMATCH;
1511 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1512 break;
1514 break;
1516 case( VT_CY ):
1517 switch( vtFrom )
1519 case( VT_I1 ):
1520 res = VarCyFromI1( V_UNION(ps,cVal), &V_UNION(pd,cyVal) );
1521 break;
1522 case( VT_I2 ):
1523 res = VarCyFromI2( V_UNION(ps,iVal), &V_UNION(pd,cyVal) );
1524 break;
1525 case( VT_INT ):
1526 res = VarCyFromInt( V_UNION(ps,intVal), &V_UNION(pd,cyVal) );
1527 break;
1528 case( VT_I4 ):
1529 res = VarCyFromI4( V_UNION(ps,lVal), &V_UNION(pd,cyVal) );
1530 break;
1531 case( VT_UI1 ):
1532 res = VarCyFromUI1( V_UNION(ps,bVal), &V_UNION(pd,cyVal) );
1533 break;
1534 case( VT_UI2 ):
1535 res = VarCyFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,cyVal) );
1536 break;
1537 case( VT_UINT ):
1538 res = VarCyFromUint( V_UNION(ps,uintVal), &V_UNION(pd,cyVal) );
1539 break;
1540 case( VT_UI4 ):
1541 res = VarCyFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,cyVal) );
1542 break;
1543 case( VT_R4 ):
1544 res = VarCyFromR4( V_UNION(ps,fltVal), &V_UNION(pd,cyVal) );
1545 break;
1546 case( VT_R8 ):
1547 res = VarCyFromR8( V_UNION(ps,dblVal), &V_UNION(pd,cyVal) );
1548 break;
1549 case( VT_DATE ):
1550 res = VarCyFromDate( V_UNION(ps,date), &V_UNION(pd,cyVal) );
1551 break;
1552 case( VT_BOOL ):
1553 res = VarCyFromBool( V_UNION(ps,date), &V_UNION(pd,cyVal) );
1554 break;
1555 case( VT_CY ):
1556 res = VariantCopy( pd, ps );
1557 break;
1558 case( VT_BSTR ):
1559 res = VarCyFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,cyVal) );
1560 break;
1561 case( VT_DISPATCH ):
1562 /*res = VarCyFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cyVal) );*/
1563 case( VT_DECIMAL ):
1564 /*res = VarCyFromDec( V_UNION(ps,deiVal), &V_UNION(pd,cyVal) );*/
1565 break;
1566 case( VT_UNKNOWN ):
1567 default:
1568 res = DISP_E_TYPEMISMATCH;
1569 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1570 break;
1572 break;
1574 default:
1575 res = DISP_E_TYPEMISMATCH;
1576 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1577 break;
1580 return res;
1583 /******************************************************************************
1584 * ValidateVtRange [INTERNAL]
1586 * Used internally by the hi-level Variant API to determine
1587 * if the vartypes are valid.
1589 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1591 /* if by value we must make sure it is in the
1592 * range of the valid types.
1594 if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1596 return DISP_E_BADVARTYPE;
1598 return S_OK;
1602 /******************************************************************************
1603 * ValidateVartype [INTERNAL]
1605 * Used internally by the hi-level Variant API to determine
1606 * if the vartypes are valid.
1608 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1610 HRESULT res = S_OK;
1612 /* check if we have a valid argument.
1614 if( vt & VT_BYREF )
1616 /* if by reference check that the type is in
1617 * the valid range and that it is not of empty or null type
1619 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1620 ( vt & VT_TYPEMASK ) == VT_NULL ||
1621 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1623 res = E_INVALIDARG;
1627 else
1629 res = ValidateVtRange( vt );
1632 return res;
1635 /******************************************************************************
1636 * ValidateVt [INTERNAL]
1638 * Used internally by the hi-level Variant API to determine
1639 * if the vartypes are valid.
1641 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1643 HRESULT res = S_OK;
1645 /* check if we have a valid argument.
1647 if( vt & VT_BYREF )
1649 /* if by reference check that the type is in
1650 * the valid range and that it is not of empty or null type
1652 if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1653 ( vt & VT_TYPEMASK ) == VT_NULL ||
1654 ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1656 res = DISP_E_BADVARTYPE;
1660 else
1662 res = ValidateVtRange( vt );
1665 return res;
1672 /******************************************************************************
1673 * VariantInit [OLEAUT32.8]
1675 * Initializes the Variant. Unlike VariantClear it does not interpret the current
1676 * contents of the Variant.
1678 void WINAPI VariantInit(VARIANTARG* pvarg)
1680 TRACE("(%p)\n",pvarg);
1682 memset(pvarg, 0, sizeof (VARIANTARG));
1683 V_VT(pvarg) = VT_EMPTY;
1685 return;
1688 /******************************************************************************
1689 * VariantClear [OLEAUT32.9]
1691 * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1692 * sets the wReservedX field to 0. The current contents of the VARIANT are
1693 * freed. If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1694 * released. If VT_ARRAY the array is freed.
1696 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1698 HRESULT res = S_OK;
1699 TRACE("(%p)\n",pvarg);
1701 res = ValidateVariantType( V_VT(pvarg) );
1702 if( res == S_OK )
1704 if( !( V_VT(pvarg) & VT_BYREF ) )
1707 * The VT_ARRAY flag is a special case of a safe array.
1709 if ( (V_VT(pvarg) & VT_ARRAY) != 0)
1711 SafeArrayDestroy(V_UNION(pvarg,parray));
1713 else
1715 switch( V_VT(pvarg) & VT_TYPEMASK )
1717 case( VT_BSTR ):
1718 SysFreeString( V_UNION(pvarg,bstrVal) );
1719 break;
1720 case( VT_DISPATCH ):
1721 if(V_UNION(pvarg,pdispVal)!=NULL)
1722 ICOM_CALL(Release,V_UNION(pvarg,pdispVal));
1723 break;
1724 case( VT_VARIANT ):
1725 VariantClear(V_UNION(pvarg,pvarVal));
1726 break;
1727 case( VT_UNKNOWN ):
1728 if(V_UNION(pvarg,punkVal)!=NULL)
1729 ICOM_CALL(Release,V_UNION(pvarg,punkVal));
1730 break;
1731 case( VT_SAFEARRAY ):
1732 SafeArrayDestroy(V_UNION(pvarg,parray));
1733 break;
1734 default:
1735 break;
1741 * Empty all the fields and mark the type as empty.
1743 memset(pvarg, 0, sizeof (VARIANTARG));
1744 V_VT(pvarg) = VT_EMPTY;
1747 return res;
1750 /******************************************************************************
1751 * VariantCopy [OLEAUT32.10]
1753 * Frees up the designation variant and makes a copy of the source.
1755 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1757 HRESULT res = S_OK;
1759 TRACE("(%p, %p), vt=%d\n", pvargDest, pvargSrc, V_VT(pvargSrc));
1761 res = ValidateVariantType( V_VT(pvargSrc) );
1763 /* If the pointer are to the same variant we don't need
1764 * to do anything.
1766 if( pvargDest != pvargSrc && res == S_OK )
1768 res = VariantClear( pvargDest );
1770 if( res == S_OK )
1772 if( V_VT(pvargSrc) & VT_BYREF )
1774 /* In the case of byreference we only need
1775 * to copy the pointer.
1777 pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3;
1778 V_VT(pvargDest) = V_VT(pvargSrc);
1780 else
1783 * The VT_ARRAY flag is another way to designate a safe array.
1785 if (V_VT(pvargSrc) & VT_ARRAY)
1787 SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray));
1789 else
1791 /* In the case of by value we need to
1792 * copy the actuall value. In the case of
1793 * VT_BSTR a copy of the string is made,
1794 * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1795 * called to increment the object's reference count.
1797 switch( V_VT(pvargSrc) & VT_TYPEMASK )
1799 case( VT_BSTR ):
1800 V_UNION(pvargDest,bstrVal) = SYSDUPSTRING( V_UNION(pvargSrc,bstrVal) );
1801 break;
1802 case( VT_DISPATCH ):
1803 V_UNION(pvargDest,pdispVal) = V_UNION(pvargSrc,pdispVal);
1804 if (V_UNION(pvargDest,pdispVal)!=NULL)
1805 ICOM_CALL(AddRef,V_UNION(pvargDest,pdispVal));
1806 break;
1807 case( VT_VARIANT ):
1808 VariantCopy(V_UNION(pvargDest,pvarVal),V_UNION(pvargSrc,pvarVal));
1809 break;
1810 case( VT_UNKNOWN ):
1811 V_UNION(pvargDest,punkVal) = V_UNION(pvargSrc,punkVal);
1812 if (V_UNION(pvargDest,pdispVal)!=NULL)
1813 ICOM_CALL(AddRef,V_UNION(pvargDest,punkVal));
1814 break;
1815 case( VT_SAFEARRAY ):
1816 SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray));
1817 break;
1818 default:
1819 pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3;
1820 break;
1824 V_VT(pvargDest) = V_VT(pvargSrc);
1829 return res;
1833 /******************************************************************************
1834 * VariantCopyInd [OLEAUT32.11]
1836 * Frees up the destination variant and makes a copy of the source. If
1837 * the source is of type VT_BYREF it performs the necessary indirections.
1839 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1841 HRESULT res = S_OK;
1843 TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1845 res = ValidateVariantType( V_VT(pvargSrc) );
1847 if( res != S_OK )
1848 return res;
1850 if( V_VT(pvargSrc) & VT_BYREF )
1852 VARIANTARG varg;
1853 VariantInit( &varg );
1855 /* handle the in place copy.
1857 if( pvargDest == pvargSrc )
1859 /* we will use a copy of the source instead.
1861 res = VariantCopy( &varg, pvargSrc );
1862 pvargSrc = &varg;
1865 if( res == S_OK )
1867 res = VariantClear( pvargDest );
1869 if( res == S_OK )
1872 * The VT_ARRAY flag is another way to designate a safearray variant.
1874 if ( V_VT(pvargSrc) & VT_ARRAY)
1876 SafeArrayCopy(*V_UNION(pvargSrc,pparray), &V_UNION(pvargDest,parray));
1878 else
1880 /* In the case of by reference we need
1881 * to copy the date pointed to by the variant.
1884 /* Get the variant type.
1886 switch( V_VT(pvargSrc) & VT_TYPEMASK )
1888 case( VT_BSTR ):
1889 V_UNION(pvargDest,bstrVal) = SYSDUPSTRING( *(V_UNION(pvargSrc,pbstrVal)) );
1890 break;
1891 case( VT_DISPATCH ):
1892 break;
1893 case( VT_VARIANT ):
1895 /* Prevent from cycling. According to tests on
1896 * VariantCopyInd in Windows and the documentation
1897 * this API dereferences the inner Variants to only one depth.
1898 * If the inner Variant itself contains an
1899 * other inner variant the E_INVALIDARG error is
1900 * returned.
1902 if( pvargSrc->n1.n2.wReserved1 & PROCESSING_INNER_VARIANT )
1904 /* If we get here we are attempting to deference
1905 * an inner variant that that is itself contained
1906 * in an inner variant so report E_INVALIDARG error.
1908 res = E_INVALIDARG;
1910 else
1912 /* Set the processing inner variant flag.
1913 * We will set this flag in the inner variant
1914 * that will be passed to the VariantCopyInd function.
1916 (V_UNION(pvargSrc,pvarVal))->n1.n2.wReserved1 |= PROCESSING_INNER_VARIANT;
1918 /* Dereference the inner variant.
1920 res = VariantCopyInd( pvargDest, V_UNION(pvargSrc,pvarVal) );
1921 /* We must also copy its type, I think.
1923 V_VT(pvargSrc) = V_VT(V_UNION(pvargSrc,pvarVal));
1926 break;
1927 case( VT_UNKNOWN ):
1928 break;
1929 case( VT_SAFEARRAY ):
1930 SafeArrayCopy(*V_UNION(pvargSrc,pparray), &V_UNION(pvargDest,parray));
1931 break;
1932 default:
1933 /* This is a by reference Variant which means that the union
1934 * part of the Variant contains a pointer to some data of
1935 * type "V_VT(pvargSrc) & VT_TYPEMASK".
1936 * We will deference this data in a generic fashion using
1937 * the void pointer "Variant.u.byref".
1938 * We will copy this data into the union of the destination
1939 * Variant.
1941 memcpy( &pvargDest->n1.n2, V_UNION(pvargSrc,byref), SizeOfVariantData( pvargSrc ) );
1942 break;
1946 V_VT(pvargDest) = V_VT(pvargSrc) & VT_TYPEMASK;
1950 /* this should not fail.
1952 VariantClear( &varg );
1954 else
1956 res = VariantCopy( pvargDest, pvargSrc );
1959 return res;
1962 /******************************************************************************
1963 * VariantChangeType [OLEAUT32.12]
1965 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1966 USHORT wFlags, VARTYPE vt)
1968 return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1971 /******************************************************************************
1972 * VariantChangeTypeEx [OLEAUT32.147]
1974 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1975 LCID lcid, USHORT wFlags, VARTYPE vt)
1977 HRESULT res = S_OK;
1978 VARIANTARG varg;
1979 VariantInit( &varg );
1981 TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
1983 /* validate our source argument.
1985 res = ValidateVariantType( V_VT(pvargSrc) );
1987 /* validate the vartype.
1989 if( res == S_OK )
1991 res = ValidateVt( vt );
1994 /* if we are doing an in-place conversion make a copy of the source.
1996 if( res == S_OK && pvargDest == pvargSrc )
1998 res = VariantCopy( &varg, pvargSrc );
1999 pvargSrc = &varg;
2002 if( res == S_OK )
2004 /* free up the destination variant.
2006 res = VariantClear( pvargDest );
2009 if( res == S_OK )
2011 if( V_VT(pvargSrc) & VT_BYREF )
2013 /* Convert the source variant to a "byvalue" variant.
2015 VARIANTARG Variant;
2016 VariantInit( &Variant );
2017 res = VariantCopyInd( &Variant, pvargSrc );
2018 if( res == S_OK )
2020 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2021 /* this should not fail.
2023 VariantClear( &Variant );
2027 else
2029 /* Use the current "byvalue" source variant.
2031 res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2034 /* this should not fail.
2036 VariantClear( &varg );
2038 /* set the type of the destination
2040 if ( res == S_OK )
2041 V_VT(pvargDest) = vt;
2043 return res;
2049 /******************************************************************************
2050 * VarUI1FromI2 [OLEAUT32.130]
2052 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2054 TRACE("( %d, %p ), stub\n", sIn, pbOut );
2056 /* Check range of value.
2058 if( sIn < UI1_MIN || sIn > UI1_MAX )
2060 return DISP_E_OVERFLOW;
2063 *pbOut = (BYTE) sIn;
2065 return S_OK;
2068 /******************************************************************************
2069 * VarUI1FromI4 [OLEAUT32.131]
2071 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2073 TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2075 /* Check range of value.
2077 if( lIn < UI1_MIN || lIn > UI1_MAX )
2079 return DISP_E_OVERFLOW;
2082 *pbOut = (BYTE) lIn;
2084 return S_OK;
2088 /******************************************************************************
2089 * VarUI1FromR4 [OLEAUT32.132]
2091 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2093 TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2095 /* Check range of value.
2097 fltIn = round( fltIn );
2098 if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2100 return DISP_E_OVERFLOW;
2103 *pbOut = (BYTE) fltIn;
2105 return S_OK;
2108 /******************************************************************************
2109 * VarUI1FromR8 [OLEAUT32.133]
2111 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2113 TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2115 /* Check range of value.
2117 dblIn = round( dblIn );
2118 if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2120 return DISP_E_OVERFLOW;
2123 *pbOut = (BYTE) dblIn;
2125 return S_OK;
2128 /******************************************************************************
2129 * VarUI1FromDate [OLEAUT32.135]
2131 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2133 TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2135 /* Check range of value.
2137 dateIn = round( dateIn );
2138 if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2140 return DISP_E_OVERFLOW;
2143 *pbOut = (BYTE) dateIn;
2145 return S_OK;
2148 /******************************************************************************
2149 * VarUI1FromBool [OLEAUT32.138]
2151 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2153 TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2155 *pbOut = (BYTE) boolIn;
2157 return S_OK;
2160 /******************************************************************************
2161 * VarUI1FromI1 [OLEAUT32.237]
2163 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2165 TRACE("( %c, %p ), stub\n", cIn, pbOut );
2167 *pbOut = cIn;
2169 return S_OK;
2172 /******************************************************************************
2173 * VarUI1FromUI2 [OLEAUT32.238]
2175 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2177 TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2179 /* Check range of value.
2181 if( uiIn > UI1_MAX )
2183 return DISP_E_OVERFLOW;
2186 *pbOut = (BYTE) uiIn;
2188 return S_OK;
2191 /******************************************************************************
2192 * VarUI1FromUI4 [OLEAUT32.239]
2194 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2196 TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2198 /* Check range of value.
2200 if( ulIn > UI1_MAX )
2202 return DISP_E_OVERFLOW;
2205 *pbOut = (BYTE) ulIn;
2207 return S_OK;
2211 /******************************************************************************
2212 * VarUI1FromStr [OLEAUT32.136]
2214 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2216 double dValue = 0.0;
2217 LPSTR pNewString = NULL;
2219 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2221 /* Check if we have a valid argument
2223 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2224 RemoveCharacterFromString( pNewString, "," );
2225 if( IsValidRealString( pNewString ) == FALSE )
2227 return DISP_E_TYPEMISMATCH;
2230 /* Convert the valid string to a floating point number.
2232 dValue = atof( pNewString );
2234 /* We don't need the string anymore so free it.
2236 HeapFree( GetProcessHeap(), 0 , pNewString );
2238 /* Check range of value.
2240 dValue = round( dValue );
2241 if( dValue < UI1_MIN || dValue > UI1_MAX )
2243 return DISP_E_OVERFLOW;
2246 *pbOut = (BYTE) dValue;
2248 return S_OK;
2251 /**********************************************************************
2252 * VarUI1FromCy [OLEAUT32.134]
2253 * Convert currency to unsigned char
2255 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2256 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2258 if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2260 *pbOut = (BYTE)t;
2261 return S_OK;
2264 /******************************************************************************
2265 * VarI2FromUI1 [OLEAUT32.48]
2267 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2269 TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2271 *psOut = (short) bIn;
2273 return S_OK;
2276 /******************************************************************************
2277 * VarI2FromI4 [OLEAUT32.49]
2279 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2281 TRACE("( %lx, %p ), stub\n", lIn, psOut );
2283 /* Check range of value.
2285 if( lIn < I2_MIN || lIn > I2_MAX )
2287 return DISP_E_OVERFLOW;
2290 *psOut = (short) lIn;
2292 return S_OK;
2295 /******************************************************************************
2296 * VarI2FromR4 [OLEAUT32.50]
2298 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2300 TRACE("( %f, %p ), stub\n", fltIn, psOut );
2302 /* Check range of value.
2304 fltIn = round( fltIn );
2305 if( fltIn < I2_MIN || fltIn > I2_MAX )
2307 return DISP_E_OVERFLOW;
2310 *psOut = (short) fltIn;
2312 return S_OK;
2315 /******************************************************************************
2316 * VarI2FromR8 [OLEAUT32.51]
2318 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2320 TRACE("( %f, %p ), stub\n", dblIn, psOut );
2322 /* Check range of value.
2324 dblIn = round( dblIn );
2325 if( dblIn < I2_MIN || dblIn > I2_MAX )
2327 return DISP_E_OVERFLOW;
2330 *psOut = (short) dblIn;
2332 return S_OK;
2335 /******************************************************************************
2336 * VarI2FromDate [OLEAUT32.53]
2338 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2340 TRACE("( %f, %p ), stub\n", dateIn, psOut );
2342 /* Check range of value.
2344 dateIn = round( dateIn );
2345 if( dateIn < I2_MIN || dateIn > I2_MAX )
2347 return DISP_E_OVERFLOW;
2350 *psOut = (short) dateIn;
2352 return S_OK;
2355 /******************************************************************************
2356 * VarI2FromBool [OLEAUT32.56]
2358 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2360 TRACE("( %d, %p ), stub\n", boolIn, psOut );
2362 *psOut = (short) boolIn;
2364 return S_OK;
2367 /******************************************************************************
2368 * VarI2FromI1 [OLEAUT32.205]
2370 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2372 TRACE("( %c, %p ), stub\n", cIn, psOut );
2374 *psOut = (short) cIn;
2376 return S_OK;
2379 /******************************************************************************
2380 * VarI2FromUI2 [OLEAUT32.206]
2382 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2384 TRACE("( %d, %p ), stub\n", uiIn, psOut );
2386 /* Check range of value.
2388 if( uiIn > I2_MAX )
2390 return DISP_E_OVERFLOW;
2393 *psOut = (short) uiIn;
2395 return S_OK;
2398 /******************************************************************************
2399 * VarI2FromUI4 [OLEAUT32.207]
2401 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2403 TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2405 /* Check range of value.
2407 if( ulIn < I2_MIN || ulIn > I2_MAX )
2409 return DISP_E_OVERFLOW;
2412 *psOut = (short) ulIn;
2414 return S_OK;
2417 /******************************************************************************
2418 * VarI2FromStr [OLEAUT32.54]
2420 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2422 double dValue = 0.0;
2423 LPSTR pNewString = NULL;
2425 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2427 /* Check if we have a valid argument
2429 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2430 RemoveCharacterFromString( pNewString, "," );
2431 if( IsValidRealString( pNewString ) == FALSE )
2433 return DISP_E_TYPEMISMATCH;
2436 /* Convert the valid string to a floating point number.
2438 dValue = atof( pNewString );
2440 /* We don't need the string anymore so free it.
2442 HeapFree( GetProcessHeap(), 0, pNewString );
2444 /* Check range of value.
2446 dValue = round( dValue );
2447 if( dValue < I2_MIN || dValue > I2_MAX )
2449 return DISP_E_OVERFLOW;
2452 *psOut = (short) dValue;
2454 return S_OK;
2457 /**********************************************************************
2458 * VarI2FromCy [OLEAUT32.52]
2459 * Convert currency to signed short
2461 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2462 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2464 if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2466 *psOut = (SHORT)t;
2467 return S_OK;
2470 /******************************************************************************
2471 * VarI4FromUI1 [OLEAUT32.58]
2473 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2475 TRACE("( %X, %p ), stub\n", bIn, plOut );
2477 *plOut = (LONG) bIn;
2479 return S_OK;
2483 /******************************************************************************
2484 * VarI4FromR4 [OLEAUT32.60]
2486 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2488 TRACE("( %f, %p ), stub\n", fltIn, plOut );
2490 /* Check range of value.
2492 fltIn = round( fltIn );
2493 if( fltIn < I4_MIN || fltIn > I4_MAX )
2495 return DISP_E_OVERFLOW;
2498 *plOut = (LONG) fltIn;
2500 return S_OK;
2503 /******************************************************************************
2504 * VarI4FromR8 [OLEAUT32.61]
2506 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2508 TRACE("( %f, %p ), stub\n", dblIn, plOut );
2510 /* Check range of value.
2512 dblIn = round( dblIn );
2513 if( dblIn < I4_MIN || dblIn > I4_MAX )
2515 return DISP_E_OVERFLOW;
2518 *plOut = (LONG) dblIn;
2520 return S_OK;
2523 /******************************************************************************
2524 * VarI4FromDate [OLEAUT32.63]
2526 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2528 TRACE("( %f, %p ), stub\n", dateIn, plOut );
2530 /* Check range of value.
2532 dateIn = round( dateIn );
2533 if( dateIn < I4_MIN || dateIn > I4_MAX )
2535 return DISP_E_OVERFLOW;
2538 *plOut = (LONG) dateIn;
2540 return S_OK;
2543 /******************************************************************************
2544 * VarI4FromBool [OLEAUT32.66]
2546 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2548 TRACE("( %d, %p ), stub\n", boolIn, plOut );
2550 *plOut = (LONG) boolIn;
2552 return S_OK;
2555 /******************************************************************************
2556 * VarI4FromI1 [OLEAUT32.209]
2558 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2560 TRACE("( %c, %p ), stub\n", cIn, plOut );
2562 *plOut = (LONG) cIn;
2564 return S_OK;
2567 /******************************************************************************
2568 * VarI4FromUI2 [OLEAUT32.210]
2570 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2572 TRACE("( %d, %p ), stub\n", uiIn, plOut );
2574 *plOut = (LONG) uiIn;
2576 return S_OK;
2579 /******************************************************************************
2580 * VarI4FromUI4 [OLEAUT32.211]
2582 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2584 TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2586 /* Check range of value.
2588 if( ulIn < I4_MIN || ulIn > I4_MAX )
2590 return DISP_E_OVERFLOW;
2593 *plOut = (LONG) ulIn;
2595 return S_OK;
2598 /******************************************************************************
2599 * VarI4FromI2 [OLEAUT32.59]
2601 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2603 TRACE("( %d, %p ), stub\n", sIn, plOut );
2605 *plOut = (LONG) sIn;
2607 return S_OK;
2610 /******************************************************************************
2611 * VarI4FromStr [OLEAUT32.64]
2613 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2615 double dValue = 0.0;
2616 LPSTR pNewString = NULL;
2618 TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2620 /* Check if we have a valid argument
2622 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2623 RemoveCharacterFromString( pNewString, "," );
2624 if( IsValidRealString( pNewString ) == FALSE )
2626 return DISP_E_TYPEMISMATCH;
2629 /* Convert the valid string to a floating point number.
2631 dValue = atof( pNewString );
2633 /* We don't need the string anymore so free it.
2635 HeapFree( GetProcessHeap(), 0, pNewString );
2637 /* Check range of value.
2639 dValue = round( dValue );
2640 if( dValue < I4_MIN || dValue > I4_MAX )
2642 return DISP_E_OVERFLOW;
2645 *plOut = (LONG) dValue;
2647 return S_OK;
2650 /**********************************************************************
2651 * VarI4FromCy [OLEAUT32.62]
2652 * Convert currency to signed long
2654 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2655 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2657 if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2659 *plOut = (LONG)t;
2660 return S_OK;
2663 /******************************************************************************
2664 * VarR4FromUI1 [OLEAUT32.68]
2666 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2668 TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2670 *pfltOut = (FLOAT) bIn;
2672 return S_OK;
2675 /******************************************************************************
2676 * VarR4FromI2 [OLEAUT32.69]
2678 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2680 TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2682 *pfltOut = (FLOAT) sIn;
2684 return S_OK;
2687 /******************************************************************************
2688 * VarR4FromI4 [OLEAUT32.70]
2690 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2692 TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2694 *pfltOut = (FLOAT) lIn;
2696 return S_OK;
2699 /******************************************************************************
2700 * VarR4FromR8 [OLEAUT32.71]
2702 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2704 TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2706 /* Check range of value.
2708 if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2710 return DISP_E_OVERFLOW;
2713 *pfltOut = (FLOAT) dblIn;
2715 return S_OK;
2718 /******************************************************************************
2719 * VarR4FromDate [OLEAUT32.73]
2721 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2723 TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2725 /* Check range of value.
2727 if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2729 return DISP_E_OVERFLOW;
2732 *pfltOut = (FLOAT) dateIn;
2734 return S_OK;
2737 /******************************************************************************
2738 * VarR4FromBool [OLEAUT32.76]
2740 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2742 TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2744 *pfltOut = (FLOAT) boolIn;
2746 return S_OK;
2749 /******************************************************************************
2750 * VarR4FromI1 [OLEAUT32.213]
2752 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2754 TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2756 *pfltOut = (FLOAT) cIn;
2758 return S_OK;
2761 /******************************************************************************
2762 * VarR4FromUI2 [OLEAUT32.214]
2764 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2766 TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2768 *pfltOut = (FLOAT) uiIn;
2770 return S_OK;
2773 /******************************************************************************
2774 * VarR4FromUI4 [OLEAUT32.215]
2776 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2778 TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2780 *pfltOut = (FLOAT) ulIn;
2782 return S_OK;
2785 /******************************************************************************
2786 * VarR4FromStr [OLEAUT32.74]
2788 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2790 double dValue = 0.0;
2791 LPSTR pNewString = NULL;
2793 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2795 /* Check if we have a valid argument
2797 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2798 RemoveCharacterFromString( pNewString, "," );
2799 if( IsValidRealString( pNewString ) == FALSE )
2801 return DISP_E_TYPEMISMATCH;
2804 /* Convert the valid string to a floating point number.
2806 dValue = atof( pNewString );
2808 /* We don't need the string anymore so free it.
2810 HeapFree( GetProcessHeap(), 0, pNewString );
2812 /* Check range of value.
2814 if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2816 return DISP_E_OVERFLOW;
2819 *pfltOut = (FLOAT) dValue;
2821 return S_OK;
2824 /**********************************************************************
2825 * VarR4FromCy [OLEAUT32.72]
2826 * Convert currency to float
2828 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2829 *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2831 return S_OK;
2834 /******************************************************************************
2835 * VarR8FromUI1 [OLEAUT32.78]
2837 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2839 TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2841 *pdblOut = (double) bIn;
2843 return S_OK;
2846 /******************************************************************************
2847 * VarR8FromI2 [OLEAUT32.79]
2849 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2851 TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2853 *pdblOut = (double) sIn;
2855 return S_OK;
2858 /******************************************************************************
2859 * VarR8FromI4 [OLEAUT32.80]
2861 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2863 TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2865 *pdblOut = (double) lIn;
2867 return S_OK;
2870 /******************************************************************************
2871 * VarR8FromR4 [OLEAUT32.81]
2873 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2875 TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2877 *pdblOut = (double) fltIn;
2879 return S_OK;
2882 /******************************************************************************
2883 * VarR8FromDate [OLEAUT32.83]
2885 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2887 TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2889 *pdblOut = (double) dateIn;
2891 return S_OK;
2894 /******************************************************************************
2895 * VarR8FromBool [OLEAUT32.86]
2897 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2899 TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2901 *pdblOut = (double) boolIn;
2903 return S_OK;
2906 /******************************************************************************
2907 * VarR8FromI1 [OLEAUT32.217]
2909 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2911 TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2913 *pdblOut = (double) cIn;
2915 return S_OK;
2918 /******************************************************************************
2919 * VarR8FromUI2 [OLEAUT32.218]
2921 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2923 TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2925 *pdblOut = (double) uiIn;
2927 return S_OK;
2930 /******************************************************************************
2931 * VarR8FromUI4 [OLEAUT32.219]
2933 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2935 TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2937 *pdblOut = (double) ulIn;
2939 return S_OK;
2942 /******************************************************************************
2943 * VarR8FromStr [OLEAUT32.84]
2945 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2947 double dValue = 0.0;
2948 LPSTR pNewString = NULL;
2950 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2952 /* Check if we have a valid argument
2954 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2955 RemoveCharacterFromString( pNewString, "," );
2956 if( IsValidRealString( pNewString ) == FALSE )
2958 return DISP_E_TYPEMISMATCH;
2961 /* Convert the valid string to a floating point number.
2963 dValue = atof( pNewString );
2965 /* We don't need the string anymore so free it.
2967 HeapFree( GetProcessHeap(), 0, pNewString );
2969 *pdblOut = dValue;
2971 return S_OK;
2974 /**********************************************************************
2975 * VarR8FromCy [OLEAUT32.82]
2976 * Convert currency to double
2978 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2979 *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2981 return S_OK;
2984 /******************************************************************************
2985 * VarDateFromUI1 [OLEAUT32.88]
2987 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2989 TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2991 *pdateOut = (DATE) bIn;
2993 return S_OK;
2996 /******************************************************************************
2997 * VarDateFromI2 [OLEAUT32.89]
2999 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
3001 TRACE("( %d, %p ), stub\n", sIn, pdateOut );
3003 *pdateOut = (DATE) sIn;
3005 return S_OK;
3008 /******************************************************************************
3009 * VarDateFromI4 [OLEAUT32.90]
3011 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
3013 TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
3015 if( lIn < DATE_MIN || lIn > DATE_MAX )
3017 return DISP_E_OVERFLOW;
3020 *pdateOut = (DATE) lIn;
3022 return S_OK;
3025 /******************************************************************************
3026 * VarDateFromR4 [OLEAUT32.91]
3028 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3030 TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3032 if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3034 return DISP_E_OVERFLOW;
3037 *pdateOut = (DATE) fltIn;
3039 return S_OK;
3042 /******************************************************************************
3043 * VarDateFromR8 [OLEAUT32.92]
3045 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3047 TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3049 if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3051 return DISP_E_OVERFLOW;
3054 *pdateOut = (DATE) dblIn;
3056 return S_OK;
3059 /******************************************************************************
3060 * VarDateFromStr [OLEAUT32.94]
3061 * The string representing the date is composed of two parts, a date and time.
3063 * The format of the time is has follows:
3064 * hh[:mm][:ss][AM|PM]
3065 * Whitespace can be inserted anywhere between these tokens. A whitespace consists
3066 * of space and/or tab characters, which are ignored.
3068 * The formats for the date part are has follows:
3069 * mm/[dd/][yy]yy
3070 * [dd/]mm/[yy]yy
3071 * [yy]yy/mm/dd
3072 * January dd[,] [yy]yy
3073 * dd January [yy]yy
3074 * [yy]yy January dd
3075 * Whitespace can be inserted anywhere between these tokens.
3077 * The formats for the date and time string are has follows.
3078 * date[whitespace][time]
3079 * [time][whitespace]date
3081 * These are the only characters allowed in a string representing a date and time:
3082 * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3084 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3086 HRESULT ret = S_OK;
3087 struct tm TM;
3089 memset( &TM, 0, sizeof(TM) );
3091 TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3093 if( DateTimeStringToTm( strIn, dwFlags, &TM ) )
3095 if( TmToDATE( &TM, pdateOut ) == FALSE )
3097 ret = E_INVALIDARG;
3100 else
3102 ret = DISP_E_TYPEMISMATCH;
3106 return ret;
3109 /******************************************************************************
3110 * VarDateFromI1 [OLEAUT32.221]
3112 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3114 TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3116 *pdateOut = (DATE) cIn;
3118 return S_OK;
3121 /******************************************************************************
3122 * VarDateFromUI2 [OLEAUT32.222]
3124 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3126 TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3128 if( uiIn > DATE_MAX )
3130 return DISP_E_OVERFLOW;
3133 *pdateOut = (DATE) uiIn;
3135 return S_OK;
3138 /******************************************************************************
3139 * VarDateFromUI4 [OLEAUT32.223]
3141 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3143 TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3145 if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3147 return DISP_E_OVERFLOW;
3150 *pdateOut = (DATE) ulIn;
3152 return S_OK;
3155 /******************************************************************************
3156 * VarDateFromBool [OLEAUT32.96]
3158 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3160 TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3162 *pdateOut = (DATE) boolIn;
3164 return S_OK;
3167 /**********************************************************************
3168 * VarDateFromCy [OLEAUT32.93]
3169 * Convert currency to date
3171 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3172 *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3174 if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3175 return S_OK;
3178 /******************************************************************************
3179 * VarBstrFromUI1 [OLEAUT32.108]
3181 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3183 TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3184 sprintf( pBuffer, "%d", bVal );
3186 *pbstrOut = StringDupAtoBstr( pBuffer );
3188 return S_OK;
3191 /******************************************************************************
3192 * VarBstrFromI2 [OLEAUT32.109]
3194 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3196 TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3197 sprintf( pBuffer, "%d", iVal );
3198 *pbstrOut = StringDupAtoBstr( pBuffer );
3200 return S_OK;
3203 /******************************************************************************
3204 * VarBstrFromI4 [OLEAUT32.110]
3206 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3208 TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3210 sprintf( pBuffer, "%ld", lIn );
3211 *pbstrOut = StringDupAtoBstr( pBuffer );
3213 return S_OK;
3216 /******************************************************************************
3217 * VarBstrFromR4 [OLEAUT32.111]
3219 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3221 TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3223 sprintf( pBuffer, "%.7g", fltIn );
3224 *pbstrOut = StringDupAtoBstr( pBuffer );
3226 return S_OK;
3229 /******************************************************************************
3230 * VarBstrFromR8 [OLEAUT32.112]
3232 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3234 TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3236 sprintf( pBuffer, "%.15g", dblIn );
3237 *pbstrOut = StringDupAtoBstr( pBuffer );
3239 return S_OK;
3242 /******************************************************************************
3243 * VarBstrFromCy [OLEAUT32.113]
3245 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3246 /* FIXME */
3247 return E_NOTIMPL;
3251 /******************************************************************************
3252 * VarBstrFromDate [OLEAUT32.114]
3254 * The date is implemented using an 8 byte floating-point number.
3255 * Days are represented by whole numbers increments starting with 0.00 as
3256 * being December 30 1899, midnight.
3257 * The hours are expressed as the fractional part of the number.
3258 * December 30 1899 at midnight = 0.00
3259 * January 1 1900 at midnight = 2.00
3260 * January 4 1900 at 6 AM = 5.25
3261 * January 4 1900 at noon = 5.50
3262 * December 29 1899 at midnight = -1.00
3263 * December 18 1899 at midnight = -12.00
3264 * December 18 1899 at 6AM = -12.25
3265 * December 18 1899 at 6PM = -12.75
3266 * December 19 1899 at midnight = -11.00
3267 * The tm structure is as follows:
3268 * struct tm {
3269 * int tm_sec; seconds after the minute - [0,59]
3270 * int tm_min; minutes after the hour - [0,59]
3271 * int tm_hour; hours since midnight - [0,23]
3272 * int tm_mday; day of the month - [1,31]
3273 * int tm_mon; months since January - [0,11]
3274 * int tm_year; years
3275 * int tm_wday; days since Sunday - [0,6]
3276 * int tm_yday; days since January 1 - [0,365]
3277 * int tm_isdst; daylight savings time flag
3278 * };
3280 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3282 struct tm TM;
3283 memset( &TM, 0, sizeof(TM) );
3285 TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3287 if( DateToTm( dateIn, dwFlags, &TM ) == FALSE )
3289 return E_INVALIDARG;
3292 if( dwFlags & VAR_DATEVALUEONLY )
3293 strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3294 else if( dwFlags & VAR_TIMEVALUEONLY )
3295 strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3296 else
3297 strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3299 *pbstrOut = StringDupAtoBstr( pBuffer );
3301 return S_OK;
3304 /******************************************************************************
3305 * VarBstrFromBool [OLEAUT32.116]
3307 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3309 TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3311 if( boolIn == VARIANT_FALSE )
3313 sprintf( pBuffer, "False" );
3315 else
3317 sprintf( pBuffer, "True" );
3320 *pbstrOut = StringDupAtoBstr( pBuffer );
3322 return S_OK;
3325 /******************************************************************************
3326 * VarBstrFromI1 [OLEAUT32.229]
3328 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3330 TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3331 sprintf( pBuffer, "%d", cIn );
3332 *pbstrOut = StringDupAtoBstr( pBuffer );
3334 return S_OK;
3337 /******************************************************************************
3338 * VarBstrFromUI2 [OLEAUT32.230]
3340 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3342 TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3343 sprintf( pBuffer, "%d", uiIn );
3344 *pbstrOut = StringDupAtoBstr( pBuffer );
3346 return S_OK;
3349 /******************************************************************************
3350 * VarBstrFromUI4 [OLEAUT32.231]
3352 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3354 TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3355 sprintf( pBuffer, "%ld", ulIn );
3356 *pbstrOut = StringDupAtoBstr( pBuffer );
3358 return S_OK;
3361 /******************************************************************************
3362 * VarBoolFromUI1 [OLEAUT32.118]
3364 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3366 TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3368 if( bIn == 0 )
3370 *pboolOut = VARIANT_FALSE;
3372 else
3374 *pboolOut = VARIANT_TRUE;
3377 return S_OK;
3380 /******************************************************************************
3381 * VarBoolFromI2 [OLEAUT32.119]
3383 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3385 TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3387 if( sIn == 0 )
3389 *pboolOut = VARIANT_FALSE;
3391 else
3393 *pboolOut = VARIANT_TRUE;
3396 return S_OK;
3399 /******************************************************************************
3400 * VarBoolFromI4 [OLEAUT32.120]
3402 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3404 TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3406 if( lIn == 0 )
3408 *pboolOut = VARIANT_FALSE;
3410 else
3412 *pboolOut = VARIANT_TRUE;
3415 return S_OK;
3418 /******************************************************************************
3419 * VarBoolFromR4 [OLEAUT32.121]
3421 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3423 TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3425 if( fltIn == 0.0 )
3427 *pboolOut = VARIANT_FALSE;
3429 else
3431 *pboolOut = VARIANT_TRUE;
3434 return S_OK;
3437 /******************************************************************************
3438 * VarBoolFromR8 [OLEAUT32.122]
3440 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3442 TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3444 if( dblIn == 0.0 )
3446 *pboolOut = VARIANT_FALSE;
3448 else
3450 *pboolOut = VARIANT_TRUE;
3453 return S_OK;
3456 /******************************************************************************
3457 * VarBoolFromDate [OLEAUT32.123]
3459 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3461 TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3463 if( dateIn == 0.0 )
3465 *pboolOut = VARIANT_FALSE;
3467 else
3469 *pboolOut = VARIANT_TRUE;
3472 return S_OK;
3475 /******************************************************************************
3476 * VarBoolFromStr [OLEAUT32.125]
3478 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3480 HRESULT ret = S_OK;
3481 char* pNewString = NULL;
3483 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3485 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3487 if( pNewString == NULL || strlen( pNewString ) == 0 )
3489 ret = DISP_E_TYPEMISMATCH;
3492 if( ret == S_OK )
3494 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3496 *pboolOut = VARIANT_TRUE;
3498 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3500 *pboolOut = VARIANT_FALSE;
3502 else
3504 /* Try converting the string to a floating point number.
3506 double dValue = 0.0;
3507 HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3508 if( res != S_OK )
3510 ret = DISP_E_TYPEMISMATCH;
3512 else if( dValue == 0.0 )
3514 *pboolOut = VARIANT_FALSE;
3516 else
3518 *pboolOut = VARIANT_TRUE;
3523 HeapFree( GetProcessHeap(), 0, pNewString );
3525 return ret;
3528 /******************************************************************************
3529 * VarBoolFromI1 [OLEAUT32.233]
3531 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3533 TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3535 if( cIn == 0 )
3537 *pboolOut = VARIANT_FALSE;
3539 else
3541 *pboolOut = VARIANT_TRUE;
3544 return S_OK;
3547 /******************************************************************************
3548 * VarBoolFromUI2 [OLEAUT32.234]
3550 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3552 TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3554 if( uiIn == 0 )
3556 *pboolOut = VARIANT_FALSE;
3558 else
3560 *pboolOut = VARIANT_TRUE;
3563 return S_OK;
3566 /******************************************************************************
3567 * VarBoolFromUI4 [OLEAUT32.235]
3569 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3571 TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3573 if( ulIn == 0 )
3575 *pboolOut = VARIANT_FALSE;
3577 else
3579 *pboolOut = VARIANT_TRUE;
3582 return S_OK;
3585 /**********************************************************************
3586 * VarBoolFromCy [OLEAUT32.124]
3587 * Convert currency to boolean
3589 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3590 if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3591 else *pboolOut = 0;
3593 return S_OK;
3596 /******************************************************************************
3597 * VarI1FromUI1 [OLEAUT32.244]
3599 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3601 TRACE("( %d, %p ), stub\n", bIn, pcOut );
3603 /* Check range of value.
3605 if( bIn > CHAR_MAX )
3607 return DISP_E_OVERFLOW;
3610 *pcOut = (CHAR) bIn;
3612 return S_OK;
3615 /******************************************************************************
3616 * VarI1FromI2 [OLEAUT32.245]
3618 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3620 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3622 if( uiIn > CHAR_MAX )
3624 return DISP_E_OVERFLOW;
3627 *pcOut = (CHAR) uiIn;
3629 return S_OK;
3632 /******************************************************************************
3633 * VarI1FromI4 [OLEAUT32.246]
3635 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3637 TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3639 if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3641 return DISP_E_OVERFLOW;
3644 *pcOut = (CHAR) lIn;
3646 return S_OK;
3649 /******************************************************************************
3650 * VarI1FromR4 [OLEAUT32.247]
3652 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3654 TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3656 fltIn = round( fltIn );
3657 if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3659 return DISP_E_OVERFLOW;
3662 *pcOut = (CHAR) fltIn;
3664 return S_OK;
3667 /******************************************************************************
3668 * VarI1FromR8 [OLEAUT32.248]
3670 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3672 TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3674 dblIn = round( dblIn );
3675 if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3677 return DISP_E_OVERFLOW;
3680 *pcOut = (CHAR) dblIn;
3682 return S_OK;
3685 /******************************************************************************
3686 * VarI1FromDate [OLEAUT32.249]
3688 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3690 TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3692 dateIn = round( dateIn );
3693 if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3695 return DISP_E_OVERFLOW;
3698 *pcOut = (CHAR) dateIn;
3700 return S_OK;
3703 /******************************************************************************
3704 * VarI1FromStr [OLEAUT32.251]
3706 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3708 double dValue = 0.0;
3709 LPSTR pNewString = NULL;
3711 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3713 /* Check if we have a valid argument
3715 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3716 RemoveCharacterFromString( pNewString, "," );
3717 if( IsValidRealString( pNewString ) == FALSE )
3719 return DISP_E_TYPEMISMATCH;
3722 /* Convert the valid string to a floating point number.
3724 dValue = atof( pNewString );
3726 /* We don't need the string anymore so free it.
3728 HeapFree( GetProcessHeap(), 0, pNewString );
3730 /* Check range of value.
3732 dValue = round( dValue );
3733 if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3735 return DISP_E_OVERFLOW;
3738 *pcOut = (CHAR) dValue;
3740 return S_OK;
3743 /******************************************************************************
3744 * VarI1FromBool [OLEAUT32.253]
3746 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3748 TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3750 *pcOut = (CHAR) boolIn;
3752 return S_OK;
3755 /******************************************************************************
3756 * VarI1FromUI2 [OLEAUT32.254]
3758 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3760 TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3762 if( uiIn > CHAR_MAX )
3764 return DISP_E_OVERFLOW;
3767 *pcOut = (CHAR) uiIn;
3769 return S_OK;
3772 /******************************************************************************
3773 * VarI1FromUI4 [OLEAUT32.255]
3775 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3777 TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3779 if( ulIn > CHAR_MAX )
3781 return DISP_E_OVERFLOW;
3784 *pcOut = (CHAR) ulIn;
3786 return S_OK;
3789 /**********************************************************************
3790 * VarI1FromCy [OLEAUT32.250]
3791 * Convert currency to signed char
3793 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3794 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3796 if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3798 *pcOut = (CHAR)t;
3799 return S_OK;
3802 /******************************************************************************
3803 * VarUI2FromUI1 [OLEAUT32.257]
3805 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3807 TRACE("( %d, %p ), stub\n", bIn, puiOut );
3809 *puiOut = (USHORT) bIn;
3811 return S_OK;
3814 /******************************************************************************
3815 * VarUI2FromI2 [OLEAUT32.258]
3817 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3819 TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3821 if( uiIn < UI2_MIN )
3823 return DISP_E_OVERFLOW;
3826 *puiOut = (USHORT) uiIn;
3828 return S_OK;
3831 /******************************************************************************
3832 * VarUI2FromI4 [OLEAUT32.259]
3834 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3836 TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3838 if( lIn < UI2_MIN || lIn > UI2_MAX )
3840 return DISP_E_OVERFLOW;
3843 *puiOut = (USHORT) lIn;
3845 return S_OK;
3848 /******************************************************************************
3849 * VarUI2FromR4 [OLEAUT32.260]
3851 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3853 TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3855 fltIn = round( fltIn );
3856 if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3858 return DISP_E_OVERFLOW;
3861 *puiOut = (USHORT) fltIn;
3863 return S_OK;
3866 /******************************************************************************
3867 * VarUI2FromR8 [OLEAUT32.261]
3869 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3871 TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3873 dblIn = round( dblIn );
3874 if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3876 return DISP_E_OVERFLOW;
3879 *puiOut = (USHORT) dblIn;
3881 return S_OK;
3884 /******************************************************************************
3885 * VarUI2FromDate [OLEAUT32.262]
3887 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3889 TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3891 dateIn = round( dateIn );
3892 if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3894 return DISP_E_OVERFLOW;
3897 *puiOut = (USHORT) dateIn;
3899 return S_OK;
3902 /******************************************************************************
3903 * VarUI2FromStr [OLEAUT32.264]
3905 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3907 double dValue = 0.0;
3908 LPSTR pNewString = NULL;
3910 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3912 /* Check if we have a valid argument
3914 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3915 RemoveCharacterFromString( pNewString, "," );
3916 if( IsValidRealString( pNewString ) == FALSE )
3918 return DISP_E_TYPEMISMATCH;
3921 /* Convert the valid string to a floating point number.
3923 dValue = atof( pNewString );
3925 /* We don't need the string anymore so free it.
3927 HeapFree( GetProcessHeap(), 0, pNewString );
3929 /* Check range of value.
3931 dValue = round( dValue );
3932 if( dValue < UI2_MIN || dValue > UI2_MAX )
3934 return DISP_E_OVERFLOW;
3937 *puiOut = (USHORT) dValue;
3939 return S_OK;
3942 /******************************************************************************
3943 * VarUI2FromBool [OLEAUT32.266]
3945 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3947 TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3949 *puiOut = (USHORT) boolIn;
3951 return S_OK;
3954 /******************************************************************************
3955 * VarUI2FromI1 [OLEAUT32.267]
3957 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3959 TRACE("( %c, %p ), stub\n", cIn, puiOut );
3961 *puiOut = (USHORT) cIn;
3963 return S_OK;
3966 /******************************************************************************
3967 * VarUI2FromUI4 [OLEAUT32.268]
3969 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3971 TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3973 if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3975 return DISP_E_OVERFLOW;
3978 *puiOut = (USHORT) ulIn;
3980 return S_OK;
3983 /******************************************************************************
3984 * VarUI4FromStr [OLEAUT32.277]
3986 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3988 double dValue = 0.0;
3989 LPSTR pNewString = NULL;
3991 TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3993 /* Check if we have a valid argument
3995 pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3996 RemoveCharacterFromString( pNewString, "," );
3997 if( IsValidRealString( pNewString ) == FALSE )
3999 return DISP_E_TYPEMISMATCH;
4002 /* Convert the valid string to a floating point number.
4004 dValue = atof( pNewString );
4006 /* We don't need the string anymore so free it.
4008 HeapFree( GetProcessHeap(), 0, pNewString );
4010 /* Check range of value.
4012 dValue = round( dValue );
4013 if( dValue < UI4_MIN || dValue > UI4_MAX )
4015 return DISP_E_OVERFLOW;
4018 *pulOut = (ULONG) dValue;
4020 return S_OK;
4023 /**********************************************************************
4024 * VarUI2FromCy [OLEAUT32.263]
4025 * Convert currency to unsigned short
4027 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4028 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4030 if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4032 *pusOut = (USHORT)t;
4034 return S_OK;
4037 /******************************************************************************
4038 * VarUI4FromUI1 [OLEAUT32.270]
4040 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4042 TRACE("( %d, %p ), stub\n", bIn, pulOut );
4044 *pulOut = (USHORT) bIn;
4046 return S_OK;
4049 /******************************************************************************
4050 * VarUI4FromI2 [OLEAUT32.271]
4052 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4054 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4056 if( uiIn < UI4_MIN )
4058 return DISP_E_OVERFLOW;
4061 *pulOut = (ULONG) uiIn;
4063 return S_OK;
4066 /******************************************************************************
4067 * VarUI4FromI4 [OLEAUT32.272]
4069 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4071 TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4073 if( lIn < UI4_MIN )
4075 return DISP_E_OVERFLOW;
4078 *pulOut = (ULONG) lIn;
4080 return S_OK;
4083 /******************************************************************************
4084 * VarUI4FromR4 [OLEAUT32.273]
4086 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4088 fltIn = round( fltIn );
4089 if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4091 return DISP_E_OVERFLOW;
4094 *pulOut = (ULONG) fltIn;
4096 return S_OK;
4099 /******************************************************************************
4100 * VarUI4FromR8 [OLEAUT32.274]
4102 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4104 TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4106 dblIn = round( dblIn );
4107 if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4109 return DISP_E_OVERFLOW;
4112 *pulOut = (ULONG) dblIn;
4114 return S_OK;
4117 /******************************************************************************
4118 * VarUI4FromDate [OLEAUT32.275]
4120 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4122 TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4124 dateIn = round( dateIn );
4125 if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4127 return DISP_E_OVERFLOW;
4130 *pulOut = (ULONG) dateIn;
4132 return S_OK;
4135 /******************************************************************************
4136 * VarUI4FromBool [OLEAUT32.279]
4138 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4140 TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4142 *pulOut = (ULONG) boolIn;
4144 return S_OK;
4147 /******************************************************************************
4148 * VarUI4FromI1 [OLEAUT32.280]
4150 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4152 TRACE("( %c, %p ), stub\n", cIn, pulOut );
4154 *pulOut = (ULONG) cIn;
4156 return S_OK;
4159 /******************************************************************************
4160 * VarUI4FromUI2 [OLEAUT32.281]
4162 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4164 TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4166 *pulOut = (ULONG) uiIn;
4168 return S_OK;
4171 /**********************************************************************
4172 * VarUI4FromCy [OLEAUT32.276]
4173 * Convert currency to unsigned long
4175 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4176 double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4178 if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4180 *pulOut = (ULONG)t;
4182 return S_OK;
4185 /**********************************************************************
4186 * VarCyFromUI1 [OLEAUT32.98]
4187 * Convert unsigned char to currency
4189 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4190 pcyOut->s.Hi = 0;
4191 pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4193 return S_OK;
4196 /**********************************************************************
4197 * VarCyFromI2 [OLEAUT32.99]
4198 * Convert signed short to currency
4200 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4201 if (sIn < 0) pcyOut->s.Hi = -1;
4202 else pcyOut->s.Hi = 0;
4203 pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4205 return S_OK;
4208 /**********************************************************************
4209 * VarCyFromI4 [OLEAUT32.100]
4210 * Convert signed long to currency
4212 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4213 double t = (double)lIn * (double)10000;
4214 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4215 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4216 if (lIn < 0) pcyOut->s.Hi--;
4218 return S_OK;
4221 /**********************************************************************
4222 * VarCyFromR4 [OLEAUT32.101]
4223 * Convert float to currency
4225 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4226 double t = round((double)fltIn * (double)10000);
4227 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4228 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4229 if (fltIn < 0) pcyOut->s.Hi--;
4231 return S_OK;
4234 /**********************************************************************
4235 * VarCyFromR8 [OLEAUT32.102]
4236 * Convert double to currency
4238 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4239 double t = round(dblIn * (double)10000);
4240 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4241 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4242 if (dblIn < 0) pcyOut->s.Hi--;
4244 return S_OK;
4247 /**********************************************************************
4248 * VarCyFromDate [OLEAUT32.103]
4249 * Convert date to currency
4251 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4252 double t = round((double)dateIn * (double)10000);
4253 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4254 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4255 if (dateIn < 0) pcyOut->s.Hi--;
4257 return S_OK;
4260 /**********************************************************************
4261 * VarCyFromStr [OLEAUT32.104]
4263 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4264 /* FIXME */
4265 return E_NOTIMPL;
4269 /**********************************************************************
4270 * VarCyFromBool [OLEAUT32.106]
4271 * Convert boolean to currency
4273 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4274 if (boolIn < 0) pcyOut->s.Hi = -1;
4275 else pcyOut->s.Hi = 0;
4276 pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4278 return S_OK;
4281 /**********************************************************************
4282 * VarCyFromI1 [OLEAUT32.225]
4283 * Convert signed char to currency
4285 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pcyOut) {
4286 if (cIn < 0) pcyOut->s.Hi = -1;
4287 else pcyOut->s.Hi = 0;
4288 pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4290 return S_OK;
4293 /**********************************************************************
4294 * VarCyFromUI2 [OLEAUT32.226]
4295 * Convert unsigned short to currency
4297 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4298 pcyOut->s.Hi = 0;
4299 pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4301 return S_OK;
4304 /**********************************************************************
4305 * VarCyFromUI4 [OLEAUT32.227]
4306 * Convert unsigned long to currency
4308 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4309 double t = (double)ulIn * (double)10000;
4310 pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4311 pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4313 return S_OK;
4317 /**********************************************************************
4318 * DosDateTimeToVariantTime [OLEAUT32.14]
4319 * Convert dos representation of time to the date and time representation
4320 * stored in a variant.
4322 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4323 DATE *pvtime)
4325 struct tm t;
4327 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4329 t.tm_sec = (wDosTime & 0x001f) * 2;
4330 t.tm_min = (wDosTime & 0x07e0) >> 5;
4331 t.tm_hour = (wDosTime & 0xf800) >> 11;
4333 t.tm_mday = (wDosDate & 0x001f);
4334 t.tm_mon = (wDosDate & 0x01e0) >> 5;
4335 t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4337 return TmToDATE( &t, pvtime );
4341 /**********************************************************************
4342 * VarParseNumFromStr [OLEAUT32.46]
4344 HRESULT WINAPI VarParseNumFromStr(OLECHAR * strIn, LCID lcid, ULONG dwFlags,
4345 NUMPARSE * pnumprs, BYTE * rgbDig)
4347 int i,lastent=0;
4348 int cDig;
4349 FIXME("(%s,flags=%lx,....), partial stub!\n",debugstr_w(strIn),dwFlags);
4350 FIXME("numparse: cDig=%d, InFlags=%lx\n",pnumprs->cDig,pnumprs->dwInFlags);
4352 /* The other struct components are to be set by us */
4354 memset(rgbDig,0,pnumprs->cDig);
4356 cDig = 0;
4357 for (i=0; strIn[i] ;i++) {
4358 if ((strIn[i]>='0') && (strIn[i]<='9')) {
4359 if (pnumprs->cDig > cDig) {
4360 *(rgbDig++)=strIn[i]-'0';
4361 cDig++;
4362 lastent = i;
4366 pnumprs->cDig = cDig;
4368 /* FIXME: Just patching some values in */
4369 pnumprs->nPwr10 = 0;
4370 pnumprs->nBaseShift = 0;
4371 pnumprs->cchUsed = lastent;
4372 pnumprs->dwOutFlags = NUMPRS_DECIMAL;
4373 return S_OK;
4377 /**********************************************************************
4378 * VarNumFromParseNum [OLEAUT32.47]
4380 HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig,
4381 ULONG dwVtBits, VARIANT * pvar)
4383 DWORD xint;
4384 int i;
4385 FIXME("(,dwVtBits=%lx,....), partial stub!\n",dwVtBits);
4387 xint = 0;
4388 for (i=0;i<pnumprs->cDig;i++)
4389 xint = xint*10 + rgbDig[i];
4391 VariantInit(pvar);
4392 if (dwVtBits & VTBIT_I4) {
4393 V_VT(pvar) = VT_I4;
4394 V_UNION(pvar,intVal) = xint;
4395 return S_OK;
4397 if (dwVtBits & VTBIT_R8) {
4398 V_VT(pvar) = VT_R8;
4399 V_UNION(pvar,dblVal) = xint;
4400 return S_OK;
4401 } else {
4402 FIXME("vtbitmask is unsupported %lx\n",dwVtBits);
4403 return E_FAIL;
4408 /**********************************************************************
4409 * VariantTimeToDosDateTime [OLEAUT32.13]
4410 * Convert variant representation of time to the date and time representation
4411 * stored in dos.
4413 INT WINAPI VariantTimeToDosDateTime(DATE pvtime, USHORT *wDosDate, USHORT *wDosTime)
4415 struct tm t;
4416 wDosTime = 0;
4417 wDosDate = 0;
4419 TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", *wDosDate, *wDosTime, &pvtime );
4421 if (DateToTm(pvtime, 0, &t) < 0) return 0;
4423 *wDosTime = *wDosTime | (t.tm_sec / 2);
4424 *wDosTime = *wDosTime | (t.tm_min << 5);
4425 *wDosTime = *wDosTime | (t.tm_hour << 11);
4427 *wDosDate = *wDosDate | t.tm_mday ;
4428 *wDosDate = *wDosDate | t.tm_mon << 5;
4429 *wDosDate = *wDosDate | ((t.tm_year - 1980) << 9) ;
4431 return 1;
4435 /***********************************************************************
4436 * SystemTimeToVariantTime [OLEAUT32.184]
4438 HRESULT WINAPI SystemTimeToVariantTime( LPSYSTEMTIME lpSystemTime, double *pvtime )
4440 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4441 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4443 struct tm t;
4445 TRACE(" %d/%d/%d %d:%d:%d\n",
4446 lpSystemTime->wMonth, lpSystemTime->wDay,
4447 lpSystemTime->wYear, lpSystemTime->wHour,
4448 lpSystemTime->wMinute, lpSystemTime->wSecond);
4450 if (lpSystemTime->wYear >= 1900)
4452 t.tm_sec = lpSystemTime->wSecond;
4453 t.tm_min = lpSystemTime->wMinute;
4454 t.tm_hour = lpSystemTime->wHour;
4456 t.tm_mday = lpSystemTime->wDay;
4457 t.tm_mon = lpSystemTime->wMonth;
4458 t.tm_year = lpSystemTime->wYear;
4460 return TmToDATE( &t, pvtime );
4462 else
4464 t.tm_sec = lpSystemTime->wSecond;
4465 t.tm_min = lpSystemTime->wMinute;
4466 t.tm_hour = lpSystemTime->wHour;
4468 if (isleap(lpSystemTime->wYear) )
4469 t.tm_mday = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4470 else
4471 t.tm_mday = Days_Per_Month[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4473 t.tm_mon = 13 - lpSystemTime->wMonth;
4474 t.tm_year = 1900 + 1899 - lpSystemTime->wYear;
4476 TmToDATE( &t, pvtime );
4478 *pvtime *= -1;
4480 return 1;
4483 return 0;
4486 /***********************************************************************
4487 * VariantTimeToSystemTime [OLEAUT32.185]
4489 HRESULT WINAPI VariantTimeToSystemTime( double vtime, LPSYSTEMTIME lpSystemTime )
4491 double t = 0, timeofday = 0;
4493 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4494 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4496 /* The Month_Code is used to find the Day of the Week (LY = LeapYear)*/
4497 static const BYTE Month_Code[] = {0, 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4498 static const BYTE Month_Code_LY[] = {0, 0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4500 /* The Century_Code is used to find the Day of the Week */
4501 static const BYTE Century_Code[] = {0, 6, 4, 2};
4503 struct tm r;
4505 TRACE(" Variant = %f SYSTEMTIME ptr %p", vtime, lpSystemTime);
4507 if (vtime >= 0)
4510 if (DateToTm(vtime, 0, &r ) <= 0) return 0;
4512 lpSystemTime->wSecond = r.tm_sec;
4513 lpSystemTime->wMinute = r.tm_min;
4514 lpSystemTime->wHour = r.tm_hour;
4515 lpSystemTime->wDay = r.tm_mday;
4516 lpSystemTime->wMonth = r.tm_mon;
4518 if (lpSystemTime->wMonth == 12)
4519 lpSystemTime->wMonth = 1;
4520 else
4521 lpSystemTime->wMonth++;
4523 lpSystemTime->wYear = r.tm_year;
4525 else
4527 vtime = -1*vtime;
4529 if (DateToTm(vtime, 0, &r ) <= 0) return 0;
4531 lpSystemTime->wSecond = r.tm_sec;
4532 lpSystemTime->wMinute = r.tm_min;
4533 lpSystemTime->wHour = r.tm_hour;
4535 lpSystemTime->wMonth = 13 - r.tm_mon;
4537 if (lpSystemTime->wMonth == 1)
4538 lpSystemTime->wMonth = 12;
4539 else
4540 lpSystemTime->wMonth--;
4542 lpSystemTime->wYear = 1899 - (r.tm_year - 1900);
4544 if (!isleap(lpSystemTime->wYear) )
4545 lpSystemTime->wDay = Days_Per_Month[13 - lpSystemTime->wMonth] - r.tm_mday;
4546 else
4547 lpSystemTime->wDay = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - r.tm_mday;
4552 if (!isleap(lpSystemTime->wYear))
4555 (Century_Code+Month_Code+Year_Code+Day) % 7
4557 The century code repeats every 400 years , so the array
4558 works out like this,
4560 Century_Code[0] is for 16th/20th Centry
4561 Century_Code[1] is for 17th/21th Centry
4562 Century_Code[2] is for 18th/22th Centry
4563 Century_Code[3] is for 19th/23th Centry
4565 The year code is found with the formula (year + (year / 4))
4566 the "year" must be between 0 and 99 .
4568 The Month Code (Month_Code[1]) starts with January and
4569 ends with December.
4572 lpSystemTime->wDayOfWeek = (
4573 Century_Code[(( (lpSystemTime->wYear+100) - lpSystemTime->wYear%100) /100) %4]+
4574 ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4575 Month_Code[lpSystemTime->wMonth]+
4576 lpSystemTime->wDay) % 7;
4578 if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4579 else lpSystemTime->wDayOfWeek -= 1;
4581 else
4583 lpSystemTime->wDayOfWeek = (
4584 Century_Code[(((lpSystemTime->wYear+100) - lpSystemTime->wYear%100)/100)%4]+
4585 ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4586 Month_Code_LY[lpSystemTime->wMonth]+
4587 lpSystemTime->wDay) % 7;
4589 if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4590 else lpSystemTime->wDayOfWeek -= 1;
4593 t = floor(vtime);
4594 timeofday = vtime - t;
4596 lpSystemTime->wMilliseconds = (timeofday
4597 - lpSystemTime->wHour*(1/24)
4598 - lpSystemTime->wMinute*(1/1440)
4599 - lpSystemTime->wSecond*(1/86400) )*(1/5184000);
4601 return 1;
4604 /***********************************************************************
4605 * VarUdateFromDate [OLEAUT32.331]
4607 HRESULT WINAPI VarUdateFromDate( DATE datein, ULONG dwFlags, UDATE *pudateout)
4609 HRESULT i = 0;
4610 static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4611 static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4613 TRACE("DATE = %f\n", (double)datein);
4614 i = VariantTimeToSystemTime(datein, &(pudateout->st) );
4616 if (i)
4618 pudateout->wDayOfYear = 0;
4620 if (isleap(pudateout->st.wYear))
4622 for (i =1; i<pudateout->st.wMonth; i++)
4623 pudateout->wDayOfYear += Days_Per_Month[i];
4625 else
4627 for (i =1; i<pudateout->st.wMonth; i++)
4628 pudateout->wDayOfYear += Days_Per_Month_LY[i];
4631 pudateout->wDayOfYear += pudateout->st.wDay;
4632 dwFlags = 0; /*VAR_VALIDDATE*/
4634 else dwFlags = 0;
4636 return i;
4639 /***********************************************************************
4640 * VarDateFromUdate [OLEAUT32.330]
4642 HRESULT WINAPI VarDateFromUdate(UDATE *pudateout,
4643 ULONG dwFlags, DATE *datein)
4645 HRESULT i;
4646 double t = 0;
4647 TRACE(" %d/%d/%d %d:%d:%d\n",
4648 pudateout->st.wMonth, pudateout->st.wDay,
4649 pudateout->st.wYear, pudateout->st.wHour,
4650 pudateout->st.wMinute, pudateout->st.wSecond);
4653 i = SystemTimeToVariantTime(&(pudateout->st), &t);
4654 *datein = t;
4656 if (i) dwFlags = 0; /*VAR_VALIDDATE*/
4657 else dwFlags = 0;
4659 return i;
4663 /**********************************************************************
4664 * VarBstrCmp [OLEAUT32.440]
4666 * flags can be:
4667 * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS
4668 * NORM_IGNORESTRINGWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA
4671 HRESULT WINAPI VarBstrCmp(BSTR left, BSTR right, LCID lcid, DWORD flags)
4673 DWORD r;
4675 FIXME("( %s %s %ld %lx ) partial stub\n", debugstr_w(left), debugstr_w(right), lcid, flags);
4677 if((!left) || (!right))
4678 return VARCMP_NULL;
4680 if(flags&NORM_IGNORECASE)
4681 r = lstrcmpiW(left,right);
4682 else
4683 r = lstrcmpW(left,right);
4685 if(r<0)
4686 return VARCMP_LT;
4687 if(r>0)
4688 return VARCMP_GT;
4690 return VARCMP_EQ;
4693 /**********************************************************************
4694 * VarBstrCat [OLEAUT32.439]
4696 HRESULT WINAPI VarBstrCat(BSTR left, BSTR right, BSTR *out)
4698 BSTR result;
4700 TRACE("( %s %s %p )\n", debugstr_w(left), debugstr_w(right), out);
4702 if( (!left) || (!right) || (!out) )
4703 return 0;
4705 result = SysAllocStringLen(left, lstrlenW(left)+lstrlenW(right));
4706 lstrcatW(result,right);
4708 *out = result;
4710 return 1;