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