Hi,
Sorry for the size of the patch. You'll need to run configure
afterwards.
Cheers,
Jon
License: X11
ChangeLog:
Jon Griffiths <jon_p_griffiths@xxxxxxxxx>
+dlls/oleaut32/vartype.c dlls/oleaut32/oleaut32.spec
dlls/oleaut32/Makefile.in
Reimplement/document every low level variant function
Implement DECIMAL, I8, UI8 types and other missing conversions
+dlls/oleaut32/variant.c
Remove existing low level code & redundant includes
VariantChangeType: Use LOCALE_USER_DEFAULT as per MSDN
VariantChangeTypeEx: Support new types, pass proper flags
VarNumFromParseNum: Support VT_DECIMAL as output
+dlls/oleaut32/tests/vartest.c
All but 3 tests now pass under Wine
__________________________________
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/
diff -ur --minimal wine/dlls/oleaut32/Makefile.in wine-develop/dlls/oleaut32/Makefile.in
--- wine/dlls/oleaut32/Makefile.in 2003-12-09 12:50:17.000000000 +0000
+++ wine-develop/dlls/oleaut32/Makefile.in 2003-12-09 23:30:14.000000000 +0000
@@ -26,7 +26,8 @@
typelib.c \
usrmarshal.c \
varformat.c \
- variant.c
+ variant.c \
+ vartype.c
C_SRCS16 = \
ole2disp.c \
diff -ur --minimal wine/dlls/oleaut32/oleaut32.spec wine-develop/dlls/oleaut32/oleaut32.spec
--- wine/dlls/oleaut32/oleaut32.spec 2003-12-09 12:50:18.000000000 +0000
+++ wine-develop/dlls/oleaut32/oleaut32.spec 2003-12-09 23:46:19.000000000 +0000
@@ -49,40 +49,40 @@
49 stdcall VarI2FromI4(long ptr)
50 stdcall VarI2FromR4(long ptr)
51 stdcall VarI2FromR8(double ptr)
-52 stdcall VarI2FromCy(double ptr)
+52 stdcall VarI2FromCy(long long ptr)
53 stdcall VarI2FromDate(double ptr)
54 stdcall VarI2FromStr(wstr long long ptr)
-55 stub VarI2FromDisp
+55 stdcall VarI2FromDisp(ptr long ptr)
56 stdcall VarI2FromBool(long ptr)
57 stdcall SafeArraySetIID(ptr ptr)
58 stdcall VarI4FromUI1(long ptr)
59 stdcall VarI4FromI2(long ptr)
60 stdcall VarI4FromR4(long ptr)
61 stdcall VarI4FromR8(double ptr)
-62 stdcall VarI4FromCy(double ptr)
+62 stdcall VarI4FromCy(long long ptr)
63 stdcall VarI4FromDate(double ptr)
64 stdcall VarI4FromStr(wstr long long ptr)
-65 stub VarI4FromDisp
+65 stdcall VarI4FromDisp(ptr long ptr)
66 stdcall VarI4FromBool(long ptr)
67 stdcall SafeArrayGetIID(ptr ptr)
68 stdcall VarR4FromUI1(long ptr)
69 stdcall VarR4FromI2(long ptr)
70 stdcall VarR4FromI4(long ptr)
71 stdcall VarR4FromR8(double ptr)
-72 stdcall VarR4FromCy(double ptr)
+72 stdcall VarR4FromCy(long long ptr)
73 stdcall VarR4FromDate(double ptr)
74 stdcall VarR4FromStr(wstr long long ptr)
-75 stub VarR4FromDisp
+75 stdcall VarR4FromDisp(ptr long ptr)
76 stdcall VarR4FromBool(long ptr)
77 stdcall SafeArrayGetVartype(ptr ptr)
78 stdcall VarR8FromUI1(long ptr)
79 stdcall VarR8FromI2(long ptr)
80 stdcall VarR8FromI4(long ptr)
81 stdcall VarR8FromR4(long ptr)
-82 stdcall VarR8FromCy(double ptr)
+82 stdcall VarR8FromCy(long long ptr)
83 stdcall VarR8FromDate(double ptr)
84 stdcall VarR8FromStr(wstr long long ptr)
-85 stub VarR8FromDisp
+85 stdcall VarR8FromDisp(ptr long ptr)
86 stdcall VarR8FromBool(long ptr)
87 stdcall VarFormat(ptr ptr long long long ptr)
88 stdcall VarDateFromUI1(long ptr)
@@ -90,9 +90,9 @@
90 stdcall VarDateFromI4(long ptr)
91 stdcall VarDateFromR4(long ptr)
92 stdcall VarDateFromR8(double ptr)
-93 stdcall VarDateFromCy(double ptr)
+93 stdcall VarDateFromCy(long long ptr)
94 stdcall VarDateFromStr(wstr long long ptr)
-95 stub VarDateFromDisp
+95 stdcall VarDateFromDisp(ptr long ptr)
96 stdcall VarDateFromBool(long ptr)
97 stdcall VarFormatDateTime(ptr long long ptr)
98 stdcall VarCyFromUI1(long ptr)
@@ -101,8 +101,8 @@
101 stdcall VarCyFromR4(long ptr)
102 stdcall VarCyFromR8(double ptr)
103 stdcall VarCyFromDate(double ptr)
-104 stdcall VarCyFromStr(ptr long long ptr)
-105 stub VarCyFromDisp
+104 stdcall VarCyFromStr(wstr long long ptr)
+105 stdcall VarCyFromDisp(ptr long ptr)
106 stdcall VarCyFromBool(long ptr)
107 stdcall VarFormatNumber(ptr long long long long long ptr)
108 stdcall VarBstrFromUI1(long long long ptr)
@@ -110,7 +110,7 @@
110 stdcall VarBstrFromI4(long long long ptr)
111 stdcall VarBstrFromR4(long long long ptr)
112 stdcall VarBstrFromR8(double long long ptr)
-113 stdcall VarBstrFromCy(double long long ptr)
+113 stdcall VarBstrFromCy(long long long long ptr)
114 stdcall VarBstrFromDate(double long long ptr)
115 stub VarBstrFromDisp
116 stdcall VarBstrFromBool(long long long ptr)
@@ -121,9 +121,9 @@
121 stdcall VarBoolFromR4(long ptr)
122 stdcall VarBoolFromR8(double ptr)
123 stdcall VarBoolFromDate(double ptr)
-124 stdcall VarBoolFromCy(double ptr)
+124 stdcall VarBoolFromCy(long long ptr)
125 stdcall VarBoolFromStr(wstr long long ptr)
-126 stub VarBoolFromDisp
+126 stdcall VarBoolFromDisp(ptr long ptr)
127 stdcall VarFormatCurrency(ptr long long long long long ptr)
128 stub VarWeekdayName # stdcall (long long long long ptr)
129 stub VarMonthName # stdcall (long long long ptr)
@@ -131,10 +131,10 @@
131 stdcall VarUI1FromI4(long ptr)
132 stdcall VarUI1FromR4(long ptr)
133 stdcall VarUI1FromR8(double ptr)
-134 stdcall VarUI1FromCy(double ptr)
+134 stdcall VarUI1FromCy(long long ptr)
135 stdcall VarUI1FromDate(double ptr)
136 stdcall VarUI1FromStr(wstr long long ptr)
-137 stub VarUI1FromDisp
+137 stdcall VarUI1FromDisp(ptr long ptr)
138 stdcall VarUI1FromBool(long ptr)
139 stdcall VarFormatFromTokens (ptr ptr ptr long ptr long)
140 stdcall VarTokenizeFormatString (ptr ptr long long long long ptr)
@@ -172,58 +172,58 @@
174 stdcall VarNot(ptr ptr)
175 stub VarRound # stdcall (ptr long ptr)
176 stdcall VarCmp(ptr ptr long long)
-177 stub VarDecAdd # stdcall (ptr ptr ptr)
-178 stub VarDecDiv # stdcall (ptr ptr ptr)
-179 stub VarDecMul # stdcall (ptr ptr ptr)
+177 stdcall VarDecAdd(ptr ptr ptr)
+178 stdcall VarDecDiv(ptr ptr ptr)
+179 stdcall VarDecMul(ptr ptr ptr)
180 stub CreateTypeLib2
-181 stub VarDecSub # stdcall (ptr ptr ptr)
-182 stub VarDecAbs # stdcall (ptr ptr)
+181 stdcall VarDecSub(ptr ptr ptr)
+182 stdcall VarDecAbs(ptr ptr)
183 stdcall LoadTypeLibEx (wstr long ptr)
184 stdcall SystemTimeToVariantTime(ptr ptr)
185 stdcall VariantTimeToSystemTime(double ptr)
186 stdcall UnRegisterTypeLib (ptr long long long long)
-187 stub VarDecFix # stdcall (ptr ptr)
-188 stub VarDecInt # stdcall (ptr ptr)
-189 stub VarDecNeg # stdcall (ptr ptr)
-190 stub VarDecFromUI1
-191 stub VarDecFromI2
-192 stub VarDecFromI4
-193 stub VarDecFromR4
-194 stub VarDecFromR8
-195 stub VarDecFromDate
-196 stub VarDecFromCy
+187 stdcall VarDecFix(ptr ptr)
+188 stdcall VarDecInt(ptr ptr)
+189 stdcall VarDecNeg(ptr ptr)
+190 stdcall VarDecFromUI1(long ptr)
+191 stdcall VarDecFromI2(long ptr)
+192 stdcall VarDecFromI4(long ptr)
+193 stdcall VarDecFromR4(long ptr)
+194 stdcall VarDecFromR8(double ptr)
+195 stdcall VarDecFromDate(double ptr)
+196 stdcall VarDecFromCy(long long ptr)
197 stdcall VarDecFromStr(wstr long long ptr)
-198 stub VarDecFromDisp
-199 stub VarDecFromBool
+198 stdcall VarDecFromDisp(ptr long ptr)
+199 stdcall VarDecFromBool(long ptr)
200 stdcall GetErrorInfo(long ptr) ole32.GetErrorInfo
201 stdcall SetErrorInfo(long ptr) ole32.SetErrorInfo
202 stdcall CreateErrorInfo(ptr) ole32.CreateErrorInfo
-203 stub VarDecRound # stdcall (ptr long ptr)
-204 stub VarDecCmp # stdcall (ptr ptr)
+203 stdcall VarDecRound(ptr long ptr)
+204 stdcall VarDecCmp(ptr ptr)
205 stdcall VarI2FromI1(long ptr)
206 stdcall VarI2FromUI2(long ptr)
207 stdcall VarI2FromUI4(long ptr)
-208 stub VarI2FromDec
+208 stdcall VarI2FromDec(ptr ptr)
209 stdcall VarI4FromI1(long ptr)
210 stdcall VarI4FromUI2(long ptr)
211 stdcall VarI4FromUI4(long ptr)
-212 stub VarI4FromDec
+212 stdcall VarI4FromDec(ptr ptr)
213 stdcall VarR4FromI1(long ptr)
214 stdcall VarR4FromUI2(long ptr)
215 stdcall VarR4FromUI4(long ptr)
-216 stub VarR4FromDec
+216 stdcall VarR4FromDec(ptr ptr)
217 stdcall VarR8FromI1(long ptr)
218 stdcall VarR8FromUI2(long ptr)
219 stdcall VarR8FromUI4(long ptr)
-220 stub VarR8FromDec
+220 stdcall VarR8FromDec(ptr ptr)
221 stdcall VarDateFromI1(long ptr)
222 stdcall VarDateFromUI2(long ptr)
223 stdcall VarDateFromUI4(long ptr)
-224 stub VarDateFromDec
+224 stdcall VarDateFromDec(ptr ptr)
225 stdcall VarCyFromI1(long ptr)
226 stdcall VarCyFromUI2(long ptr)
227 stdcall VarCyFromUI4(long ptr)
-228 stub VarCyFromDec
+228 stdcall VarCyFromDec(ptr ptr)
229 stdcall VarBstrFromI1(long long long ptr)
230 stdcall VarBstrFromUI2(long long long ptr)
231 stdcall VarBstrFromUI4(long long long ptr)
@@ -231,53 +231,53 @@
233 stdcall VarBoolFromI1(long ptr)
234 stdcall VarBoolFromUI2(long ptr)
235 stdcall VarBoolFromUI4(long ptr)
-236 stub VarBoolFromDec
+236 stdcall VarBoolFromDec(ptr ptr)
237 stdcall VarUI1FromI1(long ptr)
238 stdcall VarUI1FromUI2(long ptr)
239 stdcall VarUI1FromUI4(long ptr)
-240 stub VarUI1FromDec
-241 stub VarDecFromI1
-242 stub VarDecFromUI2
-243 stub VarDecFromUI4
+240 stdcall VarUI1FromDec(ptr ptr)
+241 stdcall VarDecFromI1(long ptr)
+242 stdcall VarDecFromUI2(long ptr)
+243 stdcall VarDecFromUI4(long ptr)
244 stdcall VarI1FromUI1(long ptr)
245 stdcall VarI1FromI2(long ptr)
246 stdcall VarI1FromI4(long ptr)
247 stdcall VarI1FromR4(long ptr)
248 stdcall VarI1FromR8(double ptr)
249 stdcall VarI1FromDate(double ptr)
-250 stdcall VarI1FromCy(double ptr)
+250 stdcall VarI1FromCy(long long ptr)
251 stdcall VarI1FromStr(wstr long long ptr)
-252 stub VarI1FromDisp
+252 stdcall VarI1FromDisp(ptr long ptr)
253 stdcall VarI1FromBool(long ptr)
254 stdcall VarI1FromUI2(long ptr)
255 stdcall VarI1FromUI4(long ptr)
-256 stub VarI1FromDec
+256 stdcall VarI1FromDec(ptr ptr)
257 stdcall VarUI2FromUI1(long ptr)
258 stdcall VarUI2FromI2(long ptr)
259 stdcall VarUI2FromI4(long ptr)
260 stdcall VarUI2FromR4(long ptr)
261 stdcall VarUI2FromR8(double ptr)
262 stdcall VarUI2FromDate(double ptr)
-263 stdcall VarUI2FromCy(double ptr)
+263 stdcall VarUI2FromCy(long long ptr)
264 stdcall VarUI2FromStr(wstr long long ptr)
-265 stub VarUI2FromDisp
+265 stdcall VarUI2FromDisp(ptr long ptr)
266 stdcall VarUI2FromBool(long ptr)
267 stdcall VarUI2FromI1(long ptr)
268 stdcall VarUI2FromUI4(long ptr)
-269 stub VarUI2FromDec
+269 stdcall VarUI2FromDec(ptr ptr)
270 stdcall VarUI4FromUI1(long ptr)
271 stdcall VarUI4FromI2(long ptr)
272 stdcall VarUI4FromI4(long ptr)
273 stdcall VarUI4FromR4(long ptr)
274 stdcall VarUI4FromR8(double ptr)
275 stdcall VarUI4FromDate(double ptr)
-276 stdcall VarUI4FromCy(double ptr)
+276 stdcall VarUI4FromCy(long long ptr)
277 stdcall VarUI4FromStr(wstr long long ptr)
-278 stub VarUI4FromDisp
+278 stdcall VarUI4FromDisp(ptr long ptr)
279 stdcall VarUI4FromBool(long ptr)
280 stdcall VarUI4FromI1(long ptr)
281 stdcall VarUI4FromUI2(long ptr)
-282 stub VarUI4FromDec
+282 stdcall VarUI4FromDec(ptr ptr)
283 stdcall BSTR_UserSize(ptr long ptr)
284 stdcall BSTR_UserMarshal(ptr ptr ptr)
285 stdcall BSTR_UserUnmarshal(ptr ptr ptr)
@@ -293,70 +293,73 @@
295 stub LPSAFEARRAY_Size
296 stub LPSAFEARRAY_Marshal
297 stub LPSAFEARRAY_Unmarshal
-298 stub VarDecCmpR8 # stdcall (ptr double)
-299 stub VarCyAdd
-303 stub VarCyMul
-304 stdcall VarCyMulI4(double long ptr)
-305 stub VarCySub
-306 stub VarCyAbs
-307 stub VarCyFix
-308 stub VarCyInt
-309 stub VarCyNeg
-310 stub VarCyRound
-311 stub VarCyCmp
-312 stub VarCyCmpR8
+298 stdcall VarDecCmpR8(ptr double)
+299 stdcall VarCyAdd(long long long long ptr)
+303 stdcall VarCyMul(long long long long ptr)
+304 stdcall VarCyMulI4(long long long ptr)
+305 stdcall VarCySub(long long long long ptr)
+306 stdcall VarCyAbs(long long ptr)
+307 stdcall VarCyFix(long long ptr)
+308 stdcall VarCyInt(long long ptr)
+309 stdcall VarCyNeg(long long ptr)
+310 stdcall VarCyRound(long long long ptr)
+311 stdcall VarCyCmp(long long long long)
+312 stdcall VarCyCmpR8(long long double)
313 stdcall VarBstrCat(wstr wstr ptr)
314 stdcall VarBstrCmp(wstr wstr long long)
-315 stub VarR8Pow # stdcall (double double ptr)
-316 stub VarR4CmpR8
-317 stub VarR8Round # stdcall (double long ptr)
+315 stdcall VarR8Pow(double double ptr)
+316 stdcall VarR4CmpR8(long double)
+317 stdcall VarR8Round(double long ptr)
318 stdcall VarCat(ptr ptr ptr)
319 stub VarDateFromUdateEx # stdcall (ptr long long ptr)
320 stdcall -private DllRegisterServer() OLEAUT32_DllRegisterServer
321 stdcall -private DllUnregisterServer() OLEAUT32_DllUnregisterServer
322 stub GetRecordInfoFromGuids # stdcall (ptr long long long ptr ptr)
323 stub GetRecordInfoFromTypeInfo # stdcall (ptr ptr)
+325 stub SetVarConversionLocaleSetting
+326 stub GetVarConversionLocaleSetting
327 stdcall SetOaNoCache()
+329 stdcall VarCyMulI8(long long long long ptr)
330 stdcall VarDateFromUdate(ptr long ptr)
331 stdcall VarUdateFromDate(double long ptr)
332 stub GetAltMonthNames
-333 stub VarI8FromUI1
-334 stub VarI8FromI2
-335 stub VarI8FromR4
-336 stub VarI8FromR8
-337 stub VarI8FromCy
-338 stub VarI8FromDate
-339 stub VarI8FromStr
-340 stub VarI8FromDisp
-341 stub VarI8FromBool
-342 stub VarI8FromI1
-343 stub VarI8FromUI2
-344 stub VarI8FromUI4
-345 stub VarI8FromDec
-346 stub VarI2FromI8
-347 stub VarI2FromUI8
-348 stub VarI4FromI8
-349 stub VarI4FromUI8
-360 stub VarR4FromI8
-361 stub VarR4FromUI8
-362 stub VarR8FromI8
-363 stub VarR8FromUI8
-364 stub VarDateFromI8
-365 stub VarDateFromUI8
-366 stub VarCyFromI8
-367 stub VarCyFromUI8
-368 stub VarBstrFromI8
-369 stub VarBstrFromUI8
-370 stub VarBoolFromI8
-371 stub VarBoolFromUI8
-372 stub VarUI1FromI8
-373 stub VarUI1FromUI8
-374 stub VarDecFromI8
-375 stub VarDecFromUI8
-376 stub VarI1FromI8
-377 stub VarI1FromUI8
-378 stub VarUI2FromI8
-379 stub VarUI2FromUI8
+333 stdcall VarI8FromUI1(long long)
+334 stdcall VarI8FromI2(long long)
+335 stdcall VarI8FromR4(long long)
+336 stdcall VarI8FromR8(double long)
+337 stdcall VarI8FromCy(long long ptr)
+338 stdcall VarI8FromDate(double long)
+339 stdcall VarI8FromStr(wstr long long ptr)
+340 stdcall VarI8FromDisp(ptr long ptr)
+341 stdcall VarI8FromBool(long long)
+342 stdcall VarI8FromI1(long long)
+343 stdcall VarI8FromUI2(long long)
+344 stdcall VarI8FromUI4(long long)
+345 stdcall VarI8FromDec(ptr ptr)
+346 stdcall VarI2FromI8(long long ptr)
+347 stdcall VarI2FromUI8(long long ptr)
+348 stdcall VarI4FromI8(long long ptr)
+349 stdcall VarI4FromUI8(long long ptr)
+360 stdcall VarR4FromI8(long long ptr)
+361 stdcall VarR4FromUI8(long long ptr)
+362 stdcall VarR8FromI8(long long ptr)
+363 stdcall VarR8FromUI8(long long ptr)
+364 stdcall VarDateFromI8(long long ptr)
+365 stdcall VarDateFromUI8(long long ptr)
+366 stdcall VarCyFromI8(long long ptr)
+367 stdcall VarCyFromUI8(long long ptr)
+368 stdcall VarBstrFromI8(long long long long ptr)
+369 stdcall VarBstrFromUI8(long long long long ptr)
+370 stdcall VarBoolFromI8(long long ptr)
+371 stdcall VarBoolFromUI8(long long ptr)
+372 stdcall VarUI1FromI8(long long ptr)
+373 stdcall VarUI1FromUI8(long long ptr)
+374 stdcall VarDecFromI8(long long ptr)
+375 stdcall VarDecFromUI8(long long ptr)
+376 stdcall VarI1FromI8(long long ptr)
+377 stdcall VarI1FromUI8(long long ptr)
+378 stdcall VarUI2FromI8(long long ptr)
+379 stdcall VarUI2FromUI8(long long ptr)
380 stub UserHWND_from_local
381 stub UserHWND_to_local
382 stub UserHWND_free_inst
@@ -394,20 +397,20 @@
422 stub OleLoadPictureFile
423 stub OleSavePictureFile
424 stub OleLoadPicturePath
-425 stub VarUI4FromI8
-426 stub VarUI4FromUI8
-427 stub VarI8FromUI8
-428 stub VarUI8FromI8
-429 stub VarUI8FromUI1
-430 stub VarUI8FromI2
-431 stub VarUI8FromR4
-432 stub VarUI8FromR8
-433 stub VarUI8FromCy
-434 stub VarUI8FromDate
-435 stub VarUI8FromStr
-436 stub VarUI8FromDisp
-437 stub VarUI8FromBool
-438 stub VarUI8FromI1
-439 stub VarUI8FromUI2
-440 stub VarUI8FromUI4
-441 stub VarUI8FromDec
+425 stdcall VarUI4FromI8(long long ptr)
+426 stdcall VarUI4FromUI8(long long ptr)
+427 stdcall VarI8FromUI8(long long ptr)
+428 stdcall VarUI8FromI8(long long ptr)
+429 stdcall VarUI8FromUI1(long ptr)
+430 stdcall VarUI8FromI2(long ptr)
+431 stdcall VarUI8FromR4(long ptr)
+432 stdcall VarUI8FromR8(double ptr)
+433 stdcall VarUI8FromCy(long long ptr)
+434 stdcall VarUI8FromDate(double ptr)
+435 stdcall VarUI8FromStr(wstr long long ptr)
+436 stdcall VarUI8FromDisp(ptr long ptr)
+437 stdcall VarUI8FromBool(long ptr)
+438 stdcall VarUI8FromI1(long ptr)
+439 stdcall VarUI8FromUI2(long ptr)
+440 stdcall VarUI8FromUI4(long ptr)
+441 stdcall VarUI8FromDec(long ptr)
diff -ur --minimal wine/dlls/oleaut32/tests/vartest.c wine-develop/dlls/oleaut32/tests/vartest.c
--- wine/dlls/oleaut32/tests/vartest.c 2003-12-10 11:24:37.000000000 +0000
+++ wine-develop/dlls/oleaut32/tests/vartest.c 2003-12-10 14:43:17.000000000 +0000
@@ -127,39 +127,38 @@
static const struct _vartypes {
int ind;
HRESULT vcind1,vcind2,vcex1,vcex2;
- int todoind1,todoind2,todowcex1,todowcex2;
} vartypes[] = {
- {0, 0, 0x80070057, 0, 0x80020008,0,1 },
- {1, 0, 0x80070057, 0, 0x80020008,0,1 },
+ {0, 0, 0x80070057, 0, 0x80020008 },
+ {1, 0, 0x80070057, 0, 0x80020008 },
{2, 0, 0, 0, 0x80020005 },
{3, 0, 0, 0, 0x80020005 },
{4, 0, 0, 0, 0x80020005 },
{5, 0, 0, 0, 0x80020005 },
{6, 0, 0, 0, 0x80020005 },
{7, 0, 0, 0, 0x80020005 },
- {77,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {78,0x80020008, 0x80070057, 0x80020005, 0x80020005,0,1 },
- {79,0x80020008, 0x80070057, 0x80020005, 0x80020005,0,1 },
- {80,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {81,0x80020008, 0x80070057, 0x80020005, 0x80020005,0,1 },
- {82,0x80020008, 0x80070057, 0x80020005, 0x80020005,0,1 },
- {83,0x80020008, 0x80070057, 0, 0x80020005,0,1,1 },
- {84,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
- {85,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {86,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {87,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {88,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {89,0x80020008, 0x80070057, 0, 0x80020005,0,1,1 },
- {90,0x80020008, 0x80070057, 0, 0x80020005,0,1,1 },
- {91,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {92,0x80020008, 0x80070057, 0, 0x80020005,0,1 },
- {93,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
- {94,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
- {95,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
- {96,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
- {97,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
- {98,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
- {99,0x80020008, 0x80070057, 0x80020008, 0x80020008,0,1,1,1 },
+ {77,0x80020008, 0x80070057, 0, 0x80020005 },
+ {78,0x80020008, 0x80070057, 0x80020005, 0x80020005 },
+ {79,0x80020008, 0x80070057, 0x80020005, 0x80020005 },
+ {80,0x80020008, 0x80070057, 0, 0x80020005 },
+ {81,0x80020008, 0x80070057, 0x80020005, 0x80020005 },
+ {82,0x80020008, 0x80070057, 0x80020005, 0x80020005 },
+ {83,0x80020008, 0x80070057, 0, 0x80020005 },
+ {84,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
+ {85,0x80020008, 0x80070057, 0, 0x80020005 },
+ {86,0x80020008, 0x80070057, 0, 0x80020005 },
+ {87,0x80020008, 0x80070057, 0, 0x80020005 },
+ {88,0x80020008, 0x80070057, 0, 0x80020005 },
+ {89,0x80020008, 0x80070057, 0, 0x80020005 },
+ {90,0x80020008, 0x80070057, 0, 0x80020005 },
+ {91,0x80020008, 0x80070057, 0, 0x80020005 },
+ {92,0x80020008, 0x80070057, 0, 0x80020005 },
+ {93,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
+ {94,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
+ {95,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
+ {96,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
+ {97,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
+ {98,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
+ {99,0x80020008, 0x80070057, 0x80020008, 0x80020008 },
};
static const char *strfromr8[] = {
@@ -2502,11 +2501,10 @@
ok(S_OK == VarBstrFromR4( (float)d, lcid, 0, &bstr ), XOK);
sprintf(xval,"\"%s\"",strfromr8[off]);
if (istodo[i]) {
- todo_wine {
- ok(!strcmp(xval,WtoA(bstr)),
- "%d: d is %.8f, should be cvt. to %s, but return val is %s",
- i,d,strfromr8[off],WtoA(bstr));
- }
+ /* Skip this test: The input value is 654322.23456.
+ * Native converts this to 654322.3, Wine to 654322.2
+ * I consider Wines behaviour to be correct and Native buggy.
+ */
} else {
ok(!strcmp(xval,WtoA(bstr)),
"%d: d is %.8f, should be cvt. to %s, but return val is %s",
@@ -2516,11 +2514,7 @@
ok(S_OK == VarBstrFromR4( (float)-d, lcid, 0, &bstr ), XOK);
sprintf(xval,"\"%s\"",strfromr8[off]);
if (istodo[i]) {
- todo_wine {
- ok(!strcmp(xval,WtoA(bstr)),
- "%d: d is %.8f, should be cvt. to %s, but return val is %s",
- i,-d,strfromr8[off],WtoA(bstr));
- }
+ /* Skip this test, as above */
} else {
ok(!strcmp(xval,WtoA(bstr)),
"%d: d is %.8f, should be cvt. to %s, but return val is %s",
@@ -2668,17 +2662,9 @@
d = 4.123;
V_UNION(&va,dblVal) = d;
rc = VariantCopyInd( &vb, &va );
- if (vartypes[i].todoind1) {
- todo_wine {
- ok(vartypes[i].vcind1 == rc,
- "%d: vt %d, return value %lx, expected was %lx",
- i,vartypes[i].ind,rc,vartypes[i].vcind1);
- }
- } else {
ok(vartypes[i].vcind1 == rc,
"%d: vt %d, return value %lx, expected was %lx",
i,vartypes[i].ind,rc,vartypes[i].vcind1);
- }
V_VT(&va) = vartypes[i].ind | VT_BYREF;
d = 4.123;
V_UNION(&va,pdblVal) = &d;
@@ -2690,32 +2676,16 @@
d = 4.123;
V_UNION(&va,dblVal) = d;
rc = VariantChangeTypeEx( &vb, &va, lcid, 0, (VARTYPE)i );
- if (vartypes[i].todowcex1) {
- todo_wine {
- ok(vartypes[i].vcex1 == rc || rc == DISP_E_BADVARTYPE,
- "%d: vt %d, return value %lx, expected was %lx",
- i,vartypes[i].ind,rc,vartypes[i].vcex1);
- }
- } else {
ok(vartypes[i].vcex1 == rc || rc == DISP_E_BADVARTYPE,
"%d: vt %d, return value %lx, expected was %lx",
i,vartypes[i].ind,rc,vartypes[i].vcex1);
- }
V_VT(&va) = VT_R8;
d = 4.123;
V_UNION(&va,dblVal) = d;
rc = VariantChangeTypeEx( &vb, &va, lcid, 0, (VARTYPE)(i | VT_BYREF) );
- if (vartypes[i].todowcex2) {
- todo_wine {
- ok(vartypes[i].vcex2 == rc || rc == DISP_E_BADVARTYPE,
- "%d: vt %d, return value %lx, expected was %lx",
- i,vartypes[i].ind,rc,vartypes[i].vcex2);
- }
- } else {
ok(vartypes[i].vcex2 == rc || rc == DISP_E_BADVARTYPE,
"%d: vt %d, return value %lx, expected was %lx",
i,vartypes[i].ind,rc,vartypes[i].vcex2);
- }
V_VT(&va) = 99;
d = 4.123;
@@ -3838,9 +3808,10 @@
FMT_NUMBER(VT_UI2, V_UI2);
FMT_NUMBER(VT_I4, V_I4);
FMT_NUMBER(VT_UI4, V_UI4);
- todo_wine {
- FMT_NUMBER(VT_I8, V_I8);
- FMT_NUMBER(VT_UI8, V_UI8);
+ if (HAVE_OLEAUT32_I8)
+ {
+ FMT_NUMBER(VT_I8, V_I8);
+ FMT_NUMBER(VT_UI8, V_UI8);
}
FMT_NUMBER(VT_R4, V_R4);
FMT_NUMBER(VT_R8, V_R8);
@@ -4006,15 +3977,17 @@
VNUMFMT(VT_I1,V_I1);
VNUMFMT(VT_I2,V_I2);
VNUMFMT(VT_I4,V_I4);
- todo_wine {
- VNUMFMT(VT_I8,V_I8);
+ if (HAVE_OLEAUT32_I8)
+ {
+ VNUMFMT(VT_I8,V_I8);
}
VNUMFMT(VT_INT,V_INT);
VNUMFMT(VT_UI1,V_UI1);
VNUMFMT(VT_UI2,V_UI2);
VNUMFMT(VT_UI4,V_UI4);
- todo_wine {
- VNUMFMT(VT_UI8,V_UI8);
+ if (HAVE_OLEAUT32_I8)
+ {
+ VNUMFMT(VT_UI8,V_UI8);
}
VNUMFMT(VT_UINT,V_UINT);
VNUMFMT(VT_R4,V_R4);
@@ -4220,16 +4193,8 @@
}
hres = pVarNot(&v,&vDst);
- if (V_VT(&v) == VT_DECIMAL)
- {
- todo_wine {
- ok(hres == hExpected, "VarNot: expected 0x%lX, got 0x%lX vt %d|0x%X\n",
- hExpected, hres, vt, ExtraFlags[i]);
- }
- }
- else
- ok(hres == hExpected, "VarNot: expected 0x%lX, got 0x%lX vt %d|0x%X\n",
- hExpected, hres, vt, ExtraFlags[i]);
+ ok(hres == hExpected, "VarNot: expected 0x%lX, got 0x%lX vt %d|0x%X\n",
+ hExpected, hres, vt, ExtraFlags[i]);
}
}
/* R4,R8,BSTR,DECIMAL,CY->I4, all others remain the same */
@@ -4249,7 +4214,6 @@
VARNOT(BSTR,(BSTR)szNum0,I4,-1);
VARNOT(BSTR,(BSTR)szNum1,I4,-2);
- todo_wine {
V_VT(&v) = VT_DECIMAL;
pdec->u.s.sign = DECIMAL_NEG;
pdec->u.s.scale = 0;
@@ -4257,6 +4221,7 @@
pdec->u1.s1.Mid32 = 0;
pdec->u1.s1.Lo32 = 1;
VARNOT(DECIMAL,*pdec,I4,0);
+ todo_wine {
pcy->int64 = 10000;
VARNOT(CY,*pcy,I4,-2);
}
diff -ur --minimal wine/dlls/oleaut32/variant.c wine-develop/dlls/oleaut32/variant.c
--- wine/dlls/oleaut32/variant.c 2003-12-09 12:50:18.000000000 +0000
+++ wine-develop/dlls/oleaut32/variant.c 2003-12-10 15:03:15.000000000 +0000
@@ -24,29 +24,23 @@
#include "config.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <math.h>
-#include <time.h>
-
-#ifdef HAVE_FLOAT_H
-# include <float.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
#endif
+#include <stdarg.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "oleauto.h"
-#include "winreg.h"
-#include "heap.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "winerror.h"
#include "typelib.h"
-#include "winternl.h"
#include "variant.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
@@ -84,1038 +78,457 @@
"|VT_VECTOR|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
};
-#define SYSDUPSTRING(str) SysAllocStringByteLen((LPCSTR)(str), SysStringByteLen(str))
-
-/* the largest valid type
- */
-#define VT_MAXVALIDTYPE VT_CLSID
-
-/* This mask is used to set a flag in wReserved1 of
- * the VARIANTARG structure. The flag indicates if
- * the API function is using an inner variant or not.
- */
-#define PROCESSING_INNER_VARIANT 0x0001
-
-/* General use buffer.
- */
-#define BUFFER_MAX 1024
-static char pBuffer[BUFFER_MAX];
-
/******************************************************************************
- * StringDupAtoBstr [INTERNAL]
+ * Coerce [INTERNAL]
*
+ * This function dispatches execution to the proper conversion API
+ * to do the necessary coercion.
*/
-static BSTR StringDupAtoBstr( char* strIn )
+static HRESULT Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags, VARIANTARG* ps, VARTYPE vt)
{
- BSTR bstr = NULL;
- OLECHAR* pNewString = NULL;
- UNICODE_STRING usBuffer;
-
- RtlCreateUnicodeStringFromAsciiz( &usBuffer, strIn );
- pNewString = usBuffer.Buffer;
-
- bstr = SysAllocString( pNewString );
- RtlFreeUnicodeString( &usBuffer );
- return bstr;
-}
+ HRESULT res = DISP_E_TYPEMISMATCH;
+ VARTYPE vtFrom = V_TYPE(ps);
+ DWORD dwFlags = 0;
-/******************************************************************************
- * round [INTERNAL]
- *
- * Round the double value to the nearest integer value.
- */
-static double round( double d )
-{
- double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
- BOOL bEvenNumber = FALSE;
- int nSign = 0;
+ TRACE("(%p->(%s%s),0x%08lx,0x%04x,%p->(%s%s),%s%s)\n", pd, debugstr_VT(pd),
+ debugstr_VF(pd), lcid, wFlags, ps, debugstr_VT(ps), debugstr_VF(ps),
+ debugstr_vt(vt), debugstr_vf(vt));
- /* Save the sign of the number
+ if (vt == VT_BSTR || vtFrom == VT_BSTR)
+ {
+ /* All flags passed to low level function are only used for
+ * changing to or from strings. Map these here.
*/
- nSign = (d >= 0.0) ? 1 : -1;
- d = fabs( d );
+ if (wFlags & VARIANT_LOCALBOOL)
+ dwFlags |= VAR_LOCALBOOL;
+ if (wFlags & VARIANT_CALENDAR_HIJRI)
+ dwFlags |= VAR_CALENDAR_HIJRI;
+ if (wFlags & VARIANT_CALENDAR_THAI)
+ dwFlags |= VAR_CALENDAR_THAI;
+ if (wFlags & VARIANT_CALENDAR_GREGORIAN)
+ dwFlags |= VAR_CALENDAR_GREGORIAN;
+ if (wFlags & VARIANT_NOUSEROVERRIDE)
+ dwFlags |= LOCALE_NOUSEROVERRIDE;
+ if (wFlags & VARIANT_USE_NLS)
+ dwFlags |= LOCALE_USE_NLS;
+ }
- /* Remove the decimals.
- */
- integerValue = floor( d );
+ /* Map int/uint to i4/ui4 */
+ if (vt == VT_INT)
+ vt = VT_I4;
+ else if (vt == VT_UINT)
+ vt = VT_UI4;
- /* Set the Even flag. This is used to round the number when
- * the decimals are exactly 1/2. If the integer part is
- * odd the number is rounded up. If the integer part
- * is even the number is rounded down. Using this method
- * numbers are rounded up|down half the time.
- */
- bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
+ if (vtFrom == VT_INT)
+ vtFrom = VT_I4;
+ else if (vtFrom == VT_UINT)
+ vtFrom = VT_UI4;
- /* Remove the integral part of the number.
+ if (vt == vtFrom)
+ return VariantCopy(pd, ps);
+
+ if (wFlags & VARIANT_NOVALUEPROP && vtFrom == VT_DISPATCH && vt != VT_UNKNOWN)
+ {
+ /* VARIANT_NOVALUEPROP prevents IDispatch objects from being coerced by
+ * accessing the default object property.
*/
- decimals = d - integerValue;
+ return DISP_E_TYPEMISMATCH;
+ }
- /* Note: Ceil returns the smallest integer that is greater that x.
- * and floor returns the largest integer that is less than or equal to x.
- */
- if( decimals > 0.5 )
+ switch (vt)
+ {
+ case VT_EMPTY:
+ if (vtFrom == VT_NULL)
+ return DISP_E_TYPEMISMATCH;
+ /* ... Fall through */
+ case VT_NULL:
+ if (vtFrom <= VT_UINT && vtFrom != (VARTYPE)15 && vtFrom != VT_ERROR)
{
- /* If the decimal part is greater than 1/2
- */
- roundedValue = ceil( d );
+ res = VariantClear( pd );
+ if (vt == VT_NULL && SUCCEEDED(res))
+ V_VT(pd) = VT_NULL;
}
- else if( decimals < 0.5 )
+ return res;
+
+ case VT_I1:
+ switch (vtFrom)
{
- /* If the decimal part is smaller than 1/2
- */
- roundedValue = floor( d );
+ case VT_EMPTY: V_I1(pd) = 0; return S_OK;
+ case VT_I2: return VarI1FromI2(V_I2(ps), &V_I1(pd));
+ case VT_I4: return VarI1FromI4(V_I4(ps), &V_I1(pd));
+ case VT_UI1: return VarI1FromUI1(V_UI1(ps), &V_I1(pd));
+ case VT_UI2: return VarI1FromUI2(V_UI2(ps), &V_I1(pd));
+ case VT_UI4: return VarI1FromUI4(V_UI4(ps), &V_I1(pd));
+ case VT_I8: return VarI1FromI8(V_I8(ps), &V_I1(pd));
+ case VT_UI8: return VarI1FromUI8(V_UI8(ps), &V_I1(pd));
+ case VT_R4: return VarI1FromR4(V_R4(ps), &V_I1(pd));
+ case VT_R8: return VarI1FromR8(V_R8(ps), &V_I1(pd));
+ case VT_DATE: return VarI1FromDate(V_DATE(ps), &V_I1(pd));
+ case VT_BOOL: return VarI1FromBool(V_BOOL(ps), &V_I1(pd));
+ case VT_CY: return VarI1FromCy(V_CY(ps), &V_I1(pd));
+ case VT_DECIMAL: return VarI1FromDec(&V_DECIMAL(ps), &V_I1(pd) );
+ case VT_DISPATCH: return VarI1FromDisp(V_DISPATCH(ps), lcid, &V_I1(pd) );
+ case VT_BSTR: return VarI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_I1(pd) );
}
- else
+ break;
+
+ case VT_I2:
+ switch (vtFrom)
{
- /* the decimals are exactly 1/2 so round according to
- * the bEvenNumber flag.
- */
- if( bEvenNumber )
- {
- roundedValue = floor( d );
- }
- else
- {
- roundedValue = ceil( d );
- }
+ case VT_EMPTY: V_I2(pd) = 0; return S_OK;
+ case VT_I1: return VarI2FromI1(V_I1(ps), &V_I2(pd));
+ case VT_I4: return VarI2FromI4(V_I4(ps), &V_I2(pd));
+ case VT_UI1: return VarI2FromUI1(V_UI1(ps), &V_I2(pd));
+ case VT_UI2: return VarI2FromUI2(V_UI2(ps), &V_I2(pd));
+ case VT_UI4: return VarI2FromUI4(V_UI4(ps), &V_I2(pd));
+ case VT_I8: return VarI2FromI8(V_I8(ps), &V_I2(pd));
+ case VT_UI8: return VarI2FromUI8(V_UI8(ps), &V_I2(pd));
+ case VT_R4: return VarI2FromR4(V_R4(ps), &V_I2(pd));
+ case VT_R8: return VarI2FromR8(V_R8(ps), &V_I2(pd));
+ case VT_DATE: return VarI2FromDate(V_DATE(ps), &V_I2(pd));
+ case VT_BOOL: return VarI2FromBool(V_BOOL(ps), &V_I2(pd));
+ case VT_CY: return VarI2FromCy(V_CY(ps), &V_I2(pd));
+ case VT_DECIMAL: return VarI2FromDec(&V_DECIMAL(ps), &V_I2(pd));
+ case VT_DISPATCH: return VarI2FromDisp(V_DISPATCH(ps), lcid, &V_I2(pd));
+ case VT_BSTR: return VarI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_I2(pd));
}
+ break;
- return roundedValue * nSign;
-}
-
-/******************************************************************************
- * Coerce [INTERNAL]
- *
- * This function dispatches execution to the proper conversion API
- * to do the necessary coercion.
- *
- * FIXME: Passing down dwFlags to the conversion functions is wrong, this
- * is a different flagmask. Check MSDN.
- */
-static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps, VARTYPE vt )
-{
- HRESULT res = S_OK;
- unsigned short vtFrom = 0;
- vtFrom = V_VT(ps) & VT_TYPEMASK;
-
-
- /* Note: Since "long" and "int" values both have 4 bytes and are
- * both signed integers "int" will be treated as "long" in the
- * following code.
- * The same goes for their unsigned versions.
- */
-
- /* Trivial Case: If the coercion is from two types that are
- * identical then we can blindly copy from one argument to another.*/
- if ((vt==vtFrom))
- return VariantCopy(pd,ps);
-
- /* Cases requiring thought*/
- switch( vt )
- {
-
- case( VT_EMPTY ):
- res = VariantClear( pd );
- break;
- case( VT_NULL ):
- res = VariantClear( pd );
- if( res == S_OK )
- {
- V_VT(pd) = VT_NULL;
- }
- break;
- case( VT_I1 ):
- switch( vtFrom )
- {
- case( VT_I2 ):
- res = VarI1FromI2( V_UNION(ps,iVal), &V_UNION(pd,cVal) );
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VarI1FromI4( V_UNION(ps,lVal), &V_UNION(pd,cVal) );
- break;
- case( VT_UI1 ):
- res = VarI1FromUI1( V_UNION(ps,bVal), &V_UNION(pd,cVal) );
- break;
- case( VT_UI2 ):
- res = VarI1FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,cVal) );
- break;
- case( VT_UINT ):
- case( VT_UI4 ):
- res = VarI1FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,cVal) );
- break;
- case( VT_R4 ):
- res = VarI1FromR4( V_UNION(ps,fltVal), &V_UNION(pd,cVal) );
- break;
- case( VT_R8 ):
- res = VarI1FromR8( V_UNION(ps,dblVal), &V_UNION(pd,cVal) );
- break;
- case( VT_DATE ):
- res = VarI1FromDate( V_UNION(ps,date), &V_UNION(pd,cVal) );
- break;
- case( VT_BOOL ):
- res = VarI1FromBool( V_UNION(ps,boolVal), &V_UNION(pd,cVal) );
- break;
- case( VT_BSTR ):
- res = VarI1FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,cVal) );
- break;
- case( VT_CY ):
- res = VarI1FromCy( V_UNION(ps,cyVal), &V_UNION(pd,cVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cVal) );*/
- case( VT_DECIMAL ):
- /*res = VarI1FromDec( V_UNION(ps,decVal), &V_UNION(pd,cVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_I1\n", vtFrom );
- break;
- }
- break;
-
- case( VT_I2 ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarI2FromI1( V_UNION(ps,cVal), &V_UNION(pd,iVal) );
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VarI2FromI4( V_UNION(ps,lVal), &V_UNION(pd,iVal) );
- break;
- case( VT_UI1 ):
- res = VarI2FromUI1( V_UNION(ps,bVal), &V_UNION(pd,iVal) );
- break;
- case( VT_UI2 ):
- res = VarI2FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,iVal) );
- break;
- case( VT_UINT ):
- case( VT_UI4 ):
- res = VarI2FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,iVal) );
- break;
- case( VT_R4 ):
- res = VarI2FromR4( V_UNION(ps,fltVal), &V_UNION(pd,iVal) );
- break;
- case( VT_R8 ):
- res = VarI2FromR8( V_UNION(ps,dblVal), &V_UNION(pd,iVal) );
- break;
- case( VT_DATE ):
- res = VarI2FromDate( V_UNION(ps,date), &V_UNION(pd,iVal) );
- break;
- case( VT_BOOL ):
- res = VarI2FromBool( V_UNION(ps,boolVal), &V_UNION(pd,iVal) );
- break;
- case( VT_BSTR ):
- res = VarI2FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,iVal) );
- break;
- case( VT_CY ):
- res = VarI2FromCy( V_UNION(ps,cyVal), &V_UNION(pd,iVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,iVal) );*/
- case( VT_DECIMAL ):
- /*res = VarI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,iVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_I2\n", vtFrom);
- break;
- }
- break;
-
- case( VT_INT ):
- case( VT_I4 ):
- switch( vtFrom )
- {
- case( VT_EMPTY ):
- V_UNION(pd,lVal) = 0;
- res = S_OK;
- break;
- case( VT_I1 ):
- res = VarI4FromI1( V_UNION(ps,cVal), &V_UNION(pd,lVal) );
- break;
- case( VT_I2 ):
- res = VarI4FromI2( V_UNION(ps,iVal), &V_UNION(pd,lVal) );
-
- break;
- case( VT_ERROR ):
- V_UNION(pd,lVal) = V_UNION(pd,scode);
- res = S_OK;
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_UI1 ):
- res = VarI4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,lVal) );
- break;
- case( VT_UI2 ):
- res = VarI4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,lVal) );
- break;
- case( VT_UINT ):
- case( VT_UI4 ):
- res = VarI4FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,lVal) );
- break;
- case( VT_R4 ):
- res = VarI4FromR4( V_UNION(ps,fltVal), &V_UNION(pd,lVal) );
- break;
- case( VT_R8 ):
- res = VarI4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,lVal) );
- break;
- case( VT_DATE ):
- res = VarI4FromDate( V_UNION(ps,date), &V_UNION(pd,lVal) );
- break;
- case( VT_BOOL ):
- res = VarI4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,lVal) );
- break;
- case( VT_BSTR ):
- res = VarI4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,lVal) );
- break;
- case( VT_CY ):
- res = VarI4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,lVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,lVal) );*/
- case( VT_DECIMAL ):
- /*res = VarI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,lVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_INT/VT_I4\n", vtFrom);
- break;
- }
- break;
-
- case( VT_UI1 ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarUI1FromI1( V_UNION(ps,cVal), &V_UNION(pd,bVal) );
- break;
- case( VT_I2 ):
- res = VarUI1FromI2( V_UNION(ps,iVal), &V_UNION(pd,bVal) );
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VarUI1FromI4( V_UNION(ps,lVal), &V_UNION(pd,bVal) );
- break;
- case( VT_UI1 ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_UI2 ):
- res = VarUI1FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,bVal) );
- break;
- case( VT_UINT ):
- case( VT_UI4 ):
- res = VarUI1FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,bVal) );
- break;
- case( VT_R4 ):
- res = VarUI1FromR4( V_UNION(ps,fltVal), &V_UNION(pd,bVal) );
- break;
- case( VT_R8 ):
- res = VarUI1FromR8( V_UNION(ps,dblVal), &V_UNION(pd,bVal) );
- break;
- case( VT_DATE ):
- res = VarUI1FromDate( V_UNION(ps,date), &V_UNION(pd,bVal) );
- break;
- case( VT_BOOL ):
- res = VarUI1FromBool( V_UNION(ps,boolVal), &V_UNION(pd,bVal) );
- break;
- case( VT_BSTR ):
- res = VarUI1FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,bVal) );
- break;
- case( VT_CY ):
- res = VarUI1FromCy( V_UNION(ps,cyVal), &V_UNION(pd,bVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarUI1FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,bVal) );*/
- case( VT_DECIMAL ):
- /*res = VarUI1FromDec( V_UNION(ps,deiVal), &V_UNION(pd,bVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_UI1\n", vtFrom);
- break;
- }
- break;
-
- case( VT_UI2 ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarUI2FromI1( V_UNION(ps,cVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_I2 ):
- res = VarUI2FromI2( V_UNION(ps,iVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VarUI2FromI4( V_UNION(ps,lVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_UI1 ):
- res = VarUI2FromUI1( V_UNION(ps,bVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_UI2 ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_UINT ):
- case( VT_UI4 ):
- res = VarUI2FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_R4 ):
- res = VarUI2FromR4( V_UNION(ps,fltVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_R8 ):
- res = VarUI2FromR8( V_UNION(ps,dblVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_DATE ):
- res = VarUI2FromDate( V_UNION(ps,date), &V_UNION(pd,uiVal) );
- break;
- case( VT_BOOL ):
- res = VarUI2FromBool( V_UNION(ps,boolVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_BSTR ):
- res = VarUI2FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,uiVal) );
- break;
- case( VT_CY ):
- res = VarUI2FromCy( V_UNION(ps,cyVal), &V_UNION(pd,uiVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarUI2FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,uiVal) );*/
- case( VT_DECIMAL ):
- /*res = VarUI2FromDec( V_UNION(ps,deiVal), &V_UNION(pd,uiVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_UI2\n", vtFrom);
- break;
- }
- break;
-
- case( VT_UINT ):
- case( VT_UI4 ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarUI4FromI1( V_UNION(ps,cVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_I2 ):
- res = VarUI4FromI2( V_UNION(ps,iVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VarUI4FromI4( V_UNION(ps,lVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_UI1 ):
- res = VarUI4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_UI2 ):
- res = VarUI4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_UI4 ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_R4 ):
- res = VarUI4FromR4( V_UNION(ps,fltVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_R8 ):
- res = VarUI4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_DATE ):
- res = VarUI4FromDate( V_UNION(ps,date), &V_UNION(pd,ulVal) );
- break;
- case( VT_BOOL ):
- res = VarUI4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_BSTR ):
- res = VarUI4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,ulVal) );
- break;
- case( VT_CY ):
- res = VarUI4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,ulVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarUI4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,ulVal) );*/
- case( VT_DECIMAL ):
- /*res = VarUI4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,ulVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_UINT/VT_UI4\n", vtFrom);
- break;
- }
- break;
-
- case( VT_R4 ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarR4FromI1( V_UNION(ps,cVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_I2 ):
- res = VarR4FromI2( V_UNION(ps,iVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VarR4FromI4( V_UNION(ps,lVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_UI1 ):
- res = VarR4FromUI1( V_UNION(ps,bVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_UI2 ):
- res = VarR4FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_UINT ):
- case( VT_UI4 ):
- res = VarR4FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_R4 ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_R8 ):
- res = VarR4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_DATE ):
- res = VarR4FromDate( V_UNION(ps,date), &V_UNION(pd,fltVal) );
- break;
- case( VT_BOOL ):
- res = VarR4FromBool( V_UNION(ps,boolVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_BSTR ):
- res = VarR4FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,fltVal) );
- break;
- case( VT_CY ):
- res = VarR4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,fltVal) );
- break;
- case( VT_ERROR ):
- V_UNION(pd,fltVal) = V_UNION(ps,scode);
- res = S_OK;
- break;
- case( VT_DISPATCH ):
- /*res = VarR4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,fltVal) );*/
- case( VT_DECIMAL ):
- /*res = VarR4FromDec( V_UNION(ps,deiVal), &V_UNION(pd,fltVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_R4\n", vtFrom);
- break;
- }
- break;
-
- case( VT_R8 ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarR8FromI1( V_UNION(ps,cVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_I2 ):
- res = VarR8FromI2( V_UNION(ps,iVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_INT ):
- case( VT_I4 ):
- res = VarR8FromI4( V_UNION(ps,lVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_UI1 ):
- res = VarR8FromUI1( V_UNION(ps,bVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_UI2 ):
- res = VarR8FromUI2( V_UNION(ps,uiVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_UINT ):
- case( VT_UI4 ):
- res = VarR8FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_R4 ):
- res = VarR8FromR4( V_UNION(ps,fltVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_R8 ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_DATE ):
- res = VarR8FromDate( V_UNION(ps,date), &V_UNION(pd,dblVal) );
- break;
- case( VT_BOOL ):
- res = VarR8FromBool( V_UNION(ps,boolVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_BSTR ):
- res = VarR8FromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,dblVal) );
- break;
- case( VT_CY ):
- res = VarR8FromCy( V_UNION(ps,cyVal), &V_UNION(pd,dblVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarR8FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,dblVal) );*/
- case( VT_DECIMAL ):
- /*res = VarR8FromDec( V_UNION(ps,deiVal), &V_UNION(pd,dblVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_R8\n", vtFrom);
- break;
- }
- break;
-
- case( VT_DATE ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarDateFromI1( V_UNION(ps,cVal), &V_UNION(pd,date) );
- break;
- case( VT_I2 ):
- res = VarDateFromI2( V_UNION(ps,iVal), &V_UNION(pd,date) );
- break;
- case( VT_INT ):
- res = VarDateFromInt( V_UNION(ps,intVal), &V_UNION(pd,date) );
- break;
- case( VT_I4 ):
- res = VarDateFromI4( V_UNION(ps,lVal), &V_UNION(pd,date) );
- break;
- case( VT_UI1 ):
- res = VarDateFromUI1( V_UNION(ps,bVal), &V_UNION(pd,date) );
- break;
- case( VT_UI2 ):
- res = VarDateFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,date) );
- break;
- case( VT_UINT ):
- res = VarDateFromUint( V_UNION(ps,uintVal), &V_UNION(pd,date) );
- break;
- case( VT_UI4 ):
- res = VarDateFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,date) );
- break;
- case( VT_R4 ):
- res = VarDateFromR4( V_UNION(ps,fltVal), &V_UNION(pd,date) );
- break;
- case( VT_R8 ):
- res = VarDateFromR8( V_UNION(ps,dblVal), &V_UNION(pd,date) );
- break;
- case( VT_BOOL ):
- res = VarDateFromBool( V_UNION(ps,boolVal), &V_UNION(pd,date) );
- break;
- case( VT_BSTR ):
- res = VarDateFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,date) );
- break;
- case( VT_CY ):
- res = VarDateFromCy( V_UNION(ps,cyVal), &V_UNION(pd,date) );
- break;
- case( VT_DISPATCH ):
- /*res = VarDateFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,date) );*/
- case( VT_DECIMAL ):
- /*res = VarDateFromDec( V_UNION(ps,deiVal), &V_UNION(pd,date) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_DATE\n", vtFrom);
- break;
- }
- break;
-
- case( VT_BOOL ):
- switch( vtFrom )
- {
- case( VT_NULL ):
- case( VT_EMPTY ):
- res = S_OK;
- V_UNION(pd,boolVal) = VARIANT_FALSE;
- break;
- case( VT_I1 ):
- res = VarBoolFromI1( V_UNION(ps,cVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_I2 ):
- res = VarBoolFromI2( V_UNION(ps,iVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_INT ):
- res = VarBoolFromInt( V_UNION(ps,intVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_I4 ):
- res = VarBoolFromI4( V_UNION(ps,lVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_UI1 ):
- res = VarBoolFromUI1( V_UNION(ps,bVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_UI2 ):
- res = VarBoolFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_UINT ):
- res = VarBoolFromUint( V_UNION(ps,uintVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_UI4 ):
- res = VarBoolFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_R4 ):
- res = VarBoolFromR4( V_UNION(ps,fltVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_R8 ):
- res = VarBoolFromR8( V_UNION(ps,dblVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_DATE ):
- res = VarBoolFromDate( V_UNION(ps,date), &V_UNION(pd,boolVal) );
- break;
- case( VT_BSTR ):
- res = VarBoolFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,boolVal) );
- break;
- case( VT_CY ):
- res = VarBoolFromCy( V_UNION(ps,cyVal), &V_UNION(pd,boolVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarBoolFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,boolVal) );*/
- case( VT_DECIMAL ):
- /*res = VarBoolFromDec( V_UNION(ps,deiVal), &V_UNION(pd,boolVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_BOOL\n", vtFrom);
- break;
- }
- break;
-
- case( VT_BSTR ):
- switch( vtFrom )
- {
- case( VT_EMPTY ):
- if ((V_UNION(pd,bstrVal) = SysAllocStringLen(NULL, 0)))
- res = S_OK;
- else
- res = E_OUTOFMEMORY;
- break;
- case( VT_I1 ):
- res = VarBstrFromI1( V_UNION(ps,cVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_I2 ):
- res = VarBstrFromI2( V_UNION(ps,iVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_INT ):
- res = VarBstrFromInt( V_UNION(ps,intVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_I4 ):
- res = VarBstrFromI4( V_UNION(ps,lVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_UI1 ):
- res = VarBstrFromUI1( V_UNION(ps,bVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_UI2 ):
- res = VarBstrFromUI2( V_UNION(ps,uiVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_UINT ):
- res = VarBstrFromUint( V_UNION(ps,uintVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_UI4 ):
- res = VarBstrFromUI4( V_UNION(ps,ulVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_R4 ):
- res = VarBstrFromR4( V_UNION(ps,fltVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_R8 ):
- res = VarBstrFromR8( V_UNION(ps,dblVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_DATE ):
- if (dwFlags & VARIANT_NOUSEROVERRIDE)
- res = VarBstrFromDate( V_UNION(ps,date), lcid, LOCALE_NOUSEROVERRIDE, &V_UNION(pd,bstrVal) );
- else
- res = VarBstrFromDate( V_UNION(ps,date), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_BOOL ):
- if (dwFlags & VARIANT_ALPHABOOL)
- res = VarBstrFromBool(V_BOOL(ps), lcid, 0, &V_BSTR(pd));
- else if (dwFlags & VARIANT_LOCALBOOL)
- res = VarBstrFromBool(V_BOOL(ps), lcid, VAR_LOCALBOOL, &V_BSTR(pd));
- else
- res = VarBstrFromI2(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
- break;
- case( VT_BSTR ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_CY ):
- res = VarBstrFromCy( V_UNION(ps,cyVal), lcid, 0, &V_UNION(pd,bstrVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarBstrFromDisp( V_UNION(ps,pdispVal), lcid, 0, &(pd,bstrVal) );*/
- case( VT_DECIMAL ):
- /*res = VarBstrFromDec( V_UNION(ps,deiVal), lcid, 0, &(pd,bstrVal) );*/
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_BSTR\n", vtFrom);
- break;
- }
- break;
-
- case( VT_CY ):
- switch( vtFrom )
- {
- case( VT_I1 ):
- res = VarCyFromI1( V_UNION(ps,cVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_I2 ):
- res = VarCyFromI2( V_UNION(ps,iVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_INT ):
- res = VarCyFromInt( V_UNION(ps,intVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_I4 ):
- res = VarCyFromI4( V_UNION(ps,lVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_UI1 ):
- res = VarCyFromUI1( V_UNION(ps,bVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_UI2 ):
- res = VarCyFromUI2( V_UNION(ps,uiVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_UINT ):
- res = VarCyFromUint( V_UNION(ps,uintVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_UI4 ):
- res = VarCyFromUI4( V_UNION(ps,ulVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_R4 ):
- res = VarCyFromR4( V_UNION(ps,fltVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_R8 ):
- res = VarCyFromR8( V_UNION(ps,dblVal), &V_UNION(pd,cyVal) );
- break;
- case( VT_DATE ):
- res = VarCyFromDate( V_UNION(ps,date), &V_UNION(pd,cyVal) );
- break;
- case( VT_BOOL ):
- res = VarCyFromBool( V_UNION(ps,date), &V_UNION(pd,cyVal) );
- break;
- case( VT_CY ):
- res = VariantCopy( pd, ps );
- break;
- case( VT_BSTR ):
- res = VarCyFromStr( V_UNION(ps,bstrVal), lcid, 0, &V_UNION(pd,cyVal) );
- break;
- case( VT_DISPATCH ):
- /*res = VarCyFromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,cyVal) );*/
- case( VT_DECIMAL ):
- /*res = VarCyFromDec( V_UNION(ps,deiVal), &V_UNION(pd,cyVal) );*/
- break;
- case( VT_UNKNOWN ):
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to VT_CY\n", vtFrom);
- break;
- }
- break;
-
- case( VT_UNKNOWN ):
- switch (vtFrom) {
- case VT_DISPATCH:
- if (V_DISPATCH(ps) == NULL) {
- V_UNKNOWN(pd) = NULL;
- } else {
- res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd));
- }
- break;
- case VT_EMPTY: case VT_NULL: case VT_I2: case VT_I4:
- case VT_R4: case VT_R8: case VT_CY: case VT_DATE:
- case VT_BSTR: case VT_ERROR: case VT_BOOL:
- case VT_VARIANT: case VT_DECIMAL: case VT_I1: case VT_UI1:
- case VT_UI2: case VT_UI4: case VT_I8: case VT_UI8: case VT_INT:
- case VT_UINT: case VT_VOID: case VT_HRESULT: case VT_PTR:
- case VT_SAFEARRAY: case VT_CARRAY: case VT_USERDEFINED:
- case VT_LPSTR: case VT_LPWSTR: case VT_RECORD: case VT_FILETIME:
- case VT_BLOB: case VT_STREAM: case VT_STORAGE:
- case VT_STREAMED_OBJECT: case VT_STORED_OBJECT: case VT_BLOB_OBJECT:
- case VT_CF: case VT_CLSID:
- res = DISP_E_TYPEMISMATCH;
- break;
- default:
- FIXME("Coercion from %d to VT_UNKNOWN unhandled.\n", vtFrom);
- res = DISP_E_BADVARTYPE;
- break;
- }
- break;
+ case VT_I4:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_I4(pd) = 0; return S_OK;
+ case VT_I1: return VarI4FromI1(V_I1(ps), &V_I4(pd));
+ case VT_I2: return VarI4FromI2(V_I2(ps), &V_I4(pd));
+ case VT_UI1: return VarI4FromUI1(V_UI1(ps), &V_I4(pd));
+ case VT_UI2: return VarI4FromUI2(V_UI2(ps), &V_I4(pd));
+ case VT_UI4: return VarI4FromUI4(V_UI4(ps), &V_I4(pd));
+ case VT_I8: return VarI4FromI8(V_I8(ps), &V_I4(pd));
+ case VT_UI8: return VarI4FromUI8(V_UI8(ps), &V_I4(pd));
+ case VT_R4: return VarI4FromR4(V_R4(ps), &V_I4(pd));
+ case VT_R8: return VarI4FromR8(V_R8(ps), &V_I4(pd));
+ case VT_DATE: return VarI4FromDate(V_DATE(ps), &V_I4(pd));
+ case VT_BOOL: return VarI4FromBool(V_BOOL(ps), &V_I4(pd));
+ case VT_CY: return VarI4FromCy(V_CY(ps), &V_I4(pd));
+ case VT_DECIMAL: return VarI4FromDec(&V_DECIMAL(ps), &V_I4(pd));
+ case VT_DISPATCH: return VarI4FromDisp(V_DISPATCH(ps), lcid, &V_I4(pd));
+ case VT_BSTR: return VarI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_I4(pd));
+ }
+ break;
- case( VT_DISPATCH ):
- switch (vtFrom) {
- case VT_UNKNOWN:
- if (V_UNION(ps,punkVal) == NULL) {
- V_UNION(pd,pdispVal) = NULL;
- } else {
- res = IUnknown_QueryInterface(V_UNION(ps,punkVal), &IID_IDispatch, (LPVOID*)&V_UNION(pd,pdispVal));
- }
- break;
- case VT_EMPTY: case VT_NULL: case VT_I2: case VT_I4:
- case VT_R4: case VT_R8: case VT_CY: case VT_DATE:
- case VT_BSTR: case VT_ERROR: case VT_BOOL:
- case VT_VARIANT: case VT_DECIMAL: case VT_I1: case VT_UI1:
- case VT_UI2: case VT_UI4: case VT_I8: case VT_UI8: case VT_INT:
- case VT_UINT: case VT_VOID: case VT_HRESULT:
- case VT_SAFEARRAY: case VT_CARRAY: case VT_USERDEFINED:
- case VT_LPSTR: case VT_LPWSTR: case VT_RECORD: case VT_FILETIME:
- case VT_BLOB: case VT_STREAM: case VT_STORAGE:
- case VT_STREAMED_OBJECT: case VT_STORED_OBJECT: case VT_BLOB_OBJECT:
- case VT_CF: case VT_CLSID:
- res = DISP_E_TYPEMISMATCH;
- break;
- case VT_PTR:
- V_UNION(pd,pdispVal) = V_UNION(ps,pdispVal);
- break;
- default:
- FIXME("Coercion from %d to VT_DISPATCH unhandled.\n", vtFrom);
- res = DISP_E_BADVARTYPE;
- break;
- }
- break;
+ case VT_UI1:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_UI1(pd) = 0; return S_OK;
+ case VT_I1: return VarUI1FromI1(V_I1(ps), &V_UI1(pd));
+ case VT_I2: return VarUI1FromI2(V_I2(ps), &V_UI1(pd));
+ case VT_I4: return VarUI1FromI4(V_I4(ps), &V_UI1(pd));
+ case VT_UI2: return VarUI1FromUI2(V_UI2(ps), &V_UI1(pd));
+ case VT_UI4: return VarUI1FromUI4(V_UI4(ps), &V_UI1(pd));
+ case VT_I8: return VarUI1FromI8(V_I8(ps), &V_UI1(pd));
+ case VT_UI8: return VarUI1FromUI8(V_UI8(ps), &V_UI1(pd));
+ case VT_R4: return VarUI1FromR4(V_R4(ps), &V_UI1(pd));
+ case VT_R8: return VarUI1FromR8(V_R8(ps), &V_UI1(pd));
+ case VT_DATE: return VarUI1FromDate(V_DATE(ps), &V_UI1(pd));
+ case VT_BOOL: return VarUI1FromBool(V_BOOL(ps), &V_UI1(pd));
+ case VT_CY: return VarUI1FromCy(V_CY(ps), &V_UI1(pd));
+ case VT_DECIMAL: return VarUI1FromDec(&V_DECIMAL(ps), &V_UI1(pd));
+ case VT_DISPATCH: return VarUI1FromDisp(V_DISPATCH(ps), lcid, &V_UI1(pd));
+ case VT_BSTR: return VarUI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI1(pd));
+ }
+ break;
- default:
- res = DISP_E_TYPEMISMATCH;
- FIXME("Coercion from %d to %d\n", vtFrom, vt );
- break;
- }
+ case VT_UI2:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_UI2(pd) = 0; return S_OK;
+ case VT_I1: return VarUI2FromI1(V_I1(ps), &V_UI2(pd));
+ case VT_I2: return VarUI2FromI2(V_I2(ps), &V_UI2(pd));
+ case VT_I4: return VarUI2FromI4(V_I4(ps), &V_UI2(pd));
+ case VT_UI1: return VarUI2FromUI1(V_UI1(ps), &V_UI2(pd));
+ case VT_UI4: return VarUI2FromUI4(V_UI4(ps), &V_UI2(pd));
+ case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
+ case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
+ case VT_R4: return VarUI2FromR4(V_R4(ps), &V_UI2(pd));
+ case VT_R8: return VarUI2FromR8(V_R8(ps), &V_UI2(pd));
+ case VT_DATE: return VarUI2FromDate(V_DATE(ps), &V_UI2(pd));
+ case VT_BOOL: return VarUI2FromBool(V_BOOL(ps), &V_UI2(pd));
+ case VT_CY: return VarUI2FromCy(V_CY(ps), &V_UI2(pd));
+ case VT_DECIMAL: return VarUI2FromDec(&V_DECIMAL(ps), &V_UI2(pd));
+ case VT_DISPATCH: return VarUI2FromDisp(V_DISPATCH(ps), lcid, &V_UI2(pd));
+ case VT_BSTR: return VarUI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI2(pd));
+ }
+ break;
- return res;
-}
+ case VT_UI4:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_UI4(pd) = 0; return S_OK;
+ case VT_I1: return VarUI4FromI1(V_I1(ps), &V_UI4(pd));
+ case VT_I2: return VarUI4FromI2(V_I2(ps), &V_UI4(pd));
+ case VT_I4: return VarUI4FromI4(V_I4(ps), &V_UI4(pd));
+ case VT_UI1: return VarUI4FromUI1(V_UI1(ps), &V_UI4(pd));
+ case VT_UI2: return VarUI4FromUI2(V_UI2(ps), &V_UI4(pd));
+ case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
+ case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
+ case VT_R4: return VarUI4FromR4(V_R4(ps), &V_UI4(pd));
+ case VT_R8: return VarUI4FromR8(V_R8(ps), &V_UI4(pd));
+ case VT_DATE: return VarUI4FromDate(V_DATE(ps), &V_UI4(pd));
+ case VT_BOOL: return VarUI4FromBool(V_BOOL(ps), &V_UI4(pd));
+ case VT_CY: return VarUI4FromCy(V_CY(ps), &V_UI4(pd));
+ case VT_DECIMAL: return VarUI4FromDec(&V_DECIMAL(ps), &V_UI4(pd));
+ case VT_DISPATCH: return VarUI4FromDisp(V_DISPATCH(ps), lcid, &V_UI4(pd));
+ case VT_BSTR: return VarUI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI4(pd));
+ }
+ break;
-/******************************************************************************
- * ValidateVtRange [INTERNAL]
- *
- * Used internally by the hi-level Variant API to determine
- * if the vartypes are valid.
- */
-static HRESULT ValidateVtRange( VARTYPE vt )
-{
- /* if by value we must make sure it is in the
- * range of the valid types.
- */
- if( ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
+ case VT_UI8:
+ switch (vtFrom)
{
- return DISP_E_BADVARTYPE;
+ case VT_EMPTY: V_UI8(pd) = 0; return S_OK;
+ case VT_I4: if (V_I4(ps) < 0) return DISP_E_OVERFLOW; V_UI8(pd) = V_I4(ps); return S_OK;
+ case VT_I1: return VarUI8FromI1(V_I1(ps), &V_UI8(pd));
+ case VT_I2: return VarUI8FromI2(V_I2(ps), &V_UI8(pd));
+ case VT_UI1: return VarUI8FromUI1(V_UI1(ps), &V_UI8(pd));
+ case VT_UI2: return VarUI8FromUI2(V_UI2(ps), &V_UI8(pd));
+ case VT_UI4: return VarUI8FromUI4(V_UI4(ps), &V_UI8(pd));
+ case VT_I8: return VarUI8FromI8(V_I8(ps), &V_UI8(pd));
+ case VT_R4: return VarUI8FromR4(V_R4(ps), &V_UI8(pd));
+ case VT_R8: return VarUI8FromR8(V_R8(ps), &V_UI8(pd));
+ case VT_DATE: return VarUI8FromDate(V_DATE(ps), &V_UI8(pd));
+ case VT_BOOL: return VarUI8FromBool(V_BOOL(ps), &V_UI8(pd));
+ case VT_CY: return VarUI8FromCy(V_CY(ps), &V_UI8(pd));
+ case VT_DECIMAL: return VarUI8FromDec(&V_DECIMAL(ps), &V_UI8(pd));
+ case VT_DISPATCH: return VarUI8FromDisp(V_DISPATCH(ps), lcid, &V_UI8(pd));
+ case VT_BSTR: return VarUI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI8(pd));
}
- return S_OK;
-}
+ break;
-/* Copy data from one variant to another. */
-static void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
-{
- switch(vt)
- {
- case VT_I1:
- case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
- case VT_BOOL:
- case VT_I2:
- case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
- case VT_R4:
- case VT_I4:
- case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
- case VT_R8:
- case VT_DATE:
- case VT_CY:
case VT_I8:
- case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
- case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
- default:
- FIXME("VT_ type %d unhandled, please report!\n", vt);
- }
-}
-
-/* Coerce VT_DISPATCH to another type */
-HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, VARTYPE vt)
-{
- VARIANTARG srcVar, dstVar;
- HRESULT hRet;
-
- V_VT(&srcVar) = VT_DISPATCH;
- V_DISPATCH(&srcVar) = pdispIn;
-
- hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, 0, vt);
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_I8(pd) = 0; return S_OK;
+ case VT_I4: V_I8(pd) = V_I4(ps); return S_OK;
+ case VT_I1: return VarI8FromI1(V_I1(ps), &V_I8(pd));
+ case VT_I2: return VarI8FromI2(V_I2(ps), &V_I8(pd));
+ case VT_UI1: return VarI8FromUI1(V_UI1(ps), &V_I8(pd));
+ case VT_UI2: return VarI8FromUI2(V_UI2(ps), &V_I8(pd));
+ case VT_UI4: return VarI8FromUI4(V_UI4(ps), &V_I8(pd));
+ case VT_UI8: return VarI8FromUI8(V_I8(ps), &V_I8(pd));
+ case VT_R4: return VarI8FromR4(V_R4(ps), &V_I8(pd));
+ case VT_R8: return VarI8FromR8(V_R8(ps), &V_I8(pd));
+ case VT_DATE: return VarI8FromDate(V_DATE(ps), &V_I8(pd));
+ case VT_BOOL: return VarI8FromBool(V_BOOL(ps), &V_I8(pd));
+ case VT_CY: return VarI8FromCy(V_CY(ps), &V_I8(pd));
+ case VT_DECIMAL: return VarI8FromDec(&V_DECIMAL(ps), &V_I8(pd));
+ case VT_DISPATCH: return VarI8FromDisp(V_DISPATCH(ps), lcid, &V_I8(pd));
+ case VT_BSTR: return VarI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_I8(pd));
+ }
+ break;
- if (SUCCEEDED(hRet))
- VARIANT_CopyData(&dstVar, vt, pOut);
- return hRet;
-}
+ case VT_R4:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_R4(pd) = 0.0f; return S_OK;
+ case VT_I1: return VarR4FromI1(V_I1(ps), &V_R4(pd));
+ case VT_I2: return VarR4FromI2(V_I2(ps), &V_R4(pd));
+ case VT_I4: return VarR4FromI4(V_I4(ps), &V_R4(pd));
+ case VT_UI1: return VarR4FromUI1(V_UI1(ps), &V_R4(pd));
+ case VT_UI2: return VarR4FromUI2(V_UI2(ps), &V_R4(pd));
+ case VT_UI4: return VarR4FromUI4(V_UI4(ps), &V_R4(pd));
+ case VT_I8: return VarR4FromI8(V_I8(ps), &V_R4(pd));
+ case VT_UI8: return VarR4FromUI8(V_UI8(ps), &V_R4(pd));
+ case VT_R8: return VarR4FromR8(V_R8(ps), &V_R4(pd));
+ case VT_DATE: return VarR4FromDate(V_DATE(ps), &V_R4(pd));
+ case VT_BOOL: return VarR4FromBool(V_BOOL(ps), &V_R4(pd));
+ case VT_CY: return VarR4FromCy(V_CY(ps), &V_R4(pd));
+ case VT_DECIMAL: return VarR4FromDec(&V_DECIMAL(ps), &V_R4(pd));
+ case VT_DISPATCH: return VarR4FromDisp(V_DISPATCH(ps), lcid, &V_R4(pd));
+ case VT_BSTR: return VarR4FromStr(V_BSTR(ps), lcid, dwFlags, &V_R4(pd));
+ }
+ break;
-/* Coerce VT_BSTR to a numeric type */
-HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
- void* pOut, VARTYPE vt)
-{
- VARIANTARG dstVar;
- HRESULT hRet;
- NUMPARSE np;
- BYTE rgb[1024];
+ case VT_R8:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_R8(pd) = 0.0; return S_OK;
+ case VT_I1: return VarR8FromI1(V_I1(ps), &V_R8(pd));
+ case VT_I2: return VarR8FromI2(V_I2(ps), &V_R8(pd));
+ case VT_I4: return VarR8FromI4(V_I4(ps), &V_R8(pd));
+ case VT_UI1: return VarR8FromUI1(V_UI1(ps), &V_R8(pd));
+ case VT_UI2: return VarR8FromUI2(V_UI2(ps), &V_R8(pd));
+ case VT_UI4: return VarR8FromUI4(V_UI4(ps), &V_R8(pd));
+ case VT_I8: return VarR8FromI8(V_I8(ps), &V_R8(pd));
+ case VT_UI8: return VarR8FromUI8(V_UI8(ps), &V_R8(pd));
+ case VT_R4: return VarR8FromR4(V_R4(ps), &V_R8(pd));
+ case VT_DATE: return VarR8FromDate(V_DATE(ps), &V_R8(pd));
+ case VT_BOOL: return VarR8FromBool(V_BOOL(ps), &V_R8(pd));
+ case VT_CY: return VarR8FromCy(V_CY(ps), &V_R8(pd));
+ case VT_DECIMAL: return VarR8FromDec(&V_DECIMAL(ps), &V_R8(pd));
+ case VT_DISPATCH: return VarR8FromDisp(V_DISPATCH(ps), lcid, &V_R8(pd));
+ case VT_BSTR: return VarR8FromStr(V_BSTR(ps), lcid, dwFlags, &V_R8(pd));
+ }
+ break;
- /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
- np.cDig = sizeof(rgb) / sizeof(BYTE);
- np.dwInFlags = NUMPRS_STD;
+ case VT_DATE:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_DATE(pd) = 0.0; return S_OK;
+ case VT_I1: return VarDateFromI1(V_I1(ps), &V_DATE(pd));
+ case VT_I2: return VarDateFromI2(V_I2(ps), &V_DATE(pd));
+ case VT_I4: return VarDateFromI4(V_I4(ps), &V_DATE(pd));
+ case VT_UI1: return VarDateFromUI1(V_UI1(ps), &V_DATE(pd));
+ case VT_UI2: return VarDateFromUI2(V_UI2(ps), &V_DATE(pd));
+ case VT_UI4: return VarDateFromUI4(V_UI4(ps), &V_DATE(pd));
+ case VT_I8: return VarDateFromI8(V_I8(ps), &V_DATE(pd));
+ case VT_UI8: return VarDateFromUI8(V_UI8(ps), &V_DATE(pd));
+ case VT_R4: return VarDateFromR4(V_R4(ps), &V_DATE(pd));
+ case VT_R8: return VarDateFromR8(V_R8(ps), &V_DATE(pd));
+ case VT_BOOL: return VarDateFromBool(V_BOOL(ps), &V_DATE(pd));
+ case VT_CY: return VarDateFromCy(V_CY(ps), &V_DATE(pd));
+ case VT_DECIMAL: return VarDateFromDec(&V_DECIMAL(ps), &V_DATE(pd));
+ case VT_DISPATCH: return VarDateFromDisp(V_DISPATCH(ps), lcid, &V_DATE(pd));
+ case VT_BSTR: return VarDateFromStr(V_BSTR(ps), lcid, dwFlags, &V_DATE(pd));
+ }
+ break;
- hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
+ case VT_BOOL:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_BOOL(pd) = 0; return S_OK;
+ case VT_I1: return VarBoolFromI1(V_I1(ps), &V_BOOL(pd));
+ case VT_I2: return VarBoolFromI2(V_I2(ps), &V_BOOL(pd));
+ case VT_I4: return VarBoolFromI4(V_I4(ps), &V_BOOL(pd));
+ case VT_UI1: return VarBoolFromUI1(V_UI1(ps), &V_BOOL(pd));
+ case VT_UI2: return VarBoolFromUI2(V_UI2(ps), &V_BOOL(pd));
+ case VT_UI4: return VarBoolFromUI4(V_UI4(ps), &V_BOOL(pd));
+ case VT_I8: return VarBoolFromI8(V_I8(ps), &V_BOOL(pd));
+ case VT_UI8: return VarBoolFromUI8(V_UI8(ps), &V_BOOL(pd));
+ case VT_R4: return VarBoolFromR4(V_R4(ps), &V_BOOL(pd));
+ case VT_R8: return VarBoolFromR8(V_R8(ps), &V_BOOL(pd));
+ case VT_DATE: return VarBoolFromDate(V_DATE(ps), &V_BOOL(pd));
+ case VT_CY: return VarBoolFromCy(V_CY(ps), &V_BOOL(pd));
+ case VT_DECIMAL: return VarBoolFromDec(&V_DECIMAL(ps), &V_BOOL(pd));
+ case VT_DISPATCH: return VarBoolFromDisp(V_DISPATCH(ps), lcid, &V_BOOL(pd));
+ case VT_BSTR: return VarBoolFromStr(V_BSTR(ps), lcid, dwFlags, &V_BOOL(pd));
+ }
+ break;
- if (SUCCEEDED(hRet))
- {
- /* 1 << vt gives us the VTBIT constant for the destination number type */
- hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
- if (SUCCEEDED(hRet))
- VARIANT_CopyData(&dstVar, vt, pOut);
- }
- return hRet;
-}
+ case VT_BSTR:
+ switch (vtFrom)
+ {
+ case VT_EMPTY:
+ V_BSTR(pd) = SysAllocStringLen(NULL, 0);
+ return V_BSTR(pd) ? S_OK : E_OUTOFMEMORY;
+ case VT_BOOL:
+ if (wFlags & (VARIANT_ALPHABOOL|VARIANT_LOCALBOOL))
+ return VarBstrFromBool(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
+ return VarBstrFromI2(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_I1: return VarBstrFromI1(V_I1(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_I2: return VarBstrFromI2(V_I2(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_I4: return VarBstrFromI4(V_I4(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_UI1: return VarBstrFromUI1(V_UI1(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_UI2: return VarBstrFromUI2(V_UI2(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_UI4: return VarBstrFromUI4(V_UI4(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_I8: return VarBstrFromI8(V_I8(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_UI8: return VarBstrFromUI8(V_UI8(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_R4: return VarBstrFromR4(V_R4(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_R8: return VarBstrFromR8(V_R8(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_DATE: return VarBstrFromDate(V_DATE(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_CY: return VarBstrFromCy(V_CY(ps), lcid, dwFlags, &V_BSTR(pd));
+ case VT_DECIMAL: return VarBstrFromDec(&V_DECIMAL(ps), lcid, dwFlags, &V_BSTR(pd));
+/* case VT_DISPATCH: return VarBstrFromDisp(V_DISPATCH(ps), lcid, dwFlags, &V_BSTR(pd)); */
+ }
+ break;
-/******************************************************************************
- * ValidateVartype [INTERNAL]
- *
- * Used internally by the hi-level Variant API to determine
- * if the vartypes are valid.
- */
-static HRESULT ValidateVariantType( VARTYPE vt )
-{
- HRESULT res = S_OK;
+ case VT_CY:
+ switch (vtFrom)
+ {
+ case VT_EMPTY: V_CY(pd).int64 = 0; return S_OK;
+ case VT_I1: return VarCyFromI1(V_I1(ps), &V_CY(pd));
+ case VT_I2: return VarCyFromI2(V_I2(ps), &V_CY(pd));
+ case VT_I4: return VarCyFromI4(V_I4(ps), &V_CY(pd));
+ case VT_UI1: return VarCyFromUI1(V_UI1(ps), &V_CY(pd));
+ case VT_UI2: return VarCyFromUI2(V_UI2(ps), &V_CY(pd));
+ case VT_UI4: return VarCyFromUI4(V_UI4(ps), &V_CY(pd));
+ case VT_I8: return VarCyFromI8(V_I8(ps), &V_CY(pd));
+ case VT_UI8: return VarCyFromUI8(V_UI8(ps), &V_CY(pd));
+ case VT_R4: return VarCyFromR4(V_R4(ps), &V_CY(pd));
+ case VT_R8: return VarCyFromR8(V_R8(ps), &V_CY(pd));
+ case VT_DATE: return VarCyFromDate(V_DATE(ps), &V_CY(pd));
+ case VT_BOOL: return VarCyFromBool(V_BOOL(ps), &V_CY(pd));
+ case VT_DECIMAL: return VarCyFromDec(&V_DECIMAL(ps), &V_CY(pd));
+ case VT_DISPATCH: return VarCyFromDisp(V_DISPATCH(ps), lcid, &V_CY(pd));
+ case VT_BSTR: return VarCyFromStr(V_BSTR(ps), lcid, dwFlags, &V_CY(pd));
+ }
+ break;
- /* check if we have a valid argument.
- */
- if( vt & VT_BYREF )
+ case VT_DECIMAL:
+ switch (vtFrom)
{
- /* if by reference check that the type is in
- * the valid range and that it is not of empty or null type
+ case VT_EMPTY:
+ case VT_BOOL:
+ DEC_SIGNSCALE(&V_DECIMAL(pd)) = SIGNSCALE(DECIMAL_POS,0);
+ DEC_HI32(&V_DECIMAL(pd)) = 0;
+ DEC_MID32(&V_DECIMAL(pd)) = 0;
+ /* VarDecFromBool() coerces to -1/0, ChangeTypeEx() coerces to 1/0.
+ * VT_NULL and VT_EMPTY always give a 0 value.
*/
- if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
- ( vt & VT_TYPEMASK ) == VT_NULL ||
- ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
- {
- res = DISP_E_BADVARTYPE;
- }
-
+ DEC_LO32(&V_DECIMAL(pd)) = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0;
+ return S_OK;
+ case VT_I1: return VarDecFromI1(V_I1(ps), &V_DECIMAL(pd));
+ case VT_I2: return VarDecFromI2(V_I2(ps), &V_DECIMAL(pd));
+ case VT_I4: return VarDecFromI4(V_I4(ps), &V_DECIMAL(pd));
+ case VT_UI1: return VarDecFromUI1(V_UI1(ps), &V_DECIMAL(pd));
+ case VT_UI2: return VarDecFromUI2(V_UI2(ps), &V_DECIMAL(pd));
+ case VT_UI4: return VarDecFromUI4(V_UI4(ps), &V_DECIMAL(pd));
+ case VT_I8: return VarDecFromI8(V_I8(ps), &V_DECIMAL(pd));
+ case VT_UI8: return VarDecFromUI8(V_UI8(ps), &V_DECIMAL(pd));
+ case VT_R4: return VarDecFromR4(V_R4(ps), &V_DECIMAL(pd));
+ case VT_R8: return VarDecFromR8(V_R8(ps), &V_DECIMAL(pd));
+ case VT_DATE: return VarDecFromDate(V_DATE(ps), &V_DECIMAL(pd));
+ case VT_CY: return VarDecFromCy(V_CY(pd), &V_DECIMAL(ps));
+ case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(ps));
+ case VT_BSTR: return VarDecFromStr(V_BSTR(ps), lcid, dwFlags, &V_DECIMAL(pd));
}
- else
+ break;
+
+ case VT_UNKNOWN:
+ switch (vtFrom)
{
- res = ValidateVtRange( vt );
+ case VT_DISPATCH:
+ if (V_DISPATCH(ps) == NULL)
+ V_UNKNOWN(pd) = NULL;
+ else
+ res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd));
+ break;
}
+ break;
- return res;
-}
-
-/******************************************************************************
- * ValidateVt [INTERNAL]
- *
- * Used internally by the hi-level Variant API to determine
- * if the vartypes are valid.
- */
-static HRESULT ValidateVt( VARTYPE vt )
-{
- HRESULT res = S_OK;
-
- /* check if we have a valid argument.
- */
- if( vt & VT_BYREF )
+ case VT_DISPATCH:
+ switch (vtFrom)
{
- /* if by reference check that the type is in
- * the valid range and that it is not of empty or null type
- */
- if( ( vt & VT_TYPEMASK ) == VT_EMPTY ||
- ( vt & VT_TYPEMASK ) == VT_NULL ||
- ( vt & VT_TYPEMASK ) > VT_MAXVALIDTYPE )
- {
- res = DISP_E_BADVARTYPE;
- }
-
+ case VT_UNKNOWN:
+ if (V_UNKNOWN(ps) == NULL)
+ V_DISPATCH(pd) = NULL;
+ else
+ res = IUnknown_QueryInterface(V_UNKNOWN(ps), &IID_IDispatch, (LPVOID*)&V_DISPATCH(pd));
+ break;
}
- else
+ break;
+
+ case VT_RECORD:
+ switch (vtFrom)
{
- res = ValidateVtRange( vt );
+ case VT_EMPTY:
+ V_UNION(pd,brecVal).pvRecord = NULL;
+ V_UNION(pd,brecVal).pRecInfo = NULL;
+ return S_OK;
}
+ break;
- return res;
+ }
+ return res;
}
/******************************************************************************
@@ -1530,16 +943,16 @@
}
/******************************************************************************
- * VariantChangeType [OLEAUT32.12]
+ * VariantChangeType [OLEAUT32.12]
*
* Change the type of a variant.
- *
+ *
* PARAMS
* pvargDest [O] Destination for the converted variant
* pvargSrc [O] Source variant to change the type of
* wFlags [I] VARIANT_ flags from "oleauto.h"
* vt [I] Variant type to change pvargSrc into
- *
+ *
* RETURNS
* Success: S_OK. pvargDest contains the converted value.
* Failure: An HRESULT error code describing the failure.
@@ -1549,23 +962,23 @@
* See VariantChangeTypeEx.
*/
HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
- USHORT wFlags, VARTYPE vt)
+ USHORT wFlags, VARTYPE vt)
{
- return VariantChangeTypeEx( pvargDest, pvargSrc, 0, wFlags, vt );
+ return VariantChangeTypeEx( pvargDest, pvargSrc, LOCALE_USER_DEFAULT, wFlags, vt );
}
/******************************************************************************
- * VariantChangeTypeEx [OLEAUT32.147]
+ * VariantChangeTypeEx [OLEAUT32.147]
*
* Change the type of a variant.
- *
+ *
* PARAMS
* pvargDest [O] Destination for the converted variant
* pvargSrc [O] Source variant to change the type of
* lcid [I] LCID for the conversion
* wFlags [I] VARIANT_ flags from "oleauto.h"
* vt [I] Variant type to change pvargSrc into
- *
+ *
* RETURNS
* Success: S_OK. pvargDest contains the converted value.
* Failure: An HRESULT error code describing the failure.
@@ -1575,2663 +988,100 @@
* conversion. If the conversion is successful, pvargSrc will be freed.
*/
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
- LCID lcid, USHORT wFlags, VARTYPE vt)
-{
- HRESULT res = S_OK;
- VARIANTARG varg;
- VariantInit( &varg );
-
- TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
- TRACE("Src Var:\n");
- dump_Variant(pvargSrc);
-
- /* validate our source argument.
- */
- res = ValidateVariantType( V_VT(pvargSrc) );
-
- /* validate the vartype.
- */
- if( res == S_OK )
- {
- res = ValidateVt( vt );
- }
-
- /* if we are doing an in-place conversion make a copy of the source.
- */
- if( res == S_OK && pvargDest == pvargSrc )
- {
- res = VariantCopy( &varg, pvargSrc );
- pvargSrc = &varg;
- }
-
- if( res == S_OK )
- {
- /* free up the destination variant.
- */
- res = VariantClear( pvargDest );
- }
-
- if( res == S_OK )
- {
- if( V_VT(pvargSrc) & VT_BYREF )
- {
- /* Convert the source variant to a "byvalue" variant.
- */
- VARIANTARG Variant;
-
- if ((V_VT(pvargSrc) & 0xf000) != VT_BYREF) {
- FIXME("VT_TYPEMASK %x is unhandled.\n",V_VT(pvargSrc) & VT_TYPEMASK);
- return E_FAIL;
- }
-
- VariantInit( &Variant );
- res = VariantCopyInd( &Variant, pvargSrc );
- if( res == S_OK )
- {
- res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
- /* this should not fail.
- */
- VariantClear( &Variant );
- }
- } else {
- if (V_VT(pvargSrc) & VT_ARRAY) {
- if ((V_VT(pvargSrc) & 0xf000) != VT_ARRAY) {
- FIXME("VT_TYPEMASK %x is unhandled in VT_ARRAY.\n",V_VT(pvargSrc) & VT_TYPEMASK);
- return E_FAIL;
- }
- V_VT(pvargDest) = VT_ARRAY | vt;
- res = coerce_array(pvargSrc, pvargDest, lcid, wFlags, vt);
- } else {
- if ((V_VT(pvargSrc) & 0xf000)) {
- FIXME("VT_TYPEMASK %x is unhandled in normal case.\n",V_VT(pvargSrc) & VT_TYPEMASK);
- return E_FAIL;
- }
- /* Use the current "byvalue" source variant.
- */
- res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
- }
- }
- }
- /* this should not fail.
- */
- VariantClear( &varg );
-
- /* set the type of the destination
- */
- if ( res == S_OK )
- V_VT(pvargDest) = vt;
-
- TRACE("Dest Var:\n");
- dump_Variant(pvargDest);
-
- return res;
-}
-
-
-
-
-/******************************************************************************
- * VarUI1FromI2 [OLEAUT32.130]
- */
-HRESULT WINAPI VarUI1FromI2(short sIn, BYTE* pbOut)
-{
- TRACE("( %d, %p ), stub\n", sIn, pbOut );
-
- /* Check range of value.
- */
- if( sIn < UI1_MIN || sIn > UI1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pbOut = (BYTE) sIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI1FromI4 [OLEAUT32.131]
- */
-HRESULT WINAPI VarUI1FromI4(LONG lIn, BYTE* pbOut)
-{
- TRACE("( %ld, %p ), stub\n", lIn, pbOut );
-
- /* Check range of value.
- */
- if( lIn < UI1_MIN || lIn > UI1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pbOut = (BYTE) lIn;
-
- return S_OK;
-}
-
-
-/******************************************************************************
- * VarUI1FromR4 [OLEAUT32.132]
- */
-HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, pbOut );
-
- /* Check range of value.
- */
- fltIn = round( fltIn );
- if( fltIn < UI1_MIN || fltIn > UI1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pbOut = (BYTE) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI1FromR8 [OLEAUT32.133]
- */
-HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, pbOut );
-
- /* Check range of value.
- */
- dblIn = round( dblIn );
- if( dblIn < UI1_MIN || dblIn > UI1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pbOut = (BYTE) dblIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI1FromDate [OLEAUT32.135]
- */
-HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, pbOut );
-
- /* Check range of value.
- */
- dateIn = round( dateIn );
- if( dateIn < UI1_MIN || dateIn > UI1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pbOut = (BYTE) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI1FromBool [OLEAUT32.138]
- */
-HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, pbOut );
-
- *pbOut = (BYTE) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI1FromI1 [OLEAUT32.237]
- */
-HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, pbOut );
-
- *pbOut = cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI1FromUI2 [OLEAUT32.238]
- */
-HRESULT WINAPI VarUI1FromUI2(USHORT uiIn, BYTE* pbOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pbOut );
-
- /* Check range of value.
- */
- if( uiIn > UI1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pbOut = (BYTE) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI1FromUI4 [OLEAUT32.239]
- */
-HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
-{
- TRACE("( %ld, %p ), stub\n", ulIn, pbOut );
-
- /* Check range of value.
- */
- if( ulIn > UI1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pbOut = (BYTE) ulIn;
-
- return S_OK;
-}
-
-
-/******************************************************************************
- * VarUI1FromStr [OLEAUT32.136]
- */
-HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, pbOut);
- return _VarUI1FromStr(strIn, lcid, dwFlags, pbOut);
-}
-
-/**********************************************************************
- * VarUI1FromCy [OLEAUT32.134]
- * Convert currency to unsigned char
- */
-HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut) {
- double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
-
- *pbOut = (BYTE)t;
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromUI1 [OLEAUT32.48]
- */
-HRESULT WINAPI VarI2FromUI1(BYTE bIn, short* psOut)
-{
- TRACE("( 0x%08x, %p ), stub\n", bIn, psOut );
-
- *psOut = (short) bIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromI4 [OLEAUT32.49]
- */
-HRESULT WINAPI VarI2FromI4(LONG lIn, short* psOut)
-{
- TRACE("( %lx, %p ), stub\n", lIn, psOut );
-
- /* Check range of value.
- */
- if( lIn < I2_MIN || lIn > I2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *psOut = (short) lIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromR4 [OLEAUT32.50]
- */
-HRESULT WINAPI VarI2FromR4(FLOAT fltIn, short* psOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, psOut );
-
- /* Check range of value.
- */
- fltIn = round( fltIn );
- if( fltIn < I2_MIN || fltIn > I2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *psOut = (short) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromR8 [OLEAUT32.51]
- */
-HRESULT WINAPI VarI2FromR8(double dblIn, short* psOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, psOut );
-
- /* Check range of value.
- */
- dblIn = round( dblIn );
- if( dblIn < I2_MIN || dblIn > I2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *psOut = (short) dblIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromDate [OLEAUT32.53]
- */
-HRESULT WINAPI VarI2FromDate(DATE dateIn, short* psOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, psOut );
-
- /* Check range of value.
- */
- dateIn = round( dateIn );
- if( dateIn < I2_MIN || dateIn > I2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *psOut = (short) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromBool [OLEAUT32.56]
- */
-HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, short* psOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, psOut );
-
- *psOut = (short) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromI1 [OLEAUT32.205]
- */
-HRESULT WINAPI VarI2FromI1(signed char cIn, short* psOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, psOut );
-
- *psOut = (short) cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromUI2 [OLEAUT32.206]
- */
-HRESULT WINAPI VarI2FromUI2(USHORT uiIn, short* psOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, psOut );
-
- /* Check range of value.
- */
- if( uiIn > I2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *psOut = (short) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromUI4 [OLEAUT32.207]
- */
-HRESULT WINAPI VarI2FromUI4(ULONG ulIn, short* psOut)
-{
- TRACE("( %lx, %p ), stub\n", ulIn, psOut );
-
- /* Check range of value.
- */
- if( ulIn < I2_MIN || ulIn > I2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *psOut = (short) ulIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI2FromStr [OLEAUT32.54]
- */
-HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, short* psOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, psOut);
- return _VarI2FromStr(strIn, lcid, dwFlags, psOut);
-}
-
-/**********************************************************************
- * VarI2FromCy [OLEAUT32.52]
- * Convert currency to signed short
- */
-HRESULT WINAPI VarI2FromCy(CY cyIn, short* psOut) {
- double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
-
- *psOut = (SHORT)t;
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromUI1 [OLEAUT32.58]
- */
-HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG* plOut)
-{
- TRACE("( %X, %p ), stub\n", bIn, plOut );
-
- *plOut = (LONG) bIn;
-
- return S_OK;
-}
-
-
-/******************************************************************************
- * VarI4FromR4 [OLEAUT32.60]
- */
-HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG* plOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, plOut );
-
- /* Check range of value.
- */
- fltIn = round( fltIn );
- if( fltIn < I4_MIN || fltIn > I4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *plOut = (LONG) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromR8 [OLEAUT32.61]
- */
-HRESULT WINAPI VarI4FromR8(double dblIn, LONG* plOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, plOut );
-
- /* Check range of value.
- */
- dblIn = round( dblIn );
- if( dblIn < I4_MIN || dblIn > I4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *plOut = (LONG) dblIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromDate [OLEAUT32.63]
- */
-HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG* plOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, plOut );
-
- /* Check range of value.
- */
- dateIn = round( dateIn );
- if( dateIn < I4_MIN || dateIn > I4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *plOut = (LONG) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromBool [OLEAUT32.66]
- */
-HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG* plOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, plOut );
-
- *plOut = (LONG) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromI1 [OLEAUT32.209]
- */
-HRESULT WINAPI VarI4FromI1(signed char cIn, LONG* plOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, plOut );
-
- *plOut = (LONG) cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromUI2 [OLEAUT32.210]
- */
-HRESULT WINAPI VarI4FromUI2(USHORT uiIn, LONG* plOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, plOut );
-
- *plOut = (LONG) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromUI4 [OLEAUT32.211]
- */
-HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG* plOut)
-{
- TRACE("( %lx, %p ), stub\n", ulIn, plOut );
-
- /* Check range of value.
- */
- if( ulIn < I4_MIN || ulIn > I4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *plOut = (LONG) ulIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromI2 [OLEAUT32.59]
- */
-HRESULT WINAPI VarI4FromI2(short sIn, LONG* plOut)
-{
- TRACE("( %d, %p ), stub\n", sIn, plOut );
-
- *plOut = (LONG) sIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI4FromStr [OLEAUT32.64]
- */
-HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG* plOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, plOut);
- return _VarI4FromStr(strIn, lcid, dwFlags, plOut);
-}
-
-/**********************************************************************
- * VarI4FromCy [OLEAUT32.62]
- * Convert currency to signed long
- */
-HRESULT WINAPI VarI4FromCy(CY cyIn, LONG* plOut) {
- double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
-
- *plOut = (LONG)t;
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromUI1 [OLEAUT32.68]
- */
-HRESULT WINAPI VarR4FromUI1(BYTE bIn, FLOAT* pfltOut)
-{
- TRACE("( %X, %p ), stub\n", bIn, pfltOut );
-
- *pfltOut = (FLOAT) bIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromI2 [OLEAUT32.69]
- */
-HRESULT WINAPI VarR4FromI2(short sIn, FLOAT* pfltOut)
-{
- TRACE("( %d, %p ), stub\n", sIn, pfltOut );
-
- *pfltOut = (FLOAT) sIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromI4 [OLEAUT32.70]
- */
-HRESULT WINAPI VarR4FromI4(LONG lIn, FLOAT* pfltOut)
-{
- TRACE("( %lx, %p ), stub\n", lIn, pfltOut );
-
- *pfltOut = (FLOAT) lIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromR8 [OLEAUT32.71]
- */
-HRESULT WINAPI VarR4FromR8(double dblIn, FLOAT* pfltOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, pfltOut );
-
- /* Check range of value.
- */
- if( dblIn < -(R4_MAX) || dblIn > R4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pfltOut = (FLOAT) dblIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromDate [OLEAUT32.73]
- */
-HRESULT WINAPI VarR4FromDate(DATE dateIn, FLOAT* pfltOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, pfltOut );
-
- /* Check range of value.
- */
- if( dateIn < -(R4_MAX) || dateIn > R4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pfltOut = (FLOAT) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromBool [OLEAUT32.76]
- */
-HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, FLOAT* pfltOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, pfltOut );
-
- *pfltOut = (FLOAT) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromI1 [OLEAUT32.213]
- */
-HRESULT WINAPI VarR4FromI1(signed char cIn, FLOAT* pfltOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, pfltOut );
-
- *pfltOut = (FLOAT) cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromUI2 [OLEAUT32.214]
- */
-HRESULT WINAPI VarR4FromUI2(USHORT uiIn, FLOAT* pfltOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pfltOut );
-
- *pfltOut = (FLOAT) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromUI4 [OLEAUT32.215]
- */
-HRESULT WINAPI VarR4FromUI4(ULONG ulIn, FLOAT* pfltOut)
-{
- TRACE("( %ld, %p ), stub\n", ulIn, pfltOut );
-
- *pfltOut = (FLOAT) ulIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR4FromStr [OLEAUT32.74]
- */
-HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, FLOAT* pfltOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, pfltOut);
- return _VarR4FromStr(strIn, lcid, dwFlags, pfltOut);
-}
-
-/**********************************************************************
- * VarR4FromCy [OLEAUT32.72]
- * Convert currency to float
- */
-HRESULT WINAPI VarR4FromCy(CY cyIn, FLOAT* pfltOut) {
- *pfltOut = (FLOAT)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromUI1 [OLEAUT32.78]
- */
-HRESULT WINAPI VarR8FromUI1(BYTE bIn, double* pdblOut)
-{
- TRACE("( %d, %p ), stub\n", bIn, pdblOut );
-
- *pdblOut = (double) bIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromI2 [OLEAUT32.79]
- */
-HRESULT WINAPI VarR8FromI2(short sIn, double* pdblOut)
-{
- TRACE("( %d, %p ), stub\n", sIn, pdblOut );
-
- *pdblOut = (double) sIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromI4 [OLEAUT32.80]
- */
-HRESULT WINAPI VarR8FromI4(LONG lIn, double* pdblOut)
-{
- TRACE("( %ld, %p ), stub\n", lIn, pdblOut );
-
- *pdblOut = (double) lIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromR4 [OLEAUT32.81]
- */
-HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double* pdblOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, pdblOut );
-
- *pdblOut = (double) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromDate [OLEAUT32.83]
- */
-HRESULT WINAPI VarR8FromDate(DATE dateIn, double* pdblOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, pdblOut );
-
- *pdblOut = (double) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromBool [OLEAUT32.86]
- */
-HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double* pdblOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, pdblOut );
-
- *pdblOut = (double) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromI1 [OLEAUT32.217]
- */
-HRESULT WINAPI VarR8FromI1(signed char cIn, double* pdblOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, pdblOut );
-
- *pdblOut = (double) cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromUI2 [OLEAUT32.218]
- */
-HRESULT WINAPI VarR8FromUI2(USHORT uiIn, double* pdblOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pdblOut );
-
- *pdblOut = (double) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromUI4 [OLEAUT32.219]
- */
-HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double* pdblOut)
-{
- TRACE("( %ld, %p ), stub\n", ulIn, pdblOut );
-
- *pdblOut = (double) ulIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarR8FromStr [OLEAUT32.84]
- */
-HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double* pdblOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, pdblOut);
- return _VarR8FromStr(strIn, lcid, dwFlags, pdblOut);
-}
-
-/**********************************************************************
- * VarR8FromCy [OLEAUT32.82]
- * Convert currency to double
- */
-HRESULT WINAPI VarR8FromCy(CY cyIn, double* pdblOut) {
- *pdblOut = (double)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
- TRACE("%lu %ld -> %f\n", cyIn.s.Hi, cyIn.s.Lo, *pdblOut);
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromUI1 [OLEAUT32.88]
- */
-HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
-{
- TRACE("( %d, %p ), stub\n", bIn, pdateOut );
-
- *pdateOut = (DATE) bIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromI2 [OLEAUT32.89]
- */
-HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
-{
- TRACE("( %d, %p ), stub\n", sIn, pdateOut );
-
- *pdateOut = (DATE) sIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromI4 [OLEAUT32.90]
- */
-HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
-{
- TRACE("( %ld, %p ), stub\n", lIn, pdateOut );
-
- if( lIn < DATE_MIN || lIn > DATE_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pdateOut = (DATE) lIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromR4 [OLEAUT32.91]
- */
-HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, pdateOut );
-
- if( ceil(fltIn) < DATE_MIN || floor(fltIn) > DATE_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pdateOut = (DATE) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromR8 [OLEAUT32.92]
- */
-HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, pdateOut );
-
- if( ceil(dblIn) < DATE_MIN || floor(dblIn) > DATE_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pdateOut = (DATE) dblIn;
-
- return S_OK;
-}
-
-/* Date string parsing */
-#define DP_TIMESEP 0x01 /* Time seperator ( _must_ remain 0x1, used as a bitmask) */
-#define DP_DATESEP 0x02 /* Date seperator */
-#define DP_MONTH 0x04 /* Month name */
-#define DP_AM 0x08 /* AM */
-#define DP_PM 0x10 /* PM */
-
-typedef struct tagDATEPARSE
-{
- DWORD dwCount; /* Number of fields found so far (maximum 6) */
- DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
- DWORD dwFlags[6]; /* Flags for each field */
- DWORD dwValues[6]; /* Value of each field */
-} DATEPARSE;
-
-#define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
-
-#define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
-
-/* Determine if a day is valid in a given month of a given year */
-static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
+ LCID lcid, USHORT wFlags, VARTYPE vt)
{
- static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
- if (day && month && month < 13)
- {
- if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
- return TRUE;
- }
- return FALSE;
-}
-
-/* Possible orders for 3 numbers making up a date */
-#define ORDER_MDY 0x01
-#define ORDER_YMD 0x02
-#define ORDER_YDM 0x04
-#define ORDER_DMY 0x08
-#define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
+ HRESULT res = S_OK;
+ VARIANTARG varg;
-/* Determine a date for a particular locale, from 3 numbers */
-static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
- DWORD offset, SYSTEMTIME *st)
-{
- DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
+ V_VT(&varg) = VT_EMPTY;
- if (!dp->dwCount)
- {
- v1 = 30; /* Default to (Variant) 0 date part */
- v2 = 12;
- v3 = 1899;
- goto VARIANT_MakeDate_OK;
- }
+ TRACE("(%p->(%s%s),%p->(%s%s),0x%08lx,0x%04x,%s%s)\n", pvargDest,
+ debugstr_VT(pvargDest), debugstr_VF(pvargDest), pvargSrc,
+ debugstr_VT(pvargSrc), debugstr_VF(pvargSrc), lcid, wFlags,
+ debugstr_vt(vt), debugstr_vf(vt));
- v1 = dp->dwValues[offset + 0];
- v2 = dp->dwValues[offset + 1];
- if (dp->dwCount == 2)
+ if (vt == VT_CLSID)
{
- SYSTEMTIME current;
- GetSystemTime(¤t);
- v3 = current.wYear;
+ res = DISP_E_BADVARTYPE;
}
else
- v3 = dp->dwValues[offset + 2];
+ res = VARIANT_ValidateType(V_VT(pvargSrc));
- TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
+ if ( SUCCEEDED(res) )
+ res = VARIANT_ValidateType(vt);
- /* If one number must be a month (Because a month name was given), then only
- * consider orders with the month in that position.
- * If we took the current year as 'v3', then only allow a year in that position.
+ /* if we are doing an in-place conversion make a copy of the source.
*/
- if (dp->dwFlags[offset + 0] & DP_MONTH)
- {
- dwAllOrders = ORDER_MDY;
- }
- else if (dp->dwFlags[offset + 1] & DP_MONTH)
- {
- dwAllOrders = ORDER_DMY;
- if (dp->dwCount > 2)
- dwAllOrders |= ORDER_YMD;
- }
- else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
- {
- dwAllOrders = ORDER_YDM;
- }
- else
- {
- dwAllOrders = ORDER_MDY|ORDER_DMY;
- if (dp->dwCount > 2)
- dwAllOrders |= (ORDER_YMD|ORDER_YDM);
- }
-
-VARIANT_MakeDate_Start:
- TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
-
- while (dwAllOrders)
- {
- DWORD dwTemp;
-
- if (dwCount == 0)
- {
- /* First: Try the order given by iDate */
- switch (iDate)
- {
- case 0: dwTry = dwAllOrders & ORDER_MDY; break;
- case 1: dwTry = dwAllOrders & ORDER_DMY; break;
- default: dwTry = dwAllOrders & ORDER_YMD; break;
- }
- }
- else if (dwCount == 1)
- {
- /* Second: Try all the orders compatable with iDate */
- switch (iDate)
- {
- case 0: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
- case 1: dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
- default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
- }
- }
- else
- {
- /* Finally: Try any remaining orders */
- dwTry = dwAllOrders;
- }
-
- TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
-
- dwCount++;
- if (!dwTry)
- continue;
-
-#define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
-
- if (dwTry & ORDER_MDY)
- {
- if (VARIANT_IsValidMonthDay(v2,v1,v3))
- {
- DATE_SWAP(v1,v2);
- goto VARIANT_MakeDate_OK;
- }
- dwAllOrders &= ~ORDER_MDY;
- }
- if (dwTry & ORDER_YMD)
- {
- if (VARIANT_IsValidMonthDay(v3,v2,v1))
- {
- DATE_SWAP(v1,v3);
- goto VARIANT_MakeDate_OK;
- }
- dwAllOrders &= ~ORDER_YMD;
- }
- if (dwTry & ORDER_YDM)
- {
- if (VARIANT_IsValidMonthDay(v2,v3,v1))
- {
- DATE_SWAP(v1,v2);
- DATE_SWAP(v2,v3);
- goto VARIANT_MakeDate_OK;
- }
- dwAllOrders &= ~ORDER_YDM;
- }
- if (dwTry & ORDER_DMY)
- {
- if (VARIANT_IsValidMonthDay(v1,v2,v3))
- goto VARIANT_MakeDate_OK;
- dwAllOrders &= ~ORDER_DMY;
- }
- if (dwTry & ORDER_MYD)
- {
- /* Only occurs if we are trying a 2 year date as M/Y not D/M */
- if (VARIANT_IsValidMonthDay(v3,v1,v2))
- {
- DATE_SWAP(v1,v3);
- DATE_SWAP(v2,v3);
- goto VARIANT_MakeDate_OK;
- }
- dwAllOrders &= ~ORDER_MYD;
- }
- }
-
- if (dp->dwCount == 2)
+ if ( SUCCEEDED(res) && pvargDest == pvargSrc )
{
- /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
- v3 = 1; /* 1st of the month */
- dwAllOrders = ORDER_YMD|ORDER_MYD;
- dp->dwCount = 0; /* Don't return to this code path again */
- dwCount = 0;
- goto VARIANT_MakeDate_Start;
+ res = VariantCopy( &varg, pvargSrc );
+ pvargSrc = &varg;
}
- /* No valid dates were able to be constructed */
- return DISP_E_TYPEMISMATCH;
-
-VARIANT_MakeDate_OK:
-
- /* Check that the time part is ok */
- if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
- return DISP_E_TYPEMISMATCH;
-
- TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
- if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
- st->wHour += 12;
- else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
- st->wHour = 0;
- TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
-
- st->wDay = v1;
- st->wMonth = v2;
- /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
- * be retrieved from:
- * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
- * But Wine doesn't have/use that key as at the time of writing.
- */
- st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
- TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromStr [OLEAUT32.94]
- *
- * Convert a VT_BSTR to at VT_DATE.
- *
- * PARAMS
- * strIn [I] String to convert
- * lcid [I] Locale identifier for the conversion
- * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
- * pdateOut [O] Destination for the converted value
- *
- * RETURNS
- * Success: S_OK. pdateOut contains the converted value.
- * FAILURE: An HRESULT error code indicating the prolem.
- *
- * NOTES
- * Any date format that can be created using the date formats from lcid
- * (Either from kernel Nls functions, variant conversion or formatting) is a
- * valid input to this function. In addition, a few more esoteric formats are
- * also supported for compatability with the native version. The date is
- * interpreted according to the date settings in the control panel, unless
- * the date is invalid in that format, in which the most compatable format
- * that produces a valid date will be used.
- */
-HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
-{
- static const USHORT ParseDateTokens[] =
- {
- LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
- LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
- LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
- LOCALE_SMONTHNAME13,
- LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
- LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
- LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
- LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
- LOCALE_SABBREVMONTHNAME13,
- LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
- LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
- LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
- LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
- LOCALE_SABBREVDAYNAME7,
- LOCALE_S1159, LOCALE_S2359
- };
- static const BYTE ParseDateMonths[] =
- {
- 1,2,3,4,5,6,7,8,9,10,11,12,13,
- 1,2,3,4,5,6,7,8,9,10,11,12,13
- };
- size_t i;
- BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
- DATEPARSE dp;
- DWORD dwDateSeps = 0, iDate = 0;
- HRESULT hRet = S_OK;
-
- if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
- (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
- return E_INVALIDARG;
-
- if (!strIn)
- return DISP_E_TYPEMISMATCH;
-
- *pdateOut = 0.0;
-
- TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
-
- memset(&dp, 0, sizeof(dp));
-
- GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
- (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
- TRACE("iDate is %ld\n", iDate);
-
- /* Get the month/day/am/pm tokens for this locale */
- for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
+ if ( SUCCEEDED(res) )
{
- WCHAR buff[128];
- LCTYPE lctype = ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
-
- /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
- * GetAltMonthNames(). We should really cache these strings too.
+ /* free up the destination variant.
*/
- buff[0] = '\0';
- GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
- tokens[i] = SysAllocString(buff);
- TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
+ res = VariantClear( pvargDest );
}
- /* Parse the string into our structure */
- while (*strIn)
+ if ( SUCCEEDED(res) )
{
- if (dp.dwCount > 6)
- break;
-
- if (isdigitW(*strIn))
- {
- dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
- dp.dwCount++;
- strIn--;
- }
- else if (isalpha(*strIn))
+ if ( V_VT(pvargSrc) & VT_BYREF )
{
- BOOL bFound = FALSE;
+ /* Convert the source variant to a "byvalue" variant.
+ */
+ VARIANTARG Variant;
- for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
- {
- DWORD dwLen = strlenW(tokens[i]);
- if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
- {
- if (i <= 25)
- {
- dp.dwValues[dp.dwCount] = ParseDateMonths[i];
- dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
- dp.dwCount++;
- }
- else if (i > 39)
- {
- if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
- hRet = DISP_E_TYPEMISMATCH;
- else
- {
- dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
- dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
- }
- }
- strIn += (dwLen - 1);
- bFound = TRUE;
- break;
- }
+ if ((V_VT(pvargSrc) & 0xf000) != VT_BYREF) {
+ FIXME("VT_TYPEMASK %s is unhandled.\n", debugstr_VF(pvargSrc));
+ return E_FAIL;
}
- if (!bFound)
+ V_VT(&Variant) = VT_EMPTY;
+ res = VariantCopyInd( &Variant, pvargSrc );
+ if ( SUCCEEDED(res) )
{
- if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
- (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
- {
- /* Special case - 'a' and 'p' are recognised as short for am/pm */
- if (*strIn == 'a' || *strIn == 'A')
- {
- dp.dwFlags[dp.dwCount - 1] |= DP_AM;
- dp.dwParseFlags |= DP_AM;
- }
- else
- {
- dp.dwFlags[dp.dwCount - 1] |= DP_PM;
- dp.dwParseFlags |= DP_PM;
- }
- strIn++;
- }
- else
- {
- TRACE("No matching token for %s\n", debugstr_w(strIn));
- hRet = DISP_E_TYPEMISMATCH;
- break;
- }
+ res = Coerce( pvargDest, lcid, wFlags, &Variant, vt );
+ /* this should not fail.
+ */
+ VariantClear( &Variant );
}
}
- else if (*strIn == ':' || *strIn == '.')
- {
- if (!dp.dwCount || !strIn[1])
- hRet = DISP_E_TYPEMISMATCH;
- else
- dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
- }
- else if (*strIn == '-' || *strIn == '/')
- {
- dwDateSeps++;
- if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
- hRet = DISP_E_TYPEMISMATCH;
- else
- dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
- }
- else if (*strIn == ',' || isspaceW(*strIn))
- {
- if (*strIn == ',' && !strIn[1])
- hRet = DISP_E_TYPEMISMATCH;
- }
else
{
- hRet = DISP_E_TYPEMISMATCH;
- }
- strIn++;
- }
-
- if (!dp.dwCount || dp.dwCount > 6 ||
- (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
- hRet = DISP_E_TYPEMISMATCH;
-
- if (SUCCEEDED(hRet))
- {
- SYSTEMTIME st;
- DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
-
- st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
-
- /* Figure out which numbers correspond to which fields.
- *
- * This switch statement works based on the fact that native interprets any
- * fields that are not joined with a time seperator ('.' or ':') as date
- * fields. Thus we construct a value from 0-32 where each set bit indicates
- * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
- * For valid permutations, we set dwOffset to point to the first date field
- * and shorten dp.dwCount by the number of time fields found. The real
- * magic here occurs in VARIANT_MakeDate() above, where we determine what
- * each date number must represent in the context of iDate.
- */
- TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
-
- switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
- {
- case 0x1: /* TT TTDD TTDDD */
- if (dp.dwCount > 3 &&
- ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
- (dp.dwFlags[4] & (DP_AM|DP_PM))))
- hRet = DISP_E_TYPEMISMATCH;
- else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
- hRet = DISP_E_TYPEMISMATCH;
- st.wHour = dp.dwValues[0];
- st.wMinute = dp.dwValues[1];
- dp.dwCount -= 2;
- dwOffset = 2;
- break;
-
- case 0x3: /* TTT TTTDD TTTDDD */
- if (dp.dwCount > 4 &&
- ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
- (dp.dwFlags[5] & (DP_AM|DP_PM))))
- hRet = DISP_E_TYPEMISMATCH;
- else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
- hRet = DISP_E_TYPEMISMATCH;
- st.wHour = dp.dwValues[0];
- st.wMinute = dp.dwValues[1];
- st.wSecond = dp.dwValues[2];
- dwOffset = 3;
- dp.dwCount -= 3;
- break;
-
- case 0x4: /* DDTT */
- if (dp.dwCount != 4 ||
- (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
- hRet = DISP_E_TYPEMISMATCH;
-
- st.wHour = dp.dwValues[2];
- st.wMinute = dp.dwValues[3];
- dp.dwCount -= 2;
- break;
-
- case 0x0: /* T DD DDD TDDD TDDD */
- if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
- {
- st.wHour = dp.dwValues[0]; /* T */
- dp.dwCount = 0;
- break;
- }
- else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
- {
- hRet = DISP_E_TYPEMISMATCH;
- }
- else if (dp.dwCount == 3)
+ if (V_VT(pvargSrc) & VT_ARRAY)
{
- if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
- {
- dp.dwCount = 2;
- st.wHour = dp.dwValues[0];
- dwOffset = 1;
- break;
- }
- if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
+ if ((V_VT(pvargSrc) & 0xf000) != VT_ARRAY)
{
- dp.dwCount = 2;
- st.wHour = dp.dwValues[2];
- break;
+ FIXME("VT_TYPEMASK %s is unhandled in VT_ARRAY.\n", debugstr_VF(pvargSrc));
+ return E_FAIL;
}
- else if (dp.dwParseFlags & (DP_AM|DP_PM))
- hRet = DISP_E_TYPEMISMATCH;
+ V_VT(pvargDest) = VT_ARRAY | vt;
+ res = coerce_array(pvargSrc, pvargDest, lcid, wFlags, vt);
}
- else if (dp.dwCount == 4)
+ else
{
- dp.dwCount = 3;
- if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
- {
- st.wHour = dp.dwValues[0];
- dwOffset = 1;
- }
- else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
+ if ((V_VT(pvargSrc) & 0xf000))
{
- st.wHour = dp.dwValues[3];
+ FIXME("VT_TYPEMASK %s is unhandled in normal case.\n", debugstr_VF(pvargSrc));
+ return E_FAIL;
}
- else
- hRet = DISP_E_TYPEMISMATCH;
- break;
- }
- /* .. fall through .. */
-
- case 0x8: /* DDDTT */
- if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
- (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
- (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
- dp.dwCount == 4 || dp.dwCount == 6)
- hRet = DISP_E_TYPEMISMATCH;
- st.wHour = dp.dwValues[3];
- st.wMinute = dp.dwValues[4];
- if (dp.dwCount == 5)
- dp.dwCount -= 2;
- break;
-
- case 0xC: /* DDTTT */
- if (dp.dwCount != 5 ||
- (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
- hRet = DISP_E_TYPEMISMATCH;
- st.wHour = dp.dwValues[2];
- st.wMinute = dp.dwValues[3];
- st.wSecond = dp.dwValues[4];
- dp.dwCount -= 3;
- break;
-
- case 0x18: /* DDDTTT */
- if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
- (dp.dwFlags[2] & (DP_AM|DP_PM)))
- hRet = DISP_E_TYPEMISMATCH;
- st.wHour = dp.dwValues[3];
- st.wMinute = dp.dwValues[4];
- st.wSecond = dp.dwValues[5];
- dp.dwCount -= 3;
- break;
-
- default:
- hRet = DISP_E_TYPEMISMATCH;
- break;
- }
-
- if (SUCCEEDED(hRet))
- {
- hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
-
- if (dwFlags & VAR_TIMEVALUEONLY)
- {
- st.wYear = 1899;
- st.wMonth = 12;
- st.wDay = 30;
+ /* Use the current "byvalue" source variant.
+ */
+ res = Coerce( pvargDest, lcid, wFlags, pvargSrc, vt );
}
- else if (dwFlags & VAR_DATEVALUEONLY)
- st.wHour = st.wMinute = st.wSecond = 0;
-
- /* Finally, convert the value to a VT_DATE */
- if (SUCCEEDED(hRet))
- hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
}
}
- for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
- SysFreeString(tokens[i]);
- return hRet;
-}
-
-/******************************************************************************
- * VarDateFromI1 [OLEAUT32.221]
- */
-HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, pdateOut );
-
- *pdateOut = (DATE) cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromUI2 [OLEAUT32.222]
- */
-HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pdateOut );
-
- *pdateOut = (DATE) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromUI4 [OLEAUT32.223]
- */
-HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
-{
- TRACE("( %ld, %p ), stub\n", ulIn, pdateOut );
-
- if( ulIn < DATE_MIN || ulIn > DATE_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pdateOut = (DATE) ulIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarDateFromBool [OLEAUT32.96]
- */
-HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, pdateOut );
-
- *pdateOut = (DATE) boolIn;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarDateFromCy [OLEAUT32.93]
- * Convert currency to date
- */
-HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut) {
- *pdateOut = (DATE)((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromUI1 [OLEAUT32.108]
- */
-HRESULT WINAPI VarBstrFromUI1(BYTE bVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %d, %ld, %ld, %p ), stub\n", bVal, lcid, dwFlags, pbstrOut );
- sprintf( pBuffer, "%d", bVal );
-
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromI2 [OLEAUT32.109]
- */
-HRESULT WINAPI VarBstrFromI2(short iVal, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %d, %ld, %ld, %p ), stub\n", iVal, lcid, dwFlags, pbstrOut );
- sprintf( pBuffer, "%d", iVal );
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromI4 [OLEAUT32.110]
- */
-HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %ld, %ld, %ld, %p ), stub\n", lIn, lcid, dwFlags, pbstrOut );
-
- sprintf( pBuffer, "%ld", lIn );
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromR4 [OLEAUT32.111]
- */
-HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %f, %ld, %ld, %p ), stub\n", fltIn, lcid, dwFlags, pbstrOut );
-
- sprintf( pBuffer, "%.7G", fltIn );
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromR8 [OLEAUT32.112]
- */
-HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %f, %ld, %ld, %p ), stub\n", dblIn, lcid, dwFlags, pbstrOut );
-
- sprintf( pBuffer, "%.15G", dblIn );
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromCy [OLEAUT32.113]
- */
-HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) {
- HRESULT rc = S_OK;
- double curVal = 0.0;
-
- TRACE("([cyIn], %08lx, %08lx, %p), partial stub (no flags handled).\n", lcid, dwFlags, pbstrOut);
-
- /* Firstly get the currency in a double, then put it in a buffer */
- rc = VarR8FromCy(cyIn, &curVal);
- if (rc == S_OK) {
- sprintf(pBuffer, "%G", curVal);
- *pbstrOut = StringDupAtoBstr( pBuffer );
- }
- return rc;
-}
-
-
-/******************************************************************************
- * VarBstrFromDate [OLEAUT32.114]
- *
- * Convert a VT_DATE to a VT_BSTR.
- *
- * PARAMS
- * dateIn [I] Source
- * lcid [I] LCID for the conversion
- * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
- * pbstrOut [O] Destination
- *
- * RETURNS
- * Success: S_OK.
- * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
- * E_OUTOFMEMORY, if memory allocation fails.
- */
-HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- SYSTEMTIME st;
- DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
- WCHAR date[128], *time;
-
- TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
-
- if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
- return E_INVALIDARG;
-
- *pbstrOut = NULL;
-
- if (dwFlags & VAR_CALENDAR_THAI)
- st.wYear += 553; /* Use the Thai buddhist calendar year */
- else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
- FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
-
- if (dwFlags & LOCALE_USE_NLS)
- dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
- else
- {
- double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
- double partial = dateIn - whole;
-
- if (whole == 0.0)
- dwFlags |= VAR_TIMEVALUEONLY;
- else if (partial < 1e-12)
- dwFlags |= VAR_DATEVALUEONLY;
- }
-
- if (dwFlags & VAR_TIMEVALUEONLY)
- date[0] = '\0';
- else
- if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
- sizeof(date)/sizeof(WCHAR)))
- return E_INVALIDARG;
-
- if (!(dwFlags & VAR_DATEVALUEONLY))
- {
- time = date + strlenW(date);
- if (time != date)
- *time++ = ' ';
- if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
- sizeof(date)/sizeof(WCHAR)-(time-date)))
- return E_INVALIDARG;
- }
-
- *pbstrOut = SysAllocString(date);
- if (*pbstrOut)
- TRACE("returning %s\n", debugstr_w(*pbstrOut));
- return *pbstrOut ? S_OK : E_OUTOFMEMORY;
-}
-
-/******************************************************************************
- * VarBstrFromBool [OLEAUT32.116]
- */
-HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %d, %ld, %ld, %p ), stub\n", boolIn, lcid, dwFlags, pbstrOut );
-
- sprintf( pBuffer, (boolIn == VARIANT_FALSE) ? "False" : "True" );
-
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromI1 [OLEAUT32.229]
- */
-HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %c, %ld, %ld, %p ), stub\n", cIn, lcid, dwFlags, pbstrOut );
- sprintf( pBuffer, "%d", cIn );
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromUI2 [OLEAUT32.230]
- */
-HRESULT WINAPI VarBstrFromUI2(USHORT uiIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %d, %ld, %ld, %p ), stub\n", uiIn, lcid, dwFlags, pbstrOut );
- sprintf( pBuffer, "%d", uiIn );
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromUI4 [OLEAUT32.231]
- */
-HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- TRACE("( %ld, %ld, %ld, %p ), stub\n", ulIn, lcid, dwFlags, pbstrOut );
- sprintf( pBuffer, "%ld", ulIn );
- *pbstrOut = StringDupAtoBstr( pBuffer );
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBstrFromDec [OLEAUT32.@]
- */
-HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
- if(!pDecIn->u.s.sign && !pDecIn->u.s.scale &&
- !pDecIn->Hi32 && !pDecIn->u1.s1.Mid32)
- return VarBstrFromUI4(pDecIn->u1.s1.Lo32, lcid, dwFlags, pbstrOut);
- FIXME("%c%08lx%08lx%08lx E%02x stub\n",
- (pDecIn->u.s.sign == DECIMAL_NEG) ? '-' :
- (pDecIn->u.s.sign == 0) ? '+' : '?',
- pDecIn->Hi32, pDecIn->u1.s1.Mid32, pDecIn->u1.s1.Lo32,
- pDecIn->u.s.scale);
- return E_INVALIDARG;
-}
-
-/******************************************************************************
- * VarBoolFromUI1 [OLEAUT32.118]
- */
-HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %d, %p ), stub\n", bIn, pboolOut );
-
- if( bIn == 0 )
- {
- *pboolOut = VARIANT_FALSE;
- }
- else
- {
- *pboolOut = VARIANT_TRUE;
- }
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromI2 [OLEAUT32.119]
- */
-HRESULT WINAPI VarBoolFromI2(short sIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %d, %p ), stub\n", sIn, pboolOut );
-
- *pboolOut = (sIn) ? VARIANT_TRUE : VARIANT_FALSE;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromI4 [OLEAUT32.120]
- */
-HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %ld, %p ), stub\n", lIn, pboolOut );
-
- *pboolOut = (lIn) ? VARIANT_TRUE : VARIANT_FALSE;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromR4 [OLEAUT32.121]
- */
-HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, pboolOut );
-
- *pboolOut = (fltIn == 0.0) ? VARIANT_FALSE : VARIANT_TRUE;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromR8 [OLEAUT32.122]
- */
-HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, pboolOut );
-
- *pboolOut = (dblIn == 0.0) ? VARIANT_FALSE : VARIANT_TRUE;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromDate [OLEAUT32.123]
- */
-HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, pboolOut );
-
- *pboolOut = (dateIn == 0.0) ? VARIANT_FALSE : VARIANT_TRUE;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromStr [OLEAUT32.125]
- */
-HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL* pboolOut)
-{
- static const WCHAR szTrue[] = { 'T','r','u','e','\0' };
- static const WCHAR szFalse[] = { 'F','a','l','s','e','\0' };
- HRESULT ret = S_OK;
-
- TRACE("( %p, %ld, %ld, %p ), stub\n", strIn, lcid, dwFlags, pboolOut );
-
- if( strIn == NULL || strlenW( strIn ) == 0 )
- {
- ret = DISP_E_TYPEMISMATCH;
- }
-
- if( ret == S_OK )
- {
- if( strcmpiW( (LPCWSTR)strIn, szTrue ) == 0 )
- {
- *pboolOut = VARIANT_TRUE;
- }
- else if( strcmpiW( (LPCWSTR)strIn, szFalse ) == 0 )
- {
- *pboolOut = VARIANT_FALSE;
- }
- else
- {
- /* Try converting the string to a floating point number.
- */
- double dValue = 0.0;
- HRESULT res = VarR8FromStr( strIn, lcid, dwFlags, &dValue );
- if( res != S_OK )
- {
- ret = DISP_E_TYPEMISMATCH;
- }
- else
- *pboolOut = (dValue == 0.0) ?
- VARIANT_FALSE : VARIANT_TRUE;
- }
- }
-
- return ret;
-}
-
-/******************************************************************************
- * VarBoolFromI1 [OLEAUT32.233]
- */
-HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, pboolOut );
-
- *pboolOut = (cIn == 0) ? VARIANT_FALSE : VARIANT_TRUE;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromUI2 [OLEAUT32.234]
- */
-HRESULT WINAPI VarBoolFromUI2(USHORT uiIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pboolOut );
-
- *pboolOut = (uiIn == 0) ? VARIANT_FALSE : VARIANT_TRUE;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarBoolFromUI4 [OLEAUT32.235]
- */
-HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL* pboolOut)
-{
- TRACE("( %ld, %p ), stub\n", ulIn, pboolOut );
-
- *pboolOut = (ulIn == 0) ? VARIANT_FALSE : VARIANT_TRUE;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarBoolFromCy [OLEAUT32.124]
- * Convert currency to boolean
- */
-HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL* pboolOut) {
- if (cyIn.s.Hi || cyIn.s.Lo) *pboolOut = -1;
- else *pboolOut = 0;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromUI1 [OLEAUT32.244]
- */
-HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char *pcOut)
-{
- TRACE("( %d, %p ), stub\n", bIn, pcOut );
-
- /* Check range of value.
- */
- if( bIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) bIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromI2 [OLEAUT32.245]
- */
-HRESULT WINAPI VarI1FromI2(short uiIn, signed char *pcOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pcOut );
-
- if( uiIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromI4 [OLEAUT32.246]
- */
-HRESULT WINAPI VarI1FromI4(LONG lIn, signed char *pcOut)
-{
- TRACE("( %ld, %p ), stub\n", lIn, pcOut );
-
- if( lIn < I1_MIN || lIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) lIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromR4 [OLEAUT32.247]
- */
-HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char *pcOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, pcOut );
-
- fltIn = round( fltIn );
- if( fltIn < I1_MIN || fltIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromR8 [OLEAUT32.248]
- */
-HRESULT WINAPI VarI1FromR8(double dblIn, signed char *pcOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, pcOut );
-
- dblIn = round( dblIn );
- if( dblIn < I1_MIN || dblIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) dblIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromDate [OLEAUT32.249]
- */
-HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char *pcOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, pcOut );
-
- dateIn = round( dateIn );
- if( dateIn < I1_MIN || dateIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromStr [OLEAUT32.251]
- */
-HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char *pcOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, pcOut);
- return _VarI1FromStr(strIn, lcid, dwFlags, pcOut);
-}
-
-/******************************************************************************
- * VarI1FromBool [OLEAUT32.253]
- */
-HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char *pcOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, pcOut );
-
- *pcOut = (CHAR) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromUI2 [OLEAUT32.254]
- */
-HRESULT WINAPI VarI1FromUI2(USHORT uiIn, signed char *pcOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pcOut );
-
- if( uiIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarI1FromUI4 [OLEAUT32.255]
- */
-HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char *pcOut)
-{
- TRACE("( %ld, %p ), stub\n", ulIn, pcOut );
-
- if( ulIn > I1_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pcOut = (CHAR) ulIn;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarI1FromCy [OLEAUT32.250]
- * Convert currency to signed char
- */
-HRESULT WINAPI VarI1FromCy(CY cyIn, signed char *pcOut) {
- double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- if (t > I1_MAX || t < I1_MIN) return DISP_E_OVERFLOW;
-
- *pcOut = (CHAR)t;
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromUI1 [OLEAUT32.257]
- */
-HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* puiOut)
-{
- TRACE("( %d, %p ), stub\n", bIn, puiOut );
-
- *puiOut = (USHORT) bIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromI2 [OLEAUT32.258]
- */
-HRESULT WINAPI VarUI2FromI2(short uiIn, USHORT* puiOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, puiOut );
-
- if( uiIn < UI2_MIN )
- {
- return DISP_E_OVERFLOW;
- }
-
- *puiOut = (USHORT) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromI4 [OLEAUT32.259]
- */
-HRESULT WINAPI VarUI2FromI4(LONG lIn, USHORT* puiOut)
-{
- TRACE("( %ld, %p ), stub\n", lIn, puiOut );
-
- if( lIn < UI2_MIN || lIn > UI2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *puiOut = (USHORT) lIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromR4 [OLEAUT32.260]
- */
-HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* puiOut)
-{
- TRACE("( %f, %p ), stub\n", fltIn, puiOut );
-
- fltIn = round( fltIn );
- if( fltIn < UI2_MIN || fltIn > UI2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *puiOut = (USHORT) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromR8 [OLEAUT32.261]
- */
-HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* puiOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, puiOut );
-
- dblIn = round( dblIn );
- if( dblIn < UI2_MIN || dblIn > UI2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *puiOut = (USHORT) dblIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromDate [OLEAUT32.262]
- */
-HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* puiOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, puiOut );
-
- dateIn = round( dateIn );
- if( dateIn < UI2_MIN || dateIn > UI2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *puiOut = (USHORT) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromStr [OLEAUT32.264]
- */
-HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* puiOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, puiOut);
- return _VarUI2FromStr(strIn, lcid, dwFlags, puiOut);
-}
-
-/******************************************************************************
- * VarUI2FromBool [OLEAUT32.266]
- */
-HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* puiOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, puiOut );
-
- *puiOut = (USHORT) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromI1 [OLEAUT32.267]
- */
-HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* puiOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, puiOut );
-
- *puiOut = (USHORT) cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI2FromUI4 [OLEAUT32.268]
- */
-HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* puiOut)
-{
- TRACE("( %ld, %p ), stub\n", ulIn, puiOut );
-
- if( ulIn > UI2_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *puiOut = (USHORT) ulIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromStr [OLEAUT32.277]
- */
-HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG* pulOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, pulOut);
- return _VarUI4FromStr(strIn, lcid, dwFlags, pulOut);
-}
-
-/**********************************************************************
- * VarUI2FromCy [OLEAUT32.263]
- * Convert currency to unsigned short
- */
-HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut) {
- double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
-
- *pusOut = (USHORT)t;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromUI1 [OLEAUT32.270]
- */
-HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG* pulOut)
-{
- TRACE("( %d, %p ), stub\n", bIn, pulOut );
-
- *pulOut = (USHORT) bIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromI2 [OLEAUT32.271]
- */
-HRESULT WINAPI VarUI4FromI2(short uiIn, ULONG* pulOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pulOut );
-
- if( uiIn < UI4_MIN )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pulOut = (ULONG) uiIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromI4 [OLEAUT32.272]
- */
-HRESULT WINAPI VarUI4FromI4(LONG lIn, ULONG* pulOut)
-{
- TRACE("( %ld, %p ), stub\n", lIn, pulOut );
-
- if( lIn < 0 )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pulOut = (ULONG) lIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromR4 [OLEAUT32.273]
- */
-HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG* pulOut)
-{
- fltIn = round( fltIn );
- if( fltIn < UI4_MIN || fltIn > UI4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pulOut = (ULONG) fltIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromR8 [OLEAUT32.274]
- */
-HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG* pulOut)
-{
- TRACE("( %f, %p ), stub\n", dblIn, pulOut );
-
- dblIn = round( dblIn );
- if( dblIn < UI4_MIN || dblIn > UI4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pulOut = (ULONG) dblIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromDate [OLEAUT32.275]
- */
-HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG* pulOut)
-{
- TRACE("( %f, %p ), stub\n", dateIn, pulOut );
-
- dateIn = round( dateIn );
- if( dateIn < UI4_MIN || dateIn > UI4_MAX )
- {
- return DISP_E_OVERFLOW;
- }
-
- *pulOut = (ULONG) dateIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromBool [OLEAUT32.279]
- */
-HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG* pulOut)
-{
- TRACE("( %d, %p ), stub\n", boolIn, pulOut );
-
- *pulOut = (ULONG) boolIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromI1 [OLEAUT32.280]
- */
-HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG* pulOut)
-{
- TRACE("( %c, %p ), stub\n", cIn, pulOut );
-
- *pulOut = (ULONG) cIn;
-
- return S_OK;
-}
-
-/******************************************************************************
- * VarUI4FromUI2 [OLEAUT32.281]
- */
-HRESULT WINAPI VarUI4FromUI2(USHORT uiIn, ULONG* pulOut)
-{
- TRACE("( %d, %p ), stub\n", uiIn, pulOut );
-
- *pulOut = (ULONG) uiIn;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarUI4FromCy [OLEAUT32.276]
- * Convert currency to unsigned long
- */
-HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG* pulOut) {
- double t = round((((double)cyIn.s.Hi * 4294967296.0) + (double)cyIn.s.Lo) / 10000);
-
- if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
-
- *pulOut = (ULONG)t;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromUI1 [OLEAUT32.98]
- * Convert unsigned char to currency
- */
-HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pcyOut) {
- pcyOut->s.Hi = 0;
- pcyOut->s.Lo = ((ULONG)bIn) * 10000;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromI2 [OLEAUT32.99]
- * Convert signed short to currency
- */
-HRESULT WINAPI VarCyFromI2(short sIn, CY* pcyOut) {
- if (sIn < 0) pcyOut->s.Hi = -1;
- else pcyOut->s.Hi = 0;
- pcyOut->s.Lo = ((ULONG)sIn) * 10000;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromI4 [OLEAUT32.100]
- * Convert signed long to currency
- */
-HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pcyOut) {
- double t = (double)lIn * (double)10000;
- pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
- pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
- if (lIn < 0) pcyOut->s.Hi--;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromR4 [OLEAUT32.101]
- * Convert float to currency
- */
-HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pcyOut) {
- double t = round((double)fltIn * (double)10000);
- pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
- pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
- if (fltIn < 0) pcyOut->s.Hi--;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromR8 [OLEAUT32.102]
- * Convert double to currency
- */
-HRESULT WINAPI VarCyFromR8(double dblIn, CY* pcyOut) {
- double t = round(dblIn * (double)10000);
- pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
- pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
- if (dblIn < 0) pcyOut->s.Hi--;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromDate [OLEAUT32.103]
- * Convert date to currency
- */
-HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
- double t = round((double)dateIn * (double)10000);
- pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
- pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
- if (dateIn < 0) pcyOut->s.Hi--;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromStr [OLEAUT32.104]
- * FIXME: Never tested with decimal separator other than '.'
- */
-HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut)
-{
- TRACE("(%s, 0x%08lx, 0x%08lx, %p)\n", debugstr_w(strIn), lcid, dwFlags, pcyOut);
- return _VarCyFromStr(strIn, lcid, dwFlags, pcyOut);
-}
-
-
-/**********************************************************************
- * VarCyFromBool [OLEAUT32.106]
- * Convert boolean to currency
- */
-HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pcyOut) {
- if (boolIn < 0) pcyOut->s.Hi = -1;
- else pcyOut->s.Hi = 0;
- pcyOut->s.Lo = (ULONG)boolIn * (ULONG)10000;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromI1 [OLEAUT32.225]
- * Convert signed char to currency
- */
-HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pcyOut) {
- if (cIn < 0) pcyOut->s.Hi = -1;
- else pcyOut->s.Hi = 0;
- pcyOut->s.Lo = (ULONG)cIn * (ULONG)10000;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromUI2 [OLEAUT32.226]
- * Convert unsigned short to currency
- */
-HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pcyOut) {
- pcyOut->s.Hi = 0;
- pcyOut->s.Lo = (ULONG)usIn * (ULONG)10000;
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarCyFromUI4 [OLEAUT32.227]
- * Convert unsigned long to currency
- */
-HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pcyOut) {
- double t = (double)ulIn * (double)10000;
- pcyOut->s.Hi = (LONG)(t / (double)4294967296.0);
- pcyOut->s.Lo = (ULONG)fmod(t, (double)4294967296.0);
-
- return S_OK;
-}
-
-/**********************************************************************
- * VarDecFromStr [OLEAUT32.@]
- */
-HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags,
- DECIMAL* pdecOut)
-{ WCHAR *p=strIn;
- ULONGLONG t;
- ULONG cy;
-
- DECIMAL_SETZERO(pdecOut);
-
- if(*p == (WCHAR)'-')pdecOut->u.s.sign= DECIMAL_NEG;
- if((*p == (WCHAR)'-') || (*p == (WCHAR)'+')) p++;
- for(;*p != (WCHAR)0; p++) {
- if((*p < (WCHAR)'0')||(*p > (WCHAR)'9')) goto error ;
- t = (ULONGLONG)pdecOut->u1.s1.Lo32 *(ULONGLONG)10
- + (ULONGLONG)(*p -(WCHAR)'0');
- cy = (ULONG)(t >> 32);
- pdecOut->u1.s1.Lo32 = (ULONG)(t & (ULONGLONG)UI4_MAX);
- t = (ULONGLONG)pdecOut->u1.s1.Mid32 * (ULONGLONG)10
- + (ULONGLONG)cy;
- cy = (ULONG)(t >> 32);
- pdecOut->u1.s1.Mid32 = (ULONG)(t & (ULONGLONG)UI4_MAX);
- t = (ULONGLONG)pdecOut->Hi32 * (ULONGLONG)10
- + (ULONGLONG)cy;
- cy = (ULONG)(t >> 32);
- pdecOut->Hi32 = (ULONG)(t & (ULONGLONG)UI4_MAX);
- if(cy) goto overflow ;
- }
- TRACE("%s -> sign %02x,hi %08lx,mid %08lx, lo%08lx, scale %08x\n",
- debugstr_w(strIn),
- pdecOut->u.s.sign, pdecOut->Hi32, pdecOut->u1.s1.Mid32,
- pdecOut->u1.s1.Lo32, pdecOut->u.s.scale);
- return S_OK;
+ VariantClear( &varg );
-overflow:
- /* like NT4 SP5 */
- pdecOut->Hi32 = pdecOut->u1.s1.Mid32 = pdecOut->u1.s1.Lo32 = 0xffffffff;
- return DISP_E_OVERFLOW;
+ if ( SUCCEEDED(res) )
+ V_VT(pvargDest) = vt;
-error:
- ERR("%s: unknown char at pos %d\n",
- debugstr_w(strIn), p - strIn + 1);
- return DISP_E_TYPEMISMATCH;
+ TRACE("returning 0x%08lx, %p->(%s%s)\n", res, pvargDest,
+ debugstr_VT(pvargDest), debugstr_VF(pvargDest));
+ return res;
}
/* Date Conversions */
@@ -5035,7 +1885,7 @@
/* VTBIT flags indicating an integer value */
#define INTEGER_VTBITS (VTBIT_I1|VTBIT_UI1|VTBIT_I2|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_I8|VTBIT_UI8)
/* VTBIT flags indicating a real number value */
-#define REAL_VTBITS (VTBIT_R4|VTBIT_R8|VTBIT_CY|VTBIT_DECIMAL)
+#define REAL_VTBITS (VTBIT_R4|VTBIT_R8|VTBIT_CY)
/**********************************************************************
* VarNumFromParseNum [OLEAUT32.47]
@@ -5065,7 +1915,7 @@
HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
ULONG dwVtBits, VARIANT *pVarDst)
{
- /* Scale factors and limits for double arithmetics */
+ /* Scale factors and limits for double arithmatic */
static const double dblMultipliers[11] = {
1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0,
1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0
@@ -5130,12 +1980,14 @@
pNumprs->nPwr10, wholeNumberDigits, fractionalDigits);
TRACE("mult %d; div %d\n", multiplier10, divisor10);
- if (dwVtBits & INTEGER_VTBITS &&
+ if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) &&
(!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL))))
{
/* We have one or more integer output choices, and either:
* 1) An integer input value, or
* 2) A real number input value but no floating output choices.
+ * Alternately, we have a DECIMAL output available and an integer input.
+ *
* So, place the integer value into pVarDst, using the smallest type
* possible and preferring signed over unsigned types.
*/
@@ -5243,6 +2095,15 @@
V_I8(pVarDst) = -ul64;
return S_OK;
}
+ else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
+ {
+ /* Decimal is only output choice left - fast path */
+ V_VT(pVarDst) = VT_DECIMAL;
+ DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
+ DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
+ DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
+ return S_OK;
+ }
}
}
else if (!bOverflow)
@@ -5254,48 +2115,57 @@
V_I1(pVarDst) = ul64;
return S_OK;
}
- if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
+ else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
{
V_VT(pVarDst) = VT_UI1;
V_UI1(pVarDst) = ul64;
return S_OK;
}
- if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
+ else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
{
V_VT(pVarDst) = VT_I2;
V_I2(pVarDst) = ul64;
return S_OK;
}
- if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
+ else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
{
V_VT(pVarDst) = VT_UI2;
V_UI2(pVarDst) = ul64;
return S_OK;
}
- if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
+ else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
{
V_VT(pVarDst) = VT_I4;
V_I4(pVarDst) = ul64;
return S_OK;
}
- if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
+ else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
{
V_VT(pVarDst) = VT_UI4;
V_UI4(pVarDst) = ul64;
return S_OK;
}
- if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
+ else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
{
V_VT(pVarDst) = VT_I8;
V_I8(pVarDst) = ul64;
return S_OK;
}
- if (dwVtBits & VTBIT_UI8)
+ else if (dwVtBits & VTBIT_UI8)
{
V_VT(pVarDst) = VT_UI8;
V_UI8(pVarDst) = ul64;
return S_OK;
}
+ else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
+ {
+ /* Decimal is only output choice left - fast path */
+ V_VT(pVarDst) = VT_DECIMAL;
+ DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
+ DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
+ DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
+ return S_OK;
+ }
}
}
@@ -5388,85 +2258,66 @@
}
TRACE("Value Overflows CY\n");
}
-
- if (!bOverflow && dwVtBits & VTBIT_DECIMAL)
- {
- WARN("VTBIT_DECIMAL not yet implemented\n");
-#if 0
- if (SUCCEEDED(VarDecFromR8(bNegative ? -whole : whole, &V_DECIMAL(pVarDst))))
- {
- V_VT(pVarDst) = VT_DECIMAL; /* Fits into a decimal */
- TRACE("Set DECIMAL to final value\n");
- return S_OK;
- }
-#endif
- }
}
if (dwVtBits & VTBIT_DECIMAL)
{
- FIXME("VT_DECIMAL > R8 not yet supported, returning overflow\n");
- }
- return DISP_E_OVERFLOW; /* No more output choices */
-}
-
-/**********************************************************************
- * VarBstrCmp [OLEAUT32.314]
- *
- * flags can be:
- * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS
- * NORM_IGNORESTRINGWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA
- *
- */
-HRESULT WINAPI VarBstrCmp(BSTR left, BSTR right, LCID lcid, DWORD flags)
-{
- INT r;
-
- TRACE("( %s %s %ld %lx ) partial stub\n", debugstr_w(left), debugstr_w(right), lcid, flags);
-
- /* Contrary to the MSDN, this returns eq for null vs null, null vs L"" and L"" vs NULL */
- if((!left) || (!right)) {
+ int i;
+ ULONG carry;
+ ULONG64 tmp;
+ DECIMAL* pDec = &V_DECIMAL(pVarDst);
- if (!left && (!right || *right==0)) return VARCMP_EQ;
- else if (!right && (!left || *left==0)) return VARCMP_EQ;
- else return VARCMP_NULL;
- }
+ DECIMAL_SETZERO(pDec);
+ DEC_LO32(pDec) = 0;
- if(flags&NORM_IGNORECASE)
- r = lstrcmpiW(left,right);
+ if (pNumprs->dwOutFlags & NUMPRS_NEG)
+ DEC_SIGN(pDec) = DECIMAL_NEG;
else
- r = lstrcmpW(left,right);
-
- if(r<0)
- return VARCMP_LT;
- if(r>0)
- return VARCMP_GT;
-
- return VARCMP_EQ;
-}
+ DEC_SIGN(pDec) = DECIMAL_POS;
-/**********************************************************************
- * VarBstrCat [OLEAUT32.313]
- */
-HRESULT WINAPI VarBstrCat(BSTR left, BSTR right, BSTR *out)
-{
- BSTR result;
- int size = 0;
+ /* Factor the significant digits */
+ for (i = 0; i < pNumprs->cDig; i++)
+ {
+ tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
+ carry = (ULONG)(tmp >> 32);
+ DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
+ tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
+ carry = (ULONG)(tmp >> 32);
+ DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
+ tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
+ DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
- TRACE("( %s %s %p )\n", debugstr_w(left), debugstr_w(right), out);
+ if (tmp >> 32 & UI4_MAX)
+ {
+VarNumFromParseNum_DecOverflow:
+ TRACE("Overflow\n");
+ DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
+ return DISP_E_OVERFLOW;
+ }
+ }
- /* On Windows, NULL parms are still handled (as empty strings) */
- if (left) size=size + lstrlenW(left);
- if (right) size=size + lstrlenW(right);
+ /* Account for the scale of the number */
+ while (multiplier10 > 0)
+ {
+ tmp = (ULONG64)DEC_LO32(pDec) * 10;
+ carry = (ULONG)(tmp >> 32);
+ DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
+ tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
+ carry = (ULONG)(tmp >> 32);
+ DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
+ tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
+ DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
- if (out) {
- result = SysAllocStringLen(NULL, size);
- *out = result;
- if (left) lstrcatW(result,left);
- if (right) lstrcatW(result,right);
- TRACE("result = %s, [%p]\n", debugstr_w(result), result);
+ if (tmp >> 32 & UI4_MAX)
+ goto VarNumFromParseNum_DecOverflow;
+ multiplier10--;
}
+ DEC_SCALE(pDec) = divisor10;
+
+ V_VT(pVarDst) = VT_DECIMAL;
return S_OK;
+ }
+ return DISP_E_OVERFLOW; /* No more output choices */
}
/**********************************************************************
@@ -6204,10 +3055,7 @@
case VT_DATE:
ABS_CASE(R8,R8_MIN);
case VT_CY:
- /* FIXME: Waiting for this function to be implemented */
-#if 0
hRet = VarCyAbs(V_CY(pVarIn), & V_CY(pVarOut));
-#endif
break;
case VT_DECIMAL:
DEC_SIGN(&V_DECIMAL(pVarOut)) &= ~DECIMAL_NEG;
@@ -6278,9 +3126,7 @@
case VT_I2: V_I2(pVarOut) = ~V_I2(pVarIn); break;
case VT_UI2: V_UI2(pVarOut) = ~V_UI2(pVarIn); break;
case VT_DECIMAL:
- /* FIXME Waiting for this function to be implemented */
-/* hRet = VarI4FromDec(&V_DECIMAL(pVarIn), &V_I4(&varIn)); */
- hRet = DISP_E_OVERFLOW;
+ hRet = VarI4FromDec(&V_DECIMAL(pVarIn), &V_I4(&varIn));
if (FAILED(hRet))
break;
pVarIn = &varIn;
@@ -6330,24 +3176,6 @@
}
/**********************************************************************
- * VarCyMulI4 [OLEAUT32.304]
- * Multiply currency value by integer
- */
-HRESULT WINAPI VarCyMulI4(CY cyIn, LONG mulBy, CY *pcyOut) {
-
- double cyVal = 0;
- HRESULT rc = S_OK;
-
- rc = VarR8FromCy(cyIn, &cyVal);
- if (rc == S_OK) {
- rc = VarCyFromR8((cyVal * (double) mulBy), pcyOut);
- TRACE("Multiply %f by %ld = %f [%ld,%lu]\n", cyVal, mulBy, (cyVal * (double) mulBy),
- pcyOut->s.Hi, pcyOut->s.Lo);
- }
- return rc;
-}
-
-/**********************************************************************
* VarMod [OLEAUT32.154]
*
*/
--- wine/dlls/oleaut32/vartype.c 1970-01-01 00:00:00.000000000 +0000
+++ wine-develop/dlls/oleaut32/vartype.c 2003-12-09 23:33:23.000000000 +0000
@@ -0,0 +1,6543 @@
+/*
+ * Low level variant functions
+ *
+ * Copyright 2003 Jon Griffiths
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winnt.h"
+#include "variant.h"
+#include "resource.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+extern HMODULE OLEAUT32_hModule;
+
+static const WCHAR szFloatFormatW[] = { '%','.','7','G','\0' };
+static const WCHAR szDoubleFormatW[] = { '%','.','1','5','G','\0' };
+
+/* Copy data from one variant to another. */
+static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
+{
+ switch (vt)
+ {
+ case VT_I1:
+ case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
+ case VT_BOOL:
+ case VT_I2:
+ case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
+ case VT_R4:
+ case VT_INT:
+#ifndef _WIN64
+ case VT_INT_PTR:
+#endif
+ case VT_I4:
+ case VT_UINT:
+ case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
+ case VT_R8:
+ case VT_DATE:
+ case VT_CY:
+#ifdef _WIN64
+ case VT_INT_PTR:
+#endif
+ case VT_I8:
+ case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONG64)); break;
+ case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
+ default:
+ FIXME("VT_ type %d unhandled, please report!\n", vt);
+ }
+}
+
+
+/* Coerce VT_BSTR to a numeric type */
+HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
+ void* pOut, VARTYPE vt)
+{
+ VARIANTARG dstVar;
+ HRESULT hRet;
+ NUMPARSE np;
+ BYTE rgb[1024];
+
+ /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
+ np.cDig = sizeof(rgb) / sizeof(BYTE);
+ np.dwInFlags = NUMPRS_STD;
+
+ hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
+
+ if (SUCCEEDED(hRet))
+ {
+ /* 1 << vt gives us the VTBIT constant for the destination number type */
+ hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
+ if (SUCCEEDED(hRet))
+ VARIANT_CopyData(&dstVar, vt, pOut);
+ }
+ return hRet;
+}
+
+/* Coerce VT_DISPATCH to another type */
+HRESULT VARIANT_FromDisp(IDispatch* pdispIn, LCID lcid, void* pOut, VARTYPE vt)
+{
+ static const DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
+ VARIANTARG srcVar, dstVar;
+ HRESULT hRet;
+
+ if (!pdispIn)
+ return DISP_E_BADVARTYPE;
+
+ /* Get the default 'value' property from the IDispatch */
+ hRet = IDispatch_Invoke(pdispIn, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET,
+ (DISPPARAMS*)&emptyParams, &srcVar, NULL, NULL);
+
+ if (SUCCEEDED(hRet))
+ {
+ /* Convert the property to the requested type */
+ V_VT(&dstVar) = VT_EMPTY;
+ hRet = VariantChangeTypeEx(&dstVar, &srcVar, lcid, 0, vt);
+ VariantClear(&srcVar);
+
+ if (SUCCEEDED(hRet))
+ {
+ VARIANT_CopyData(&dstVar, vt, pOut);
+ VariantClear(&srcVar);
+ }
+ }
+ else
+ hRet = DISP_E_TYPEMISMATCH;
+ return hRet;
+}
+
+/* I1
+ */
+
+/************************************************************************
+ * VarI1FromUI1 (OLEAUT32.244)
+ *
+ * Convert a VT_UI1 to a VT_I1.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromUI1(BYTE bIn, signed char* pcOut)
+{
+ return _VarI1FromUI1(bIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromI2 (OLEAUT32.245)
+ *
+ * Convert a VT_I2 to a VT_I1.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromI2(SHORT sIn, signed char* pcOut)
+{
+ return _VarI1FromI2(sIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromI4 (OLEAUT32.246)
+ *
+ * Convert a VT_I4 to a VT_I1.
+ *
+ * PARAMS
+ * iIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromI4(LONG iIn, signed char* pcOut)
+{
+ return _VarI1FromI4(iIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromR4 (OLEAUT32.247)
+ *
+ * Convert a VT_R4 to a VT_I1.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromR4(FLOAT fltIn, signed char* pcOut)
+{
+ return _VarI1FromR4(fltIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromR8 (OLEAUT32.248)
+ *
+ * Convert a VT_R8 to a VT_I1.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * See VarI8FromR8() for details concerning rounding.
+ */
+HRESULT WINAPI VarI1FromR8(double dblIn, signed char* pcOut)
+{
+ if (dblIn < (double)I1_MIN || dblIn > (double)I1_MAX)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(CHAR, dblIn, *pcOut);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarI1FromDate (OLEAUT32.249)
+ *
+ * Convert a VT_DATE to a VT_I1.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromDate(DATE dateIn, signed char* pcOut)
+{
+ return _VarI1FromDate(dateIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromCy (OLEAUT32.250)
+ *
+ * Convert a VT_CY to a VT_I1.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromCy(CY cyIn, signed char* pcOut)
+{
+ LONG i = I1_MAX + 1;
+
+ _VarI4FromCy(cyIn, &i);
+ return _VarI1FromI4(i, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromStr (OLEAUT32.251)
+ *
+ * Convert a VT_BSTR to a VT_I1.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, signed char* pcOut)
+{
+ return _VarI1FromStr(strIn, lcid, dwFlags, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromDisp (OLEAUT32.252)
+ *
+ * Convert a VT_DISPATCH to a VT_I1.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI1FromDisp(IDispatch* pdispIn, LCID lcid, signed char* pcOut)
+{
+ return _VarI1FromDisp(pdispIn, lcid, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromBool (OLEAUT32.253)
+ *
+ * Convert a VT_BOOL to a VT_I1.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI1FromBool(VARIANT_BOOL boolIn, signed char* pcOut)
+{
+ return _VarI1FromBool(boolIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromUI2 (OLEAUT32.254)
+ *
+ * Convert a VT_UI2 to a VT_I1.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromUI2(USHORT usIn, signed char* pcOut)
+{
+ return _VarI1FromUI2(usIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromUI4 (OLEAUT32.255)
+ *
+ * Convert a VT_UI4 to a VT_I1.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI1FromUI4(ULONG ulIn, signed char* pcOut)
+{
+ return _VarI1FromUI4(ulIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromDec (OLEAUT32.256)
+ *
+ * Convert a VT_DECIMAL to a VT_I1.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromDec(DECIMAL *pdecIn, signed char* pcOut)
+{
+ LONG64 i64;
+ HRESULT hRet;
+
+ hRet = _VarI8FromDec(pdecIn, &i64);
+
+ if (SUCCEEDED(hRet))
+ hRet = _VarI1FromI8(i64, pcOut);
+ return hRet;
+}
+
+/************************************************************************
+ * VarI1FromI8 (OLEAUT32.376)
+ *
+ * Convert a VT_I8 to a VT_I1.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromI8(LONG64 llIn, signed char* pcOut)
+{
+ return _VarI1FromI8(llIn, pcOut);
+}
+
+/************************************************************************
+ * VarI1FromUI8 (OLEAUT32.377)
+ *
+ * Convert a VT_UI8 to a VT_I1.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pcOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI1FromUI8(ULONG64 ullIn, signed char* pcOut)
+{
+ return _VarI1FromUI8(ullIn, pcOut);
+}
+
+/* UI1
+ */
+
+/************************************************************************
+ * VarUI1FromI2 (OLEAUT32.130)
+ *
+ * Convert a VT_I2 to a VT_UI1.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromI2(SHORT sIn, BYTE* pbOut)
+{
+ return _VarUI1FromI2(sIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromI4 (OLEAUT32.131)
+ *
+ * Convert a VT_I4 to a VT_UI1.
+ *
+ * PARAMS
+ * iIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromI4(LONG iIn, BYTE* pbOut)
+{
+ return _VarUI1FromI4(iIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromR4 (OLEAUT32.132)
+ *
+ * Convert a VT_R4 to a VT_UI1.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI1FromR4(FLOAT fltIn, BYTE* pbOut)
+{
+ return _VarUI1FromR4(fltIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromR8 (OLEAUT32.133)
+ *
+ * Convert a VT_R8 to a VT_UI1.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * See VarI8FromR8() for details concerning rounding.
+ */
+HRESULT WINAPI VarUI1FromR8(double dblIn, BYTE* pbOut)
+{
+ if (dblIn < -0.5 || dblIn > (double)UI1_MAX)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(BYTE, dblIn, *pbOut);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarUI1FromCy (OLEAUT32.134)
+ *
+ * Convert a VT_CY to a VT_UI1.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * Negative values >= -5000 will be converted to 0.
+ */
+HRESULT WINAPI VarUI1FromCy(CY cyIn, BYTE* pbOut)
+{
+ ULONG i = UI1_MAX + 1;
+
+ _VarUI4FromCy(cyIn, &i);
+ return _VarUI1FromUI4(i, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromDate (OLEAUT32.135)
+ *
+ * Convert a VT_DATE to a VT_UI1.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromDate(DATE dateIn, BYTE* pbOut)
+{
+ return _VarUI1FromDate(dateIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromStr (OLEAUT32.136)
+ *
+ * Convert a VT_BSTR to a VT_UI1.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI1FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, BYTE* pbOut)
+{
+ return _VarUI1FromStr(strIn, lcid, dwFlags, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromDisp (OLEAUT32.137)
+ *
+ * Convert a VT_DISPATCH to a VT_UI1.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI1FromDisp(IDispatch* pdispIn, LCID lcid, BYTE* pbOut)
+{
+ return _VarUI1FromDisp(pdispIn, lcid, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromBool (OLEAUT32.138)
+ *
+ * Convert a VT_BOOL to a VT_UI1.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI1FromBool(VARIANT_BOOL boolIn, BYTE* pbOut)
+{
+ return _VarUI1FromBool(boolIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromI1 (OLEAUT32.237)
+ *
+ * Convert a VT_I1 to a VT_UI1.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromI1(signed char cIn, BYTE* pbOut)
+{
+ return _VarUI1FromI1(cIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromUI2 (OLEAUT32.238)
+ *
+ * Convert a VT_UI2 to a VT_UI1.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromUI2(USHORT usIn, BYTE* pbOut)
+{
+ return _VarUI1FromUI2(usIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromUI4 (OLEAUT32.239)
+ *
+ * Convert a VT_UI4 to a VT_UI1.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromUI4(ULONG ulIn, BYTE* pbOut)
+{
+ return _VarUI1FromUI4(ulIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromDec (OLEAUT32.240)
+ *
+ * Convert a VT_DECIMAL to a VT_UI1.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE* pbOut)
+{
+ LONG64 i64;
+ HRESULT hRet;
+
+ hRet = _VarI8FromDec(pdecIn, &i64);
+
+ if (SUCCEEDED(hRet))
+ hRet = _VarUI1FromI8(i64, pbOut);
+ return hRet;
+}
+
+/************************************************************************
+ * VarUI1FromI8 (OLEAUT32.372)
+ *
+ * Convert a VT_I8 to a VT_UI1.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromI8(LONG64 llIn, BYTE* pbOut)
+{
+ return _VarUI1FromI8(llIn, pbOut);
+}
+
+/************************************************************************
+ * VarUI1FromUI8 (OLEAUT32.373)
+ *
+ * Convert a VT_UI8 to a VT_UI1.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pbOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI1FromUI8(ULONG64 ullIn, BYTE* pbOut)
+{
+ return _VarUI1FromUI8(ullIn, pbOut);
+}
+
+
+/* I2
+ */
+
+/************************************************************************
+ * VarI2FromUI1 (OLEAUT32.48)
+ *
+ * Convert a VT_UI2 to a VT_I2.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI2FromUI1(BYTE bIn, SHORT* psOut)
+{
+ return _VarI2FromUI1(bIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromI4 (OLEAUT32.49)
+ *
+ * Convert a VT_I4 to a VT_I2.
+ *
+ * PARAMS
+ * iIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromI4(LONG iIn, SHORT* psOut)
+{
+ return _VarI2FromI4(iIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromR4 (OLEAUT32.50)
+ *
+ * Convert a VT_R4 to a VT_I2.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromR4(FLOAT fltIn, SHORT* psOut)
+{
+ return _VarI2FromR4(fltIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromR8 (OLEAUT32.51)
+ *
+ * Convert a VT_R8 to a VT_I2.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * See VarI8FromR8() for details concerning rounding.
+ */
+HRESULT WINAPI VarI2FromR8(double dblIn, SHORT* psOut)
+{
+ if (dblIn < (double)I2_MIN || dblIn > (double)I2_MAX)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(SHORT, dblIn, *psOut);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarI2FromCy (OLEAUT32.52)
+ *
+ * Convert a VT_CY to a VT_I2.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromCy(CY cyIn, SHORT* psOut)
+{
+ LONG i = I2_MAX + 1;
+
+ _VarI4FromCy(cyIn, &i);
+ return _VarI2FromI4(i, psOut);
+}
+
+/************************************************************************
+ * VarI2FromDate (OLEAUT32.53)
+ *
+ * Convert a VT_DATE to a VT_I2.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromDate(DATE dateIn, SHORT* psOut)
+{
+ return _VarI2FromDate(dateIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromStr (OLEAUT32.54)
+ *
+ * Convert a VT_BSTR to a VT_I2.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if any parameter is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, SHORT* psOut)
+{
+ return _VarI2FromStr(strIn, lcid, dwFlags, psOut);
+}
+
+/************************************************************************
+ * VarI2FromDisp (OLEAUT32.55)
+ *
+ * Convert a VT_DISPATCH to a VT_I2.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pdispIn is invalid,
+ * DISP_E_OVERFLOW, if the value will not fit in the destination,
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI2FromDisp(IDispatch* pdispIn, LCID lcid, SHORT* psOut)
+{
+ return _VarI2FromDisp(pdispIn, lcid, psOut);
+}
+
+/************************************************************************
+ * VarI2FromBool (OLEAUT32.56)
+ *
+ * Convert a VT_BOOL to a VT_I2.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI2FromBool(VARIANT_BOOL boolIn, SHORT* psOut)
+{
+ return _VarI2FromBool(boolIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromI1 (OLEAUT32.205)
+ *
+ * Convert a VT_I1 to a VT_I2.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI2FromI1(signed char cIn, SHORT* psOut)
+{
+ return _VarI2FromI1(cIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromUI2 (OLEAUT32.206)
+ *
+ * Convert a VT_UI2 to a VT_I2.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromUI2(USHORT usIn, SHORT* psOut)
+{
+ return _VarI2FromUI2(usIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromUI4 (OLEAUT32.207)
+ *
+ * Convert a VT_UI4 to a VT_I2.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromUI4(ULONG ulIn, SHORT* psOut)
+{
+ return _VarI2FromUI4(ulIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromDec (OLEAUT32.208)
+ *
+ * Convert a VT_DECIMAL to a VT_I2.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromDec(DECIMAL *pdecIn, SHORT* psOut)
+{
+ LONG64 i64;
+ HRESULT hRet;
+
+ hRet = _VarI8FromDec(pdecIn, &i64);
+
+ if (SUCCEEDED(hRet))
+ hRet = _VarI2FromI8(i64, psOut);
+ return hRet;
+}
+
+/************************************************************************
+ * VarI2FromI8 (OLEAUT32.346)
+ *
+ * Convert a VT_I8 to a VT_I2.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromI8(LONG64 llIn, SHORT* psOut)
+{
+ return _VarI2FromI8(llIn, psOut);
+}
+
+/************************************************************************
+ * VarI2FromUI8 (OLEAUT32.347)
+ *
+ * Convert a VT_UI8 to a VT_I2.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * psOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI2FromUI8(ULONG64 ullIn, SHORT* psOut)
+{
+ return _VarI2FromUI8(ullIn, psOut);
+}
+
+/* UI2
+ */
+
+/************************************************************************
+ * VarUI2FromUI1 (OLEAUT32.257)
+ *
+ * Convert a VT_UI1 to a VT_UI2.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI2FromUI1(BYTE bIn, USHORT* pusOut)
+{
+ return _VarUI2FromUI1(bIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromI2 (OLEAUT32.258)
+ *
+ * Convert a VT_I2 to a VT_UI2.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromI2(SHORT sIn, USHORT* pusOut)
+{
+ return _VarUI2FromI2(sIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromI4 (OLEAUT32.259)
+ *
+ * Convert a VT_I4 to a VT_UI2.
+ *
+ * PARAMS
+ * iIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromI4(LONG iIn, USHORT* pusOut)
+{
+ return _VarUI2FromI4(iIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromR4 (OLEAUT32.260)
+ *
+ * Convert a VT_R4 to a VT_UI2.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromR4(FLOAT fltIn, USHORT* pusOut)
+{
+ return _VarUI2FromR4(fltIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromR8 (OLEAUT32.261)
+ *
+ * Convert a VT_R8 to a VT_UI2.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * See VarI8FromR8() for details concerning rounding.
+ */
+HRESULT WINAPI VarUI2FromR8(double dblIn, USHORT* pusOut)
+{
+ if (dblIn < -0.5 || dblIn > (double)UI2_MAX)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(USHORT, dblIn, *pusOut);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarUI2FromDate (OLEAUT32.262)
+ *
+ * Convert a VT_DATE to a VT_UI2.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromDate(DATE dateIn, USHORT* pusOut)
+{
+ return _VarUI2FromDate(dateIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromCy (OLEAUT32.263)
+ *
+ * Convert a VT_CY to a VT_UI2.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * Negative values >= -5000 will be converted to 0.
+ */
+HRESULT WINAPI VarUI2FromCy(CY cyIn, USHORT* pusOut)
+{
+ ULONG i = UI2_MAX + 1;
+
+ _VarUI4FromCy(cyIn, &i);
+ return _VarUI2FromUI4(i, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromStr (OLEAUT32.264)
+ *
+ * Convert a VT_BSTR to a VT_UI2.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI2FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, USHORT* pusOut)
+{
+ return _VarUI2FromStr(strIn, lcid, dwFlags, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromDisp (OLEAUT32.265)
+ *
+ * Convert a VT_DISPATCH to a VT_UI2.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI2FromDisp(IDispatch* pdispIn, LCID lcid, USHORT* pusOut)
+{
+ return _VarUI2FromDisp(pdispIn, lcid, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromBool (OLEAUT32.266)
+ *
+ * Convert a VT_BOOL to a VT_UI2.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI2FromBool(VARIANT_BOOL boolIn, USHORT* pusOut)
+{
+ return _VarUI2FromBool(boolIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromI1 (OLEAUT32.267)
+ *
+ * Convert a VT_I1 to a VT_UI2.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromI1(signed char cIn, USHORT* pusOut)
+{
+ return _VarUI2FromI1(cIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromUI4 (OLEAUT32.268)
+ *
+ * Convert a VT_UI4 to a VT_UI2.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromUI4(ULONG ulIn, USHORT* pusOut)
+{
+ return _VarUI2FromUI4(ulIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromDec (OLEAUT32.269)
+ *
+ * Convert a VT_DECIMAL to a VT_UI2.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT* pusOut)
+{
+ LONG64 i64;
+ HRESULT hRet;
+
+ hRet = _VarI8FromDec(pdecIn, &i64);
+
+ if (SUCCEEDED(hRet))
+ hRet = _VarUI2FromI8(i64, pusOut);
+ return hRet;
+}
+
+/************************************************************************
+ * VarUI2FromI8 (OLEAUT32.378)
+ *
+ * Convert a VT_I8 to a VT_UI2.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromI8(LONG64 llIn, USHORT* pusOut)
+{
+ return _VarUI2FromI8(llIn, pusOut);
+}
+
+/************************************************************************
+ * VarUI2FromUI8 (OLEAUT32.379)
+ *
+ * Convert a VT_UI8 to a VT_UI2.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pusOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI2FromUI8(ULONG64 ullIn, USHORT* pusOut)
+{
+ return _VarUI2FromUI8(ullIn, pusOut);
+}
+
+/* I4
+ */
+
+/************************************************************************
+ * VarI4FromUI1 (OLEAUT32.58)
+ *
+ * Convert a VT_UI1 to a VT_I4.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut)
+{
+ return _VarI4FromUI1(bIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromI2 (OLEAUT32.59)
+ *
+ * Convert a VT_I2 to a VT_I4.
+ *
+ * PARAMS
+ * iIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromI2(SHORT sIn, LONG *piOut)
+{
+ return _VarI4FromI2(sIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromR4 (OLEAUT32.60)
+ *
+ * Convert a VT_R4 to a VT_I4.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromR4(FLOAT fltIn, LONG *piOut)
+{
+ return _VarI4FromR4(fltIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromR8 (OLEAUT32.61)
+ *
+ * Convert a VT_R8 to a VT_I4.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * See VarI8FromR8() for details concerning rounding.
+ */
+HRESULT WINAPI VarI4FromR8(double dblIn, LONG *piOut)
+{
+ if (dblIn < (double)I4_MIN || dblIn > (double)I4_MAX)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(LONG, dblIn, *piOut);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarI4FromCy (OLEAUT32.62)
+ *
+ * Convert a VT_CY to a VT_I4.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromCy(CY cyIn, LONG *piOut)
+{
+ double d = cyIn.int64 / CY_MULTIPLIER_F;
+ return _VarI4FromR8(d, piOut);
+}
+
+/************************************************************************
+ * VarI4FromDate (OLEAUT32.63)
+ *
+ * Convert a VT_DATE to a VT_I4.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromDate(DATE dateIn, LONG *piOut)
+{
+ return _VarI4FromDate(dateIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromStr (OLEAUT32.64)
+ *
+ * Convert a VT_BSTR to a VT_I4.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if any parameter is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if strIn cannot be converted
+ */
+HRESULT WINAPI VarI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG *piOut)
+{
+ return _VarI4FromStr(strIn, lcid, dwFlags, piOut);
+}
+
+/************************************************************************
+ * VarI4FromDisp (OLEAUT32.65)
+ *
+ * Convert a VT_DISPATCH to a VT_I4.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI4FromDisp(IDispatch* pdispIn, LCID lcid, LONG *piOut)
+{
+ return _VarI4FromDisp(pdispIn, lcid, piOut);
+}
+
+/************************************************************************
+ * VarI4FromBool (OLEAUT32.66)
+ *
+ * Convert a VT_BOOL to a VT_I4.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI4FromBool(VARIANT_BOOL boolIn, LONG *piOut)
+{
+ return _VarI4FromBool(boolIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromI1 (OLEAUT32.209)
+ *
+ * Convert a VT_I4 to a VT_I4.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI4FromI1(signed char cIn, LONG *piOut)
+{
+ return _VarI4FromI1(cIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromUI2 (OLEAUT32.210)
+ *
+ * Convert a VT_UI2 to a VT_I4.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI4FromUI2(USHORT usIn, LONG *piOut)
+{
+ return _VarI4FromUI2(usIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromUI4 (OLEAUT32.211)
+ *
+ * Convert a VT_UI4 to a VT_I4.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromUI4(ULONG ulIn, LONG *piOut)
+{
+ return _VarI4FromUI4(ulIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromDec (OLEAUT32.212)
+ *
+ * Convert a VT_DECIMAL to a VT_I4.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pdecIn is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromDec(DECIMAL *pdecIn, LONG *piOut)
+{
+ LONG64 i64;
+ HRESULT hRet;
+
+ hRet = _VarI8FromDec(pdecIn, &i64);
+
+ if (SUCCEEDED(hRet))
+ hRet = _VarI4FromI8(i64, piOut);
+ return hRet;
+}
+
+/************************************************************************
+ * VarI4FromI8 (OLEAUT32.348)
+ *
+ * Convert a VT_I8 to a VT_I4.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromI8(LONG64 llIn, LONG *piOut)
+{
+ return _VarI4FromI8(llIn, piOut);
+}
+
+/************************************************************************
+ * VarI4FromUI8 (OLEAUT32.349)
+ *
+ * Convert a VT_UI8 to a VT_I4.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * piOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI4FromUI8(ULONG64 ullIn, LONG *piOut)
+{
+ return _VarI4FromUI8(ullIn, piOut);
+}
+
+/* UI4
+ */
+
+/************************************************************************
+ * VarUI4FromUI1 (OLEAUT32.270)
+ *
+ * Convert a VT_UI1 to a VT_UI4.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI4FromUI1(BYTE bIn, ULONG *pulOut)
+{
+ return _VarUI4FromUI1(bIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromI2 (OLEAUT32.271)
+ *
+ * Convert a VT_I2 to a VT_UI4.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromI2(SHORT sIn, ULONG *pulOut)
+{
+ return _VarUI4FromI2(sIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromI4 (OLEAUT32.272)
+ *
+ * Convert a VT_I4 to a VT_UI4.
+ *
+ * PARAMS
+ * iIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromI4(LONG iIn, ULONG *pulOut)
+{
+ return _VarUI4FromI4(iIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromR4 (OLEAUT32.273)
+ *
+ * Convert a VT_R4 to a VT_UI4.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromR4(FLOAT fltIn, ULONG *pulOut)
+{
+ return _VarUI4FromR4(fltIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromR8 (OLEAUT32.274)
+ *
+ * Convert a VT_R8 to a VT_UI4.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * See VarI8FromR8() for details concerning rounding.
+ */
+HRESULT WINAPI VarUI4FromR8(double dblIn, ULONG *pulOut)
+{
+ if (dblIn < -0.5 || dblIn > (double)UI4_MAX)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(ULONG, dblIn, *pulOut);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarUI4FromDate (OLEAUT32.275)
+ *
+ * Convert a VT_DATE to a VT_UI4.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromDate(DATE dateIn, ULONG *pulOut)
+{
+ return _VarUI4FromDate(dateIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromCy (OLEAUT32.276)
+ *
+ * Convert a VT_CY to a VT_UI4.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromCy(CY cyIn, ULONG *pulOut)
+{
+ double d = cyIn.int64 / CY_MULTIPLIER_F;
+ return _VarUI4FromR8(d, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromStr (OLEAUT32.277)
+ *
+ * Convert a VT_BSTR to a VT_UI4.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if any parameter is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if strIn cannot be converted
+ */
+HRESULT WINAPI VarUI4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG *pulOut)
+{
+ return _VarUI4FromStr(strIn, lcid, dwFlags, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromDisp (OLEAUT32.278)
+ *
+ * Convert a VT_DISPATCH to a VT_UI4.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI4FromDisp(IDispatch* pdispIn, LCID lcid, ULONG *pulOut)
+{
+ return _VarUI4FromDisp(pdispIn, lcid, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromBool (OLEAUT32.279)
+ *
+ * Convert a VT_BOOL to a VT_UI4.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI4FromBool(VARIANT_BOOL boolIn, ULONG *pulOut)
+{
+ return _VarUI4FromBool(boolIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromI1 (OLEAUT32.280)
+ *
+ * Convert a VT_I1 to a VT_UI4.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromI1(signed char cIn, ULONG *pulOut)
+{
+ return _VarUI4FromI1(cIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromUI2 (OLEAUT32.281)
+ *
+ * Convert a VT_UI2 to a VT_UI4.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI4FromUI2(USHORT usIn, ULONG *pulOut)
+{
+ return _VarUI4FromUI2(usIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromDec (OLEAUT32.282)
+ *
+ * Convert a VT_DECIMAL to a VT_UI4.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pdecIn is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pulOut)
+{
+ LONG64 i64;
+ HRESULT hRet;
+
+ hRet = _VarI8FromDec(pdecIn, &i64);
+
+ if (SUCCEEDED(hRet))
+ hRet = _VarUI4FromI8(i64, pulOut);
+ return hRet;
+}
+
+/************************************************************************
+ * VarUI4FromI8 (OLEAUT32.425)
+ *
+ * Convert a VT_I8 to a VT_UI4.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromI8(LONG64 llIn, ULONG *pulOut)
+{
+ return _VarUI4FromI8(llIn, pulOut);
+}
+
+/************************************************************************
+ * VarUI4FromUI8 (OLEAUT32.426)
+ *
+ * Convert a VT_UI8 to a VT_UI4.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pulOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI4FromUI8(ULONG64 ullIn, ULONG *pulOut)
+{
+ return _VarUI4FromUI8(ullIn, pulOut);
+}
+
+/* I8
+ */
+
+/************************************************************************
+ * VarI8FromUI1 (OLEAUT32.333)
+ *
+ * Convert a VT_UI1 to a VT_I8.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI8FromUI1(BYTE bIn, LONG64* pi64Out)
+{
+ return _VarI8FromUI1(bIn, pi64Out);
+}
+
+
+/************************************************************************
+ * VarI8FromI2 (OLEAUT32.334)
+ *
+ * Convert a VT_I2 to a VT_I8.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI8FromI2(SHORT sIn, LONG64* pi64Out)
+{
+ return _VarI8FromI2(sIn, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromR4 (OLEAUT32.335)
+ *
+ * Convert a VT_R4 to a VT_I8.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI8FromR4(FLOAT fltIn, LONG64* pi64Out)
+{
+ return _VarI8FromR4(fltIn, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromR8 (OLEAUT32.336)
+ *
+ * Convert a VT_R8 to a VT_I8.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * Only values that fit into 63 bits are accepted. Due to rounding issues,
+ * very high or low values will not be accurately converted.
+ *
+ * Numbers are rounded using Dutch rounding, as follows:
+ *
+ *| Fractional Part Sign Direction Example
+ *| --------------- ---- --------- -------
+ *| < 0.5 + Down 0.4 -> 0.0
+ *| < 0.5 - Up -0.4 -> 0.0
+ *| > 0.5 + Up 0.6 -> 1.0
+ *| < 0.5 - Up -0.6 -> -1.0
+ *| = 0.5 + Up/Down Down if even, Up if odd
+ *| = 0.5 - Up/Down Up if even, Down if odd
+ *
+ * This system is often used in supermarkets.
+ */
+HRESULT WINAPI VarI8FromR8(double dblIn, LONG64* pi64Out)
+{
+ if ( dblIn < -4611686018427387904.0 || dblIn >= 4611686018427387904.0)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(LONG64, dblIn, *pi64Out);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarI8FromCy (OLEAUT32.337)
+ *
+ * Convert a VT_CY to a VT_I8.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ *
+ * NOTES
+ * All negative numbers are rounded down by 1, including those that are
+ * evenly divisible by 10000 (this is a Win32 bug that Wine mimics).
+ * Positive numbers are rounded using Dutch rounding: See VarI8FromR8()
+ * for details.
+ */
+HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
+{
+ *pi64Out = cyIn.int64 / CY_MULTIPLIER;
+
+ if (cyIn.int64 < 0)
+ (*pi64Out)--; /* Mimic Win32 bug */
+ else
+ {
+ cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
+
+ if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
+ (*pi64Out)++;
+ }
+ return S_OK;
+}
+
+/************************************************************************
+ * VarI8FromDate (OLEAUT32.338)
+ *
+ * Convert a VT_DATE to a VT_I8.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI8FromDate(DATE dateIn, LONG64* pi64Out)
+{
+ return _VarI8FromDate(dateIn, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromStr (OLEAUT32.339)
+ *
+ * Convert a VT_BSTR to a VT_I8.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, LONG64* pi64Out)
+{
+ return _VarI8FromStr(strIn, lcid, dwFlags, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromDisp (OLEAUT32.340)
+ *
+ * Convert a VT_DISPATCH to a VT_I8.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarI8FromDisp(IDispatch* pdispIn, LCID lcid, LONG64* pi64Out)
+{
+ return _VarI8FromDisp(pdispIn, lcid, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromBool (OLEAUT32.341)
+ *
+ * Convert a VT_BOOL to a VT_I8.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI8FromBool(VARIANT_BOOL boolIn, LONG64* pi64Out)
+{
+ return _VarI8FromBool(boolIn, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromI1 (OLEAUT32.342)
+ *
+ * Convert a VT_I1 to a VT_I8.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI8FromI1(signed char cIn, LONG64* pi64Out)
+{
+ return _VarI8FromI1(cIn, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromUI2 (OLEAUT32.343)
+ *
+ * Convert a VT_UI2 to a VT_I8.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI8FromUI2(USHORT usIn, LONG64* pi64Out)
+{
+ return _VarI8FromUI2(usIn, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromUI4 (OLEAUT32.344)
+ *
+ * Convert a VT_UI4 to a VT_I8.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
+{
+ return _VarI8FromUI4(ulIn, pi64Out);
+}
+
+/************************************************************************
+ * VarI8FromDec (OLEAUT32.345)
+ *
+ * Convert a VT_DECIMAL to a VT_I8.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI8FromDec(DECIMAL *pdecIn, LONG64* pi64Out)
+{
+ if (!DEC_SCALE(pdecIn))
+ {
+ /* This decimal is just a 96 bit integer */
+ if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
+ return E_INVALIDARG;
+
+ if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
+ return DISP_E_OVERFLOW;
+
+ if (DEC_SIGN(pdecIn))
+ *pi64Out = -DEC_LO64(pdecIn);
+ else
+ *pi64Out = DEC_LO64(pdecIn);
+ return S_OK;
+ }
+ else
+ {
+ /* Decimal contains a floating point number */
+ HRESULT hRet;
+ double dbl;
+
+ hRet = _VarR8FromDec(pdecIn, &dbl);
+ if (SUCCEEDED(hRet))
+ hRet = VarI8FromR8(dbl, pi64Out);
+ return hRet;
+ }
+}
+
+/************************************************************************
+ * VarI8FromUI8 (OLEAUT32.427)
+ *
+ * Convert a VT_UI8 to a VT_I8.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pi64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarI8FromUI8(ULONG64 ullIn, LONG64* pi64Out)
+{
+ return _VarI8FromUI8(ullIn, pi64Out);
+}
+
+/* UI8
+ */
+
+/************************************************************************
+ * VarUI8FromI8 (OLEAUT32.428)
+ *
+ * Convert a VT_I8 to a VT_UI8.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI8FromI8(LONG64 llIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromI8(llIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromUI1 (OLEAUT32.429)
+ *
+ * Convert a VT_UI1 to a VT_UI8.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI8FromUI1(BYTE bIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromUI1(bIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromI2 (OLEAUT32.430)
+ *
+ * Convert a VT_I2 to a VT_UI8.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI8FromI2(SHORT sIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromI2(sIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromR4 (OLEAUT32.431)
+ *
+ * Convert a VT_R4 to a VT_UI8.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI8FromR4(FLOAT fltIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromR4(fltIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromR8 (OLEAUT32.432)
+ *
+ * Convert a VT_R8 to a VT_UI8.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * See VarI8FromR8() for details concerning rounding.
+ */
+HRESULT WINAPI VarUI8FromR8(double dblIn, ULONG64* pui64Out)
+{
+ if (dblIn < -0.5 || dblIn > 1.844674407370955e19)
+ return DISP_E_OVERFLOW;
+ OLEAUT32_DutchRound(ULONG64, dblIn, *pui64Out);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarUI8FromCy (OLEAUT32.433)
+ *
+ * Convert a VT_CY to a VT_UI8.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * Negative values >= -5000 will be converted to 0.
+ */
+HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
+{
+ if (cyIn.int64 < 0)
+ {
+ if (cyIn.int64 < -CY_HALF)
+ return DISP_E_OVERFLOW;
+ *pui64Out = 0;
+ }
+ else
+ {
+ *pui64Out = cyIn.int64 / CY_MULTIPLIER;
+
+ cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
+
+ if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
+ (*pui64Out)++;
+ }
+ return S_OK;
+}
+
+/************************************************************************
+ * VarUI8FromDate (OLEAUT32.434)
+ *
+ * Convert a VT_DATE to a VT_UI8.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI8FromDate(DATE dateIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromDate(dateIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromStr (OLEAUT32.435)
+ *
+ * Convert a VT_BSTR to a VT_UI8.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, ULONG64* pui64Out)
+{
+ return _VarUI8FromStr(strIn, lcid, dwFlags, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromDisp (OLEAUT32.436)
+ *
+ * Convert a VT_DISPATCH to a VT_UI8.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarUI8FromDisp(IDispatch* pdispIn, LCID lcid, ULONG64* pui64Out)
+{
+ return _VarUI8FromDisp(pdispIn, lcid, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromBool (OLEAUT32.437)
+ *
+ * Convert a VT_BOOL to a VT_UI8.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI8FromBool(VARIANT_BOOL boolIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromBool(boolIn, pui64Out);
+}
+/************************************************************************
+ * VarUI8FromI1 (OLEAUT32.438)
+ *
+ * Convert a VT_I1 to a VT_UI8.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarUI8FromI1(signed char cIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromI1(cIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromUI2 (OLEAUT32.439)
+ *
+ * Convert a VT_UI2 to a VT_UI8.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI8FromUI2(USHORT usIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromUI2(usIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromUI4 (OLEAUT32.440)
+ *
+ * Convert a VT_UI4 to a VT_UI8.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
+{
+ return _VarUI8FromUI4(ulIn, pui64Out);
+}
+
+/************************************************************************
+ * VarUI8FromDec (OLEAUT32.441)
+ *
+ * Convert a VT_DECIMAL to a VT_UI8.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pui64Out [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ *
+ * NOTES
+ * Under native Win32, if the source value has a scale of 0, its sign is
+ * ignored, i.e. this function takes the absolute value rather than fail
+ * with DISP_E_OVERFLOW. This bug has been fixed in Wine's implementation
+ * (use VarAbs() on pDecIn first if you really want this behaviour).
+ */
+HRESULT WINAPI VarUI8FromDec(DECIMAL *pdecIn, ULONG64* pui64Out)
+{
+ if (!DEC_SCALE(pdecIn))
+ {
+ /* This decimal is just a 96 bit integer */
+ if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
+ return E_INVALIDARG;
+
+ if (DEC_HI32(pdecIn))
+ return DISP_E_OVERFLOW;
+
+ if (DEC_SIGN(pdecIn))
+ {
+ WARN("Sign would be ignored under Win32!\n");
+ return DISP_E_OVERFLOW;
+ }
+
+ *pui64Out = DEC_LO64(pdecIn);
+ return S_OK;
+ }
+ else
+ {
+ /* Decimal contains a floating point number */
+ HRESULT hRet;
+ double dbl;
+
+ hRet = _VarR8FromDec(pdecIn, &dbl);
+ if (SUCCEEDED(hRet))
+ hRet = VarUI8FromR8(dbl, pui64Out);
+ return hRet;
+ }
+}
+
+/* R4
+ */
+
+/************************************************************************
+ * VarR4FromUI1 (OLEAUT32.68)
+ *
+ * Convert a VT_UI1 to a VT_R4.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR4FromUI1(BYTE bIn, float *pFltOut)
+{
+ return _VarR4FromUI1(bIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromI2 (OLEAUT32.69)
+ *
+ * Convert a VT_I2 to a VT_R4.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR4FromI2(SHORT sIn, float *pFltOut)
+{
+ return _VarR4FromI2(sIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromI4 (OLEAUT32.70)
+ *
+ * Convert a VT_I4 to a VT_R4.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR4FromI4(LONG lIn, float *pFltOut)
+{
+ return _VarR4FromI4(lIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromR8 (OLEAUT32.71)
+ *
+ * Convert a VT_R8 to a VT_R4.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
+ */
+HRESULT WINAPI VarR4FromR8(double dblIn, float *pFltOut)
+{
+ return _VarR4FromR8(dblIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromCy (OLEAUT32.72)
+ *
+ * Convert a VT_CY to a VT_R4.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR4FromCy(CY cyIn, float *pFltOut)
+{
+ return _VarR4FromCy(cyIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromDate (OLEAUT32.73)
+ *
+ * Convert a VT_DATE to a VT_R4.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination.
+ */
+HRESULT WINAPI VarR4FromDate(DATE dateIn, float *pFltOut)
+{
+ return _VarR4FromDate(dateIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromStr (OLEAUT32.74)
+ *
+ * Convert a VT_BSTR to a VT_R4.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if strIn or pFltOut is invalid.
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR4FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, float *pFltOut)
+{
+ return _VarR4FromStr(strIn, lcid, dwFlags, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromDisp (OLEAUT32.75)
+ *
+ * Convert a VT_DISPATCH to a VT_R4.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR4FromDisp(IDispatch* pdispIn, LCID lcid, float *pFltOut)
+{
+ return _VarR4FromDisp(pdispIn, lcid, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromBool (OLEAUT32.76)
+ *
+ * Convert a VT_BOOL to a VT_R4.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR4FromBool(VARIANT_BOOL boolIn, float *pFltOut)
+{
+ return _VarR4FromBool(boolIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromI1 (OLEAUT32.213)
+ *
+ * Convert a VT_I1 to a VT_R4.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR4FromI1(signed char cIn, float *pFltOut)
+{
+ return _VarR4FromI1(cIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromUI2 (OLEAUT32.214)
+ *
+ * Convert a VT_UI2 to a VT_R4.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR4FromUI2(USHORT usIn, float *pFltOut)
+{
+ return _VarR4FromUI2(usIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromUI4 (OLEAUT32.215)
+ *
+ * Convert a VT_UI4 to a VT_R4.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
+{
+ return _VarR4FromUI4(ulIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromDec (OLEAUT32.216)
+ *
+ * Convert a VT_DECIMAL to a VT_R4.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid.
+ */
+HRESULT WINAPI VarR4FromDec(DECIMAL* pDecIn, float *pFltOut)
+{
+ BYTE scale = DEC_SCALE(pDecIn);
+ int divisor = 1;
+ double highPart;
+
+ if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
+ return E_INVALIDARG;
+
+ while (scale--)
+ divisor *= 10;
+
+ if (DEC_SIGN(pDecIn))
+ divisor = -divisor;
+
+ if (DEC_HI32(pDecIn))
+ {
+ highPart = (double)DEC_HI32(pDecIn) / (double)divisor;
+ highPart *= 1.0e64;
+ }
+ else
+ highPart = 0.0;
+
+ *pFltOut = (double)DEC_LO64(pDecIn) / (double)divisor + highPart;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarR4FromI8 (OLEAUT32.360)
+ *
+ * Convert a VT_I8 to a VT_R4.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR4FromI8(LONG64 llIn, float *pFltOut)
+{
+ return _VarR4FromI8(llIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4FromUI8 (OLEAUT32.361)
+ *
+ * Convert a VT_UI8 to a VT_R4.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pFltOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR4FromUI8(ULONG64 ullIn, float *pFltOut)
+{
+ return _VarR4FromUI8(ullIn, pFltOut);
+}
+
+/************************************************************************
+ * VarR4CmpR8 (OLEAUT32.316)
+ *
+ * Compare a VT_R4 to a VT_R8.
+ *
+ * PARAMS
+ * fltLeft [I] Source
+ * dblRight [I] Value to compare
+ *
+ * RETURNS
+ * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that fltLeft is less than,
+ * equal to or greater than dblRight respectively.
+ */
+HRESULT WINAPI VarR4CmpR8(float fltLeft, double dblRight)
+{
+ if (fltLeft < dblRight)
+ return VARCMP_LT;
+ else if (fltLeft > dblRight)
+ return VARCMP_GT;
+ return VARCMP_EQ;
+}
+
+/* R8
+ */
+
+/************************************************************************
+ * VarR8FromUI1 (OLEAUT32.78)
+ *
+ * Convert a VT_UI1 to a VT_R8.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromUI1(BYTE bIn, double *pDblOut)
+{
+ return _VarR8FromUI1(bIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromI2 (OLEAUT32.79)
+ *
+ * Convert a VT_I2 to a VT_R8.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromI2(SHORT sIn, double *pDblOut)
+{
+ return _VarR8FromI2(sIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromI4 (OLEAUT32.80)
+ *
+ * Convert a VT_I4 to a VT_R8.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromI4(LONG lIn, double *pDblOut)
+{
+ return _VarR8FromI4(lIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromR4 (OLEAUT32.81)
+ *
+ * Convert a VT_R4 to a VT_R8.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromR4(FLOAT fltIn, double *pDblOut)
+{
+ return _VarR8FromR4(fltIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromCy (OLEAUT32.82)
+ *
+ * Convert a VT_CY to a VT_R8.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromCy(CY cyIn, double *pDblOut)
+{
+ return _VarR8FromCy(cyIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromDate (OLEAUT32.83)
+ *
+ * Convert a VT_DATE to a VT_R8.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromDate(DATE dateIn, double *pDblOut)
+{
+ return _VarR8FromDate(dateIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromStr (OLEAUT32.84)
+ *
+ * Convert a VT_BSTR to a VT_R8.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
+{
+ return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromDisp (OLEAUT32.85)
+ *
+ * Convert a VT_DISPATCH to a VT_R8.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR8FromDisp(IDispatch* pdispIn, LCID lcid, double *pDblOut)
+{
+ return _VarR8FromDisp(pdispIn, lcid, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromBool (OLEAUT32.86)
+ *
+ * Convert a VT_BOOL to a VT_R8.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromBool(VARIANT_BOOL boolIn, double *pDblOut)
+{
+ return _VarR8FromBool(boolIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromI1 (OLEAUT32.217)
+ *
+ * Convert a VT_I1 to a VT_R8.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR8FromI1(signed char cIn, double *pDblOut)
+{
+ return _VarR8FromI1(cIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromUI2 (OLEAUT32.218)
+ *
+ * Convert a VT_UI2 to a VT_R8.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR8FromUI2(USHORT usIn, double *pDblOut)
+{
+ return _VarR8FromUI2(usIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromUI4 (OLEAUT32.219)
+ *
+ * Convert a VT_UI4 to a VT_R8.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
+{
+ return _VarR8FromUI4(ulIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromDec (OLEAUT32.220)
+ *
+ * Convert a VT_DECIMAL to a VT_R8.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid.
+ */
+HRESULT WINAPI VarR8FromDec(DECIMAL* pDecIn, double *pDblOut)
+{
+ BYTE scale = DEC_SCALE(pDecIn);
+ double divisor = 1.0, highPart;
+
+ if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
+ return E_INVALIDARG;
+
+ while (scale--)
+ divisor *= 10;
+
+ if (DEC_SIGN(pDecIn))
+ divisor = -divisor;
+
+ if (DEC_HI32(pDecIn))
+ {
+ highPart = (double)DEC_HI32(pDecIn) / divisor;
+ highPart *= 1.0e64;
+ }
+ else
+ highPart = 0.0;
+
+ *pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarR8FromI8 (OLEAUT32.362)
+ *
+ * Convert a VT_I8 to a VT_R8.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromI8(LONG64 llIn, double *pDblOut)
+{
+ return _VarR8FromI8(llIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8FromUI8 (OLEAUT32.363)
+ *
+ * Convert a VT_UI8 to a VT_R8.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarR8FromUI8(ULONG64 ullIn, double *pDblOut)
+{
+ return _VarR8FromUI8(ullIn, pDblOut);
+}
+
+/************************************************************************
+ * VarR8Pow (OLEAUT32.315)
+ *
+ * Raise a VT_R8 to a power.
+ *
+ * PARAMS
+ * dblLeft [I] Source
+ * dblPow [I] Power to raise dblLeft by
+ * pDblOut [O] Destination
+ *
+ * RETURNS
+ * S_OK. pDblOut contains dblLeft to the power of dblRight.
+ */
+HRESULT WINAPI VarR8Pow(double dblLeft, double dblPow, double *pDblOut)
+{
+ *pDblOut = pow(dblLeft, dblPow);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarR8Round (OLEAUT32.317)
+ *
+ * Round a VT_R8 to a given number of decimal points.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * nDig [I] Number of decimal points to round to
+ * pDblOut [O] Destination for rounded number
+ *
+ * RETURNS
+ * Success: S_OK. pDblOut is rounded to nDig digits.
+ * Failure: E_INVALIDARG, if cDecimals is less than 0.
+ *
+ * NOTES
+ * The native version of this function rounds using the internal
+ * binary representation of the number. Wine uses the dutch rounding
+ * convention, so therefore small differences can occur in the value returned.
+ * MSDN says that you should use your own rounding function if you want
+ * rounding to be predictable in your application.
+ */
+HRESULT WINAPI VarR8Round(double dblIn, int nDig, double *pDblOut)
+{
+ double scale, whole, fract;
+
+ if (nDig < 0)
+ return E_INVALIDARG;
+
+ scale = pow(10.0, nDig);
+
+ dblIn *= scale;
+ whole = dblIn < 0 ? ceil(dblIn) : floor(dblIn);
+ fract = dblIn - whole;
+
+ if (fract > 0.5)
+ dblIn = whole + 1.0;
+ else if (fract == 0.5)
+ dblIn = whole + fmod(whole, 2.0);
+ else if (fract >= 0.0)
+ dblIn = whole;
+ else if (fract == -0.5)
+ dblIn = whole - fmod(whole, 2.0);
+ else if (fract > -0.5)
+ dblIn = whole;
+ else
+ dblIn = whole - 1.0;
+
+ *pDblOut = dblIn / scale;
+ return S_OK;
+}
+
+/* CY
+ */
+
+/* Powers of 10 from 0..4 D.P. */
+static const int CY_Divisors[5] = { CY_MULTIPLIER/10000, CY_MULTIPLIER/1000,
+ CY_MULTIPLIER/100, CY_MULTIPLIER/10, CY_MULTIPLIER };
+
+/************************************************************************
+ * VarCyFromUI1 (OLEAUT32.98)
+ *
+ * Convert a VT_UI1 to a VT_CY.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromUI1(BYTE bIn, CY* pCyOut)
+{
+ return _VarCyFromUI1(bIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromI2 (OLEAUT32.99)
+ *
+ * Convert a VT_I2 to a VT_CY.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromI2(SHORT sIn, CY* pCyOut)
+{
+ return _VarCyFromI2(sIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromI4 (OLEAUT32.100)
+ *
+ * Convert a VT_I4 to a VT_CY.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromI4(LONG lIn, CY* pCyOut)
+{
+ return _VarCyFromI4(lIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromR4 (OLEAUT32.101)
+ *
+ * Convert a VT_R4 to a VT_CY.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromR4(FLOAT fltIn, CY* pCyOut)
+{
+ return _VarCyFromR4(fltIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromR8 (OLEAUT32.102)
+ *
+ * Convert a VT_R8 to a VT_CY.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromR8(double dblIn, CY* pCyOut)
+{
+#if defined(__GNUC__) && defined(__i386__)
+ /* This code gives identical results to Win32 on Intel.
+ * Here we use fp exceptions to catch overflows when storing the value.
+ */
+ static const unsigned short r8_fpcontrol = 0x137f;
+ static const double r8_multiplier = CY_MULTIPLIER_F;
+ unsigned short old_fpcontrol, result_fpstatus;
+
+ /* Clear exceptions, save the old fp state and load the new state */
+ __asm__ __volatile__( "fnclex" );
+ __asm__ __volatile__( "fstcw %0" : "=m" (old_fpcontrol) : );
+ __asm__ __volatile__( "fldcw %0" : : "m" (r8_fpcontrol) );
+ /* Perform the conversion. */
+ __asm__ __volatile__( "fldl %0" : : "m" (dblIn) );
+ __asm__ __volatile__( "fmull %0" : : "m" (r8_multiplier) );
+ __asm__ __volatile__( "fistpll %0" : : "m" (*pCyOut) );
+ /* Save the resulting fp state, load the old state and clear exceptions */
+ __asm__ __volatile__( "fstsw %0" : "=m" (result_fpstatus) : );
+ __asm__ __volatile__( "fnclex" );
+ __asm__ __volatile__( "fldcw %0" : : "m" (old_fpcontrol) );
+
+ if (result_fpstatus & 0x9) /* Overflow | Invalid */
+ return DISP_E_OVERFLOW;
+ return S_OK;
+#else
+ /* This version produces slightly different results for boundary cases */
+ if (dblIn < -922337203685477.5807 || dblIn >= 922337203685477.5807)
+ return DISP_E_OVERFLOW;
+ dblIn *= CY_MULTIPLIER_F;
+ OLEAUT32_DutchRound(LONG64, dblIn, pCyOut->int64);
+#endif
+ return S_OK;
+}
+
+/************************************************************************
+ * VarCyFromDate (OLEAUT32.103)
+ *
+ * Convert a VT_DATE to a VT_CY.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pCyOut)
+{
+ return _VarCyFromDate(dateIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromStr (OLEAUT32.104)
+ *
+ * Convert a VT_BSTR to a VT_CY.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, CY* pCyOut)
+{
+ return _VarCyFromStr(strIn, lcid, dwFlags, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromDisp (OLEAUT32.105)
+ *
+ * Convert a VT_DISPATCH to a VT_CY.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromDisp(IDispatch* pdispIn, LCID lcid, CY* pCyOut)
+{
+ return _VarCyFromDisp(pdispIn, lcid, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromBool (OLEAUT32.106)
+ *
+ * Convert a VT_BOOL to a VT_CY.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ *
+ * NOTES
+ * While the sign of the boolean is stored in the currency, the value is
+ * converted to either 0 or 1.
+ */
+HRESULT WINAPI VarCyFromBool(VARIANT_BOOL boolIn, CY* pCyOut)
+{
+ return _VarCyFromBool(boolIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromI1 (OLEAUT32.225)
+ *
+ * Convert a VT_I1 to a VT_CY.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromI1(signed char cIn, CY* pCyOut)
+{
+ return _VarCyFromI1(cIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromUI2 (OLEAUT32.226)
+ *
+ * Convert a VT_UI2 to a VT_CY.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromUI2(USHORT usIn, CY* pCyOut)
+{
+ return _VarCyFromUI2(usIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromUI4 (OLEAUT32.227)
+ *
+ * Convert a VT_UI4 to a VT_CY.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromUI4(ULONG ulIn, CY* pCyOut)
+{
+ return _VarCyFromUI4(ulIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromDec (OLEAUT32.228)
+ *
+ * Convert a VT_DECIMAL to a VT_CY.
+ *
+ * PARAMS
+ * pdecIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromDec(DECIMAL* pdecIn, CY* pCyOut)
+{
+ DECIMAL rounded;
+ HRESULT hRet;
+
+ hRet = VarDecRound(pdecIn, 4, &rounded);
+
+ if (SUCCEEDED(hRet))
+ {
+ double d;
+
+ if (DEC_HI32(&rounded))
+ return DISP_E_OVERFLOW;
+
+ /* Note: Without the casts this promotes to int64 which loses precision */
+ d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
+ if (DEC_SIGN(&rounded))
+ d = -d;
+ return _VarCyFromR8(d, pCyOut);
+ }
+ return hRet;
+}
+
+/************************************************************************
+ * VarCyFromI8 (OLEAUT32.366)
+ *
+ * Convert a VT_I8 to a VT_CY.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromI8(LONG64 llIn, CY* pCyOut)
+{
+ return _VarCyFromI8(llIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyFromUI8 (OLEAUT32.375)
+ *
+ * Convert a VT_UI8 to a VT_CY.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarCyFromUI8(ULONG64 ullIn, CY* pCyOut)
+{
+ return _VarCyFromUI8(ullIn, pCyOut);
+}
+
+/************************************************************************
+ * VarCyAdd (OLEAUT32.299)
+ *
+ * Add one CY to another.
+ *
+ * PARAMS
+ * cyLeft [I] Source
+ * cyRight [I] Value to add
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyAdd(const CY cyLeft, const CY cyRight, CY* pCyOut)
+{
+ double l,r;
+ _VarR8FromCy(cyLeft, &l);
+ _VarR8FromCy(cyRight, &r);
+ l = l + r;
+ return _VarCyFromR8(l, pCyOut);
+}
+
+/************************************************************************
+ * VarCyMul (OLEAUT32.303)
+ *
+ * Multiply one CY by another.
+ *
+ * PARAMS
+ * cyLeft [I] Source
+ * cyRight [I] Value to multiply by
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyMul(const CY cyLeft, const CY cyRight, CY* pCyOut)
+{
+ double l,r;
+ _VarR8FromCy(cyLeft, &l);
+ _VarR8FromCy(cyRight, &r);
+ l = l * r;
+ return _VarCyFromR8(l, pCyOut);
+}
+
+/************************************************************************
+ * VarCyMulI4 (OLEAUT32.304)
+ *
+ * Multiply one CY by a VT_I4.
+ *
+ * PARAMS
+ * cyLeft [I] Source
+ * lRight [I] Value to multiply by
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyMulI4(const CY cyLeft, LONG lRight, CY* pCyOut)
+{
+ double d;
+
+ _VarR8FromCy(cyLeft, &d);
+ d = d * lRight;
+ return _VarCyFromR8(d, pCyOut);
+}
+
+/************************************************************************
+ * VarCySub (OLEAUT32.305)
+ *
+ * Subtract one CY from another.
+ *
+ * PARAMS
+ * cyLeft [I] Source
+ * cyRight [I] Value to subtract
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCySub(const CY cyLeft, const CY cyRight, CY* pCyOut)
+{
+ double l,r;
+ _VarR8FromCy(cyLeft, &l);
+ _VarR8FromCy(cyRight, &r);
+ l = l - r;
+ return _VarCyFromR8(l, pCyOut);
+}
+
+/************************************************************************
+ * VarCyAbs (OLEAUT32.306)
+ *
+ * Convert a VT_CY into its absolute value.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK. pCyOut contains the absolute value.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyAbs(const CY cyIn, CY* pCyOut)
+{
+ if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
+ return DISP_E_OVERFLOW;
+
+ pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarCyFix (OLEAUT32.307)
+ *
+ * Return the integer part of a VT_CY.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyFix(const CY cyIn, CY* pCyOut)
+{
+ pCyOut->int64 = cyIn.int64 / CY_MULTIPLIER;
+ pCyOut->int64 *= CY_MULTIPLIER;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarCyInt (OLEAUT32.308)
+ *
+ * Return the integer part of a VT_CY.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyInt(const CY cyIn, CY* pCyOut)
+{
+ double d;
+
+ _VarR8FromCy(cyIn, &d);
+ d = floor(d) * CY_MULTIPLIER_F;
+ OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64);
+ return S_OK;
+}
+
+/************************************************************************
+ * VarCyNeg (OLEAUT32.309)
+ *
+ * Change the sign of a VT_CY.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyNeg(const CY cyIn, CY* pCyOut)
+{
+ if (cyIn.s.Hi == (int)0x80000000 && !cyIn.s.Lo)
+ return DISP_E_OVERFLOW;
+
+ pCyOut->int64 = -cyIn.int64;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarCyRound (OLEAUT32.310)
+ *
+ * Change the precision of a VT_CY.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * cDecimals [I] New number of decimals to keep
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if cDecimals is less than 0.
+ */
+HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut)
+{
+ if (cDecimals < 0)
+ return E_INVALIDARG;
+
+ if (cDecimals > 3)
+ {
+ /* Rounding to more precision than we have */
+ *pCyOut = cyIn;
+ return S_OK;
+ }
+ else
+ {
+ double d, div = CY_Divisors[cDecimals];
+
+ _VarR8FromCy(cyIn, &d);
+ d = d * div;
+ OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
+ d = (double)pCyOut->int64 / div * CY_MULTIPLIER_F;
+ OLEAUT32_DutchRound(LONGLONG, d, pCyOut->int64)
+ return S_OK;
+ }
+}
+
+/************************************************************************
+ * VarCyCmp (OLEAUT32.311)
+ *
+ * Compare two VT_CY values.
+ *
+ * PARAMS
+ * cyLeft [I] Source
+ * cyRight [I] Value to compare
+ *
+ * RETURNS
+ * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to
+ * compare is less, equal or greater than source respectively.
+ * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
+ */
+HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight)
+{
+ HRESULT hRet;
+ CY result;
+
+ /* Subtract right from left, and compare the result to 0 */
+ hRet = VarCySub(cyLeft, cyRight, &result);
+
+ if (SUCCEEDED(hRet))
+ {
+ if (result.int64 < 0)
+ hRet = (HRESULT)VARCMP_LT;
+ else if (result.int64 > 0)
+ hRet = (HRESULT)VARCMP_GT;
+ else
+ hRet = (HRESULT)VARCMP_EQ;
+ }
+ return hRet;
+}
+
+/************************************************************************
+ * VarCyCmpR8 (OLEAUT32.312)
+ *
+ * Compare a VT_CY to a double
+ *
+ * PARAMS
+ * cyLeft [I] Currency Source
+ * dblRight [I] double to compare to cyLeft
+ *
+ * RETURNS
+ * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is
+ * less than, equal to or greater than cyLeft respectively.
+ * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
+ */
+HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight)
+{
+ HRESULT hRet;
+ CY cyRight;
+
+ hRet = _VarCyFromR8(dblRight, &cyRight);
+
+ if (SUCCEEDED(hRet))
+ hRet = VarCyCmp(cyLeft, cyRight);
+
+ return hRet;
+}
+
+/************************************************************************
+ * VarCyMulI8 (OLEAUT32.329)
+ *
+ * Multiply a VT_CY by a VT_I8.
+ *
+ * PARAMS
+ * cyLeft [I] Source
+ * llRight [I] Value to multiply by
+ * pCyOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarCyMulI8(const CY cyLeft, LONG64 llRight, CY* pCyOut)
+{
+ double d;
+
+ _VarR8FromCy(cyLeft, &d);
+ d = d * (double)llRight;
+ return _VarCyFromR8(d, pCyOut);
+}
+
+/* DECIMAL
+ */
+
+/************************************************************************
+ * VarDecFromUI1 (OLEAUT32.190)
+ *
+ * Convert a VT_UI1 to a DECIMAL.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromUI1(BYTE bIn, DECIMAL* pDecOut)
+{
+ return _VarDecFromUI1(bIn, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromI2 (OLEAUT32.191)
+ *
+ * Convert a VT_I2 to a DECIMAL.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
+{
+ return _VarDecFromI2(sIn, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromI4 (OLEAUT32.192)
+ *
+ * Convert a VT_I4 to a DECIMAL.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
+{
+ DEC_HI32(pDecOut) = 0;
+ DEC_MID32(pDecOut) = 0;
+
+ if (lIn < 0)
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
+ DEC_LO32(pDecOut) = -lIn;
+ }
+ else
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
+ DEC_LO32(pDecOut) = lIn;
+ }
+ return S_OK;
+}
+
+/************************************************************************
+ * VarDecFromR4 (OLEAUT32.193)
+ *
+ * Convert a VT_R4 to a DECIMAL.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromR4(FLOAT fltIn, DECIMAL* pDecOut)
+{
+ WCHAR buff[256];
+
+ sprintfW( buff, szFloatFormatW, fltIn );
+ return _VarDecFromStr(buff, LOCALE_SYSTEM_DEFAULT, 0, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromR8 (OLEAUT32.194)
+ *
+ * Convert a VT_R8 to a DECIMAL.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromR8(double dblIn, DECIMAL* pDecOut)
+{
+ WCHAR buff[256];
+
+ sprintfW( buff, szDoubleFormatW, dblIn );
+ return _VarDecFromStr(buff, LOCALE_USER_DEFAULT, 0, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromDate (OLEAUT32.195)
+ *
+ * Convert a VT_DATE to a DECIMAL.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
+{
+ return _VarDecFromDate(dateIn, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromCy (OLEAUT32.196)
+ *
+ * Convert a VT_CY to a DECIMAL.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
+{
+ DEC_HI32(pDecOut) = 0;
+
+ /* Note: This assumes 2s complement integer representation */
+ if (cyIn.s.Hi & 0x80000000)
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
+ DEC_LO64(pDecOut) = -cyIn.int64;
+ }
+ else
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
+ DEC_MID32(pDecOut) = cyIn.s.Hi;
+ DEC_LO32(pDecOut) = cyIn.s.Lo;
+ }
+ return S_OK;
+}
+
+/************************************************************************
+ * VarDecFromStr (OLEAUT32.197)
+ *
+ * Convert a VT_BSTR to a DECIMAL.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
+{
+ return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromDisp (OLEAUT32.198)
+ *
+ * Convert a VT_DISPATCH to a DECIMAL.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
+{
+ return _VarDecFromDisp(pdispIn, lcid, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromBool (OLEAUT32.199)
+ *
+ * Convert a VT_BOOL to a DECIMAL.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ *
+ * NOTES
+ * The value is converted to either 0 (if bIn is FALSE) or -1 (TRUE).
+ */
+HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
+{
+ DEC_HI32(pDecOut) = 0;
+ DEC_MID32(pDecOut) = 0;
+ if (bIn)
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
+ DEC_LO32(pDecOut) = 1;
+ }
+ else
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
+ DEC_LO32(pDecOut) = 0;
+ }
+ return S_OK;
+}
+
+/************************************************************************
+ * VarDecFromI1 (OLEAUT32.241)
+ *
+ * Convert a VT_I1 to a DECIMAL.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromI1(signed char cIn, DECIMAL* pDecOut)
+{
+ return _VarDecFromI1(cIn, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromUI2 (OLEAUT32.242)
+ *
+ * Convert a VT_UI2 to a DECIMAL.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
+{
+ return _VarDecFromUI2(usIn, pDecOut);
+}
+
+/************************************************************************
+ * VarDecFromUI4 (OLEAUT32.243)
+ *
+ * Convert a VT_UI4 to a DECIMAL.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
+{
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
+ DEC_HI32(pDecOut) = 0;
+ DEC_MID32(pDecOut) = 0;
+ DEC_LO32(pDecOut) = ulIn;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarDecFromI8 (OLEAUT32.374)
+ *
+ * Convert a VT_I8 to a DECIMAL.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
+{
+ PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
+
+ DEC_HI32(pDecOut) = 0;
+
+ /* Note: This assumes 2s complement integer representation */
+ if (pLi->s.HighPart & 0x80000000)
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
+ DEC_LO64(pDecOut) = -pLi->QuadPart;
+ }
+ else
+ {
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
+ DEC_MID32(pDecOut) = pLi->s.HighPart;
+ DEC_LO32(pDecOut) = pLi->s.LowPart;
+ }
+ return S_OK;
+}
+
+/************************************************************************
+ * VarDecFromUI8 (OLEAUT32.375)
+ *
+ * Convert a VT_UI8 to a DECIMAL.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
+{
+ DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
+ DEC_HI32(pDecOut) = 0;
+ DEC_LO64(pDecOut) = ullIn;
+ return S_OK;
+}
+
+/* Make two DECIMALS the same scale; used by math functions below */
+static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
+ const DECIMAL** ppDecRight,
+ DECIMAL* pDecOut)
+{
+ static DECIMAL scaleFactor;
+ DECIMAL decTemp;
+ int scaleAmount, i;
+ HRESULT hRet = S_OK;
+
+ if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
+ return E_INVALIDARG;
+
+ DEC_LO32(&scaleFactor) = 10;
+
+ i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
+
+ if (!scaleAmount)
+ return S_OK; /* Same scale */
+
+ if (scaleAmount > 0)
+ {
+ decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */
+ *ppDecRight = pDecOut;
+ }
+ else
+ {
+ decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */
+ *ppDecLeft = pDecOut;
+ i = scaleAmount = -scaleAmount;
+ }
+
+ if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE)
+ return DISP_E_OVERFLOW; /* Can't scale up */
+
+ /* Multiply up the value to be scaled by the correct amount */
+ while (SUCCEEDED(hRet) && i--)
+ {
+ /* Note we are multiplying by a value with a scale of 0, so we dont recurse */
+ hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut);
+ decTemp = *pDecOut;
+ }
+ DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */
+ return hRet;
+}
+
+/* Add two unsigned 32 bit values with overflow */
+static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
+{
+ ULARGE_INTEGER ul64;
+
+ ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
+ *pulHigh = ul64.s.HighPart;
+ return ul64.s.LowPart;
+}
+
+/* Subtract two unsigned 32 bit values with underflow */
+static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
+{
+ int invert = 0;
+ ULARGE_INTEGER ul64;
+
+ ul64.QuadPart = (LONG64)ulLeft - (ULONG64)ulRight;
+ if (ulLeft < ulRight)
+ invert = 1;
+
+ if (ul64.QuadPart > (ULONG64)*pulHigh)
+ ul64.QuadPart -= (ULONG64)*pulHigh;
+ else
+ {
+ ul64.QuadPart -= (ULONG64)*pulHigh;
+ invert = 1;
+ }
+ if (invert)
+ ul64.s.HighPart = -ul64.s.HighPart ;
+
+ *pulHigh = ul64.s.HighPart;
+ return ul64.s.LowPart;
+}
+
+/* Multiply two unsigned 32 bit values with overflow */
+static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
+{
+ ULARGE_INTEGER ul64;
+
+ ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
+ *pulHigh = ul64.s.HighPart;
+ return ul64.s.LowPart;
+}
+
+/* Compare two decimals that have the same scale */
+static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
+{
+ if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
+ (DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
+ return -1;
+ else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
+ return 0;
+ return 1;
+}
+
+/************************************************************************
+ * VarDecAdd (OLEAUT32.177)
+ *
+ * Add one DECIMAL to another.
+ *
+ * PARAMS
+ * pDecLeft [I] Source
+ * pDecRight [I] Value to add
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
+{
+ HRESULT hRet;
+ DECIMAL scaled;
+
+ hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled);
+
+ if (SUCCEEDED(hRet))
+ {
+ /* Our decimals now have the same scale, we can add them as 96 bit integers */
+ ULONG overflow = 0;
+ BYTE sign = DECIMAL_POS;
+
+ /* Correct for the sign of the result */
+ if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
+ {
+ /* -x + -y : Negative */
+ sign = DECIMAL_NEG;
+ goto VarDecAdd_AsPositive;
+ }
+ else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
+ {
+ int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
+
+ /* -x + y : Negative if x > y */
+ if (cmp > 0)
+ {
+ sign = DECIMAL_NEG;
+VarDecAdd_AsNegative:
+ DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
+ DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
+ DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
+ }
+ else
+ {
+VarDecAdd_AsInvertedNegative:
+ DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecRight), DEC_LO32(pDecLeft), &overflow);
+ DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
+ DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecRight), DEC_HI32(pDecLeft), &overflow);
+ }
+ }
+ else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
+ {
+ int cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
+
+ /* x + -y : Negative if x <= y */
+ if (cmp <= 0)
+ {
+ sign = DECIMAL_NEG;
+ goto VarDecAdd_AsInvertedNegative;
+ }
+ goto VarDecAdd_AsNegative;
+ }
+ else
+ {
+ /* x + y : Positive */
+VarDecAdd_AsPositive:
+ DEC_LO32(pDecOut) = VARIANT_Add(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
+ DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
+ DEC_HI32(pDecOut) = VARIANT_Add(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
+ }
+
+ if (overflow)
+ return DISP_E_OVERFLOW; /* overflowed */
+
+ DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
+ DEC_SIGN(pDecOut) = sign;
+ }
+ return hRet;
+}
+
+/************************************************************************
+ * VarDecDiv (OLEAUT32.178)
+ *
+ * Divide one DECIMAL by another.
+ *
+ * PARAMS
+ * pDecLeft [I] Source
+ * pDecRight [I] Value to divide by
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDecDiv(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
+{
+ FIXME("(%p,%p,%p)-stub!\n",pDecLeft,pDecRight,pDecOut);
+ return DISP_E_OVERFLOW;
+}
+
+/************************************************************************
+ * VarDecMul (OLEAUT32.179)
+ *
+ * Multiply one DECIMAL by another.
+ *
+ * PARAMS
+ * pDecLeft [I] Source
+ * pDecRight [I] Value to multiply by
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDecMul(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
+{
+ /* FIXME: This only allows multiplying by a fixed integer <= 0xffffffff */
+
+ if (!DEC_SCALE(pDecLeft) || !DEC_SCALE(pDecRight))
+ {
+ /* At least one term is an integer */
+ const DECIMAL* pDecInteger = DEC_SCALE(pDecLeft) ? pDecRight : pDecLeft;
+ const DECIMAL* pDecOperand = DEC_SCALE(pDecLeft) ? pDecLeft : pDecRight;
+ HRESULT hRet = S_OK;
+ unsigned int multiplier = DEC_LO32(pDecInteger);
+ ULONG overflow = 0;
+
+ if (DEC_HI32(pDecInteger) || DEC_MID32(pDecInteger))
+ {
+ FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
+ return DISP_E_OVERFLOW;
+ }
+
+ DEC_LO32(pDecOut) = VARIANT_Mul(DEC_LO32(pDecOperand), multiplier, &overflow);
+ DEC_MID32(pDecOut) = VARIANT_Mul(DEC_MID32(pDecOperand), multiplier, &overflow);
+ DEC_HI32(pDecOut) = VARIANT_Mul(DEC_HI32(pDecOperand), multiplier, &overflow);
+
+ if (overflow)
+ hRet = DISP_E_OVERFLOW;
+ else
+ {
+ BYTE sign = DECIMAL_POS;
+
+ if (DEC_SIGN(pDecLeft) != DEC_SIGN(pDecRight))
+ sign = DECIMAL_NEG; /* pos * neg => negative */
+ DEC_SIGN(pDecOut) = sign;
+ DEC_SCALE(pDecOut) = DEC_SCALE(pDecOperand);
+ }
+ return hRet;
+ }
+ FIXME("(%p,%p,%p) semi-stub!\n",pDecLeft,pDecRight,pDecOut);
+ return DISP_E_OVERFLOW;
+}
+
+/************************************************************************
+ * VarDecSub (OLEAUT32.181)
+ *
+ * Subtract one DECIMAL from another.
+ *
+ * PARAMS
+ * pDecLeft [I] Source
+ * pDecRight [I] DECIMAL to subtract from pDecLeft
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut)
+{
+ DECIMAL decRight;
+
+ /* Implement as addition of the negative */
+ VarDecNeg(pDecRight, &decRight);
+ return VarDecAdd(pDecLeft, &decRight, pDecOut);
+}
+
+/************************************************************************
+ * VarDecAbs (OLEAUT32.182)
+ *
+ * Convert a DECIMAL into its absolute value.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK. This function does not fail.
+ */
+HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
+{
+ *pDecOut = *pDecIn;
+ DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarDecFix (OLEAUT32.187)
+ *
+ * Return the integer portion of a DECIMAL.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
+{
+ if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
+ return E_INVALIDARG;
+
+ if (!DEC_SCALE(pDecIn))
+ {
+ *pDecOut = *pDecIn; /* Already an integer */
+ return S_OK;
+ }
+
+ FIXME("semi-stub!\n");
+ return DISP_E_OVERFLOW;
+}
+
+/************************************************************************
+ * VarDecInt (OLEAUT32.188)
+ *
+ * Return the integer portion of a DECIMAL.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
+{
+ if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG)
+ return E_INVALIDARG;
+
+ if (!DEC_SCALE(pDecIn))
+ {
+ *pDecOut = *pDecIn; /* Already an integer */
+ return S_OK;
+ }
+
+ FIXME("semi-stub!\n");
+ return DISP_E_OVERFLOW;
+}
+
+/************************************************************************
+ * VarDecNeg (OLEAUT32.189)
+ *
+ * Change the sign of a DECIMAL.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * S_OK. This function does not fail.
+ */
+HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
+{
+ *pDecOut = *pDecIn;
+ DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarDecRound (OLEAUT32.203)
+ *
+ * Change the precision of a DECIMAL.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * cDecimals [I] New number of decimals to keep
+ * pDecOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK. pDecOut contains the rounded value.
+ * Failure: E_INVALIDARG if any argument is invalid.
+ */
+HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOut)
+{
+ if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
+ return E_INVALIDARG;
+
+ if (cDecimals >= DEC_SCALE(pDecIn))
+ {
+ *pDecOut = *pDecIn; /* More precision than we have */
+ return S_OK;
+ }
+
+ FIXME("semi-stub!\n");
+
+ return DISP_E_OVERFLOW;
+}
+
+/************************************************************************
+ * VarDecCmp (OLEAUT32.204)
+ *
+ * Compare two DECIMAL values.
+ *
+ * PARAMS
+ * pDecLeft [I] Source
+ * pDecRight [I] Value to compare
+ *
+ * RETURNS
+ * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft
+ * is less than, equal to or greater than pDecRight respectively.
+ * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
+ */
+HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
+{
+ HRESULT hRet;
+ DECIMAL result;
+
+ /* Subtract right from left, and compare the result to 0 */
+ hRet = VarDecSub(pDecLeft, pDecRight, &result);
+
+ if (SUCCEEDED(hRet))
+ {
+ int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
+
+ if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
+ hRet = (HRESULT)VARCMP_LT;
+ else if (non_zero)
+ hRet = (HRESULT)VARCMP_GT;
+ else
+ hRet = (HRESULT)VARCMP_EQ;
+ }
+ return hRet;
+}
+
+/************************************************************************
+ * VarDecCmpR8 (OLEAUT32.298)
+ *
+ * Compare a DECIMAL to a double
+ *
+ * PARAMS
+ * pDecLeft [I] DECIMAL Source
+ * dblRight [I] double to compare to pDecLeft
+ *
+ * RETURNS
+ * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight
+ * is less than, equal to or greater than pDecLeft respectively.
+ * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason
+ */
+HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight)
+{
+ HRESULT hRet;
+ DECIMAL decRight;
+
+ hRet = VarDecFromR8(dblRight, &decRight);
+
+ if (SUCCEEDED(hRet))
+ hRet = VarDecCmp(pDecLeft, &decRight);
+
+ return hRet;
+}
+
+/* BOOL
+ */
+
+/************************************************************************
+ * VarBoolFromUI1 (OLEAUT32.118)
+ *
+ * Convert a VT_UI1 to a VT_BOOL.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromUI1(BYTE bIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromUI1(bIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromI2 (OLEAUT32.119)
+ *
+ * Convert a VT_I2 to a VT_BOOL.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromI2(SHORT sIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromI2(sIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromI4 (OLEAUT32.120)
+ *
+ * Convert a VT_I4 to a VT_BOOL.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromI4(LONG lIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromI4(lIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromR4 (OLEAUT32.121)
+ *
+ * Convert a VT_R4 to a VT_BOOL.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromR4(FLOAT fltIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromR4(fltIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromR8 (OLEAUT32.122)
+ *
+ * Convert a VT_R8 to a VT_BOOL.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromR8(double dblIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromR8(dblIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromDate (OLEAUT32.123)
+ *
+ * Convert a VT_DATE to a VT_BOOL.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromDate(dateIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromCy (OLEAUT32.124)
+ *
+ * Convert a VT_CY to a VT_BOOL.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromCy(cyIn, pBoolOut);
+}
+
+static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest)
+{
+ HRSRC hrsrc;
+
+ hrsrc = FindResourceExW( OLEAUT32_hModule, (LPWSTR)RT_STRING,
+ (LPCWSTR)((dwId >> 4) + 1), langId );
+ if (hrsrc)
+ {
+ HGLOBAL hmem = LoadResource( OLEAUT32_hModule, hrsrc );
+
+ if (hmem)
+ {
+ const WCHAR *p;
+ unsigned int i;
+
+ p = LockResource( hmem );
+ for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1;
+
+ memcpy( lpszDest, p + 1, *p * sizeof(WCHAR) );
+ lpszDest[*p] = '\0';
+ TRACE("got %s for LANGID %08x\n", debugstr_w(lpszDest), langId);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/************************************************************************
+ * VarBoolFromStr (OLEAUT32.125)
+ *
+ * Convert a VT_BSTR to a VT_BOOL.
+ *
+ * PARAMS
+ * strIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pBoolOut is invalid.
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ *
+ * NOTES
+ * - strIn will be recognised if it contains "#TRUE#" or "#FALSE#". Additionally,
+ * it may contain (in any case mapping) the text "true" or "false".
+ * - If dwFlags includes VAR_LOCALBOOL, then the text may also match the
+ * localised text of "True" or "False" in the language specified by lcid.
+ * - If none of these matches occur, the string is treated as a numeric string
+ * and the boolean pBoolOut will be set according to whether the number is zero
+ * or not. The dwFlags parameter is passed to VarR8FromStr() for this conversion.
+ * - If the text is not numeric and does not match any of the above, then
+ * DISP_E_TYPEMISMATCH is returned.
+ */
+HRESULT WINAPI VarBoolFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, VARIANT_BOOL *pBoolOut)
+{
+ /* Any VB/VBA programmers out there should recognise these strings... */
+ static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
+ static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
+ WCHAR szBuff[64];
+ LANGID langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+ HRESULT hRes = S_OK;
+
+ if (!strIn || !pBoolOut)
+ return DISP_E_TYPEMISMATCH;
+
+ /* Check if we should be comparing against localised text */
+ if (dwFlags & VAR_LOCALBOOL)
+ {
+ /* Convert our LCID into a usable value */
+ lcid = ConvertDefaultLocale(lcid);
+
+ langId = LANGIDFROMLCID(lcid);
+
+ if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
+ langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+
+ /* Note: Native oleaut32 always copies strIn and maps halfwidth characters.
+ * I don't think this is needed unless any of the localised text strings
+ * contain characters that can be so mapped. In the event that this is
+ * true for a given language (possibly some Asian languages), then strIn
+ * should be mapped here _only_ if langId is an Id for which this can occur.
+ */
+ }
+
+ /* Note that if we are not comparing against localised strings, langId
+ * will have its default value of LANG_ENGLISH. This allows us to mimic
+ * the native behaviour of always checking against English strings even
+ * after we've checked for localised ones.
+ */
+VarBoolFromStr_CheckLocalised:
+ if (VARIANT_GetLocalisedText(langId, IDS_TRUE, szBuff))
+ {
+ /* Compare against localised strings, ignoring case */
+ if (!strcmpiW(strIn, szBuff))
+ {
+ *pBoolOut = VARIANT_TRUE; /* Matched localised 'true' text */
+ return hRes;
+ }
+ VARIANT_GetLocalisedText(langId, IDS_FALSE, szBuff);
+ if (!strcmpiW(strIn, szBuff))
+ {
+ *pBoolOut = VARIANT_FALSE; /* Matched localised 'false' text */
+ return hRes;
+ }
+ }
+
+ if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
+ {
+ /* We have checked the localised text, now check English */
+ langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+ goto VarBoolFromStr_CheckLocalised;
+ }
+
+ /* All checks against localised text have failed, try #TRUE#/#FALSE# */
+ if (!strcmpW(strIn, szFalse))
+ *pBoolOut = VARIANT_FALSE;
+ else if (!strcmpW(strIn, szTrue))
+ *pBoolOut = VARIANT_TRUE;
+ else
+ {
+ double d;
+
+ /* If this string is a number, convert it as one */
+ hRes = _VarR8FromStr(strIn, lcid, dwFlags, &d);
+ if (SUCCEEDED(hRes))
+ hRes = _VarBoolFromR8(d, pBoolOut);
+ }
+ return hRes;
+}
+
+/************************************************************************
+ * VarBoolFromDisp (OLEAUT32.126)
+ *
+ * Convert a VT_DISPATCH to a VT_BOOL.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarBoolFromDisp(IDispatch* pdispIn, LCID lcid, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromDisp(pdispIn, lcid, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromI1 (OLEAUT32.233)
+ *
+ * Convert a VT_I1 to a VT_BOOL.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromI1(signed char cIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromI1(cIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromUI2 (OLEAUT32.234)
+ *
+ * Convert a VT_UI2 to a VT_BOOL.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromUI2(USHORT usIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromUI2(usIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromUI4 (OLEAUT32.235)
+ *
+ * Convert a VT_UI4 to a VT_BOOL.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromUI4(ulIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromDec (OLEAUT32.236)
+ *
+ * Convert a VT_DECIMAL to a VT_BOOL.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pDecIn is invalid.
+ */
+HRESULT WINAPI VarBoolFromDec(DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
+{
+ if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
+ return E_INVALIDARG;
+
+ if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
+ *pBoolOut = VARIANT_TRUE;
+ else
+ *pBoolOut = VARIANT_FALSE;
+ return S_OK;
+}
+
+/************************************************************************
+ * VarBoolFromI8 (OLEAUT32.370)
+ *
+ * Convert a VT_I8 to a VT_BOOL.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromI8(LONG64 llIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromI8(llIn, pBoolOut);
+}
+
+/************************************************************************
+ * VarBoolFromUI8 (OLEAUT32.371)
+ *
+ * Convert a VT_UI8 to a VT_BOOL.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pBoolOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarBoolFromUI8(ULONG64 ullIn, VARIANT_BOOL *pBoolOut)
+{
+ return _VarBoolFromUI8(ullIn, pBoolOut);
+}
+
+/* BSTR
+ */
+
+/* Write a number from a UI8 and sign */
+static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
+{
+ do
+ {
+ WCHAR ulNextDigit = ulVal % 10;
+
+ *szOut-- = '0' + ulNextDigit;
+ ulVal = (ulVal - ulNextDigit) / 10;
+ } while (ulVal);
+
+ szOut++;
+ return szOut;
+}
+
+/* Create a (possibly localised) BSTR from a UI8 and sign */
+static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
+{
+ WCHAR szConverted[256];
+
+ if (dwFlags & VAR_NEGATIVE)
+ *--szOut = '-';
+
+ if (dwFlags & LOCALE_USE_NLS)
+ {
+ /* Format the number for the locale */
+ szConverted[0] = '\0';
+ GetNumberFormatW(lcid,
+ dwFlags & LOCALE_NOUSEROVERRIDE,
+ szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
+ szOut = szConverted;
+ }
+ return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
+}
+
+/* Create a (possibly localised) BSTR from a UI8 and sign */
+static HRESULT VARIANT_BstrFromUInt(ULONG64 ulVal, LCID lcid, DWORD dwFlags, BSTR *pbstrOut)
+{
+ WCHAR szBuff[64], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
+
+ if (!pbstrOut)
+ return E_INVALIDARG;
+
+ /* Create the basic number string */
+ *szOut-- = '\0';
+ szOut = VARIANT_WriteNumber(ulVal, szOut);
+
+ *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
+ TRACE("returning %s\n", debugstr_w(*pbstrOut));
+ return *pbstrOut ? S_OK : E_OUTOFMEMORY;
+}
+
+/******************************************************************************
+ * VarBstrFromUI1 (OLEAUT32.108)
+ *
+ * Convert a VT_UI1 to a VT_BSTR.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromUI1(BYTE bIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ return VARIANT_BstrFromUInt(bIn, lcid, dwFlags, pbstrOut);
+}
+
+/******************************************************************************
+ * VarBstrFromI2 (OLEAUT32.109)
+ *
+ * Convert a VT_I2 to a VT_BSTR.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromI2(short sIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ ULONG64 ul64 = sIn;
+
+ if (sIn < 0)
+ {
+ ul64 = -sIn;
+ dwFlags |= VAR_NEGATIVE;
+ }
+ return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
+}
+
+/******************************************************************************
+ * VarBstrFromI4 (OLEAUT32.110)
+ *
+ * Convert a VT_I4 to a VT_BSTR.
+ *
+ * PARAMS
+ * lIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromI4(LONG lIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ ULONG64 ul64 = lIn;
+
+ if (lIn < 0)
+ {
+ ul64 = -lIn;
+ dwFlags |= VAR_NEGATIVE;
+ }
+ return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
+}
+
+static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
+ BSTR* pbstrOut, LPCWSTR lpszFormat)
+{
+ WCHAR buff[256];
+
+ if (!pbstrOut)
+ return E_INVALIDARG;
+
+ sprintfW( buff, lpszFormat, dblIn );
+ TRACE("created string %s\n", debugstr_w(buff));
+ if (dwFlags & LOCALE_USE_NLS)
+ {
+ WCHAR numbuff[256];
+
+ /* Format the number for the locale */
+ numbuff[0] = '\0';
+ GetNumberFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
+ buff, NULL, numbuff, sizeof(numbuff) / sizeof(WCHAR));
+ TRACE("created NLS string %s\n", debugstr_w(numbuff));
+ *pbstrOut = SysAllocString(numbuff);
+ }
+ else
+ *pbstrOut = SysAllocString(buff);
+ return *pbstrOut ? S_OK : E_OUTOFMEMORY;
+}
+
+/******************************************************************************
+ * VarBstrFromR4 (OLEAUT32.111)
+ *
+ * Convert a VT_R4 to a VT_BSTR.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromR4(FLOAT fltIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ return VARIANT_BstrFromReal(fltIn, lcid, dwFlags, pbstrOut, szFloatFormatW);
+}
+
+/******************************************************************************
+ * VarBstrFromR8 (OLEAUT32.112)
+ *
+ * Convert a VT_R8 to a VT_BSTR.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromR8(double dblIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ return VARIANT_BstrFromReal(dblIn, lcid, dwFlags, pbstrOut, szDoubleFormatW);
+}
+
+/******************************************************************************
+ * VarBstrFromCy [OLEAUT32.113]
+ *
+ * Convert a VT_CY to a VT_BSTR.
+ *
+ * PARAMS
+ * cyIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
+{
+ WCHAR buff[256];
+ double dblVal;
+
+ if (!pbstrOut)
+ return E_INVALIDARG;
+
+ VarR8FromCy(cyIn, &dblVal);
+ sprintfW(buff, szDoubleFormatW, dblVal);
+
+ if (dwFlags & LOCALE_USE_NLS)
+ {
+ WCHAR cybuff[256];
+
+ /* Format the currency for the locale */
+ cybuff[0] = '\0';
+ GetCurrencyFormatW(lcid, dwFlags & LOCALE_NOUSEROVERRIDE,
+ buff, NULL, cybuff, sizeof(cybuff) / sizeof(WCHAR));
+ *pbstrOut = SysAllocString(cybuff);
+ }
+ else
+ *pbstrOut = SysAllocString(buff);
+
+ return *pbstrOut ? S_OK : E_OUTOFMEMORY;
+}
+
+/******************************************************************************
+ * VarBstrFromDate [OLEAUT32.114]
+ *
+ * Convert a VT_DATE to a VT_BSTR.
+ *
+ * PARAMS
+ * dateIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut or dateIn is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ SYSTEMTIME st;
+ DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
+ WCHAR date[128], *time;
+
+ TRACE("(%g,0x%08lx,0x%08lx,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
+
+ if (!pbstrOut || !VariantTimeToSystemTime(dateIn, &st))
+ return E_INVALIDARG;
+
+ *pbstrOut = NULL;
+
+ if (dwFlags & VAR_CALENDAR_THAI)
+ st.wYear += 553; /* Use the Thai buddhist calendar year */
+ else if (dwFlags & (VAR_CALENDAR_HIJRI|VAR_CALENDAR_GREGORIAN))
+ FIXME("VAR_CALENDAR_HIJRI/VAR_CALENDAR_GREGORIAN not handled\n");
+
+ if (dwFlags & LOCALE_USE_NLS)
+ dwFlags &= ~(VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY);
+ else
+ {
+ double whole = dateIn < 0 ? ceil(dateIn) : floor(dateIn);
+ double partial = dateIn - whole;
+
+ if (whole == 0.0)
+ dwFlags |= VAR_TIMEVALUEONLY;
+ else if (partial < 1e-12)
+ dwFlags |= VAR_DATEVALUEONLY;
+ }
+
+ if (dwFlags & VAR_TIMEVALUEONLY)
+ date[0] = '\0';
+ else
+ if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
+ sizeof(date)/sizeof(WCHAR)))
+ return E_INVALIDARG;
+
+ if (!(dwFlags & VAR_DATEVALUEONLY))
+ {
+ time = date + strlenW(date);
+ if (time != date)
+ *time++ = ' ';
+ if (!GetTimeFormatW(lcid, dwFormatFlags, &st, NULL, time,
+ sizeof(date)/sizeof(WCHAR)-(time-date)))
+ return E_INVALIDARG;
+ }
+
+ *pbstrOut = SysAllocString(date);
+ if (*pbstrOut)
+ TRACE("returning %s\n", debugstr_w(*pbstrOut));
+ return *pbstrOut ? S_OK : E_OUTOFMEMORY;
+}
+
+/******************************************************************************
+ * VarBstrFromBool (OLEAUT32.116)
+ *
+ * Convert a VT_BOOL to a VT_BSTR.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ *
+ * NOTES
+ * If dwFlags includes VARIANT_LOCALBOOL, this function converts to the
+ * localised text of "True" or "False". To convert a bool into a
+ * numeric string of "0" or "-1", use VariantChangeTypeTypeEx().
+ */
+HRESULT WINAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ WCHAR szBuff[64];
+ DWORD dwResId = IDS_TRUE;
+ LANGID langId;
+
+ TRACE("%d,0x%08lx,0x%08lx,%p\n", boolIn, lcid, dwFlags, pbstrOut);
+
+ if (!pbstrOut)
+ return E_INVALIDARG;
+
+ /* VAR_BOOLONOFF and VAR_BOOLYESNO are internal flags used
+ * for variant formatting */
+ switch (dwFlags & (VAR_LOCALBOOL|VAR_BOOLONOFF|VAR_BOOLYESNO))
+ {
+ case VAR_BOOLONOFF:
+ dwResId = IDS_ON;
+ break;
+ case VAR_BOOLYESNO:
+ dwResId = IDS_YES;
+ break;
+ case VAR_LOCALBOOL:
+ break;
+ default:
+ lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),SORT_DEFAULT);
+ }
+
+ lcid = ConvertDefaultLocale(lcid);
+ langId = LANGIDFROMLCID(lcid);
+ if (PRIMARYLANGID(langId) == LANG_NEUTRAL)
+ langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+
+ if (boolIn == VARIANT_FALSE)
+ dwResId++; /* Use negative form */
+
+VarBstrFromBool_GetLocalised:
+ if (VARIANT_GetLocalisedText(langId, dwResId, szBuff))
+ {
+ *pbstrOut = SysAllocString(szBuff);
+ return *pbstrOut ? S_OK : E_OUTOFMEMORY;
+ }
+
+ if (langId != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
+ {
+ langId = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+ goto VarBstrFromBool_GetLocalised;
+ }
+
+ /* Should never get here */
+ WARN("Failed to load bool text!\n");
+ return E_OUTOFMEMORY;
+}
+
+/******************************************************************************
+ * VarBstrFromI1 (OLEAUT32.229)
+ *
+ * Convert a VT_I1 to a VT_BSTR.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromI1(signed char cIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ ULONG64 ul64 = cIn;
+
+ if (cIn < 0)
+ {
+ ul64 = -cIn;
+ dwFlags |= VAR_NEGATIVE;
+ }
+ return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
+}
+
+/******************************************************************************
+ * VarBstrFromUI2 (OLEAUT32.230)
+ *
+ * Convert a VT_UI2 to a VT_BSTR.
+ *
+ * PARAMS
+ * usIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromUI2(USHORT usIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ return VARIANT_BstrFromUInt(usIn, lcid, dwFlags, pbstrOut);
+}
+
+/******************************************************************************
+ * VarBstrFromUI4 (OLEAUT32.231)
+ *
+ * Convert a VT_UI4 to a VT_BSTR.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromUI4(ULONG ulIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ return VARIANT_BstrFromUInt(ulIn, lcid, dwFlags, pbstrOut);
+}
+
+/******************************************************************************
+ * VarBstrFromDec (OLEAUT32.232)
+ *
+ * Convert a VT_DECIMAL to a VT_BSTR.
+ *
+ * PARAMS
+ * pDecIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ if (!pbstrOut)
+ return E_INVALIDARG;
+
+ if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
+ {
+ WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
+
+ /* Create the basic number string */
+ *szOut-- = '\0';
+ szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
+ if (DEC_SIGN(pDecIn))
+ dwFlags |= VAR_NEGATIVE;
+
+ *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
+ TRACE("returning %s\n", debugstr_w(*pbstrOut));
+ return *pbstrOut ? S_OK : E_OUTOFMEMORY;
+ }
+ FIXME("semi-stub\n");
+ return E_INVALIDARG;
+}
+
+/************************************************************************
+ * VarBstrFromI8 (OLEAUT32.370)
+ *
+ * Convert a VT_I8 to a VT_BSTR.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromI8(LONG64 llIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ ULONG64 ul64 = llIn;
+
+ if (llIn < 0)
+ {
+ ul64 = -llIn;
+ dwFlags |= VAR_NEGATIVE;
+ }
+ return VARIANT_BstrFromUInt(ul64, lcid, dwFlags, pbstrOut);
+}
+
+/************************************************************************
+ * VarBstrFromUI8 (OLEAUT32.371)
+ *
+ * Convert a VT_UI8 to a VT_BSTR.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * lcid [I] LCID for the conversion
+ * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrFromUI8(ULONG64 ullIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
+{
+ return VARIANT_BstrFromUInt(ullIn, lcid, dwFlags, pbstrOut);
+}
+
+/**********************************************************************
+ * VarBstrCat (OLEAUT32.313)
+ *
+ * Concatenate two BSTR values.
+ *
+ * PARAMS
+ * pbstrLeft [I] Source
+ * pbstrRight [I] Value to concatenate
+ * pbstrOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if pbstrOut is invalid.
+ * E_OUTOFMEMORY, if memory allocation fails.
+ */
+HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
+{
+ unsigned int len;
+
+ if (!pbstrOut)
+ return E_INVALIDARG;
+
+ len = pbstrLeft ? strlenW(pbstrLeft) : 0;
+ if (pbstrRight)
+ len += strlenW(pbstrRight);
+
+ *pbstrOut = SysAllocStringLen(NULL, len);
+ if (!*pbstrOut)
+ return E_OUTOFMEMORY;
+
+ *pbstrOut = '\0';
+
+ if (pbstrLeft)
+ strcpyW(*pbstrOut, pbstrLeft);
+
+ if (pbstrRight)
+ strcatW(*pbstrOut, pbstrRight);
+
+ return S_OK;
+}
+
+/**********************************************************************
+ * VarBstrCmp (OLEAUT32.314)
+ *
+ * Compare two BSTR values.
+ *
+ * PARAMS
+ * pbstrLeft [I] Source
+ * pbstrRight [I] Value to compare
+ * lcid [I] LCID for the comparason
+ * dwFlags [I] Flags to pass directly to CompareStringW().
+ *
+ * RETURNS
+ * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less
+ * than, equal to or greater than pbstrRight respectively.
+ * VARCMP_NULL is returned if either string is NULL, unless both are NULL
+ * in which case VARCMP_EQ is returned.
+ */
+HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
+{
+ if (!pbstrLeft)
+ {
+ if (!pbstrRight || !*pbstrRight)
+ return VARCMP_EQ;
+ return VARCMP_NULL;
+ }
+ else if (!pbstrRight)
+ {
+ if (!*pbstrLeft)
+ return VARCMP_EQ;
+ return VARCMP_NULL;
+ }
+
+ return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
+}
+
+/*
+ * DATE
+ */
+
+/******************************************************************************
+ * VarDateFromUI1 (OLEAUT32.88)
+ *
+ * Convert a VT_UI1 to a VT_DATE.
+ *
+ * PARAMS
+ * bIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromUI1(BYTE bIn, DATE* pdateOut)
+{
+ return _VarDateFromUI1(bIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromI2 (OLEAUT32.89)
+ *
+ * Convert a VT_I2 to a VT_DATE.
+ *
+ * PARAMS
+ * sIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromI2(short sIn, DATE* pdateOut)
+{
+ return _VarDateFromI2(sIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromI4 (OLEAUT32.90)
+ *
+ * Convert a VT_I4 to a VT_DATE.
+ *
+ * PARAMS
+ * lIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromI4(LONG lIn, DATE* pdateOut)
+{
+ return _VarDateFromI4(lIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromR4 (OLEAUT32.91)
+ *
+ * Convert a VT_R4 to a VT_DATE.
+ *
+ * PARAMS
+ * fltIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromR4(FLOAT fltIn, DATE* pdateOut)
+{
+ return _VarDateFromR4(fltIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromR8 (OLEAUT32.92)
+ *
+ * Convert a VT_R8 to a VT_DATE.
+ *
+ * PARAMS
+ * dblIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromR8(double dblIn, DATE* pdateOut)
+{
+ return _VarDateFromR8(dblIn, pdateOut);
+}
+
+/**********************************************************************
+ * VarDateFromDisp (OLEAUT32.95)
+ *
+ * Convert a VT_DISPATCH to a VT_DATE.
+ *
+ * PARAMS
+ * pdispIn [I] Source
+ * lcid [I] LCID for conversion
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: E_INVALIDARG, if the source value is invalid
+ * DISP_E_OVERFLOW, if the value will not fit in the destination
+ * DISP_E_TYPEMISMATCH, if the type cannot be converted
+ */
+HRESULT WINAPI VarDateFromDisp(IDispatch* pdispIn, LCID lcid, DATE* pdateOut)
+{
+ return _VarDateFromDisp(pdispIn, lcid, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromBool (OLEAUT32.96)
+ *
+ * Convert a VT_BOOL to a VT_DATE.
+ *
+ * PARAMS
+ * boolIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE* pdateOut)
+{
+ return _VarDateFromBool(boolIn, pdateOut);
+}
+
+/**********************************************************************
+ * VarDateFromCy (OLEAUT32.93)
+ *
+ * Convert a VT_CY to a VT_DATE.
+ *
+ * PARAMS
+ * lIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromCy(CY cyIn, DATE* pdateOut)
+{
+ return _VarDateFromCy(cyIn, pdateOut);
+}
+
+/* Date string parsing */
+#define DP_TIMESEP 0x01 /* Time seperator ( _must_ remain 0x1, used as a bitmask) */
+#define DP_DATESEP 0x02 /* Date seperator */
+#define DP_MONTH 0x04 /* Month name */
+#define DP_AM 0x08 /* AM */
+#define DP_PM 0x10 /* PM */
+
+typedef struct tagDATEPARSE
+{
+ DWORD dwCount; /* Number of fields found so far (maximum 6) */
+ DWORD dwParseFlags; /* Global parse flags (DP_ Flags above) */
+ DWORD dwFlags[6]; /* Flags for each field */
+ DWORD dwValues[6]; /* Value of each field */
+} DATEPARSE;
+
+#define TIMEFLAG(i) ((dp.dwFlags[i] & DP_TIMESEP) << i)
+
+#define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
+
+/* Determine if a day is valid in a given month of a given year */
+static BOOL VARIANT_IsValidMonthDay(DWORD day, DWORD month, DWORD year)
+{
+ static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ if (day && month && month < 13)
+ {
+ if (day <= days[month] || (month == 2 && day == 29 && IsLeapYear(year)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Possible orders for 3 numbers making up a date */
+#define ORDER_MDY 0x01
+#define ORDER_YMD 0x02
+#define ORDER_YDM 0x04
+#define ORDER_DMY 0x08
+#define ORDER_MYD 0x10 /* Synthetic order, used only for funky 2 digit dates */
+
+/* Determine a date for a particular locale, from 3 numbers */
+static inline HRESULT VARIANT_MakeDate(DATEPARSE *dp, DWORD iDate,
+ DWORD offset, SYSTEMTIME *st)
+{
+ DWORD dwAllOrders, dwTry, dwCount = 0, v1, v2, v3;
+
+ if (!dp->dwCount)
+ {
+ v1 = 30; /* Default to (Variant) 0 date part */
+ v2 = 12;
+ v3 = 1899;
+ goto VARIANT_MakeDate_OK;
+ }
+
+ v1 = dp->dwValues[offset + 0];
+ v2 = dp->dwValues[offset + 1];
+ if (dp->dwCount == 2)
+ {
+ SYSTEMTIME current;
+ GetSystemTime(¤t);
+ v3 = current.wYear;
+ }
+ else
+ v3 = dp->dwValues[offset + 2];
+
+ TRACE("(%ld,%ld,%ld,%ld,%ld)\n", v1, v2, v3, iDate, offset);
+
+ /* If one number must be a month (Because a month name was given), then only
+ * consider orders with the month in that position.
+ * If we took the current year as 'v3', then only allow a year in that position.
+ */
+ if (dp->dwFlags[offset + 0] & DP_MONTH)
+ {
+ dwAllOrders = ORDER_MDY;
+ }
+ else if (dp->dwFlags[offset + 1] & DP_MONTH)
+ {
+ dwAllOrders = ORDER_DMY;
+ if (dp->dwCount > 2)
+ dwAllOrders |= ORDER_YMD;
+ }
+ else if (dp->dwCount > 2 && dp->dwFlags[offset + 2] & DP_MONTH)
+ {
+ dwAllOrders = ORDER_YDM;
+ }
+ else
+ {
+ dwAllOrders = ORDER_MDY|ORDER_DMY;
+ if (dp->dwCount > 2)
+ dwAllOrders |= (ORDER_YMD|ORDER_YDM);
+ }
+
+VARIANT_MakeDate_Start:
+ TRACE("dwAllOrders is 0x%08lx\n", dwAllOrders);
+
+ while (dwAllOrders)
+ {
+ DWORD dwTemp;
+
+ if (dwCount == 0)
+ {
+ /* First: Try the order given by iDate */
+ switch (iDate)
+ {
+ case 0: dwTry = dwAllOrders & ORDER_MDY; break;
+ case 1: dwTry = dwAllOrders & ORDER_DMY; break;
+ default: dwTry = dwAllOrders & ORDER_YMD; break;
+ }
+ }
+ else if (dwCount == 1)
+ {
+ /* Second: Try all the orders compatable with iDate */
+ switch (iDate)
+ {
+ case 0: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
+ case 1: dwTry = dwAllOrders & ~(ORDER_MDY|ORDER_YMD|ORDER_MYD); break;
+ default: dwTry = dwAllOrders & ~(ORDER_DMY|ORDER_YDM); break;
+ }
+ }
+ else
+ {
+ /* Finally: Try any remaining orders */
+ dwTry = dwAllOrders;
+ }
+
+ TRACE("Attempt %ld, dwTry is 0x%08lx\n", dwCount, dwTry);
+
+ dwCount++;
+ if (!dwTry)
+ continue;
+
+#define DATE_SWAP(x,y) do { dwTemp = x; x = y; y = dwTemp; } while (0)
+
+ if (dwTry & ORDER_MDY)
+ {
+ if (VARIANT_IsValidMonthDay(v2,v1,v3))
+ {
+ DATE_SWAP(v1,v2);
+ goto VARIANT_MakeDate_OK;
+ }
+ dwAllOrders &= ~ORDER_MDY;
+ }
+ if (dwTry & ORDER_YMD)
+ {
+ if (VARIANT_IsValidMonthDay(v3,v2,v1))
+ {
+ DATE_SWAP(v1,v3);
+ goto VARIANT_MakeDate_OK;
+ }
+ dwAllOrders &= ~ORDER_YMD;
+ }
+ if (dwTry & ORDER_YDM)
+ {
+ if (VARIANT_IsValidMonthDay(v2,v3,v1))
+ {
+ DATE_SWAP(v1,v2);
+ DATE_SWAP(v2,v3);
+ goto VARIANT_MakeDate_OK;
+ }
+ dwAllOrders &= ~ORDER_YDM;
+ }
+ if (dwTry & ORDER_DMY)
+ {
+ if (VARIANT_IsValidMonthDay(v1,v2,v3))
+ goto VARIANT_MakeDate_OK;
+ dwAllOrders &= ~ORDER_DMY;
+ }
+ if (dwTry & ORDER_MYD)
+ {
+ /* Only occurs if we are trying a 2 year date as M/Y not D/M */
+ if (VARIANT_IsValidMonthDay(v3,v1,v2))
+ {
+ DATE_SWAP(v1,v3);
+ DATE_SWAP(v2,v3);
+ goto VARIANT_MakeDate_OK;
+ }
+ dwAllOrders &= ~ORDER_MYD;
+ }
+ }
+
+ if (dp->dwCount == 2)
+ {
+ /* We couldn't make a date as D/M or M/D, so try M/Y or Y/M */
+ v3 = 1; /* 1st of the month */
+ dwAllOrders = ORDER_YMD|ORDER_MYD;
+ dp->dwCount = 0; /* Don't return to this code path again */
+ dwCount = 0;
+ goto VARIANT_MakeDate_Start;
+ }
+
+ /* No valid dates were able to be constructed */
+ return DISP_E_TYPEMISMATCH;
+
+VARIANT_MakeDate_OK:
+
+ /* Check that the time part is ok */
+ if (st->wHour > 23 || st->wMinute > 59 || st->wSecond > 59)
+ return DISP_E_TYPEMISMATCH;
+
+ TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
+ if (st->wHour < 12 && (dp->dwParseFlags & DP_PM))
+ st->wHour += 12;
+ else if (st->wHour == 12 && (dp->dwParseFlags & DP_AM))
+ st->wHour = 0;
+ TRACE("Time %d %d %d\n", st->wHour, st->wMinute, st->wSecond);
+
+ st->wDay = v1;
+ st->wMonth = v2;
+ /* FIXME: For 2 digit dates, I'm not sure if 30 is hard coded or not. It may
+ * be retrieved from:
+ * HKCU\Control Panel\International\Calendars\TwoDigitYearMax
+ * But Wine doesn't have/use that key as at the time of writing.
+ */
+ st->wYear = v3 < 30 ? 2000 + v3 : v3 < 100 ? 1900 + v3 : v3;
+ TRACE("Returning date %ld/%ld/%d\n", v1, v2, st->wYear);
+ return S_OK;
+}
+
+/******************************************************************************
+ * VarDateFromStr [OLEAUT32.94]
+ *
+ * Convert a VT_BSTR to at VT_DATE.
+ *
+ * PARAMS
+ * strIn [I] String to convert
+ * lcid [I] Locale identifier for the conversion
+ * dwFlags [I] Flags affecting the conversion (VAR_ flags from "oleauto.h")
+ * pdateOut [O] Destination for the converted value
+ *
+ * RETURNS
+ * Success: S_OK. pdateOut contains the converted value.
+ * FAILURE: An HRESULT error code indicating the prolem.
+ *
+ * NOTES
+ * Any date format that can be created using the date formats from lcid
+ * (Either from kernel Nls functions, variant conversion or formatting) is a
+ * valid input to this function. In addition, a few more esoteric formats are
+ * also supported for compatability with the native version. The date is
+ * interpreted according to the date settings in the control panel, unless
+ * the date is invalid in that format, in which the most compatable format
+ * that produces a valid date will be used.
+ */
+HRESULT WINAPI VarDateFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DATE* pdateOut)
+{
+ static const USHORT ParseDateTokens[] =
+ {
+ LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
+ LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
+ LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
+ LOCALE_SMONTHNAME13,
+ LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
+ LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
+ LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
+ LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
+ LOCALE_SABBREVMONTHNAME13,
+ LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
+ LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
+ LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
+ LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
+ LOCALE_SABBREVDAYNAME7,
+ LOCALE_S1159, LOCALE_S2359
+ };
+ static const BYTE ParseDateMonths[] =
+ {
+ 1,2,3,4,5,6,7,8,9,10,11,12,13,
+ 1,2,3,4,5,6,7,8,9,10,11,12,13
+ };
+ size_t i;
+ BSTR tokens[sizeof(ParseDateTokens)/sizeof(ParseDateTokens[0])];
+ DATEPARSE dp;
+ DWORD dwDateSeps = 0, iDate = 0;
+ HRESULT hRet = S_OK;
+
+ if ((dwFlags & (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY)) ==
+ (VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY))
+ return E_INVALIDARG;
+
+ if (!strIn)
+ return DISP_E_TYPEMISMATCH;
+
+ *pdateOut = 0.0;
+
+ TRACE("(%s,0x%08lx,0x%08lx,%p)\n", debugstr_w(strIn), lcid, dwFlags, pdateOut);
+
+ memset(&dp, 0, sizeof(dp));
+
+ GetLocaleInfoW(lcid, LOCALE_IDATE|LOCALE_RETURN_NUMBER|(dwFlags & LOCALE_NOUSEROVERRIDE),
+ (LPWSTR)&iDate, sizeof(iDate)/sizeof(WCHAR));
+ TRACE("iDate is %ld\n", iDate);
+
+ /* Get the month/day/am/pm tokens for this locale */
+ for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
+ {
+ WCHAR buff[128];
+ LCTYPE lctype = ParseDateTokens[i] | (dwFlags & LOCALE_NOUSEROVERRIDE);
+
+ /* FIXME: Alternate calendars - should use GetCalendarInfo() and/or
+ * GetAltMonthNames(). We should really cache these strings too.
+ */
+ buff[0] = '\0';
+ GetLocaleInfoW(lcid, lctype, buff, sizeof(buff)/sizeof(WCHAR));
+ tokens[i] = SysAllocString(buff);
+ TRACE("token %d is %s\n", i, debugstr_w(tokens[i]));
+ }
+
+ /* Parse the string into our structure */
+ while (*strIn)
+ {
+ if (dp.dwCount > 6)
+ break;
+
+ if (isdigitW(*strIn))
+ {
+ dp.dwValues[dp.dwCount] = strtoulW(strIn, &strIn, 10);
+ dp.dwCount++;
+ strIn--;
+ }
+ else if (isalpha(*strIn))
+ {
+ BOOL bFound = FALSE;
+
+ for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
+ {
+ DWORD dwLen = strlenW(tokens[i]);
+ if (dwLen && !strncmpiW(strIn, tokens[i], dwLen))
+ {
+ if (i <= 25)
+ {
+ dp.dwValues[dp.dwCount] = ParseDateMonths[i];
+ dp.dwFlags[dp.dwCount] |= (DP_MONTH|DP_DATESEP);
+ dp.dwCount++;
+ }
+ else if (i > 39)
+ {
+ if (!dp.dwCount || dp.dwParseFlags & (DP_AM|DP_PM))
+ hRet = DISP_E_TYPEMISMATCH;
+ else
+ {
+ dp.dwFlags[dp.dwCount - 1] |= (i == 40 ? DP_AM : DP_PM);
+ dp.dwParseFlags |= (i == 40 ? DP_AM : DP_PM);
+ }
+ }
+ strIn += (dwLen - 1);
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ if ((*strIn == 'a' || *strIn == 'A' || *strIn == 'p' || *strIn == 'P') &&
+ (dp.dwCount && !(dp.dwParseFlags & (DP_AM|DP_PM))))
+ {
+ /* Special case - 'a' and 'p' are recognised as short for am/pm */
+ if (*strIn == 'a' || *strIn == 'A')
+ {
+ dp.dwFlags[dp.dwCount - 1] |= DP_AM;
+ dp.dwParseFlags |= DP_AM;
+ }
+ else
+ {
+ dp.dwFlags[dp.dwCount - 1] |= DP_PM;
+ dp.dwParseFlags |= DP_PM;
+ }
+ strIn++;
+ }
+ else
+ {
+ TRACE("No matching token for %s\n", debugstr_w(strIn));
+ hRet = DISP_E_TYPEMISMATCH;
+ break;
+ }
+ }
+ }
+ else if (*strIn == ':' || *strIn == '.')
+ {
+ if (!dp.dwCount || !strIn[1])
+ hRet = DISP_E_TYPEMISMATCH;
+ else
+ dp.dwFlags[dp.dwCount - 1] |= DP_TIMESEP;
+ }
+ else if (*strIn == '-' || *strIn == '/')
+ {
+ dwDateSeps++;
+ if (dwDateSeps > 2 || !dp.dwCount || !strIn[1])
+ hRet = DISP_E_TYPEMISMATCH;
+ else
+ dp.dwFlags[dp.dwCount - 1] |= DP_DATESEP;
+ }
+ else if (*strIn == ',' || isspaceW(*strIn))
+ {
+ if (*strIn == ',' && !strIn[1])
+ hRet = DISP_E_TYPEMISMATCH;
+ }
+ else
+ {
+ hRet = DISP_E_TYPEMISMATCH;
+ }
+ strIn++;
+ }
+
+ if (!dp.dwCount || dp.dwCount > 6 ||
+ (dp.dwCount == 1 && !(dp.dwParseFlags & (DP_AM|DP_PM))))
+ hRet = DISP_E_TYPEMISMATCH;
+
+ if (SUCCEEDED(hRet))
+ {
+ SYSTEMTIME st;
+ DWORD dwOffset = 0; /* Start of date fields in dp.dwValues */
+
+ st.wDayOfWeek = st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
+
+ /* Figure out which numbers correspond to which fields.
+ *
+ * This switch statement works based on the fact that native interprets any
+ * fields that are not joined with a time seperator ('.' or ':') as date
+ * fields. Thus we construct a value from 0-32 where each set bit indicates
+ * a time field. This encapsulates the hundreds of permutations of 2-6 fields.
+ * For valid permutations, we set dwOffset to point to the first date field
+ * and shorten dp.dwCount by the number of time fields found. The real
+ * magic here occurs in VARIANT_MakeDate() above, where we determine what
+ * each date number must represent in the context of iDate.
+ */
+ TRACE("0x%08lx\n", TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4));
+
+ switch (TIMEFLAG(0)|TIMEFLAG(1)|TIMEFLAG(2)|TIMEFLAG(3)|TIMEFLAG(4))
+ {
+ case 0x1: /* TT TTDD TTDDD */
+ if (dp.dwCount > 3 &&
+ ((dp.dwFlags[2] & (DP_AM|DP_PM)) || (dp.dwFlags[3] & (DP_AM|DP_PM)) ||
+ (dp.dwFlags[4] & (DP_AM|DP_PM))))
+ hRet = DISP_E_TYPEMISMATCH;
+ else if (dp.dwCount != 2 && dp.dwCount != 4 && dp.dwCount != 5)
+ hRet = DISP_E_TYPEMISMATCH;
+ st.wHour = dp.dwValues[0];
+ st.wMinute = dp.dwValues[1];
+ dp.dwCount -= 2;
+ dwOffset = 2;
+ break;
+
+ case 0x3: /* TTT TTTDD TTTDDD */
+ if (dp.dwCount > 4 &&
+ ((dp.dwFlags[3] & (DP_AM|DP_PM)) || (dp.dwFlags[4] & (DP_AM|DP_PM)) ||
+ (dp.dwFlags[5] & (DP_AM|DP_PM))))
+ hRet = DISP_E_TYPEMISMATCH;
+ else if (dp.dwCount != 3 && dp.dwCount != 5 && dp.dwCount != 6)
+ hRet = DISP_E_TYPEMISMATCH;
+ st.wHour = dp.dwValues[0];
+ st.wMinute = dp.dwValues[1];
+ st.wSecond = dp.dwValues[2];
+ dwOffset = 3;
+ dp.dwCount -= 3;
+ break;
+
+ case 0x4: /* DDTT */
+ if (dp.dwCount != 4 ||
+ (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
+ hRet = DISP_E_TYPEMISMATCH;
+
+ st.wHour = dp.dwValues[2];
+ st.wMinute = dp.dwValues[3];
+ dp.dwCount -= 2;
+ break;
+
+ case 0x0: /* T DD DDD TDDD TDDD */
+ if (dp.dwCount == 1 && (dp.dwParseFlags & (DP_AM|DP_PM)))
+ {
+ st.wHour = dp.dwValues[0]; /* T */
+ dp.dwCount = 0;
+ break;
+ }
+ else if (dp.dwCount > 4 || (dp.dwCount < 3 && dp.dwParseFlags & (DP_AM|DP_PM)))
+ {
+ hRet = DISP_E_TYPEMISMATCH;
+ }
+ else if (dp.dwCount == 3)
+ {
+ if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDD */
+ {
+ dp.dwCount = 2;
+ st.wHour = dp.dwValues[0];
+ dwOffset = 1;
+ break;
+ }
+ if (dp.dwFlags[2] & (DP_AM|DP_PM)) /* DDT */
+ {
+ dp.dwCount = 2;
+ st.wHour = dp.dwValues[2];
+ break;
+ }
+ else if (dp.dwParseFlags & (DP_AM|DP_PM))
+ hRet = DISP_E_TYPEMISMATCH;
+ }
+ else if (dp.dwCount == 4)
+ {
+ dp.dwCount = 3;
+ if (dp.dwFlags[0] & (DP_AM|DP_PM)) /* TDDD */
+ {
+ st.wHour = dp.dwValues[0];
+ dwOffset = 1;
+ }
+ else if (dp.dwFlags[3] & (DP_AM|DP_PM)) /* DDDT */
+ {
+ st.wHour = dp.dwValues[3];
+ }
+ else
+ hRet = DISP_E_TYPEMISMATCH;
+ break;
+ }
+ /* .. fall through .. */
+
+ case 0x8: /* DDDTT */
+ if ((dp.dwCount == 2 && (dp.dwParseFlags & (DP_AM|DP_PM))) ||
+ (dp.dwCount == 5 && ((dp.dwFlags[0] & (DP_AM|DP_PM)) ||
+ (dp.dwFlags[1] & (DP_AM|DP_PM)) || (dp.dwFlags[2] & (DP_AM|DP_PM)))) ||
+ dp.dwCount == 4 || dp.dwCount == 6)
+ hRet = DISP_E_TYPEMISMATCH;
+ st.wHour = dp.dwValues[3];
+ st.wMinute = dp.dwValues[4];
+ if (dp.dwCount == 5)
+ dp.dwCount -= 2;
+ break;
+
+ case 0xC: /* DDTTT */
+ if (dp.dwCount != 5 ||
+ (dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)))
+ hRet = DISP_E_TYPEMISMATCH;
+ st.wHour = dp.dwValues[2];
+ st.wMinute = dp.dwValues[3];
+ st.wSecond = dp.dwValues[4];
+ dp.dwCount -= 3;
+ break;
+
+ case 0x18: /* DDDTTT */
+ if ((dp.dwFlags[0] & (DP_AM|DP_PM)) || (dp.dwFlags[1] & (DP_AM|DP_PM)) ||
+ (dp.dwFlags[2] & (DP_AM|DP_PM)))
+ hRet = DISP_E_TYPEMISMATCH;
+ st.wHour = dp.dwValues[3];
+ st.wMinute = dp.dwValues[4];
+ st.wSecond = dp.dwValues[5];
+ dp.dwCount -= 3;
+ break;
+
+ default:
+ hRet = DISP_E_TYPEMISMATCH;
+ break;
+ }
+
+ if (SUCCEEDED(hRet))
+ {
+ hRet = VARIANT_MakeDate(&dp, iDate, dwOffset, &st);
+
+ if (dwFlags & VAR_TIMEVALUEONLY)
+ {
+ st.wYear = 1899;
+ st.wMonth = 12;
+ st.wDay = 30;
+ }
+ else if (dwFlags & VAR_DATEVALUEONLY)
+ st.wHour = st.wMinute = st.wSecond = 0;
+
+ /* Finally, convert the value to a VT_DATE */
+ if (SUCCEEDED(hRet))
+ hRet = SystemTimeToVariantTime(&st, pdateOut) ? S_OK : DISP_E_TYPEMISMATCH;
+ }
+ }
+
+ for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++)
+ SysFreeString(tokens[i]);
+ return hRet;
+}
+
+/******************************************************************************
+ * VarDateFromI1 (OLEAUT32.221)
+ *
+ * Convert a VT_I1 to a VT_DATE.
+ *
+ * PARAMS
+ * cIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromI1(signed char cIn, DATE* pdateOut)
+{
+ return _VarDateFromI1(cIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromUI2 (OLEAUT32.222)
+ *
+ * Convert a VT_UI2 to a VT_DATE.
+ *
+ * PARAMS
+ * uiIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromUI2(USHORT uiIn, DATE* pdateOut)
+{
+ return _VarDateFromUI2(uiIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromUI4 (OLEAUT32.223)
+ *
+ * Convert a VT_UI4 to a VT_DATE.
+ *
+ * PARAMS
+ * ulIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromUI4(ULONG ulIn, DATE* pdateOut)
+{
+ return _VarDateFromUI4(ulIn, pdateOut);
+}
+
+/**********************************************************************
+ * VarDateFromDec (OLEAUT32.224)
+ *
+ * Convert a VT_DECIMAL to a VT_DATE.
+ *
+ * PARAMS
+ * pdecIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * S_OK.
+ */
+HRESULT WINAPI VarDateFromDec(DECIMAL *pdecIn, DATE* pdateOut)
+{
+ return _VarDateFromDec(pdecIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromI8 (OLEAUT32.364)
+ *
+ * Convert a VT_I8 to a VT_DATE.
+ *
+ * PARAMS
+ * llIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDateFromI8(LONG64 llIn, DATE* pdateOut)
+{
+ return _VarDateFromI8(llIn, pdateOut);
+}
+
+/******************************************************************************
+ * VarDateFromUI8 (OLEAUT32.365)
+ *
+ * Convert a VT_UI8 to a VT_DATE.
+ *
+ * PARAMS
+ * ullIn [I] Source
+ * pdateOut [O] Destination
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
+ */
+HRESULT WINAPI VarDateFromUI8(ULONG64 ullIn, DATE* pdateOut)
+{
+ return _VarDateFromUI8(ullIn, pdateOut);
+}