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