Started implementing support for the SubSystemTib field in the TEB of
[wine] / dlls / oleaut32 / variant.c
1 /*
2  * VARIANT
3  *
4  * Copyright 1998 Jean-Claude Cote
5  * Copyright 2003 Jon Griffiths
6  * The alorithm for conversion from Julian days to day/month/year is based on
7  * that devised by Henry Fliegel, as implemented in PostgreSQL, which is
8  * Copyright 1994-7 Regents of the University of California
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33 #include "windef.h"
34 #include "winbase.h"
35 #include "oleauto.h"
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
38 #include "winerror.h"
39 #include "variant.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(ole);
42
43 const char* wine_vtypes[VT_CLSID] =
44 {
45   "VT_EMPTY","VT_NULL","VT_I2","VT_I4","VT_R4","VT_R8","VT_CY","VT_DATE",
46   "VT_BSTR","VT_DISPATCH","VT_ERROR","VT_BOOL","VT_VARIANT","VT_UNKNOWN",
47   "VT_DECIMAL","15","VT_I1","VT_UI1","VT_UI2","VT_UI4","VT_I8","VT_UI8",
48   "VT_INT","VT_UINT","VT_VOID","VT_HRESULT","VT_PTR","VT_SAFEARRAY",
49   "VT_CARRAY","VT_USERDEFINED","VT_LPSTR","VT_LPWSTR""32","33","34","35",
50   "VT_RECORD","VT_INT_PTR","VT_UINT_PTR","39","40","41","42","43","44","45",
51   "46","47","48","49","50","51","52","53","54","55","56","57","58","59","60",
52   "61","62","63","VT_FILETIME","VT_BLOB","VT_STREAM","VT_STORAGE",
53   "VT_STREAMED_OBJECT","VT_STORED_OBJECT","VT_BLOB_OBJECT","VT_CF","VT_CLSID"
54 };
55
56 const char* wine_vflags[16] =
57 {
58  "",
59  "|VT_VECTOR",
60  "|VT_ARRAY",
61  "|VT_VECTOR|VT_ARRAY",
62  "|VT_BYREF",
63  "|VT_VECTOR|VT_ARRAY",
64  "|VT_ARRAY|VT_BYREF",
65  "|VT_VECTOR|VT_ARRAY|VT_BYREF",
66  "|VT_HARDTYPE",
67  "|VT_VECTOR|VT_HARDTYPE",
68  "|VT_ARRAY|VT_HARDTYPE",
69  "|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
70  "|VT_BYREF|VT_HARDTYPE",
71  "|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
72  "|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
73  "|VT_VECTOR|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
74 };
75
76 /* Convert a variant from one type to another */
77 static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
78                                      VARIANTARG* ps, VARTYPE vt)
79 {
80   HRESULT res = DISP_E_TYPEMISMATCH;
81   VARTYPE vtFrom =  V_TYPE(ps);
82   DWORD dwFlags = 0;
83
84   TRACE("(%p->(%s%s),0x%08lx,0x%04x,%p->(%s%s),%s%s)\n", pd, debugstr_VT(pd),
85         debugstr_VF(pd), lcid, wFlags, ps, debugstr_VT(ps), debugstr_VF(ps),
86         debugstr_vt(vt), debugstr_vf(vt));
87
88   if (vt == VT_BSTR || vtFrom == VT_BSTR)
89   {
90     /* All flags passed to low level function are only used for
91      * changing to or from strings. Map these here.
92      */
93     if (wFlags & VARIANT_LOCALBOOL)
94       dwFlags |= VAR_LOCALBOOL;
95     if (wFlags & VARIANT_CALENDAR_HIJRI)
96       dwFlags |= VAR_CALENDAR_HIJRI;
97     if (wFlags & VARIANT_CALENDAR_THAI)
98       dwFlags |= VAR_CALENDAR_THAI;
99     if (wFlags & VARIANT_CALENDAR_GREGORIAN)
100       dwFlags |= VAR_CALENDAR_GREGORIAN;
101     if (wFlags & VARIANT_NOUSEROVERRIDE)
102       dwFlags |= LOCALE_NOUSEROVERRIDE;
103     if (wFlags & VARIANT_USE_NLS)
104       dwFlags |= LOCALE_USE_NLS;
105   }
106
107   /* Map int/uint to i4/ui4 */
108   if (vt == VT_INT)
109     vt = VT_I4;
110   else if (vt == VT_UINT)
111     vt = VT_UI4;
112
113   if (vtFrom == VT_INT)
114     vtFrom = VT_I4;
115   else if (vtFrom == VT_UINT)
116      vtFrom = VT_UI4;
117
118   if (vt == vtFrom)
119      return VariantCopy(pd, ps);
120
121   if (wFlags & VARIANT_NOVALUEPROP && vtFrom == VT_DISPATCH && vt != VT_UNKNOWN)
122   {
123     /* VARIANT_NOVALUEPROP prevents IDispatch objects from being coerced by
124      * accessing the default object property.
125      */
126     return DISP_E_TYPEMISMATCH;
127   }
128
129   switch (vt)
130   {
131   case VT_EMPTY:
132     if (vtFrom == VT_NULL)
133       return DISP_E_TYPEMISMATCH;
134     /* ... Fall through */
135   case VT_NULL:
136     if (vtFrom <= VT_UINT && vtFrom != (VARTYPE)15 && vtFrom != VT_ERROR)
137     {
138       res = VariantClear( pd );
139       if (vt == VT_NULL && SUCCEEDED(res))
140         V_VT(pd) = VT_NULL;
141     }
142     return res;
143
144   case VT_I1:
145     switch (vtFrom)
146     {
147     case VT_EMPTY:    V_I1(pd) = 0; return S_OK;
148     case VT_I2:       return VarI1FromI2(V_I2(ps), &V_I1(pd));
149     case VT_I4:       return VarI1FromI4(V_I4(ps), &V_I1(pd));
150     case VT_UI1:      return VarI1FromUI1(V_UI1(ps), &V_I1(pd));
151     case VT_UI2:      return VarI1FromUI2(V_UI2(ps), &V_I1(pd));
152     case VT_UI4:      return VarI1FromUI4(V_UI4(ps), &V_I1(pd));
153     case VT_I8:       return VarI1FromI8(V_I8(ps), &V_I1(pd));
154     case VT_UI8:      return VarI1FromUI8(V_UI8(ps), &V_I1(pd));
155     case VT_R4:       return VarI1FromR4(V_R4(ps), &V_I1(pd));
156     case VT_R8:       return VarI1FromR8(V_R8(ps), &V_I1(pd));
157     case VT_DATE:     return VarI1FromDate(V_DATE(ps), &V_I1(pd));
158     case VT_BOOL:     return VarI1FromBool(V_BOOL(ps), &V_I1(pd));
159     case VT_CY:       return VarI1FromCy(V_CY(ps), &V_I1(pd));
160     case VT_DECIMAL:  return VarI1FromDec(&V_DECIMAL(ps), &V_I1(pd) );
161     case VT_DISPATCH: return VarI1FromDisp(V_DISPATCH(ps), lcid, &V_I1(pd) );
162     case VT_BSTR:     return VarI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_I1(pd) );
163     }
164     break;
165
166   case VT_I2:
167     switch (vtFrom)
168     {
169     case VT_EMPTY:    V_I2(pd) = 0; return S_OK;
170     case VT_I1:       return VarI2FromI1(V_I1(ps), &V_I2(pd));
171     case VT_I4:       return VarI2FromI4(V_I4(ps), &V_I2(pd));
172     case VT_UI1:      return VarI2FromUI1(V_UI1(ps), &V_I2(pd));
173     case VT_UI2:      return VarI2FromUI2(V_UI2(ps), &V_I2(pd));
174     case VT_UI4:      return VarI2FromUI4(V_UI4(ps), &V_I2(pd));
175     case VT_I8:       return VarI2FromI8(V_I8(ps), &V_I2(pd));
176     case VT_UI8:      return VarI2FromUI8(V_UI8(ps), &V_I2(pd));
177     case VT_R4:       return VarI2FromR4(V_R4(ps), &V_I2(pd));
178     case VT_R8:       return VarI2FromR8(V_R8(ps), &V_I2(pd));
179     case VT_DATE:     return VarI2FromDate(V_DATE(ps), &V_I2(pd));
180     case VT_BOOL:     return VarI2FromBool(V_BOOL(ps), &V_I2(pd));
181     case VT_CY:       return VarI2FromCy(V_CY(ps), &V_I2(pd));
182     case VT_DECIMAL:  return VarI2FromDec(&V_DECIMAL(ps), &V_I2(pd));
183     case VT_DISPATCH: return VarI2FromDisp(V_DISPATCH(ps), lcid, &V_I2(pd));
184     case VT_BSTR:     return VarI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_I2(pd));
185     }
186     break;
187
188   case VT_I4:
189     switch (vtFrom)
190     {
191     case VT_EMPTY:    V_I4(pd) = 0; return S_OK;
192     case VT_I1:       return VarI4FromI1(V_I1(ps), &V_I4(pd));
193     case VT_I2:       return VarI4FromI2(V_I2(ps), &V_I4(pd));
194     case VT_UI1:      return VarI4FromUI1(V_UI1(ps), &V_I4(pd));
195     case VT_UI2:      return VarI4FromUI2(V_UI2(ps), &V_I4(pd));
196     case VT_UI4:      return VarI4FromUI4(V_UI4(ps), &V_I4(pd));
197     case VT_I8:       return VarI4FromI8(V_I8(ps), &V_I4(pd));
198     case VT_UI8:      return VarI4FromUI8(V_UI8(ps), &V_I4(pd));
199     case VT_R4:       return VarI4FromR4(V_R4(ps), &V_I4(pd));
200     case VT_R8:       return VarI4FromR8(V_R8(ps), &V_I4(pd));
201     case VT_DATE:     return VarI4FromDate(V_DATE(ps), &V_I4(pd));
202     case VT_BOOL:     return VarI4FromBool(V_BOOL(ps), &V_I4(pd));
203     case VT_CY:       return VarI4FromCy(V_CY(ps), &V_I4(pd));
204     case VT_DECIMAL:  return VarI4FromDec(&V_DECIMAL(ps), &V_I4(pd));
205     case VT_DISPATCH: return VarI4FromDisp(V_DISPATCH(ps), lcid, &V_I4(pd));
206     case VT_BSTR:     return VarI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_I4(pd));
207     }
208     break;
209
210   case VT_UI1:
211     switch (vtFrom)
212     {
213     case VT_EMPTY:    V_UI1(pd) = 0; return S_OK;
214     case VT_I1:       return VarUI1FromI1(V_I1(ps), &V_UI1(pd));
215     case VT_I2:       return VarUI1FromI2(V_I2(ps), &V_UI1(pd));
216     case VT_I4:       return VarUI1FromI4(V_I4(ps), &V_UI1(pd));
217     case VT_UI2:      return VarUI1FromUI2(V_UI2(ps), &V_UI1(pd));
218     case VT_UI4:      return VarUI1FromUI4(V_UI4(ps), &V_UI1(pd));
219     case VT_I8:       return VarUI1FromI8(V_I8(ps), &V_UI1(pd));
220     case VT_UI8:      return VarUI1FromUI8(V_UI8(ps), &V_UI1(pd));
221     case VT_R4:       return VarUI1FromR4(V_R4(ps), &V_UI1(pd));
222     case VT_R8:       return VarUI1FromR8(V_R8(ps), &V_UI1(pd));
223     case VT_DATE:     return VarUI1FromDate(V_DATE(ps), &V_UI1(pd));
224     case VT_BOOL:     return VarUI1FromBool(V_BOOL(ps), &V_UI1(pd));
225     case VT_CY:       return VarUI1FromCy(V_CY(ps), &V_UI1(pd));
226     case VT_DECIMAL:  return VarUI1FromDec(&V_DECIMAL(ps), &V_UI1(pd));
227     case VT_DISPATCH: return VarUI1FromDisp(V_DISPATCH(ps), lcid, &V_UI1(pd));
228     case VT_BSTR:     return VarUI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI1(pd));
229     }
230     break;
231
232   case VT_UI2:
233     switch (vtFrom)
234     {
235     case VT_EMPTY:    V_UI2(pd) = 0; return S_OK;
236     case VT_I1:       return VarUI2FromI1(V_I1(ps), &V_UI2(pd));
237     case VT_I2:       return VarUI2FromI2(V_I2(ps), &V_UI2(pd));
238     case VT_I4:       return VarUI2FromI4(V_I4(ps), &V_UI2(pd));
239     case VT_UI1:      return VarUI2FromUI1(V_UI1(ps), &V_UI2(pd));
240     case VT_UI4:      return VarUI2FromUI4(V_UI4(ps), &V_UI2(pd));
241     case VT_I8:       return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
242     case VT_UI8:      return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
243     case VT_R4:       return VarUI2FromR4(V_R4(ps), &V_UI2(pd));
244     case VT_R8:       return VarUI2FromR8(V_R8(ps), &V_UI2(pd));
245     case VT_DATE:     return VarUI2FromDate(V_DATE(ps), &V_UI2(pd));
246     case VT_BOOL:     return VarUI2FromBool(V_BOOL(ps), &V_UI2(pd));
247     case VT_CY:       return VarUI2FromCy(V_CY(ps), &V_UI2(pd));
248     case VT_DECIMAL:  return VarUI2FromDec(&V_DECIMAL(ps), &V_UI2(pd));
249     case VT_DISPATCH: return VarUI2FromDisp(V_DISPATCH(ps), lcid, &V_UI2(pd));
250     case VT_BSTR:     return VarUI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI2(pd));
251     }
252     break;
253
254   case VT_UI4:
255     switch (vtFrom)
256     {
257     case VT_EMPTY:    V_UI4(pd) = 0; return S_OK;
258     case VT_I1:       return VarUI4FromI1(V_I1(ps), &V_UI4(pd));
259     case VT_I2:       return VarUI4FromI2(V_I2(ps), &V_UI4(pd));
260     case VT_I4:       return VarUI4FromI4(V_I4(ps), &V_UI4(pd));
261     case VT_UI1:      return VarUI4FromUI1(V_UI1(ps), &V_UI4(pd));
262     case VT_UI2:      return VarUI4FromUI2(V_UI2(ps), &V_UI4(pd));
263     case VT_I8:       return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
264     case VT_UI8:      return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
265     case VT_R4:       return VarUI4FromR4(V_R4(ps), &V_UI4(pd));
266     case VT_R8:       return VarUI4FromR8(V_R8(ps), &V_UI4(pd));
267     case VT_DATE:     return VarUI4FromDate(V_DATE(ps), &V_UI4(pd));
268     case VT_BOOL:     return VarUI4FromBool(V_BOOL(ps), &V_UI4(pd));
269     case VT_CY:       return VarUI4FromCy(V_CY(ps), &V_UI4(pd));
270     case VT_DECIMAL:  return VarUI4FromDec(&V_DECIMAL(ps), &V_UI4(pd));
271     case VT_DISPATCH: return VarUI4FromDisp(V_DISPATCH(ps), lcid, &V_UI4(pd));
272     case VT_BSTR:     return VarUI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI4(pd));
273     }
274     break;
275
276   case VT_UI8:
277     switch (vtFrom)
278     {
279     case VT_EMPTY:    V_UI8(pd) = 0; return S_OK;
280     case VT_I4:       if (V_I4(ps) < 0) return DISP_E_OVERFLOW; V_UI8(pd) = V_I4(ps); return S_OK;
281     case VT_I1:       return VarUI8FromI1(V_I1(ps), &V_UI8(pd));
282     case VT_I2:       return VarUI8FromI2(V_I2(ps), &V_UI8(pd));
283     case VT_UI1:      return VarUI8FromUI1(V_UI1(ps), &V_UI8(pd));
284     case VT_UI2:      return VarUI8FromUI2(V_UI2(ps), &V_UI8(pd));
285     case VT_UI4:      return VarUI8FromUI4(V_UI4(ps), &V_UI8(pd));
286     case VT_I8:       return VarUI8FromI8(V_I8(ps), &V_UI8(pd));
287     case VT_R4:       return VarUI8FromR4(V_R4(ps), &V_UI8(pd));
288     case VT_R8:       return VarUI8FromR8(V_R8(ps), &V_UI8(pd));
289     case VT_DATE:     return VarUI8FromDate(V_DATE(ps), &V_UI8(pd));
290     case VT_BOOL:     return VarUI8FromBool(V_BOOL(ps), &V_UI8(pd));
291     case VT_CY:       return VarUI8FromCy(V_CY(ps), &V_UI8(pd));
292     case VT_DECIMAL:  return VarUI8FromDec(&V_DECIMAL(ps), &V_UI8(pd));
293     case VT_DISPATCH: return VarUI8FromDisp(V_DISPATCH(ps), lcid, &V_UI8(pd));
294     case VT_BSTR:     return VarUI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI8(pd));
295     }
296     break;
297
298   case VT_I8:
299     switch (vtFrom)
300     {
301     case VT_EMPTY:    V_I8(pd) = 0; return S_OK;
302     case VT_I4:       V_I8(pd) = V_I4(ps); return S_OK;
303     case VT_I1:       return VarI8FromI1(V_I1(ps), &V_I8(pd));
304     case VT_I2:       return VarI8FromI2(V_I2(ps), &V_I8(pd));
305     case VT_UI1:      return VarI8FromUI1(V_UI1(ps), &V_I8(pd));
306     case VT_UI2:      return VarI8FromUI2(V_UI2(ps), &V_I8(pd));
307     case VT_UI4:      return VarI8FromUI4(V_UI4(ps), &V_I8(pd));
308     case VT_UI8:      return VarI8FromUI8(V_I8(ps), &V_I8(pd));
309     case VT_R4:       return VarI8FromR4(V_R4(ps), &V_I8(pd));
310     case VT_R8:       return VarI8FromR8(V_R8(ps), &V_I8(pd));
311     case VT_DATE:     return VarI8FromDate(V_DATE(ps), &V_I8(pd));
312     case VT_BOOL:     return VarI8FromBool(V_BOOL(ps), &V_I8(pd));
313     case VT_CY:       return VarI8FromCy(V_CY(ps), &V_I8(pd));
314     case VT_DECIMAL:  return VarI8FromDec(&V_DECIMAL(ps), &V_I8(pd));
315     case VT_DISPATCH: return VarI8FromDisp(V_DISPATCH(ps), lcid, &V_I8(pd));
316     case VT_BSTR:     return VarI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_I8(pd));
317     }
318     break;
319
320   case VT_R4:
321     switch (vtFrom)
322     {
323     case VT_EMPTY:    V_R4(pd) = 0.0f; return S_OK;
324     case VT_I1:       return VarR4FromI1(V_I1(ps), &V_R4(pd));
325     case VT_I2:       return VarR4FromI2(V_I2(ps), &V_R4(pd));
326     case VT_I4:       return VarR4FromI4(V_I4(ps), &V_R4(pd));
327     case VT_UI1:      return VarR4FromUI1(V_UI1(ps), &V_R4(pd));
328     case VT_UI2:      return VarR4FromUI2(V_UI2(ps), &V_R4(pd));
329     case VT_UI4:      return VarR4FromUI4(V_UI4(ps), &V_R4(pd));
330     case VT_I8:       return VarR4FromI8(V_I8(ps), &V_R4(pd));
331     case VT_UI8:      return VarR4FromUI8(V_UI8(ps), &V_R4(pd));
332     case VT_R8:       return VarR4FromR8(V_R8(ps), &V_R4(pd));
333     case VT_DATE:     return VarR4FromDate(V_DATE(ps), &V_R4(pd));
334     case VT_BOOL:     return VarR4FromBool(V_BOOL(ps), &V_R4(pd));
335     case VT_CY:       return VarR4FromCy(V_CY(ps), &V_R4(pd));
336     case VT_DECIMAL:  return VarR4FromDec(&V_DECIMAL(ps), &V_R4(pd));
337     case VT_DISPATCH: return VarR4FromDisp(V_DISPATCH(ps), lcid, &V_R4(pd));
338     case VT_BSTR:     return VarR4FromStr(V_BSTR(ps), lcid, dwFlags, &V_R4(pd));
339     }
340     break;
341
342   case VT_R8:
343     switch (vtFrom)
344     {
345     case VT_EMPTY:    V_R8(pd) = 0.0; return S_OK;
346     case VT_I1:       return VarR8FromI1(V_I1(ps), &V_R8(pd));
347     case VT_I2:       return VarR8FromI2(V_I2(ps), &V_R8(pd));
348     case VT_I4:       return VarR8FromI4(V_I4(ps), &V_R8(pd));
349     case VT_UI1:      return VarR8FromUI1(V_UI1(ps), &V_R8(pd));
350     case VT_UI2:      return VarR8FromUI2(V_UI2(ps), &V_R8(pd));
351     case VT_UI4:      return VarR8FromUI4(V_UI4(ps), &V_R8(pd));
352     case VT_I8:       return VarR8FromI8(V_I8(ps), &V_R8(pd));
353     case VT_UI8:      return VarR8FromUI8(V_UI8(ps), &V_R8(pd));
354     case VT_R4:       return VarR8FromR4(V_R4(ps), &V_R8(pd));
355     case VT_DATE:     return VarR8FromDate(V_DATE(ps), &V_R8(pd));
356     case VT_BOOL:     return VarR8FromBool(V_BOOL(ps), &V_R8(pd));
357     case VT_CY:       return VarR8FromCy(V_CY(ps), &V_R8(pd));
358     case VT_DECIMAL:  return VarR8FromDec(&V_DECIMAL(ps), &V_R8(pd));
359     case VT_DISPATCH: return VarR8FromDisp(V_DISPATCH(ps), lcid, &V_R8(pd));
360     case VT_BSTR:     return VarR8FromStr(V_BSTR(ps), lcid, dwFlags, &V_R8(pd));
361     }
362     break;
363
364   case VT_DATE:
365     switch (vtFrom)
366     {
367     case VT_EMPTY:    V_DATE(pd) = 0.0; return S_OK;
368     case VT_I1:       return VarDateFromI1(V_I1(ps), &V_DATE(pd));
369     case VT_I2:       return VarDateFromI2(V_I2(ps), &V_DATE(pd));
370     case VT_I4:       return VarDateFromI4(V_I4(ps), &V_DATE(pd));
371     case VT_UI1:      return VarDateFromUI1(V_UI1(ps), &V_DATE(pd));
372     case VT_UI2:      return VarDateFromUI2(V_UI2(ps), &V_DATE(pd));
373     case VT_UI4:      return VarDateFromUI4(V_UI4(ps), &V_DATE(pd));
374     case VT_I8:       return VarDateFromI8(V_I8(ps), &V_DATE(pd));
375     case VT_UI8:      return VarDateFromUI8(V_UI8(ps), &V_DATE(pd));
376     case VT_R4:       return VarDateFromR4(V_R4(ps), &V_DATE(pd));
377     case VT_R8:       return VarDateFromR8(V_R8(ps), &V_DATE(pd));
378     case VT_BOOL:     return VarDateFromBool(V_BOOL(ps), &V_DATE(pd));
379     case VT_CY:       return VarDateFromCy(V_CY(ps), &V_DATE(pd));
380     case VT_DECIMAL:  return VarDateFromDec(&V_DECIMAL(ps), &V_DATE(pd));
381     case VT_DISPATCH: return VarDateFromDisp(V_DISPATCH(ps), lcid, &V_DATE(pd));
382     case VT_BSTR:     return VarDateFromStr(V_BSTR(ps), lcid, dwFlags, &V_DATE(pd));
383     }
384     break;
385
386   case VT_BOOL:
387     switch (vtFrom)
388     {
389     case VT_EMPTY:    V_BOOL(pd) = 0; return S_OK;
390     case VT_I1:       return VarBoolFromI1(V_I1(ps), &V_BOOL(pd));
391     case VT_I2:       return VarBoolFromI2(V_I2(ps), &V_BOOL(pd));
392     case VT_I4:       return VarBoolFromI4(V_I4(ps), &V_BOOL(pd));
393     case VT_UI1:      return VarBoolFromUI1(V_UI1(ps), &V_BOOL(pd));
394     case VT_UI2:      return VarBoolFromUI2(V_UI2(ps), &V_BOOL(pd));
395     case VT_UI4:      return VarBoolFromUI4(V_UI4(ps), &V_BOOL(pd));
396     case VT_I8:       return VarBoolFromI8(V_I8(ps), &V_BOOL(pd));
397     case VT_UI8:      return VarBoolFromUI8(V_UI8(ps), &V_BOOL(pd));
398     case VT_R4:       return VarBoolFromR4(V_R4(ps), &V_BOOL(pd));
399     case VT_R8:       return VarBoolFromR8(V_R8(ps), &V_BOOL(pd));
400     case VT_DATE:     return VarBoolFromDate(V_DATE(ps), &V_BOOL(pd));
401     case VT_CY:       return VarBoolFromCy(V_CY(ps), &V_BOOL(pd));
402     case VT_DECIMAL:  return VarBoolFromDec(&V_DECIMAL(ps), &V_BOOL(pd));
403     case VT_DISPATCH: return VarBoolFromDisp(V_DISPATCH(ps), lcid, &V_BOOL(pd));
404     case VT_BSTR:     return VarBoolFromStr(V_BSTR(ps), lcid, dwFlags, &V_BOOL(pd));
405     }
406     break;
407
408   case VT_BSTR:
409     switch (vtFrom)
410     {
411     case VT_EMPTY:
412       V_BSTR(pd) = SysAllocStringLen(NULL, 0);
413       return V_BSTR(pd) ? S_OK : E_OUTOFMEMORY;
414     case VT_BOOL:
415       if (wFlags & (VARIANT_ALPHABOOL|VARIANT_LOCALBOOL))
416          return VarBstrFromBool(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
417       return VarBstrFromI2(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
418     case VT_I1:       return VarBstrFromI1(V_I1(ps), lcid, dwFlags, &V_BSTR(pd));
419     case VT_I2:       return VarBstrFromI2(V_I2(ps), lcid, dwFlags, &V_BSTR(pd));
420     case VT_I4:       return VarBstrFromI4(V_I4(ps), lcid, dwFlags, &V_BSTR(pd));
421     case VT_UI1:      return VarBstrFromUI1(V_UI1(ps), lcid, dwFlags, &V_BSTR(pd));
422     case VT_UI2:      return VarBstrFromUI2(V_UI2(ps), lcid, dwFlags, &V_BSTR(pd));
423     case VT_UI4:      return VarBstrFromUI4(V_UI4(ps), lcid, dwFlags, &V_BSTR(pd));
424     case VT_I8:       return VarBstrFromI8(V_I8(ps), lcid, dwFlags, &V_BSTR(pd));
425     case VT_UI8:      return VarBstrFromUI8(V_UI8(ps), lcid, dwFlags, &V_BSTR(pd));
426     case VT_R4:       return VarBstrFromR4(V_R4(ps), lcid, dwFlags, &V_BSTR(pd));
427     case VT_R8:       return VarBstrFromR8(V_R8(ps), lcid, dwFlags, &V_BSTR(pd));
428     case VT_DATE:     return VarBstrFromDate(V_DATE(ps), lcid, dwFlags, &V_BSTR(pd));
429     case VT_CY:       return VarBstrFromCy(V_CY(ps), lcid, dwFlags, &V_BSTR(pd));
430     case VT_DECIMAL:  return VarBstrFromDec(&V_DECIMAL(ps), lcid, dwFlags, &V_BSTR(pd));
431 /*  case VT_DISPATCH: return VarBstrFromDisp(V_DISPATCH(ps), lcid, dwFlags, &V_BSTR(pd)); */
432     }
433     break;
434
435   case VT_CY:
436     switch (vtFrom)
437     {
438     case VT_EMPTY:    V_CY(pd).int64 = 0; return S_OK;
439     case VT_I1:       return VarCyFromI1(V_I1(ps), &V_CY(pd));
440     case VT_I2:       return VarCyFromI2(V_I2(ps), &V_CY(pd));
441     case VT_I4:       return VarCyFromI4(V_I4(ps), &V_CY(pd));
442     case VT_UI1:      return VarCyFromUI1(V_UI1(ps), &V_CY(pd));
443     case VT_UI2:      return VarCyFromUI2(V_UI2(ps), &V_CY(pd));
444     case VT_UI4:      return VarCyFromUI4(V_UI4(ps), &V_CY(pd));
445     case VT_I8:       return VarCyFromI8(V_I8(ps), &V_CY(pd));
446     case VT_UI8:      return VarCyFromUI8(V_UI8(ps), &V_CY(pd));
447     case VT_R4:       return VarCyFromR4(V_R4(ps), &V_CY(pd));
448     case VT_R8:       return VarCyFromR8(V_R8(ps), &V_CY(pd));
449     case VT_DATE:     return VarCyFromDate(V_DATE(ps), &V_CY(pd));
450     case VT_BOOL:     return VarCyFromBool(V_BOOL(ps), &V_CY(pd));
451     case VT_DECIMAL:  return VarCyFromDec(&V_DECIMAL(ps), &V_CY(pd));
452     case VT_DISPATCH: return VarCyFromDisp(V_DISPATCH(ps), lcid, &V_CY(pd));
453     case VT_BSTR:     return VarCyFromStr(V_BSTR(ps), lcid, dwFlags, &V_CY(pd));
454     }
455     break;
456
457   case VT_DECIMAL:
458     switch (vtFrom)
459     {
460     case VT_EMPTY:
461     case VT_BOOL:
462        DEC_SIGNSCALE(&V_DECIMAL(pd)) = SIGNSCALE(DECIMAL_POS,0);
463        DEC_HI32(&V_DECIMAL(pd)) = 0;
464        DEC_MID32(&V_DECIMAL(pd)) = 0;
465         /* VarDecFromBool() coerces to -1/0, ChangeTypeEx() coerces to 1/0.
466          * VT_NULL and VT_EMPTY always give a 0 value.
467          */
468        DEC_LO32(&V_DECIMAL(pd)) = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0;
469        return S_OK;
470     case VT_I1:       return VarDecFromI1(V_I1(ps), &V_DECIMAL(pd));
471     case VT_I2:       return VarDecFromI2(V_I2(ps), &V_DECIMAL(pd));
472     case VT_I4:       return VarDecFromI4(V_I4(ps), &V_DECIMAL(pd));
473     case VT_UI1:      return VarDecFromUI1(V_UI1(ps), &V_DECIMAL(pd));
474     case VT_UI2:      return VarDecFromUI2(V_UI2(ps), &V_DECIMAL(pd));
475     case VT_UI4:      return VarDecFromUI4(V_UI4(ps), &V_DECIMAL(pd));
476     case VT_I8:       return VarDecFromI8(V_I8(ps), &V_DECIMAL(pd));
477     case VT_UI8:      return VarDecFromUI8(V_UI8(ps), &V_DECIMAL(pd));
478     case VT_R4:       return VarDecFromR4(V_R4(ps), &V_DECIMAL(pd));
479     case VT_R8:       return VarDecFromR8(V_R8(ps), &V_DECIMAL(pd));
480     case VT_DATE:     return VarDecFromDate(V_DATE(ps), &V_DECIMAL(pd));
481     case VT_CY:       return VarDecFromCy(V_CY(pd), &V_DECIMAL(ps));
482     case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(ps));
483     case VT_BSTR:     return VarDecFromStr(V_BSTR(ps), lcid, dwFlags, &V_DECIMAL(pd));
484     }
485     break;
486
487   case VT_UNKNOWN:
488     switch (vtFrom)
489     {
490     case VT_DISPATCH:
491       if (V_DISPATCH(ps) == NULL)
492         V_UNKNOWN(pd) = NULL;
493       else
494         res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd));
495       break;
496     }
497     break;
498
499   case VT_DISPATCH:
500     switch (vtFrom)
501     {
502     case VT_UNKNOWN:
503       if (V_UNKNOWN(ps) == NULL)
504         V_DISPATCH(pd) = NULL;
505       else
506         res = IUnknown_QueryInterface(V_UNKNOWN(ps), &IID_IDispatch, (LPVOID*)&V_DISPATCH(pd));
507       break;
508     }
509     break;
510
511   case VT_RECORD:
512     break;
513   }
514   return res;
515 }
516
517 /* Coerce to/from an array */
518 static inline HRESULT VARIANT_CoerceArray(VARIANTARG* pd, VARIANTARG* ps, VARTYPE vt)
519 {
520   if (vt == VT_BSTR && V_VT(ps) == (VT_ARRAY|VT_UI1))
521     return BstrFromVector(V_ARRAY(ps), &V_BSTR(pd));
522
523   if (V_VT(ps) == VT_BSTR && vt == (VT_ARRAY|VT_UI1))
524     return VectorFromBstr(V_BSTR(ps), &V_ARRAY(ps));
525
526   if (V_VT(ps) == vt)
527     return SafeArrayCopy(V_ARRAY(ps), &V_ARRAY(pd));
528
529   return DISP_E_TYPEMISMATCH;
530 }
531
532 /******************************************************************************
533  * Check if a variants type is valid.
534  */
535 static inline HRESULT VARIANT_ValidateType(VARTYPE vt)
536 {
537   VARTYPE vtExtra = vt & VT_EXTRA_TYPE;
538
539   vt &= VT_TYPEMASK;
540
541   if (!(vtExtra & (VT_VECTOR|VT_RESERVED)))
542   {
543     if (vt < VT_VOID || vt == VT_RECORD || vt == VT_CLSID)
544     {
545       if ((vtExtra & (VT_BYREF|VT_ARRAY)) && vt <= VT_NULL)
546         return DISP_E_BADVARTYPE;
547       if (vt != (VARTYPE)15)
548         return S_OK;
549     }
550   }
551   return DISP_E_BADVARTYPE;
552 }
553
554 /******************************************************************************
555  *              VariantInit     [OLEAUT32.8]
556  *
557  * Initialise a variant.
558  *
559  * PARAMS
560  *  pVarg [O] Variant to initialise
561  *
562  * RETURNS
563  *  Nothing.
564  *
565  * NOTES
566  *  This function simply sets the type of the variant to VT_EMPTY. It does not
567  *  free any existing value, use VariantClear() for that.
568  */
569 void WINAPI VariantInit(VARIANTARG* pVarg)
570 {
571   TRACE("(%p)\n", pVarg);
572
573   V_VT(pVarg) = VT_EMPTY; /* Native doesn't set any other fields */
574 }
575
576 /******************************************************************************
577  *              VariantClear    [OLEAUT32.9]
578  *
579  * Clear a variant.
580  *
581  * PARAMS
582  *  pVarg [I/O] Variant to clear
583  *
584  * RETURNS
585  *  Success: S_OK. Any previous value in pVarg is freed and its type is set to VT_EMPTY.
586  *  Failure: DISP_E_BADVARTYPE, if the variant is a not a valid variant type.
587  */
588 HRESULT WINAPI VariantClear(VARIANTARG* pVarg)
589 {
590   HRESULT hres = S_OK;
591
592   TRACE("(%p->(%s%s))\n", pVarg, debugstr_VT(pVarg), debugstr_VF(pVarg));
593
594   hres = VARIANT_ValidateType(V_VT(pVarg));
595
596   if (SUCCEEDED(hres))
597   {
598     if (!V_ISBYREF(pVarg))
599     {
600       if (V_ISARRAY(pVarg) || V_VT(pVarg) == VT_SAFEARRAY)
601       {
602         if (V_ARRAY(pVarg))
603           hres = SafeArrayDestroy(V_ARRAY(pVarg));
604       }
605       else if (V_VT(pVarg) == VT_BSTR)
606       {
607         if (V_BSTR(pVarg))
608           SysFreeString(V_BSTR(pVarg));
609       }
610       else if (V_VT(pVarg) == VT_RECORD)
611       {
612         struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal);
613         if (pBr->pRecInfo)
614         {
615           IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord);
616           IRecordInfo_Release(pBr->pRecInfo);
617         }
618       }
619       else if (V_VT(pVarg) == VT_DISPATCH ||
620                V_VT(pVarg) == VT_UNKNOWN)
621       {
622         if (V_UNKNOWN(pVarg))
623           IUnknown_Release(V_UNKNOWN(pVarg));
624       }
625       else if (V_VT(pVarg) == VT_VARIANT)
626       {
627         if (V_VARIANTREF(pVarg))
628           VariantClear(V_VARIANTREF(pVarg));
629       }
630     }
631     V_VT(pVarg) = VT_EMPTY;
632   }
633   return hres;
634 }
635
636 /******************************************************************************
637  * Copy an IRecordInfo object contained in a variant.
638  */
639 static HRESULT VARIANT_CopyIRecordInfo(struct __tagBRECORD* pBr)
640 {
641   HRESULT hres = S_OK;
642
643   if (pBr->pRecInfo)
644   {
645     ULONG ulSize;
646
647     hres = IRecordInfo_GetSize(pBr->pRecInfo, &ulSize);
648     if (SUCCEEDED(hres))
649     {
650       PVOID pvRecord = HeapAlloc(GetProcessHeap(), 0, ulSize);
651       if (!pvRecord)
652         hres = E_OUTOFMEMORY;
653       else
654       {
655         memcpy(pvRecord, pBr->pvRecord, ulSize);
656         pBr->pvRecord = pvRecord;
657
658         hres = IRecordInfo_RecordCopy(pBr->pRecInfo, pvRecord, pvRecord);
659         if (SUCCEEDED(hres))
660           IRecordInfo_AddRef(pBr->pRecInfo);
661       }
662     }
663   }
664   else if (pBr->pvRecord)
665     hres = E_INVALIDARG;
666   return hres;
667 }
668
669 /******************************************************************************
670  *    VariantCopy  [OLEAUT32.10]
671  *
672  * Copy a variant.
673  *
674  * PARAMS
675  *  pvargDest [O] Destination for copy
676  *  pvargSrc  [I] Source variant to copy
677  *
678  * RETURNS
679  *  Success: S_OK. pvargDest contains a copy of pvargSrc.
680  *  Failure: DISP_E_BADVARTYPE, if either variant has an invalid type.
681  *           E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an
682  *           HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(),
683  *           or IRecordInfo_RecordCopy(), depending on the type of pvargSrc.
684  *
685  * NOTES
686  *  - If pvargSrc == pvargDest, this function does nothing, and succeeds if
687  *    pvargSrc is valid. Otherwise, pvargDest is always cleared using
688  *    VariantClear() before pvargSrc is copied to it. If clearing pvargDest
689  *    fails, so does this function.
690  *  - VT_CLSID is a valid type type for pvargSrc, but not for pvargDest.
691  *  - For by-value non-intrinsic types, a deep copy is made, i.e. The whole value
692  *    is copied rather than just any pointers to it.
693  *  - For by-value object types the object pointer is copied and the objects
694  *    reference count increased using IUnknown_AddRef().
695  *  - For all by-reference types, only the referencing pointer is copied.
696  */
697 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
698 {
699   HRESULT hres = S_OK;
700
701   TRACE("(%p->(%s%s),%p->(%s%s))\n", pvargDest, debugstr_VT(pvargDest),
702         debugstr_VF(pvargDest), pvargSrc, debugstr_VT(pvargSrc),
703         debugstr_VF(pvargSrc));
704
705   if (V_TYPE(pvargSrc) == VT_CLSID || /* VT_CLSID is a special case */
706       FAILED(VARIANT_ValidateType(V_VT(pvargSrc))))
707     return DISP_E_BADVARTYPE;
708
709   if (pvargSrc != pvargDest &&
710       SUCCEEDED(hres = VariantClear(pvargDest)))
711   {
712     *pvargDest = *pvargSrc; /* Shallow copy the value */
713
714     if (!V_ISBYREF(pvargSrc))
715     {
716       if (V_ISARRAY(pvargSrc))
717       {
718         if (V_ARRAY(pvargSrc))
719           hres = SafeArrayCopy(V_ARRAY(pvargSrc), &V_ARRAY(pvargDest));
720       }
721       else if (V_VT(pvargSrc) == VT_BSTR)
722       {
723         if (V_BSTR(pvargSrc))
724         {
725           V_BSTR(pvargDest) = SysAllocStringByteLen((char*)V_BSTR(pvargSrc), SysStringByteLen(V_BSTR(pvargSrc)));
726           if (!V_BSTR(pvargDest))
727           {
728             TRACE("!V_BSTR(pvargDest), SysAllocStringByteLen() failed to allocate %d bytes\n", SysStringByteLen(V_BSTR(pvargSrc)));
729             hres = E_OUTOFMEMORY;
730           }
731         }
732       }
733       else if (V_VT(pvargSrc) == VT_RECORD)
734       {
735         hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
736       }
737       else if (V_VT(pvargSrc) == VT_DISPATCH ||
738                V_VT(pvargSrc) == VT_UNKNOWN)
739       {
740         if (V_UNKNOWN(pvargSrc))
741           IUnknown_AddRef(V_UNKNOWN(pvargSrc));
742       }
743     }
744   }
745   return hres;
746 }
747
748 /* Return the byte size of a variants data */
749 static inline size_t VARIANT_DataSize(const VARIANT* pv)
750 {
751   switch (V_TYPE(pv))
752   {
753   case VT_I1:
754   case VT_UI1:   return sizeof(BYTE); break;
755   case VT_I2:
756   case VT_UI2:   return sizeof(SHORT); break;
757   case VT_INT:
758   case VT_UINT:
759   case VT_I4:
760   case VT_UI4:   return sizeof(LONG); break;
761   case VT_I8:
762   case VT_UI8:   return sizeof(LONGLONG); break;
763   case VT_R4:    return sizeof(float); break;
764   case VT_R8:    return sizeof(double); break;
765   case VT_DATE:  return sizeof(DATE); break;
766   case VT_BOOL:  return sizeof(VARIANT_BOOL); break;
767   case VT_DISPATCH:
768   case VT_UNKNOWN:
769   case VT_BSTR:  return sizeof(void*); break;
770   case VT_CY:    return sizeof(CY); break;
771   case VT_ERROR: return sizeof(SCODE); break;
772   }
773   TRACE("Shouldn't be called for vt %s%s!\n", debugstr_VT(pv), debugstr_VF(pv));
774   return 0;
775 }
776
777 /******************************************************************************
778  *    VariantCopyInd  [OLEAUT32.11]
779  *
780  * Copy a variant, dereferencing it it is by-reference.
781  *
782  * PARAMS
783  *  pvargDest [O] Destination for copy
784  *  pvargSrc  [I] Source variant to copy
785  *
786  * RETURNS
787  *  Success: S_OK. pvargDest contains a copy of pvargSrc.
788  *  Failure: An HRESULT error code indicating the error.
789  *
790  * NOTES
791  *  Failure: DISP_E_BADVARTYPE, if either variant has an invalid by-value type.
792  *           E_INVALIDARG, if pvargSrc  is an invalid by-reference type.
793  *           E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an
794  *           HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(),
795  *           or IRecordInfo_RecordCopy(), depending on the type of pvargSrc.
796  *
797  * NOTES
798  *  - If pvargSrc is by-value, this function behaves exactly as VariantCopy().
799  *  - If pvargSrc is by-reference, the value copied to pvargDest is the pointed-to
800  *    value.
801  *  - if pvargSrc == pvargDest, this function dereferences in place. Otherwise,
802  *    pvargDest is always cleared using VariantClear() before pvargSrc is copied
803  *    to it. If clearing pvargDest fails, so does this function.
804  */
805 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
806 {
807   VARIANTARG vTmp, *pSrc = pvargSrc;
808   VARTYPE vt;
809   HRESULT hres = S_OK;
810
811   TRACE("(%p->(%s%s),%p->(%s%s))\n", pvargDest, debugstr_VT(pvargDest),
812         debugstr_VF(pvargDest), pvargSrc, debugstr_VT(pvargSrc),
813         debugstr_VF(pvargSrc));
814
815   if (!V_ISBYREF(pvargSrc))
816     return VariantCopy(pvargDest, pvargSrc);
817
818   /* Argument checking is more lax than VariantCopy()... */
819   vt = V_TYPE(pvargSrc);
820   if (V_ISARRAY(pvargSrc) ||
821      (vt > VT_NULL && vt != (VARTYPE)15 && vt < VT_VOID &&
822      !(V_VT(pvargSrc) & (VT_VECTOR|VT_RESERVED))))
823   {
824     /* OK */
825   }
826   else
827     return E_INVALIDARG; /* ...And the return value for invalid types differs too */
828
829   if (pvargSrc == pvargDest)
830   {
831     /* In place copy. Use a shallow copy of pvargSrc & init pvargDest.
832      * This avoids an expensive VariantCopy() call - e.g. SafeArrayCopy().
833      */
834     vTmp = *pvargSrc;
835     pSrc = &vTmp;
836     V_VT(pvargDest) = VT_EMPTY;
837   }
838   else
839   {
840     /* Copy into another variant. Free the variant in pvargDest */
841     if (FAILED(hres = VariantClear(pvargDest)))
842     {
843       TRACE("VariantClear() of destination failed\n");
844       return hres;
845     }
846   }
847
848   if (V_ISARRAY(pSrc))
849   {
850     /* Native doesn't check that *V_ARRAYREF(pSrc) is valid */
851     hres = SafeArrayCopy(*V_ARRAYREF(pSrc), &V_ARRAY(pvargDest));
852   }
853   else if (V_VT(pSrc) == (VT_BSTR|VT_BYREF))
854   {
855     /* Native doesn't check that *V_BSTRREF(pSrc) is valid */
856     V_BSTR(pvargDest) = SysAllocStringByteLen((char*)*V_BSTRREF(pSrc), SysStringByteLen(*V_BSTRREF(pSrc)));
857   }
858   else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF))
859   {
860     V_UNION(pvargDest,brecVal) = V_UNION(pvargSrc,brecVal);
861     hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
862   }
863   else if (V_VT(pSrc) == (VT_DISPATCH|VT_BYREF) ||
864            V_VT(pSrc) == (VT_UNKNOWN|VT_BYREF))
865   {
866     /* Native doesn't check that *V_UNKNOWNREF(pSrc) is valid */
867     V_UNKNOWN(pvargDest) = *V_UNKNOWNREF(pSrc);
868     if (*V_UNKNOWNREF(pSrc))
869       IUnknown_AddRef(*V_UNKNOWNREF(pSrc));
870   }
871   else if (V_VT(pSrc) == (VT_VARIANT|VT_BYREF))
872   {
873     /* Native doesn't check that *V_VARIANTREF(pSrc) is valid */
874     if (V_VT(V_VARIANTREF(pSrc)) == (VT_VARIANT|VT_BYREF))
875       hres = E_INVALIDARG; /* Don't dereference more than one level */
876     else
877       hres = VariantCopyInd(pvargDest, V_VARIANTREF(pSrc));
878
879     /* Use the dereferenced variants type value, not VT_VARIANT */
880     goto VariantCopyInd_Return;
881   }
882   else if (V_VT(pSrc) == (VT_DECIMAL|VT_BYREF))
883   {
884     memcpy(&DEC_SCALE(&V_DECIMAL(pvargDest)), &DEC_SCALE(V_DECIMALREF(pSrc)),
885            sizeof(DECIMAL) - sizeof(USHORT));
886   }
887   else
888   {
889     /* Copy the pointed to data into this variant */
890     memcpy(&V_BYREF(pvargDest), V_BYREF(pSrc), VARIANT_DataSize(pSrc));
891   }
892
893   V_VT(pvargDest) = V_VT(pSrc) & ~VT_BYREF;
894
895 VariantCopyInd_Return:
896
897   if (pSrc != pvargSrc)
898     VariantClear(pSrc);
899
900   TRACE("returning 0x%08lx, %p->(%s%s)\n", hres, pvargDest,
901         debugstr_VT(pvargDest), debugstr_VF(pvargDest));
902   return hres;
903 }
904
905 /******************************************************************************
906  *    VariantChangeType  [OLEAUT32.12]
907  *
908  * Change the type of a variant.
909  *
910  * PARAMS
911  *  pvargDest [O] Destination for the converted variant
912  *  pvargSrc  [O] Source variant to change the type of
913  *  wFlags    [I] VARIANT_ flags from "oleauto.h"
914  *  vt        [I] Variant type to change pvargSrc into
915  *
916  * RETURNS
917  *  Success: S_OK. pvargDest contains the converted value.
918  *  Failure: An HRESULT error code describing the failure.
919  *
920  * NOTES
921  *  The LCID used for the conversion is LOCALE_USER_DEFAULT.
922  *  See VariantChangeTypeEx.
923  */
924 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
925                                  USHORT wFlags, VARTYPE vt)
926 {
927   return VariantChangeTypeEx( pvargDest, pvargSrc, LOCALE_USER_DEFAULT, wFlags, vt );
928 }
929
930 /******************************************************************************
931  *    VariantChangeTypeEx  [OLEAUT32.147]
932  *
933  * Change the type of a variant.
934  *
935  * PARAMS
936  *  pvargDest [O] Destination for the converted variant
937  *  pvargSrc  [O] Source variant to change the type of
938  *  lcid      [I] LCID for the conversion
939  *  wFlags    [I] VARIANT_ flags from "oleauto.h"
940  *  vt        [I] Variant type to change pvargSrc into
941  *
942  * RETURNS
943  *  Success: S_OK. pvargDest contains the converted value.
944  *  Failure: An HRESULT error code describing the failure.
945  *
946  * NOTES
947  *  pvargDest and pvargSrc can point to the same variant to perform an in-place
948  *  conversion. If the conversion is successful, pvargSrc will be freed.
949  */
950 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
951                                    LCID lcid, USHORT wFlags, VARTYPE vt)
952 {
953   HRESULT res = S_OK;
954
955   TRACE("(%p->(%s%s),%p->(%s%s),0x%08lx,0x%04x,%s%s)\n", pvargDest,
956         debugstr_VT(pvargDest), debugstr_VF(pvargDest), pvargSrc,
957         debugstr_VT(pvargSrc), debugstr_VF(pvargSrc), lcid, wFlags,
958         debugstr_vt(vt), debugstr_vf(vt));
959
960   if (vt == VT_CLSID)
961     res = DISP_E_BADVARTYPE;
962   else
963   {
964     res = VARIANT_ValidateType(V_VT(pvargSrc));
965
966     if (SUCCEEDED(res))
967     {
968       res = VARIANT_ValidateType(vt);
969
970       if (SUCCEEDED(res))
971       {
972         VARIANTARG vTmp;
973
974         V_VT(&vTmp) = VT_EMPTY;
975         res = VariantCopyInd(&vTmp, pvargSrc);
976
977         if (SUCCEEDED(res))
978         {
979           res = VariantClear(pvargDest);
980
981           if (SUCCEEDED(res))
982           {
983             if (V_ISARRAY(&vTmp) || (vt & VT_ARRAY))
984               res = VARIANT_CoerceArray(pvargDest, &vTmp, vt);
985             else
986               res = VARIANT_Coerce(pvargDest, lcid, wFlags, &vTmp, vt);
987
988             if (SUCCEEDED(res))
989               V_VT(pvargDest) = vt;
990           }
991           VariantClear(&vTmp);
992         }
993       }
994     }
995   }
996
997   TRACE("returning 0x%08lx, %p->(%s%s)\n", res, pvargDest,
998         debugstr_VT(pvargDest), debugstr_VF(pvargDest));
999   return res;
1000 }
1001
1002 /* Date Conversions */
1003
1004 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
1005
1006 /* Convert a VT_DATE value to a Julian Date */
1007 static inline int VARIANT_JulianFromDate(int dateIn)
1008 {
1009   int julianDays = dateIn;
1010
1011   julianDays -= DATE_MIN; /* Convert to + days from 1 Jan 100 AD */
1012   julianDays += 1757585;  /* Convert to + days from 23 Nov 4713 BC (Julian) */
1013   return julianDays;
1014 }
1015
1016 /* Convert a Julian Date to a VT_DATE value */
1017 static inline int VARIANT_DateFromJulian(int dateIn)
1018 {
1019   int julianDays = dateIn;
1020
1021   julianDays -= 1757585;  /* Convert to + days from 1 Jan 100 AD */
1022   julianDays += DATE_MIN; /* Convert to +/- days from 1 Jan 1899 AD */
1023   return julianDays;
1024 }
1025
1026 /* Convert a Julian date to Day/Month/Year - from PostgreSQL */
1027 static inline void VARIANT_DMYFromJulian(int jd, USHORT *year, USHORT *month, USHORT *day)
1028 {
1029   int j, i, l, n;
1030
1031   l = jd + 68569;
1032   n = l * 4 / 146097;
1033   l -= (n * 146097 + 3) / 4;
1034   i = (4000 * (l + 1)) / 1461001;
1035   l += 31 - (i * 1461) / 4;
1036   j = (l * 80) / 2447;
1037   *day = l - (j * 2447) / 80;
1038   l = j / 11;
1039   *month = (j + 2) - (12 * l);
1040   *year = 100 * (n - 49) + i + l;
1041 }
1042
1043 /* Convert Day/Month/Year to a Julian date - from PostgreSQL */
1044 static inline double VARIANT_JulianFromDMY(USHORT year, USHORT month, USHORT day)
1045 {
1046   int m12 = (month - 14) / 12;
1047
1048   return ((1461 * (year + 4800 + m12)) / 4 + (367 * (month - 2 - 12 * m12)) / 12 -
1049            (3 * ((year + 4900 + m12) / 100)) / 4 + day - 32075);
1050 }
1051
1052 /* Macros for accessing DOS format date/time fields */
1053 #define DOS_YEAR(x)   (1980 + (x >> 9))
1054 #define DOS_MONTH(x)  ((x >> 5) & 0xf)
1055 #define DOS_DAY(x)    (x & 0x1f)
1056 #define DOS_HOUR(x)   (x >> 11)
1057 #define DOS_MINUTE(x) ((x >> 5) & 0x3f)
1058 #define DOS_SECOND(x) ((x & 0x1f) << 1)
1059 /* Create a DOS format date/time */
1060 #define DOS_DATE(d,m,y) (d | (m << 5) | ((y-1980) << 9))
1061 #define DOS_TIME(h,m,s) ((s >> 1) | (m << 5) | (h << 11))
1062
1063 /* Roll a date forwards or backwards to correct it */
1064 static HRESULT VARIANT_RollUdate(UDATE *lpUd)
1065 {
1066   static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1067
1068   TRACE("Raw date: %d/%d/%d %d:%d:%d\n", lpUd->st.wDay, lpUd->st.wMonth,
1069         lpUd->st.wYear, lpUd->st.wHour, lpUd->st.wMinute, lpUd->st.wSecond);
1070
1071   /* Years < 100 are treated as 1900 + year */
1072   if (lpUd->st.wYear < 100)
1073     lpUd->st.wYear += 1900;
1074
1075   if (!lpUd->st.wMonth)
1076   {
1077     /* Roll back to December of the previous year */
1078     lpUd->st.wMonth = 12;
1079     lpUd->st.wYear--;
1080   }
1081   else while (lpUd->st.wMonth > 12)
1082   {
1083     /* Roll forward the correct number of months */
1084     lpUd->st.wYear++;
1085     lpUd->st.wMonth -= 12;
1086   }
1087
1088   if (lpUd->st.wYear > 9999 || lpUd->st.wHour > 23 ||
1089       lpUd->st.wMinute > 59 || lpUd->st.wSecond > 59)
1090     return E_INVALIDARG; /* Invalid values */
1091
1092   if (!lpUd->st.wDay)
1093   {
1094     /* Roll back the date one day */
1095     if (lpUd->st.wMonth == 1)
1096     {
1097       /* Roll back to December 31 of the previous year */
1098       lpUd->st.wDay   = 31;
1099       lpUd->st.wMonth = 12;
1100       lpUd->st.wYear--;
1101     }
1102     else
1103     {
1104       lpUd->st.wMonth--; /* Previous month */
1105       if (lpUd->st.wMonth == 2 && IsLeapYear(lpUd->st.wYear))
1106         lpUd->st.wDay = 29; /* Februaury has 29 days on leap years */
1107       else
1108         lpUd->st.wDay = days[lpUd->st.wMonth]; /* Last day of the month */
1109     }
1110   }
1111   else if (lpUd->st.wDay > 28)
1112   {
1113     int rollForward = 0;
1114
1115     /* Possibly need to roll the date forward */
1116     if (lpUd->st.wMonth == 2 && IsLeapYear(lpUd->st.wYear))
1117       rollForward = lpUd->st.wDay - 29; /* Februaury has 29 days on leap years */
1118     else
1119       rollForward = lpUd->st.wDay - days[lpUd->st.wMonth];
1120
1121     if (rollForward > 0)
1122     {
1123       lpUd->st.wDay = rollForward;
1124       lpUd->st.wMonth++;
1125       if (lpUd->st.wMonth > 12)
1126       {
1127         lpUd->st.wMonth = 1; /* Roll forward into January of the next year */
1128         lpUd->st.wYear++;
1129       }
1130     }
1131   }
1132   TRACE("Rolled date: %d/%d/%d %d:%d:%d\n", lpUd->st.wDay, lpUd->st.wMonth,
1133         lpUd->st.wYear, lpUd->st.wHour, lpUd->st.wMinute, lpUd->st.wSecond);
1134   return S_OK;
1135 }
1136
1137 /**********************************************************************
1138  *              DosDateTimeToVariantTime [OLEAUT32.14]
1139  *
1140  * Convert a Dos format date and time into variant VT_DATE format.
1141  *
1142  * PARAMS
1143  *  wDosDate [I] Dos format date
1144  *  wDosTime [I] Dos format time
1145  *  pDateOut [O] Destination for VT_DATE format
1146  *
1147  * RETURNS
1148  *  Success: TRUE. pDateOut contains the converted time.
1149  *  Failure: FALSE, if wDosDate or wDosTime are invalid (see notes).
1150  *
1151  * NOTES
1152  * - Dos format dates can only hold dates from 1-Jan-1980 to 31-Dec-2099.
1153  * - Dos format times are accurate to only 2 second precision.
1154  * - The format of a Dos Date is:
1155  *| Bits   Values  Meaning
1156  *| ----   ------  -------
1157  *| 0-4    1-31    Day of the week. 0 rolls back one day. A value greater than
1158  *|                the days in the month rolls forward the extra days.
1159  *| 5-8    1-12    Month of the year. 0 rolls back to December of the previous
1160  *|                year. 13-15 are invalid.
1161  *| 9-15   0-119   Year based from 1980 (Max 2099). 120-127 are invalid.
1162  * - The format of a Dos Time is:
1163  *| Bits   Values  Meaning
1164  *| ----   ------  -------
1165  *| 0-4    0-29    Seconds/2. 30 and 31 are invalid.
1166  *| 5-10   0-59    Minutes. 60-63 are invalid.
1167  *| 11-15  0-23    Hours (24 hour clock). 24-32 are invalid.
1168  */
1169 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
1170                                     double *pDateOut)
1171 {
1172   UDATE ud;
1173
1174   TRACE("(0x%x(%d/%d/%d),0x%x(%d:%d:%d),%p)\n",
1175         wDosDate, DOS_YEAR(wDosDate), DOS_MONTH(wDosDate), DOS_DAY(wDosDate),
1176         wDosTime, DOS_HOUR(wDosTime), DOS_MINUTE(wDosTime), DOS_SECOND(wDosTime),
1177         pDateOut);
1178
1179   ud.st.wYear = DOS_YEAR(wDosDate);
1180   ud.st.wMonth = DOS_MONTH(wDosDate);
1181   if (ud.st.wYear > 2099 || ud.st.wMonth > 12)
1182     return FALSE;
1183   ud.st.wDay = DOS_DAY(wDosDate);
1184   ud.st.wHour = DOS_HOUR(wDosTime);
1185   ud.st.wMinute = DOS_MINUTE(wDosTime);
1186   ud.st.wSecond = DOS_SECOND(wDosTime);
1187   ud.st.wDayOfWeek = ud.st.wMilliseconds = 0;
1188
1189   return !VarDateFromUdate(&ud, 0, pDateOut);
1190 }
1191
1192 /**********************************************************************
1193  *              VariantTimeToDosDateTime [OLEAUT32.13]
1194  *
1195  * Convert a variant format date into a Dos format date and time.
1196  *
1197  *  dateIn    [I] VT_DATE time format
1198  *  pwDosDate [O] Destination for Dos format date
1199  *  pwDosTime [O] Destination for Dos format time
1200  *
1201  * RETURNS
1202  *  Success: TRUE. pwDosDate and pwDosTime contains the converted values.
1203  *  Failure: FALSE, if dateIn cannot be represented in Dos format.
1204  *
1205  * NOTES
1206  *   See DosDateTimeToVariantTime() for Dos format details and bugs.
1207  */
1208 INT WINAPI VariantTimeToDosDateTime(double dateIn, USHORT *pwDosDate, USHORT *pwDosTime)
1209 {
1210   UDATE ud;
1211
1212   TRACE("(%g,%p,%p)\n", dateIn, pwDosDate, pwDosTime);
1213
1214   if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
1215     return FALSE;
1216
1217   if (ud.st.wYear < 1980 || ud.st.wYear > 2099)
1218     return FALSE;
1219
1220   *pwDosDate = DOS_DATE(ud.st.wDay, ud.st.wMonth, ud.st.wYear);
1221   *pwDosTime = DOS_TIME(ud.st.wHour, ud.st.wMinute, ud.st.wSecond);
1222
1223   TRACE("Returning 0x%x(%d/%d/%d), 0x%x(%d:%d:%d)\n",
1224         *pwDosDate, DOS_YEAR(*pwDosDate), DOS_MONTH(*pwDosDate), DOS_DAY(*pwDosDate),
1225         *pwDosTime, DOS_HOUR(*pwDosTime), DOS_MINUTE(*pwDosTime), DOS_SECOND(*pwDosTime));
1226   return TRUE;
1227 }
1228
1229 /***********************************************************************
1230  *              SystemTimeToVariantTime [OLEAUT32.184]
1231  *
1232  * Convert a System format date and time into variant VT_DATE format.
1233  *
1234  * PARAMS
1235  *  lpSt     [I] System format date and time
1236  *  pDateOut [O] Destination for VT_DATE format date
1237  *
1238  * RETURNS
1239  *  Success: TRUE. *pDateOut contains the converted value.
1240  *  Failure: FALSE, if lpSt cannot be represented in VT_DATE format.
1241  */
1242 INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut)
1243 {
1244   UDATE ud;
1245
1246   TRACE("(%p->%d/%d/%d %d:%d:%d,%p)\n", lpSt, lpSt->wDay, lpSt->wMonth,
1247         lpSt->wYear, lpSt->wHour, lpSt->wMinute, lpSt->wSecond, pDateOut);
1248
1249   if (lpSt->wMonth > 12)
1250     return FALSE;
1251
1252   memcpy(&ud.st, lpSt, sizeof(ud.st));
1253   return !VarDateFromUdate(&ud, 0, pDateOut);
1254 }
1255
1256 /***********************************************************************
1257  *              VariantTimeToSystemTime [OLEAUT32.185]
1258  *
1259  * Convert a variant VT_DATE into a System format date and time.
1260  *
1261  * PARAMS
1262  *  datein [I] Variant VT_DATE format date
1263  *  lpSt   [O] Destination for System format date and time
1264  *
1265  * RETURNS
1266  *  Success: TRUE. *lpSt contains the converted value.
1267  *  Failure: FALSE, if dateIn is too large or small.
1268  */
1269 INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt)
1270 {
1271   UDATE ud;
1272
1273   TRACE("(%g,%p)\n", dateIn, lpSt);
1274
1275   if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
1276     return FALSE;
1277
1278   memcpy(lpSt, &ud.st, sizeof(ud.st));
1279   return TRUE;
1280 }
1281
1282 /***********************************************************************
1283  *              VarDateFromUdate [OLEAUT32.330]
1284  *
1285  * Convert an unpacked format date and time to a variant VT_DATE.
1286  *
1287  * PARAMS
1288  *  pUdateIn [I] Unpacked format date and time to convert
1289  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1290  *  pDateOut [O] Destination for variant VT_DATE.
1291  *
1292  * RETURNS
1293  *  Success: S_OK. *pDateOut contains the converted value.
1294  *  Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
1295  */
1296 HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut)
1297 {
1298   UDATE ud;
1299   double dateVal;
1300
1301   TRACE("(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08lx,%p)\n", pUdateIn,
1302         pUdateIn->st.wMonth, pUdateIn->st.wDay, pUdateIn->st.wYear,
1303         pUdateIn->st.wHour, pUdateIn->st.wMinute, pUdateIn->st.wSecond,
1304         pUdateIn->st.wMilliseconds, pUdateIn->st.wDayOfWeek,
1305         pUdateIn->wDayOfYear, dwFlags, pDateOut);
1306
1307   memcpy(&ud, pUdateIn, sizeof(ud));
1308
1309   if (dwFlags & VAR_VALIDDATE)
1310     WARN("Ignoring VAR_VALIDDATE\n");
1311
1312   if (FAILED(VARIANT_RollUdate(&ud)))
1313     return E_INVALIDARG;
1314
1315   /* Date */
1316   dateVal = VARIANT_DateFromJulian(VARIANT_JulianFromDMY(ud.st.wYear, ud.st.wMonth, ud.st.wDay));
1317
1318   /* Time */
1319   dateVal += ud.st.wHour / 24.0;
1320   dateVal += ud.st.wMinute / 1440.0;
1321   dateVal += ud.st.wSecond / 86400.0;
1322   dateVal += ud.st.wMilliseconds / 86400000.0;
1323
1324   TRACE("Returning %g\n", dateVal);
1325   *pDateOut = dateVal;
1326   return S_OK;
1327 }
1328
1329 /***********************************************************************
1330  *              VarUdateFromDate [OLEAUT32.331]
1331  *
1332  * Convert a variant VT_DATE into an unpacked format date and time.
1333  *
1334  * PARAMS
1335  *  datein    [I] Variant VT_DATE format date
1336  *  dwFlags   [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1337  *  lpUdate   [O] Destination for unpacked format date and time
1338  *
1339  * RETURNS
1340  *  Success: S_OK. *lpUdate contains the converted value.
1341  *  Failure: E_INVALIDARG, if dateIn is too large or small.
1342  */
1343 HRESULT WINAPI VarUdateFromDate(DATE dateIn, ULONG dwFlags, UDATE *lpUdate)
1344 {
1345   /* Cumulative totals of days per month */
1346   static const USHORT cumulativeDays[] =
1347   {
1348     0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
1349   };
1350   double datePart, timePart;
1351   int julianDays;
1352
1353   TRACE("(%g,0x%08lx,%p)\n", dateIn, dwFlags, lpUdate);
1354
1355   if (dateIn <= (DATE_MIN - 1.0) || dateIn >= (DATE_MAX + 1.0))
1356     return E_INVALIDARG;
1357
1358   datePart = dateIn < 0.0 ? ceil(dateIn) : floor(dateIn);
1359   /* Compensate for int truncation (always downwards) */
1360   timePart = dateIn - datePart + 0.00000000001;
1361   if (timePart >= 1.0)
1362     timePart -= 0.00000000001;
1363
1364   /* Date */
1365   julianDays = VARIANT_JulianFromDate(dateIn);
1366   VARIANT_DMYFromJulian(julianDays, &lpUdate->st.wYear, &lpUdate->st.wMonth,
1367                         &lpUdate->st.wDay);
1368
1369   datePart = (datePart + 1.5) / 7.0;
1370   lpUdate->st.wDayOfWeek = (datePart - floor(datePart)) * 7;
1371   if (lpUdate->st.wDayOfWeek == 0)
1372     lpUdate->st.wDayOfWeek = 5;
1373   else if (lpUdate->st.wDayOfWeek == 1)
1374     lpUdate->st.wDayOfWeek = 6;
1375   else
1376     lpUdate->st.wDayOfWeek -= 2;
1377
1378   if (lpUdate->st.wMonth > 2 && IsLeapYear(lpUdate->st.wYear))
1379     lpUdate->wDayOfYear = 1; /* After February, in a leap year */
1380   else
1381     lpUdate->wDayOfYear = 0;
1382
1383   lpUdate->wDayOfYear += cumulativeDays[lpUdate->st.wMonth];
1384   lpUdate->wDayOfYear += lpUdate->st.wDay;
1385
1386   /* Time */
1387   timePart *= 24.0;
1388   lpUdate->st.wHour = timePart;
1389   timePart -= lpUdate->st.wHour;
1390   timePart *= 60.0;
1391   lpUdate->st.wMinute = timePart;
1392   timePart -= lpUdate->st.wMinute;
1393   timePart *= 60.0;
1394   lpUdate->st.wSecond = timePart;
1395   timePart -= lpUdate->st.wSecond;
1396   lpUdate->st.wMilliseconds = 0;
1397   if (timePart > 0.5)
1398   {
1399     /* Round the milliseconds, adjusting the time/date forward if needed */
1400     if (lpUdate->st.wSecond < 59)
1401       lpUdate->st.wSecond++;
1402     else
1403     {
1404       lpUdate->st.wSecond = 0;
1405       if (lpUdate->st.wMinute < 59)
1406         lpUdate->st.wMinute++;
1407       else
1408       {
1409         lpUdate->st.wMinute = 0;
1410         if (lpUdate->st.wHour < 23)
1411           lpUdate->st.wHour++;
1412         else
1413         {
1414           lpUdate->st.wHour = 0;
1415           /* Roll over a whole day */
1416           if (++lpUdate->st.wDay > 28)
1417             VARIANT_RollUdate(lpUdate);
1418         }
1419       }
1420     }
1421   }
1422   return S_OK;
1423 }
1424
1425 #define GET_NUMBER_TEXT(fld,name) \
1426   buff[0] = 0; \
1427   if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \
1428     WARN("buffer too small for " #fld "\n"); \
1429   else \
1430     if (buff[0]) lpChars->name = buff[0]; \
1431   TRACE("lcid 0x%lx, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name)
1432
1433 /* Get the valid number characters for an lcid */
1434 void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
1435 {
1436   static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',',','$',0,'.',',' };
1437   LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
1438   WCHAR buff[4];
1439
1440   memcpy(lpChars, &defaultChars, sizeof(defaultChars));
1441   GET_NUMBER_TEXT(LOCALE_SNEGATIVESIGN, cNegativeSymbol);
1442   GET_NUMBER_TEXT(LOCALE_SPOSITIVESIGN, cPositiveSymbol);
1443   GET_NUMBER_TEXT(LOCALE_SDECIMAL, cDecimalPoint);
1444   GET_NUMBER_TEXT(LOCALE_STHOUSAND, cDigitSeperator);
1445   GET_NUMBER_TEXT(LOCALE_SMONDECIMALSEP, cCurrencyDecimalPoint);
1446   GET_NUMBER_TEXT(LOCALE_SMONTHOUSANDSEP, cCurrencyDigitSeperator);
1447
1448   /* Local currency symbols are often 2 characters */
1449   lpChars->cCurrencyLocal2 = '\0';
1450   switch(GetLocaleInfoW(lcid, lctype|LOCALE_SCURRENCY, buff, sizeof(buff)/sizeof(WCHAR)))
1451   {
1452     case 3: lpChars->cCurrencyLocal2 = buff[1]; /* Fall through */
1453     case 2: lpChars->cCurrencyLocal  = buff[0];
1454             break;
1455     default: WARN("buffer too small for LOCALE_SCURRENCY\n");
1456   }
1457   TRACE("lcid 0x%lx, cCurrencyLocal =%d,%d '%c','%c'\n", lcid, lpChars->cCurrencyLocal,
1458         lpChars->cCurrencyLocal2, lpChars->cCurrencyLocal, lpChars->cCurrencyLocal2);
1459 }
1460
1461 /* Number Parsing States */
1462 #define B_PROCESSING_EXPONENT 0x1
1463 #define B_NEGATIVE_EXPONENT   0x2
1464 #define B_EXPONENT_START      0x4
1465 #define B_INEXACT_ZEROS       0x8
1466 #define B_LEADING_ZERO        0x10
1467 #define B_PROCESSING_HEX      0x20
1468 #define B_PROCESSING_OCT      0x40
1469
1470 /**********************************************************************
1471  *              VarParseNumFromStr [OLEAUT32.46]
1472  *
1473  * Parse a string containing a number into a NUMPARSE structure.
1474  *
1475  * PARAMS
1476  *  lpszStr [I]   String to parse number from
1477  *  lcid    [I]   Locale Id for the conversion
1478  *  dwFlags [I]   0, or LOCALE_NOUSEROVERRIDE to use system default number chars
1479  *  pNumprs [I/O] Destination for parsed number
1480  *  rgbDig  [O]   Destination for digits read in
1481  *
1482  * RETURNS
1483  *  Success: S_OK. pNumprs and rgbDig contain the parsed representation of
1484  *           the number.
1485  *  Failure: E_INVALIDARG, if any parameter is invalid.
1486  *           DISP_E_TYPEMISMATCH, if the string is not a number or is formatted
1487  *           incorrectly.
1488  *           DISP_E_OVERFLOW, if rgbDig is too small to hold the number.
1489  *
1490  * NOTES
1491  *  pNumprs must have the following fields set:
1492  *   cDig: Set to the size of rgbDig.
1493  *   dwInFlags: Set to the allowable syntax of the number using NUMPRS_ flags
1494  *            from "oleauto.h".
1495  *
1496  * FIXME
1497  *  - I am unsure if this function should parse non-arabic (e.g. Thai)
1498  *   numerals, so this has not been implemented.
1499  */
1500 HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
1501                                   NUMPARSE *pNumprs, BYTE *rgbDig)
1502 {
1503   VARIANT_NUMBER_CHARS chars;
1504   BYTE rgbTmp[1024];
1505   DWORD dwState = B_EXPONENT_START|B_INEXACT_ZEROS;
1506   int iMaxDigits = sizeof(rgbTmp) / sizeof(BYTE);
1507   int cchUsed = 0;
1508
1509   TRACE("(%s,%ld,0x%08lx,%p,%p)\n", debugstr_w(lpszStr), lcid, dwFlags, pNumprs, rgbDig);
1510
1511   if (!pNumprs || !rgbDig)
1512     return E_INVALIDARG;
1513
1514   if (pNumprs->cDig < iMaxDigits)
1515     iMaxDigits = pNumprs->cDig;
1516
1517   pNumprs->cDig = 0;
1518   pNumprs->dwOutFlags = 0;
1519   pNumprs->cchUsed = 0;
1520   pNumprs->nBaseShift = 0;
1521   pNumprs->nPwr10 = 0;
1522
1523   if (!lpszStr)
1524     return DISP_E_TYPEMISMATCH;
1525
1526   VARIANT_GetLocalisedNumberChars(&chars, lcid, dwFlags);
1527
1528   /* First consume all the leading symbols and space from the string */
1529   while (1)
1530   {
1531     if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && isspaceW(*lpszStr))
1532     {
1533       pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE;
1534       do
1535       {
1536         cchUsed++;
1537         lpszStr++;
1538       } while (isspaceW(*lpszStr));
1539     }
1540     else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS &&
1541              *lpszStr == chars.cPositiveSymbol &&
1542              !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS))
1543     {
1544       pNumprs->dwOutFlags |= NUMPRS_LEADING_PLUS;
1545       cchUsed++;
1546       lpszStr++;
1547     }
1548     else if (pNumprs->dwInFlags & NUMPRS_LEADING_MINUS &&
1549              *lpszStr == chars.cNegativeSymbol &&
1550              !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS))
1551     {
1552       pNumprs->dwOutFlags |= (NUMPRS_LEADING_MINUS|NUMPRS_NEG);
1553       cchUsed++;
1554       lpszStr++;
1555     }
1556     else if (pNumprs->dwInFlags & NUMPRS_CURRENCY &&
1557              !(pNumprs->dwOutFlags & NUMPRS_CURRENCY) &&
1558              *lpszStr == chars.cCurrencyLocal &&
1559              (!chars.cCurrencyLocal2 || lpszStr[1] == chars.cCurrencyLocal2))
1560     {
1561       pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
1562       cchUsed++;
1563       lpszStr++;
1564       /* Only accept currency characters */
1565       chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
1566       chars.cDigitSeperator = chars.cCurrencyDigitSeperator;
1567     }
1568     else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
1569              !(pNumprs->dwOutFlags & NUMPRS_PARENS))
1570     {
1571       pNumprs->dwOutFlags |= NUMPRS_PARENS;
1572       cchUsed++;
1573       lpszStr++;
1574     }
1575     else
1576       break;
1577   }
1578
1579   if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY))
1580   {
1581     /* Only accept non-currency characters */
1582     chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
1583     chars.cCurrencyDigitSeperator = chars.cDigitSeperator;
1584   }
1585
1586   if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
1587     pNumprs->dwInFlags & NUMPRS_HEX_OCT)
1588   {
1589       dwState |= B_PROCESSING_HEX;
1590       pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
1591       cchUsed=cchUsed+2;
1592       lpszStr=lpszStr+2;
1593   }
1594   else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
1595     pNumprs->dwInFlags & NUMPRS_HEX_OCT)
1596   {
1597       dwState |= B_PROCESSING_OCT;
1598       pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
1599       cchUsed=cchUsed+2;
1600       lpszStr=lpszStr+2;
1601   }
1602
1603   /* Strip Leading zeros */
1604   while (*lpszStr == '0')
1605   {
1606     dwState |= B_LEADING_ZERO;
1607     cchUsed++;
1608     lpszStr++;
1609   }
1610
1611   while (*lpszStr)
1612   {
1613     if (isdigitW(*lpszStr))
1614     {
1615       if (dwState & B_PROCESSING_EXPONENT)
1616       {
1617         int exponentSize = 0;
1618         if (dwState & B_EXPONENT_START)
1619         {
1620           while (*lpszStr == '0')
1621           {
1622             /* Skip leading zero's in the exponent */
1623             cchUsed++;
1624             lpszStr++;
1625           }
1626           if (!isdigitW(*lpszStr))
1627             break; /* No exponent digits - invalid */
1628         }
1629
1630         while (isdigitW(*lpszStr))
1631         {
1632           exponentSize *= 10;
1633           exponentSize += *lpszStr - '0';
1634           cchUsed++;
1635           lpszStr++;
1636         }
1637         if (dwState & B_NEGATIVE_EXPONENT)
1638           exponentSize = -exponentSize;
1639         /* Add the exponent into the powers of 10 */
1640         pNumprs->nPwr10 += exponentSize;
1641         dwState &= ~(B_PROCESSING_EXPONENT|B_EXPONENT_START);
1642         lpszStr--; /* back up to allow processing of next char */
1643       }
1644       else
1645       {
1646         if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
1647           && !(dwState & B_PROCESSING_OCT))
1648         {
1649           pNumprs->dwOutFlags |= NUMPRS_INEXACT;
1650
1651           if (*lpszStr != '0')
1652             dwState &= ~B_INEXACT_ZEROS; /* Inexact number with non-trailing zeros */
1653
1654           /* This digit can't be represented, but count it in nPwr10 */
1655           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
1656             pNumprs->nPwr10--;
1657           else
1658             pNumprs->nPwr10++;
1659         }
1660         else
1661         {
1662           if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
1663             return DISP_E_TYPEMISMATCH;
1664           }
1665
1666           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
1667             pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
1668
1669           rgbTmp[pNumprs->cDig] = *lpszStr - '0';
1670         }
1671         pNumprs->cDig++;
1672         cchUsed++;
1673       }
1674     }
1675     else if (*lpszStr == chars.cDigitSeperator && pNumprs->dwInFlags & NUMPRS_THOUSANDS)
1676     {
1677       pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
1678       cchUsed++;
1679     }
1680     else if (*lpszStr == chars.cDecimalPoint &&
1681              pNumprs->dwInFlags & NUMPRS_DECIMAL &&
1682              !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
1683     {
1684       pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
1685       cchUsed++;
1686
1687       /* Remove trailing zeros from the whole number part */
1688       while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
1689       {
1690         pNumprs->nPwr10++;
1691         pNumprs->cDig--;
1692       }
1693
1694       /* If we have no digits so far, skip leading zeros */
1695       if (!pNumprs->cDig)
1696       {
1697         while (lpszStr[1] == '0')
1698         {
1699           dwState |= B_LEADING_ZERO;
1700           cchUsed++;
1701           lpszStr++;
1702         }
1703       }
1704     }
1705     else if ((*lpszStr == 'e' || *lpszStr == 'E') &&
1706              pNumprs->dwInFlags & NUMPRS_EXPONENT &&
1707              !(pNumprs->dwOutFlags & NUMPRS_EXPONENT))
1708     {
1709       dwState |= B_PROCESSING_EXPONENT;
1710       pNumprs->dwOutFlags |= NUMPRS_EXPONENT;
1711       cchUsed++;
1712     }
1713     else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cPositiveSymbol)
1714     {
1715       cchUsed++; /* Ignore positive exponent */
1716     }
1717     else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cNegativeSymbol)
1718     {
1719       dwState |= B_NEGATIVE_EXPONENT;
1720       cchUsed++;
1721     }
1722     else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
1723              (*lpszStr >= 'A' && *lpszStr <= 'F')) &&
1724              dwState & B_PROCESSING_HEX)
1725     {
1726       if (pNumprs->cDig >= iMaxDigits)
1727       {
1728         return DISP_E_OVERFLOW;
1729       }
1730       else
1731       {
1732         if (*lpszStr >= 'a')
1733           rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
1734         else
1735           rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
1736       }
1737       pNumprs->cDig++;
1738       cchUsed++;
1739     }
1740     else
1741       break; /* Stop at an unrecognised character */
1742
1743     lpszStr++;
1744   }
1745
1746   if (!pNumprs->cDig && dwState & B_LEADING_ZERO)
1747   {
1748     /* Ensure a 0 on its own gets stored */
1749     pNumprs->cDig = 1;
1750     rgbTmp[0] = 0;
1751   }
1752
1753   if (pNumprs->dwOutFlags & NUMPRS_EXPONENT && dwState & B_PROCESSING_EXPONENT)
1754   {
1755     pNumprs->cchUsed = cchUsed;
1756     return DISP_E_TYPEMISMATCH; /* Failed to completely parse the exponent */
1757   }
1758
1759   if (pNumprs->dwOutFlags & NUMPRS_INEXACT)
1760   {
1761     if (dwState & B_INEXACT_ZEROS)
1762       pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* All zeros doesn't set NUMPRS_INEXACT */
1763   } else if(pNumprs->dwInFlags & NUMPRS_HEX_OCT)
1764   {
1765     /* copy all of the digits into the output digit buffer */
1766     /* this is exactly what windows does although it also returns */
1767     /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
1768     memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
1769
1770     if (dwState & B_PROCESSING_HEX) {
1771       /* hex numbers have always the same format */
1772       pNumprs->nPwr10=0;
1773       pNumprs->nBaseShift=4;
1774     } else {
1775       if (dwState & B_PROCESSING_OCT) {
1776         /* oct numbers have always the same format */
1777         pNumprs->nPwr10=0;
1778         pNumprs->nBaseShift=3;
1779       } else {
1780         while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
1781         {
1782           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
1783             pNumprs->nPwr10--;
1784           else
1785             pNumprs->nPwr10++;
1786
1787           pNumprs->cDig--;
1788         }
1789       }
1790     }
1791   } else
1792   {
1793     /* Remove trailing zeros from the last (whole number or decimal) part */
1794     while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
1795     {
1796       if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
1797         pNumprs->nPwr10--;
1798       else
1799         pNumprs->nPwr10++;
1800
1801       pNumprs->cDig--;
1802     }
1803   }
1804
1805   if (pNumprs->cDig <= iMaxDigits)
1806     pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* Ignore stripped zeros for NUMPRS_INEXACT */
1807   else
1808     pNumprs->cDig = iMaxDigits; /* Only return iMaxDigits worth of digits */
1809
1810   /* Copy the digits we processed into rgbDig */
1811   memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
1812
1813   /* Consume any trailing symbols and space */
1814   while (1)
1815   {
1816     if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && isspaceW(*lpszStr))
1817     {
1818       pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE;
1819       do
1820       {
1821         cchUsed++;
1822         lpszStr++;
1823       } while (isspaceW(*lpszStr));
1824     }
1825     else if (pNumprs->dwInFlags & NUMPRS_TRAILING_PLUS &&
1826              !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS) &&
1827              *lpszStr == chars.cPositiveSymbol)
1828     {
1829       pNumprs->dwOutFlags |= NUMPRS_TRAILING_PLUS;
1830       cchUsed++;
1831       lpszStr++;
1832     }
1833     else if (pNumprs->dwInFlags & NUMPRS_TRAILING_MINUS &&
1834              !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS) &&
1835              *lpszStr == chars.cNegativeSymbol)
1836     {
1837       pNumprs->dwOutFlags |= (NUMPRS_TRAILING_MINUS|NUMPRS_NEG);
1838       cchUsed++;
1839       lpszStr++;
1840     }
1841     else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == ')' &&
1842              pNumprs->dwOutFlags & NUMPRS_PARENS)
1843     {
1844       cchUsed++;
1845       lpszStr++;
1846       pNumprs->dwOutFlags |= NUMPRS_NEG;
1847     }
1848     else
1849       break;
1850   }
1851
1852   if (pNumprs->dwOutFlags & NUMPRS_PARENS && !(pNumprs->dwOutFlags & NUMPRS_NEG))
1853   {
1854     pNumprs->cchUsed = cchUsed;
1855     return DISP_E_TYPEMISMATCH; /* Opening parenthesis not matched */
1856   }
1857
1858   if (pNumprs->dwInFlags & NUMPRS_USE_ALL && *lpszStr != '\0')
1859     return DISP_E_TYPEMISMATCH; /* Not all chars were consumed */
1860
1861   if (!pNumprs->cDig)
1862     return DISP_E_TYPEMISMATCH; /* No Number found */
1863
1864   pNumprs->cchUsed = cchUsed;
1865   return S_OK;
1866 }
1867
1868 /* VTBIT flags indicating an integer value */
1869 #define INTEGER_VTBITS (VTBIT_I1|VTBIT_UI1|VTBIT_I2|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_I8|VTBIT_UI8)
1870 /* VTBIT flags indicating a real number value */
1871 #define REAL_VTBITS (VTBIT_R4|VTBIT_R8|VTBIT_CY)
1872
1873 /**********************************************************************
1874  *              VarNumFromParseNum [OLEAUT32.47]
1875  *
1876  * Convert a NUMPARSE structure into a numeric Variant type.
1877  *
1878  * PARAMS
1879  *  pNumprs  [I] Source for parsed number. cDig must be set to the size of rgbDig
1880  *  rgbDig   [I] Source for the numbers digits
1881  *  dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types
1882  *  pVarDst  [O] Destination for the converted Variant value.
1883  *
1884  * RETURNS
1885  *  Success: S_OK. pVarDst contains the converted value.
1886  *  Failure: E_INVALIDARG, if any parameter is invalid.
1887  *           DISP_E_OVERFLOW, if the number is too big for the types set in dwVtBits.
1888  *
1889  * NOTES
1890  *  - The smallest favoured type present in dwVtBits that can represent the
1891  *    number in pNumprs without losing precision is used.
1892  *  - Signed types are preferrred over unsigned types of the same size.
1893  *  - Preferred types in order are: integer, float, double, currency then decimal.
1894  *  - Rounding (dropping of decimal points) occurs without error. See VarI8FromR8()
1895  *    for details of the rounding method.
1896  *  - pVarDst is not cleared before the result is stored in it.
1897  */
1898 HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
1899                                   ULONG dwVtBits, VARIANT *pVarDst)
1900 {
1901   /* Scale factors and limits for double arithmetic */
1902   static const double dblMultipliers[11] = {
1903     1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0,
1904     1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0
1905   };
1906   static const double dblMinimums[11] = {
1907     R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0,
1908     R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0,
1909     R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0
1910   };
1911   static const double dblMaximums[11] = {
1912     R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0,
1913     R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0,
1914     R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0
1915   };
1916
1917   int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0;
1918
1919   TRACE("(%p,%p,0x%lx,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst);
1920
1921   if (pNumprs->nBaseShift)
1922   {
1923     /* nBaseShift indicates a hex or octal number */
1924     ULONG64 ul64 = 0;
1925     LONG64 l64;
1926     int i;
1927
1928     /* Convert the hex or octal number string into a UI64 */
1929     for (i = 0; i < pNumprs->cDig; i++)
1930     {
1931       if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
1932       {
1933         TRACE("Overflow multiplying digits\n");
1934         return DISP_E_OVERFLOW;
1935       }
1936       ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
1937     }
1938
1939     /* also make a negative representation */
1940     l64=-ul64;
1941
1942     /* Try signed and unsigned types in size order */
1943     if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN)))
1944     {
1945       V_VT(pVarDst) = VT_I1;
1946       if (ul64 <= I1_MAX)
1947           V_I1(pVarDst) = ul64;
1948       else
1949           V_I1(pVarDst) = l64;
1950       return S_OK;
1951     }
1952     else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
1953     {
1954       V_VT(pVarDst) = VT_UI1;
1955       V_UI1(pVarDst) = ul64;
1956       return S_OK;
1957     }
1958     else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN)))
1959     {
1960       V_VT(pVarDst) = VT_I2;
1961       if (ul64 <= I2_MAX)
1962           V_I2(pVarDst) = ul64;
1963       else
1964           V_I2(pVarDst) = l64;
1965       return S_OK;
1966     }
1967     else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
1968     {
1969       V_VT(pVarDst) = VT_UI2;
1970       V_UI2(pVarDst) = ul64;
1971       return S_OK;
1972     }
1973     else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
1974     {
1975       V_VT(pVarDst) = VT_I4;
1976       if (ul64 <= I4_MAX)
1977           V_I4(pVarDst) = ul64;
1978       else
1979           V_I4(pVarDst) = l64;
1980       return S_OK;
1981     }
1982     else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
1983     {
1984       V_VT(pVarDst) = VT_UI4;
1985       V_UI4(pVarDst) = ul64;
1986       return S_OK;
1987     }
1988     else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN)))
1989     {
1990       V_VT(pVarDst) = VT_I8;
1991       V_I8(pVarDst) = ul64;
1992       return S_OK;
1993     }
1994     else if (dwVtBits & VTBIT_UI8)
1995     {
1996       V_VT(pVarDst) = VT_UI8;
1997       V_UI8(pVarDst) = ul64;
1998       return S_OK;
1999     }
2000     else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
2001     {
2002       V_VT(pVarDst) = VT_DECIMAL;
2003       DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
2004       DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
2005       DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
2006       return S_OK;
2007     }
2008     else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
2009     {
2010       V_VT(pVarDst) = VT_R4;
2011       if (ul64 <= I4_MAX)
2012           V_R4(pVarDst) = ul64;
2013       else
2014           V_R4(pVarDst) = l64;
2015       return S_OK;
2016     }
2017     else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
2018     {
2019       V_VT(pVarDst) = VT_R8;
2020       if (ul64 <= I4_MAX)
2021           V_R8(pVarDst) = ul64;
2022       else
2023           V_R8(pVarDst) = l64;
2024       return S_OK;
2025     }
2026
2027     TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
2028     return DISP_E_OVERFLOW;
2029   }
2030
2031   /* Count the number of relevant fractional and whole digits stored,
2032    * And compute the divisor/multiplier to scale the number by.
2033    */
2034   if (pNumprs->nPwr10 < 0)
2035   {
2036     if (-pNumprs->nPwr10 >= pNumprs->cDig)
2037     {
2038       /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
2039       wholeNumberDigits = 0;
2040       fractionalDigits = pNumprs->cDig;
2041       divisor10 = -pNumprs->nPwr10;
2042     }
2043     else
2044     {
2045       /* An exactly represented real number e.g. 1.024 */
2046       wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10;
2047       fractionalDigits = pNumprs->cDig - wholeNumberDigits;
2048       divisor10 = pNumprs->cDig - wholeNumberDigits;
2049     }
2050   }
2051   else if (pNumprs->nPwr10 == 0)
2052   {
2053     /* An exactly represented whole number e.g. 1024 */
2054     wholeNumberDigits = pNumprs->cDig;
2055     fractionalDigits = 0;
2056   }
2057   else /* pNumprs->nPwr10 > 0 */
2058   {
2059     /* A whole number followed by nPwr10 0's e.g. 102400 */
2060     wholeNumberDigits = pNumprs->cDig;
2061     fractionalDigits = 0;
2062     multiplier10 = pNumprs->nPwr10;
2063   }
2064
2065   TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", pNumprs->cDig,
2066         pNumprs->nPwr10, wholeNumberDigits, fractionalDigits);
2067   TRACE("mult %d; div %d\n", multiplier10, divisor10);
2068
2069   if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) &&
2070       (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL))))
2071   {
2072     /* We have one or more integer output choices, and either:
2073      *  1) An integer input value, or
2074      *  2) A real number input value but no floating output choices.
2075      * Alternately, we have a DECIMAL output available and an integer input.
2076      *
2077      * So, place the integer value into pVarDst, using the smallest type
2078      * possible and preferring signed over unsigned types.
2079      */
2080     BOOL bOverflow = FALSE, bNegative;
2081     ULONG64 ul64 = 0;
2082     int i;
2083
2084     /* Convert the integer part of the number into a UI8 */
2085     for (i = 0; i < wholeNumberDigits; i++)
2086     {
2087       if (ul64 > (UI8_MAX / 10 - rgbDig[i]))
2088       {
2089         TRACE("Overflow multiplying digits\n");
2090         bOverflow = TRUE;
2091         break;
2092       }
2093       ul64 = ul64 * 10 + rgbDig[i];
2094     }
2095
2096     /* Account for the scale of the number */
2097     if (!bOverflow && multiplier10)
2098     {
2099       for (i = 0; i < multiplier10; i++)
2100       {
2101         if (ul64 > (UI8_MAX / 10))
2102         {
2103           TRACE("Overflow scaling number\n");
2104           bOverflow = TRUE;
2105           break;
2106         }
2107         ul64 = ul64 * 10;
2108       }
2109     }
2110
2111     /* If we have any fractional digits, round the value.
2112      * Note we don't have to do this if divisor10 is < 1,
2113      * because this means the fractional part must be < 0.5
2114      */
2115     if (!bOverflow && fractionalDigits && divisor10 > 0)
2116     {
2117       const BYTE* fracDig = rgbDig + wholeNumberDigits;
2118       BOOL bAdjust = FALSE;
2119
2120       TRACE("first decimal value is %d\n", *fracDig);
2121
2122       if (*fracDig > 5)
2123         bAdjust = TRUE; /* > 0.5 */
2124       else if (*fracDig == 5)
2125       {
2126         for (i = 1; i < fractionalDigits; i++)
2127         {
2128           if (fracDig[i])
2129           {
2130             bAdjust = TRUE; /* > 0.5 */
2131             break;
2132           }
2133         }
2134         /* If exactly 0.5, round only odd values */
2135         if (i == fractionalDigits && (ul64 & 1))
2136           bAdjust = TRUE;
2137       }
2138
2139       if (bAdjust)
2140       {
2141         if (ul64 == UI8_MAX)
2142         {
2143           TRACE("Overflow after rounding\n");
2144           bOverflow = TRUE;
2145         }
2146         ul64++;
2147       }
2148     }
2149
2150     /* Zero is not a negative number */
2151     bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64 ? TRUE : FALSE;
2152
2153     TRACE("Integer value is %lld, bNeg %d\n", ul64, bNegative);
2154
2155     /* For negative integers, try the signed types in size order */
2156     if (!bOverflow && bNegative)
2157     {
2158       if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8))
2159       {
2160         if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN)
2161         {
2162           V_VT(pVarDst) = VT_I1;
2163           V_I1(pVarDst) = -ul64;
2164           return S_OK;
2165         }
2166         else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN)
2167         {
2168           V_VT(pVarDst) = VT_I2;
2169           V_I2(pVarDst) = -ul64;
2170           return S_OK;
2171         }
2172         else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN))
2173         {
2174           V_VT(pVarDst) = VT_I4;
2175           V_I4(pVarDst) = -ul64;
2176           return S_OK;
2177         }
2178         else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1)
2179         {
2180           V_VT(pVarDst) = VT_I8;
2181           V_I8(pVarDst) = -ul64;
2182           return S_OK;
2183         }
2184         else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
2185         {
2186           /* Decimal is only output choice left - fast path */
2187           V_VT(pVarDst) = VT_DECIMAL;
2188           DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
2189           DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
2190           DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
2191           return S_OK;
2192         }
2193       }
2194     }
2195     else if (!bOverflow)
2196     {
2197       /* For positive integers, try signed then unsigned types in size order */
2198       if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX)
2199       {
2200         V_VT(pVarDst) = VT_I1;
2201         V_I1(pVarDst) = ul64;
2202         return S_OK;
2203       }
2204       else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
2205       {
2206         V_VT(pVarDst) = VT_UI1;
2207         V_UI1(pVarDst) = ul64;
2208         return S_OK;
2209       }
2210       else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
2211       {
2212         V_VT(pVarDst) = VT_I2;
2213         V_I2(pVarDst) = ul64;
2214         return S_OK;
2215       }
2216       else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
2217       {
2218         V_VT(pVarDst) = VT_UI2;
2219         V_UI2(pVarDst) = ul64;
2220         return S_OK;
2221       }
2222       else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
2223       {
2224         V_VT(pVarDst) = VT_I4;
2225         V_I4(pVarDst) = ul64;
2226         return S_OK;
2227       }
2228       else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
2229       {
2230         V_VT(pVarDst) = VT_UI4;
2231         V_UI4(pVarDst) = ul64;
2232         return S_OK;
2233       }
2234       else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
2235       {
2236         V_VT(pVarDst) = VT_I8;
2237         V_I8(pVarDst) = ul64;
2238         return S_OK;
2239       }
2240       else if (dwVtBits & VTBIT_UI8)
2241       {
2242         V_VT(pVarDst) = VT_UI8;
2243         V_UI8(pVarDst) = ul64;
2244         return S_OK;
2245       }
2246       else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
2247       {
2248         /* Decimal is only output choice left - fast path */
2249         V_VT(pVarDst) = VT_DECIMAL;
2250         DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
2251         DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
2252         DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
2253         return S_OK;
2254       }
2255     }
2256   }
2257
2258   if (dwVtBits & REAL_VTBITS)
2259   {
2260     /* Try to put the number into a float or real */
2261     BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG;
2262     double whole = 0.0;
2263     int i;
2264
2265     /* Convert the number into a double */
2266     for (i = 0; i < pNumprs->cDig; i++)
2267       whole = whole * 10.0 + rgbDig[i];
2268
2269     TRACE("Whole double value is %16.16g\n", whole);
2270
2271     /* Account for the scale */
2272     while (multiplier10 > 10)
2273     {
2274       if (whole > dblMaximums[10])
2275       {
2276         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
2277         bOverflow = TRUE;
2278         break;
2279       }
2280       whole = whole * dblMultipliers[10];
2281       multiplier10 -= 10;
2282     }
2283     if (multiplier10)
2284     {
2285       if (whole > dblMaximums[multiplier10])
2286       {
2287         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
2288         bOverflow = TRUE;
2289       }
2290       else
2291         whole = whole * dblMultipliers[multiplier10];
2292     }
2293
2294     TRACE("Scaled double value is %16.16g\n", whole);
2295
2296     while (divisor10 > 10)
2297     {
2298       if (whole < dblMinimums[10])
2299       {
2300         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
2301         bOverflow = TRUE;
2302         break;
2303       }
2304       whole = whole / dblMultipliers[10];
2305       divisor10 -= 10;
2306     }
2307     if (divisor10)
2308     {
2309       if (whole < dblMinimums[divisor10])
2310       {
2311         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
2312         bOverflow = TRUE;
2313       }
2314       else
2315         whole = whole / dblMultipliers[divisor10];
2316     }
2317     if (!bOverflow)
2318       TRACE("Final double value is %16.16g\n", whole);
2319
2320     if (dwVtBits & VTBIT_R4 &&
2321         ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0))
2322     {
2323       TRACE("Set R4 to final value\n");
2324       V_VT(pVarDst) = VT_R4; /* Fits into a float */
2325       V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
2326       return S_OK;
2327     }
2328
2329     if (dwVtBits & VTBIT_R8)
2330     {
2331       TRACE("Set R8 to final value\n");
2332       V_VT(pVarDst) = VT_R8; /* Fits into a double */
2333       V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
2334       return S_OK;
2335     }
2336
2337     if (dwVtBits & VTBIT_CY)
2338     {
2339       if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst))))
2340       {
2341         V_VT(pVarDst) = VT_CY; /* Fits into a currency */
2342         TRACE("Set CY to final value\n");
2343         return S_OK;
2344       }
2345       TRACE("Value Overflows CY\n");
2346     }
2347   }
2348
2349   if (dwVtBits & VTBIT_DECIMAL)
2350   {
2351     int i;
2352     ULONG carry;
2353     ULONG64 tmp;
2354     DECIMAL* pDec = &V_DECIMAL(pVarDst);
2355
2356     DECIMAL_SETZERO(pDec);
2357     DEC_LO32(pDec) = 0;
2358
2359     if (pNumprs->dwOutFlags & NUMPRS_NEG)
2360       DEC_SIGN(pDec) = DECIMAL_NEG;
2361     else
2362       DEC_SIGN(pDec) = DECIMAL_POS;
2363
2364     /* Factor the significant digits */
2365     for (i = 0; i < pNumprs->cDig; i++)
2366     {
2367       tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
2368       carry = (ULONG)(tmp >> 32);
2369       DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
2370       tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
2371       carry = (ULONG)(tmp >> 32);
2372       DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
2373       tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
2374       DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
2375
2376       if (tmp >> 32 & UI4_MAX)
2377       {
2378 VarNumFromParseNum_DecOverflow:
2379         TRACE("Overflow\n");
2380         DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
2381         return DISP_E_OVERFLOW;
2382       }
2383     }
2384
2385     /* Account for the scale of the number */
2386     while (multiplier10 > 0)
2387     {
2388       tmp = (ULONG64)DEC_LO32(pDec) * 10;
2389       carry = (ULONG)(tmp >> 32);
2390       DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
2391       tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
2392       carry = (ULONG)(tmp >> 32);
2393       DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
2394       tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
2395       DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
2396
2397       if (tmp >> 32 & UI4_MAX)
2398         goto VarNumFromParseNum_DecOverflow;
2399       multiplier10--;
2400     }
2401     DEC_SCALE(pDec) = divisor10;
2402
2403     V_VT(pVarDst) = VT_DECIMAL;
2404     return S_OK;
2405   }
2406   return DISP_E_OVERFLOW; /* No more output choices */
2407 }
2408
2409 /**********************************************************************
2410  *              VarCat [OLEAUT32.318]
2411  */
2412 HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
2413 {
2414     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
2415           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), out);
2416
2417     /* Should we VariantClear out? */
2418     /* Can we handle array, vector, by ref etc. */
2419     if ((V_VT(left)&VT_TYPEMASK) == VT_NULL &&
2420         (V_VT(right)&VT_TYPEMASK) == VT_NULL)
2421     {
2422         V_VT(out) = VT_NULL;
2423         return S_OK;
2424     }
2425
2426     if (V_VT(left) == VT_BSTR && V_VT(right) == VT_BSTR)
2427     {
2428         V_VT(out) = VT_BSTR;
2429         VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out));
2430         return S_OK;
2431     }
2432     if (V_VT(left) == VT_BSTR) {
2433         VARIANT bstrvar;
2434         HRESULT hres;
2435
2436         V_VT(out) = VT_BSTR;
2437         hres = VariantChangeTypeEx(&bstrvar,right,0,0,VT_BSTR);
2438         if (hres) {
2439             FIXME("Failed to convert right side from vt %d to VT_BSTR?\n",V_VT(right));
2440             return hres;
2441         }
2442         VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar), &V_BSTR(out));
2443         return S_OK;
2444     }
2445     if (V_VT(right) == VT_BSTR) {
2446         VARIANT bstrvar;
2447         HRESULT hres;
2448
2449         V_VT(out) = VT_BSTR;
2450         hres = VariantChangeTypeEx(&bstrvar,left,0,0,VT_BSTR);
2451         if (hres) {
2452             FIXME("Failed to convert right side from vt %d to VT_BSTR?\n",V_VT(right));
2453             return hres;
2454         }
2455         VarBstrCat (V_BSTR(&bstrvar), V_BSTR(right), &V_BSTR(out));
2456         return S_OK;
2457     }
2458     FIXME ("types %d / %d not supported\n",V_VT(left)&VT_TYPEMASK, V_VT(right)&VT_TYPEMASK);
2459     return S_OK;
2460 }
2461
2462 /**********************************************************************
2463  *              VarCmp [OLEAUT32.176]
2464  *
2465  * flags can be:
2466  *   NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS
2467  *   NORM_IGNOREWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA
2468  *
2469  */
2470 HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
2471 {
2472     BOOL        lOk        = TRUE;
2473     BOOL        rOk        = TRUE;
2474     LONGLONG    lVal = -1;
2475     LONGLONG    rVal = -1;
2476     VARIANT     rv,lv;
2477     DWORD       xmask;
2478     HRESULT     rc;
2479
2480     TRACE("(%p->(%s%s),%p->(%s%s),0x%08lx,0x%08lx)\n", left, debugstr_VT(left),
2481           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), lcid, flags);
2482
2483     VariantInit(&lv);VariantInit(&rv);
2484     V_VT(right) &= ~0x8000; /* hack since we sometime get this flag.  */
2485     V_VT(left) &= ~0x8000; /* hack since we sometime get this flag. */
2486
2487     /* If either are null, then return VARCMP_NULL */
2488     if ((V_VT(left)&VT_TYPEMASK) == VT_NULL ||
2489         (V_VT(right)&VT_TYPEMASK) == VT_NULL)
2490         return VARCMP_NULL;
2491
2492     /* Strings - use VarBstrCmp */
2493     if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR &&
2494         (V_VT(right)&VT_TYPEMASK) == VT_BSTR) {
2495         return VarBstrCmp(V_BSTR(left), V_BSTR(right), lcid, flags);
2496     }
2497
2498     xmask = (1<<(V_VT(left)&VT_TYPEMASK))|(1<<(V_VT(right)&VT_TYPEMASK));
2499     if (xmask & (1<<VT_R8)) {
2500         rc = VariantChangeType(&lv,left,0,VT_R8);
2501         if (FAILED(rc)) return rc;
2502         rc = VariantChangeType(&rv,right,0,VT_R8);
2503         if (FAILED(rc)) return rc;
2504
2505         if (V_R8(&lv) == V_R8(&rv)) return VARCMP_EQ;
2506         if (V_R8(&lv) < V_R8(&rv)) return VARCMP_LT;
2507         if (V_R8(&lv) > V_R8(&rv)) return VARCMP_GT;
2508         return E_FAIL; /* can't get here */
2509     }
2510     if (xmask & (1<<VT_R4)) {
2511         rc = VariantChangeType(&lv,left,0,VT_R4);
2512         if (FAILED(rc)) return rc;
2513         rc = VariantChangeType(&rv,right,0,VT_R4);
2514         if (FAILED(rc)) return rc;
2515
2516         if (V_R4(&lv) == V_R4(&rv)) return VARCMP_EQ;
2517         if (V_R4(&lv) < V_R4(&rv)) return VARCMP_LT;
2518         if (V_R4(&lv) > V_R4(&rv)) return VARCMP_GT;
2519         return E_FAIL; /* can't get here */
2520     }
2521
2522     /* Integers - Ideally like to use VarDecCmp, but no Dec support yet
2523            Use LONGLONG to maximize ranges                              */
2524     lOk = TRUE;
2525     switch (V_VT(left)&VT_TYPEMASK) {
2526     case VT_I1   : lVal = V_UNION(left,cVal); break;
2527     case VT_I2   : lVal = V_UNION(left,iVal); break;
2528     case VT_I4   : lVal = V_UNION(left,lVal); break;
2529     case VT_INT  : lVal = V_UNION(left,lVal); break;
2530     case VT_UI1  : lVal = V_UNION(left,bVal); break;
2531     case VT_UI2  : lVal = V_UNION(left,uiVal); break;
2532     case VT_UI4  : lVal = V_UNION(left,ulVal); break;
2533     case VT_UINT : lVal = V_UNION(left,ulVal); break;
2534     case VT_BOOL : lVal = V_UNION(left,boolVal); break;
2535     default: lOk = FALSE;
2536     }
2537
2538     rOk = TRUE;
2539     switch (V_VT(right)&VT_TYPEMASK) {
2540     case VT_I1   : rVal = V_UNION(right,cVal); break;
2541     case VT_I2   : rVal = V_UNION(right,iVal); break;
2542     case VT_I4   : rVal = V_UNION(right,lVal); break;
2543     case VT_INT  : rVal = V_UNION(right,lVal); break;
2544     case VT_UI1  : rVal = V_UNION(right,bVal); break;
2545     case VT_UI2  : rVal = V_UNION(right,uiVal); break;
2546     case VT_UI4  : rVal = V_UNION(right,ulVal); break;
2547     case VT_UINT : rVal = V_UNION(right,ulVal); break;
2548     case VT_BOOL : rVal = V_UNION(right,boolVal); break;
2549     default: rOk = FALSE;
2550     }
2551
2552     if (lOk && rOk) {
2553         if (lVal < rVal) {
2554             return VARCMP_LT;
2555         } else if (lVal > rVal) {
2556             return VARCMP_GT;
2557         } else {
2558             return VARCMP_EQ;
2559         }
2560     }
2561
2562     /* Strings - use VarBstrCmp */
2563     if ((V_VT(left)&VT_TYPEMASK) == VT_DATE &&
2564         (V_VT(right)&VT_TYPEMASK) == VT_DATE) {
2565
2566         if (floor(V_UNION(left,date)) == floor(V_UNION(right,date))) {
2567             /* Due to floating point rounding errors, calculate varDate in whole numbers) */
2568             double wholePart = 0.0;
2569             double leftR;
2570             double rightR;
2571
2572             /* Get the fraction * 24*60*60 to make it into whole seconds */
2573             wholePart = (double) floor( V_UNION(left,date) );
2574             if (wholePart == 0) wholePart = 1;
2575             leftR = floor(fmod( V_UNION(left,date), wholePart ) * (24*60*60));
2576
2577             wholePart = (double) floor( V_UNION(right,date) );
2578             if (wholePart == 0) wholePart = 1;
2579             rightR = floor(fmod( V_UNION(right,date), wholePart ) * (24*60*60));
2580
2581             if (leftR < rightR) {
2582                 return VARCMP_LT;
2583             } else if (leftR > rightR) {
2584                 return VARCMP_GT;
2585             } else {
2586                 return VARCMP_EQ;
2587             }
2588
2589         } else if (V_UNION(left,date) < V_UNION(right,date)) {
2590             return VARCMP_LT;
2591         } else if (V_UNION(left,date) > V_UNION(right,date)) {
2592             return VARCMP_GT;
2593         }
2594     }
2595     FIXME("VarCmp partial implementation, doesn't support vt 0x%x / 0x%x\n",V_VT(left), V_VT(right));
2596     return E_FAIL;
2597 }
2598
2599 /**********************************************************************
2600  *              VarAnd [OLEAUT32.142]
2601  *
2602  */
2603 HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
2604 {
2605     HRESULT rc = E_FAIL;
2606
2607     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
2608           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
2609
2610     if ((V_VT(left)&VT_TYPEMASK) == VT_BOOL &&
2611         (V_VT(right)&VT_TYPEMASK) == VT_BOOL) {
2612
2613         V_VT(result) = VT_BOOL;
2614         if (V_BOOL(left) && V_BOOL(right)) {
2615             V_BOOL(result) = VARIANT_TRUE;
2616         } else {
2617             V_BOOL(result) = VARIANT_FALSE;
2618         }
2619         rc = S_OK;
2620
2621     } else {
2622         /* Integers */
2623         BOOL         lOk        = TRUE;
2624         BOOL         rOk        = TRUE;
2625         LONGLONG     lVal = -1;
2626         LONGLONG     rVal = -1;
2627         LONGLONG     res  = -1;
2628         int          resT = 0; /* Testing has shown I2 & I2 == I2, all else
2629                                   becomes I4, even unsigned ints (incl. UI2) */
2630
2631         lOk = TRUE;
2632         switch (V_VT(left)&VT_TYPEMASK) {
2633         case VT_I1   : lVal = V_UNION(left,cVal);  resT=VT_I4; break;
2634         case VT_I2   : lVal = V_UNION(left,iVal);  resT=VT_I2; break;
2635         case VT_I4   : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
2636         case VT_INT  : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
2637         case VT_UI1  : lVal = V_UNION(left,bVal);  resT=VT_I4; break;
2638         case VT_UI2  : lVal = V_UNION(left,uiVal); resT=VT_I4; break;
2639         case VT_UI4  : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
2640         case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
2641         case VT_BOOL : rVal = V_UNION(left,boolVal); resT=VT_I4; break;
2642         default: lOk = FALSE;
2643         }
2644
2645         rOk = TRUE;
2646         switch (V_VT(right)&VT_TYPEMASK) {
2647         case VT_I1   : rVal = V_UNION(right,cVal);  resT=VT_I4; break;
2648         case VT_I2   : rVal = V_UNION(right,iVal);  resT=max(VT_I2, resT); break;
2649         case VT_I4   : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
2650         case VT_INT  : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
2651         case VT_UI1  : rVal = V_UNION(right,bVal);  resT=VT_I4; break;
2652         case VT_UI2  : rVal = V_UNION(right,uiVal); resT=VT_I4; break;
2653         case VT_UI4  : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
2654         case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
2655         case VT_BOOL : rVal = V_UNION(right,boolVal); resT=VT_I4; break;
2656         default: rOk = FALSE;
2657         }
2658
2659         if (lOk && rOk) {
2660             res = (lVal & rVal);
2661             V_VT(result) = resT;
2662             switch (resT) {
2663             case VT_I2   : V_UNION(result,iVal)  = res; break;
2664             case VT_I4   : V_UNION(result,lVal)  = res; break;
2665             default:
2666                 FIXME("Unexpected result variant type %x\n", resT);
2667                 V_UNION(result,lVal)  = res;
2668             }
2669             rc = S_OK;
2670
2671         } else {
2672             FIXME("VarAnd stub\n");
2673         }
2674     }
2675
2676     TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
2677           debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
2678     return rc;
2679 }
2680
2681 /**********************************************************************
2682  *              VarAdd [OLEAUT32.141]
2683  * FIXME: From MSDN: If ... Then
2684  * Both expressions are of the string type Concatenated.
2685  * One expression is a string type and the other a character Addition.
2686  * One expression is numeric and the other is a string Addition.
2687  * Both expressions are numeric Addition.
2688  * Either expression is NULL NULL is returned.
2689  * Both expressions are empty  Integer subtype is returned.
2690  *
2691  */
2692 HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
2693 {
2694     HRESULT rc = E_FAIL;
2695
2696     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
2697           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
2698
2699     if ((V_VT(left)&VT_TYPEMASK) == VT_EMPTY)
2700         return VariantCopy(result,right);
2701
2702     if ((V_VT(right)&VT_TYPEMASK) == VT_EMPTY)
2703         return VariantCopy(result,left);
2704
2705     /* check if we add doubles */
2706     if (((V_VT(left)&VT_TYPEMASK) == VT_R8) || ((V_VT(right)&VT_TYPEMASK) == VT_R8)) {
2707         BOOL         lOk        = TRUE;
2708         BOOL         rOk        = TRUE;
2709         double       lVal = -1;
2710         double       rVal = -1;
2711         double       res  = -1;
2712
2713         lOk = TRUE;
2714         switch (V_VT(left)&VT_TYPEMASK) {
2715         case VT_I1   : lVal = V_UNION(left,cVal);   break;
2716         case VT_I2   : lVal = V_UNION(left,iVal);   break;
2717         case VT_I4   : lVal = V_UNION(left,lVal);   break;
2718         case VT_INT  : lVal = V_UNION(left,lVal);   break;
2719         case VT_UI1  : lVal = V_UNION(left,bVal);   break;
2720         case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
2721         case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
2722         case VT_UINT : lVal = V_UNION(left,ulVal);  break;
2723         case VT_R4   : lVal = V_UNION(left,fltVal);  break;
2724         case VT_R8   : lVal = V_UNION(left,dblVal);  break;
2725         case VT_NULL : lVal = 0.0;  break;
2726         default: lOk = FALSE;
2727         }
2728
2729         rOk = TRUE;
2730         switch (V_VT(right)&VT_TYPEMASK) {
2731         case VT_I1   : rVal = V_UNION(right,cVal);  break;
2732         case VT_I2   : rVal = V_UNION(right,iVal);  break;
2733         case VT_I4   : rVal = V_UNION(right,lVal);  break;
2734         case VT_INT  : rVal = V_UNION(right,lVal);  break;
2735         case VT_UI1  : rVal = V_UNION(right,bVal);  break;
2736         case VT_UI2  : rVal = V_UNION(right,uiVal); break;
2737         case VT_UI4  : rVal = V_UNION(right,ulVal); break;
2738         case VT_UINT : rVal = V_UNION(right,ulVal); break;
2739         case VT_R4   : rVal = V_UNION(right,fltVal);break;
2740         case VT_R8   : rVal = V_UNION(right,dblVal);break;
2741         case VT_NULL : rVal = 0.0; break;
2742         default: rOk = FALSE;
2743         }
2744
2745         if (lOk && rOk) {
2746             res = (lVal + rVal);
2747             V_VT(result) = VT_R8;
2748             V_UNION(result,dblVal)  = res;
2749             rc = S_OK;
2750         } else {
2751             FIXME("Unhandled type pair %d / %d in double addition.\n",
2752                 (V_VT(left)&VT_TYPEMASK),
2753                 (V_VT(right)&VT_TYPEMASK)
2754             );
2755         }
2756         return rc;
2757     }
2758
2759     /* now check if we add floats. VT_R8 can no longer happen here! */
2760     if (((V_VT(left)&VT_TYPEMASK) == VT_R4) || ((V_VT(right)&VT_TYPEMASK) == VT_R4)) {
2761         BOOL         lOk        = TRUE;
2762         BOOL         rOk        = TRUE;
2763         float        lVal = -1;
2764         float        rVal = -1;
2765         float        res  = -1;
2766
2767         lOk = TRUE;
2768         switch (V_VT(left)&VT_TYPEMASK) {
2769         case VT_I1   : lVal = V_UNION(left,cVal);   break;
2770         case VT_I2   : lVal = V_UNION(left,iVal);   break;
2771         case VT_I4   : lVal = V_UNION(left,lVal);   break;
2772         case VT_INT  : lVal = V_UNION(left,lVal);   break;
2773         case VT_UI1  : lVal = V_UNION(left,bVal);   break;
2774         case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
2775         case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
2776         case VT_UINT : lVal = V_UNION(left,ulVal);  break;
2777         case VT_R4   : lVal = V_UNION(left,fltVal);  break;
2778         case VT_NULL : lVal = 0.0;  break;
2779         default: lOk = FALSE;
2780         }
2781
2782         rOk = TRUE;
2783         switch (V_VT(right)&VT_TYPEMASK) {
2784         case VT_I1   : rVal = V_UNION(right,cVal);  break;
2785         case VT_I2   : rVal = V_UNION(right,iVal);  break;
2786         case VT_I4   : rVal = V_UNION(right,lVal);  break;
2787         case VT_INT  : rVal = V_UNION(right,lVal);  break;
2788         case VT_UI1  : rVal = V_UNION(right,bVal);  break;
2789         case VT_UI2  : rVal = V_UNION(right,uiVal); break;
2790         case VT_UI4  : rVal = V_UNION(right,ulVal); break;
2791         case VT_UINT : rVal = V_UNION(right,ulVal); break;
2792         case VT_R4   : rVal = V_UNION(right,fltVal);break;
2793         case VT_NULL : rVal = 0.0; break;
2794         default: rOk = FALSE;
2795         }
2796
2797         if (lOk && rOk) {
2798             res = (lVal + rVal);
2799             V_VT(result) = VT_R4;
2800             V_UNION(result,fltVal)  = res;
2801             rc = S_OK;
2802         } else {
2803             FIXME("Unhandled type pair %d / %d in float addition.\n",
2804                 (V_VT(left)&VT_TYPEMASK),
2805                 (V_VT(right)&VT_TYPEMASK)
2806             );
2807         }
2808         return rc;
2809     }
2810
2811     /* Handle strings as concat */
2812     if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR &&
2813         (V_VT(right)&VT_TYPEMASK) == VT_BSTR) {
2814         V_VT(result) = VT_BSTR;
2815         return VarBstrCat(V_BSTR(left), V_BSTR(right), &V_BSTR(result));
2816     } else {
2817
2818         /* Integers */
2819         BOOL         lOk        = TRUE;
2820         BOOL         rOk        = TRUE;
2821         LONGLONG     lVal = -1;
2822         LONGLONG     rVal = -1;
2823         LONGLONG     res  = -1;
2824         int          resT = 0; /* Testing has shown I2 + I2 == I2, all else
2825                                   becomes I4                                */
2826
2827         lOk = TRUE;
2828         switch (V_VT(left)&VT_TYPEMASK) {
2829         case VT_I1   : lVal = V_UNION(left,cVal);  resT=VT_I4; break;
2830         case VT_I2   : lVal = V_UNION(left,iVal);  resT=VT_I2; break;
2831         case VT_I4   : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
2832         case VT_INT  : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
2833         case VT_UI1  : lVal = V_UNION(left,bVal);  resT=VT_I4; break;
2834         case VT_UI2  : lVal = V_UNION(left,uiVal); resT=VT_I4; break;
2835         case VT_UI4  : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
2836         case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
2837         case VT_NULL : lVal = 0; resT = VT_I4; break;
2838         default: lOk = FALSE;
2839         }
2840
2841         rOk = TRUE;
2842         switch (V_VT(right)&VT_TYPEMASK) {
2843         case VT_I1   : rVal = V_UNION(right,cVal);  resT=VT_I4; break;
2844         case VT_I2   : rVal = V_UNION(right,iVal);  resT=max(VT_I2, resT); break;
2845         case VT_I4   : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
2846         case VT_INT  : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
2847         case VT_UI1  : rVal = V_UNION(right,bVal);  resT=VT_I4; break;
2848         case VT_UI2  : rVal = V_UNION(right,uiVal); resT=VT_I4; break;
2849         case VT_UI4  : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
2850         case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
2851         case VT_NULL : rVal = 0; resT=VT_I4; break;
2852         default: rOk = FALSE;
2853         }
2854
2855         if (lOk && rOk) {
2856             res = (lVal + rVal);
2857             V_VT(result) = resT;
2858             switch (resT) {
2859             case VT_I2   : V_UNION(result,iVal)  = res; break;
2860             case VT_I4   : V_UNION(result,lVal)  = res; break;
2861             default:
2862                 FIXME("Unexpected result variant type %x\n", resT);
2863                 V_UNION(result,lVal)  = res;
2864             }
2865             rc = S_OK;
2866
2867         } else {
2868             FIXME("unimplemented part (0x%x + 0x%x)\n",V_VT(left), V_VT(right));
2869         }
2870     }
2871
2872     TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
2873           debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
2874     return rc;
2875 }
2876
2877 /**********************************************************************
2878  *              VarMul [OLEAUT32.156]
2879  *
2880  */
2881 HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
2882 {
2883     HRESULT rc = E_FAIL;
2884     VARTYPE lvt,rvt,resvt;
2885     VARIANT lv,rv;
2886     BOOL found;
2887
2888     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
2889           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
2890
2891     VariantInit(&lv);VariantInit(&rv);
2892     lvt = V_VT(left)&VT_TYPEMASK;
2893     rvt = V_VT(right)&VT_TYPEMASK;
2894     found = FALSE;resvt=VT_VOID;
2895     if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
2896         found = TRUE;
2897         resvt = VT_R8;
2898     }
2899     if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
2900         found = TRUE;
2901         resvt = VT_I4;
2902     }
2903     if (!found) {
2904         FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
2905         return E_FAIL;
2906     }
2907     rc = VariantChangeType(&lv, left, 0, resvt);
2908     if (FAILED(rc)) {
2909         FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
2910         return rc;
2911     }
2912     rc = VariantChangeType(&rv, right, 0, resvt);
2913     if (FAILED(rc)) {
2914         FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
2915         return rc;
2916     }
2917     switch (resvt) {
2918     case VT_R8:
2919         V_VT(result) = resvt;
2920         V_R8(result) = V_R8(&lv) * V_R8(&rv);
2921         rc = S_OK;
2922         break;
2923     case VT_I4:
2924         V_VT(result) = resvt;
2925         V_I4(result) = V_I4(&lv) * V_I4(&rv);
2926         rc = S_OK;
2927         break;
2928     }
2929     TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
2930           debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
2931     return rc;
2932 }
2933
2934 /**********************************************************************
2935  *              VarDiv [OLEAUT32.143]
2936  *
2937  */
2938 HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
2939 {
2940     HRESULT rc = E_FAIL;
2941     VARTYPE lvt,rvt,resvt;
2942     VARIANT lv,rv;
2943     BOOL found;
2944
2945     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
2946           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
2947
2948     VariantInit(&lv);VariantInit(&rv);
2949     lvt = V_VT(left)&VT_TYPEMASK;
2950     rvt = V_VT(right)&VT_TYPEMASK;
2951     found = FALSE;resvt = VT_VOID;
2952     if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
2953         found = TRUE;
2954         resvt = VT_R8;
2955     }
2956     if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
2957         found = TRUE;
2958         resvt = VT_I4;
2959     }
2960     if (!found) {
2961         FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
2962         return E_FAIL;
2963     }
2964     rc = VariantChangeType(&lv, left, 0, resvt);
2965     if (FAILED(rc)) {
2966         FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
2967         return rc;
2968     }
2969     rc = VariantChangeType(&rv, right, 0, resvt);
2970     if (FAILED(rc)) {
2971         FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
2972         return rc;
2973     }
2974     switch (resvt) {
2975     case VT_R8:
2976         V_VT(result) = resvt;
2977         V_R8(result) = V_R8(&lv) / V_R8(&rv);
2978         rc = S_OK;
2979         break;
2980     case VT_I4:
2981         V_VT(result) = resvt;
2982         V_I4(result) = V_I4(&lv) / V_I4(&rv);
2983         rc = S_OK;
2984         break;
2985     }
2986     TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
2987           debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
2988     return rc;
2989 }
2990
2991 /**********************************************************************
2992  *              VarSub [OLEAUT32.159]
2993  *
2994  */
2995 HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
2996 {
2997     HRESULT rc = E_FAIL;
2998     VARTYPE lvt,rvt,resvt;
2999     VARIANT lv,rv;
3000     BOOL found;
3001
3002     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
3003           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
3004
3005     VariantInit(&lv);VariantInit(&rv);
3006     lvt = V_VT(left)&VT_TYPEMASK;
3007     rvt = V_VT(right)&VT_TYPEMASK;
3008     found = FALSE;resvt = VT_VOID;
3009     if (((1<<lvt) | (1<<rvt)) & ((1<<VT_DATE)|(1<<VT_R4)|(1<<VT_R8))) {
3010         found = TRUE;
3011         resvt = VT_R8;
3012     }
3013     if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
3014         found = TRUE;
3015         resvt = VT_I4;
3016     }
3017     if (!found) {
3018         FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
3019         return E_FAIL;
3020     }
3021     rc = VariantChangeType(&lv, left, 0, resvt);
3022     if (FAILED(rc)) {
3023         FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
3024         return rc;
3025     }
3026     rc = VariantChangeType(&rv, right, 0, resvt);
3027     if (FAILED(rc)) {
3028         FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
3029         return rc;
3030     }
3031     switch (resvt) {
3032     case VT_R8:
3033         V_VT(result) = resvt;
3034         V_R8(result) = V_R8(&lv) - V_R8(&rv);
3035         rc = S_OK;
3036         break;
3037     case VT_I4:
3038         V_VT(result) = resvt;
3039         V_I4(result) = V_I4(&lv) - V_I4(&rv);
3040         rc = S_OK;
3041         break;
3042     }
3043     TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
3044           debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
3045     return rc;
3046 }
3047
3048 /**********************************************************************
3049  *              VarOr [OLEAUT32.157]
3050  *
3051  */
3052 HRESULT WINAPI VarOr(LPVARIANT left, LPVARIANT right, LPVARIANT result)
3053 {
3054     HRESULT rc = E_FAIL;
3055
3056     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
3057           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
3058
3059     if ((V_VT(left)&VT_TYPEMASK) == VT_BOOL &&
3060         (V_VT(right)&VT_TYPEMASK) == VT_BOOL) {
3061
3062         V_VT(result) = VT_BOOL;
3063         if (V_BOOL(left) || V_BOOL(right)) {
3064             V_BOOL(result) = VARIANT_TRUE;
3065         } else {
3066             V_BOOL(result) = VARIANT_FALSE;
3067         }
3068         rc = S_OK;
3069
3070     } else {
3071         /* Integers */
3072         BOOL         lOk        = TRUE;
3073         BOOL         rOk        = TRUE;
3074         LONGLONG     lVal = -1;
3075         LONGLONG     rVal = -1;
3076         LONGLONG     res  = -1;
3077         int          resT = 0; /* Testing has shown I2 & I2 == I2, all else
3078                                   becomes I4, even unsigned ints (incl. UI2) */
3079
3080         lOk = TRUE;
3081         switch (V_VT(left)&VT_TYPEMASK) {
3082         case VT_I1   : lVal = V_UNION(left,cVal);  resT=VT_I4; break;
3083         case VT_I2   : lVal = V_UNION(left,iVal);  resT=VT_I2; break;
3084         case VT_I4   : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
3085         case VT_INT  : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
3086         case VT_UI1  : lVal = V_UNION(left,bVal);  resT=VT_I4; break;
3087         case VT_UI2  : lVal = V_UNION(left,uiVal); resT=VT_I4; break;
3088         case VT_UI4  : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
3089         case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
3090         case VT_BOOL : lVal = V_UNION(left,boolVal); resT=VT_I4; break;
3091         default: lOk = FALSE;
3092         }
3093
3094         rOk = TRUE;
3095         switch (V_VT(right)&VT_TYPEMASK) {
3096         case VT_I1   : rVal = V_UNION(right,cVal);  resT=VT_I4; break;
3097         case VT_I2   : rVal = V_UNION(right,iVal);  resT=max(VT_I2, resT); break;
3098         case VT_I4   : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
3099         case VT_INT  : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
3100         case VT_UI1  : rVal = V_UNION(right,bVal);  resT=VT_I4; break;
3101         case VT_UI2  : rVal = V_UNION(right,uiVal); resT=VT_I4; break;
3102         case VT_UI4  : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
3103         case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
3104         case VT_BOOL : rVal = V_UNION(right,boolVal); resT=VT_I4; break;
3105         default: rOk = FALSE;
3106         }
3107
3108         if (lOk && rOk) {
3109             res = (lVal | rVal);
3110             V_VT(result) = resT;
3111             switch (resT) {
3112             case VT_I2   : V_UNION(result,iVal)  = res; break;
3113             case VT_I4   : V_UNION(result,lVal)  = res; break;
3114             default:
3115                 FIXME("Unexpected result variant type %x\n", resT);
3116                 V_UNION(result,lVal)  = res;
3117             }
3118             rc = S_OK;
3119
3120         } else {
3121             FIXME("unimplemented part, V_VT(left) == 0x%X, V_VT(right) == 0x%X\n",
3122                 V_VT(left) & VT_TYPEMASK, V_VT(right) & VT_TYPEMASK);
3123         }
3124     }
3125
3126     TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
3127           debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
3128     return rc;
3129 }
3130
3131 /**********************************************************************
3132  * VarAbs [OLEAUT32.168]
3133  *
3134  * Convert a variant to its absolute value.
3135  *
3136  * PARAMS
3137  *  pVarIn  [I] Source variant
3138  *  pVarOut [O] Destination for converted value
3139  *
3140  * RETURNS
3141  *  Success: S_OK. pVarOut contains the absolute value of pVarIn.
3142  *  Failure: An HRESULT error code indicating the error.
3143  *
3144  * NOTES
3145  *  - This function does not process by-reference variants.
3146  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
3147  *    according to the following table:
3148  *| Input Type       Output Type
3149  *| ----------       -----------
3150  *| VT_BOOL          VT_I2
3151  *| VT_BSTR          VT_R8
3152  *| (All others)     Unchanged
3153  */
3154 HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut)
3155 {
3156     VARIANT varIn;
3157     HRESULT hRet = S_OK;
3158
3159     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
3160           debugstr_VF(pVarIn), pVarOut);
3161
3162     if (V_ISARRAY(pVarIn) || V_VT(pVarIn) == VT_UNKNOWN ||
3163         V_VT(pVarIn) == VT_DISPATCH || V_VT(pVarIn) == VT_RECORD ||
3164         V_VT(pVarIn) == VT_ERROR)
3165         return DISP_E_TYPEMISMATCH;
3166
3167     *pVarOut = *pVarIn; /* Shallow copy the value, and invert it if needed */
3168
3169 #define ABS_CASE(typ,min) \
3170     case VT_##typ: if (V_##typ(pVarIn) == min) hRet = DISP_E_OVERFLOW; \
3171                   else if (V_##typ(pVarIn) < 0) V_##typ(pVarOut) = -V_##typ(pVarIn); \
3172                   break
3173
3174     switch (V_VT(pVarIn))
3175     {
3176     ABS_CASE(I1,I1_MIN);
3177     case VT_BOOL:
3178         V_VT(pVarOut) = VT_I2;
3179         /* BOOL->I2, Fall through ... */
3180     ABS_CASE(I2,I2_MIN);
3181     case VT_INT:
3182     ABS_CASE(I4,I4_MIN);
3183     ABS_CASE(I8,I8_MIN);
3184     ABS_CASE(R4,R4_MIN);
3185     case VT_BSTR:
3186         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
3187         if (FAILED(hRet))
3188             break;
3189         V_VT(pVarOut) = VT_R8;
3190         pVarIn = &varIn;
3191         /* Fall through ... */
3192     case VT_DATE:
3193     ABS_CASE(R8,R8_MIN);
3194     case VT_CY:
3195         hRet = VarCyAbs(V_CY(pVarIn), & V_CY(pVarOut));
3196         break;
3197     case VT_DECIMAL:
3198         DEC_SIGN(&V_DECIMAL(pVarOut)) &= ~DECIMAL_NEG;
3199         break;
3200     case VT_UI1:
3201     case VT_UI2:
3202     case VT_UINT:
3203     case VT_UI4:
3204     case VT_UI8:
3205     case VT_EMPTY:
3206     case VT_NULL:
3207         /* No-Op */
3208         break;
3209     default:
3210         hRet = DISP_E_BADVARTYPE;
3211     }
3212
3213     return hRet;
3214 }
3215
3216 /**********************************************************************
3217  *              VarFix [OLEAUT32.169]
3218  *
3219  * Truncate a variants value to a whole number.
3220  *
3221  * PARAMS
3222  *  pVarIn  [I] Source variant
3223  *  pVarOut [O] Destination for converted value
3224  *
3225  * RETURNS
3226  *  Success: S_OK. pVarOut contains the converted value.
3227  *  Failure: An HRESULT error code indicating the error.
3228  *
3229  * NOTES
3230  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
3231  *    according to the following table:
3232  *| Input Type       Output Type
3233  *| ----------       -----------
3234  *|  VT_BOOL          VT_I2
3235  *|  VT_EMPTY         VT_I2
3236  *|  VT_BSTR          VT_R8
3237  *|  All Others       Unchanged
3238  *  - The difference between this function and VarInt() is that VarInt() rounds
3239  *    negative numbers away from 0, while this function rounds them towards zero.
3240  */
3241 HRESULT WINAPI VarFix(LPVARIANT pVarIn, LPVARIANT pVarOut)
3242 {
3243     HRESULT hRet = S_OK;
3244
3245     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
3246           debugstr_VF(pVarIn), pVarOut);
3247
3248     V_VT(pVarOut) = V_VT(pVarIn);
3249
3250     switch (V_VT(pVarIn))
3251     {
3252     case VT_UI1:
3253         V_UI1(pVarOut) = V_UI1(pVarIn);
3254         break;
3255     case VT_BOOL:
3256         V_VT(pVarOut) = VT_I2;
3257         /* Fall through */
3258      case VT_I2:
3259         V_I2(pVarOut) = V_I2(pVarIn);
3260         break;
3261      case VT_I4:
3262         V_I4(pVarOut) = V_I4(pVarIn);
3263         break;
3264      case VT_I8:
3265         V_I8(pVarOut) = V_I8(pVarIn);
3266         break;
3267     case VT_R4:
3268         if (V_R4(pVarIn) < 0.0f)
3269             V_R4(pVarOut) = (float)ceil(V_R4(pVarIn));
3270         else
3271             V_R4(pVarOut) = (float)floor(V_R4(pVarIn));
3272         break;
3273     case VT_BSTR:
3274         V_VT(pVarOut) = VT_R8;
3275         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
3276         pVarIn = pVarOut;
3277         /* Fall through */
3278     case VT_DATE:
3279     case VT_R8:
3280         if (V_R8(pVarIn) < 0.0)
3281             V_R8(pVarOut) = ceil(V_R8(pVarIn));
3282         else
3283             V_R8(pVarOut) = floor(V_R8(pVarIn));
3284         break;
3285     case VT_CY:
3286         hRet = VarCyFix(V_CY(pVarIn), &V_CY(pVarOut));
3287         break;
3288     case VT_DECIMAL:
3289         hRet = VarDecFix(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
3290         break;
3291     case VT_EMPTY:
3292         V_VT(pVarOut) = VT_I2;
3293         V_I2(pVarOut) = 0;
3294         break;
3295     case VT_NULL:
3296         /* No-Op */
3297         break;
3298     default:
3299         if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
3300             FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
3301             hRet = DISP_E_BADVARTYPE;
3302         else
3303             hRet = DISP_E_TYPEMISMATCH;
3304     }
3305     if (FAILED(hRet))
3306       V_VT(pVarOut) = VT_EMPTY;
3307
3308     return hRet;
3309 }
3310
3311 /**********************************************************************
3312  *              VarInt [OLEAUT32.172]
3313  *
3314  * Truncate a variants value to a whole number.
3315  *
3316  * PARAMS
3317  *  pVarIn  [I] Source variant
3318  *  pVarOut [O] Destination for converted value
3319  *
3320  * RETURNS
3321  *  Success: S_OK. pVarOut contains the converted value.
3322  *  Failure: An HRESULT error code indicating the error.
3323  *
3324  * NOTES
3325  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
3326  *    according to the following table:
3327  *| Input Type       Output Type
3328  *| ----------       -----------
3329  *|  VT_BOOL          VT_I2
3330  *|  VT_EMPTY         VT_I2
3331  *|  VT_BSTR          VT_R8
3332  *|  All Others       Unchanged
3333  *  - The difference between this function and VarFix() is that VarFix() rounds
3334  *    negative numbers towards 0, while this function rounds them away from zero.
3335  */
3336 HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut)
3337 {
3338     HRESULT hRet = S_OK;
3339
3340     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
3341           debugstr_VF(pVarIn), pVarOut);
3342
3343     V_VT(pVarOut) = V_VT(pVarIn);
3344
3345     switch (V_VT(pVarIn))
3346     {
3347     case VT_R4:
3348         V_R4(pVarOut) = (float)floor(V_R4(pVarIn));
3349         break;
3350     case VT_BSTR:
3351         V_VT(pVarOut) = VT_R8;
3352         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
3353         pVarIn = pVarOut;
3354         /* Fall through */
3355     case VT_DATE:
3356     case VT_R8:
3357         V_R8(pVarOut) = floor(V_R8(pVarIn));
3358         break;
3359     case VT_CY:
3360         hRet = VarCyInt(V_CY(pVarIn), &V_CY(pVarOut));
3361         break;
3362     case VT_DECIMAL:
3363         hRet = VarDecInt(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
3364         break;
3365     default:
3366         return VarFix(pVarIn, pVarOut);
3367     }
3368
3369     return hRet;
3370 }
3371
3372 /**********************************************************************
3373  *              VarXor [OLEAUT32.167]
3374  *
3375  * Perform a logical exclusive-or (XOR) operation on two variants.
3376  *
3377  * PARAMS
3378  *  pVarLeft  [I] First variant
3379  *  pVarRight [I] Variant to XOR with pVarLeft
3380  *  pVarOut   [O] Destination for XOR result
3381  *
3382  * RETURNS
3383  *  Success: S_OK. pVarOut contains the result of the operation with its type
3384  *           taken from the table below).
3385  *  Failure: An HRESULT error code indicating the error.
3386  *
3387  * NOTES
3388  *  - The result stored in pVarOut depends on the types of pVarLeft/pVarRight
3389  *    according to the following table:
3390  *|  Type 1     Type 2       Result Type
3391  *|  ------     ------       -----------
3392  *|  VT_NULL    All Others   VT_NULL
3393  *|  VT_BOOL    VT_BOOL      VT_BOOL
3394  *|             VT_EMPTY     VT_I2
3395  *|             VT_UI1       VT_I2
3396  *|             VT_I2        VT_I2
3397  *|  VT_EMPTY   VT_EMPTY     VT_I2
3398  *|             VT_UI1       VT_I2
3399  *|             VT_BOOL      VT_I2
3400  *|             VT_I2        VT_I2
3401  *|  VT_UI1     VT_UI1       VT_UI1
3402  *|             VT_EMPTY     VT_I2
3403  *|             VT_BOOL      VT_I2
3404  *|             VT_I2        VT_I2
3405  *|  VT_I2      VT_I2        VT_I2
3406  *|             VT_EMPTY     VT_I2
3407  *|             VT_BOOL      VT_I2
3408  *|  All Other Combinations  VT_UI4
3409  */
3410 HRESULT WINAPI VarXor(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
3411 {
3412     VARTYPE vt = VT_I4;
3413     VARIANT varLeft, varRight;
3414     HRESULT hRet;
3415
3416     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
3417           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
3418           debugstr_VF(pVarRight), pVarOut);
3419
3420     if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
3421         V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
3422         V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH ||
3423         V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD)
3424         return DISP_E_BADVARTYPE;
3425
3426     if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
3427     {
3428         if (V_VT(pVarLeft) == VT_NULL)
3429             pVarLeft = pVarRight; /* point to the non-NULL var */
3430
3431         switch (V_VT(pVarLeft))
3432         {
3433         case VT_BSTR:
3434             if (!V_BSTR(pVarLeft))
3435                 return DISP_E_BADVARTYPE;
3436             /* Fall Through ... */
3437         case VT_NULL: case VT_EMPTY: case VT_DATE: case VT_CY:
3438         case VT_DECIMAL: case VT_R4: case VT_R8: case VT_BOOL:
3439         case VT_I1: case VT_UI1: case VT_I2: case VT_UI2:
3440         case VT_I4: case VT_UI4: case VT_I8: case VT_UI8:
3441         case VT_INT: case VT_UINT:
3442             V_VT(pVarOut) = VT_NULL;
3443             return S_OK;
3444         default:
3445             return DISP_E_BADVARTYPE;
3446         }
3447     }
3448
3449     if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY)
3450     {
3451         if (V_VT(pVarLeft) == VT_EMPTY)
3452             pVarLeft = pVarRight; /* point to the non-EMPTY var */
3453
3454         switch (V_VT(pVarLeft))
3455         {
3456         case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2:
3457             V_VT(pVarOut) = VT_I2;
3458             V_I2(pVarOut) = VARIANT_FALSE;
3459             return S_OK;
3460
3461         case VT_BSTR:
3462             if (!V_BSTR(pVarLeft))
3463                 return DISP_E_BADVARTYPE;
3464             /* Fall Through ... */
3465         case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8:
3466         case VT_I1: case VT_UI2: case VT_I4: case VT_UI4:
3467         case VT_INT: case VT_UINT: case VT_UI8:
3468             V_VT(pVarOut) = VT_I4;
3469             V_I4(pVarOut) = VARIANT_FALSE;
3470             return S_OK;
3471         case VT_I8:
3472             V_VT(pVarOut) = VT_I8;
3473             V_I4(pVarOut) = VARIANT_FALSE;
3474             return S_OK;
3475         default:
3476             return DISP_E_BADVARTYPE;
3477         }
3478     }
3479
3480     if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL)
3481     {
3482         V_VT(pVarOut) = VT_BOOL;
3483         V_BOOL(pVarOut) = V_BOOL(pVarLeft) ^ V_BOOL(pVarRight);
3484         return S_OK;
3485     }
3486
3487     if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1)
3488     {
3489         V_VT(pVarOut) = VT_UI1;
3490         V_UI1(pVarOut) = V_UI1(pVarLeft) ^ V_UI1(pVarRight);
3491         return S_OK;
3492     }
3493
3494     if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 ||
3495         V_VT(pVarLeft) == VT_I2) &&
3496         (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 ||
3497         V_VT(pVarRight) == VT_I2))
3498         vt = VT_I2;
3499     else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8)
3500     {
3501         if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
3502             return DISP_E_TYPEMISMATCH;
3503         vt = VT_I8;
3504     }
3505
3506     V_VT(&varLeft) = V_VT(&varRight) = VT_EMPTY;
3507     hRet = VariantCopy(&varLeft, pVarLeft);
3508     if (FAILED(hRet))
3509         goto VarXor_Exit;
3510
3511     hRet = VariantCopy(&varRight, pVarRight);
3512     if (FAILED(hRet))
3513         goto VarXor_Exit;
3514
3515     hRet = VariantChangeTypeEx(&varLeft, pVarLeft, LOCALE_USER_DEFAULT, 0, vt);
3516     if (FAILED(hRet))
3517         goto VarXor_Exit;
3518
3519     hRet = VariantChangeTypeEx(&varRight, pVarRight, LOCALE_USER_DEFAULT, 0, vt);
3520     if (FAILED(hRet))
3521         goto VarXor_Exit;
3522
3523     V_VT(pVarOut) = vt;
3524     if (vt == VT_I8)
3525     {
3526         V_I8(pVarOut) = V_I8(&varLeft) ^ V_I8(&varRight);
3527     }
3528     else if (vt == VT_UI4)
3529     {
3530         V_I4(pVarOut) = V_I4(&varLeft) ^ V_I4(&varRight);
3531     }
3532     else
3533     {
3534         V_I2(pVarOut) = V_I2(&varLeft) ^ V_I2(&varRight);
3535     }
3536
3537 VarXor_Exit:
3538     VariantClear(&varLeft);
3539     VariantClear(&varRight);
3540     return hRet;
3541 }
3542
3543 /**********************************************************************
3544  *              VarEqv [OLEAUT32.172]
3545  *
3546  * Determine if two variants contain the same value.
3547  *
3548  * PARAMS
3549  *  pVarLeft  [I] First variant to compare
3550  *  pVarRight [I] Variant to compare to pVarLeft
3551  *  pVarOut   [O] Destination for comparison result
3552  *
3553  * RETURNS
3554  *  Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE
3555  *           if equivalent or non-zero otherwise.
3556  *  Failure: An HRESULT error code indicating the error.
3557  *
3558  * NOTES
3559  *  - This function simply calls VarXor() on pVarLeft and pVarRight and inverts
3560  *    the result.
3561  */
3562 HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
3563 {
3564     HRESULT hRet;
3565
3566     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
3567           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
3568           debugstr_VF(pVarRight), pVarOut);
3569
3570     hRet = VarXor(pVarLeft, pVarRight, pVarOut);
3571     if (SUCCEEDED(hRet))
3572     {
3573         if (V_VT(pVarOut) == VT_I8)
3574             V_I8(pVarOut) = ~V_I8(pVarOut);
3575         else
3576             V_UI4(pVarOut) = ~V_UI4(pVarOut);
3577     }
3578     return hRet;
3579 }
3580
3581 /**********************************************************************
3582  *              VarNeg [OLEAUT32.173]
3583  *
3584  * Negate the value of a variant.
3585  *
3586  * PARAMS
3587  *  pVarIn  [I] Source variant
3588  *  pVarOut [O] Destination for converted value
3589  *
3590  * RETURNS
3591  *  Success: S_OK. pVarOut contains the converted value.
3592  *  Failure: An HRESULT error code indicating the error.
3593  *
3594  * NOTES
3595  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
3596  *    according to the following table:
3597  *| Input Type       Output Type
3598  *| ----------       -----------
3599  *|  VT_EMPTY         VT_I2
3600  *|  VT_UI1           VT_I2
3601  *|  VT_BOOL          VT_I2
3602  *|  VT_BSTR          VT_R8
3603  *|  All Others       Unchanged (unless promoted)
3604  *  - Where the negated value of a variant does not fit in its base type, the type
3605  *    is promoted according to the following table:
3606  *| Input Type       Promoted To
3607  *| ----------       -----------
3608  *|   VT_I2            VT_I4
3609  *|   VT_I4            VT_R8
3610  *|   VT_I8            VT_R8
3611  *  - The native version of this function returns DISP_E_BADVARTYPE for valid
3612  *    variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH
3613  *    for types which are not valid. Since this is in contravention of the
3614  *    meaning of those error codes and unlikely to be relied on by applications,
3615  *    this implementation returns errors consistent with the other high level
3616  *    variant math functions.
3617  */
3618 HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut)
3619 {
3620     HRESULT hRet = S_OK;
3621
3622     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
3623           debugstr_VF(pVarIn), pVarOut);
3624
3625     V_VT(pVarOut) = V_VT(pVarIn);
3626
3627     switch (V_VT(pVarIn))
3628     {
3629     case VT_UI1:
3630         V_VT(pVarOut) = VT_I2;
3631         V_I2(pVarOut) = -V_UI1(pVarIn);
3632         break;
3633     case VT_BOOL:
3634         V_VT(pVarOut) = VT_I2;
3635         /* Fall through */
3636     case VT_I2:
3637         if (V_I2(pVarIn) == I2_MIN)
3638         {
3639             V_VT(pVarOut) = VT_I4;
3640             V_I4(pVarOut) = -(int)V_I2(pVarIn);
3641         }
3642         else
3643             V_I2(pVarOut) = -V_I2(pVarIn);
3644         break;
3645     case VT_I4:
3646         if (V_I4(pVarIn) == I4_MIN)
3647         {
3648             V_VT(pVarOut) = VT_R8;
3649             V_R8(pVarOut) = -(double)V_I4(pVarIn);
3650         }
3651         else
3652             V_I4(pVarOut) = -V_I4(pVarIn);
3653         break;
3654     case VT_I8:
3655         if (V_I8(pVarIn) == I8_MIN)
3656         {
3657             V_VT(pVarOut) = VT_R8;
3658             hRet = VarR8FromI8(V_I8(pVarIn), &V_R8(pVarOut));
3659             V_R8(pVarOut) *= -1.0;
3660         }
3661         else
3662             V_I8(pVarOut) = -V_I8(pVarIn);
3663         break;
3664     case VT_R4:
3665         V_R4(pVarOut) = -V_R4(pVarIn);
3666         break;
3667     case VT_DATE:
3668     case VT_R8:
3669         V_R8(pVarOut) = -V_R8(pVarIn);
3670         break;
3671     case VT_CY:
3672         hRet = VarCyNeg(V_CY(pVarIn), &V_CY(pVarOut));
3673         break;
3674     case VT_DECIMAL:
3675         hRet = VarDecNeg(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
3676         break;
3677     case VT_BSTR:
3678         V_VT(pVarOut) = VT_R8;
3679         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
3680         V_R8(pVarOut) = -V_R8(pVarOut);
3681         break;
3682     case VT_EMPTY:
3683         V_VT(pVarOut) = VT_I2;
3684         V_I2(pVarOut) = 0;
3685         break;
3686     case VT_NULL:
3687         /* No-Op */
3688         break;
3689     default:
3690         if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
3691             FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
3692             hRet = DISP_E_BADVARTYPE;
3693         else
3694             hRet = DISP_E_TYPEMISMATCH;
3695     }
3696     if (FAILED(hRet))
3697       V_VT(pVarOut) = VT_EMPTY;
3698
3699     return hRet;
3700 }
3701
3702 /**********************************************************************
3703  *              VarNot [OLEAUT32.174]
3704  *
3705  * Perform a not operation on a variant.
3706  *
3707  * PARAMS
3708  *  pVarIn  [I] Source variant
3709  *  pVarOut [O] Destination for converted value
3710  *
3711  * RETURNS
3712  *  Success: S_OK. pVarOut contains the converted value.
3713  *  Failure: An HRESULT error code indicating the error.
3714  *
3715  * NOTES
3716  *  - Strictly speaking, this function performs a bitwise ones compliment
3717  *    on the variants value (after possibly converting to VT_I4, see below).
3718  *    This only behaves like a boolean not operation if the value in
3719  *    pVarIn is either VARIANT_TRUE or VARIANT_FALSE and the type is signed.
3720  *  - To perform a genuine not operation, convert the variant to a VT_BOOL
3721  *    before calling this function.
3722  *  - This function does not process by-reference variants.
3723  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
3724  *    according to the following table:
3725  *| Input Type       Output Type
3726  *| ----------       -----------
3727  *| VT_R4            VT_I4
3728  *| VT_R8            VT_I4
3729  *| VT_BSTR          VT_I4
3730  *| VT_DECIMAL       VT_I4
3731  *| VT_CY            VT_I4
3732  *| (All others)     Unchanged
3733  */
3734 HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut)
3735 {
3736     VARIANT varIn;
3737     HRESULT hRet = S_OK;
3738
3739     TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
3740           debugstr_VF(pVarIn), pVarOut);
3741
3742     V_VT(pVarOut) = V_VT(pVarIn);
3743
3744     switch (V_VT(pVarIn))
3745     {
3746     case VT_I1:  V_I1(pVarOut) = ~V_I1(pVarIn); break;
3747     case VT_UI1: V_UI1(pVarOut) = ~V_UI1(pVarIn); break;
3748     case VT_BOOL:
3749     case VT_I2:  V_I2(pVarOut) = ~V_I2(pVarIn); break;
3750     case VT_UI2: V_UI2(pVarOut) = ~V_UI2(pVarIn); break;
3751     case VT_DECIMAL:
3752         hRet = VarI4FromDec(&V_DECIMAL(pVarIn), &V_I4(&varIn));
3753         if (FAILED(hRet))
3754             break;
3755         pVarIn = &varIn;
3756         V_VT(pVarOut) = VT_I4;
3757         /* Fall through ... */
3758     case VT_INT:
3759     case VT_I4:  V_I4(pVarOut) = ~V_I4(pVarIn); break;
3760     case VT_UINT:
3761     case VT_UI4: V_UI4(pVarOut) = ~V_UI4(pVarIn); break;
3762     case VT_I8:  V_I8(pVarOut) = ~V_I8(pVarIn); break;
3763     case VT_UI8: V_UI8(pVarOut) = ~V_UI8(pVarIn); break;
3764     case VT_R4:
3765         hRet = VarI4FromR4(V_R4(pVarIn), &V_I4(pVarOut));
3766         V_I4(pVarOut) = ~V_I4(pVarOut);
3767         V_VT(pVarOut) = VT_I4;
3768         break;
3769     case VT_BSTR:
3770         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
3771         if (FAILED(hRet))
3772             break;
3773         pVarIn = &varIn;
3774         /* Fall through ... */
3775     case VT_DATE:
3776     case VT_R8:
3777         hRet = VarI4FromR8(V_R8(pVarIn), &V_I4(pVarOut));
3778         V_I4(pVarOut) = ~V_I4(pVarOut);
3779         V_VT(pVarOut) = VT_I4;
3780         break;
3781     case VT_CY:
3782         hRet = VarI4FromCy(V_CY(pVarIn), &V_I4(pVarOut));
3783         V_I4(pVarOut) = ~V_I4(pVarOut);
3784         V_VT(pVarOut) = VT_I4;
3785         break;
3786     case VT_EMPTY:
3787     case VT_NULL:
3788         /* No-Op */
3789         break;
3790     default:
3791         if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
3792             FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
3793             hRet = DISP_E_BADVARTYPE;
3794         else
3795             hRet = DISP_E_TYPEMISMATCH;
3796     }
3797     if (FAILED(hRet))
3798       V_VT(pVarOut) = VT_EMPTY;
3799
3800     return hRet;
3801 }
3802
3803 /**********************************************************************
3804  *              VarRound [OLEAUT32.175]
3805  *
3806  * Perform a round operation on a variant.
3807  *
3808  * PARAMS
3809  *  pVarIn  [I] Source variant
3810  *  deci    [I] Number of decimals to round to
3811  *  pVarOut [O] Destination for converted value
3812  *
3813  * RETURNS
3814  *  Success: S_OK. pVarOut contains the converted value.
3815  *  Failure: An HRESULT error code indicating the error.
3816  *
3817  * NOTES
3818  *  - Floating point values are rounded to the desired number of decimals.
3819  *  - Some integer types are just copied to the return variable.
3820  *  - Some other integer types are not handled and fail.
3821  */
3822 HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut)
3823 {
3824     VARIANT varIn;
3825     HRESULT hRet = S_OK;
3826     float factor;
3827
3828     TRACE("(%p->(%s%s),%d)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), deci);
3829
3830     switch (V_VT(pVarIn))
3831     {
3832     /* cases that fail on windows */
3833     case VT_I1:
3834     case VT_I8:
3835     case VT_UI2:
3836     case VT_UI4:
3837         hRet = DISP_E_BADVARTYPE;
3838         break;
3839
3840     /* cases just copying in to out */
3841     case VT_UI1:
3842         V_VT(pVarOut) = V_VT(pVarIn);
3843         V_UI1(pVarOut) = V_UI1(pVarIn);
3844         break;
3845     case VT_I2:
3846         V_VT(pVarOut) = V_VT(pVarIn);
3847         V_I2(pVarOut) = V_I2(pVarIn);
3848         break;
3849     case VT_I4:
3850         V_VT(pVarOut) = V_VT(pVarIn);
3851         V_I4(pVarOut) = V_I4(pVarIn);
3852         break;
3853     case VT_NULL:
3854         V_VT(pVarOut) = V_VT(pVarIn);
3855         /* value unchanged */
3856         break;
3857
3858     /* cases that change type */
3859     case VT_EMPTY:
3860         V_VT(pVarOut) = VT_I2;
3861         V_I2(pVarOut) = 0;
3862         break;
3863     case VT_BOOL:
3864         V_VT(pVarOut) = VT_I2;
3865         V_I2(pVarOut) = V_BOOL(pVarIn);
3866         break;
3867     case VT_BSTR:
3868         hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
3869         if (FAILED(hRet))
3870             break;
3871         V_VT(&varIn)=VT_R8;
3872         pVarIn = &varIn;
3873         /* Fall through ... */
3874
3875     /* cases we need to do math */
3876     case VT_R8:
3877         if (V_R8(pVarIn)>0) {
3878             V_R8(pVarOut)=floor(V_R8(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
3879         } else {
3880             V_R8(pVarOut)=ceil(V_R8(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
3881         }
3882         V_VT(pVarOut) = V_VT(pVarIn);
3883         break;
3884     case VT_R4:
3885         if (V_R4(pVarIn)>0) {
3886             V_R4(pVarOut)=floor(V_R4(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
3887         } else {
3888             V_R4(pVarOut)=ceil(V_R4(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
3889         }
3890         V_VT(pVarOut) = V_VT(pVarIn);
3891         break;
3892     case VT_DATE:
3893         if (V_DATE(pVarIn)>0) {
3894             V_DATE(pVarOut)=floor(V_DATE(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
3895         } else {
3896             V_DATE(pVarOut)=ceil(V_DATE(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
3897         }
3898         V_VT(pVarOut) = V_VT(pVarIn);
3899         break;
3900     case VT_CY:
3901         if (deci>3)
3902             factor=1;
3903         else
3904             factor=pow(10, 4-deci);
3905
3906         if (V_CY(pVarIn).int64>0) {
3907             V_CY(pVarOut).int64=floor(V_CY(pVarIn).int64/factor)*factor;
3908         } else {
3909             V_CY(pVarOut).int64=ceil(V_CY(pVarIn).int64/factor)*factor;
3910         }
3911         V_VT(pVarOut) = V_VT(pVarIn);
3912         break;
3913
3914     /* cases we don't know yet */
3915     default:
3916         FIXME("unimplemented part, V_VT(pVarIn) == 0x%X, deci == %d\n",
3917                 V_VT(pVarIn) & VT_TYPEMASK, deci);
3918         hRet = DISP_E_BADVARTYPE;
3919     }
3920
3921     if (FAILED(hRet))
3922       V_VT(pVarOut) = VT_EMPTY;
3923
3924     TRACE("returning 0x%08lx (%s%s),%f\n", hRet, debugstr_VT(pVarOut),
3925         debugstr_VF(pVarOut), (V_VT(pVarOut) == VT_R4) ? V_R4(pVarOut) :
3926         (V_VT(pVarOut) == VT_R8) ? V_R8(pVarOut) : 0);
3927
3928     return hRet;
3929 }
3930
3931
3932 /**********************************************************************
3933  *              VarMod [OLEAUT32.154]
3934  *
3935  * Perform the modulus operation of the right hand variant on the left
3936  *
3937  * PARAMS
3938  *  left     [I] Left hand variant
3939  *  right    [I] Right hand variant
3940  *  result   [O] Destination for converted value
3941  *
3942  * RETURNS
3943  *  Success: S_OK. result contains the remainder.
3944  *  Failure: An HRESULT error code indicating the error.
3945  *
3946  * NOTE:
3947  *   If an error occurs the type of result will be modified but the value will not be.
3948  *   Doesn't support arrays or any special flags yet.
3949  */
3950 HRESULT WINAPI VarMod(LPVARIANT left, LPVARIANT right, LPVARIANT result)
3951 {
3952     BOOL         lOk        = TRUE;
3953     BOOL         rOk        = TRUE;
3954     HRESULT      rc         = E_FAIL;
3955     int          resT = 0;
3956     VARIANT      lv,rv;
3957
3958     VariantInit(&lv);
3959     VariantInit(&rv);
3960
3961     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
3962                   debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
3963
3964     /* check for invalid inputs */
3965     lOk = TRUE;
3966     switch (V_VT(left) & VT_TYPEMASK) {
3967     case VT_BOOL :
3968     case VT_I1   :
3969     case VT_I2   :
3970     case VT_I4   :
3971     case VT_I8   :
3972     case VT_INT  :
3973     case VT_UI1  :
3974     case VT_UI2  :
3975     case VT_UI4  :
3976     case VT_UI8  :
3977     case VT_UINT :
3978     case VT_R4   :
3979     case VT_R8   :
3980     case VT_CY   :
3981     case VT_EMPTY:
3982     case VT_DATE :
3983     case VT_BSTR :
3984       break;
3985     case VT_VARIANT:
3986     case VT_UNKNOWN:
3987       V_VT(result) = VT_EMPTY;
3988       return DISP_E_TYPEMISMATCH;
3989     case VT_DECIMAL:
3990       V_VT(result) = VT_EMPTY;
3991       return E_INVALIDARG;
3992     case VT_ERROR:
3993       return DISP_E_TYPEMISMATCH;
3994     case VT_RECORD:
3995       V_VT(result) = VT_EMPTY;
3996       return DISP_E_TYPEMISMATCH;
3997     case VT_NULL:
3998       break;
3999     default:
4000       V_VT(result) = VT_EMPTY;
4001       return DISP_E_BADVARTYPE;
4002     }
4003
4004
4005     rOk = TRUE;
4006     switch (V_VT(right) & VT_TYPEMASK) {
4007     case VT_BOOL :
4008     case VT_I1   :
4009     case VT_I2   :
4010     case VT_I4   :
4011     case VT_I8   :
4012       if((V_VT(left) == VT_INT) && (V_VT(right) == VT_I8))
4013       {
4014         V_VT(result) = VT_EMPTY;
4015         return DISP_E_TYPEMISMATCH;
4016       }
4017     case VT_INT  :
4018       if((V_VT(right) == VT_INT) && (V_VT(left) == VT_I8))
4019       {
4020         V_VT(result) = VT_EMPTY;
4021         return DISP_E_TYPEMISMATCH;
4022       }
4023     case VT_UI1  :
4024     case VT_UI2  :
4025     case VT_UI4  :
4026     case VT_UI8  :
4027     case VT_UINT :
4028     case VT_R4   :
4029     case VT_R8   :
4030     case VT_CY   :
4031       if(V_VT(left) == VT_EMPTY)
4032       {
4033         V_VT(result) = VT_I4;
4034         return S_OK;
4035       }
4036     case VT_EMPTY:
4037     case VT_DATE :
4038     case VT_BSTR:
4039       if(V_VT(left) == VT_NULL)
4040       {
4041         V_VT(result) = VT_NULL;
4042         return S_OK;
4043       }
4044       break;
4045
4046     case VT_VOID:
4047       V_VT(result) = VT_EMPTY;
4048       return DISP_E_BADVARTYPE;
4049     case VT_NULL:
4050       if(V_VT(left) == VT_VOID)
4051       {
4052         V_VT(result) = VT_EMPTY;
4053         return DISP_E_BADVARTYPE;
4054       } else if((V_VT(left) == VT_NULL) || (V_VT(left) == VT_EMPTY) || (V_VT(left) == VT_ERROR) ||
4055                 lOk)
4056       {
4057         V_VT(result) = VT_NULL;
4058         return S_OK;
4059       } else
4060       {
4061         V_VT(result) = VT_NULL;
4062         return DISP_E_BADVARTYPE;
4063       }
4064     case VT_VARIANT:
4065     case VT_UNKNOWN:
4066       V_VT(result) = VT_EMPTY;
4067       return DISP_E_TYPEMISMATCH;
4068     case VT_DECIMAL:
4069       if(V_VT(left) == VT_ERROR)
4070       {
4071         V_VT(result) = VT_EMPTY;
4072         return DISP_E_TYPEMISMATCH;
4073       } else
4074       {
4075         V_VT(result) = VT_EMPTY;
4076         return E_INVALIDARG;
4077       }
4078     case VT_ERROR:
4079       return DISP_E_TYPEMISMATCH;
4080     case VT_RECORD:
4081       if((V_VT(left) == 15) || ((V_VT(left) >= 24) && (V_VT(left) <= 35)) || !lOk)
4082       {
4083         V_VT(result) = VT_EMPTY;
4084         return DISP_E_BADVARTYPE;
4085       } else
4086       {
4087         V_VT(result) = VT_EMPTY;
4088         return DISP_E_TYPEMISMATCH;
4089       }
4090     default:
4091       V_VT(result) = VT_EMPTY;
4092       return DISP_E_BADVARTYPE;
4093     }
4094
4095     /* determine the result type */
4096     if((V_VT(left) == VT_I8)        || (V_VT(right) == VT_I8))   resT = VT_I8;
4097     else if((V_VT(left) == VT_UI1)  && (V_VT(right) == VT_BOOL)) resT = VT_I2;
4098     else if((V_VT(left) == VT_UI1)  && (V_VT(right) == VT_UI1))  resT = VT_UI1;
4099     else if((V_VT(left) == VT_UI1)  && (V_VT(right) == VT_I2))   resT = VT_I2;
4100     else if((V_VT(left) == VT_I2)   && (V_VT(right) == VT_BOOL)) resT = VT_I2;
4101     else if((V_VT(left) == VT_I2)   && (V_VT(right) == VT_UI1))  resT = VT_I2;
4102     else if((V_VT(left) == VT_I2)   && (V_VT(right) == VT_I2))   resT = VT_I2;
4103     else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_BOOL)) resT = VT_I2;
4104     else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_UI1))  resT = VT_I2;
4105     else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_I2))   resT = VT_I2;
4106     else resT = VT_I4; /* most outputs are I4 */
4107
4108     /* convert to I8 for the modulo */
4109     rc = VariantChangeType(&lv, left, 0, VT_I8);
4110     if(FAILED(rc))
4111     {
4112       FIXME("Could not convert left type %d to %d? rc == 0x%lX\n", V_VT(left), VT_I8, rc);
4113       return rc;
4114     }
4115
4116     rc = VariantChangeType(&rv, right, 0, VT_I8);
4117     if(FAILED(rc))
4118     {
4119       FIXME("Could not convert right type %d to %d? rc == 0x%lX\n", V_VT(right), VT_I8, rc);
4120       return rc;
4121     }
4122
4123     /* if right is zero set VT_EMPTY and return divide by zero */
4124     if(V_I8(&rv) == 0)
4125     {
4126       V_VT(result) = VT_EMPTY;
4127       return DISP_E_DIVBYZERO;
4128     }
4129
4130     /* perform the modulo operation */
4131     V_VT(result) = VT_I8;
4132     V_I8(result) = V_I8(&lv) % V_I8(&rv);
4133
4134     TRACE("V_I8(left) == %ld, V_I8(right) == %ld, V_I8(result) == %ld\n", (long)V_I8(&lv), (long)V_I8(&rv), (long)V_I8(result));
4135
4136     /* convert left and right to the destination type */
4137     rc = VariantChangeType(result, result, 0, resT);
4138     if(FAILED(rc))
4139     {
4140       FIXME("Could not convert 0x%x to %d?\n", V_VT(result), resT);
4141       return rc;
4142     }
4143
4144     return S_OK;
4145 }
4146
4147 /**********************************************************************
4148  *              VarPow [OLEAUT32.158]
4149  *
4150  */
4151 HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result)
4152 {
4153     HRESULT hr;
4154     VARIANT dl,dr;
4155
4156     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left),
4157           right, debugstr_VT(right), debugstr_VF(right), result);
4158
4159     hr = VariantChangeType(&dl,left,0,VT_R8);
4160     if (!SUCCEEDED(hr)) {
4161         ERR("Could not change passed left argument to VT_R8, handle it differently.\n");
4162         return E_FAIL;
4163     }
4164     hr = VariantChangeType(&dr,right,0,VT_R8);
4165     if (!SUCCEEDED(hr)) {
4166         ERR("Could not change passed right argument to VT_R8, handle it differently.\n");
4167         return E_FAIL;
4168     }
4169     V_VT(result) = VT_R8;
4170     V_R8(result) = pow(V_R8(&dl),V_R8(&dr));
4171     return S_OK;
4172 }