source: trunk/src/oleaut32/variant.cpp@ 632

Last change on this file since 632 was 632, checked in by sandervl, 26 years ago

Created (WINE Port of OLEAUT32)

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