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

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

typelib updates

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