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