Revised shell link process to treat empty (e.g. "") strings
[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 dates prior to 1900.
20  *   - The parsing does not accept as many formats as 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 successful.
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 successful.
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 converts 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 successful.
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_EMPTY ):
1451                         if ((pd->u.bstrVal = SysAllocStringLen(NULL, 0)))
1452                                 res = S_OK;
1453                         else
1454                                 res = E_OUTOFMEMORY;
1455                         break;
1456                 case( VT_I1 ):
1457                         res = VarBstrFromI1( ps->u.cVal, lcid, dwFlags, &(pd->u.bstrVal) );
1458                         break;
1459                 case( VT_I2 ):
1460                         res = VarBstrFromI2( ps->u.iVal, lcid, dwFlags, &(pd->u.bstrVal) );
1461                         break;
1462                 case( VT_INT ):
1463                         res = VarBstrFromInt( ps->u.intVal, lcid, dwFlags, &(pd->u.bstrVal) );
1464                         break;
1465                 case( VT_I4 ):
1466                         res = VarBstrFromI4( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );
1467                         break;
1468                 case( VT_UI1 ):
1469                         res = VarBstrFromUI1( ps->u.bVal, lcid, dwFlags, &(pd->u.bstrVal) );
1470                         break;
1471                 case( VT_UI2 ):
1472                         res = VarBstrFromUI2( ps->u.uiVal, lcid, dwFlags, &(pd->u.bstrVal) );
1473                         break;
1474                 case( VT_UINT ):
1475                         res = VarBstrFromUint( ps->u.uintVal, lcid, dwFlags, &(pd->u.bstrVal) );
1476                         break;
1477                 case( VT_UI4 ):
1478                         res = VarBstrFromUI4( ps->u.ulVal, lcid, dwFlags, &(pd->u.bstrVal) );
1479                         break;
1480                 case( VT_R4 ):
1481                         res = VarBstrFromR4( ps->u.fltVal, lcid, dwFlags, &(pd->u.bstrVal) );
1482                         break;
1483                 case( VT_R8 ):
1484                         res = VarBstrFromR8( ps->u.dblVal, lcid, dwFlags, &(pd->u.bstrVal) );
1485                         break;
1486                 case( VT_DATE ):
1487                         res = VarBstrFromDate( ps->u.date, lcid, dwFlags, &(pd->u.bstrVal) );
1488                         break;
1489                 case( VT_BOOL ):
1490                         res = VarBstrFromBool( ps->u.boolVal, lcid, dwFlags, &(pd->u.bstrVal) );
1491                         break;
1492         case( VT_BSTR ):
1493             res = VariantCopy( pd, ps );
1494             break;
1495                 case( VT_CY ):
1496              /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1497                 case( VT_DISPATCH ):
1498                         /*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
1499                 case( VT_UNKNOWN ):
1500                         /*res = VarBstrFrom32( ps->u.lVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1501                 case( VT_DECIMAL ):
1502                         /*res = VarBstrFromDec32( ps->u.deiVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
1503                 default:
1504                         res = DISP_E_TYPEMISMATCH;
1505                         FIXME("Coercion from %d to %d\n", vtFrom, vt );
1506                         break;
1507                 }
1508                 break;
1509
1510      case( VT_CY ):
1511         switch( vtFrom )
1512           {
1513           case( VT_I1 ):
1514              res = VarCyFromI1( ps->u.cVal, &(pd->u.cyVal) );
1515              break;
1516           case( VT_I2 ):
1517              res = VarCyFromI2( ps->u.iVal, &(pd->u.cyVal) );
1518              break;
1519           case( VT_INT ):
1520              res = VarCyFromInt( ps->u.intVal, &(pd->u.cyVal) );
1521              break;
1522           case( VT_I4 ):
1523              res = VarCyFromI4( ps->u.lVal, &(pd->u.cyVal) );
1524              break;
1525           case( VT_UI1 ):
1526              res = VarCyFromUI1( ps->u.bVal, &(pd->u.cyVal) );
1527              break;
1528           case( VT_UI2 ):
1529              res = VarCyFromUI2( ps->u.uiVal, &(pd->u.cyVal) );
1530              break;
1531           case( VT_UINT ):
1532              res = VarCyFromUint( ps->u.uintVal, &(pd->u.cyVal) );
1533              break;
1534           case( VT_UI4 ):
1535              res = VarCyFromUI4( ps->u.ulVal, &(pd->u.cyVal) );
1536              break;
1537           case( VT_R4 ):
1538              res = VarCyFromR4( ps->u.fltVal, &(pd->u.cyVal) );
1539              break;
1540           case( VT_R8 ):
1541              res = VarCyFromR8( ps->u.dblVal, &(pd->u.cyVal) );
1542              break;
1543           case( VT_DATE ):
1544              res = VarCyFromDate( ps->u.date, &(pd->u.cyVal) );
1545              break;
1546           case( VT_BOOL ):
1547              res = VarCyFromBool( ps->u.date, &(pd->u.cyVal) );
1548              break;
1549           case( VT_CY ):
1550              res = VariantCopy( pd, ps );
1551              break;
1552           case( VT_BSTR ):
1553              /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
1554           case( VT_DISPATCH ):
1555              /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
1556           case( VT_UNKNOWN ):
1557              /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
1558           case( VT_DECIMAL ):
1559              /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
1560           default:
1561              res = DISP_E_TYPEMISMATCH;
1562              FIXME("Coercion from %d to %d\n", vtFrom, vt );
1563              break;
1564           }
1565         break;
1566
1567         default:
1568                 res = DISP_E_TYPEMISMATCH;
1569                 FIXME("Coercion from %d to %d\n", vtFrom, vt );
1570                 break;
1571         }
1572         
1573         return res;
1574 }
1575
1576 /******************************************************************************
1577  *              ValidateVtRange [INTERNAL]
1578  *
1579  * Used internally by the hi-level Variant API to determine
1580  * if the vartypes are valid.
1581  */
1582 static HRESULT WINAPI ValidateVtRange( VARTYPE vt )
1583 {
1584     /* if by value we must make sure it is in the
1585      * range of the valid types.
1586      */
1587     if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1588     {
1589         return DISP_E_BADVARTYPE;
1590     }
1591     return S_OK;
1592 }
1593
1594
1595 /******************************************************************************
1596  *              ValidateVartype [INTERNAL]
1597  *
1598  * Used internally by the hi-level Variant API to determine
1599  * if the vartypes are valid.
1600  */
1601 static HRESULT WINAPI ValidateVariantType( VARTYPE vt )
1602 {
1603         HRESULT res = S_OK;
1604
1605         /* check if we have a valid argument.
1606          */
1607         if( vt & VT_BYREF )
1608     {
1609         /* if by reference check that the type is in
1610          * the valid range and that it is not of empty or null type
1611          */
1612         if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1613             ( vt & VT_TYPEMASK ) == VT_NULL ||
1614                         ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1615                 {
1616                         res = E_INVALIDARG;
1617                 }
1618                         
1619     }
1620     else
1621     {
1622         res = ValidateVtRange( vt );
1623     }
1624                 
1625         return res;
1626 }
1627
1628 /******************************************************************************
1629  *              ValidateVt      [INTERNAL]
1630  *
1631  * Used internally by the hi-level Variant API to determine
1632  * if the vartypes are valid.
1633  */
1634 static HRESULT WINAPI ValidateVt( VARTYPE vt )
1635 {
1636         HRESULT res = S_OK;
1637
1638         /* check if we have a valid argument.
1639          */
1640         if( vt & VT_BYREF )
1641     {
1642         /* if by reference check that the type is in
1643          * the valid range and that it is not of empty or null type
1644          */
1645         if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
1646             ( vt & VT_TYPEMASK ) == VT_NULL ||
1647                         ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
1648                 {
1649                         res = DISP_E_BADVARTYPE;
1650                 }
1651                         
1652     }
1653     else
1654     {
1655         res = ValidateVtRange( vt );
1656     }
1657                 
1658         return res;
1659 }
1660
1661
1662
1663
1664
1665 /******************************************************************************
1666  *              VariantInit     [OLEAUT32.8]
1667  *
1668  * Initializes the Variant.  Unlike VariantClear it does not interpret the current
1669  * contents of the Variant.
1670  */
1671 void WINAPI VariantInit(VARIANTARG* pvarg)
1672 {
1673   TRACE("(%p),stub\n",pvarg);
1674
1675   memset(pvarg, 0, sizeof (VARIANTARG));
1676   pvarg->vt = VT_EMPTY;
1677
1678   return;
1679 }
1680
1681 /******************************************************************************
1682  *              VariantClear    [OLEAUT32.9]
1683  *
1684  * This function clears the VARIANT by setting the vt field to VT_EMPTY. It also
1685  * sets the wReservedX field to 0.      The current contents of the VARIANT are
1686  * freed.  If the vt is VT_BSTR the string is freed. If VT_DISPATCH the object is
1687  * released. If VT_ARRAY the array is freed.
1688  */
1689 HRESULT WINAPI VariantClear(VARIANTARG* pvarg)
1690 {
1691   HRESULT res = S_OK;
1692   TRACE("(%p)\n",pvarg);
1693
1694   res = ValidateVariantType( pvarg->vt );
1695   if( res == S_OK )
1696   {
1697     if( !( pvarg->vt & VT_BYREF ) )
1698     {
1699       /*
1700        * The VT_ARRAY flag is a special case of a safe array.
1701        */
1702       if ( (pvarg->vt & VT_ARRAY) != 0)
1703       {
1704         SafeArrayDestroy(pvarg->u.parray);
1705       }
1706       else
1707       {
1708         switch( pvarg->vt & VT_TYPEMASK )
1709         {
1710           case( VT_BSTR ):
1711             SysFreeString( pvarg->u.bstrVal );
1712             break;
1713           case( VT_DISPATCH ):
1714             if(pvarg->u.pdispVal!=NULL)
1715               ICOM_CALL(Release,pvarg->u.pdispVal);
1716             break;
1717           case( VT_VARIANT ):
1718             VariantClear(pvarg->u.pvarVal);
1719             break;
1720           case( VT_UNKNOWN ):
1721             if(pvarg->u.punkVal!=NULL)
1722               ICOM_CALL(Release,pvarg->u.punkVal);
1723             break;
1724           case( VT_SAFEARRAY ):
1725             SafeArrayDestroy(pvarg->u.parray);
1726             break;
1727           default:
1728             break;
1729         }
1730       }
1731     }
1732         
1733     /*
1734      * Empty all the fields and mark the type as empty.
1735      */
1736     memset(pvarg, 0, sizeof (VARIANTARG));
1737     pvarg->vt = VT_EMPTY;
1738   }
1739
1740   return res;
1741 }
1742
1743 /******************************************************************************
1744  *              VariantCopy     [OLEAUT32.10]
1745  *
1746  * Frees up the designation variant and makes a copy of the source.
1747  */
1748 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
1749 {
1750   HRESULT res = S_OK;
1751
1752   TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1753
1754   res = ValidateVariantType( pvargSrc->vt );
1755
1756   /* If the pointer are to the same variant we don't need
1757    * to do anything.
1758    */
1759   if( pvargDest != pvargSrc && res == S_OK )
1760   {
1761     res = VariantClear( pvargDest );
1762                 
1763     if( res == S_OK )
1764     {
1765       if( pvargSrc->vt & VT_BYREF )
1766       {
1767         /* In the case of byreference we only need
1768          * to copy the pointer.
1769          */
1770         pvargDest->u = pvargSrc->u;
1771         pvargDest->vt = pvargSrc->vt;
1772       }
1773       else
1774       {
1775         /*
1776          * The VT_ARRAY flag is another way to designate a safe array.
1777          */
1778         if (pvargSrc->vt & VT_ARRAY)
1779         {
1780           SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1781         }
1782         else
1783         {
1784           /* In the case of by value we need to
1785            * copy the actuall value. In the case of
1786            * VT_BSTR a copy of the string is made,
1787            * if VT_DISPATCH or VT_IUNKNOWN AddReff is
1788            * called to increment the object's reference count.
1789            */
1790           switch( pvargSrc->vt & VT_TYPEMASK )
1791           {
1792             case( VT_BSTR ):
1793               pvargDest->u.bstrVal = SysAllocString( pvargSrc->u.bstrVal );
1794               break;
1795             case( VT_DISPATCH ):
1796               pvargDest->u.pdispVal = pvargSrc->u.pdispVal;
1797               if (pvargDest->u.pdispVal!=NULL)
1798                 ICOM_CALL(AddRef,pvargDest->u.pdispVal);
1799               break;
1800             case( VT_VARIANT ):
1801               VariantCopy(pvargDest->u.pvarVal,pvargSrc->u.pvarVal);
1802               break;
1803             case( VT_UNKNOWN ):
1804               pvargDest->u.punkVal = pvargSrc->u.punkVal;
1805               if (pvargDest->u.pdispVal!=NULL)
1806                 ICOM_CALL(AddRef,pvargDest->u.punkVal);
1807               break;
1808             case( VT_SAFEARRAY ):
1809               SafeArrayCopy(pvargSrc->u.parray, &pvargDest->u.parray);
1810               break;
1811             default:
1812               pvargDest->u = pvargSrc->u;
1813               break;
1814           }
1815         }
1816         
1817         pvargDest->vt = pvargSrc->vt;
1818       }      
1819     }
1820   }
1821
1822   return res;
1823 }
1824
1825
1826 /******************************************************************************
1827  *              VariantCopyInd  [OLEAUT32.11]
1828  *
1829  * Frees up the destination variant and makes a copy of the source.  If
1830  * the source is of type VT_BYREF it performs the necessary indirections.
1831  */
1832 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
1833 {
1834   HRESULT res = S_OK;
1835
1836   TRACE("(%p, %p)\n", pvargDest, pvargSrc);
1837
1838   res = ValidateVariantType( pvargSrc->vt );
1839
1840   if( res != S_OK )
1841     return res;
1842   
1843   if( pvargSrc->vt & VT_BYREF )
1844   {
1845     VARIANTARG varg;
1846     VariantInit( &varg );
1847
1848     /* handle the in place copy.
1849      */
1850     if( pvargDest == pvargSrc )
1851     {
1852       /* we will use a copy of the source instead.
1853        */
1854       res = VariantCopy( &varg, pvargSrc );
1855       pvargSrc = &varg;
1856     }
1857
1858     if( res == S_OK )
1859     {
1860       res = VariantClear( pvargDest );
1861
1862       if( res == S_OK )
1863       {
1864         /*
1865          * The VT_ARRAY flag is another way to designate a safearray variant.
1866          */
1867         if ( pvargSrc->vt & VT_ARRAY)
1868         {
1869           SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1870         }
1871         else
1872         {
1873           /* In the case of by reference we need
1874            * to copy the date pointed to by the variant.
1875            */
1876
1877           /* Get the variant type.
1878            */
1879           switch( pvargSrc->vt & VT_TYPEMASK )
1880           {
1881             case( VT_BSTR ):
1882               pvargDest->u.bstrVal = SysAllocString( *(pvargSrc->u.pbstrVal) );
1883               break;
1884             case( VT_DISPATCH ):
1885               break;
1886             case( VT_VARIANT ):
1887               {
1888                 /* Prevent from cycling.  According to tests on
1889                  * VariantCopyInd in Windows and the documentation
1890                  * this API dereferences the inner Variants to only one depth.
1891                  * If the inner Variant itself contains an
1892                  * other inner variant the E_INVALIDARG error is
1893                  * returned. 
1894                  */
1895                 if( pvargSrc->wReserved1 & PROCESSING_INNER_VARIANT )
1896                 {
1897                   /* If we get here we are attempting to deference
1898                    * an inner variant that that is itself contained
1899                    * in an inner variant so report E_INVALIDARG error.
1900                    */
1901                   res = E_INVALIDARG;
1902                 }
1903                 else
1904                 {
1905                   /* Set the processing inner variant flag.
1906                    * We will set this flag in the inner variant
1907                    * that will be passed to the VariantCopyInd function.
1908                    */
1909                   (pvargSrc->u.pvarVal)->wReserved1 |= PROCESSING_INNER_VARIANT;
1910                   
1911                   /* Dereference the inner variant.
1912                    */
1913                   res = VariantCopyInd( pvargDest, pvargSrc->u.pvarVal );
1914                   /* We must also copy its type, I think.
1915                    */
1916                   pvargSrc->vt = pvargSrc->u.pvarVal->vt; 
1917                 }
1918               }
1919               break;
1920             case( VT_UNKNOWN ):
1921               break;
1922             case( VT_SAFEARRAY ):
1923               SafeArrayCopy(*pvargSrc->u.pparray, &pvargDest->u.parray);
1924               break;
1925             default:
1926               /* This is a by reference Variant which means that the union
1927                * part of the Variant contains a pointer to some data of
1928                * type "pvargSrc->vt & VT_TYPEMASK".
1929                * We will deference this data in a generic fashion using
1930                * the void pointer "Variant.u.byref".
1931                * We will copy this data into the union of the destination
1932                * Variant.
1933                */
1934               memcpy( &pvargDest->u, pvargSrc->u.byref, SizeOfVariantData( pvargSrc ) );
1935               break;
1936           }
1937         }
1938         
1939         pvargDest->vt = pvargSrc->vt & VT_TYPEMASK;
1940       }
1941     }
1942
1943     /* this should not fail.
1944      */
1945     VariantClear( &varg );
1946   }
1947   else
1948   {
1949     res = VariantCopy( pvargDest, pvargSrc );
1950   }
1951
1952   return res;
1953 }
1954
1955 /******************************************************************************
1956  *              VariantChangeType       [OLEAUT32.12]
1957  */
1958 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1959                                                         USHORT wFlags, VARTYPE vt)
1960 {
1961         return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
1962 }
1963
1964 /******************************************************************************
1965  *              VariantChangeTypeEx     [OLEAUT32.147]
1966  */
1967 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
1968                                                           LCID lcid, USHORT wFlags, VARTYPE vt)
1969 {
1970         HRESULT res = S_OK;
1971         VARIANTARG varg;
1972         VariantInit( &varg );
1973         
1974         TRACE("(%p, %p, %ld, %u, %u),stub\n", pvargDest, pvargSrc, lcid, wFlags, vt);
1975
1976         /* validate our source argument.
1977          */
1978         res = ValidateVariantType( pvargSrc->vt );
1979
1980         /* validate the vartype.
1981          */
1982         if( res == S_OK )
1983         {
1984                 res = ValidateVt( vt );
1985         }
1986
1987         /* if we are doing an in-place conversion make a copy of the source.
1988          */
1989         if( res == S_OK && pvargDest == pvargSrc )
1990         {
1991                 res = VariantCopy( &varg, pvargSrc );
1992                 pvargSrc = &varg;
1993         }
1994
1995         if( res == S_OK )
1996         {
1997                 /* free up the destination variant.
1998                  */
1999                 res = VariantClear( pvargDest );
2000         }
2001
2002         if( res == S_OK )
2003         {
2004                 if( pvargSrc->vt & VT_BYREF )
2005                 {
2006                         /* Convert the source variant to a "byvalue" variant.
2007                          */
2008                         VARIANTARG Variant;
2009                         VariantInit( &Variant );
2010                         res = VariantCopyInd( &Variant, pvargSrc );
2011                         if( res == S_OK )
2012                         {
2013                                 res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
2014                                 /* this should not fail.
2015                                  */
2016                                 VariantClear( &Variant );
2017                         }
2018         
2019                 }
2020                 else
2021                 {
2022                         /* Use the current "byvalue" source variant.
2023                          */
2024                         res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
2025                 }
2026         }
2027         /* this should not fail.
2028          */
2029         VariantClear( &varg );
2030         
2031         /* set the type of the destination
2032          */
2033         if ( res == S_OK )
2034                 pvargDest->vt = vt;
2035
2036         return res;
2037 }
2038
2039
2040
2041
2042 /******************************************************************************
2043  *              VarUI1FromI2            [OLEAUT32.130]
2044  */
2045 HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
2046 {
2047         TRACE("( %d, %p ), stub\n", sIn, pbOut );
2048
2049         /* Check range of value.
2050          */
2051         if( sIn < UI1_MIN || sIn > UI1_MAX )
2052         {
2053                 return DISP_E_OVERFLOW;
2054         }
2055
2056         *pbOut = (BYTE) sIn;
2057         
2058         return S_OK;
2059 }
2060
2061 /******************************************************************************
2062  *              VarUI1FromI4            [OLEAUT32.131]
2063  */
2064 HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
2065 {
2066         TRACE("( %ld, %p ), stub\n", lIn, pbOut );
2067
2068         /* Check range of value.
2069          */
2070         if( lIn < UI1_MIN || lIn > UI1_MAX )
2071         {
2072                 return DISP_E_OVERFLOW;
2073         }
2074
2075         *pbOut = (BYTE) lIn;
2076         
2077         return S_OK;
2078 }
2079
2080
2081 /******************************************************************************
2082  *              VarUI1FromR4            [OLEAUT32.132]
2083  */
2084 HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
2085 {
2086         TRACE("( %f, %p ), stub\n", fltIn, pbOut );
2087
2088         /* Check range of value.
2089      */
2090     fltIn = round( fltIn );
2091         if( fltIn < UI1_MIN || fltIn > UI1_MAX )
2092         {
2093                 return DISP_E_OVERFLOW;
2094         }
2095
2096         *pbOut = (BYTE) fltIn;
2097         
2098         return S_OK;
2099 }
2100
2101 /******************************************************************************
2102  *              VarUI1FromR8            [OLEAUT32.133]
2103  */
2104 HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
2105 {
2106         TRACE("( %f, %p ), stub\n", dblIn, pbOut );
2107
2108         /* Check range of value.
2109      */
2110     dblIn = round( dblIn );
2111         if( dblIn < UI1_MIN || dblIn > UI1_MAX )
2112         {
2113                 return DISP_E_OVERFLOW;
2114         }
2115
2116         *pbOut = (BYTE) dblIn;
2117
2118         return S_OK;
2119 }
2120
2121 /******************************************************************************
2122  *              VarUI1FromDate          [OLEAUT32.135]
2123  */
2124 HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
2125 {
2126         TRACE("( %f, %p ), stub\n", dateIn, pbOut );
2127
2128         /* Check range of value.
2129      */
2130     dateIn = round( dateIn );
2131         if( dateIn < UI1_MIN || dateIn > UI1_MAX )
2132         {
2133                 return DISP_E_OVERFLOW;
2134         }
2135
2136         *pbOut = (BYTE) dateIn;
2137
2138         return S_OK;
2139 }
2140
2141 /******************************************************************************
2142  *              VarUI1FromBool          [OLEAUT32.138]
2143  */
2144 HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
2145 {
2146         TRACE("( %d, %p ), stub\n", boolIn, pbOut );
2147
2148         *pbOut = (BYTE) boolIn;
2149
2150         return S_OK;
2151 }
2152
2153 /******************************************************************************
2154  *              VarUI1FromI1            [OLEAUT32.237]
2155  */
2156 HRESULT WINAPI VarUI1FromI1(CHAR cIn, BYTE* pbOut)
2157 {
2158         TRACE("( %c, %p ), stub\n", cIn, pbOut );
2159
2160         *pbOut = cIn;
2161
2162         return S_OK;
2163 }
2164
2165 /******************************************************************************
2166  *              VarUI1FromUI2           [OLEAUT32.238]
2167  */
2168 HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
2169 {
2170         TRACE("( %d, %p ), stub\n", uiIn, pbOut );
2171
2172         /* Check range of value.
2173          */
2174         if( uiIn > UI1_MAX )
2175         {
2176                 return DISP_E_OVERFLOW;
2177         }
2178
2179         *pbOut = (BYTE) uiIn;
2180
2181         return S_OK;
2182 }
2183
2184 /******************************************************************************
2185  *              VarUI1FromUI4           [OLEAUT32.239]
2186  */
2187 HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
2188 {
2189         TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
2190
2191         /* Check range of value.
2192          */
2193         if( ulIn > UI1_MAX )
2194         {
2195                 return DISP_E_OVERFLOW;
2196         }
2197
2198         *pbOut = (BYTE) ulIn;
2199
2200         return S_OK;
2201 }
2202
2203
2204 /******************************************************************************
2205  *              VarUI1FromStr           [OLEAUT32.54]
2206  */
2207 HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
2208 {
2209         double dValue = 0.0;
2210         LPSTR pNewString = NULL;
2211
2212         TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, pbOut );
2213
2214         /* Check if we have a valid argument
2215          */
2216         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2217         RemoveCharacterFromString( pNewString, "," );
2218         if( IsValidRealString( pNewString ) == FALSE )
2219         {
2220                 return DISP_E_TYPEMISMATCH;
2221         }
2222
2223         /* Convert the valid string to a floating point number.
2224          */
2225         dValue = atof( pNewString );
2226         
2227         /* We don't need the string anymore so free it.
2228          */
2229         HeapFree( GetProcessHeap(), 0 , pNewString );
2230
2231         /* Check range of value.
2232      */
2233     dValue = round( dValue );
2234         if( dValue < UI1_MIN || dValue > UI1_MAX )
2235         {
2236                 return DISP_E_OVERFLOW;
2237         }
2238
2239         *pbOut = (BYTE) dValue;
2240
2241         return S_OK;
2242 }
2243
2244 /**********************************************************************
2245  *              VarUI1FromCy [OLEAUT32.134]
2246  * Convert currency to unsigned char
2247  */
2248 HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
2249    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2250    
2251    if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
2252    
2253    *pbOut = (BYTE)t;
2254    return S_OK;
2255 }
2256
2257 /******************************************************************************
2258  *              VarI2FromUI1            [OLEAUT32.48]
2259  */
2260 HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
2261 {
2262         TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
2263
2264         *psOut = (short) bIn;
2265         
2266         return S_OK;
2267 }
2268
2269 /******************************************************************************
2270  *              VarI2FromI4             [OLEAUT32.49]
2271  */
2272 HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
2273 {
2274         TRACE("( %lx, %p ), stub\n", lIn, psOut );
2275
2276         /* Check range of value.
2277          */
2278         if( lIn < I2_MIN || lIn > I2_MAX )
2279         {
2280                 return DISP_E_OVERFLOW;
2281         }
2282
2283         *psOut = (short) lIn;
2284         
2285         return S_OK;
2286 }
2287
2288 /******************************************************************************
2289  *              VarI2FromR4             [OLEAUT32.50]
2290  */
2291 HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
2292 {
2293         TRACE("( %f, %p ), stub\n", fltIn, psOut );
2294
2295         /* Check range of value.
2296      */
2297     fltIn = round( fltIn );
2298         if( fltIn < I2_MIN || fltIn > I2_MAX )
2299         {
2300                 return DISP_E_OVERFLOW;
2301         }
2302
2303         *psOut = (short) fltIn;
2304
2305         return S_OK;
2306 }
2307
2308 /******************************************************************************
2309  *              VarI2FromR8             [OLEAUT32.51]
2310  */
2311 HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
2312 {
2313         TRACE("( %f, %p ), stub\n", dblIn, psOut );
2314
2315         /* Check range of value.
2316      */
2317     dblIn = round( dblIn );
2318         if( dblIn < I2_MIN || dblIn > I2_MAX )
2319         {
2320                 return DISP_E_OVERFLOW;
2321         }
2322
2323         *psOut = (short) dblIn;
2324
2325         return S_OK;
2326 }
2327
2328 /******************************************************************************
2329  *              VarI2FromDate           [OLEAUT32.53]
2330  */
2331 HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
2332 {
2333         TRACE("( %f, %p ), stub\n", dateIn, psOut );
2334
2335         /* Check range of value.
2336      */
2337     dateIn = round( dateIn );
2338         if( dateIn < I2_MIN || dateIn > I2_MAX )
2339         {
2340                 return DISP_E_OVERFLOW;
2341         }
2342
2343         *psOut = (short) dateIn;
2344
2345         return S_OK;
2346 }
2347
2348 /******************************************************************************
2349  *              VarI2FromBool           [OLEAUT32.56]
2350  */
2351 HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
2352 {
2353         TRACE("( %d, %p ), stub\n", boolIn, psOut );
2354
2355         *psOut = (short) boolIn;
2356
2357         return S_OK;
2358 }
2359
2360 /******************************************************************************
2361  *              VarI2FromI1             [OLEAUT32.48]
2362  */
2363 HRESULT WINAPI VarI2FromI1(CHAR cIn, short* psOut)
2364 {
2365         TRACE("( %c, %p ), stub\n", cIn, psOut );
2366
2367         *psOut = (short) cIn;
2368
2369         return S_OK;
2370 }
2371
2372 /******************************************************************************
2373  *              VarI2FromUI2            [OLEAUT32.206]
2374  */
2375 HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
2376 {
2377         TRACE("( %d, %p ), stub\n", uiIn, psOut );
2378
2379         /* Check range of value.
2380          */
2381         if( uiIn > I2_MAX )
2382         {
2383                 return DISP_E_OVERFLOW;
2384         }
2385
2386         *psOut = (short) uiIn;
2387
2388         return S_OK;
2389 }
2390
2391 /******************************************************************************
2392  *              VarI2FromUI4            [OLEAUT32.49]
2393  */
2394 HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
2395 {
2396         TRACE("( %lx, %p ), stub\n", ulIn, psOut );
2397
2398         /* Check range of value.
2399          */
2400         if( ulIn < I2_MIN || ulIn > I2_MAX )
2401         {
2402                 return DISP_E_OVERFLOW;
2403         }
2404
2405         *psOut = (short) ulIn;
2406
2407         return S_OK;
2408 }
2409
2410 /******************************************************************************
2411  *              VarI2FromStr            [OLEAUT32.54]
2412  */
2413 HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
2414 {
2415         double dValue = 0.0;
2416         LPSTR pNewString = NULL;
2417
2418         TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, psOut );
2419
2420         /* Check if we have a valid argument
2421          */
2422         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2423         RemoveCharacterFromString( pNewString, "," );
2424         if( IsValidRealString( pNewString ) == FALSE )
2425         {
2426                 return DISP_E_TYPEMISMATCH;
2427         }
2428
2429         /* Convert the valid string to a floating point number.
2430          */
2431         dValue = atof( pNewString );
2432         
2433         /* We don't need the string anymore so free it.
2434          */
2435         HeapFree( GetProcessHeap(), 0, pNewString );
2436
2437         /* Check range of value.
2438      */
2439     dValue = round( dValue );
2440         if( dValue < I2_MIN || dValue > I2_MAX )
2441         {
2442                 return DISP_E_OVERFLOW;
2443         }
2444
2445         *psOut = (short)  dValue;
2446
2447         return S_OK;
2448 }
2449
2450 /**********************************************************************
2451  *              VarI2FromCy [OLEAUT32.52]
2452  * Convert currency to signed short
2453  */
2454 HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
2455    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2456    
2457    if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
2458    
2459    *psOut = (SHORT)t;
2460    return S_OK;
2461 }
2462
2463 /******************************************************************************
2464  *              VarI4FromUI1            [OLEAUT32.58]
2465  */
2466 HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
2467 {
2468         TRACE("( %X, %p ), stub\n", bIn, plOut );
2469
2470         *plOut = (LONG) bIn;
2471
2472         return S_OK;
2473 }
2474
2475
2476 /******************************************************************************
2477  *              VarI4FromR4             [OLEAUT32.60]
2478  */
2479 HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
2480 {
2481         TRACE("( %f, %p ), stub\n", fltIn, plOut );
2482
2483         /* Check range of value.
2484      */
2485     fltIn = round( fltIn );
2486         if( fltIn < I4_MIN || fltIn > I4_MAX )
2487         {
2488                 return DISP_E_OVERFLOW;
2489         }
2490
2491         *plOut = (LONG) fltIn;
2492
2493         return S_OK;
2494 }
2495
2496 /******************************************************************************
2497  *              VarI4FromR8             [OLEAUT32.61]
2498  */
2499 HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
2500 {
2501         TRACE("( %f, %p ), stub\n", dblIn, plOut );
2502
2503         /* Check range of value.
2504      */
2505     dblIn = round( dblIn );
2506         if( dblIn < I4_MIN || dblIn > I4_MAX )
2507         {
2508                 return DISP_E_OVERFLOW;
2509         }
2510
2511         *plOut = (LONG) dblIn;
2512
2513         return S_OK;
2514 }
2515
2516 /******************************************************************************
2517  *              VarI4FromDate           [OLEAUT32.63]
2518  */
2519 HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
2520 {
2521         TRACE("( %f, %p ), stub\n", dateIn, plOut );
2522
2523         /* Check range of value.
2524      */
2525     dateIn = round( dateIn );
2526         if( dateIn < I4_MIN || dateIn > I4_MAX )
2527         {
2528                 return DISP_E_OVERFLOW;
2529         }
2530
2531         *plOut = (LONG) dateIn;
2532
2533         return S_OK;
2534 }
2535
2536 /******************************************************************************
2537  *              VarI4FromBool           [OLEAUT32.66]
2538  */
2539 HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
2540 {
2541         TRACE("( %d, %p ), stub\n", boolIn, plOut );
2542
2543         *plOut = (LONG) boolIn;
2544
2545         return S_OK;
2546 }
2547
2548 /******************************************************************************
2549  *              VarI4FromI1             [OLEAUT32.209]
2550  */
2551 HRESULT WINAPI VarI4FromI1(CHAR cIn, LONG* plOut)
2552 {
2553         TRACE("( %c, %p ), stub\n", cIn, plOut );
2554
2555         *plOut = (LONG) cIn;
2556
2557         return S_OK;
2558 }
2559
2560 /******************************************************************************
2561  *              VarI4FromUI2            [OLEAUT32.210]
2562  */
2563 HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
2564 {
2565         TRACE("( %d, %p ), stub\n", uiIn, plOut );
2566
2567         *plOut = (LONG) uiIn;
2568
2569         return S_OK;
2570 }
2571
2572 /******************************************************************************
2573  *              VarI4FromUI4            [OLEAUT32.211]
2574  */
2575 HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
2576 {
2577         TRACE("( %lx, %p ), stub\n", ulIn, plOut );
2578
2579         /* Check range of value.
2580          */
2581         if( ulIn < I4_MIN || ulIn > I4_MAX )
2582         {
2583                 return DISP_E_OVERFLOW;
2584         }
2585
2586         *plOut = (LONG) ulIn;
2587
2588         return S_OK;
2589 }
2590
2591 /******************************************************************************
2592  *              VarI4FromI2             [OLEAUT32.59]
2593  */
2594 HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
2595 {
2596         TRACE("( %d, %p ), stub\n", sIn, plOut );
2597
2598         *plOut = (LONG) sIn;
2599
2600         return S_OK;
2601 }
2602
2603 /******************************************************************************
2604  *              VarI4FromStr            [OLEAUT32.64]
2605  */
2606 HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
2607 {
2608         double dValue = 0.0;
2609         LPSTR pNewString = NULL;
2610
2611         TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
2612
2613         /* Check if we have a valid argument
2614          */
2615         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2616         RemoveCharacterFromString( pNewString, "," );
2617         if( IsValidRealString( pNewString ) == FALSE )
2618         {
2619                 return DISP_E_TYPEMISMATCH;
2620         }
2621
2622         /* Convert the valid string to a floating point number.
2623          */
2624         dValue = atof( pNewString );
2625         
2626         /* We don't need the string anymore so free it.
2627          */
2628         HeapFree( GetProcessHeap(), 0, pNewString );
2629
2630         /* Check range of value.
2631      */
2632     dValue = round( dValue );
2633         if( dValue < I4_MIN || dValue > I4_MAX )
2634         {
2635                 return DISP_E_OVERFLOW;
2636         }
2637
2638         *plOut = (LONG) dValue;
2639
2640         return S_OK;
2641 }
2642
2643 /**********************************************************************
2644  *              VarI4FromCy [OLEAUT32.62]
2645  * Convert currency to signed long
2646  */
2647 HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
2648    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2649    
2650    if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
2651    
2652    *plOut = (LONG)t;
2653    return S_OK;
2654 }
2655
2656 /******************************************************************************
2657  *              VarR4FromUI1            [OLEAUT32.68]
2658  */
2659 HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
2660 {
2661         TRACE("( %X, %p ), stub\n", bIn, pfltOut );
2662
2663         *pfltOut = (FLOAT) bIn;
2664
2665         return S_OK;
2666 }
2667
2668 /******************************************************************************
2669  *              VarR4FromI2             [OLEAUT32.69]
2670  */
2671 HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
2672 {
2673         TRACE("( %d, %p ), stub\n", sIn, pfltOut );
2674
2675         *pfltOut = (FLOAT) sIn;
2676
2677         return S_OK;
2678 }
2679
2680 /******************************************************************************
2681  *              VarR4FromI4             [OLEAUT32.70]
2682  */
2683 HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
2684 {
2685         TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
2686
2687         *pfltOut = (FLOAT) lIn;
2688
2689         return S_OK;
2690 }
2691
2692 /******************************************************************************
2693  *              VarR4FromR8             [OLEAUT32.71]
2694  */
2695 HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
2696 {
2697         TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
2698
2699         /* Check range of value.
2700          */
2701         if( dblIn < -(FLT_MAX) || dblIn > FLT_MAX )
2702         {
2703                 return DISP_E_OVERFLOW;
2704         }
2705
2706         *pfltOut = (FLOAT) dblIn;
2707
2708         return S_OK;
2709 }
2710
2711 /******************************************************************************
2712  *              VarR4FromDate           [OLEAUT32.73]
2713  */
2714 HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
2715 {
2716         TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
2717
2718         /* Check range of value.
2719          */
2720         if( dateIn < -(FLT_MAX) || dateIn > FLT_MAX )
2721         {
2722                 return DISP_E_OVERFLOW;
2723         }
2724
2725         *pfltOut = (FLOAT) dateIn;
2726
2727         return S_OK;
2728 }
2729
2730 /******************************************************************************
2731  *              VarR4FromBool           [OLEAUT32.76]
2732  */
2733 HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
2734 {
2735         TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
2736
2737         *pfltOut = (FLOAT) boolIn;
2738
2739         return S_OK;
2740 }
2741
2742 /******************************************************************************
2743  *              VarR4FromI1             [OLEAUT32.213]
2744  */
2745 HRESULT WINAPI VarR4FromI1(CHAR cIn, FLOAT* pfltOut)
2746 {
2747         TRACE("( %c, %p ), stub\n", cIn, pfltOut );
2748
2749         *pfltOut = (FLOAT) cIn;
2750
2751         return S_OK;
2752 }
2753
2754 /******************************************************************************
2755  *              VarR4FromUI2            [OLEAUT32.214]
2756  */
2757 HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
2758 {
2759         TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
2760
2761         *pfltOut = (FLOAT) uiIn;
2762
2763         return S_OK;
2764 }
2765
2766 /******************************************************************************
2767  *              VarR4FromUI4            [OLEAUT32.215]
2768  */
2769 HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
2770 {
2771         TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
2772
2773         *pfltOut = (FLOAT) ulIn;
2774
2775         return S_OK;
2776 }
2777
2778 /******************************************************************************
2779  *              VarR4FromStr            [OLEAUT32.74]
2780  */
2781 HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
2782 {
2783         double dValue = 0.0;
2784         LPSTR pNewString = NULL;
2785
2786         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pfltOut );
2787
2788         /* Check if we have a valid argument
2789          */
2790         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2791         RemoveCharacterFromString( pNewString, "," );
2792         if( IsValidRealString( pNewString ) == FALSE )
2793         {
2794                 return DISP_E_TYPEMISMATCH;
2795         }
2796
2797         /* Convert the valid string to a floating point number.
2798          */
2799         dValue = atof( pNewString );
2800         
2801         /* We don't need the string anymore so free it.
2802          */
2803         HeapFree( GetProcessHeap(), 0, pNewString );
2804
2805         /* Check range of value.
2806          */
2807         if( dValue < -(FLT_MAX) || dValue > FLT_MAX )
2808         {
2809                 return DISP_E_OVERFLOW;
2810         }
2811
2812         *pfltOut = (FLOAT) dValue;
2813
2814         return S_OK;
2815 }
2816
2817 /**********************************************************************
2818  *              VarR4FromCy [OLEAUT32.72]
2819  * Convert currency to float
2820  */
2821 HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
2822    *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2823    
2824    return S_OK;
2825 }
2826
2827 /******************************************************************************
2828  *              VarR8FromUI1            [OLEAUT32.68]
2829  */
2830 HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
2831 {
2832         TRACE("( %d, %p ), stub\n", bIn, pdblOut );
2833
2834         *pdblOut = (double) bIn;
2835
2836         return S_OK;
2837 }
2838
2839 /******************************************************************************
2840  *              VarR8FromI2             [OLEAUT32.69]
2841  */
2842 HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
2843 {
2844         TRACE("( %d, %p ), stub\n", sIn, pdblOut );
2845
2846         *pdblOut = (double) sIn;
2847
2848         return S_OK;
2849 }
2850
2851 /******************************************************************************
2852  *              VarR8FromI4             [OLEAUT32.70]
2853  */
2854 HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
2855 {
2856         TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
2857
2858         *pdblOut = (double) lIn;
2859
2860         return S_OK;
2861 }
2862
2863 /******************************************************************************
2864  *              VarR8FromR4             [OLEAUT32.81]
2865  */
2866 HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
2867 {
2868         TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
2869
2870         *pdblOut = (double) fltIn;
2871
2872         return S_OK;
2873 }
2874
2875 /******************************************************************************
2876  *              VarR8FromDate           [OLEAUT32.83]
2877  */
2878 HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
2879 {
2880         TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
2881
2882         *pdblOut = (double) dateIn;
2883
2884         return S_OK;
2885 }
2886
2887 /******************************************************************************
2888  *              VarR8FromBool           [OLEAUT32.86]
2889  */
2890 HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
2891 {
2892         TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
2893
2894         *pdblOut = (double) boolIn;
2895
2896         return S_OK;
2897 }
2898
2899 /******************************************************************************
2900  *              VarR8FromI1             [OLEAUT32.217]
2901  */
2902 HRESULT WINAPI VarR8FromI1(CHAR cIn, double* pdblOut)
2903 {
2904         TRACE("( %c, %p ), stub\n", cIn, pdblOut );
2905
2906         *pdblOut = (double) cIn;
2907
2908         return S_OK;
2909 }
2910
2911 /******************************************************************************
2912  *              VarR8FromUI2            [OLEAUT32.218]
2913  */
2914 HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
2915 {
2916         TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
2917
2918         *pdblOut = (double) uiIn;
2919
2920         return S_OK;
2921 }
2922
2923 /******************************************************************************
2924  *              VarR8FromUI4            [OLEAUT32.219]
2925  */
2926 HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
2927 {
2928         TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
2929
2930         *pdblOut = (double) ulIn;
2931
2932         return S_OK;
2933 }
2934
2935 /******************************************************************************
2936  *              VarR8FromStr            [OLEAUT32.84]
2937  */
2938 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
2939 {
2940         double dValue = 0.0;
2941         LPSTR pNewString = NULL;
2942
2943         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pdblOut );
2944
2945         /* Check if we have a valid argument
2946          */
2947         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
2948         RemoveCharacterFromString( pNewString, "," );
2949         if( IsValidRealString( pNewString ) == FALSE )
2950         {
2951                 return DISP_E_TYPEMISMATCH;
2952         }
2953
2954         /* Convert the valid string to a floating point number.
2955          */
2956         dValue = atof( pNewString );
2957         
2958         /* We don't need the string anymore so free it.
2959          */
2960         HeapFree( GetProcessHeap(), 0, pNewString );
2961
2962         *pdblOut = dValue;
2963
2964         return S_OK;
2965 }
2966
2967 /**********************************************************************
2968  *              VarR8FromCy [OLEAUT32.82]
2969  * Convert currency to double
2970  */
2971 HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
2972    *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
2973    
2974    return S_OK;
2975 }
2976
2977 /******************************************************************************
2978  *              VarDateFromUI1          [OLEAUT32.]
2979  */
2980 HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
2981 {
2982         TRACE("( %d, %p ), stub\n", bIn, pdateOut );
2983
2984         *pdateOut = (DATE) bIn;
2985
2986         return S_OK;
2987 }
2988
2989 /******************************************************************************
2990  *              VarDateFromI2           [OLEAUT32.222]
2991  */
2992 HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
2993 {
2994         TRACE("( %d, %p ), stub\n", sIn, pdateOut );
2995
2996         *pdateOut = (DATE) sIn;
2997
2998         return S_OK;
2999 }
3000
3001 /******************************************************************************
3002  *              VarDateFromI4           [OLEAUT32.90]
3003  */
3004 HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
3005 {
3006         TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
3007
3008         if( lIn < DATE_MIN || lIn > DATE_MAX )
3009         {
3010                 return DISP_E_OVERFLOW;
3011         }
3012
3013         *pdateOut = (DATE) lIn;
3014
3015         return S_OK;
3016 }
3017
3018 /******************************************************************************
3019  *              VarDateFromR4           [OLEAUT32.91]
3020  */
3021 HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
3022 {
3023     TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
3024
3025     if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
3026         {
3027                 return DISP_E_OVERFLOW;
3028         }
3029
3030         *pdateOut = (DATE) fltIn;
3031
3032         return S_OK;
3033 }
3034
3035 /******************************************************************************
3036  *              VarDateFromR8           [OLEAUT32.92]
3037  */
3038 HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
3039 {
3040     TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
3041
3042         if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
3043         {
3044                 return DISP_E_OVERFLOW;
3045         }
3046
3047         *pdateOut = (DATE) dblIn;
3048
3049         return S_OK;
3050 }
3051
3052 /******************************************************************************
3053  *              VarDateFromStr          [OLEAUT32.94]
3054  * The string representing the date is composed of two parts, a date and time.
3055  *
3056  * The format of the time is has follows:
3057  * hh[:mm][:ss][AM|PM]
3058  * Whitespace can be inserted anywhere between these tokens.  A whitespace consists
3059  * of space and/or tab characters, which are ignored.
3060  *
3061  * The formats for the date part are has follows:
3062  * mm/[dd/][yy]yy 
3063  * [dd/]mm/[yy]yy
3064  * [yy]yy/mm/dd 
3065  * January dd[,] [yy]yy
3066  * dd January [yy]yy
3067  * [yy]yy January dd
3068  * Whitespace can be inserted anywhere between these tokens.
3069  *
3070  * The formats for the date and time string are has follows.
3071  * date[whitespace][time] 
3072  * [time][whitespace]date
3073  *
3074  * These are the only characters allowed in a string representing a date and time:
3075  * [A-Z] [a-z] [0-9] ':' '-' '/' ',' ' ' '\t'
3076  */
3077 HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
3078 {
3079     HRESULT ret = S_OK;
3080     struct tm TM;
3081
3082     memset( &TM, 0, sizeof(TM) );
3083
3084     TRACE("( %p, %lx, %lx, %p ), stub\n", strIn, lcid, dwFlags, pdateOut );
3085
3086     if( DateTimeStringToTm( strIn, lcid, &TM ) )
3087     {
3088         if( TmToDATE( &TM, pdateOut ) == FALSE )
3089         {
3090             ret = E_INVALIDARG;
3091         }
3092     }
3093     else
3094     {
3095         ret = DISP_E_TYPEMISMATCH;
3096     }
3097
3098
3099         return ret;
3100 }
3101
3102 /******************************************************************************
3103  *              VarDateFromI1           [OLEAUT32.221]
3104  */
3105 HRESULT WINAPI VarDateFromI1(CHAR cIn, DATE* pdateOut)
3106 {
3107         TRACE("( %c, %p ), stub\n", cIn, pdateOut );
3108
3109         *pdateOut = (DATE) cIn;
3110
3111         return S_OK;
3112 }
3113
3114 /******************************************************************************
3115  *              VarDateFromUI2          [OLEAUT32.222]
3116  */
3117 HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
3118 {
3119         TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
3120
3121         if( uiIn > DATE_MAX )
3122         {
3123                 return DISP_E_OVERFLOW;
3124         }
3125
3126         *pdateOut = (DATE) uiIn;
3127
3128         return S_OK;
3129 }
3130
3131 /******************************************************************************
3132  *              VarDateFromUI4          [OLEAUT32.223]
3133  */
3134 HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
3135 {
3136         TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
3137
3138         if( ulIn < DATE_MIN || ulIn > DATE_MAX )
3139         {
3140                 return DISP_E_OVERFLOW;
3141         }
3142
3143         *pdateOut = (DATE) ulIn;
3144
3145         return S_OK;
3146 }
3147
3148 /******************************************************************************
3149  *              VarDateFromBool         [OLEAUT32.96]
3150  */
3151 HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
3152 {
3153         TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
3154
3155         *pdateOut = (DATE) boolIn;
3156
3157         return S_OK;
3158 }
3159
3160 /**********************************************************************
3161  *              VarDateFromCy [OLEAUT32.93]
3162  * Convert currency to date
3163  */
3164 HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
3165    *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3166
3167    if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
3168    return S_OK;
3169 }
3170
3171 /******************************************************************************
3172  *              VarBstrFromUI1          [OLEAUT32.108]
3173  */
3174 HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3175 {
3176         TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
3177         sprintf( pBuffer, "%d", bVal );
3178
3179         *pbstrOut =  StringDupAtoBstr( pBuffer );
3180         
3181         return S_OK;
3182 }
3183
3184 /******************************************************************************
3185  *              VarBstrFromI2           [OLEAUT32.109]
3186  */
3187 HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3188 {
3189         TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
3190         sprintf( pBuffer, "%d", iVal );
3191         *pbstrOut = StringDupAtoBstr( pBuffer );
3192
3193         return S_OK;
3194 }
3195
3196 /******************************************************************************
3197  *              VarBstrFromI4           [OLEAUT32.110]
3198  */
3199 HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3200 {
3201         TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
3202
3203         sprintf( pBuffer, "%ld", lIn );
3204         *pbstrOut = StringDupAtoBstr( pBuffer );
3205
3206         return S_OK;
3207 }
3208
3209 /******************************************************************************
3210  *              VarBstrFromR4           [OLEAUT32.111]
3211  */
3212 HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3213 {
3214         TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
3215
3216         sprintf( pBuffer, "%.7g", fltIn );
3217         *pbstrOut = StringDupAtoBstr( pBuffer );
3218
3219         return S_OK;
3220 }
3221
3222 /******************************************************************************
3223  *              VarBstrFromR8           [OLEAUT32.112]
3224  */
3225 HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3226 {
3227         TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
3228
3229         sprintf( pBuffer, "%.15g", dblIn );
3230         *pbstrOut = StringDupAtoBstr( pBuffer );
3231
3232         return S_OK;
3233 }
3234
3235 /******************************************************************************
3236  *    VarBstrFromCy   [OLEAUT32.113]
3237  */
3238 HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
3239                                 /* FIXME */
3240         return E_NOTIMPL;
3241 }
3242
3243  
3244 /******************************************************************************
3245  *              VarBstrFromDate         [OLEAUT32.114]
3246  *
3247  * The date is implemented using an 8 byte floating-point number.
3248  * Days are represented by whole numbers increments starting with 0.00 has
3249  * being December 30 1899, midnight.
3250  * The hours are expressed as the fractional part of the number.
3251  * December 30 1899 at midnight = 0.00
3252  * January 1 1900 at midnight = 2.00
3253  * January 4 1900 at 6 AM = 5.25
3254  * January 4 1900 at noon = 5.50
3255  * December 29 1899 at midnight = -1.00
3256  * December 18 1899 at midnight = -12.00
3257  * December 18 1899 at 6AM = -12.25
3258  * December 18 1899 at 6PM = -12.75
3259  * December 19 1899 at midnight = -11.00
3260  * The tm structure is as follows:
3261  * struct tm {
3262  *                int tm_sec;      seconds after the minute - [0,59]
3263  *                int tm_min;      minutes after the hour - [0,59]
3264  *                int tm_hour;     hours since midnight - [0,23]
3265  *                int tm_mday;     day of the month - [1,31]
3266  *                int tm_mon;      months since January - [0,11]
3267  *                int tm_year;     years
3268  *                int tm_wday;     days since Sunday - [0,6]
3269  *                int tm_yday;     days since January 1 - [0,365]
3270  *                int tm_isdst;    daylight savings time flag
3271  *                };
3272  */
3273 HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3274 {
3275     struct tm TM;
3276     memset( &TM, 0, sizeof(TM) );
3277
3278     TRACE("( %f, %ld, %ld, %p ), stub\n", dateIn, lcid, dwFlags, pbstrOut );
3279
3280     if( DateToTm( dateIn, lcid, &TM ) == FALSE )
3281                         {
3282         return E_INVALIDARG;
3283                 }
3284
3285     if( dwFlags & VAR_DATEVALUEONLY )
3286                         strftime( pBuffer, BUFFER_MAX, "%x", &TM );
3287     else if( dwFlags & VAR_TIMEVALUEONLY )
3288                         strftime( pBuffer, BUFFER_MAX, "%X", &TM );
3289                 else
3290         strftime( pBuffer, BUFFER_MAX, "%x %X", &TM );
3291
3292                 *pbstrOut = StringDupAtoBstr( pBuffer );
3293
3294         return S_OK;
3295 }
3296
3297 /******************************************************************************
3298  *              VarBstrFromBool         [OLEAUT32.116]
3299  */
3300 HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3301 {
3302         TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
3303
3304         if( boolIn == VARIANT_FALSE )
3305         {
3306                 sprintf( pBuffer, "False" );
3307         }
3308         else
3309         {
3310                 sprintf( pBuffer, "True" );
3311         }
3312
3313         *pbstrOut = StringDupAtoBstr( pBuffer );
3314
3315         return S_OK;
3316 }
3317
3318 /******************************************************************************
3319  *              VarBstrFromI1           [OLEAUT32.229]
3320  */
3321 HRESULT WINAPI VarBstrFromI1(CHAR cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3322 {
3323         TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
3324         sprintf( pBuffer, "%d", cIn );
3325         *pbstrOut = StringDupAtoBstr( pBuffer );
3326
3327         return S_OK;
3328 }
3329
3330 /******************************************************************************
3331  *              VarBstrFromUI2          [OLEAUT32.230]
3332  */
3333 HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3334 {
3335         TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
3336         sprintf( pBuffer, "%d", uiIn );
3337         *pbstrOut = StringDupAtoBstr( pBuffer );
3338
3339         return S_OK;
3340 }
3341
3342 /******************************************************************************
3343  *              VarBstrFromUI4          [OLEAUT32.231]
3344  */
3345 HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
3346 {
3347         TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
3348         sprintf( pBuffer, "%ld", ulIn );
3349         *pbstrOut = StringDupAtoBstr( pBuffer );
3350
3351         return S_OK;
3352 }
3353
3354 /******************************************************************************
3355  *              VarBoolFromUI1          [OLEAUT32.118]
3356  */
3357 HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
3358 {
3359         TRACE("( %d, %p ), stub\n", bIn, pboolOut );
3360
3361         if( bIn == 0 )
3362         {
3363                 *pboolOut = VARIANT_FALSE;
3364         }
3365         else
3366         {
3367                 *pboolOut = VARIANT_TRUE;
3368         }
3369
3370         return S_OK;
3371 }
3372
3373 /******************************************************************************
3374  *              VarBoolFromI2           [OLEAUT32.119]
3375  */
3376 HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
3377 {
3378         TRACE("( %d, %p ), stub\n", sIn, pboolOut );
3379
3380         if( sIn == 0 )
3381         {
3382                 *pboolOut = VARIANT_FALSE;
3383         }
3384         else
3385         {
3386                 *pboolOut = VARIANT_TRUE;
3387         }
3388
3389         return S_OK;
3390 }
3391
3392 /******************************************************************************
3393  *              VarBoolFromI4           [OLEAUT32.120]
3394  */
3395 HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
3396 {
3397         TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
3398
3399         if( lIn == 0 )
3400         {
3401                 *pboolOut = VARIANT_FALSE;
3402         }
3403         else
3404         {
3405                 *pboolOut = VARIANT_TRUE;
3406         }
3407
3408         return S_OK;
3409 }
3410
3411 /******************************************************************************
3412  *              VarBoolFromR4           [OLEAUT32.121]
3413  */
3414 HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
3415 {
3416         TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
3417
3418         if( fltIn == 0.0 )
3419         {
3420                 *pboolOut = VARIANT_FALSE;
3421         }
3422         else
3423         {
3424                 *pboolOut = VARIANT_TRUE;
3425         }
3426
3427         return S_OK;
3428 }
3429
3430 /******************************************************************************
3431  *              VarBoolFromR8           [OLEAUT32.122]
3432  */
3433 HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
3434 {
3435         TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
3436
3437         if( dblIn == 0.0 )
3438         {
3439                 *pboolOut = VARIANT_FALSE;
3440         }
3441         else
3442         {
3443                 *pboolOut = VARIANT_TRUE;
3444         }
3445
3446         return S_OK;
3447 }
3448
3449 /******************************************************************************
3450  *              VarBoolFromDate         [OLEAUT32.123]
3451  */
3452 HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
3453 {
3454         TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
3455
3456         if( dateIn == 0.0 )
3457         {
3458                 *pboolOut = VARIANT_FALSE;
3459         }
3460         else
3461         {
3462                 *pboolOut = VARIANT_TRUE;
3463         }
3464
3465         return S_OK;
3466 }
3467
3468 /******************************************************************************
3469  *              VarBoolFromStr          [OLEAUT32.125]
3470  */
3471 HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
3472 {
3473         HRESULT ret = S_OK;
3474         char* pNewString = NULL;
3475
3476         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
3477
3478     pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3479
3480         if( pNewString == NULL || strlen( pNewString ) == 0 )
3481         {
3482                 ret = DISP_E_TYPEMISMATCH;
3483         }
3484
3485         if( ret == S_OK )
3486         {
3487                 if( strncasecmp( pNewString, "True", strlen( pNewString ) ) == 0 )
3488                 {
3489                         *pboolOut = VARIANT_TRUE;
3490                 }
3491                 else if( strncasecmp( pNewString, "False", strlen( pNewString ) ) == 0 )
3492                 {
3493                         *pboolOut = VARIANT_FALSE;
3494                 }
3495                 else
3496                 {
3497                         /* Try converting the string to a floating point number.
3498                          */
3499                         double dValue = 0.0;
3500                         HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
3501                         if( res != S_OK )
3502                         {
3503                                 ret = DISP_E_TYPEMISMATCH;
3504                         }
3505                         else if( dValue == 0.0 )
3506                         {
3507                                 *pboolOut = VARIANT_FALSE;
3508                         }
3509                         else
3510                         {
3511                                 *pboolOut = VARIANT_TRUE;
3512                         }
3513                 }
3514         }
3515
3516         HeapFree( GetProcessHeap(), 0, pNewString );
3517         
3518         return ret;
3519 }
3520
3521 /******************************************************************************
3522  *              VarBoolFromI1           [OLEAUT32.233]
3523  */
3524 HRESULT WINAPI VarBoolFromI1(CHAR cIn, VARIANT_BOOL* pboolOut)
3525 {
3526         TRACE("( %c, %p ), stub\n", cIn, pboolOut );
3527
3528         if( cIn == 0 )
3529         {
3530                 *pboolOut = VARIANT_FALSE;
3531         }
3532         else
3533         {
3534                 *pboolOut = VARIANT_TRUE;
3535         }
3536
3537         return S_OK;
3538 }
3539
3540 /******************************************************************************
3541  *              VarBoolFromUI2          [OLEAUT32.234]
3542  */
3543 HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
3544 {
3545         TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
3546
3547         if( uiIn == 0 )
3548         {
3549                 *pboolOut = VARIANT_FALSE;
3550         }
3551         else
3552         {
3553                 *pboolOut = VARIANT_TRUE;
3554         }
3555
3556         return S_OK;
3557 }
3558
3559 /******************************************************************************
3560  *              VarBoolFromUI4          [OLEAUT32.235]
3561  */
3562 HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
3563 {
3564         TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
3565
3566         if( ulIn == 0 )
3567         {
3568                 *pboolOut = VARIANT_FALSE;
3569         }
3570         else
3571         {
3572                 *pboolOut = VARIANT_TRUE;
3573         }
3574
3575         return S_OK;
3576 }
3577
3578 /**********************************************************************
3579  *              VarBoolFromCy [OLEAUT32.124]
3580  * Convert currency to boolean
3581  */
3582 HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
3583       if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
3584       else *pboolOut = 0;
3585       
3586       return S_OK;
3587 }
3588
3589 /******************************************************************************
3590  *              VarI1FromUI1            [OLEAUT32.244]
3591  */
3592 HRESULT WINAPI VarI1FromUI1(BYTE bIn, CHAR* pcOut)
3593 {
3594         TRACE("( %d, %p ), stub\n", bIn, pcOut );
3595
3596         /* Check range of value.
3597          */
3598         if( bIn > CHAR_MAX )
3599         {
3600                 return DISP_E_OVERFLOW;
3601         }
3602
3603         *pcOut = (CHAR) bIn;
3604
3605         return S_OK;
3606 }
3607
3608 /******************************************************************************
3609  *              VarI1FromI2             [OLEAUT32.245]
3610  */
3611 HRESULT WINAPI VarI1FromI2(short uiIn, CHAR* pcOut)
3612 {
3613         TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3614
3615         if( uiIn > CHAR_MAX )
3616         {
3617                 return DISP_E_OVERFLOW;
3618         }
3619
3620         *pcOut = (CHAR) uiIn;
3621
3622         return S_OK;
3623 }
3624
3625 /******************************************************************************
3626  *              VarI1FromI4             [OLEAUT32.246]
3627  */
3628 HRESULT WINAPI VarI1FromI4(LONG lIn, CHAR* pcOut)
3629 {
3630         TRACE("( %ld, %p ), stub\n", lIn, pcOut );
3631
3632         if( lIn < CHAR_MIN || lIn > CHAR_MAX )
3633         {
3634                 return DISP_E_OVERFLOW;
3635         }
3636
3637         *pcOut = (CHAR) lIn;
3638
3639         return S_OK;
3640 }
3641
3642 /******************************************************************************
3643  *              VarI1FromR4             [OLEAUT32.247]
3644  */
3645 HRESULT WINAPI VarI1FromR4(FLOAT fltIn, CHAR* pcOut)
3646 {
3647         TRACE("( %f, %p ), stub\n", fltIn, pcOut );
3648
3649     fltIn = round( fltIn );
3650         if( fltIn < CHAR_MIN || fltIn > CHAR_MAX )
3651         {
3652                 return DISP_E_OVERFLOW;
3653         }
3654
3655         *pcOut = (CHAR) fltIn;
3656
3657         return S_OK;
3658 }
3659
3660 /******************************************************************************
3661  *              VarI1FromR8             [OLEAUT32.248]
3662  */
3663 HRESULT WINAPI VarI1FromR8(double dblIn, CHAR* pcOut)
3664 {
3665         TRACE("( %f, %p ), stub\n", dblIn, pcOut );
3666
3667     dblIn = round( dblIn );
3668     if( dblIn < CHAR_MIN || dblIn > CHAR_MAX )
3669         {
3670                 return DISP_E_OVERFLOW;
3671         }
3672
3673         *pcOut = (CHAR) dblIn;
3674
3675         return S_OK;
3676 }
3677
3678 /******************************************************************************
3679  *              VarI1FromDate           [OLEAUT32.249]
3680  */
3681 HRESULT WINAPI VarI1FromDate(DATE dateIn, CHAR* pcOut)
3682 {
3683         TRACE("( %f, %p ), stub\n", dateIn, pcOut );
3684
3685     dateIn = round( dateIn );
3686         if( dateIn < CHAR_MIN || dateIn > CHAR_MAX )
3687         {
3688                 return DISP_E_OVERFLOW;
3689         }
3690
3691         *pcOut = (CHAR) dateIn;
3692
3693         return S_OK;
3694 }
3695
3696 /******************************************************************************
3697  *              VarI1FromStr            [OLEAUT32.251]
3698  */
3699 HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CHAR* pcOut)
3700 {
3701         double dValue = 0.0;
3702         LPSTR pNewString = NULL;
3703
3704         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pcOut );
3705
3706         /* Check if we have a valid argument
3707          */
3708         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3709         RemoveCharacterFromString( pNewString, "," );
3710         if( IsValidRealString( pNewString ) == FALSE )
3711         {
3712                 return DISP_E_TYPEMISMATCH;
3713         }
3714
3715         /* Convert the valid string to a floating point number.
3716          */
3717         dValue = atof( pNewString );
3718   
3719         /* We don't need the string anymore so free it.
3720          */
3721         HeapFree( GetProcessHeap(), 0, pNewString );
3722
3723         /* Check range of value.
3724      */
3725     dValue = round( dValue );
3726         if( dValue < CHAR_MIN || dValue > CHAR_MAX )
3727         {
3728                 return DISP_E_OVERFLOW;
3729         }
3730
3731         *pcOut = (CHAR) dValue;
3732
3733         return S_OK;
3734 }
3735
3736 /******************************************************************************
3737  *              VarI1FromBool           [OLEAUT32.253]
3738  */
3739 HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, CHAR* pcOut)
3740 {
3741         TRACE("( %d, %p ), stub\n", boolIn, pcOut );
3742
3743         *pcOut = (CHAR) boolIn;
3744
3745         return S_OK;
3746 }
3747
3748 /******************************************************************************
3749  *              VarI1FromUI2            [OLEAUT32.254]
3750  */
3751 HRESULT WINAPI VarI1FromUI2(USHORT uiIn, CHAR* pcOut)
3752 {
3753         TRACE("( %d, %p ), stub\n", uiIn, pcOut );
3754
3755         if( uiIn > CHAR_MAX )
3756         {
3757                 return DISP_E_OVERFLOW;
3758         }
3759
3760         *pcOut = (CHAR) uiIn;
3761
3762         return S_OK;
3763 }
3764
3765 /******************************************************************************
3766  *              VarI1FromUI4            [OLEAUT32.255]
3767  */
3768 HRESULT WINAPI VarI1FromUI4(ULONG ulIn, CHAR* pcOut)
3769 {
3770         TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
3771
3772         if( ulIn > CHAR_MAX )
3773         {
3774                 return DISP_E_OVERFLOW;
3775         }
3776
3777         *pcOut = (CHAR) ulIn;
3778
3779         return S_OK;
3780 }
3781
3782 /**********************************************************************
3783  *              VarI1FromCy [OLEAUT32.250]
3784  * Convert currency to signed char
3785  */
3786 HRESULT WINAPI VarI1FromCy(CY cyIn, CHAR* pcOut) {
3787    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
3788    
3789    if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
3790    
3791    *pcOut = (CHAR)t;
3792    return S_OK;
3793 }
3794
3795 /******************************************************************************
3796  *              VarUI2FromUI1           [OLEAUT32.257]
3797  */
3798 HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
3799 {
3800         TRACE("( %d, %p ), stub\n", bIn, puiOut );
3801
3802         *puiOut = (USHORT) bIn;
3803
3804         return S_OK;
3805 }
3806
3807 /******************************************************************************
3808  *              VarUI2FromI2            [OLEAUT32.258]
3809  */
3810 HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
3811 {
3812         TRACE("( %d, %p ), stub\n", uiIn, puiOut );
3813
3814         if( uiIn < UI2_MIN )
3815         {
3816                 return DISP_E_OVERFLOW;
3817         }
3818
3819         *puiOut = (USHORT) uiIn;
3820
3821         return S_OK;
3822 }
3823
3824 /******************************************************************************
3825  *              VarUI2FromI4            [OLEAUT32.259]
3826  */
3827 HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
3828 {
3829         TRACE("( %ld, %p ), stub\n", lIn, puiOut );
3830
3831         if( lIn < UI2_MIN || lIn > UI2_MAX )
3832         {
3833                 return DISP_E_OVERFLOW;
3834         }
3835
3836         *puiOut = (USHORT) lIn;
3837
3838         return S_OK;
3839 }
3840
3841 /******************************************************************************
3842  *              VarUI2FromR4            [OLEAUT32.260]
3843  */
3844 HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
3845 {
3846         TRACE("( %f, %p ), stub\n", fltIn, puiOut );
3847
3848     fltIn = round( fltIn );
3849         if( fltIn < UI2_MIN || fltIn > UI2_MAX )
3850         {
3851                 return DISP_E_OVERFLOW;
3852         }
3853
3854         *puiOut = (USHORT) fltIn;
3855
3856         return S_OK;
3857 }
3858
3859 /******************************************************************************
3860  *              VarUI2FromR8            [OLEAUT32.261]
3861  */
3862 HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
3863 {
3864         TRACE("( %f, %p ), stub\n", dblIn, puiOut );
3865
3866     dblIn = round( dblIn );
3867     if( dblIn < UI2_MIN || dblIn > UI2_MAX )
3868         {
3869                 return DISP_E_OVERFLOW;
3870         }
3871
3872         *puiOut = (USHORT) dblIn;
3873
3874         return S_OK;
3875 }
3876
3877 /******************************************************************************
3878  *              VarUI2FromDate          [OLEAUT32.262]
3879  */
3880 HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
3881 {
3882         TRACE("( %f, %p ), stub\n", dateIn, puiOut );
3883
3884     dateIn = round( dateIn );
3885         if( dateIn < UI2_MIN || dateIn > UI2_MAX )
3886         {
3887                 return DISP_E_OVERFLOW;
3888         }
3889
3890         *puiOut = (USHORT) dateIn;
3891
3892         return S_OK;
3893 }
3894
3895 /******************************************************************************
3896  *              VarUI2FromStr           [OLEAUT32.264]
3897  */
3898 HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
3899 {
3900         double dValue = 0.0;
3901         LPSTR pNewString = NULL;
3902
3903         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, puiOut );
3904
3905         /* Check if we have a valid argument
3906          */
3907         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3908         RemoveCharacterFromString( pNewString, "," );
3909         if( IsValidRealString( pNewString ) == FALSE )
3910         {
3911                 return DISP_E_TYPEMISMATCH;
3912         }
3913
3914         /* Convert the valid string to a floating point number.
3915          */
3916         dValue = atof( pNewString );
3917   
3918         /* We don't need the string anymore so free it.
3919          */
3920         HeapFree( GetProcessHeap(), 0, pNewString );
3921
3922         /* Check range of value.
3923      */
3924     dValue = round( dValue );
3925         if( dValue < UI2_MIN || dValue > UI2_MAX )
3926         {
3927                 return DISP_E_OVERFLOW;
3928         }
3929
3930         *puiOut = (USHORT) dValue;
3931
3932         return S_OK;
3933 }
3934
3935 /******************************************************************************
3936  *              VarUI2FromBool          [OLEAUT32.266]
3937  */
3938 HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
3939 {
3940         TRACE("( %d, %p ), stub\n", boolIn, puiOut );
3941
3942         *puiOut = (USHORT) boolIn;
3943
3944         return S_OK;
3945 }
3946
3947 /******************************************************************************
3948  *              VarUI2FromI1            [OLEAUT32.267]
3949  */
3950 HRESULT WINAPI VarUI2FromI1(CHAR cIn, USHORT* puiOut)
3951 {
3952         TRACE("( %c, %p ), stub\n", cIn, puiOut );
3953
3954         *puiOut = (USHORT) cIn;
3955
3956         return S_OK;
3957 }
3958
3959 /******************************************************************************
3960  *              VarUI2FromUI4           [OLEAUT32.268]
3961  */
3962 HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
3963 {
3964         TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
3965
3966         if( ulIn < UI2_MIN || ulIn > UI2_MAX )
3967         {
3968                 return DISP_E_OVERFLOW;
3969         }
3970
3971         *puiOut = (USHORT) ulIn;
3972
3973         return S_OK;
3974 }
3975
3976 /******************************************************************************
3977  *              VarUI4FromStr           [OLEAUT32.277]
3978  */
3979 HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
3980 {
3981         double dValue = 0.0;
3982         LPSTR pNewString = NULL;
3983
3984         TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pulOut );
3985
3986         /* Check if we have a valid argument
3987          */
3988         pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, strIn );
3989         RemoveCharacterFromString( pNewString, "," );
3990         if( IsValidRealString( pNewString ) == FALSE )
3991         {
3992                 return DISP_E_TYPEMISMATCH;
3993         }
3994
3995         /* Convert the valid string to a floating point number.
3996          */
3997         dValue = atof( pNewString );
3998   
3999         /* We don't need the string anymore so free it.
4000          */
4001         HeapFree( GetProcessHeap(), 0, pNewString );
4002
4003         /* Check range of value.
4004      */
4005     dValue = round( dValue );
4006         if( dValue < UI4_MIN || dValue > UI4_MAX )
4007         {
4008                 return DISP_E_OVERFLOW;
4009         }
4010
4011         *pulOut = (ULONG) dValue;
4012
4013         return S_OK;
4014 }
4015
4016 /**********************************************************************
4017  *              VarUI2FromCy [OLEAUT32.263]
4018  * Convert currency to unsigned short
4019  */
4020 HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
4021    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4022    
4023    if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
4024       
4025    *pusOut = (USHORT)t;
4026    
4027    return S_OK;
4028 }
4029
4030 /******************************************************************************
4031  *              VarUI4FromUI1           [OLEAUT32.270]
4032  */
4033 HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
4034 {
4035         TRACE("( %d, %p ), stub\n", bIn, pulOut );
4036
4037         *pulOut = (USHORT) bIn;
4038
4039         return S_OK;
4040 }
4041
4042 /******************************************************************************
4043  *              VarUI4FromI2            [OLEAUT32.271]
4044  */
4045 HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
4046 {
4047         TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4048
4049         if( uiIn < UI4_MIN )
4050         {
4051                 return DISP_E_OVERFLOW;
4052         }
4053
4054         *pulOut = (ULONG) uiIn;
4055
4056         return S_OK;
4057 }
4058
4059 /******************************************************************************
4060  *              VarUI4FromI4            [OLEAUT32.272]
4061  */
4062 HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
4063 {
4064         TRACE("( %ld, %p ), stub\n", lIn, pulOut );
4065
4066         if( lIn < UI4_MIN )
4067         {
4068                 return DISP_E_OVERFLOW;
4069         }
4070
4071         *pulOut = (ULONG) lIn;
4072
4073         return S_OK;
4074 }
4075
4076 /******************************************************************************
4077  *              VarUI4FromR4            [OLEAUT32.273]
4078  */
4079 HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
4080 {
4081     fltIn = round( fltIn );
4082     if( fltIn < UI4_MIN || fltIn > UI4_MAX )
4083         {
4084                 return DISP_E_OVERFLOW;
4085         }
4086
4087         *pulOut = (ULONG) fltIn;
4088
4089         return S_OK;
4090 }
4091
4092 /******************************************************************************
4093  *              VarUI4FromR8            [OLEAUT32.274]
4094  */
4095 HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
4096 {
4097         TRACE("( %f, %p ), stub\n", dblIn, pulOut );
4098
4099     dblIn = round( dblIn );
4100         if( dblIn < UI4_MIN || dblIn > UI4_MAX )
4101         {
4102                 return DISP_E_OVERFLOW;
4103     }
4104
4105         *pulOut = (ULONG) dblIn;
4106
4107         return S_OK;
4108 }
4109
4110 /******************************************************************************
4111  *              VarUI4FromDate          [OLEAUT32.275]
4112  */
4113 HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
4114 {
4115         TRACE("( %f, %p ), stub\n", dateIn, pulOut );
4116
4117     dateIn = round( dateIn );
4118     if( dateIn < UI4_MIN || dateIn > UI4_MAX )
4119         {
4120                 return DISP_E_OVERFLOW;
4121         }
4122
4123         *pulOut = (ULONG) dateIn;
4124
4125         return S_OK;
4126 }
4127
4128 /******************************************************************************
4129  *              VarUI4FromBool          [OLEAUT32.279]
4130  */
4131 HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
4132 {
4133         TRACE("( %d, %p ), stub\n", boolIn, pulOut );
4134
4135         *pulOut = (ULONG) boolIn;
4136
4137         return S_OK;
4138 }
4139
4140 /******************************************************************************
4141  *              VarUI4FromI1            [OLEAUT32.280]
4142  */
4143 HRESULT WINAPI VarUI4FromI1(CHAR cIn, ULONG* pulOut)
4144 {
4145         TRACE("( %c, %p ), stub\n", cIn, pulOut );
4146
4147         *pulOut = (ULONG) cIn;
4148
4149         return S_OK;
4150 }
4151
4152 /******************************************************************************
4153  *              VarUI4FromUI2           [OLEAUT32.281]
4154  */
4155 HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
4156 {
4157         TRACE("( %d, %p ), stub\n", uiIn, pulOut );
4158
4159         *pulOut = (ULONG) uiIn;
4160
4161         return S_OK;
4162 }
4163
4164 /**********************************************************************
4165  *              VarUI4FromCy [OLEAUT32.276]
4166  * Convert currency to unsigned long
4167  */
4168 HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
4169    double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
4170    
4171    if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
4172
4173    *pulOut = (ULONG)t;
4174
4175    return S_OK;
4176 }
4177
4178 /**********************************************************************
4179  *              VarCyFromUI1 [OLEAUT32.98]
4180  * Convert unsigned char to currency
4181  */
4182 HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
4183    pcyOut->s.Hi = 0;
4184    pcyOut->s.Lo = ((ULONG)bIn) * 10000;
4185    
4186    return S_OK;
4187 }
4188
4189 /**********************************************************************
4190  *              VarCyFromI2 [OLEAUT32.99]
4191  * Convert signed short to currency
4192  */
4193 HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
4194    if (sIn < 0) pcyOut->s.Hi = -1;
4195    else pcyOut->s.Hi = 0;
4196    pcyOut->s.Lo = ((ULONG)sIn) * 10000;
4197    
4198    return S_OK;
4199 }
4200
4201 /**********************************************************************
4202  *              VarCyFromI4 [OLEAUT32.100]
4203  * Convert signed long to currency
4204  */
4205 HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
4206       double t = (double)lIn * (double)10000;
4207       pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4208       pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4209       if (lIn < 0) pcyOut->s.Hi--;
4210    
4211       return S_OK;
4212 }
4213
4214 /**********************************************************************
4215  *              VarCyFromR4 [OLEAUT32.101]
4216  * Convert float to currency
4217  */
4218 HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
4219    double t = round((double)fltIn * (double)10000);
4220    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4221    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4222    if (fltIn < 0) pcyOut->s.Hi--;
4223    
4224    return S_OK;
4225 }
4226
4227 /**********************************************************************
4228  *              VarCyFromR8 [OLEAUT32.102]
4229  * Convert double to currency
4230  */
4231 HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
4232    double t = round(dblIn * (double)10000);
4233    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4234    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4235    if (dblIn < 0) pcyOut->s.Hi--;
4236
4237    return S_OK;
4238 }
4239
4240 /**********************************************************************
4241  *              VarCyFromDate [OLEAUT32.103]
4242  * Convert date to currency
4243  */
4244 HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
4245    double t = round((double)dateIn * (double)10000);
4246    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4247    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4248    if (dateIn < 0) pcyOut->s.Hi--;
4249
4250    return S_OK;
4251 }
4252
4253 /**********************************************************************
4254  *              VarCyFromStr [OLEAUT32.104]
4255  */
4256 HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
4257                                 /* FIXME */
4258                 return E_NOTIMPL;
4259 }
4260
4261  
4262 /**********************************************************************
4263  *              VarCyFromBool [OLEAUT32.106]
4264  * Convert boolean to currency
4265  */
4266 HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
4267    if (boolIn < 0) pcyOut->s.Hi = -1;
4268    else pcyOut->s.Hi = 0;
4269    pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
4270    
4271    return S_OK;
4272 }
4273
4274 /**********************************************************************
4275  *              VarCyFromI1 [OLEAUT32.225]
4276  * Convert signed char to currency
4277  */
4278 HRESULT WINAPI VarCyFromI1(CHAR cIn, CY* pcyOut) {
4279    if (cIn < 0) pcyOut->s.Hi = -1;
4280    else pcyOut->s.Hi = 0;
4281    pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
4282    
4283    return S_OK;
4284 }
4285
4286 /**********************************************************************
4287  *              VarCyFromUI2 [OLEAUT32.226]
4288  * Convert unsigned short to currency
4289  */
4290 HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
4291    pcyOut->s.Hi = 0;
4292    pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
4293    
4294    return S_OK;
4295 }
4296
4297 /**********************************************************************
4298  *              VarCyFromUI4 [OLEAUT32.227]
4299  * Convert unsigned long to currency
4300  */
4301 HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
4302    double t = (double)ulIn * (double)10000;
4303    pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
4304    pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
4305       
4306    return S_OK;
4307 }
4308
4309
4310 /**********************************************************************
4311  *              DosDateTimeToVariantTime [OLEAUT32.14]
4312  * Convert dos representation of time to the date and time representation
4313  * stored in a variant.
4314  */
4315 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
4316                                     DATE *pvtime)
4317 {
4318     struct tm t;
4319
4320     TRACE("( 0x%x, 0x%x, 0x%p ), stub\n", wDosDate, wDosTime, pvtime );
4321     
4322     t.tm_sec = (wDosTime & 0x001f) * 2;
4323     t.tm_min = (wDosTime & 0x07e0) >> 5;
4324     t.tm_hour = (wDosTime & 0xf800) >> 11;
4325     
4326     t.tm_mday = (wDosDate & 0x001f);
4327     t.tm_mon = (wDosDate & 0x01e0) >> 5;
4328     t.tm_year = ((wDosDate & 0xfe00) >> 9) + 1980;
4329
4330     return TmToDATE( &t, pvtime );
4331 }
4332