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

Last change on this file since 6507 was 6507, checked in by sandervl, 24 years ago

update

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