- implemented SystemTimetoVariantTime/VariantTimetoSystemTime
[wine] / dlls / oleaut32 / variant.c
1 /*
2  * VARIANT
3  *
4  * Copyright 1998 Jean-Claude Cote
5  *
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.
11  *
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.
21  */
22
23 #include "config.h"
24  
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <time.h>
30
31 #ifdef HAVE_FLOAT_H
32 # include <float.h>
33 #endif
34
35 #include "windef.h"
36 #include "oleauto.h"
37 #include "heap.h"
38 #include "debugtools.h"
39 #include "winerror.h"
40 #include "parsedt.h"
41
42 DEFAULT_DEBUG_CHANNEL(ole);
43
44 #ifndef FLT_MAX
45 # ifdef MAXFLOAT
46 #  define FLT_MAX MAXFLOAT
47 # else
48 #  error "Can't find #define for MAXFLOAT/FLT_MAX"
49 # endif
50 #endif
51
52 #undef CHAR_MAX
53 #undef CHAR_MIN
54 static const char CHAR_MAX = 127;
55 static const char CHAR_MIN = -128;
56 static const BYTE UI1_MAX = 255;
57 static const BYTE UI1_MIN = 0;
58 static const unsigned short UI2_MAX = 65535;
59 static const unsigned short UI2_MIN = 0;
60 static const short I2_MAX = 32767;
61 static const short I2_MIN =  -32768;
62 static const unsigned long UI4_MAX = 4294967295U;
63 static const unsigned long UI4_MIN = 0;
64 static const long I4_MAX = 2147483647;
65 static const long I4_MIN = -(2147483648U);
66 static const DATE DATE_MIN = -657434;
67 static const DATE DATE_MAX = 2958465;
68
69
70 /* This mask is used to set a flag in wReserved1 of
71  * the VARIANTARG structure. The flag indicates if
72  * the API function is using an inner variant or not.
73  */
74 #define PROCESSING_INNER_VARIANT 0x0001
75
76 /* General use buffer.
77  */
78 #define BUFFER_MAX 1024
79 static char pBuffer[BUFFER_MAX];
80
81 /*
82  * Note a leap year is one that is a multiple of 4
83  * but not of a 100.  Except if it is a multiple of
84  * 400 then it is a leap year.
85  */
86 /* According to postgeSQL date parsing functions there is
87  * a leap year when this expression is true.
88  * (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
89  * So according to this there is 365.2515 days in one year.
90  * One + every four years: 1/4 -> 365.25
91  * One - every 100 years: 1/100 -> 365.01
92  * One + every 400 years: 1/400 -> 365.0025
93  */
94 /* static const double DAYS_IN_ONE_YEAR = 365.2515;
95  *
96  *  ^^  Might this be the key to an easy way to factor large prime numbers?
97  *  Let's try using arithmetic.  <lawson_whitney@juno.com> 7 Mar 2000
98  */
99 static const double DAYS_IN_ONE_YEAR = 365.2425;
100
101 /******************************************************************************
102  *         DateTimeStringToTm   [INTERNAL]
103  *
104  * Converts a string representation of a date and/or time to a tm structure.
105  *
106  * Note this function uses the postgresql date parsing functions found
107  * in the parsedt.c file.
108  *
109  * Returns TRUE if successful.
110  *
111  * Note: This function does not parse the day of the week,
112  * daylight savings time. It will only fill the followin fields in
113  * the tm struct, tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
114  *
115  ******************************************************************************/
116 static BOOL DateTimeStringToTm( OLECHAR* strIn, LCID lcid, struct tm* pTm )
117 {
118         BOOL res = FALSE;
119         double          fsec;
120         int             tzp;
121         int             dtype;
122         int             nf;
123         char       *field[MAXDATEFIELDS];
124         int             ftype[MAXDATEFIELDS];
125         char            lowstr[MAXDATELEN + 1];
126         char* strDateTime = NULL;
127
128         /* Convert the string to ASCII since this is the only format
129          * postgesql can handle.
130          */
131         strDateTime = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
132
133         if( strDateTime != NULL )
134         {
135                 /* Make sure we don't go over the maximum length
136                  * accepted by postgesql.
137                  */
138                 if( strlen( strDateTime ) <= MAXDATELEN )
139                 {
140                         if( ParseDateTime( strDateTime, lowstr, field, ftype, MAXDATEFIELDS, &nf) == 0 )
141                         {
142                                 if( lcid & VAR_DATEVALUEONLY )
143                                 {
144                                         /* Get the date information.
145                                          * It returns 0 if date information was
146                                          * present and 1 if only time information was present.
147                                          * -1 if an error occures.
148                                          */
149                                         if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) == 0 )
150                                         {
151                                                 /* Eliminate the time information since we
152                                                  * were asked to get date information only.
153                                                  */
154                                                 pTm->tm_sec = 0;
155                                                 pTm->tm_min = 0;
156                                                 pTm->tm_hour = 0;
157                                                 res = TRUE;
158                                         }
159                                 }
160                                 if( lcid & VAR_TIMEVALUEONLY )
161                                 {
162                                         /* Get time information only.
163                                          */
164                                         if( DecodeTimeOnly(field, ftype, nf, &dtype, pTm, &fsec) == 0 )
165                                         {
166                                                 res = TRUE;
167                                         }
168                                 }
169                                 else
170                                 {
171                                         /* Get both date and time information.
172                                          * It returns 0 if date information was
173                                          * present and 1 if only time information was present.
174                                          * -1 if an error occures.
175                                          */
176                                         if( DecodeDateTime(field, ftype, nf, &dtype, pTm, &fsec, &tzp) != -1 )
177                                         {
178                                                 res = TRUE;
179                                         }
180                                 }
181                         }
182                 }
183                 HeapFree( GetProcessHeap(), 0, strDateTime );
184         }
185
186         return res;
187 }
188
189
190
191
192
193
194 /******************************************************************************
195  *         TmToDATE     [INTERNAL]
196  *
197  * The date is implemented using an 8 byte floating-point number.
198  * Days are represented by whole numbers increments starting with 0.00 has
199  * being December 30 1899, midnight.
200  * The hours are expressed as the fractional part of the number.
201  * December 30 1899 at midnight = 0.00
202  * January 1 1900 at midnight = 2.00
203  * January 4 1900 at 6 AM = 5.25
204  * January 4 1900 at noon = 5.50
205  * December 29 1899 at midnight = -1.00
206  * December 18 1899 at midnight = -12.00
207  * December 18 1899 at 6AM = -12.25
208  * December 18 1899 at 6PM = -12.75
209  * December 19 1899 at midnight = -11.00
210  * The tm structure is as follows:
211  * struct tm {
212  *                int tm_sec;      seconds after the minute - [0,59]
213  *                int tm_min;      minutes after the hour - [0,59]
214  *                int tm_hour;     hours since midnight - [0,23]
215  *                int tm_mday;     day of the month - [1,31]
216  *                int tm_mon;      months since January - [0,11]
217  *                int tm_year;     years
218  *                int tm_wday;     days since Sunday - [0,6]
219  *                int tm_yday;     days since January 1 - [0,365]
220  *                int tm_isdst;    daylight savings time flag
221  *                };
222  *
223  * Note: This function does not use the tm_wday, tm_yday, tm_wday,
224  * and tm_isdst fields of the tm structure. And only converts years
225  * after 1900.
226  *
227  * Returns TRUE if successful.
228  */
229 static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
230 {
231         if( (pTm->tm_year - 1900) >= 0 )
232         {
233                 int leapYear = 0;
234                 
235                 /* Start at 1. This is the way DATE is defined.
236                  * January 1, 1900 at Midnight is 1.00.
237                  * January 1, 1900 at 6AM is 1.25.
238                  * and so on.
239                  */
240                 *pDateOut = 1;
241
242                 /* Add the number of days corresponding to
243                  * tm_year.
244                  */
245                 *pDateOut += (pTm->tm_year - 1900) * 365;
246
247                 /* Add the leap days in the previous years between now and 1900.
248                  * Note a leap year is one that is a multiple of 4
249                  * but not of a 100.  Except if it is a multiple of
250                  * 400 then it is a leap year.
251                  */
252                 *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
253                 *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
254                 *pDateOut += ( (pTm->tm_year - 1) / 400 ) - ( 1900 / 400 );
255
256                 /* Set the leap year flag if the
257                  * current year specified by tm_year is a
258                  * leap year. This will be used to add a day
259                  * to the day count.
260                  */
261                 if( isleap( pTm->tm_year ) )
262                         leapYear = 1;
263                 
264                 /* Add the number of days corresponding to
265                  * the month.
266                  */
267                 switch( pTm->tm_mon )
268                 {
269                 case 2:
270                         *pDateOut += 31;
271                         break;
272                 case 3:
273                         *pDateOut += ( 59 + leapYear );
274                         break;
275                 case 4:
276                         *pDateOut += ( 90 + leapYear );
277                         break;
278                 case 5:
279                         *pDateOut += ( 120 + leapYear );
280                         break;
281                 case 6:
282                         *pDateOut += ( 151 + leapYear );
283                         break;
284                 case 7:
285                         *pDateOut += ( 181 + leapYear );
286                         break;
287                 case 8:
288                         *pDateOut += ( 212 + leapYear );
289                         break;
290                 case 9:
291                         *pDateOut += ( 243 + leapYear );
292                         break;
293                 case 10:
294                         *pDateOut += ( 273 + leapYear );
295                         break;
296                 case 11:
297                         *pDateOut += ( 304 + leapYear );
298                         break;
299                 case 12:
300                         *pDateOut += ( 334 + leapYear );
301                         break;
302                 }
303                 /* Add the number of days in this month.
304                  */
305                 *pDateOut += pTm->tm_mday;
306         
307                 /* Add the number of seconds, minutes, and hours
308                  * to the DATE. Note these are the fracionnal part
309                  * of the DATE so seconds / number of seconds in a day.
310                  */
311                 *pDateOut += pTm->tm_hour / 24.0;
312                 *pDateOut += pTm->tm_min / 1440.0;
313                 *pDateOut += pTm->tm_sec / 86400.0;
314                 return TRUE;
315         }
316         return FALSE;
317 }
318
319 /******************************************************************************
320  *         DateToTm     [INTERNAL]
321  *
322  * This function converts a windows DATE to a tm structure.
323  *
324  * It does not fill all the fields of the tm structure.
325  * Here is a list of the fields that are filled:
326  * tm_sec, tm_min, tm_hour, tm_year, tm_day, tm_mon.
327  *
328  * Note this function does not support dates before the January 1, 1900
329  * or ( dateIn < 2.0 ).
330  *
331  * Returns TRUE if successful.
332  */
333 static BOOL DateToTm( DATE dateIn, LCID lcid, struct tm* pTm )
334 {
335         /* Do not process dates smaller than January 1, 1900.
336          * Which corresponds to 2.0 in the windows DATE format.
337          */
338         if( dateIn >= 2.0 )
339         {
340                 double decimalPart = 0.0;
341                 double wholePart = 0.0;
342
343                 memset(pTm,0,sizeof(*pTm));
344         
345                 /* Because of the nature of DATE format which
346                  * associates 2.0 to January 1, 1900. We will
347                  * remove 1.0 from the whole part of the DATE
348                  * so that in the following code 1.0
349                  * will correspond to January 1, 1900.
350                  * This simplifies the processing of the DATE value.
351                  */
352                 dateIn -= 1.0;
353
354                 wholePart = (double) floor( dateIn );
355                 decimalPart = fmod( dateIn, wholePart );
356
357                 if( !(lcid & VAR_TIMEVALUEONLY) )
358                 {
359                         int nDay = 0;
360                         int leapYear = 0;
361                         double yearsSince1900 = 0;
362                         /* Start at 1900, this is where the DATE time 0.0 starts.
363                          */
364                         pTm->tm_year = 1900;
365                         /* find in what year the day in the "wholePart" falls into.
366                          * add the value to the year field.
367                          */
368                         yearsSince1900 = floor( (wholePart / DAYS_IN_ONE_YEAR) + 0.001 );
369                         pTm->tm_year += yearsSince1900;
370                         /* determine if this is a leap year.
371                          */
372                         if( isleap( pTm->tm_year ) )
373                         {
374                                 leapYear = 1;
375                                 wholePart++;
376                         }
377
378                         /* find what day of that year the "wholePart" corresponds to.
379                          * Note: nDay is in [1-366] format
380                          */
381                         nDay = (int) ( wholePart - floor( yearsSince1900 * DAYS_IN_ONE_YEAR ) );
382                         /* Set the tm_yday value.
383                          * Note: The day must be converted from [1-366] to [0-365]
384                          */
385                         /*pTm->tm_yday = nDay - 1;*/
386                         /* find which month this day corresponds to.
387                          */
388                         if( nDay <= 31 )
389                         {
390                                 pTm->tm_mday = nDay;
391                                 pTm->tm_mon = 0;
392                         }
393                         else if( nDay <= ( 59 + leapYear ) )
394                         {
395                                 pTm->tm_mday = nDay - 31;
396                                 pTm->tm_mon = 1;
397                         }
398                         else if( nDay <= ( 90 + leapYear ) )
399                         {
400                                 pTm->tm_mday = nDay - ( 59 + leapYear );
401                                 pTm->tm_mon = 2;
402                         }
403                         else if( nDay <= ( 120 + leapYear ) )
404                         {
405                                 pTm->tm_mday = nDay - ( 90 + leapYear );
406                                 pTm->tm_mon = 3;
407                         }
408                         else if( nDay <= ( 151 + leapYear ) )
409                         {
410                                 pTm->tm_mday = nDay - ( 120 + leapYear );
411                                 pTm->tm_mon = 4;
412                         }
413                         else if( nDay <= ( 181 + leapYear ) )
414                         {
415                                 pTm->tm_mday = nDay - ( 151 + leapYear );
416                                 pTm->tm_mon = 5;
417                         }
418                         else if( nDay <= ( 212 + leapYear ) )
419                         {
420                                 pTm->tm_mday = nDay - ( 181 + leapYear );
421                                 pTm->tm_mon = 6;
422                         }
423                         else if( nDay <= ( 243 + leapYear ) )
424                         {
425                                 pTm->tm_mday = nDay - ( 212 + leapYear );
426                                 pTm->tm_mon = 7;
427                         }
428                         else if( nDay <= ( 273 + leapYear ) )
429                         {
430                                 pTm->tm_mday = nDay - ( 243 + leapYear );
431                                 pTm->tm_mon = 8;
432                         }
433                         else if( nDay <= ( 304 + leapYear ) )
434                         {
435                                 pTm->tm_mday = nDay - ( 273 + leapYear );
436                                 pTm->tm_mon = 9;
437                         }
438                         else if( nDay <= ( 334 + leapYear ) )
439                         {
440                                 pTm->tm_mday = nDay - ( 304 + leapYear );
441                                 pTm->tm_mon = 10;
442                         }
443                         else if( nDay <= ( 365 + leapYear ) )
444                         {
445                                 pTm->tm_mday = nDay - ( 334 + leapYear );
446                                 pTm->tm_mon = 11;
447                         }
448                 }
449                 if( !(lcid & VAR_DATEVALUEONLY) )
450                 {
451                         /* find the number of seconds in this day.
452                          * fractional part times, hours, minutes, seconds.
453                          */
454                         pTm->tm_hour = (int) ( decimalPart * 24 );
455                         pTm->tm_min = (int) ( ( ( decimalPart * 24 ) - pTm->tm_hour ) * 60 );
456                         pTm->tm_sec = (int) ( ( ( decimalPart * 24 * 60 ) - ( pTm->tm_hour * 60 ) - pTm->tm_min ) * 60 );
457                 }
458                 return TRUE;
459         }
460         return FALSE;
461 }
462
463
464
465 /******************************************************************************
466  *         SizeOfVariantData    [INTERNAL]
467  *
468  * This function finds the size of the data referenced by a Variant based
469  * the type "vt" of the Variant.
470  */
471 static int SizeOfVariantData( VARIANT* parg )
472 {
473     int size = 0;
474     switch( parg->vt & VT_TYPEMASK )
475     {
476     case( VT_I2 ):
477         size = sizeof(short);
478         break;
479     case( VT_INT ):
480         size = sizeof(int);
481         break;
482     case( VT_I4 ):
483         size = sizeof(long);
484         break;
485     case( VT_UI1 ):
486         size = sizeof(BYTE);
487         break;
488     case( VT_UI2 ):
489         size = sizeof(unsigned short);
490         break;
491     case( VT_UINT ):
492         size = sizeof(unsigned int);
493         break;
494     case( VT_UI4 ):
495         size = sizeof(unsigned long);
496         break;
497     case( VT_R4 ):
498         size = sizeof(float);
499         break;
500     case( VT_R8 ):
501         size = sizeof(double);
502         break;
503     case( VT_DATE ):
504         size = sizeof(DATE);
505         break;
506     case( VT_BOOL ):
507         size = sizeof(VARIANT_BOOL);
508         break;
509     case( VT_BSTR ):
510         size = sizeof(void*);
511         break;
512     case( VT_CY ):
513     case( VT_DISPATCH ):
514     case( VT_UNKNOWN ):
515     case( VT_DECIMAL ):
516     default:
517         FIXME("Add size information for type vt=%d\n", parg->vt & VT_TYPEMASK );
518         break;
519     }
520
521     return size;
522 }
523 /******************************************************************************
524  *         StringDupAtoBstr             [INTERNAL]
525  * 
526  */
527 static BSTR StringDupAtoBstr( char* strIn )
528 {
529         BSTR bstr = NULL;
530         OLECHAR* pNewString = NULL;
531         pNewString = HEAP_strdupAtoW( GetProcessHeap(), 0, strIn );
532         bstr = SysAllocString( pNewString );
533         HeapFree( GetProcessHeap(), 0, pNewString );
534         return bstr;
535 }
536
537 /******************************************************************************
538  *              round           [INTERNAL]
539  *
540  * Round the double value to the nearest integer value.
541  */
542 static double round( double d )
543 {
544    double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
545     BOOL bEvenNumber = FALSE;
546     int nSign = 0;
547
548     /* Save the sign of the number
549      */
550    nSign = (d >= 0.0) ? 1 : -1;
551     d = fabs( d );
552     
553         /* Remove the decimals.
554          */
555    integerValue = floor( d );
556
557     /* Set the Even flag.  This is used to round the number when
558      * the decimals are exactly 1/2.  If the integer part is
559      * odd the number is rounded up. If the integer part
560      * is even the number is rounded down.  Using this method
561      * numbers are rounded up|down half the time.
562      */
563    bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
564
565     /* Remove the integral part of the number.
566      */
567     decimals = d - integerValue;
568
569         /* Note: Ceil returns the smallest integer that is greater that x.
570          * and floor returns the largest integer that is less than or equal to x.
571          */
572     if( decimals > 0.5 )
573     {
574         /* If the decimal part is greater than 1/2
575          */
576         roundedValue = ceil( d );
577     }
578     else if( decimals < 0.5 )
579     {
580         /* If the decimal part is smaller than 1/2
581          */
582         roundedValue = floor( d );
583     }
584     else
585     {
586         /* the decimals are exactly 1/2 so round according to
587          * the bEvenNumber flag.
588          */
589         if( bEvenNumber )
590         {
591             roundedValue = floor( d );
592         }
593         else
594         {
595             roundedValue = ceil( d );
596         }
597     }
598
599         return roundedValue * nSign;
600 }
601
602 /******************************************************************************
603  *              RemoveCharacterFromString               [INTERNAL]
604  *
605  * Removes any of the characters in "strOfCharToRemove" from the "str" argument.
606  */
607 static void RemoveCharacterFromString( LPSTR str, LPSTR strOfCharToRemove )
608 {
609         LPSTR pNewString = NULL;
610         LPSTR strToken = NULL;
611
612
613         /* Check if we have a valid argument
614          */
615         if( str != NULL )
616         {
617                 pNewString = strdup( str );
618                 str[0] = '\0';
619                 strToken = strtok( pNewString, strOfCharToRemove );
620                 while( strToken != NULL ) { 
621                         strcat( str, strToken );
622                         strToken = strtok( NULL, strOfCharToRemove );
623                 }
624                 free( pNewString );
625         }
626         return;
627 }
628
629 /******************************************************************************
630  *              GetValidRealString              [INTERNAL]
631  *
632  * Checks if the string is of proper format to be converted to a real value.
633  */
634 static BOOL IsValidRealString( LPSTR strRealString )
635 {
636         /* Real values that have a decimal point are required to either have
637          * digits before or after the decimal point.  We will assume that
638          * we do not have any digits at either position. If we do encounter
639          * some we will disable this flag.
640          */
641         BOOL bDigitsRequired = TRUE;
642         /* Processed fields in the string representation of the real number.
643          */
644         BOOL bWhiteSpaceProcessed = FALSE;
645         BOOL bFirstSignProcessed = FALSE;
646         BOOL bFirstDigitsProcessed = FALSE;
647         BOOL bDecimalPointProcessed = FALSE;
648         BOOL bSecondDigitsProcessed = FALSE;
649         BOOL bExponentProcessed = FALSE;
650         BOOL bSecondSignProcessed = FALSE;
651         BOOL bThirdDigitsProcessed = FALSE;
652         /* Assume string parameter "strRealString" is valid and try to disprove it.
653          */
654         BOOL bValidRealString = TRUE;
655
656         /* Used to count the number of tokens in the "strRealString".
657          */
658         LPSTR strToken = NULL;
659         int nTokens = 0;
660         LPSTR pChar = NULL;
661         
662         /* Check if we have a valid argument
663          */
664         if( strRealString == NULL )
665         {
666                 bValidRealString = FALSE;
667         }
668
669         if( bValidRealString == TRUE )
670         {
671                 /* Make sure we only have ONE token in the string.
672                  */
673                 strToken = strtok( strRealString, " " );
674                 while( strToken != NULL ) { 
675                         nTokens++;              
676                         strToken = strtok( NULL, " " ); 
677                 }
678
679                 if( nTokens != 1 )
680                 {
681                         bValidRealString = FALSE;
682                 }
683         }
684
685
686         /* Make sure this token contains only valid characters.
687          * The string argument to atof has the following form:
688          * [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits]
689          * Whitespace consists of space and|or <TAB> characters, which are ignored.
690      * Sign is either plus '+' or minus '-'.
691      * Digits are one or more decimal digits.
692      * Note: If no digits appear before the decimal point, at least one must
693      * appear after the decimal point.
694      * The decimal digits may be followed by an exponent.
695      * An Exponent consists of an introductory letter ( D, d, E, or e) and
696          * an optionally signed decimal integer.
697          */
698         pChar = strRealString;
699         while( bValidRealString == TRUE && *pChar != '\0' )
700         {
701                 switch( *pChar )
702                 {
703                 /* If whitespace...
704                  */
705                 case ' ':
706                 case '\t':
707                         if( bWhiteSpaceProcessed ||
708                                 bFirstSignProcessed ||
709                                 bFirstDigitsProcessed ||
710                                 bDecimalPointProcessed ||
711                                 bSecondDigitsProcessed ||
712                                 bExponentProcessed ||
713                                 bSecondSignProcessed ||
714                                 bThirdDigitsProcessed )
715                         {
716                                 bValidRealString = FALSE;
717                         }
718                         break;
719                 /* If sign...
720                  */
721                 case '+':
722                 case '-':
723                         if( bFirstSignProcessed == FALSE )
724                         {
725                                 if( bFirstDigitsProcessed ||
726                                         bDecimalPointProcessed ||
727                                         bSecondDigitsProcessed ||
728                                         bExponentProcessed ||
729                                         bSecondSignProcessed ||
730                                         bThirdDigitsProcessed )
731                                 {
732                                         bValidRealString = FALSE;
733                                 }
734                                 bWhiteSpaceProcessed = TRUE;
735                                 bFirstSignProcessed = TRUE;
736                         }
737                         else if( bSecondSignProcessed == FALSE )
738                         {
739                 /* Note: The exponent must be present in
740                                  * order to accept the second sign...
741                                  */
742                                 if( bExponentProcessed == FALSE ||
743                                         bThirdDigitsProcessed ||
744                                         bDigitsRequired )
745                                 {
746                                         bValidRealString = FALSE;
747                                 }
748                                 bFirstSignProcessed = TRUE;
749                                 bWhiteSpaceProcessed = TRUE;
750                                 bFirstDigitsProcessed = TRUE;
751                                 bDecimalPointProcessed = TRUE;
752                                 bSecondDigitsProcessed = TRUE;
753                                 bSecondSignProcessed = TRUE;
754                         }
755                         break;
756
757                 /* If decimals...
758                  */
759                 case '0':
760                 case '1':
761                 case '2':
762                 case '3':
763                 case '4':
764                 case '5':
765                 case '6':
766                 case '7':
767                 case '8':
768                 case '9': 
769                         if( bFirstDigitsProcessed == FALSE )
770                         {
771                                 if( bDecimalPointProcessed ||
772                                         bSecondDigitsProcessed ||
773                                         bExponentProcessed ||
774                                         bSecondSignProcessed ||
775                                         bThirdDigitsProcessed )
776                                 {
777                                         bValidRealString = FALSE;
778                                 }
779                                 bFirstSignProcessed = TRUE;
780                                 bWhiteSpaceProcessed = TRUE;
781                                 /* We have found some digits before the decimal point
782                                  * so disable the "Digits required" flag.
783                                  */
784                                 bDigitsRequired = FALSE;
785                         }
786                         else if( bSecondDigitsProcessed == FALSE )
787                         {
788                                 if( bExponentProcessed ||
789                                         bSecondSignProcessed ||
790                                         bThirdDigitsProcessed )
791                                 {
792                                         bValidRealString = FALSE;
793                                 }
794                                 bFirstSignProcessed = TRUE;
795                                 bWhiteSpaceProcessed = TRUE;
796                                 bFirstDigitsProcessed = TRUE;
797                                 bDecimalPointProcessed = TRUE;
798                                 /* We have found some digits after the decimal point
799                                  * so disable the "Digits required" flag.
800                                  */
801                                 bDigitsRequired = FALSE;
802                         }
803                         else if( bThirdDigitsProcessed == FALSE )
804                         {
805                                 /* Getting here means everything else should be processed.
806                  * If we get anything else than a decimal following this
807                  * digit it will be flagged by the other cases, so
808                                  * we do not really need to do anything in here.
809                                  */
810                         }
811                         break;
812                 /* If DecimalPoint...
813                  */
814                 case '.': 
815                         if( bDecimalPointProcessed ||
816                                 bSecondDigitsProcessed ||
817                                 bExponentProcessed ||
818                                 bSecondSignProcessed ||
819                                 bThirdDigitsProcessed )
820                         {
821                                 bValidRealString = FALSE;
822                         }
823                         bFirstSignProcessed = TRUE;
824                         bWhiteSpaceProcessed = TRUE;
825                         bFirstDigitsProcessed = TRUE;
826                         bDecimalPointProcessed = TRUE;
827                         break;
828                 /* If Exponent...
829                  */
830                 case 'e':
831                 case 'E':
832                 case 'd':
833                 case 'D':
834                         if( bExponentProcessed ||
835                                 bSecondSignProcessed ||
836                                 bThirdDigitsProcessed ||
837                                 bDigitsRequired )
838                         {
839                                 bValidRealString = FALSE;
840                         }
841                         bFirstSignProcessed = TRUE;
842                         bWhiteSpaceProcessed = TRUE;
843                         bFirstDigitsProcessed = TRUE;
844                         bDecimalPointProcessed = TRUE;
845                         bSecondDigitsProcessed = TRUE;
846                         bExponentProcessed = TRUE;
847                         break;
848                 default:
849                         bValidRealString = FALSE;
850                         break;
851                 }
852                 /* Process next character.
853                  */
854                 pChar++;
855         }
856
857         /* If the required digits were not present we have an invalid
858          * string representation of a real number.
859          */
860         if( bDigitsRequired == TRUE )
861         {
862                 bValidRealString = FALSE;
863         }
864
865         return bValidRealString;
866 }
867
868
869 /******************************************************************************
870  *              Coerce  [INTERNAL]
871  *
872  * This function dispatches execution to the proper conversion API
873  * to do the necessary coercion.
874  */
875 static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
876 {
877         HRESULT res = S_OK;
878         unsigned short vtFrom = 0;
879         vtFrom = ps->vt & VT_TYPEMASK;
880         
881         /* Note: Since "long" and "int" values both have 4 bytes and are
882          * both signed integers "int" will be treated as "long" in the
883          * following code.
884          * The same goes for their unsigned versions.
885          */
886
887         /* Trivial Case: If the coercion is from two types that are 
888          * identical then we can blindly copy from one argument to another.*/
889         if ((vt==vtFrom))
890         {
891            return VariantCopy(pd,ps);
892         }
893
894         /* Cases requiring thought*/
895         switch( vt )
896         {
897
898     case( VT_EMPTY ):
899         res = VariantClear( pd );
900         break;
901     case( VT_NULL ):
902         res = VariantClear( pd );
903         if( res == S_OK )
904         {
905             pd->vt = VT_NULL;
906         }
907         break;
908         case( VT_I1 ):
909                 switch( vtFrom )
910         {
911         case( VT_I1 ):
912             res = VariantCopy( pd, ps );
913             break;
914                 case( VT_I2 ):
915                         res = VarI1FromI2( ps->u.iVal, &(pd->u.cVal) );
916                         break;
917                 case( VT_INT ):
918                 case( VT_I4 ):
919                         res = VarI1FromI4( ps->u.lVal, &(pd->u.cVal) );
920                         break;
921                 case( VT_UI1 ):
922                         res = VarI1FromUI1( ps->u.bVal, &(pd->u.cVal) );
923                         break;
924                 case( VT_UI2 ):
925                         res = VarI1FromUI2( ps->u.uiVal, &(pd->u.cVal) );
926                         break;
927                 case( VT_UINT ):
928                 case( VT_UI4 ):
929                         res = VarI1FromUI4( ps->u.ulVal, &(pd->u.cVal) );
930                         break;
931                 case( VT_R4 ):
932                         res = VarI1FromR4( ps->u.fltVal, &(pd->u.cVal) );
933                         break;
934                 case( VT_R8 ):
935                         res = VarI1FromR8( ps->u.dblVal, &(pd->u.cVal) );
936                         break;
937                 case( VT_DATE ):
938                         res = VarI1FromDate( ps->u.date, &(pd->u.cVal) );
939                         break;
940                 case( VT_BOOL ):
941                         res = VarI1FromBool( ps->u.boolVal, &(pd->u.cVal) );
942                         break;
943                 case( VT_BSTR ):
944                         res = VarI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
945                         break;
946                 case( VT_CY ):
947                         res = VarI1FromCy( ps->u.cyVal, &(pd->u.cVal) );
948                         break;
949                 case( VT_DISPATCH ):
950                         /*res = VarI1FromDisp( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
951                 case( VT_DECIMAL ):
952                         /*res = VarI1FromDec( ps->u.decVal, &(pd->u.cVal) );*/
953                 case( VT_UNKNOWN ):
954                 default:
955                         res = DISP_E_TYPEMISMATCH;
956                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
957                         break;
958                 }
959                 break;
960
961         case( VT_I2 ):
962                 switch( vtFrom )
963                 {
964                 case( VT_I1 ):
965                         res = VarI2FromI1( ps->u.cVal, &(pd->u.iVal) );
966                         break;
967         case( VT_I2 ):
968             res = VariantCopy( pd, ps );
969             break;
970                 case( VT_INT ):
971                 case( VT_I4 ):
972                         res = VarI2FromI4( ps->u.lVal, &(pd->u.iVal) );
973                         break;
974                 case( VT_UI1 ):
975                         res = VarI2FromUI1( ps->u.bVal, &(pd->u.iVal) );
976                         break;
977                 case( VT_UI2 ):
978                         res = VarI2FromUI2( ps->u.uiVal, &(pd->u.iVal) );
979                         break;
980                 case( VT_UINT ):
981                 case( VT_UI4 ):
982                         res = VarI2FromUI4( ps->u.ulVal, &(pd->u.iVal) );
983                         break;
984                 case( VT_R4 ):
985                         res = VarI2FromR4( ps->u.fltVal, &(pd->u.iVal) );
986                         break;
987                 case( VT_R8 ):
988                         res = VarI2FromR8( ps->u.dblVal, &(pd->u.iVal) );
989                         break;
990                 case( VT_DATE ):
991                         res = VarI2FromDate( ps->u.date, &(pd->u.iVal) );
992                         break;
993                 case( VT_BOOL ):
994                         res = VarI2FromBool( ps->u.boolVal, &(pd->u.iVal) );
995                         break;
996                 case( VT_BSTR ):
997                         res = VarI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
998                         break;
999                 case( VT_CY ):
1000                         res = VarI2FromCy( ps->u.cyVal, &(pd->u.iVal) );
1001                         break;
1002                 case( VT_DISPATCH ):
1003                         /*res = VarI2FromDisp( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
1004                 case( VT_DECIMAL ):
1005                         /*res = VarI2FromDec( ps->u.deiVal, &(pd->u.iVal) );*/
1006                 case( VT_UNKNOWN ):
1007                 default:
1008                         res = DISP_E_TYPEMISMATCH;
1009                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1010                         break;
1011                 }
1012                 break;
1013
1014         case( VT_INT ):
1015         case( VT_I4 ):
1016                 switch( vtFrom )
1017                 {
1018                 case( VT_I1 ):
1019                         res = VarI4FromI1( ps->u.cVal, &(pd->u.lVal) );
1020                         break;
1021                 case( VT_I2 ):
1022                         res = VarI4FromI2( ps->u.iVal, &(pd->u.lVal) );
1023             break;
1024         case( VT_INT ):
1025         case( VT_I4 ):
1026             res = VariantCopy( pd, ps );
1027             break;
1028                 case( VT_UI1 ):
1029                         res = VarI4FromUI1( ps->u.bVal, &(pd->u.lVal) );
1030                         break;
1031                 case( VT_UI2 ):
1032                         res = VarI4FromUI2( ps->u.uiVal, &(pd->u.lVal) );
1033                         break;
1034                 case( VT_UINT ):
1035                 case( VT_UI4 ):
1036                         res = VarI4FromUI4( ps->u.ulVal, &(pd->u.lVal) );
1037                         break;
1038                 case( VT_R4 ):
1039                         res = VarI4FromR4( ps->u.fltVal, &(pd->u.lVal) );
1040                         break;
1041                 case( VT_R8 ):
1042                         res = VarI4FromR8( ps->u.dblVal, &(pd->u.lVal) );
1043                         break;
1044                 case( VT_DATE ):
1045                         res = VarI4FromDate( ps->u.date, &(pd->u.lVal) );
1046                         break;
1047                 case( VT_BOOL ):
1048                         res = VarI4FromBool( ps->u.boolVal, &(pd->u.lVal) );
1049                         break;
1050                 case( VT_BSTR ):
1051                         res = VarI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
1052                         break;
1053                 case( VT_CY ):
1054                         res = VarI4FromCy( ps->u.cyVal, &(pd->u.lVal) );
1055                         break;
1056                 case( VT_DISPATCH ):
1057                         /*res = VarI4FromDisp( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
1058                 case( VT_DECIMAL ):
1059                         /*res = VarI4FromDec( ps->u.deiVal, &(pd->u.lVal) );*/
1060                 case( VT_UNKNOWN ):
1061                 default:
1062                         res = DISP_E_TYPEMISMATCH;
1063                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1064                         break;
1065                 }
1066                 break;
1067
1068         case( VT_UI1 ):
1069                 switch( vtFrom )
1070                 {
1071                 case( VT_I1 ):
1072                         res = VarUI1FromI1( ps->u.cVal, &(pd->u.bVal) );
1073                         break;
1074                 case( VT_I2 ):
1075                         res = VarUI1FromI2( ps->u.iVal, &(pd->u.bVal) );
1076                         break;
1077                 case( VT_INT ):
1078                 case( VT_I4 ):
1079                         res = VarUI1FromI4( ps->u.lVal, &(pd->u.bVal) );
1080                         break;
1081         case( VT_UI1 ):
1082             res = VariantCopy( pd, ps );
1083             break;
1084                 case( VT_UI2 ):
1085                         res = VarUI1FromUI2( ps->u.uiVal, &(pd->u.bVal) );
1086                         break;
1087                 case( VT_UINT ):
1088                 case( VT_UI4 ):
1089                         res = VarUI1FromUI4( ps->u.ulVal, &(pd->u.bVal) );
1090                         break;
1091                 case( VT_R4 ):
1092                         res = VarUI1FromR4( ps->u.fltVal, &(pd->u.bVal) );
1093                         break;
1094                 case( VT_R8 ):
1095                         res = VarUI1FromR8( ps->u.dblVal, &(pd->u.bVal) );
1096                         break;
1097                 case( VT_DATE ):
1098                         res = VarUI1FromDate( ps->u.date, &(pd->u.bVal) );
1099                         break;
1100                 case( VT_BOOL ):
1101                         res = VarUI1FromBool( ps->u.boolVal, &(pd->u.bVal) );
1102                         break;
1103                 case( VT_BSTR ):
1104                         res = VarUI1FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
1105                         break;
1106                 case( VT_CY ):
1107                         res = VarUI1FromCy( ps->u.cyVal, &(pd->u.bVal) );
1108                         break;
1109                 case( VT_DISPATCH ):
1110                         /*res = VarUI1FromDisp( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
1111                 case( VT_DECIMAL ):
1112                         /*res = VarUI1FromDec( ps->u.deiVal, &(pd->u.bVal) );*/
1113                 case( VT_UNKNOWN ):
1114                 default:
1115                         res = DISP_E_TYPEMISMATCH;
1116                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1117                         break;
1118                 }
1119                 break;
1120
1121         case( VT_UI2 ):
1122                 switch( vtFrom )
1123                 {
1124                 case( VT_I1 ):
1125                         res = VarUI2FromI1( ps->u.cVal, &(pd->u.uiVal) );
1126                         break;
1127                 case( VT_I2 ):
1128                         res = VarUI2FromI2( ps->u.iVal, &(pd->u.uiVal) );
1129                         break;
1130                 case( VT_INT ):
1131                 case( VT_I4 ):
1132                         res = VarUI2FromI4( ps->u.lVal, &(pd->u.uiVal) );
1133                         break;
1134                 case( VT_UI1 ):
1135                         res = VarUI2FromUI1( ps->u.bVal, &(pd->u.uiVal) );
1136                         break;
1137         case( VT_UI2 ):
1138             res = VariantCopy( pd, ps );
1139             break;
1140                 case( VT_UINT ):
1141                 case( VT_UI4 ):
1142                         res = VarUI2FromUI4( ps->u.ulVal, &(pd->u.uiVal) );
1143                         break;
1144                 case( VT_R4 ):
1145                         res = VarUI2FromR4( ps->u.fltVal, &(pd->u.uiVal) );
1146                         break;
1147                 case( VT_R8 ):
1148                         res = VarUI2FromR8( ps->u.dblVal, &(pd->u.uiVal) );
1149                         break;
1150                 case( VT_DATE ):
1151                         res = VarUI2FromDate( ps->u.date, &(pd->u.uiVal) );
1152                         break;
1153                 case( VT_BOOL ):
1154                         res = VarUI2FromBool( ps->u.boolVal, &(pd->u.uiVal) );
1155                         break;
1156                 case( VT_BSTR ):
1157                         res = VarUI2FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
1158                         break;
1159                 case( VT_CY ):
1160                         res = VarUI2FromCy( ps->u.cyVal, &(pd->u.uiVal) );
1161                         break;
1162                 case( VT_DISPATCH ):
1163                         /*res = VarUI2FromDisp( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
1164                 case( VT_DECIMAL ):
1165                         /*res = VarUI2FromDec( ps->u.deiVal, &(pd->u.uiVal) );*/
1166                 case( VT_UNKNOWN ):
1167                 default:
1168                         res = DISP_E_TYPEMISMATCH;
1169                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1170                         break;
1171                 }
1172                 break;
1173
1174         case( VT_UINT ):
1175         case( VT_UI4 ):
1176                 switch( vtFrom )
1177                 {
1178                 case( VT_I1 ):
1179                         res = VarUI4FromI1( ps->u.cVal, &(pd->u.ulVal) );
1180                         break;
1181                 case( VT_I2 ):
1182                         res = VarUI4FromI2( ps->u.iVal, &(pd->u.ulVal) );
1183                         break;
1184                 case( VT_INT ):
1185                 case( VT_I4 ):
1186                         res = VarUI4FromI4( ps->u.lVal, &(pd->u.ulVal) );
1187                         break;
1188                 case( VT_UI1 ):
1189                         res = VarUI4FromUI1( ps->u.bVal, &(pd->u.ulVal) );
1190                         break;
1191                 case( VT_UI2 ):
1192                         res = VarUI4FromUI2( ps->u.uiVal, &(pd->u.ulVal) );
1193                         break;
1194         case( VT_UI4 ):
1195             res = VariantCopy( pd, ps );
1196             break;
1197                 case( VT_R4 ):
1198                         res = VarUI4FromR4( ps->u.fltVal, &(pd->u.ulVal) );
1199                         break;
1200                 case( VT_R8 ):
1201                         res = VarUI4FromR8( ps->u.dblVal, &(pd->u.ulVal) );
1202                         break;
1203                 case( VT_DATE ):
1204                         res = VarUI4FromDate( ps->u.date, &(pd->u.ulVal) );
1205                         break;
1206                 case( VT_BOOL ):
1207                         res = VarUI4FromBool( ps->u.boolVal, &(pd->u.ulVal) );
1208                         break;
1209                 case( VT_BSTR ):
1210                         res = VarUI4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
1211                         break;
1212                 case( VT_CY ):
1213                         res = VarUI4FromCy( ps->u.cyVal, &(pd->u.ulVal) );
1214                         break;
1215                 case( VT_DISPATCH ):
1216                         /*res = VarUI4FromDisp( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
1217                 case( VT_DECIMAL ):
1218                         /*res = VarUI4FromDec( ps->u.deiVal, &(pd->u.ulVal) );*/
1219                 case( VT_UNKNOWN ):
1220                 default:
1221                         res = DISP_E_TYPEMISMATCH;
1222                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1223                         break;
1224                 }
1225                 break;
1226                 
1227         case( VT_R4 ):
1228                 switch( vtFrom )
1229                 {
1230                 case( VT_I1 ):
1231                         res = VarR4FromI1( ps->u.cVal, &(pd->u.fltVal) );
1232                         break;
1233                 case( VT_I2 ):
1234                         res = VarR4FromI2( ps->u.iVal, &(pd->u.fltVal) );
1235                         break;
1236                 case( VT_INT ):
1237                 case( VT_I4 ):
1238                         res = VarR4FromI4( ps->u.lVal, &(pd->u.fltVal) );
1239                         break;
1240                 case( VT_UI1 ):
1241                         res = VarR4FromUI1( ps->u.bVal, &(pd->u.fltVal) );
1242                         break;
1243                 case( VT_UI2 ):
1244                         res = VarR4FromUI2( ps->u.uiVal, &(pd->u.fltVal) );
1245                         break;
1246                 case( VT_UINT ):
1247                 case( VT_UI4 ):
1248                         res = VarR4FromUI4( ps->u.ulVal, &(pd->u.fltVal) );
1249                         break;
1250         case( VT_R4 ):
1251             res = VariantCopy( pd, ps );
1252             break;
1253                 case( VT_R8 ):
1254                         res = VarR4FromR8( ps->u.dblVal, &(pd->u.fltVal) );
1255                         break;
1256                 case( VT_DATE ):
1257                         res = VarR4FromDate( ps->u.date, &(pd->u.fltVal) );
1258                         break;
1259                 case( VT_BOOL ):
1260                         res = VarR4FromBool( ps->u.boolVal, &(pd->u.fltVal) );
1261                         break;
1262                 case( VT_BSTR ):
1263                         res = VarR4FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
1264                         break;
1265                 case( VT_CY ):
1266                         res = VarR4FromCy( ps->u.cyVal, &(pd->u.fltVal) );
1267                         break;
1268                 case( VT_DISPATCH ):
1269                         /*res = VarR4FromDisp( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
1270                 case( VT_DECIMAL ):
1271                         /*res = VarR4FromDec( ps->u.deiVal, &(pd->u.fltVal) );*/
1272                 case( VT_UNKNOWN ):
1273                 default:
1274                         res = DISP_E_TYPEMISMATCH;
1275                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1276                         break;
1277                 }
1278                 break;
1279
1280         case( VT_R8 ):
1281                 switch( vtFrom )
1282                 {
1283                 case( VT_I1 ):
1284                         res = VarR8FromI1( ps->u.cVal, &(pd->u.dblVal) );
1285                         break;
1286                 case( VT_I2 ):
1287                         res = VarR8FromI2( ps->u.iVal, &(pd->u.dblVal) );
1288                         break;
1289                 case( VT_INT ):
1290                 case( VT_I4 ):
1291                         res = VarR8FromI4( ps->u.lVal, &(pd->u.dblVal) );
1292                         break;
1293                 case( VT_UI1 ):
1294                         res = VarR8FromUI1( ps->u.bVal, &(pd->u.dblVal) );
1295                         break;
1296                 case( VT_UI2 ):
1297                         res = VarR8FromUI2( ps->u.uiVal, &(pd->u.dblVal) );
1298                         break;
1299                 case( VT_UINT ):
1300                 case( VT_UI4 ):
1301                         res = VarR8FromUI4( ps->u.ulVal, &(pd->u.dblVal) );
1302                         break;
1303                 case( VT_R4 ):
1304                         res = VarR8FromR4( ps->u.fltVal, &(pd->u.dblVal) );
1305                         break;
1306         case( VT_R8 ):
1307             res = VariantCopy( pd, ps );
1308             break;
1309                 case( VT_DATE ):
1310                         res = VarR8FromDate( ps->u.date, &(pd->u.dblVal) );
1311                         break;
1312                 case( VT_BOOL ):
1313                         res = VarR8FromBool( ps->u.boolVal, &(pd->u.dblVal) );
1314                         break;
1315                 case( VT_BSTR ):
1316                         res = VarR8FromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
1317                         break;
1318                 case( VT_CY ):
1319                         res = VarR8FromCy( ps->u.cyVal, &(pd->u.dblVal) );
1320                         break;
1321                 case( VT_DISPATCH ):
1322                         /*res = VarR8FromDisp( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
1323                 case( VT_DECIMAL ):
1324                         /*res = VarR8FromDec( ps->u.deiVal, &(pd->u.dblVal) );*/
1325                 case( VT_UNKNOWN ):
1326                 default:
1327                         res = DISP_E_TYPEMISMATCH;
1328                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1329                         break;
1330                 }
1331                 break;
1332
1333         case( VT_DATE ):
1334                 switch( vtFrom )
1335                 {
1336                 case( VT_I1 ):
1337                         res = VarDateFromI1( ps->u.cVal, &(pd->u.date) );
1338                         break;
1339                 case( VT_I2 ):
1340                         res = VarDateFromI2( ps->u.iVal, &(pd->u.date) );
1341                         break;
1342                 case( VT_INT ):
1343                         res = VarDateFromInt( ps->u.intVal, &(pd->u.date) );
1344                         break;
1345                 case( VT_I4 ):
1346                         res = VarDateFromI4( ps->u.lVal, &(pd->u.date) );
1347                         break;
1348                 case( VT_UI1 ):
1349                         res = VarDateFromUI1( ps->u.bVal, &(pd->u.date) );
1350                         break;
1351                 case( VT_UI2 ):
1352                         res = VarDateFromUI2( ps->u.uiVal, &(pd->u.date) );
1353                         break;
1354                 case( VT_UINT ):
1355                         res = VarDateFromUint( ps->u.uintVal, &(pd->u.date) );
1356                         break;
1357                 case( VT_UI4 ):
1358                         res = VarDateFromUI4( ps->u.ulVal, &(pd->u.date) );
1359                         break;
1360                 case( VT_R4 ):
1361                         res = VarDateFromR4( ps->u.fltVal, &(pd->u.date) );
1362                         break;
1363                 case( VT_R8 ):
1364                         res = VarDateFromR8( ps->u.dblVal, &(pd->u.date) );
1365                         break;
1366         case( VT_DATE ):
1367             res = VariantCopy( pd, ps );
1368             break;
1369                 case( VT_BOOL ):
1370                         res = VarDateFromBool( ps->u.boolVal, &(pd->u.date) );
1371                         break;
1372                 case( VT_BSTR ):
1373                         res = VarDateFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
1374                         break;
1375                 case( VT_CY ):
1376                         res = VarDateFromCy( ps->u.cyVal, &(pd->u.date) );
1377                         break;
1378                 case( VT_DISPATCH ):
1379                         /*res = VarDateFromDisp( ps->u.pdispVal, lcid, &(pd->u.date) );*/
1380                 case( VT_DECIMAL ):
1381                         /*res = VarDateFromDec( ps->u.deiVal, &(pd->u.date) );*/
1382                 case( VT_UNKNOWN ):
1383                 default:
1384                         res = DISP_E_TYPEMISMATCH;
1385                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1386                         break;
1387                 }
1388                 break;
1389
1390         case( VT_BOOL ):
1391                 switch( vtFrom )
1392                 {
1393                 case( VT_I1 ):
1394                         res = VarBoolFromI1( ps->u.cVal, &(pd->u.boolVal) );
1395                         break;
1396                 case( VT_I2 ):
1397                         res = VarBoolFromI2( ps->u.iVal, &(pd->u.boolVal) );
1398                         break;
1399                 case( VT_INT ):
1400                         res = VarBoolFromInt( ps->u.intVal, &(pd->u.boolVal) );
1401                         break;
1402                 case( VT_I4 ):
1403                         res = VarBoolFromI4( ps->u.lVal, &(pd->u.boolVal) );
1404                         break;
1405                 case( VT_UI1 ):
1406                         res = VarBoolFromUI1( ps->u.bVal, &(pd->u.boolVal) );
1407                         break;
1408                 case( VT_UI2 ):
1409                         res = VarBoolFromUI2( ps->u.uiVal, &(pd->u.boolVal) );
1410                         break;
1411                 case( VT_UINT ):
1412                         res = VarBoolFromUint( ps->u.uintVal, &(pd->u.boolVal) );
1413                         break;
1414                 case( VT_UI4 ):
1415                         res = VarBoolFromUI4( ps->u.ulVal, &(pd->u.boolVal) );
1416                         break;
1417                 case( VT_R4 ):
1418                         res = VarBoolFromR4( ps->u.fltVal, &(pd->u.boolVal) );
1419                         break;
1420                 case( VT_R8 ):
1421                         res = VarBoolFromR8( ps->u.dblVal, &(pd->u.boolVal) );
1422                         break;
1423                 case( VT_DATE ):
1424                         res = VarBoolFromDate( ps->u.date, &(pd->u.boolVal) );
1425                         break;
1426         case( VT_BOOL ):
1427             res = VariantCopy( pd, ps );
1428             break;
1429                 case( VT_BSTR ):
1430                         res = VarBoolFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
1431                         break;
1432                 case( VT_CY ):
1433                         res = VarBoolFromCy( ps->u.cyVal, &(pd->u.boolVal) );
1434                         break;
1435                 case( VT_DISPATCH ):
1436                         /*res = VarBoolFromDisp( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1437                 case( VT_DECIMAL ):
1438                         /*res = VarBoolFromDec( ps->u.deiVal, &(pd->u.boolVal) );*/
1439                 case( VT_UNKNOWN ):
1440                 default:
1441                         res = DISP_E_TYPEMISMATCH;
1442                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1443                         break;
1444                 }
1445                 break;
1446
1447         case( VT_BSTR ):
1448                 switch( vtFrom )
1449                 {
1450                 case( VT_EMPTY ):
1451                         if ((pd->u.bstrVal = SysAllocStringLen(NULL, 0)))
1452                                 res = S_OK;
1453                         else
1454                                 res = E_OUTOFMEMORY;
1455                         break;
1456                 case( VT_I1 ):
1457                         res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1458                         break;
1459                 case( VT_I2 ):
1460                         res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1461                         break;
1462                 case( VT_INT ):
1463                         res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1464                         break;
1465                 case( VT_I4 ):
1466                         res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1467                         break;
1468                 case( VT_UI1 ):
1469                         res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1470                         break;
1471                 case( VT_UI2 ):
1472                         res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1473                         break;
1474                 case( VT_UINT ):
1475                         res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1476                         break;
1477                 case( VT_UI4 ):
1478                         res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1479                         break;
1480                 case( VT_R4 ):
1481                         res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1482                         break;
1483                 case( VT_R8 ):
1484                         res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1485                         break;
1486                 case( VT_DATE ):
1487                         res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1488                         break;
1489                 case( VT_BOOL ):
1490                         res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1491                         break;
1492                 case( VT_BSTR ):
1493                         res = VariantCopy( pd, ps );
1494                         break;
1495                 case( VT_CY ):
1496                         res = VarBstrFromCy( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );
1497                         break;
1498                 case( VT_DISPATCH ):
1499                         /*res = VarBstrFromDisp( ps->u.pdispVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1500                 case( VT_DECIMAL ):
1501                         /*res = VarBstrFromDec( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1502                 case( VT_UNKNOWN ):
1503                 default:
1504                         res = DISP_E_TYPEMISMATCH;
1505                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1506                         break;
1507                 }
1508                 break;
1509
1510      case( VT_CY ):
1511         switch( vtFrom )
1512           {
1513           case( VT_I1 ):
1514              res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1515              break;
1516           case( VT_I2 ):
1517              res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1518              break;
1519           case( VT_INT ):
1520              res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1521              break;
1522           case( VT_I4 ):
1523              res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1524              break;
1525           case( VT_UI1 ):
1526              res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1527              break;
1528           case( VT_UI2 ):
1529              res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1530              break;
1531           case( VT_UINT ):
1532              res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1533              break;
1534           case( VT_UI4 ):
1535              res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1536              break;
1537           case( VT_R4 ):
1538              res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1539              break;
1540           case( VT_R8 ):
1541              res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1542              break;
1543           case( VT_DATE ):
1544              res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1545              break;
1546           case( VT_BOOL ):
1547              res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1548              break;
1549           case( VT_CY ):
1550              res = VariantCopy( pd, ps );
1551              break;
1552           case( VT_BSTR ):
1553              res = VarCyFromStr( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );
1554              break;
1555           case( VT_DISPATCH ):
1556              /*res = VarCyFromDisp( ps->u.pdispVal, lcid, &(pd->u.cyVal) );*/
1557           case( VT_DECIMAL ):
1558              /*res = VarCyFromDec( ps->u.deiVal, &(pd->u.cyVal) );*/
1559              break;
1560           case( VT_UNKNOWN ):
1561           default:
1562              res = DISP_E_TYPEMISMATCH;
1563              FIXME("Coercion from %d to %d\n", vtFrom, vt );
1564              break;
1565           }
1566         break;
1567
1568         default:
1569                 res = DISP_E_TYPEMISMATCH;
1570                 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1571                 break;
1572         }
1573         
1574         return res;
1575 }
1576
1577 /******************************************************************************
1578  *              ValidateVtRange [INTERNAL]
1579  *
1580  * Used internally by the hi-level Variant API to determine
1581  * if the vartypes are valid.
1582  */
1583 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1584 {
1585     /* if by value we must make sure it is in the
1586      * range of the valid types.
1587      */
1588     if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1589     {
1590         return DISP_E_BADVARTYPE;
1591     }
1592     return S_OK;
1593 }
1594
1595
1596 /******************************************************************************
1597  *              ValidateVartype [INTERNAL]
1598  *
1599  * Used internally by the hi-level Variant API to determine
1600  * if the vartypes are valid.
1601  */
1602 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1603 {
1604         HRESULT res = S_OK;
1605
1606         /* check if we have a valid argument.
1607          */
1608         if( vt & VT_BYREF )
1609     {
1610         /* if by reference check that the type is in
1611          * the valid range and that it is not of empty or null type
1612          */
1613         if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1614             ( vt & VT_TYPEMASK ) == VT_NULL ||
1615                         ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1616                 {
1617                         res = E_INVALIDARG;
1618                 }
1619                         
1620     }
1621     else
1622     {
1623         res = ValidateVtRange( vt );
1624     }
1625                 
1626         return res;
1627 }
1628
1629 /******************************************************************************
1630  *              ValidateVt      [INTERNAL]
1631  *
1632  * Used internally by the hi-level Variant API to determine
1633  * if the vartypes are valid.
1634  */
1635 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1636 {
1637         HRESULT res = S_OK;
1638
1639         /* check if we have a valid argument.
1640          */
1641         if( vt & VT_BYREF )
1642     {
1643         /* if by reference check that the type is in
1644          * the valid range and that it is not of empty or null type
1645          */
1646         if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1647             ( vt & VT_TYPEMASK ) == VT_NULL ||
1648                         ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1649                 {
1650                         res = DISP_E_BADVARTYPE;
1651                 }
1652                         
1653     }
1654     else
1655     {
1656         res = ValidateVtRange( vt );
1657     }
1658                 
1659         return res;
1660 }
1661
1662
1663
1664
1665
1666 /******************************************************************************
1667  *              VariantInit     [OLEAUT32.8]
1668  *
1669  * Initializes the Variant.  Unlike VariantClear it does not interpret the current
1670  * contents of the Variant.
1671  */
1672 void WINAPI VariantInit(VARIANTARG* pvarg)
1673 {
1674   TRACE("(%p),stub\n",pvarg);
1675
1676   memset(pvarg, 0, sizeof (VARIANTARG));
1677   pvarg->vt = VT_EMPTY;
1678
1679   return;
1680 }
1681
1682 /******************************************************************************
1683  *              VariantClear    [OLEAUT32.9]
1684  *
1685  * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1686  * sets the wReservedX field to 0.      The current contents of the VARIANT are
1687  * freed.  If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1688  * released. If VT_ARRAY the array is freed.
1689  */
1690 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1691 {
1692   HRESULT res = S_OK;
1693   TRACE("(%p)\n",pvarg);
1694
1695   res = ValidateVariantType( pvarg->vt );
1696   if( res == S_OK )
1697   {
1698     if( !( pvarg->vt & VT_BYREF ) )
1699     {
1700       /*
1701        * The VT_ARRAY flag is a special case of a safe array.
1702        */
1703       if ( (pvarg->vt & VT_ARRAY) != 0)
1704       {
1705         SafeArrayDestroy(pvarg->u.parray);
1706       }
1707       else
1708       {
1709         switch( pvarg->vt & VT_TYPEMASK )
1710         {
1711           case( VT_BSTR ):
1712             SysFreeString( pvarg->u.bstrVal );
1713             break;
1714           case( VT_DISPATCH ):
1715             if(pvarg->u.pdispVal!=NULL)
1716               ICOM_CALL(Release,pvarg->u.pdispVal);
1717             break;
1718           case( VT_VARIANT ):
1719             VariantClear(pvarg->u.pvarVal);
1720             break;
1721           case( VT_UNKNOWN ):
1722             if(pvarg->u.punkVal!=NULL)
1723               ICOM_CALL(Release,pvarg->u.punkVal);
1724             break;
1725           case( VT_SAFEARRAY ):
1726             SafeArrayDestroy(pvarg->u.parray);
1727             break;
1728           default:
1729             break;
1730         }
1731       }
1732     }
1733         
1734     /*
1735      * Empty all the fields and mark the type as empty.
1736      */
1737     memset(pvarg, 0, sizeof (VARIANTARG));
1738     pvarg->vt = VT_EMPTY;
1739   }
1740
1741   return res;
1742 }
1743
1744 /******************************************************************************
1745  *              VariantCopy     [OLEAUT32.10]
1746  *
1747  * Frees up the designation variant and makes a copy of the source.
1748  */
1749 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1750 {
1751   HRESULT res = S_OK;
1752
1753   TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1754
1755   res = ValidateVariantType( pvargSrc->vt );
1756
1757   /* If the pointer are to the same variant we don't need
1758    * to do anything.
1759    */
1760   if( pvargDest != pvargSrc && res == S_OK )
1761   {
1762     res = VariantClear( pvargDest );
1763                 
1764     if( res == S_OK )
1765     {
1766       if( pvargSrc->vt & VT_BYREF )
1767       {
1768         /* In the case of byreference we only need
1769          * to copy the pointer.
1770          */
1771         pvargDest->u = pvargSrc->u;
1772         pvargDest->vt = pvargSrc->vt;
1773       }
1774       else
1775       {
1776         /*
1777          * The VT_ARRAY flag is another way to designate a safe array.
1778          */
1779         if (pvargSrc->vt & VT_ARRAY)
1780         {
1781           SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1782         }
1783         else
1784         {
1785           /* In the case of by value we need to
1786            * copy the actuall value. In the case of
1787            * VT_BSTR a copy of the string is made,
1788            * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1789            * called to increment the object's reference count.
1790            */
1791           switch( pvargSrc->vt & VT_TYPEMASK )
1792           {
1793             case( VT_BSTR ):
1794               pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1795               break;
1796             case( VT_DISPATCH ):
1797               pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1798               if (pvargDest->u.pdispVal!=NULL)
1799                 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1800               break;
1801             case( VT_VARIANT ):
1802               VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1803               break;
1804             case( VT_UNKNOWN ):
1805               pvargDest->u.punkVal = pvargSrc->u.punkVal;
1806               if (pvargDest->u.pdispVal!=NULL)
1807                 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1808               break;
1809             case( VT_SAFEARRAY ):
1810               SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1811               break;
1812             default:
1813               pvargDest->u = pvargSrc->u;
1814               break;
1815           }
1816         }
1817         
1818         pvargDest->vt = pvargSrc->vt;
1819       }      
1820     }
1821   }
1822
1823   return res;
1824 }
1825
1826
1827 /******************************************************************************
1828  *              VariantCopyInd  [OLEAUT32.11]
1829  *
1830  * Frees up the destination variant and makes a copy of the source.  If
1831  * the source is of type VT_BYREF it performs the necessary indirections.
1832  */
1833 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1834 {
1835   HRESULT res = S_OK;
1836
1837   TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1838
1839   res = ValidateVariantType( pvargSrc->vt );
1840
1841   if( res != S_OK )
1842     return res;
1843   
1844   if( pvargSrc->vt & VT_BYREF )
1845   {
1846     VARIANTARG varg;
1847     VariantInit( &varg );
1848
1849     /* handle the in place copy.
1850      */
1851     if( pvargDest == pvargSrc )
1852     {
1853       /* we will use a copy of the source instead.
1854        */
1855       res = VariantCopy( &varg, pvargSrc );
1856       pvargSrc = &varg;
1857     }
1858
1859     if( res == S_OK )
1860     {
1861       res = VariantClear( pvargDest );
1862
1863       if( res == S_OK )
1864       {
1865         /*
1866          * The VT_ARRAY flag is another way to designate a safearray variant.
1867          */
1868         if ( pvargSrc->vt & VT_ARRAY)
1869         {
1870           SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1871         }
1872         else
1873         {
1874           /* In the case of by reference we need
1875            * to copy the date pointed to by the variant.
1876            */
1877
1878           /* Get the variant type.
1879            */
1880           switch( pvargSrc->vt & VT_TYPEMASK )
1881           {
1882             case( VT_BSTR ):
1883               pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1884               break;
1885             case( VT_DISPATCH ):
1886               break;
1887             case( VT_VARIANT ):
1888               {
1889                 /* Prevent from cycling.  According to tests on
1890                  * VariantCopyInd in Windows and the documentation
1891                  * this API dereferences the inner Variants to only one depth.
1892                  * If the inner Variant itself contains an
1893                  * other inner variant the E_INVALIDARG error is
1894                  * returned. 
1895                  */
1896                 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1897                 {
1898                   /* If we get here we are attempting to deference
1899                    * an inner variant that that is itself contained
1900                    * in an inner variant so report E_INVALIDARG error.
1901                    */
1902                   res = E_INVALIDARG;
1903                 }
1904                 else
1905                 {
1906                   /* Set the processing inner variant flag.
1907                    * We will set this flag in the inner variant
1908                    * that will be passed to the VariantCopyInd function.
1909                    */
1910                   (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1911                   
1912                   /* Dereference the inner variant.
1913                    */
1914                   res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1915                   /* We must also copy its type, I think.
1916                    */
1917                   pvargSrc->vt = pvargSrc->u.pvarVal->vt; 
1918                 }
1919               }
1920               break;
1921             case( VT_UNKNOWN ):
1922               break;
1923             case( VT_SAFEARRAY ):
1924               SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1925               break;
1926             default:
1927               /* This is a by reference Variant which means that the union
1928                * part of the Variant contains a pointer to some data of
1929                * type "pvargSrc->vt & VT_TYPEMASK".
1930                * We will deference this data in a generic fashion using
1931                * the void pointer "Variant.u.byref".
1932                * We will copy this data into the union of the destination
1933                * Variant.
1934                */
1935               memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1936               break;
1937           }
1938         }
1939         
1940         pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1941       }
1942     }
1943
1944     /* this should not fail.
1945      */
1946     VariantClear( &varg );
1947   }
1948   else
1949   {
1950     res = VariantCopy( pvargDest, pvargSrc );
1951   }
1952
1953   return res;
1954 }
1955
1956 /******************************************************************************
1957  *              VariantChangeType       [OLEAUT32.12]
1958  */
1959 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1960                                                         USHORT wFlags, VARTYPE vt)
1961 {
1962         return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1963 }
1964
1965 /******************************************************************************
1966  *              VariantChangeTypeEx     [OLEAUT32.147]
1967  */
1968 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1969                                                           LCID lcid, USHORT wFlags, VARTYPE vt)
1970 {
1971         HRESULT res = S_OK;
1972         VARIANTARG varg;
1973         VariantInit( &varg );
1974         
1975         TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1976
1977         /* validate our source argument.
1978          */
1979         res = ValidateVariantType( pvargSrc->vt );
1980
1981         /* validate the vartype.
1982          */
1983         if( res == S_OK )
1984         {
1985                 res = ValidateVt( vt );
1986         }
1987
1988         /* if we are doing an in-place conversion make a copy of the source.
1989          */
1990         if( res == S_OK && pvargDest == pvargSrc )
1991         {
1992                 res = VariantCopy( &varg, pvargSrc );
1993                 pvargSrc = &varg;
1994         }
1995
1996         if( res == S_OK )
1997         {
1998                 /* free up the destination variant.
1999                  */
2000                 res = VariantClear( pvargDest );
2001         }
2002
2003         if( res == S_OK )
2004         {
2005                 if( pvargSrc->vt & VT_BYREF )
2006                 {
2007                         /* Convert the source variant to a "byvalue" variant.
2008                          */
2009                         VARIANTARG Variant;
2010                         VariantInit( &Variant );
2011                         res = VariantCopyInd( &Variant, pvargSrc );
2012                         if( res == S_OK )
2013                         {
2014                                 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2015                                 /* this should not fail.
2016                                  */
2017                                 VariantClear( &Variant );
2018                         }
2019         
2020                 }
2021                 else
2022                 {
2023                         /* Use the current "byvalue" source variant.
2024                          */
2025                         res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2026                 }
2027         }
2028         /* this should not fail.
2029          */
2030         VariantClear( &varg );
2031         
2032         /* set the type of the destination
2033          */
2034         if ( res == S_OK )
2035                 pvargDest->vt = vt;
2036
2037         return res;
2038 }
2039
2040
2041
2042
2043 /******************************************************************************
2044  *              VarUI1FromI2            [OLEAUT32.130]
2045  */
2046 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2047 {
2048         TRACE("( %d, %p ), stub\n", sIn, pbOut );
2049
2050         /* Check range of value.
2051          */
2052         if( sIn < UI1_MIN || sIn > UI1_MAX )
2053         {
2054                 return DISP_E_OVERFLOW;
2055         }
2056
2057         *pbOut = (BYTE) sIn;
2058         
2059         return S_OK;
2060 }
2061
2062 /******************************************************************************
2063  *              VarUI1FromI4            [OLEAUT32.131]
2064  */
2065 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2066 {
2067         TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2068
2069         /* Check range of value.
2070          */
2071         if( lIn < UI1_MIN || lIn > UI1_MAX )
2072         {
2073                 return DISP_E_OVERFLOW;
2074         }
2075
2076         *pbOut = (BYTE) lIn;
2077         
2078         return S_OK;
2079 }
2080
2081
2082 /******************************************************************************
2083  *              VarUI1FromR4            [OLEAUT32.132]
2084  */
2085 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2086 {
2087         TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2088
2089         /* Check range of value.
2090      */
2091     fltIn = round( fltIn );
2092         if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2093         {
2094                 return DISP_E_OVERFLOW;
2095         }
2096
2097         *pbOut = (BYTE) fltIn;
2098         
2099         return S_OK;
2100 }
2101
2102 /******************************************************************************
2103  *              VarUI1FromR8            [OLEAUT32.133]
2104  */
2105 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2106 {
2107         TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2108
2109         /* Check range of value.
2110      */
2111     dblIn = round( dblIn );
2112         if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2113         {
2114                 return DISP_E_OVERFLOW;
2115         }
2116
2117         *pbOut = (BYTE) dblIn;
2118
2119         return S_OK;
2120 }
2121
2122 /******************************************************************************
2123  *              VarUI1FromDate          [OLEAUT32.135]
2124  */
2125 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2126 {
2127         TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2128
2129         /* Check range of value.
2130      */
2131     dateIn = round( dateIn );
2132         if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2133         {
2134                 return DISP_E_OVERFLOW;
2135         }
2136
2137         *pbOut = (BYTE) dateIn;
2138
2139         return S_OK;
2140 }
2141
2142 /******************************************************************************
2143  *              VarUI1FromBool          [OLEAUT32.138]
2144  */
2145 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2146 {
2147         TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2148
2149         *pbOut = (BYTE) boolIn;
2150
2151         return S_OK;
2152 }
2153
2154 /******************************************************************************
2155  *              VarUI1FromI1            [OLEAUT32.237]
2156  */
2157 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2158 {
2159         TRACE("( %c, %p ), stub\n", cIn, pbOut );
2160
2161         *pbOut = cIn;
2162
2163         return S_OK;
2164 }
2165
2166 /******************************************************************************
2167  *              VarUI1FromUI2           [OLEAUT32.238]
2168  */
2169 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2170 {
2171         TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2172
2173         /* Check range of value.
2174          */
2175         if( uiIn > UI1_MAX )
2176         {
2177                 return DISP_E_OVERFLOW;
2178         }
2179
2180         *pbOut = (BYTE) uiIn;
2181
2182         return S_OK;
2183 }
2184
2185 /******************************************************************************
2186  *              VarUI1FromUI4           [OLEAUT32.239]
2187  */
2188 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2189 {
2190         TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2191
2192         /* Check range of value.
2193          */
2194         if( ulIn > UI1_MAX )
2195         {
2196                 return DISP_E_OVERFLOW;
2197         }
2198
2199         *pbOut = (BYTE) ulIn;
2200
2201         return S_OK;
2202 }
2203
2204
2205 /******************************************************************************
2206  *              VarUI1FromStr           [OLEAUT32.136]
2207  */
2208 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2209 {
2210         double dValue = 0.0;
2211         LPSTR pNewString = NULL;
2212
2213         TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2214
2215         /* Check if we have a valid argument
2216          */
2217         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2218         RemoveCharacterFromString( pNewString, "," );
2219         if( IsValidRealString( pNewString ) == FALSE )
2220         {
2221                 return DISP_E_TYPEMISMATCH;
2222         }
2223
2224         /* Convert the valid string to a floating point number.
2225          */
2226         dValue = atof( pNewString );
2227         
2228         /* We don't need the string anymore so free it.
2229          */
2230         HeapFree( GetProcessHeap(), 0 , pNewString );
2231
2232         /* Check range of value.
2233      */
2234     dValue = round( dValue );
2235         if( dValue < UI1_MIN || dValue > UI1_MAX )
2236         {
2237                 return DISP_E_OVERFLOW;
2238         }
2239
2240         *pbOut = (BYTE) dValue;
2241
2242         return S_OK;
2243 }
2244
2245 /**********************************************************************
2246  *              VarUI1FromCy [OLEAUT32.134]
2247  * Convert currency to unsigned char
2248  */
2249 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2250    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2251    
2252    if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2253    
2254    *pbOut = (BYTE)t;
2255    return S_OK;
2256 }
2257
2258 /******************************************************************************
2259  *              VarI2FromUI1            [OLEAUT32.48]
2260  */
2261 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2262 {
2263         TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2264
2265         *psOut = (short) bIn;
2266         
2267         return S_OK;
2268 }
2269
2270 /******************************************************************************
2271  *              VarI2FromI4             [OLEAUT32.49]
2272  */
2273 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2274 {
2275         TRACE("( %lx, %p ), stub\n", lIn, psOut );
2276
2277         /* Check range of value.
2278          */
2279         if( lIn < I2_MIN || lIn > I2_MAX )
2280         {
2281                 return DISP_E_OVERFLOW;
2282         }
2283
2284         *psOut = (short) lIn;
2285         
2286         return S_OK;
2287 }
2288
2289 /******************************************************************************
2290  *              VarI2FromR4             [OLEAUT32.50]
2291  */
2292 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2293 {
2294         TRACE("( %f, %p ), stub\n", fltIn, psOut );
2295
2296         /* Check range of value.
2297      */
2298     fltIn = round( fltIn );
2299         if( fltIn < I2_MIN || fltIn > I2_MAX )
2300         {
2301                 return DISP_E_OVERFLOW;
2302         }
2303
2304         *psOut = (short) fltIn;
2305
2306         return S_OK;
2307 }
2308
2309 /******************************************************************************
2310  *              VarI2FromR8             [OLEAUT32.51]
2311  */
2312 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2313 {
2314         TRACE("( %f, %p ), stub\n", dblIn, psOut );
2315
2316         /* Check range of value.
2317      */
2318     dblIn = round( dblIn );
2319         if( dblIn < I2_MIN || dblIn > I2_MAX )
2320         {
2321                 return DISP_E_OVERFLOW;
2322         }
2323
2324         *psOut = (short) dblIn;
2325
2326         return S_OK;
2327 }
2328
2329 /******************************************************************************
2330  *              VarI2FromDate           [OLEAUT32.53]
2331  */
2332 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2333 {
2334         TRACE("( %f, %p ), stub\n", dateIn, psOut );
2335
2336         /* Check range of value.
2337      */
2338     dateIn = round( dateIn );
2339         if( dateIn < I2_MIN || dateIn > I2_MAX )
2340         {
2341                 return DISP_E_OVERFLOW;
2342         }
2343
2344         *psOut = (short) dateIn;
2345
2346         return S_OK;
2347 }
2348
2349 /******************************************************************************
2350  *              VarI2FromBool           [OLEAUT32.56]
2351  */
2352 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2353 {
2354         TRACE("( %d, %p ), stub\n", boolIn, psOut );
2355
2356         *psOut = (short) boolIn;
2357
2358         return S_OK;
2359 }
2360
2361 /******************************************************************************
2362  *              VarI2FromI1             [OLEAUT32.205]
2363  */
2364 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2365 {
2366         TRACE("( %c, %p ), stub\n", cIn, psOut );
2367
2368         *psOut = (short) cIn;
2369
2370         return S_OK;
2371 }
2372
2373 /******************************************************************************
2374  *              VarI2FromUI2            [OLEAUT32.206]
2375  */
2376 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2377 {
2378         TRACE("( %d, %p ), stub\n", uiIn, psOut );
2379
2380         /* Check range of value.
2381          */
2382         if( uiIn > I2_MAX )
2383         {
2384                 return DISP_E_OVERFLOW;
2385         }
2386
2387         *psOut = (short) uiIn;
2388
2389         return S_OK;
2390 }
2391
2392 /******************************************************************************
2393  *              VarI2FromUI4            [OLEAUT32.207]
2394  */
2395 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2396 {
2397         TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2398
2399         /* Check range of value.
2400          */
2401         if( ulIn < I2_MIN || ulIn > I2_MAX )
2402         {
2403                 return DISP_E_OVERFLOW;
2404         }
2405
2406         *psOut = (short) ulIn;
2407
2408         return S_OK;
2409 }
2410
2411 /******************************************************************************
2412  *              VarI2FromStr            [OLEAUT32.54]
2413  */
2414 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2415 {
2416         double dValue = 0.0;
2417         LPSTR pNewString = NULL;
2418
2419         TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2420
2421         /* Check if we have a valid argument
2422          */
2423         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2424         RemoveCharacterFromString( pNewString, "," );
2425         if( IsValidRealString( pNewString ) == FALSE )
2426         {
2427                 return DISP_E_TYPEMISMATCH;
2428         }
2429
2430         /* Convert the valid string to a floating point number.
2431          */
2432         dValue = atof( pNewString );
2433         
2434         /* We don't need the string anymore so free it.
2435          */
2436         HeapFree( GetProcessHeap(), 0, pNewString );
2437
2438         /* Check range of value.
2439      */
2440     dValue = round( dValue );
2441         if( dValue < I2_MIN || dValue > I2_MAX )
2442         {
2443                 return DISP_E_OVERFLOW;
2444         }
2445
2446         *psOut = (short)  dValue;
2447
2448         return S_OK;
2449 }
2450
2451 /**********************************************************************
2452  *              VarI2FromCy [OLEAUT32.52]
2453  * Convert currency to signed short
2454  */
2455 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2456    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2457    
2458    if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2459    
2460    *psOut = (SHORT)t;
2461    return S_OK;
2462 }
2463
2464 /******************************************************************************
2465  *              VarI4FromUI1            [OLEAUT32.58]
2466  */
2467 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2468 {
2469         TRACE("( %X, %p ), stub\n", bIn, plOut );
2470
2471         *plOut = (LONG) bIn;
2472
2473         return S_OK;
2474 }
2475
2476
2477 /******************************************************************************
2478  *              VarI4FromR4             [OLEAUT32.60]
2479  */
2480 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2481 {
2482         TRACE("( %f, %p ), stub\n", fltIn, plOut );
2483
2484         /* Check range of value.
2485      */
2486     fltIn = round( fltIn );
2487         if( fltIn < I4_MIN || fltIn > I4_MAX )
2488         {
2489                 return DISP_E_OVERFLOW;
2490         }
2491
2492         *plOut = (LONG) fltIn;
2493
2494         return S_OK;
2495 }
2496
2497 /******************************************************************************
2498  *              VarI4FromR8             [OLEAUT32.61]
2499  */
2500 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2501 {
2502         TRACE("( %f, %p ), stub\n", dblIn, plOut );
2503
2504         /* Check range of value.
2505      */
2506     dblIn = round( dblIn );
2507         if( dblIn < I4_MIN || dblIn > I4_MAX )
2508         {
2509                 return DISP_E_OVERFLOW;
2510         }
2511
2512         *plOut = (LONG) dblIn;
2513
2514         return S_OK;
2515 }
2516
2517 /******************************************************************************
2518  *              VarI4FromDate           [OLEAUT32.63]
2519  */
2520 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2521 {
2522         TRACE("( %f, %p ), stub\n", dateIn, plOut );
2523
2524         /* Check range of value.
2525      */
2526     dateIn = round( dateIn );
2527         if( dateIn < I4_MIN || dateIn > I4_MAX )
2528         {
2529                 return DISP_E_OVERFLOW;
2530         }
2531
2532         *plOut = (LONG) dateIn;
2533
2534         return S_OK;
2535 }
2536
2537 /******************************************************************************
2538  *              VarI4FromBool           [OLEAUT32.66]
2539  */
2540 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2541 {
2542         TRACE("( %d, %p ), stub\n", boolIn, plOut );
2543
2544         *plOut = (LONG) boolIn;
2545
2546         return S_OK;
2547 }
2548
2549 /******************************************************************************
2550  *              VarI4FromI1             [OLEAUT32.209]
2551  */
2552 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2553 {
2554         TRACE("( %c, %p ), stub\n", cIn, plOut );
2555
2556         *plOut = (LONG) cIn;
2557
2558         return S_OK;
2559 }
2560
2561 /******************************************************************************
2562  *              VarI4FromUI2            [OLEAUT32.210]
2563  */
2564 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2565 {
2566         TRACE("( %d, %p ), stub\n", uiIn, plOut );
2567
2568         *plOut = (LONG) uiIn;
2569
2570         return S_OK;
2571 }
2572
2573 /******************************************************************************
2574  *              VarI4FromUI4            [OLEAUT32.211]
2575  */
2576 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2577 {
2578         TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2579
2580         /* Check range of value.
2581          */
2582         if( ulIn < I4_MIN || ulIn > I4_MAX )
2583         {
2584                 return DISP_E_OVERFLOW;
2585         }
2586
2587         *plOut = (LONG) ulIn;
2588
2589         return S_OK;
2590 }
2591
2592 /******************************************************************************
2593  *              VarI4FromI2             [OLEAUT32.59]
2594  */
2595 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2596 {
2597         TRACE("( %d, %p ), stub\n", sIn, plOut );
2598
2599         *plOut = (LONG) sIn;
2600
2601         return S_OK;
2602 }
2603
2604 /******************************************************************************
2605  *              VarI4FromStr            [OLEAUT32.64]
2606  */
2607 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2608 {
2609         double dValue = 0.0;
2610         LPSTR pNewString = NULL;
2611
2612         TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2613
2614         /* Check if we have a valid argument
2615          */
2616         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2617         RemoveCharacterFromString( pNewString, "," );
2618         if( IsValidRealString( pNewString ) == FALSE )
2619         {
2620                 return DISP_E_TYPEMISMATCH;
2621         }
2622
2623         /* Convert the valid string to a floating point number.
2624          */
2625         dValue = atof( pNewString );
2626         
2627         /* We don't need the string anymore so free it.
2628          */
2629         HeapFree( GetProcessHeap(), 0, pNewString );
2630
2631         /* Check range of value.
2632      */
2633     dValue = round( dValue );
2634         if( dValue < I4_MIN || dValue > I4_MAX )
2635         {
2636                 return DISP_E_OVERFLOW;
2637         }
2638
2639         *plOut = (LONG) dValue;
2640
2641         return S_OK;
2642 }
2643
2644 /**********************************************************************
2645  *              VarI4FromCy [OLEAUT32.62]
2646  * Convert currency to signed long
2647  */
2648 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2649    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2650    
2651    if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2652    
2653    *plOut = (LONG)t;
2654    return S_OK;
2655 }
2656
2657 /******************************************************************************
2658  *              VarR4FromUI1            [OLEAUT32.68]
2659  */
2660 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2661 {
2662         TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2663
2664         *pfltOut = (FLOAT) bIn;
2665
2666         return S_OK;
2667 }
2668
2669 /******************************************************************************
2670  *              VarR4FromI2             [OLEAUT32.69]
2671  */
2672 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2673 {
2674         TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2675
2676         *pfltOut = (FLOAT) sIn;
2677
2678         return S_OK;
2679 }
2680
2681 /******************************************************************************
2682  *              VarR4FromI4             [OLEAUT32.70]
2683  */
2684 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2685 {
2686         TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2687
2688         *pfltOut = (FLOAT) lIn;
2689
2690         return S_OK;
2691 }
2692
2693 /******************************************************************************
2694  *              VarR4FromR8             [OLEAUT32.71]
2695  */
2696 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2697 {
2698         TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2699
2700         /* Check range of value.
2701          */
2702         if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2703         {
2704                 return DISP_E_OVERFLOW;
2705         }
2706
2707         *pfltOut = (FLOAT) dblIn;
2708
2709         return S_OK;
2710 }
2711
2712 /******************************************************************************
2713  *              VarR4FromDate           [OLEAUT32.73]
2714  */
2715 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2716 {
2717         TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2718
2719         /* Check range of value.
2720          */
2721         if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2722         {
2723                 return DISP_E_OVERFLOW;
2724         }
2725
2726         *pfltOut = (FLOAT) dateIn;
2727
2728         return S_OK;
2729 }
2730
2731 /******************************************************************************
2732  *              VarR4FromBool           [OLEAUT32.76]
2733  */
2734 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2735 {
2736         TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2737
2738         *pfltOut = (FLOAT) boolIn;
2739
2740         return S_OK;
2741 }
2742
2743 /******************************************************************************
2744  *              VarR4FromI1             [OLEAUT32.213]
2745  */
2746 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2747 {
2748         TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2749
2750         *pfltOut = (FLOAT) cIn;
2751
2752         return S_OK;
2753 }
2754
2755 /******************************************************************************
2756  *              VarR4FromUI2            [OLEAUT32.214]
2757  */
2758 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2759 {
2760         TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2761
2762         *pfltOut = (FLOAT) uiIn;
2763
2764         return S_OK;
2765 }
2766
2767 /******************************************************************************
2768  *              VarR4FromUI4            [OLEAUT32.215]
2769  */
2770 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2771 {
2772         TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2773
2774         *pfltOut = (FLOAT) ulIn;
2775
2776         return S_OK;
2777 }
2778
2779 /******************************************************************************
2780  *              VarR4FromStr            [OLEAUT32.74]
2781  */
2782 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2783 {
2784         double dValue = 0.0;
2785         LPSTR pNewString = NULL;
2786
2787         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2788
2789         /* Check if we have a valid argument
2790          */
2791         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2792         RemoveCharacterFromString( pNewString, "," );
2793         if( IsValidRealString( pNewString ) == FALSE )
2794         {
2795                 return DISP_E_TYPEMISMATCH;
2796         }
2797
2798         /* Convert the valid string to a floating point number.
2799          */
2800         dValue = atof( pNewString );
2801         
2802         /* We don't need the string anymore so free it.
2803          */
2804         HeapFree( GetProcessHeap(), 0, pNewString );
2805
2806         /* Check range of value.
2807          */
2808         if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2809         {
2810                 return DISP_E_OVERFLOW;
2811         }
2812
2813         *pfltOut = (FLOAT) dValue;
2814
2815         return S_OK;
2816 }
2817
2818 /**********************************************************************
2819  *              VarR4FromCy [OLEAUT32.72]
2820  * Convert currency to float
2821  */
2822 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2823    *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2824    
2825    return S_OK;
2826 }
2827
2828 /******************************************************************************
2829  *              VarR8FromUI1            [OLEAUT32.78]
2830  */
2831 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2832 {
2833         TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2834
2835         *pdblOut = (double) bIn;
2836
2837         return S_OK;
2838 }
2839
2840 /******************************************************************************
2841  *              VarR8FromI2             [OLEAUT32.79]
2842  */
2843 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2844 {
2845         TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2846
2847         *pdblOut = (double) sIn;
2848
2849         return S_OK;
2850 }
2851
2852 /******************************************************************************
2853  *              VarR8FromI4             [OLEAUT32.80]
2854  */
2855 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2856 {
2857         TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2858
2859         *pdblOut = (double) lIn;
2860
2861         return S_OK;
2862 }
2863
2864 /******************************************************************************
2865  *              VarR8FromR4             [OLEAUT32.81]
2866  */
2867 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2868 {
2869         TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2870
2871         *pdblOut = (double) fltIn;
2872
2873         return S_OK;
2874 }
2875
2876 /******************************************************************************
2877  *              VarR8FromDate           [OLEAUT32.83]
2878  */
2879 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2880 {
2881         TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2882
2883         *pdblOut = (double) dateIn;
2884
2885         return S_OK;
2886 }
2887
2888 /******************************************************************************
2889  *              VarR8FromBool           [OLEAUT32.86]
2890  */
2891 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2892 {
2893         TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2894
2895         *pdblOut = (double) boolIn;
2896
2897         return S_OK;
2898 }
2899
2900 /******************************************************************************
2901  *              VarR8FromI1             [OLEAUT32.217]
2902  */
2903 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2904 {
2905         TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2906
2907         *pdblOut = (double) cIn;
2908
2909         return S_OK;
2910 }
2911
2912 /******************************************************************************
2913  *              VarR8FromUI2            [OLEAUT32.218]
2914  */
2915 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2916 {
2917         TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2918
2919         *pdblOut = (double) uiIn;
2920
2921         return S_OK;
2922 }
2923
2924 /******************************************************************************
2925  *              VarR8FromUI4            [OLEAUT32.219]
2926  */
2927 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2928 {
2929         TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2930
2931         *pdblOut = (double) ulIn;
2932
2933         return S_OK;
2934 }
2935
2936 /******************************************************************************
2937  *              VarR8FromStr            [OLEAUT32.84]
2938  */
2939 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2940 {
2941         double dValue = 0.0;
2942         LPSTR pNewString = NULL;
2943
2944         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2945
2946         /* Check if we have a valid argument
2947          */
2948         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2949         RemoveCharacterFromString( pNewString, "," );
2950         if( IsValidRealString( pNewString ) == FALSE )
2951         {
2952                 return DISP_E_TYPEMISMATCH;
2953         }
2954
2955         /* Convert the valid string to a floating point number.
2956          */
2957         dValue = atof( pNewString );
2958         
2959         /* We don't need the string anymore so free it.
2960          */
2961         HeapFree( GetProcessHeap(), 0, pNewString );
2962
2963         *pdblOut = dValue;
2964
2965         return S_OK;
2966 }
2967
2968 /**********************************************************************
2969  *              VarR8FromCy [OLEAUT32.82]
2970  * Convert currency to double
2971  */
2972 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2973    *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2974    
2975    return S_OK;
2976 }
2977
2978 /******************************************************************************
2979  *              VarDateFromUI1          [OLEAUT32.88]
2980  */
2981 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2982 {
2983         TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2984
2985         *pdateOut = (DATE) bIn;
2986
2987         return S_OK;
2988 }
2989
2990 /******************************************************************************
2991  *              VarDateFromI2           [OLEAUT32.89]
2992  */
2993 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2994 {
2995         TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2996
2997         *pdateOut = (DATE) sIn;
2998
2999         return S_OK;
3000 }
3001
3002 /******************************************************************************
3003  *              VarDateFromI4           [OLEAUT32.90]
3004  */
3005 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
3006 {
3007         TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
3008
3009         if( lIn < DATE_MIN || lIn > DATE_MAX )
3010         {
3011                 return DISP_E_OVERFLOW;
3012         }
3013
3014         *pdateOut = (DATE) lIn;
3015
3016         return S_OK;
3017 }
3018
3019 /******************************************************************************
3020  *              VarDateFromR4           [OLEAUT32.91]
3021  */
3022 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3023 {
3024     TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3025
3026     if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3027         {
3028                 return DISP_E_OVERFLOW;
3029         }
3030
3031         *pdateOut = (DATE) fltIn;
3032
3033         return S_OK;
3034 }
3035
3036 /******************************************************************************
3037  *              VarDateFromR8           [OLEAUT32.92]
3038  */
3039 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3040 {
3041     TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3042
3043         if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3044         {
3045                 return DISP_E_OVERFLOW;
3046         }
3047
3048         *pdateOut = (DATE) dblIn;
3049
3050         return S_OK;
3051 }
3052
3053 /******************************************************************************
3054  *              VarDateFromStr          [OLEAUT32.94]
3055  * The string representing the date is composed of two parts, a date and time.
3056  *
3057  * The format of the time is has follows:
3058  * hh[:mm][:ss][AM|PM]
3059  * Whitespace can be inserted anywhere between these tokens.  A whitespace consists
3060  * of space and/or tab characters, which are ignored.
3061  *
3062  * The formats for the date part are has follows:
3063  * mm/[dd/][yy]yy 
3064  * [dd/]mm/[yy]yy
3065  * [yy]yy/mm/dd 
3066  * January dd[,] [yy]yy
3067  * dd January [yy]yy
3068  * [yy]yy January dd
3069  * Whitespace can be inserted anywhere between these tokens.
3070  *
3071  * The formats for the date and time string are has follows.
3072  * date[whitespace][time] 
3073  * [time][whitespace]date
3074  *
3075  * These are the only characters allowed in a string representing a date and time:
3076  * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3077  */
3078 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3079 {
3080     HRESULT ret = S_OK;
3081     struct tm TM;
3082
3083     memset( &TM, 0, sizeof(TM) );
3084
3085     TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3086
3087     if( DateTimeStringToTm( strIn, lcid, &TM ) )
3088     {
3089         if( TmToDATE( &TM, pdateOut ) == FALSE )
3090         {
3091             ret = E_INVALIDARG;
3092         }
3093     }
3094     else
3095     {
3096         ret = DISP_E_TYPEMISMATCH;
3097     }
3098
3099
3100         return ret;
3101 }
3102
3103 /******************************************************************************
3104  *              VarDateFromI1           [OLEAUT32.221]
3105  */
3106 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3107 {
3108         TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3109
3110         *pdateOut = (DATE) cIn;
3111
3112         return S_OK;
3113 }
3114
3115 /******************************************************************************
3116  *              VarDateFromUI2          [OLEAUT32.222]
3117  */
3118 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3119 {
3120         TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3121
3122         if( uiIn > DATE_MAX )
3123         {
3124                 return DISP_E_OVERFLOW;
3125         }
3126
3127         *pdateOut = (DATE) uiIn;
3128
3129         return S_OK;
3130 }
3131
3132 /******************************************************************************
3133  *              VarDateFromUI4          [OLEAUT32.223]
3134  */
3135 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3136 {
3137         TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3138
3139         if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3140         {
3141                 return DISP_E_OVERFLOW;
3142         }
3143
3144         *pdateOut = (DATE) ulIn;
3145
3146         return S_OK;
3147 }
3148
3149 /******************************************************************************
3150  *              VarDateFromBool         [OLEAUT32.96]
3151  */
3152 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3153 {
3154         TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3155
3156         *pdateOut = (DATE) boolIn;
3157
3158         return S_OK;
3159 }
3160
3161 /**********************************************************************
3162  *              VarDateFromCy [OLEAUT32.93]
3163  * Convert currency to date
3164  */
3165 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3166    *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3167
3168    if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3169    return S_OK;
3170 }
3171
3172 /******************************************************************************
3173  *              VarBstrFromUI1          [OLEAUT32.108]
3174  */
3175 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3176 {
3177         TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3178         sprintf( pBuffer, "%d", bVal );
3179
3180         *pbstrOut =  StringDupAtoBstr( pBuffer );
3181         
3182         return S_OK;
3183 }
3184
3185 /******************************************************************************
3186  *              VarBstrFromI2           [OLEAUT32.109]
3187  */
3188 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3189 {
3190         TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3191         sprintf( pBuffer, "%d", iVal );
3192         *pbstrOut = StringDupAtoBstr( pBuffer );
3193
3194         return S_OK;
3195 }
3196
3197 /******************************************************************************
3198  *              VarBstrFromI4           [OLEAUT32.110]
3199  */
3200 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3201 {
3202         TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3203
3204         sprintf( pBuffer, "%ld", lIn );
3205         *pbstrOut = StringDupAtoBstr( pBuffer );
3206
3207         return S_OK;
3208 }
3209
3210 /******************************************************************************
3211  *              VarBstrFromR4           [OLEAUT32.111]
3212  */
3213 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3214 {
3215         TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3216
3217         sprintf( pBuffer, "%.7g", fltIn );
3218         *pbstrOut = StringDupAtoBstr( pBuffer );
3219
3220         return S_OK;
3221 }
3222
3223 /******************************************************************************
3224  *              VarBstrFromR8           [OLEAUT32.112]
3225  */
3226 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3227 {
3228         TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3229
3230         sprintf( pBuffer, "%.15g", dblIn );
3231         *pbstrOut = StringDupAtoBstr( pBuffer );
3232
3233         return S_OK;
3234 }
3235
3236 /******************************************************************************
3237  *    VarBstrFromCy   [OLEAUT32.113]
3238  */
3239 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3240                                 /* FIXME */
3241         return E_NOTIMPL;
3242 }
3243
3244  
3245 /******************************************************************************
3246  *              VarBstrFromDate         [OLEAUT32.114]
3247  *
3248  * The date is implemented using an 8 byte floating-point number.
3249  * Days are represented by whole numbers increments starting with 0.00 as
3250  * being December 30 1899, midnight.
3251  * The hours are expressed as the fractional part of the number.
3252  * December 30 1899 at midnight = 0.00
3253  * January 1 1900 at midnight = 2.00
3254  * January 4 1900 at 6 AM = 5.25
3255  * January 4 1900 at noon = 5.50
3256  * December 29 1899 at midnight = -1.00
3257  * December 18 1899 at midnight = -12.00
3258  * December 18 1899 at 6AM = -12.25
3259  * December 18 1899 at 6PM = -12.75
3260  * December 19 1899 at midnight = -11.00
3261  * The tm structure is as follows:
3262  * struct tm {
3263  *                int tm_sec;      seconds after the minute - [0,59]
3264  *                int tm_min;      minutes after the hour - [0,59]
3265  *                int tm_hour;     hours since midnight - [0,23]
3266  *                int tm_mday;     day of the month - [1,31]
3267  *                int tm_mon;      months since January - [0,11]
3268  *                int tm_year;     years
3269  *                int tm_wday;     days since Sunday - [0,6]
3270  *                int tm_yday;     days since January 1 - [0,365]
3271  *                int tm_isdst;    daylight savings time flag
3272  *                };
3273  */
3274 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3275 {
3276     struct tm TM;
3277     memset( &TM, 0, sizeof(TM) );
3278
3279     TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3280
3281     if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3282                         {
3283         return E_INVALIDARG;
3284                 }
3285
3286     if( dwFlags & VAR_DATEVALUEONLY )
3287                         strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3288     else if( dwFlags & VAR_TIMEVALUEONLY )
3289                         strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3290                 else
3291         strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3292
3293                 *pbstrOut = StringDupAtoBstr( pBuffer );
3294
3295         return S_OK;
3296 }
3297
3298 /******************************************************************************
3299  *              VarBstrFromBool         [OLEAUT32.116]
3300  */
3301 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3302 {
3303         TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3304
3305         if( boolIn == VARIANT_FALSE )
3306         {
3307                 sprintf( pBuffer, "False" );
3308         }
3309         else
3310         {
3311                 sprintf( pBuffer, "True" );
3312         }
3313
3314         *pbstrOut = StringDupAtoBstr( pBuffer );
3315
3316         return S_OK;
3317 }
3318
3319 /******************************************************************************
3320  *              VarBstrFromI1           [OLEAUT32.229]
3321  */
3322 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3323 {
3324         TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3325         sprintf( pBuffer, "%d", cIn );
3326         *pbstrOut = StringDupAtoBstr( pBuffer );
3327
3328         return S_OK;
3329 }
3330
3331 /******************************************************************************
3332  *              VarBstrFromUI2          [OLEAUT32.230]
3333  */
3334 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3335 {
3336         TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3337         sprintf( pBuffer, "%d", uiIn );
3338         *pbstrOut = StringDupAtoBstr( pBuffer );
3339
3340         return S_OK;
3341 }
3342
3343 /******************************************************************************
3344  *              VarBstrFromUI4          [OLEAUT32.231]
3345  */
3346 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3347 {
3348         TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3349         sprintf( pBuffer, "%ld", ulIn );
3350         *pbstrOut = StringDupAtoBstr( pBuffer );
3351
3352         return S_OK;
3353 }
3354
3355 /******************************************************************************
3356  *              VarBoolFromUI1          [OLEAUT32.118]
3357  */
3358 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3359 {
3360         TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3361
3362         if( bIn == 0 )
3363         {
3364                 *pboolOut = VARIANT_FALSE;
3365         }
3366         else
3367         {
3368                 *pboolOut = VARIANT_TRUE;
3369         }
3370
3371         return S_OK;
3372 }
3373
3374 /******************************************************************************
3375  *              VarBoolFromI2           [OLEAUT32.119]
3376  */
3377 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3378 {
3379         TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3380
3381         if( sIn == 0 )
3382         {
3383                 *pboolOut = VARIANT_FALSE;
3384         }
3385         else
3386         {
3387                 *pboolOut = VARIANT_TRUE;
3388         }
3389
3390         return S_OK;
3391 }
3392
3393 /******************************************************************************
3394  *              VarBoolFromI4           [OLEAUT32.120]
3395  */
3396 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3397 {
3398         TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3399
3400         if( lIn == 0 )
3401         {
3402                 *pboolOut = VARIANT_FALSE;
3403         }
3404         else
3405         {
3406                 *pboolOut = VARIANT_TRUE;
3407         }
3408
3409         return S_OK;
3410 }
3411
3412 /******************************************************************************
3413  *              VarBoolFromR4           [OLEAUT32.121]
3414  */
3415 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3416 {
3417         TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3418
3419         if( fltIn == 0.0 )
3420         {
3421                 *pboolOut = VARIANT_FALSE;
3422         }
3423         else
3424         {
3425                 *pboolOut = VARIANT_TRUE;
3426         }
3427
3428         return S_OK;
3429 }
3430
3431 /******************************************************************************
3432  *              VarBoolFromR8           [OLEAUT32.122]
3433  */
3434 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3435 {
3436         TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3437
3438         if( dblIn == 0.0 )
3439         {
3440                 *pboolOut = VARIANT_FALSE;
3441         }
3442         else
3443         {
3444                 *pboolOut = VARIANT_TRUE;
3445         }
3446
3447         return S_OK;
3448 }
3449
3450 /******************************************************************************
3451  *              VarBoolFromDate         [OLEAUT32.123]
3452  */
3453 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3454 {
3455         TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3456
3457         if( dateIn == 0.0 )
3458         {
3459                 *pboolOut = VARIANT_FALSE;
3460         }
3461         else
3462         {
3463                 *pboolOut = VARIANT_TRUE;
3464         }
3465
3466         return S_OK;
3467 }
3468
3469 /******************************************************************************
3470  *              VarBoolFromStr          [OLEAUT32.125]
3471  */
3472 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3473 {
3474         HRESULT ret = S_OK;
3475         char* pNewString = NULL;
3476
3477         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3478
3479     pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3480
3481         if( pNewString == NULL || strlen( pNewString ) == 0 )
3482         {
3483                 ret = DISP_E_TYPEMISMATCH;
3484         }
3485
3486         if( ret == S_OK )
3487         {
3488                 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3489                 {
3490                         *pboolOut = VARIANT_TRUE;
3491                 }
3492                 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3493                 {
3494                         *pboolOut = VARIANT_FALSE;
3495                 }
3496                 else
3497                 {
3498                         /* Try converting the string to a floating point number.
3499                          */
3500                         double dValue = 0.0;
3501                         HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3502                         if( res != S_OK )
3503                         {
3504                                 ret = DISP_E_TYPEMISMATCH;
3505                         }
3506                         else if( dValue == 0.0 )
3507                         {
3508                                 *pboolOut = VARIANT_FALSE;
3509                         }
3510                         else
3511                         {
3512                                 *pboolOut = VARIANT_TRUE;
3513                         }
3514                 }
3515         }
3516
3517         HeapFree( GetProcessHeap(), 0, pNewString );
3518         
3519         return ret;
3520 }
3521
3522 /******************************************************************************
3523  *              VarBoolFromI1           [OLEAUT32.233]
3524  */
3525 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3526 {
3527         TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3528
3529         if( cIn == 0 )
3530         {
3531                 *pboolOut = VARIANT_FALSE;
3532         }
3533         else
3534         {
3535                 *pboolOut = VARIANT_TRUE;
3536         }
3537
3538         return S_OK;
3539 }
3540
3541 /******************************************************************************
3542  *              VarBoolFromUI2          [OLEAUT32.234]
3543  */
3544 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3545 {
3546         TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3547
3548         if( uiIn == 0 )
3549         {
3550                 *pboolOut = VARIANT_FALSE;
3551         }
3552         else
3553         {
3554                 *pboolOut = VARIANT_TRUE;
3555         }
3556
3557         return S_OK;
3558 }
3559
3560 /******************************************************************************
3561  *              VarBoolFromUI4          [OLEAUT32.235]
3562  */
3563 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3564 {
3565         TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3566
3567         if( ulIn == 0 )
3568         {
3569                 *pboolOut = VARIANT_FALSE;
3570         }
3571         else
3572         {
3573                 *pboolOut = VARIANT_TRUE;
3574         }
3575
3576         return S_OK;
3577 }
3578
3579 /**********************************************************************
3580  *              VarBoolFromCy [OLEAUT32.124]
3581  * Convert currency to boolean
3582  */
3583 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3584       if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3585       else *pboolOut = 0;
3586       
3587       return S_OK;
3588 }
3589
3590 /******************************************************************************
3591  *              VarI1FromUI1            [OLEAUT32.244]
3592  */
3593 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3594 {
3595         TRACE("( %d, %p ), stub\n", bIn, pcOut );
3596
3597         /* Check range of value.
3598          */
3599         if( bIn > CHAR_MAX )
3600         {
3601                 return DISP_E_OVERFLOW;
3602         }
3603
3604         *pcOut = (CHAR) bIn;
3605
3606         return S_OK;
3607 }
3608
3609 /******************************************************************************
3610  *              VarI1FromI2             [OLEAUT32.245]
3611  */
3612 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3613 {
3614         TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3615
3616         if( uiIn > CHAR_MAX )
3617         {
3618                 return DISP_E_OVERFLOW;
3619         }
3620
3621         *pcOut = (CHAR) uiIn;
3622
3623         return S_OK;
3624 }
3625
3626 /******************************************************************************
3627  *              VarI1FromI4             [OLEAUT32.246]
3628  */
3629 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3630 {
3631         TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3632
3633         if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3634         {
3635                 return DISP_E_OVERFLOW;
3636         }
3637
3638         *pcOut = (CHAR) lIn;
3639
3640         return S_OK;
3641 }
3642
3643 /******************************************************************************
3644  *              VarI1FromR4             [OLEAUT32.247]
3645  */
3646 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3647 {
3648         TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3649
3650     fltIn = round( fltIn );
3651         if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3652         {
3653                 return DISP_E_OVERFLOW;
3654         }
3655
3656         *pcOut = (CHAR) fltIn;
3657
3658         return S_OK;
3659 }
3660
3661 /******************************************************************************
3662  *              VarI1FromR8             [OLEAUT32.248]
3663  */
3664 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3665 {
3666         TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3667
3668     dblIn = round( dblIn );
3669     if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3670         {
3671                 return DISP_E_OVERFLOW;
3672         }
3673
3674         *pcOut = (CHAR) dblIn;
3675
3676         return S_OK;
3677 }
3678
3679 /******************************************************************************
3680  *              VarI1FromDate           [OLEAUT32.249]
3681  */
3682 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3683 {
3684         TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3685
3686     dateIn = round( dateIn );
3687         if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3688         {
3689                 return DISP_E_OVERFLOW;
3690         }
3691
3692         *pcOut = (CHAR) dateIn;
3693
3694         return S_OK;
3695 }
3696
3697 /******************************************************************************
3698  *              VarI1FromStr            [OLEAUT32.251]
3699  */
3700 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3701 {
3702         double dValue = 0.0;
3703         LPSTR pNewString = NULL;
3704
3705         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3706
3707         /* Check if we have a valid argument
3708          */
3709         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3710         RemoveCharacterFromString( pNewString, "," );
3711         if( IsValidRealString( pNewString ) == FALSE )
3712         {
3713                 return DISP_E_TYPEMISMATCH;
3714         }
3715
3716         /* Convert the valid string to a floating point number.
3717          */
3718         dValue = atof( pNewString );
3719   
3720         /* We don't need the string anymore so free it.
3721          */
3722         HeapFree( GetProcessHeap(), 0, pNewString );
3723
3724         /* Check range of value.
3725      */
3726     dValue = round( dValue );
3727         if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3728         {
3729                 return DISP_E_OVERFLOW;
3730         }
3731
3732         *pcOut = (CHAR) dValue;
3733
3734         return S_OK;
3735 }
3736
3737 /******************************************************************************
3738  *              VarI1FromBool           [OLEAUT32.253]
3739  */
3740 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3741 {
3742         TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3743
3744         *pcOut = (CHAR) boolIn;
3745
3746         return S_OK;
3747 }
3748
3749 /******************************************************************************
3750  *              VarI1FromUI2            [OLEAUT32.254]
3751  */
3752 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3753 {
3754         TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3755
3756         if( uiIn > CHAR_MAX )
3757         {
3758                 return DISP_E_OVERFLOW;
3759         }
3760
3761         *pcOut = (CHAR) uiIn;
3762
3763         return S_OK;
3764 }
3765
3766 /******************************************************************************
3767  *              VarI1FromUI4            [OLEAUT32.255]
3768  */
3769 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3770 {
3771         TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3772
3773         if( ulIn > CHAR_MAX )
3774         {
3775                 return DISP_E_OVERFLOW;
3776         }
3777
3778         *pcOut = (CHAR) ulIn;
3779
3780         return S_OK;
3781 }
3782
3783 /**********************************************************************
3784  *              VarI1FromCy [OLEAUT32.250]
3785  * Convert currency to signed char
3786  */
3787 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3788    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3789    
3790    if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3791    
3792    *pcOut = (CHAR)t;
3793    return S_OK;
3794 }
3795
3796 /******************************************************************************
3797  *              VarUI2FromUI1           [OLEAUT32.257]
3798  */
3799 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3800 {
3801         TRACE("( %d, %p ), stub\n", bIn, puiOut );
3802
3803         *puiOut = (USHORT) bIn;
3804
3805         return S_OK;
3806 }
3807
3808 /******************************************************************************
3809  *              VarUI2FromI2            [OLEAUT32.258]
3810  */
3811 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3812 {
3813         TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3814
3815         if( uiIn < UI2_MIN )
3816         {
3817                 return DISP_E_OVERFLOW;
3818         }
3819
3820         *puiOut = (USHORT) uiIn;
3821
3822         return S_OK;
3823 }
3824
3825 /******************************************************************************
3826  *              VarUI2FromI4            [OLEAUT32.259]
3827  */
3828 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3829 {
3830         TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3831
3832         if( lIn < UI2_MIN || lIn > UI2_MAX )
3833         {
3834                 return DISP_E_OVERFLOW;
3835         }
3836
3837         *puiOut = (USHORT) lIn;
3838
3839         return S_OK;
3840 }
3841
3842 /******************************************************************************
3843  *              VarUI2FromR4            [OLEAUT32.260]
3844  */
3845 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3846 {
3847         TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3848
3849     fltIn = round( fltIn );
3850         if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3851         {
3852                 return DISP_E_OVERFLOW;
3853         }
3854
3855         *puiOut = (USHORT) fltIn;
3856
3857         return S_OK;
3858 }
3859
3860 /******************************************************************************
3861  *              VarUI2FromR8            [OLEAUT32.261]
3862  */
3863 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3864 {
3865         TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3866
3867     dblIn = round( dblIn );
3868     if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3869         {
3870                 return DISP_E_OVERFLOW;
3871         }
3872
3873         *puiOut = (USHORT) dblIn;
3874
3875         return S_OK;
3876 }
3877
3878 /******************************************************************************
3879  *              VarUI2FromDate          [OLEAUT32.262]
3880  */
3881 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3882 {
3883         TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3884
3885     dateIn = round( dateIn );
3886         if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3887         {
3888                 return DISP_E_OVERFLOW;
3889         }
3890
3891         *puiOut = (USHORT) dateIn;
3892
3893         return S_OK;
3894 }
3895
3896 /******************************************************************************
3897  *              VarUI2FromStr           [OLEAUT32.264]
3898  */
3899 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3900 {
3901         double dValue = 0.0;
3902         LPSTR pNewString = NULL;
3903
3904         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3905
3906         /* Check if we have a valid argument
3907          */
3908         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3909         RemoveCharacterFromString( pNewString, "," );
3910         if( IsValidRealString( pNewString ) == FALSE )
3911         {
3912                 return DISP_E_TYPEMISMATCH;
3913         }
3914
3915         /* Convert the valid string to a floating point number.
3916          */
3917         dValue = atof( pNewString );
3918   
3919         /* We don't need the string anymore so free it.
3920          */
3921         HeapFree( GetProcessHeap(), 0, pNewString );
3922
3923         /* Check range of value.
3924      */
3925     dValue = round( dValue );
3926         if( dValue < UI2_MIN || dValue > UI2_MAX )
3927         {
3928                 return DISP_E_OVERFLOW;
3929         }
3930
3931         *puiOut = (USHORT) dValue;
3932
3933         return S_OK;
3934 }
3935
3936 /******************************************************************************
3937  *              VarUI2FromBool          [OLEAUT32.266]
3938  */
3939 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3940 {
3941         TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3942
3943         *puiOut = (USHORT) boolIn;
3944
3945         return S_OK;
3946 }
3947
3948 /******************************************************************************
3949  *              VarUI2FromI1            [OLEAUT32.267]
3950  */
3951 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3952 {
3953         TRACE("( %c, %p ), stub\n", cIn, puiOut );
3954
3955         *puiOut = (USHORT) cIn;
3956
3957         return S_OK;
3958 }
3959
3960 /******************************************************************************
3961  *              VarUI2FromUI4           [OLEAUT32.268]
3962  */
3963 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3964 {
3965         TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3966
3967         if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3968         {
3969                 return DISP_E_OVERFLOW;
3970         }
3971
3972         *puiOut = (USHORT) ulIn;
3973
3974         return S_OK;
3975 }
3976
3977 /******************************************************************************
3978  *              VarUI4FromStr           [OLEAUT32.277]
3979  */
3980 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3981 {
3982         double dValue = 0.0;
3983         LPSTR pNewString = NULL;
3984
3985         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3986
3987         /* Check if we have a valid argument
3988          */
3989         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3990         RemoveCharacterFromString( pNewString, "," );
3991         if( IsValidRealString( pNewString ) == FALSE )
3992         {
3993                 return DISP_E_TYPEMISMATCH;
3994         }
3995
3996         /* Convert the valid string to a floating point number.
3997          */
3998         dValue = atof( pNewString );
3999   
4000         /* We don't need the string anymore so free it.
4001          */
4002         HeapFree( GetProcessHeap(), 0, pNewString );
4003
4004         /* Check range of value.
4005      */
4006     dValue = round( dValue );
4007         if( dValue < UI4_MIN || dValue > UI4_MAX )
4008         {
4009                 return DISP_E_OVERFLOW;
4010         }
4011
4012         *pulOut = (ULONG) dValue;
4013
4014         return S_OK;
4015 }
4016
4017 /**********************************************************************
4018  *              VarUI2FromCy [OLEAUT32.263]
4019  * Convert currency to unsigned short
4020  */
4021 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4022    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4023    
4024    if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4025       
4026    *pusOut = (USHORT)t;
4027    
4028    return S_OK;
4029 }
4030
4031 /******************************************************************************
4032  *              VarUI4FromUI1           [OLEAUT32.270]
4033  */
4034 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4035 {
4036         TRACE("( %d, %p ), stub\n", bIn, pulOut );
4037
4038         *pulOut = (USHORT) bIn;
4039
4040         return S_OK;
4041 }
4042
4043 /******************************************************************************
4044  *              VarUI4FromI2            [OLEAUT32.271]
4045  */
4046 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4047 {
4048         TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4049
4050         if( uiIn < UI4_MIN )
4051         {
4052                 return DISP_E_OVERFLOW;
4053         }
4054
4055         *pulOut = (ULONG) uiIn;
4056
4057         return S_OK;
4058 }
4059
4060 /******************************************************************************
4061  *              VarUI4FromI4            [OLEAUT32.272]
4062  */
4063 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4064 {
4065         TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4066
4067         if( lIn < UI4_MIN )
4068         {
4069                 return DISP_E_OVERFLOW;
4070         }
4071
4072         *pulOut = (ULONG) lIn;
4073
4074         return S_OK;
4075 }
4076
4077 /******************************************************************************
4078  *              VarUI4FromR4            [OLEAUT32.273]
4079  */
4080 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4081 {
4082     fltIn = round( fltIn );
4083     if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4084         {
4085                 return DISP_E_OVERFLOW;
4086         }
4087
4088         *pulOut = (ULONG) fltIn;
4089
4090         return S_OK;
4091 }
4092
4093 /******************************************************************************
4094  *              VarUI4FromR8            [OLEAUT32.274]
4095  */
4096 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4097 {
4098         TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4099
4100     dblIn = round( dblIn );
4101         if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4102         {
4103                 return DISP_E_OVERFLOW;
4104     }
4105
4106         *pulOut = (ULONG) dblIn;
4107
4108         return S_OK;
4109 }
4110
4111 /******************************************************************************
4112  *              VarUI4FromDate          [OLEAUT32.275]
4113  */
4114 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4115 {
4116         TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4117
4118     dateIn = round( dateIn );
4119     if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4120         {
4121                 return DISP_E_OVERFLOW;
4122         }
4123
4124         *pulOut = (ULONG) dateIn;
4125
4126         return S_OK;
4127 }
4128
4129 /******************************************************************************
4130  *              VarUI4FromBool          [OLEAUT32.279]
4131  */
4132 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4133 {
4134         TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4135
4136         *pulOut = (ULONG) boolIn;
4137
4138         return S_OK;
4139 }
4140
4141 /******************************************************************************
4142  *              VarUI4FromI1            [OLEAUT32.280]
4143  */
4144 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4145 {
4146         TRACE("( %c, %p ), stub\n", cIn, pulOut );
4147
4148         *pulOut = (ULONG) cIn;
4149
4150         return S_OK;
4151 }
4152
4153 /******************************************************************************
4154  *              VarUI4FromUI2           [OLEAUT32.281]
4155  */
4156 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4157 {
4158         TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4159
4160         *pulOut = (ULONG) uiIn;
4161
4162         return S_OK;
4163 }
4164
4165 /**********************************************************************
4166  *              VarUI4FromCy [OLEAUT32.276]
4167  * Convert currency to unsigned long
4168  */
4169 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4170    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4171    
4172    if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4173
4174    *pulOut = (ULONG)t;
4175
4176    return S_OK;
4177 }
4178
4179 /**********************************************************************
4180  *              VarCyFromUI1 [OLEAUT32.98]
4181  * Convert unsigned char to currency
4182  */
4183 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4184    pcyOut->s.Hi = 0;
4185    pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4186    
4187    return S_OK;
4188 }
4189
4190 /**********************************************************************
4191  *              VarCyFromI2 [OLEAUT32.99]
4192  * Convert signed short to currency
4193  */
4194 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4195    if (sIn < 0) pcyOut->s.Hi = -1;
4196    else pcyOut->s.Hi = 0;
4197    pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4198    
4199    return S_OK;
4200 }
4201
4202 /**********************************************************************
4203  *              VarCyFromI4 [OLEAUT32.100]
4204  * Convert signed long to currency
4205  */
4206 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4207       double t = (double)lIn * (double)10000;
4208       pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4209       pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4210       if (lIn < 0) pcyOut->s.Hi--;
4211    
4212       return S_OK;
4213 }
4214
4215 /**********************************************************************
4216  *              VarCyFromR4 [OLEAUT32.101]
4217  * Convert float to currency
4218  */
4219 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4220    double t = round((double)fltIn * (double)10000);
4221    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4222    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4223    if (fltIn < 0) pcyOut->s.Hi--;
4224    
4225    return S_OK;
4226 }
4227
4228 /**********************************************************************
4229  *              VarCyFromR8 [OLEAUT32.102]
4230  * Convert double to currency
4231  */
4232 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4233    double t = round(dblIn * (double)10000);
4234    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4235    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4236    if (dblIn < 0) pcyOut->s.Hi--;
4237
4238    return S_OK;
4239 }
4240
4241 /**********************************************************************
4242  *              VarCyFromDate [OLEAUT32.103]
4243  * Convert date to currency
4244  */
4245 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4246    double t = round((double)dateIn * (double)10000);
4247    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4248    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4249    if (dateIn < 0) pcyOut->s.Hi--;
4250
4251    return S_OK;
4252 }
4253
4254 /**********************************************************************
4255  *              VarCyFromStr [OLEAUT32.104]
4256  */
4257 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4258                                 /* FIXME */
4259                 return E_NOTIMPL;
4260 }
4261
4262  
4263 /**********************************************************************
4264  *              VarCyFromBool [OLEAUT32.106]
4265  * Convert boolean to currency
4266  */
4267 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4268    if (boolIn < 0) pcyOut->s.Hi = -1;
4269    else pcyOut->s.Hi = 0;
4270    pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4271    
4272    return S_OK;
4273 }
4274
4275 /**********************************************************************
4276  *              VarCyFromI1 [OLEAUT32.225]
4277  * Convert signed char to currency
4278  */
4279 HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pcyOut) {
4280    if (cIn < 0) pcyOut->s.Hi = -1;
4281    else pcyOut->s.Hi = 0;
4282    pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4283    
4284    return S_OK;
4285 }
4286
4287 /**********************************************************************
4288  *              VarCyFromUI2 [OLEAUT32.226]
4289  * Convert unsigned short to currency
4290  */
4291 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4292    pcyOut->s.Hi = 0;
4293    pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4294    
4295    return S_OK;
4296 }
4297
4298 /**********************************************************************
4299  *              VarCyFromUI4 [OLEAUT32.227]
4300  * Convert unsigned long to currency
4301  */
4302 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4303    double t = (double)ulIn * (double)10000;
4304    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4305    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4306       
4307    return S_OK;
4308 }
4309
4310
4311 /**********************************************************************
4312  *              DosDateTimeToVariantTime [OLEAUT32.14]
4313  * Convert dos representation of time to the date and time representation
4314  * stored in a variant.
4315  */
4316 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4317                                     DATE *pvtime)
4318 {
4319     struct tm t;
4320
4321     TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4322     
4323     t.tm_sec = (wDosTime & 0x001f) * 2;
4324     t.tm_min = (wDosTime & 0x07e0) >> 5;
4325     t.tm_hour = (wDosTime & 0xf800) >> 11;
4326     
4327     t.tm_mday = (wDosDate & 0x001f);
4328     t.tm_mon = (wDosDate & 0x01e0) >> 5;
4329     t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4330
4331     return TmToDATE( &t, pvtime );
4332 }
4333
4334 /**********************************************************************
4335  *              VariantTimeToDosDateTime [OLEAUT32.??]
4336  * Convert variant representation of time to the date and time representation
4337  * stored in dos.
4338  */
4339 INT WINAPI VariantTimeToDosDateTime(DATE pvtime, USHORT *wDosDate, USHORT *wDosTime)
4340 {
4341     struct tm t;
4342     wDosTime = 0;
4343     wDosDate = 0;
4344
4345     TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", *wDosDate, *wDosTime, &pvtime );
4346
4347     if (DateToTm(pvtime, (LCID)NULL, &t) < 0) return 0;
4348
4349     *wDosTime = *wDosTime | (t.tm_sec / 2);
4350     *wDosTime = *wDosTime | (t.tm_min << 5);
4351     *wDosTime = *wDosTime | (t.tm_hour << 11);
4352
4353     *wDosDate = *wDosDate | t.tm_mday ;
4354     *wDosDate = *wDosDate | t.tm_mon << 5;
4355     *wDosDate = *wDosDate | ((t.tm_year - 1980) << 9) ;
4356
4357     return 1;
4358 }
4359
4360
4361 HRESULT WINAPI SystemTimeToVariantTime( LPSYSTEMTIME  lpSystemTime, double *pvtime )
4362 {
4363     static const BYTE Days_Per_Month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4364     static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4365
4366     struct tm t;
4367
4368     TRACE(" %d/%d/%d %d:%d:%d\n",
4369           lpSystemTime->wMonth, lpSystemTime->wDay,
4370           lpSystemTime->wYear, lpSystemTime->wHour,
4371           lpSystemTime->wMinute, lpSystemTime->wSecond);
4372
4373     if (lpSystemTime->wYear >= 1900)
4374     {
4375         t.tm_sec = lpSystemTime->wSecond;
4376         t.tm_min = lpSystemTime->wMinute;
4377         t.tm_hour = lpSystemTime->wHour;
4378
4379         t.tm_mday = lpSystemTime->wDay;
4380         t.tm_mon = lpSystemTime->wMonth;
4381         t.tm_year = lpSystemTime->wYear;
4382
4383         return TmToDATE( &t, pvtime );
4384     }
4385     else
4386     {
4387         t.tm_sec = lpSystemTime->wSecond;
4388         t.tm_min = lpSystemTime->wMinute;
4389         t.tm_hour = lpSystemTime->wHour;
4390
4391         if (isleap(lpSystemTime->wYear) )
4392             t.tm_mday = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4393         else
4394             t.tm_mday = Days_Per_Month[13 - lpSystemTime->wMonth] - lpSystemTime->wDay;
4395
4396         t.tm_mon = 13 - lpSystemTime->wMonth;
4397         t.tm_year = 1900 + 1899 - lpSystemTime->wYear;
4398
4399         TmToDATE( &t, pvtime );
4400
4401         *pvtime *= -1;
4402
4403         return 1;
4404     }
4405
4406     return 0;
4407 }
4408
4409 HRESULT WINAPI VariantTimeToSystemTime( double vtime, LPSYSTEMTIME  lpSystemTime )
4410 {
4411     double t = 0, timeofday = 0;
4412
4413     static const BYTE Days_Per_Month[] =    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4414     static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4415
4416     /* The Month_Code is used to find the Day of the Week (LY = LeapYear)*/
4417     static const BYTE Month_Code[] =    {0, 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4418     static const BYTE Month_Code_LY[] = {0, 0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6};
4419
4420     /* The Century_Code is used to find the Day of the Week */
4421     static const BYTE Century_Code[]  = {0, 6, 4, 2};
4422
4423     struct tm r;
4424
4425     TRACE(" Variant = %f SYSTEMTIME ptr %p", vtime, lpSystemTime);
4426
4427     if (vtime >= 0)
4428     {
4429
4430         if (DateToTm(vtime, (LCID)NULL, &r ) <= 0) return 0;
4431
4432         lpSystemTime->wSecond = r.tm_sec;
4433         lpSystemTime->wMinute = r.tm_min;
4434         lpSystemTime->wHour = r.tm_hour;
4435         lpSystemTime->wDay = r.tm_mday;
4436         lpSystemTime->wMonth = r.tm_mon;
4437
4438         if (lpSystemTime->wMonth == 12)
4439             lpSystemTime->wMonth = 1;
4440         else
4441             lpSystemTime->wMonth++;
4442
4443         lpSystemTime->wYear = r.tm_year;
4444     }
4445     else
4446     {
4447         vtime = -1*vtime;
4448
4449         if (DateToTm(vtime, (LCID)NULL, &r ) <= 0) return 0;
4450
4451         lpSystemTime->wSecond = r.tm_sec;
4452         lpSystemTime->wMinute = r.tm_min;
4453         lpSystemTime->wHour = r.tm_hour;
4454
4455         lpSystemTime->wMonth = 13 - r.tm_mon;
4456
4457         if (lpSystemTime->wMonth == 1)
4458             lpSystemTime->wMonth = 12;
4459         else
4460             lpSystemTime->wMonth--;
4461
4462         lpSystemTime->wYear = 1899 - (r.tm_year - 1900);
4463
4464         if (!isleap(lpSystemTime->wYear) )
4465             lpSystemTime->wDay = Days_Per_Month[13 - lpSystemTime->wMonth] - r.tm_mday;
4466         else
4467             lpSystemTime->wDay = Days_Per_Month_LY[13 - lpSystemTime->wMonth] - r.tm_mday;
4468
4469
4470     }
4471
4472     if (!isleap(lpSystemTime->wYear))
4473     {
4474         /*
4475           (Century_Code+Month_Code+Year_Code+Day) % 7
4476
4477           The century code repeats every 400 years , so the array
4478           works out like this,
4479
4480           Century_Code[0] is for 16th/20th Centry
4481           Century_Code[1] is for 17th/21th Centry
4482           Century_Code[2] is for 18th/22th Centry
4483           Century_Code[3] is for 19th/23th Centry
4484
4485           The year code is found with the formula (year + (year / 4))
4486           the "year" must be between 0 and 99 .
4487
4488           The Month Code (Month_Code[1]) starts with January and
4489           ends with December.
4490         */
4491
4492         lpSystemTime->wDayOfWeek = (
4493             Century_Code[(( (lpSystemTime->wYear+100) - lpSystemTime->wYear%100) /100) %4]+
4494             ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4495             Month_Code[lpSystemTime->wMonth]+
4496             lpSystemTime->wDay) % 7;
4497
4498         if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4499         else lpSystemTime->wDayOfWeek -= 1;
4500     }
4501     else
4502     {
4503         lpSystemTime->wDayOfWeek = (
4504             Century_Code[(((lpSystemTime->wYear+100) - lpSystemTime->wYear%100)/100)%4]+
4505             ((lpSystemTime->wYear%100)+(lpSystemTime->wYear%100)/4)+
4506             Month_Code_LY[lpSystemTime->wMonth]+
4507             lpSystemTime->wDay) % 7;
4508
4509         if (lpSystemTime->wDayOfWeek == 0) lpSystemTime->wDayOfWeek = 7;
4510         else lpSystemTime->wDayOfWeek -= 1;
4511     }
4512
4513     t = floor(vtime);
4514     timeofday = vtime - t;
4515
4516     lpSystemTime->wMilliseconds = (timeofday
4517                                    - lpSystemTime->wHour*(1/24)
4518                                    - lpSystemTime->wMinute*(1/1440)
4519                                    - lpSystemTime->wSecond*(1/86400) )*(1/5184000);
4520
4521     return 1;
4522 }
4523
4524 HRESULT WINAPI VarUdateFromDate( DATE datein, ULONG dwFlags, UDATE *pudateout)
4525 {
4526     HRESULT i = 0;
4527     static const BYTE Days_Per_Month[] =    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4528     static const BYTE Days_Per_Month_LY[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4529
4530     TRACE("DATE = %f\n", (double)datein);
4531     i = VariantTimeToSystemTime(datein, &(pudateout->st) );
4532
4533     if (i)
4534     {
4535         pudateout->wDayOfYear = 0;
4536
4537         if (isleap(pudateout->st.wYear))
4538         {
4539             for (i =1; i<pudateout->st.wMonth; i++)
4540                 pudateout->wDayOfYear += Days_Per_Month[i];
4541         }
4542         else
4543         {
4544             for (i =1; i<pudateout->st.wMonth; i++)
4545                 pudateout->wDayOfYear += Days_Per_Month_LY[i];
4546         }
4547
4548         pudateout->wDayOfYear += pudateout->st.wDay;
4549         dwFlags = 0; /*VAR_VALIDDATE*/
4550     }
4551     else dwFlags = 0;
4552
4553     return i;
4554 }
4555
4556 HRESULT WINAPI VarDateFromUdate(UDATE *pudateout,
4557                                 ULONG dwFlags, DATE *datein)
4558 {
4559     HRESULT i;
4560     double t = 0;
4561     TRACE(" %d/%d/%d %d:%d:%d\n",
4562           pudateout->st.wMonth, pudateout->st.wDay,
4563           pudateout->st.wYear, pudateout->st.wHour,
4564           pudateout->st.wMinute, pudateout->st.wSecond);
4565
4566
4567     i = SystemTimeToVariantTime(&(pudateout->st), &t);
4568     *datein = t;
4569
4570     if (i) dwFlags = 0; /*VAR_VALIDDATE*/
4571     else dwFlags = 0;
4572
4573     return i;
4574 }