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