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