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

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

wine update

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