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

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

Created (WINE Port of OLEAUT32)

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