source: trunk/src/oleaut32/variant.c@ 5280

Last change on this file since 5280 was 4837, checked in by sandervl, 25 years ago

merged with Wine 12-22-2000

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