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