189840dbdeb1728dfcc39bf8fb923acbc94cf140
[reactos.git] / reactos / dll / win32 / oleaut32 / variant.c
1 /*
2 * VARIANT
3 *
4 * Copyright 1998 Jean-Claude Cote
5 * Copyright 2003 Jon Griffiths
6 * Copyright 2005 Daniel Remenak
7 * Copyright 2006 Google (Benjamin Arai)
8 *
9 * The algorithm for conversion from Julian days to day/month/year is based on
10 * that devised by Henry Fliegel, as implemented in PostgreSQL, which is
11 * Copyright 1994-7 Regents of the University of California
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28 #include "precomp.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(variant);
31
32 const char * const wine_vtypes[VT_CLSID+1] =
33 {
34 "VT_EMPTY","VT_NULL","VT_I2","VT_I4","VT_R4","VT_R8","VT_CY","VT_DATE",
35 "VT_BSTR","VT_DISPATCH","VT_ERROR","VT_BOOL","VT_VARIANT","VT_UNKNOWN",
36 "VT_DECIMAL","15","VT_I1","VT_UI1","VT_UI2","VT_UI4","VT_I8","VT_UI8",
37 "VT_INT","VT_UINT","VT_VOID","VT_HRESULT","VT_PTR","VT_SAFEARRAY",
38 "VT_CARRAY","VT_USERDEFINED","VT_LPSTR","VT_LPWSTR","32","33","34","35",
39 "VT_RECORD","VT_INT_PTR","VT_UINT_PTR","39","40","41","42","43","44","45",
40 "46","47","48","49","50","51","52","53","54","55","56","57","58","59","60",
41 "61","62","63","VT_FILETIME","VT_BLOB","VT_STREAM","VT_STORAGE",
42 "VT_STREAMED_OBJECT","VT_STORED_OBJECT","VT_BLOB_OBJECT","VT_CF","VT_CLSID"
43 };
44
45 const char * const wine_vflags[16] =
46 {
47 "",
48 "|VT_VECTOR",
49 "|VT_ARRAY",
50 "|VT_VECTOR|VT_ARRAY",
51 "|VT_BYREF",
52 "|VT_VECTOR|VT_ARRAY",
53 "|VT_ARRAY|VT_BYREF",
54 "|VT_VECTOR|VT_ARRAY|VT_BYREF",
55 "|VT_HARDTYPE",
56 "|VT_VECTOR|VT_HARDTYPE",
57 "|VT_ARRAY|VT_HARDTYPE",
58 "|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
59 "|VT_BYREF|VT_HARDTYPE",
60 "|VT_VECTOR|VT_ARRAY|VT_HARDTYPE",
61 "|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
62 "|VT_VECTOR|VT_ARRAY|VT_BYREF|VT_HARDTYPE",
63 };
64
65 /* Convert a variant from one type to another */
66 static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
67 VARIANTARG* ps, VARTYPE vt)
68 {
69 HRESULT res = DISP_E_TYPEMISMATCH;
70 VARTYPE vtFrom = V_TYPE(ps);
71 DWORD dwFlags = 0;
72
73 TRACE("(%p->(%s%s),0x%08x,0x%04x,%p->(%s%s),%s%s)\n", pd, debugstr_VT(pd),
74 debugstr_VF(pd), lcid, wFlags, ps, debugstr_VT(ps), debugstr_VF(ps),
75 debugstr_vt(vt), debugstr_vf(vt));
76
77 if (vt == VT_BSTR || vtFrom == VT_BSTR)
78 {
79 /* All flags passed to low level function are only used for
80 * changing to or from strings. Map these here.
81 */
82 if (wFlags & VARIANT_LOCALBOOL)
83 dwFlags |= VAR_LOCALBOOL;
84 if (wFlags & VARIANT_CALENDAR_HIJRI)
85 dwFlags |= VAR_CALENDAR_HIJRI;
86 if (wFlags & VARIANT_CALENDAR_THAI)
87 dwFlags |= VAR_CALENDAR_THAI;
88 if (wFlags & VARIANT_CALENDAR_GREGORIAN)
89 dwFlags |= VAR_CALENDAR_GREGORIAN;
90 if (wFlags & VARIANT_NOUSEROVERRIDE)
91 dwFlags |= LOCALE_NOUSEROVERRIDE;
92 if (wFlags & VARIANT_USE_NLS)
93 dwFlags |= LOCALE_USE_NLS;
94 }
95
96 /* Map int/uint to i4/ui4 */
97 if (vt == VT_INT)
98 vt = VT_I4;
99 else if (vt == VT_UINT)
100 vt = VT_UI4;
101
102 if (vtFrom == VT_INT)
103 vtFrom = VT_I4;
104 else if (vtFrom == VT_UINT)
105 vtFrom = VT_UI4;
106
107 if (vt == vtFrom)
108 return VariantCopy(pd, ps);
109
110 if (wFlags & VARIANT_NOVALUEPROP && vtFrom == VT_DISPATCH && vt != VT_UNKNOWN)
111 {
112 /* VARIANT_NOVALUEPROP prevents IDispatch objects from being coerced by
113 * accessing the default object property.
114 */
115 return DISP_E_TYPEMISMATCH;
116 }
117
118 switch (vt)
119 {
120 case VT_EMPTY:
121 if (vtFrom == VT_NULL)
122 return DISP_E_TYPEMISMATCH;
123 /* ... Fall through */
124 case VT_NULL:
125 if (vtFrom <= VT_UINT && vtFrom != (VARTYPE)15 && vtFrom != VT_ERROR)
126 {
127 res = VariantClear( pd );
128 if (vt == VT_NULL && SUCCEEDED(res))
129 V_VT(pd) = VT_NULL;
130 }
131 return res;
132
133 case VT_I1:
134 switch (vtFrom)
135 {
136 case VT_EMPTY: V_I1(pd) = 0; return S_OK;
137 case VT_I2: return VarI1FromI2(V_I2(ps), &V_I1(pd));
138 case VT_I4: return VarI1FromI4(V_I4(ps), &V_I1(pd));
139 case VT_UI1: V_I1(pd) = V_UI1(ps); return S_OK;
140 case VT_UI2: return VarI1FromUI2(V_UI2(ps), &V_I1(pd));
141 case VT_UI4: return VarI1FromUI4(V_UI4(ps), &V_I1(pd));
142 case VT_I8: return VarI1FromI8(V_I8(ps), &V_I1(pd));
143 case VT_UI8: return VarI1FromUI8(V_UI8(ps), &V_I1(pd));
144 case VT_R4: return VarI1FromR4(V_R4(ps), &V_I1(pd));
145 case VT_R8: return VarI1FromR8(V_R8(ps), &V_I1(pd));
146 case VT_DATE: return VarI1FromDate(V_DATE(ps), &V_I1(pd));
147 case VT_BOOL: return VarI1FromBool(V_BOOL(ps), &V_I1(pd));
148 case VT_CY: return VarI1FromCy(V_CY(ps), &V_I1(pd));
149 case VT_DECIMAL: return VarI1FromDec(&V_DECIMAL(ps), &V_I1(pd) );
150 case VT_DISPATCH: return VarI1FromDisp(V_DISPATCH(ps), lcid, &V_I1(pd) );
151 case VT_BSTR: return VarI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_I1(pd) );
152 }
153 break;
154
155 case VT_I2:
156 switch (vtFrom)
157 {
158 case VT_EMPTY: V_I2(pd) = 0; return S_OK;
159 case VT_I1: return VarI2FromI1(V_I1(ps), &V_I2(pd));
160 case VT_I4: return VarI2FromI4(V_I4(ps), &V_I2(pd));
161 case VT_UI1: return VarI2FromUI1(V_UI1(ps), &V_I2(pd));
162 case VT_UI2: V_I2(pd) = V_UI2(ps); return S_OK;
163 case VT_UI4: return VarI2FromUI4(V_UI4(ps), &V_I2(pd));
164 case VT_I8: return VarI2FromI8(V_I8(ps), &V_I2(pd));
165 case VT_UI8: return VarI2FromUI8(V_UI8(ps), &V_I2(pd));
166 case VT_R4: return VarI2FromR4(V_R4(ps), &V_I2(pd));
167 case VT_R8: return VarI2FromR8(V_R8(ps), &V_I2(pd));
168 case VT_DATE: return VarI2FromDate(V_DATE(ps), &V_I2(pd));
169 case VT_BOOL: return VarI2FromBool(V_BOOL(ps), &V_I2(pd));
170 case VT_CY: return VarI2FromCy(V_CY(ps), &V_I2(pd));
171 case VT_DECIMAL: return VarI2FromDec(&V_DECIMAL(ps), &V_I2(pd));
172 case VT_DISPATCH: return VarI2FromDisp(V_DISPATCH(ps), lcid, &V_I2(pd));
173 case VT_BSTR: return VarI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_I2(pd));
174 }
175 break;
176
177 case VT_I4:
178 switch (vtFrom)
179 {
180 case VT_EMPTY: V_I4(pd) = 0; return S_OK;
181 case VT_I1: return VarI4FromI1(V_I1(ps), &V_I4(pd));
182 case VT_I2: return VarI4FromI2(V_I2(ps), &V_I4(pd));
183 case VT_UI1: return VarI4FromUI1(V_UI1(ps), &V_I4(pd));
184 case VT_UI2: return VarI4FromUI2(V_UI2(ps), &V_I4(pd));
185 case VT_UI4: V_I4(pd) = V_UI4(ps); return S_OK;
186 case VT_I8: return VarI4FromI8(V_I8(ps), &V_I4(pd));
187 case VT_UI8: return VarI4FromUI8(V_UI8(ps), &V_I4(pd));
188 case VT_R4: return VarI4FromR4(V_R4(ps), &V_I4(pd));
189 case VT_R8: return VarI4FromR8(V_R8(ps), &V_I4(pd));
190 case VT_DATE: return VarI4FromDate(V_DATE(ps), &V_I4(pd));
191 case VT_BOOL: return VarI4FromBool(V_BOOL(ps), &V_I4(pd));
192 case VT_CY: return VarI4FromCy(V_CY(ps), &V_I4(pd));
193 case VT_DECIMAL: return VarI4FromDec(&V_DECIMAL(ps), &V_I4(pd));
194 case VT_DISPATCH: return VarI4FromDisp(V_DISPATCH(ps), lcid, &V_I4(pd));
195 case VT_BSTR: return VarI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_I4(pd));
196 }
197 break;
198
199 case VT_UI1:
200 switch (vtFrom)
201 {
202 case VT_EMPTY: V_UI1(pd) = 0; return S_OK;
203 case VT_I1: V_UI1(pd) = V_I1(ps); return S_OK;
204 case VT_I2: return VarUI1FromI2(V_I2(ps), &V_UI1(pd));
205 case VT_I4: return VarUI1FromI4(V_I4(ps), &V_UI1(pd));
206 case VT_UI2: return VarUI1FromUI2(V_UI2(ps), &V_UI1(pd));
207 case VT_UI4: return VarUI1FromUI4(V_UI4(ps), &V_UI1(pd));
208 case VT_I8: return VarUI1FromI8(V_I8(ps), &V_UI1(pd));
209 case VT_UI8: return VarUI1FromUI8(V_UI8(ps), &V_UI1(pd));
210 case VT_R4: return VarUI1FromR4(V_R4(ps), &V_UI1(pd));
211 case VT_R8: return VarUI1FromR8(V_R8(ps), &V_UI1(pd));
212 case VT_DATE: return VarUI1FromDate(V_DATE(ps), &V_UI1(pd));
213 case VT_BOOL: return VarUI1FromBool(V_BOOL(ps), &V_UI1(pd));
214 case VT_CY: return VarUI1FromCy(V_CY(ps), &V_UI1(pd));
215 case VT_DECIMAL: return VarUI1FromDec(&V_DECIMAL(ps), &V_UI1(pd));
216 case VT_DISPATCH: return VarUI1FromDisp(V_DISPATCH(ps), lcid, &V_UI1(pd));
217 case VT_BSTR: return VarUI1FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI1(pd));
218 }
219 break;
220
221 case VT_UI2:
222 switch (vtFrom)
223 {
224 case VT_EMPTY: V_UI2(pd) = 0; return S_OK;
225 case VT_I1: return VarUI2FromI1(V_I1(ps), &V_UI2(pd));
226 case VT_I2: V_UI2(pd) = V_I2(ps); return S_OK;
227 case VT_I4: return VarUI2FromI4(V_I4(ps), &V_UI2(pd));
228 case VT_UI1: return VarUI2FromUI1(V_UI1(ps), &V_UI2(pd));
229 case VT_UI4: return VarUI2FromUI4(V_UI4(ps), &V_UI2(pd));
230 case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
231 case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
232 case VT_R4: return VarUI2FromR4(V_R4(ps), &V_UI2(pd));
233 case VT_R8: return VarUI2FromR8(V_R8(ps), &V_UI2(pd));
234 case VT_DATE: return VarUI2FromDate(V_DATE(ps), &V_UI2(pd));
235 case VT_BOOL: return VarUI2FromBool(V_BOOL(ps), &V_UI2(pd));
236 case VT_CY: return VarUI2FromCy(V_CY(ps), &V_UI2(pd));
237 case VT_DECIMAL: return VarUI2FromDec(&V_DECIMAL(ps), &V_UI2(pd));
238 case VT_DISPATCH: return VarUI2FromDisp(V_DISPATCH(ps), lcid, &V_UI2(pd));
239 case VT_BSTR: return VarUI2FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI2(pd));
240 }
241 break;
242
243 case VT_UI4:
244 switch (vtFrom)
245 {
246 case VT_EMPTY: V_UI4(pd) = 0; return S_OK;
247 case VT_I1: return VarUI4FromI1(V_I1(ps), &V_UI4(pd));
248 case VT_I2: return VarUI4FromI2(V_I2(ps), &V_UI4(pd));
249 case VT_I4: V_UI4(pd) = V_I4(ps); return S_OK;
250 case VT_UI1: return VarUI4FromUI1(V_UI1(ps), &V_UI4(pd));
251 case VT_UI2: return VarUI4FromUI2(V_UI2(ps), &V_UI4(pd));
252 case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
253 case VT_UI8: return VarUI4FromUI8(V_UI8(ps), &V_UI4(pd));
254 case VT_R4: return VarUI4FromR4(V_R4(ps), &V_UI4(pd));
255 case VT_R8: return VarUI4FromR8(V_R8(ps), &V_UI4(pd));
256 case VT_DATE: return VarUI4FromDate(V_DATE(ps), &V_UI4(pd));
257 case VT_BOOL: return VarUI4FromBool(V_BOOL(ps), &V_UI4(pd));
258 case VT_CY: return VarUI4FromCy(V_CY(ps), &V_UI4(pd));
259 case VT_DECIMAL: return VarUI4FromDec(&V_DECIMAL(ps), &V_UI4(pd));
260 case VT_DISPATCH: return VarUI4FromDisp(V_DISPATCH(ps), lcid, &V_UI4(pd));
261 case VT_BSTR: return VarUI4FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI4(pd));
262 }
263 break;
264
265 case VT_UI8:
266 switch (vtFrom)
267 {
268 case VT_EMPTY: V_UI8(pd) = 0; return S_OK;
269 case VT_I4: if (V_I4(ps) < 0) return DISP_E_OVERFLOW; V_UI8(pd) = V_I4(ps); return S_OK;
270 case VT_I1: return VarUI8FromI1(V_I1(ps), &V_UI8(pd));
271 case VT_I2: return VarUI8FromI2(V_I2(ps), &V_UI8(pd));
272 case VT_UI1: return VarUI8FromUI1(V_UI1(ps), &V_UI8(pd));
273 case VT_UI2: return VarUI8FromUI2(V_UI2(ps), &V_UI8(pd));
274 case VT_UI4: return VarUI8FromUI4(V_UI4(ps), &V_UI8(pd));
275 case VT_I8: V_UI8(pd) = V_I8(ps); return S_OK;
276 case VT_R4: return VarUI8FromR4(V_R4(ps), &V_UI8(pd));
277 case VT_R8: return VarUI8FromR8(V_R8(ps), &V_UI8(pd));
278 case VT_DATE: return VarUI8FromDate(V_DATE(ps), &V_UI8(pd));
279 case VT_BOOL: return VarUI8FromBool(V_BOOL(ps), &V_UI8(pd));
280 case VT_CY: return VarUI8FromCy(V_CY(ps), &V_UI8(pd));
281 case VT_DECIMAL: return VarUI8FromDec(&V_DECIMAL(ps), &V_UI8(pd));
282 case VT_DISPATCH: return VarUI8FromDisp(V_DISPATCH(ps), lcid, &V_UI8(pd));
283 case VT_BSTR: return VarUI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_UI8(pd));
284 }
285 break;
286
287 case VT_I8:
288 switch (vtFrom)
289 {
290 case VT_EMPTY: V_I8(pd) = 0; return S_OK;
291 case VT_I4: V_I8(pd) = V_I4(ps); return S_OK;
292 case VT_I1: return VarI8FromI1(V_I1(ps), &V_I8(pd));
293 case VT_I2: return VarI8FromI2(V_I2(ps), &V_I8(pd));
294 case VT_UI1: return VarI8FromUI1(V_UI1(ps), &V_I8(pd));
295 case VT_UI2: return VarI8FromUI2(V_UI2(ps), &V_I8(pd));
296 case VT_UI4: return VarI8FromUI4(V_UI4(ps), &V_I8(pd));
297 case VT_UI8: V_I8(pd) = V_UI8(ps); return S_OK;
298 case VT_R4: return VarI8FromR4(V_R4(ps), &V_I8(pd));
299 case VT_R8: return VarI8FromR8(V_R8(ps), &V_I8(pd));
300 case VT_DATE: return VarI8FromDate(V_DATE(ps), &V_I8(pd));
301 case VT_BOOL: return VarI8FromBool(V_BOOL(ps), &V_I8(pd));
302 case VT_CY: return VarI8FromCy(V_CY(ps), &V_I8(pd));
303 case VT_DECIMAL: return VarI8FromDec(&V_DECIMAL(ps), &V_I8(pd));
304 case VT_DISPATCH: return VarI8FromDisp(V_DISPATCH(ps), lcid, &V_I8(pd));
305 case VT_BSTR: return VarI8FromStr(V_BSTR(ps), lcid, dwFlags, &V_I8(pd));
306 }
307 break;
308
309 case VT_R4:
310 switch (vtFrom)
311 {
312 case VT_EMPTY: V_R4(pd) = 0.0f; return S_OK;
313 case VT_I1: return VarR4FromI1(V_I1(ps), &V_R4(pd));
314 case VT_I2: return VarR4FromI2(V_I2(ps), &V_R4(pd));
315 case VT_I4: return VarR4FromI4(V_I4(ps), &V_R4(pd));
316 case VT_UI1: return VarR4FromUI1(V_UI1(ps), &V_R4(pd));
317 case VT_UI2: return VarR4FromUI2(V_UI2(ps), &V_R4(pd));
318 case VT_UI4: return VarR4FromUI4(V_UI4(ps), &V_R4(pd));
319 case VT_I8: return VarR4FromI8(V_I8(ps), &V_R4(pd));
320 case VT_UI8: return VarR4FromUI8(V_UI8(ps), &V_R4(pd));
321 case VT_R8: return VarR4FromR8(V_R8(ps), &V_R4(pd));
322 case VT_DATE: return VarR4FromDate(V_DATE(ps), &V_R4(pd));
323 case VT_BOOL: return VarR4FromBool(V_BOOL(ps), &V_R4(pd));
324 case VT_CY: return VarR4FromCy(V_CY(ps), &V_R4(pd));
325 case VT_DECIMAL: return VarR4FromDec(&V_DECIMAL(ps), &V_R4(pd));
326 case VT_DISPATCH: return VarR4FromDisp(V_DISPATCH(ps), lcid, &V_R4(pd));
327 case VT_BSTR: return VarR4FromStr(V_BSTR(ps), lcid, dwFlags, &V_R4(pd));
328 }
329 break;
330
331 case VT_R8:
332 switch (vtFrom)
333 {
334 case VT_EMPTY: V_R8(pd) = 0.0; return S_OK;
335 case VT_I1: return VarR8FromI1(V_I1(ps), &V_R8(pd));
336 case VT_I2: return VarR8FromI2(V_I2(ps), &V_R8(pd));
337 case VT_I4: return VarR8FromI4(V_I4(ps), &V_R8(pd));
338 case VT_UI1: return VarR8FromUI1(V_UI1(ps), &V_R8(pd));
339 case VT_UI2: return VarR8FromUI2(V_UI2(ps), &V_R8(pd));
340 case VT_UI4: return VarR8FromUI4(V_UI4(ps), &V_R8(pd));
341 case VT_I8: return VarR8FromI8(V_I8(ps), &V_R8(pd));
342 case VT_UI8: return VarR8FromUI8(V_UI8(ps), &V_R8(pd));
343 case VT_R4: return VarR8FromR4(V_R4(ps), &V_R8(pd));
344 case VT_DATE: return VarR8FromDate(V_DATE(ps), &V_R8(pd));
345 case VT_BOOL: return VarR8FromBool(V_BOOL(ps), &V_R8(pd));
346 case VT_CY: return VarR8FromCy(V_CY(ps), &V_R8(pd));
347 case VT_DECIMAL: return VarR8FromDec(&V_DECIMAL(ps), &V_R8(pd));
348 case VT_DISPATCH: return VarR8FromDisp(V_DISPATCH(ps), lcid, &V_R8(pd));
349 case VT_BSTR: return VarR8FromStr(V_BSTR(ps), lcid, dwFlags, &V_R8(pd));
350 }
351 break;
352
353 case VT_DATE:
354 switch (vtFrom)
355 {
356 case VT_EMPTY: V_DATE(pd) = 0.0; return S_OK;
357 case VT_I1: return VarDateFromI1(V_I1(ps), &V_DATE(pd));
358 case VT_I2: return VarDateFromI2(V_I2(ps), &V_DATE(pd));
359 case VT_I4: return VarDateFromI4(V_I4(ps), &V_DATE(pd));
360 case VT_UI1: return VarDateFromUI1(V_UI1(ps), &V_DATE(pd));
361 case VT_UI2: return VarDateFromUI2(V_UI2(ps), &V_DATE(pd));
362 case VT_UI4: return VarDateFromUI4(V_UI4(ps), &V_DATE(pd));
363 case VT_I8: return VarDateFromI8(V_I8(ps), &V_DATE(pd));
364 case VT_UI8: return VarDateFromUI8(V_UI8(ps), &V_DATE(pd));
365 case VT_R4: return VarDateFromR4(V_R4(ps), &V_DATE(pd));
366 case VT_R8: return VarDateFromR8(V_R8(ps), &V_DATE(pd));
367 case VT_BOOL: return VarDateFromBool(V_BOOL(ps), &V_DATE(pd));
368 case VT_CY: return VarDateFromCy(V_CY(ps), &V_DATE(pd));
369 case VT_DECIMAL: return VarDateFromDec(&V_DECIMAL(ps), &V_DATE(pd));
370 case VT_DISPATCH: return VarDateFromDisp(V_DISPATCH(ps), lcid, &V_DATE(pd));
371 case VT_BSTR: return VarDateFromStr(V_BSTR(ps), lcid, dwFlags, &V_DATE(pd));
372 }
373 break;
374
375 case VT_BOOL:
376 switch (vtFrom)
377 {
378 case VT_EMPTY: V_BOOL(pd) = 0; return S_OK;
379 case VT_I1: return VarBoolFromI1(V_I1(ps), &V_BOOL(pd));
380 case VT_I2: return VarBoolFromI2(V_I2(ps), &V_BOOL(pd));
381 case VT_I4: return VarBoolFromI4(V_I4(ps), &V_BOOL(pd));
382 case VT_UI1: return VarBoolFromUI1(V_UI1(ps), &V_BOOL(pd));
383 case VT_UI2: return VarBoolFromUI2(V_UI2(ps), &V_BOOL(pd));
384 case VT_UI4: return VarBoolFromUI4(V_UI4(ps), &V_BOOL(pd));
385 case VT_I8: return VarBoolFromI8(V_I8(ps), &V_BOOL(pd));
386 case VT_UI8: return VarBoolFromUI8(V_UI8(ps), &V_BOOL(pd));
387 case VT_R4: return VarBoolFromR4(V_R4(ps), &V_BOOL(pd));
388 case VT_R8: return VarBoolFromR8(V_R8(ps), &V_BOOL(pd));
389 case VT_DATE: return VarBoolFromDate(V_DATE(ps), &V_BOOL(pd));
390 case VT_CY: return VarBoolFromCy(V_CY(ps), &V_BOOL(pd));
391 case VT_DECIMAL: return VarBoolFromDec(&V_DECIMAL(ps), &V_BOOL(pd));
392 case VT_DISPATCH: return VarBoolFromDisp(V_DISPATCH(ps), lcid, &V_BOOL(pd));
393 case VT_BSTR: return VarBoolFromStr(V_BSTR(ps), lcid, dwFlags, &V_BOOL(pd));
394 }
395 break;
396
397 case VT_BSTR:
398 switch (vtFrom)
399 {
400 case VT_EMPTY:
401 V_BSTR(pd) = SysAllocStringLen(NULL, 0);
402 return V_BSTR(pd) ? S_OK : E_OUTOFMEMORY;
403 case VT_BOOL:
404 if (wFlags & (VARIANT_ALPHABOOL|VARIANT_LOCALBOOL))
405 return VarBstrFromBool(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
406 return VarBstrFromI2(V_BOOL(ps), lcid, dwFlags, &V_BSTR(pd));
407 case VT_I1: return VarBstrFromI1(V_I1(ps), lcid, dwFlags, &V_BSTR(pd));
408 case VT_I2: return VarBstrFromI2(V_I2(ps), lcid, dwFlags, &V_BSTR(pd));
409 case VT_I4: return VarBstrFromI4(V_I4(ps), lcid, dwFlags, &V_BSTR(pd));
410 case VT_UI1: return VarBstrFromUI1(V_UI1(ps), lcid, dwFlags, &V_BSTR(pd));
411 case VT_UI2: return VarBstrFromUI2(V_UI2(ps), lcid, dwFlags, &V_BSTR(pd));
412 case VT_UI4: return VarBstrFromUI4(V_UI4(ps), lcid, dwFlags, &V_BSTR(pd));
413 case VT_I8: return VarBstrFromI8(V_I8(ps), lcid, dwFlags, &V_BSTR(pd));
414 case VT_UI8: return VarBstrFromUI8(V_UI8(ps), lcid, dwFlags, &V_BSTR(pd));
415 case VT_R4: return VarBstrFromR4(V_R4(ps), lcid, dwFlags, &V_BSTR(pd));
416 case VT_R8: return VarBstrFromR8(V_R8(ps), lcid, dwFlags, &V_BSTR(pd));
417 case VT_DATE: return VarBstrFromDate(V_DATE(ps), lcid, dwFlags, &V_BSTR(pd));
418 case VT_CY: return VarBstrFromCy(V_CY(ps), lcid, dwFlags, &V_BSTR(pd));
419 case VT_DECIMAL: return VarBstrFromDec(&V_DECIMAL(ps), lcid, dwFlags, &V_BSTR(pd));
420 case VT_DISPATCH: return VarBstrFromDisp(V_DISPATCH(ps), lcid, dwFlags, &V_BSTR(pd));
421 }
422 break;
423
424 case VT_CY:
425 switch (vtFrom)
426 {
427 case VT_EMPTY: V_CY(pd).int64 = 0; return S_OK;
428 case VT_I1: return VarCyFromI1(V_I1(ps), &V_CY(pd));
429 case VT_I2: return VarCyFromI2(V_I2(ps), &V_CY(pd));
430 case VT_I4: return VarCyFromI4(V_I4(ps), &V_CY(pd));
431 case VT_UI1: return VarCyFromUI1(V_UI1(ps), &V_CY(pd));
432 case VT_UI2: return VarCyFromUI2(V_UI2(ps), &V_CY(pd));
433 case VT_UI4: return VarCyFromUI4(V_UI4(ps), &V_CY(pd));
434 case VT_I8: return VarCyFromI8(V_I8(ps), &V_CY(pd));
435 case VT_UI8: return VarCyFromUI8(V_UI8(ps), &V_CY(pd));
436 case VT_R4: return VarCyFromR4(V_R4(ps), &V_CY(pd));
437 case VT_R8: return VarCyFromR8(V_R8(ps), &V_CY(pd));
438 case VT_DATE: return VarCyFromDate(V_DATE(ps), &V_CY(pd));
439 case VT_BOOL: return VarCyFromBool(V_BOOL(ps), &V_CY(pd));
440 case VT_DECIMAL: return VarCyFromDec(&V_DECIMAL(ps), &V_CY(pd));
441 case VT_DISPATCH: return VarCyFromDisp(V_DISPATCH(ps), lcid, &V_CY(pd));
442 case VT_BSTR: return VarCyFromStr(V_BSTR(ps), lcid, dwFlags, &V_CY(pd));
443 }
444 break;
445
446 case VT_DECIMAL:
447 switch (vtFrom)
448 {
449 case VT_EMPTY:
450 case VT_BOOL:
451 DEC_SIGNSCALE(&V_DECIMAL(pd)) = SIGNSCALE(DECIMAL_POS,0);
452 DEC_HI32(&V_DECIMAL(pd)) = 0;
453 DEC_MID32(&V_DECIMAL(pd)) = 0;
454 /* VarDecFromBool() coerces to -1/0, ChangeTypeEx() coerces to 1/0.
455 * VT_NULL and VT_EMPTY always give a 0 value.
456 */
457 DEC_LO32(&V_DECIMAL(pd)) = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0;
458 return S_OK;
459 case VT_I1: return VarDecFromI1(V_I1(ps), &V_DECIMAL(pd));
460 case VT_I2: return VarDecFromI2(V_I2(ps), &V_DECIMAL(pd));
461 case VT_I4: return VarDecFromI4(V_I4(ps), &V_DECIMAL(pd));
462 case VT_UI1: return VarDecFromUI1(V_UI1(ps), &V_DECIMAL(pd));
463 case VT_UI2: return VarDecFromUI2(V_UI2(ps), &V_DECIMAL(pd));
464 case VT_UI4: return VarDecFromUI4(V_UI4(ps), &V_DECIMAL(pd));
465 case VT_I8: return VarDecFromI8(V_I8(ps), &V_DECIMAL(pd));
466 case VT_UI8: return VarDecFromUI8(V_UI8(ps), &V_DECIMAL(pd));
467 case VT_R4: return VarDecFromR4(V_R4(ps), &V_DECIMAL(pd));
468 case VT_R8: return VarDecFromR8(V_R8(ps), &V_DECIMAL(pd));
469 case VT_DATE: return VarDecFromDate(V_DATE(ps), &V_DECIMAL(pd));
470 case VT_CY: return VarDecFromCy(V_CY(ps), &V_DECIMAL(pd));
471 case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(pd));
472 case VT_BSTR: return VarDecFromStr(V_BSTR(ps), lcid, dwFlags, &V_DECIMAL(pd));
473 }
474 break;
475
476 case VT_UNKNOWN:
477 switch (vtFrom)
478 {
479 case VT_DISPATCH:
480 if (V_DISPATCH(ps) == NULL)
481 V_UNKNOWN(pd) = NULL;
482 else
483 res = IDispatch_QueryInterface(V_DISPATCH(ps), &IID_IUnknown, (LPVOID*)&V_UNKNOWN(pd));
484 break;
485 }
486 break;
487
488 case VT_DISPATCH:
489 switch (vtFrom)
490 {
491 case VT_UNKNOWN:
492 if (V_UNKNOWN(ps) == NULL)
493 V_DISPATCH(pd) = NULL;
494 else
495 res = IUnknown_QueryInterface(V_UNKNOWN(ps), &IID_IDispatch, (LPVOID*)&V_DISPATCH(pd));
496 break;
497 }
498 break;
499
500 case VT_RECORD:
501 break;
502 }
503 return res;
504 }
505
506 /* Coerce to/from an array */
507 static inline HRESULT VARIANT_CoerceArray(VARIANTARG* pd, VARIANTARG* ps, VARTYPE vt)
508 {
509 if (vt == VT_BSTR && V_VT(ps) == (VT_ARRAY|VT_UI1))
510 return BstrFromVector(V_ARRAY(ps), &V_BSTR(pd));
511
512 if (V_VT(ps) == VT_BSTR && vt == (VT_ARRAY|VT_UI1))
513 return VectorFromBstr(V_BSTR(ps), &V_ARRAY(pd));
514
515 if (V_VT(ps) == vt)
516 return SafeArrayCopy(V_ARRAY(ps), &V_ARRAY(pd));
517
518 return DISP_E_TYPEMISMATCH;
519 }
520
521 /******************************************************************************
522 * Check if a variants type is valid.
523 */
524 static inline HRESULT VARIANT_ValidateType(VARTYPE vt)
525 {
526 VARTYPE vtExtra = vt & VT_EXTRA_TYPE;
527
528 vt &= VT_TYPEMASK;
529
530 if (!(vtExtra & (VT_VECTOR|VT_RESERVED)))
531 {
532 if (vt < VT_VOID || vt == VT_RECORD || vt == VT_CLSID)
533 {
534 if ((vtExtra & (VT_BYREF|VT_ARRAY)) && vt <= VT_NULL)
535 return DISP_E_BADVARTYPE;
536 if (vt != (VARTYPE)15)
537 return S_OK;
538 }
539 }
540 return DISP_E_BADVARTYPE;
541 }
542
543 /******************************************************************************
544 * VariantInit [OLEAUT32.8]
545 *
546 * Initialise a variant.
547 *
548 * PARAMS
549 * pVarg [O] Variant to initialise
550 *
551 * RETURNS
552 * Nothing.
553 *
554 * NOTES
555 * This function simply sets the type of the variant to VT_EMPTY. It does not
556 * free any existing value, use VariantClear() for that.
557 */
558 void WINAPI VariantInit(VARIANTARG* pVarg)
559 {
560 TRACE("(%p)\n", pVarg);
561
562 V_VT(pVarg) = VT_EMPTY; /* Native doesn't set any other fields */
563 }
564
565 HRESULT VARIANT_ClearInd(VARIANTARG *pVarg)
566 {
567 HRESULT hres;
568
569 TRACE("(%p->(%s%s))\n", pVarg, debugstr_VT(pVarg), debugstr_VF(pVarg));
570
571 hres = VARIANT_ValidateType(V_VT(pVarg));
572 if (FAILED(hres))
573 return hres;
574
575 switch (V_VT(pVarg))
576 {
577 case VT_DISPATCH:
578 case VT_UNKNOWN:
579 if (V_UNKNOWN(pVarg))
580 IUnknown_Release(V_UNKNOWN(pVarg));
581 break;
582 case VT_UNKNOWN | VT_BYREF:
583 case VT_DISPATCH | VT_BYREF:
584 if(*V_UNKNOWNREF(pVarg))
585 IUnknown_Release(*V_UNKNOWNREF(pVarg));
586 break;
587 case VT_BSTR:
588 SysFreeString(V_BSTR(pVarg));
589 break;
590 case VT_BSTR | VT_BYREF:
591 SysFreeString(*V_BSTRREF(pVarg));
592 break;
593 case VT_VARIANT | VT_BYREF:
594 VariantClear(V_VARIANTREF(pVarg));
595 break;
596 case VT_RECORD:
597 case VT_RECORD | VT_BYREF:
598 {
599 struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal);
600 if (pBr->pRecInfo)
601 {
602 IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord);
603 IRecordInfo_Release(pBr->pRecInfo);
604 }
605 break;
606 }
607 default:
608 if (V_ISARRAY(pVarg) || (V_VT(pVarg) & ~VT_BYREF) == VT_SAFEARRAY)
609 {
610 if (V_ISBYREF(pVarg))
611 {
612 if (*V_ARRAYREF(pVarg))
613 hres = SafeArrayDestroy(*V_ARRAYREF(pVarg));
614 }
615 else if (V_ARRAY(pVarg))
616 hres = SafeArrayDestroy(V_ARRAY(pVarg));
617 }
618 break;
619 }
620
621 V_VT(pVarg) = VT_EMPTY;
622 return hres;
623 }
624
625 /******************************************************************************
626 * VariantClear [OLEAUT32.9]
627 *
628 * Clear a variant.
629 *
630 * PARAMS
631 * pVarg [I/O] Variant to clear
632 *
633 * RETURNS
634 * Success: S_OK. Any previous value in pVarg is freed and its type is set to VT_EMPTY.
635 * Failure: DISP_E_BADVARTYPE, if the variant is not a valid variant type.
636 */
637 HRESULT WINAPI VariantClear(VARIANTARG* pVarg)
638 {
639 HRESULT hres;
640
641 TRACE("(%p->(%s%s))\n", pVarg, debugstr_VT(pVarg), debugstr_VF(pVarg));
642
643 hres = VARIANT_ValidateType(V_VT(pVarg));
644
645 if (SUCCEEDED(hres))
646 {
647 if (!V_ISBYREF(pVarg))
648 {
649 if (V_ISARRAY(pVarg) || V_VT(pVarg) == VT_SAFEARRAY)
650 {
651 hres = SafeArrayDestroy(V_ARRAY(pVarg));
652 }
653 else if (V_VT(pVarg) == VT_BSTR)
654 {
655 SysFreeString(V_BSTR(pVarg));
656 }
657 else if (V_VT(pVarg) == VT_RECORD)
658 {
659 struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal);
660 if (pBr->pRecInfo)
661 {
662 IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord);
663 IRecordInfo_Release(pBr->pRecInfo);
664 }
665 }
666 else if (V_VT(pVarg) == VT_DISPATCH ||
667 V_VT(pVarg) == VT_UNKNOWN)
668 {
669 if (V_UNKNOWN(pVarg))
670 IUnknown_Release(V_UNKNOWN(pVarg));
671 }
672 }
673 V_VT(pVarg) = VT_EMPTY;
674 }
675 return hres;
676 }
677
678 /******************************************************************************
679 * Copy an IRecordInfo object contained in a variant.
680 */
681 static HRESULT VARIANT_CopyIRecordInfo(struct __tagBRECORD* pBr)
682 {
683 HRESULT hres = S_OK;
684
685 if (pBr->pRecInfo)
686 {
687 ULONG ulSize;
688
689 hres = IRecordInfo_GetSize(pBr->pRecInfo, &ulSize);
690 if (SUCCEEDED(hres))
691 {
692 PVOID pvRecord = HeapAlloc(GetProcessHeap(), 0, ulSize);
693 if (!pvRecord)
694 hres = E_OUTOFMEMORY;
695 else
696 {
697 memcpy(pvRecord, pBr->pvRecord, ulSize);
698 pBr->pvRecord = pvRecord;
699
700 hres = IRecordInfo_RecordCopy(pBr->pRecInfo, pvRecord, pvRecord);
701 if (SUCCEEDED(hres))
702 IRecordInfo_AddRef(pBr->pRecInfo);
703 }
704 }
705 }
706 else if (pBr->pvRecord)
707 hres = E_INVALIDARG;
708 return hres;
709 }
710
711 /******************************************************************************
712 * VariantCopy [OLEAUT32.10]
713 *
714 * Copy a variant.
715 *
716 * PARAMS
717 * pvargDest [O] Destination for copy
718 * pvargSrc [I] Source variant to copy
719 *
720 * RETURNS
721 * Success: S_OK. pvargDest contains a copy of pvargSrc.
722 * Failure: DISP_E_BADVARTYPE, if either variant has an invalid type.
723 * E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an
724 * HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(),
725 * or IRecordInfo_RecordCopy(), depending on the type of pvargSrc.
726 *
727 * NOTES
728 * - If pvargSrc == pvargDest, this function does nothing, and succeeds if
729 * pvargSrc is valid. Otherwise, pvargDest is always cleared using
730 * VariantClear() before pvargSrc is copied to it. If clearing pvargDest
731 * fails, so does this function.
732 * - VT_CLSID is a valid type type for pvargSrc, but not for pvargDest.
733 * - For by-value non-intrinsic types, a deep copy is made, i.e. The whole value
734 * is copied rather than just any pointers to it.
735 * - For by-value object types the object pointer is copied and the objects
736 * reference count increased using IUnknown_AddRef().
737 * - For all by-reference types, only the referencing pointer is copied.
738 */
739 HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
740 {
741 HRESULT hres = S_OK;
742
743 TRACE("(%p->(%s%s),%p->(%s%s))\n", pvargDest, debugstr_VT(pvargDest),
744 debugstr_VF(pvargDest), pvargSrc, debugstr_VT(pvargSrc),
745 debugstr_VF(pvargSrc));
746
747 if (V_TYPE(pvargSrc) == VT_CLSID || /* VT_CLSID is a special case */
748 FAILED(VARIANT_ValidateType(V_VT(pvargSrc))))
749 return DISP_E_BADVARTYPE;
750
751 if (pvargSrc != pvargDest &&
752 SUCCEEDED(hres = VariantClear(pvargDest)))
753 {
754 *pvargDest = *pvargSrc; /* Shallow copy the value */
755
756 if (!V_ISBYREF(pvargSrc))
757 {
758 if (V_ISARRAY(pvargSrc))
759 {
760 if (V_ARRAY(pvargSrc))
761 hres = SafeArrayCopy(V_ARRAY(pvargSrc), &V_ARRAY(pvargDest));
762 }
763 else if (V_VT(pvargSrc) == VT_BSTR)
764 {
765 V_BSTR(pvargDest) = SysAllocStringByteLen((char*)V_BSTR(pvargSrc), SysStringByteLen(V_BSTR(pvargSrc)));
766 if (!V_BSTR(pvargDest))
767 {
768 TRACE("!V_BSTR(pvargDest), SysAllocStringByteLen() failed to allocate %d bytes\n", SysStringByteLen(V_BSTR(pvargSrc)));
769 hres = E_OUTOFMEMORY;
770 }
771 }
772 else if (V_VT(pvargSrc) == VT_RECORD)
773 {
774 hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
775 }
776 else if (V_VT(pvargSrc) == VT_DISPATCH ||
777 V_VT(pvargSrc) == VT_UNKNOWN)
778 {
779 if (V_UNKNOWN(pvargSrc))
780 IUnknown_AddRef(V_UNKNOWN(pvargSrc));
781 }
782 }
783 }
784 return hres;
785 }
786
787 /* Return the byte size of a variants data */
788 static inline size_t VARIANT_DataSize(const VARIANT* pv)
789 {
790 switch (V_TYPE(pv))
791 {
792 case VT_I1:
793 case VT_UI1: return sizeof(BYTE);
794 case VT_I2:
795 case VT_UI2: return sizeof(SHORT);
796 case VT_INT:
797 case VT_UINT:
798 case VT_I4:
799 case VT_UI4: return sizeof(LONG);
800 case VT_I8:
801 case VT_UI8: return sizeof(LONGLONG);
802 case VT_R4: return sizeof(float);
803 case VT_R8: return sizeof(double);
804 case VT_DATE: return sizeof(DATE);
805 case VT_BOOL: return sizeof(VARIANT_BOOL);
806 case VT_DISPATCH:
807 case VT_UNKNOWN:
808 case VT_BSTR: return sizeof(void*);
809 case VT_CY: return sizeof(CY);
810 case VT_ERROR: return sizeof(SCODE);
811 }
812 TRACE("Shouldn't be called for vt %s%s!\n", debugstr_VT(pv), debugstr_VF(pv));
813 return 0;
814 }
815
816 /******************************************************************************
817 * VariantCopyInd [OLEAUT32.11]
818 *
819 * Copy a variant, dereferencing it if it is by-reference.
820 *
821 * PARAMS
822 * pvargDest [O] Destination for copy
823 * pvargSrc [I] Source variant to copy
824 *
825 * RETURNS
826 * Success: S_OK. pvargDest contains a copy of pvargSrc.
827 * Failure: An HRESULT error code indicating the error.
828 *
829 * NOTES
830 * Failure: DISP_E_BADVARTYPE, if either variant has an invalid by-value type.
831 * E_INVALIDARG, if pvargSrc is an invalid by-reference type.
832 * E_OUTOFMEMORY, if memory cannot be allocated. Otherwise an
833 * HRESULT error code from SafeArrayCopy(), IRecordInfo_GetSize(),
834 * or IRecordInfo_RecordCopy(), depending on the type of pvargSrc.
835 *
836 * NOTES
837 * - If pvargSrc is by-value, this function behaves exactly as VariantCopy().
838 * - If pvargSrc is by-reference, the value copied to pvargDest is the pointed-to
839 * value.
840 * - if pvargSrc == pvargDest, this function dereferences in place. Otherwise,
841 * pvargDest is always cleared using VariantClear() before pvargSrc is copied
842 * to it. If clearing pvargDest fails, so does this function.
843 */
844 HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
845 {
846 VARIANTARG vTmp, *pSrc = pvargSrc;
847 VARTYPE vt;
848 HRESULT hres = S_OK;
849
850 TRACE("(%p->(%s%s),%p->(%s%s))\n", pvargDest, debugstr_VT(pvargDest),
851 debugstr_VF(pvargDest), pvargSrc, debugstr_VT(pvargSrc),
852 debugstr_VF(pvargSrc));
853
854 if (!V_ISBYREF(pvargSrc))
855 return VariantCopy(pvargDest, pvargSrc);
856
857 /* Argument checking is more lax than VariantCopy()... */
858 vt = V_TYPE(pvargSrc);
859 if (V_ISARRAY(pvargSrc) || (V_VT(pvargSrc) == (VT_RECORD|VT_BYREF)) ||
860 (vt > VT_NULL && vt != (VARTYPE)15 && vt < VT_VOID &&
861 !(V_VT(pvargSrc) & (VT_VECTOR|VT_RESERVED))))
862 {
863 /* OK */
864 }
865 else
866 return E_INVALIDARG; /* ...And the return value for invalid types differs too */
867
868 if (pvargSrc == pvargDest)
869 {
870 /* In place copy. Use a shallow copy of pvargSrc & init pvargDest.
871 * This avoids an expensive VariantCopy() call - e.g. SafeArrayCopy().
872 */
873 vTmp = *pvargSrc;
874 pSrc = &vTmp;
875 V_VT(pvargDest) = VT_EMPTY;
876 }
877 else
878 {
879 /* Copy into another variant. Free the variant in pvargDest */
880 if (FAILED(hres = VariantClear(pvargDest)))
881 {
882 TRACE("VariantClear() of destination failed\n");
883 return hres;
884 }
885 }
886
887 if (V_ISARRAY(pSrc))
888 {
889 /* Native doesn't check that *V_ARRAYREF(pSrc) is valid */
890 hres = SafeArrayCopy(*V_ARRAYREF(pSrc), &V_ARRAY(pvargDest));
891 }
892 else if (V_VT(pSrc) == (VT_BSTR|VT_BYREF))
893 {
894 /* Native doesn't check that *V_BSTRREF(pSrc) is valid */
895 V_BSTR(pvargDest) = SysAllocStringByteLen((char*)*V_BSTRREF(pSrc), SysStringByteLen(*V_BSTRREF(pSrc)));
896 }
897 else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF))
898 {
899 V_UNION(pvargDest,brecVal) = V_UNION(pvargSrc,brecVal);
900 hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
901 }
902 else if (V_VT(pSrc) == (VT_DISPATCH|VT_BYREF) ||
903 V_VT(pSrc) == (VT_UNKNOWN|VT_BYREF))
904 {
905 /* Native doesn't check that *V_UNKNOWNREF(pSrc) is valid */
906 V_UNKNOWN(pvargDest) = *V_UNKNOWNREF(pSrc);
907 if (*V_UNKNOWNREF(pSrc))
908 IUnknown_AddRef(*V_UNKNOWNREF(pSrc));
909 }
910 else if (V_VT(pSrc) == (VT_VARIANT|VT_BYREF))
911 {
912 /* Native doesn't check that *V_VARIANTREF(pSrc) is valid */
913 if (V_VT(V_VARIANTREF(pSrc)) == (VT_VARIANT|VT_BYREF))
914 hres = E_INVALIDARG; /* Don't dereference more than one level */
915 else
916 hres = VariantCopyInd(pvargDest, V_VARIANTREF(pSrc));
917
918 /* Use the dereferenced variants type value, not VT_VARIANT */
919 goto VariantCopyInd_Return;
920 }
921 else if (V_VT(pSrc) == (VT_DECIMAL|VT_BYREF))
922 {
923 memcpy(&DEC_SCALE(&V_DECIMAL(pvargDest)), &DEC_SCALE(V_DECIMALREF(pSrc)),
924 sizeof(DECIMAL) - sizeof(USHORT));
925 }
926 else
927 {
928 /* Copy the pointed to data into this variant */
929 memcpy(&V_BYREF(pvargDest), V_BYREF(pSrc), VARIANT_DataSize(pSrc));
930 }
931
932 V_VT(pvargDest) = V_VT(pSrc) & ~VT_BYREF;
933
934 VariantCopyInd_Return:
935
936 if (pSrc != pvargSrc)
937 VariantClear(pSrc);
938
939 TRACE("returning 0x%08x, %p->(%s%s)\n", hres, pvargDest,
940 debugstr_VT(pvargDest), debugstr_VF(pvargDest));
941 return hres;
942 }
943
944 /******************************************************************************
945 * VariantChangeType [OLEAUT32.12]
946 *
947 * Change the type of a variant.
948 *
949 * PARAMS
950 * pvargDest [O] Destination for the converted variant
951 * pvargSrc [O] Source variant to change the type of
952 * wFlags [I] VARIANT_ flags from "oleauto.h"
953 * vt [I] Variant type to change pvargSrc into
954 *
955 * RETURNS
956 * Success: S_OK. pvargDest contains the converted value.
957 * Failure: An HRESULT error code describing the failure.
958 *
959 * NOTES
960 * The LCID used for the conversion is LOCALE_USER_DEFAULT.
961 * See VariantChangeTypeEx.
962 */
963 HRESULT WINAPI VariantChangeType(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
964 USHORT wFlags, VARTYPE vt)
965 {
966 return VariantChangeTypeEx( pvargDest, pvargSrc, LOCALE_USER_DEFAULT, wFlags, vt );
967 }
968
969 /******************************************************************************
970 * VariantChangeTypeEx [OLEAUT32.147]
971 *
972 * Change the type of a variant.
973 *
974 * PARAMS
975 * pvargDest [O] Destination for the converted variant
976 * pvargSrc [O] Source variant to change the type of
977 * lcid [I] LCID for the conversion
978 * wFlags [I] VARIANT_ flags from "oleauto.h"
979 * vt [I] Variant type to change pvargSrc into
980 *
981 * RETURNS
982 * Success: S_OK. pvargDest contains the converted value.
983 * Failure: An HRESULT error code describing the failure.
984 *
985 * NOTES
986 * pvargDest and pvargSrc can point to the same variant to perform an in-place
987 * conversion. If the conversion is successful, pvargSrc will be freed.
988 */
989 HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc,
990 LCID lcid, USHORT wFlags, VARTYPE vt)
991 {
992 HRESULT res = S_OK;
993
994 TRACE("(%p->(%s%s),%p->(%s%s),0x%08x,0x%04x,%s%s)\n", pvargDest,
995 debugstr_VT(pvargDest), debugstr_VF(pvargDest), pvargSrc,
996 debugstr_VT(pvargSrc), debugstr_VF(pvargSrc), lcid, wFlags,
997 debugstr_vt(vt), debugstr_vf(vt));
998
999 if (vt == VT_CLSID)
1000 res = DISP_E_BADVARTYPE;
1001 else
1002 {
1003 res = VARIANT_ValidateType(V_VT(pvargSrc));
1004
1005 if (SUCCEEDED(res))
1006 {
1007 res = VARIANT_ValidateType(vt);
1008
1009 if (SUCCEEDED(res))
1010 {
1011 VARIANTARG vTmp, vSrcDeref;
1012
1013 if(V_ISBYREF(pvargSrc) && !V_BYREF(pvargSrc))
1014 res = DISP_E_TYPEMISMATCH;
1015 else
1016 {
1017 V_VT(&vTmp) = VT_EMPTY;
1018 V_VT(&vSrcDeref) = VT_EMPTY;
1019 VariantClear(&vTmp);
1020 VariantClear(&vSrcDeref);
1021 }
1022
1023 if (SUCCEEDED(res))
1024 {
1025 res = VariantCopyInd(&vSrcDeref, pvargSrc);
1026 if (SUCCEEDED(res))
1027 {
1028 if (V_ISARRAY(&vSrcDeref) || (vt & VT_ARRAY))
1029 res = VARIANT_CoerceArray(&vTmp, &vSrcDeref, vt);
1030 else
1031 res = VARIANT_Coerce(&vTmp, lcid, wFlags, &vSrcDeref, vt);
1032
1033 if (SUCCEEDED(res)) {
1034 V_VT(&vTmp) = vt;
1035 VariantCopy(pvargDest, &vTmp);
1036 }
1037 VariantClear(&vTmp);
1038 VariantClear(&vSrcDeref);
1039 }
1040 }
1041 }
1042 }
1043 }
1044
1045 TRACE("returning 0x%08x, %p->(%s%s)\n", res, pvargDest,
1046 debugstr_VT(pvargDest), debugstr_VF(pvargDest));
1047 return res;
1048 }
1049
1050 /* Date Conversions */
1051
1052 #define IsLeapYear(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
1053
1054 /* Convert a VT_DATE value to a Julian Date */
1055 static inline int VARIANT_JulianFromDate(int dateIn)
1056 {
1057 int julianDays = dateIn;
1058
1059 julianDays -= DATE_MIN; /* Convert to + days from 1 Jan 100 AD */
1060 julianDays += 1757585; /* Convert to + days from 23 Nov 4713 BC (Julian) */
1061 return julianDays;
1062 }
1063
1064 /* Convert a Julian Date to a VT_DATE value */
1065 static inline int VARIANT_DateFromJulian(int dateIn)
1066 {
1067 int julianDays = dateIn;
1068
1069 julianDays -= 1757585; /* Convert to + days from 1 Jan 100 AD */
1070 julianDays += DATE_MIN; /* Convert to +/- days from 1 Jan 1899 AD */
1071 return julianDays;
1072 }
1073
1074 /* Convert a Julian date to Day/Month/Year - from PostgreSQL */
1075 static inline void VARIANT_DMYFromJulian(int jd, USHORT *year, USHORT *month, USHORT *day)
1076 {
1077 int j, i, l, n;
1078
1079 l = jd + 68569;
1080 n = l * 4 / 146097;
1081 l -= (n * 146097 + 3) / 4;
1082 i = (4000 * (l + 1)) / 1461001;
1083 l += 31 - (i * 1461) / 4;
1084 j = (l * 80) / 2447;
1085 *day = l - (j * 2447) / 80;
1086 l = j / 11;
1087 *month = (j + 2) - (12 * l);
1088 *year = 100 * (n - 49) + i + l;
1089 }
1090
1091 /* Convert Day/Month/Year to a Julian date - from PostgreSQL */
1092 static inline double VARIANT_JulianFromDMY(USHORT year, USHORT month, USHORT day)
1093 {
1094 int m12 = (month - 14) / 12;
1095
1096 return ((1461 * (year + 4800 + m12)) / 4 + (367 * (month - 2 - 12 * m12)) / 12 -
1097 (3 * ((year + 4900 + m12) / 100)) / 4 + day - 32075);
1098 }
1099
1100 /* Macros for accessing DOS format date/time fields */
1101 #define DOS_YEAR(x) (1980 + (x >> 9))
1102 #define DOS_MONTH(x) ((x >> 5) & 0xf)
1103 #define DOS_DAY(x) (x & 0x1f)
1104 #define DOS_HOUR(x) (x >> 11)
1105 #define DOS_MINUTE(x) ((x >> 5) & 0x3f)
1106 #define DOS_SECOND(x) ((x & 0x1f) << 1)
1107 /* Create a DOS format date/time */
1108 #define DOS_DATE(d,m,y) (d | (m << 5) | ((y-1980) << 9))
1109 #define DOS_TIME(h,m,s) ((s >> 1) | (m << 5) | (h << 11))
1110
1111 /* Roll a date forwards or backwards to correct it */
1112 static HRESULT VARIANT_RollUdate(UDATE *lpUd)
1113 {
1114 static const BYTE days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1115 short iYear, iMonth, iDay, iHour, iMinute, iSecond;
1116
1117 /* interpret values signed */
1118 iYear = lpUd->st.wYear;
1119 iMonth = lpUd->st.wMonth;
1120 iDay = lpUd->st.wDay;
1121 iHour = lpUd->st.wHour;
1122 iMinute = lpUd->st.wMinute;
1123 iSecond = lpUd->st.wSecond;
1124
1125 TRACE("Raw date: %d/%d/%d %d:%d:%d\n", iDay, iMonth,
1126 iYear, iHour, iMinute, iSecond);
1127
1128 if (iYear > 9999 || iYear < -9999)
1129 return E_INVALIDARG; /* Invalid value */
1130 /* Year 0 to 29 are treated as 2000 + year */
1131 if (iYear >= 0 && iYear < 30)
1132 iYear += 2000;
1133 /* Remaining years < 100 are treated as 1900 + year */
1134 else if (iYear >= 30 && iYear < 100)
1135 iYear += 1900;
1136
1137 iMinute += iSecond / 60;
1138 iSecond = iSecond % 60;
1139 iHour += iMinute / 60;
1140 iMinute = iMinute % 60;
1141 iDay += iHour / 24;
1142 iHour = iHour % 24;
1143 iYear += iMonth / 12;
1144 iMonth = iMonth % 12;
1145 if (iMonth<=0) {iMonth+=12; iYear--;}
1146 while (iDay > days[iMonth])
1147 {
1148 if (iMonth == 2 && IsLeapYear(iYear))
1149 iDay -= 29;
1150 else
1151 iDay -= days[iMonth];
1152 iMonth++;
1153 iYear += iMonth / 12;
1154 iMonth = iMonth % 12;
1155 }
1156 while (iDay <= 0)
1157 {
1158 iMonth--;
1159 if (iMonth<=0) {iMonth+=12; iYear--;}
1160 if (iMonth == 2 && IsLeapYear(iYear))
1161 iDay += 29;
1162 else
1163 iDay += days[iMonth];
1164 }
1165
1166 if (iSecond<0){iSecond+=60; iMinute--;}
1167 if (iMinute<0){iMinute+=60; iHour--;}
1168 if (iHour<0) {iHour+=24; iDay--;}
1169 if (iYear<=0) iYear+=2000;
1170
1171 lpUd->st.wYear = iYear;
1172 lpUd->st.wMonth = iMonth;
1173 lpUd->st.wDay = iDay;
1174 lpUd->st.wHour = iHour;
1175 lpUd->st.wMinute = iMinute;
1176 lpUd->st.wSecond = iSecond;
1177
1178 TRACE("Rolled date: %d/%d/%d %d:%d:%d\n", lpUd->st.wDay, lpUd->st.wMonth,
1179 lpUd->st.wYear, lpUd->st.wHour, lpUd->st.wMinute, lpUd->st.wSecond);
1180 return S_OK;
1181 }
1182
1183 /**********************************************************************
1184 * DosDateTimeToVariantTime [OLEAUT32.14]
1185 *
1186 * Convert a Dos format date and time into variant VT_DATE format.
1187 *
1188 * PARAMS
1189 * wDosDate [I] Dos format date
1190 * wDosTime [I] Dos format time
1191 * pDateOut [O] Destination for VT_DATE format
1192 *
1193 * RETURNS
1194 * Success: TRUE. pDateOut contains the converted time.
1195 * Failure: FALSE, if wDosDate or wDosTime are invalid (see notes).
1196 *
1197 * NOTES
1198 * - Dos format dates can only hold dates from 1-Jan-1980 to 31-Dec-2099.
1199 * - Dos format times are accurate to only 2 second precision.
1200 * - The format of a Dos Date is:
1201 *| Bits Values Meaning
1202 *| ---- ------ -------
1203 *| 0-4 1-31 Day of the week. 0 rolls back one day. A value greater than
1204 *| the days in the month rolls forward the extra days.
1205 *| 5-8 1-12 Month of the year. 0 rolls back to December of the previous
1206 *| year. 13-15 are invalid.
1207 *| 9-15 0-119 Year based from 1980 (Max 2099). 120-127 are invalid.
1208 * - The format of a Dos Time is:
1209 *| Bits Values Meaning
1210 *| ---- ------ -------
1211 *| 0-4 0-29 Seconds/2. 30 and 31 are invalid.
1212 *| 5-10 0-59 Minutes. 60-63 are invalid.
1213 *| 11-15 0-23 Hours (24 hour clock). 24-32 are invalid.
1214 */
1215 INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime,
1216 double *pDateOut)
1217 {
1218 UDATE ud;
1219
1220 TRACE("(0x%x(%d/%d/%d),0x%x(%d:%d:%d),%p)\n",
1221 wDosDate, DOS_YEAR(wDosDate), DOS_MONTH(wDosDate), DOS_DAY(wDosDate),
1222 wDosTime, DOS_HOUR(wDosTime), DOS_MINUTE(wDosTime), DOS_SECOND(wDosTime),
1223 pDateOut);
1224
1225 ud.st.wYear = DOS_YEAR(wDosDate);
1226 ud.st.wMonth = DOS_MONTH(wDosDate);
1227 if (ud.st.wYear > 2099 || ud.st.wMonth > 12)
1228 return FALSE;
1229 ud.st.wDay = DOS_DAY(wDosDate);
1230 ud.st.wHour = DOS_HOUR(wDosTime);
1231 ud.st.wMinute = DOS_MINUTE(wDosTime);
1232 ud.st.wSecond = DOS_SECOND(wDosTime);
1233 ud.st.wDayOfWeek = ud.st.wMilliseconds = 0;
1234 if (ud.st.wHour > 23 || ud.st.wMinute > 59 || ud.st.wSecond > 59)
1235 return FALSE; /* Invalid values in Dos*/
1236
1237 return VarDateFromUdate(&ud, 0, pDateOut) == S_OK;
1238 }
1239
1240 /**********************************************************************
1241 * VariantTimeToDosDateTime [OLEAUT32.13]
1242 *
1243 * Convert a variant format date into a Dos format date and time.
1244 *
1245 * dateIn [I] VT_DATE time format
1246 * pwDosDate [O] Destination for Dos format date
1247 * pwDosTime [O] Destination for Dos format time
1248 *
1249 * RETURNS
1250 * Success: TRUE. pwDosDate and pwDosTime contains the converted values.
1251 * Failure: FALSE, if dateIn cannot be represented in Dos format.
1252 *
1253 * NOTES
1254 * See DosDateTimeToVariantTime() for Dos format details and bugs.
1255 */
1256 INT WINAPI VariantTimeToDosDateTime(double dateIn, USHORT *pwDosDate, USHORT *pwDosTime)
1257 {
1258 UDATE ud;
1259
1260 TRACE("(%g,%p,%p)\n", dateIn, pwDosDate, pwDosTime);
1261
1262 if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
1263 return FALSE;
1264
1265 if (ud.st.wYear < 1980 || ud.st.wYear > 2099)
1266 return FALSE;
1267
1268 *pwDosDate = DOS_DATE(ud.st.wDay, ud.st.wMonth, ud.st.wYear);
1269 *pwDosTime = DOS_TIME(ud.st.wHour, ud.st.wMinute, ud.st.wSecond);
1270
1271 TRACE("Returning 0x%x(%d/%d/%d), 0x%x(%d:%d:%d)\n",
1272 *pwDosDate, DOS_YEAR(*pwDosDate), DOS_MONTH(*pwDosDate), DOS_DAY(*pwDosDate),
1273 *pwDosTime, DOS_HOUR(*pwDosTime), DOS_MINUTE(*pwDosTime), DOS_SECOND(*pwDosTime));
1274 return TRUE;
1275 }
1276
1277 /***********************************************************************
1278 * SystemTimeToVariantTime [OLEAUT32.184]
1279 *
1280 * Convert a System format date and time into variant VT_DATE format.
1281 *
1282 * PARAMS
1283 * lpSt [I] System format date and time
1284 * pDateOut [O] Destination for VT_DATE format date
1285 *
1286 * RETURNS
1287 * Success: TRUE. *pDateOut contains the converted value.
1288 * Failure: FALSE, if lpSt cannot be represented in VT_DATE format.
1289 */
1290 INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut)
1291 {
1292 UDATE ud;
1293
1294 TRACE("(%p->%d/%d/%d %d:%d:%d,%p)\n", lpSt, lpSt->wDay, lpSt->wMonth,
1295 lpSt->wYear, lpSt->wHour, lpSt->wMinute, lpSt->wSecond, pDateOut);
1296
1297 if (lpSt->wMonth > 12)
1298 return FALSE;
1299
1300 ud.st = *lpSt;
1301 return VarDateFromUdate(&ud, 0, pDateOut) == S_OK;
1302 }
1303
1304 /***********************************************************************
1305 * VariantTimeToSystemTime [OLEAUT32.185]
1306 *
1307 * Convert a variant VT_DATE into a System format date and time.
1308 *
1309 * PARAMS
1310 * datein [I] Variant VT_DATE format date
1311 * lpSt [O] Destination for System format date and time
1312 *
1313 * RETURNS
1314 * Success: TRUE. *lpSt contains the converted value.
1315 * Failure: FALSE, if dateIn is too large or small.
1316 */
1317 INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt)
1318 {
1319 UDATE ud;
1320
1321 TRACE("(%g,%p)\n", dateIn, lpSt);
1322
1323 if (FAILED(VarUdateFromDate(dateIn, 0, &ud)))
1324 return FALSE;
1325
1326 *lpSt = ud.st;
1327 return TRUE;
1328 }
1329
1330 /***********************************************************************
1331 * VarDateFromUdateEx [OLEAUT32.319]
1332 *
1333 * Convert an unpacked format date and time to a variant VT_DATE.
1334 *
1335 * PARAMS
1336 * pUdateIn [I] Unpacked format date and time to convert
1337 * lcid [I] Locale identifier for the conversion
1338 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1339 * pDateOut [O] Destination for variant VT_DATE.
1340 *
1341 * RETURNS
1342 * Success: S_OK. *pDateOut contains the converted value.
1343 * Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
1344 */
1345 HRESULT WINAPI VarDateFromUdateEx(UDATE *pUdateIn, LCID lcid, ULONG dwFlags, DATE *pDateOut)
1346 {
1347 UDATE ud;
1348 double dateVal, dateSign;
1349
1350 TRACE("(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08x,0x%08x,%p)\n", pUdateIn,
1351 pUdateIn->st.wMonth, pUdateIn->st.wDay, pUdateIn->st.wYear,
1352 pUdateIn->st.wHour, pUdateIn->st.wMinute, pUdateIn->st.wSecond,
1353 pUdateIn->st.wMilliseconds, pUdateIn->st.wDayOfWeek,
1354 pUdateIn->wDayOfYear, lcid, dwFlags, pDateOut);
1355
1356 if (lcid != MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT))
1357 FIXME("lcid possibly not handled, treating as en-us\n");
1358
1359 ud = *pUdateIn;
1360
1361 if (dwFlags & VAR_VALIDDATE)
1362 WARN("Ignoring VAR_VALIDDATE\n");
1363
1364 if (FAILED(VARIANT_RollUdate(&ud)))
1365 return E_INVALIDARG;
1366
1367 /* Date */
1368 dateVal = VARIANT_DateFromJulian(VARIANT_JulianFromDMY(ud.st.wYear, ud.st.wMonth, ud.st.wDay));
1369
1370 /* Sign */
1371 dateSign = (dateVal < 0.0) ? -1.0 : 1.0;
1372
1373 /* Time */
1374 dateVal += ud.st.wHour / 24.0 * dateSign;
1375 dateVal += ud.st.wMinute / 1440.0 * dateSign;
1376 dateVal += ud.st.wSecond / 86400.0 * dateSign;
1377
1378 TRACE("Returning %g\n", dateVal);
1379 *pDateOut = dateVal;
1380 return S_OK;
1381 }
1382
1383 /***********************************************************************
1384 * VarDateFromUdate [OLEAUT32.330]
1385 *
1386 * Convert an unpacked format date and time to a variant VT_DATE.
1387 *
1388 * PARAMS
1389 * pUdateIn [I] Unpacked format date and time to convert
1390 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1391 * pDateOut [O] Destination for variant VT_DATE.
1392 *
1393 * RETURNS
1394 * Success: S_OK. *pDateOut contains the converted value.
1395 * Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format.
1396 *
1397 * NOTES
1398 * This function uses the United States English locale for the conversion. Use
1399 * VarDateFromUdateEx() for alternate locales.
1400 */
1401 HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut)
1402 {
1403 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1404
1405 return VarDateFromUdateEx(pUdateIn, lcid, dwFlags, pDateOut);
1406 }
1407
1408 /***********************************************************************
1409 * VarUdateFromDate [OLEAUT32.331]
1410 *
1411 * Convert a variant VT_DATE into an unpacked format date and time.
1412 *
1413 * PARAMS
1414 * datein [I] Variant VT_DATE format date
1415 * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
1416 * lpUdate [O] Destination for unpacked format date and time
1417 *
1418 * RETURNS
1419 * Success: S_OK. *lpUdate contains the converted value.
1420 * Failure: E_INVALIDARG, if dateIn is too large or small.
1421 */
1422 HRESULT WINAPI VarUdateFromDate(DATE dateIn, ULONG dwFlags, UDATE *lpUdate)
1423 {
1424 /* Cumulative totals of days per month */
1425 static const USHORT cumulativeDays[] =
1426 {
1427 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
1428 };
1429 double datePart, timePart;
1430 int julianDays;
1431
1432 TRACE("(%g,0x%08x,%p)\n", dateIn, dwFlags, lpUdate);
1433
1434 if (dateIn <= (DATE_MIN - 1.0) || dateIn >= (DATE_MAX + 1.0))
1435 return E_INVALIDARG;
1436
1437 datePart = dateIn < 0.0 ? ceil(dateIn) : floor(dateIn);
1438 /* Compensate for int truncation (always downwards) */
1439 timePart = fabs(dateIn - datePart) + 0.00000000001;
1440 if (timePart >= 1.0)
1441 timePart -= 0.00000000001;
1442
1443 /* Date */
1444 julianDays = VARIANT_JulianFromDate(dateIn);
1445 VARIANT_DMYFromJulian(julianDays, &lpUdate->st.wYear, &lpUdate->st.wMonth,
1446 &lpUdate->st.wDay);
1447
1448 datePart = (datePart + 1.5) / 7.0;
1449 lpUdate->st.wDayOfWeek = (datePart - floor(datePart)) * 7;
1450 if (lpUdate->st.wDayOfWeek == 0)
1451 lpUdate->st.wDayOfWeek = 5;
1452 else if (lpUdate->st.wDayOfWeek == 1)
1453 lpUdate->st.wDayOfWeek = 6;
1454 else
1455 lpUdate->st.wDayOfWeek -= 2;
1456
1457 if (lpUdate->st.wMonth > 2 && IsLeapYear(lpUdate->st.wYear))
1458 lpUdate->wDayOfYear = 1; /* After February, in a leap year */
1459 else
1460 lpUdate->wDayOfYear = 0;
1461
1462 lpUdate->wDayOfYear += cumulativeDays[lpUdate->st.wMonth];
1463 lpUdate->wDayOfYear += lpUdate->st.wDay;
1464
1465 /* Time */
1466 timePart *= 24.0;
1467 lpUdate->st.wHour = timePart;
1468 timePart -= lpUdate->st.wHour;
1469 timePart *= 60.0;
1470 lpUdate->st.wMinute = timePart;
1471 timePart -= lpUdate->st.wMinute;
1472 timePart *= 60.0;
1473 lpUdate->st.wSecond = timePart;
1474 timePart -= lpUdate->st.wSecond;
1475 lpUdate->st.wMilliseconds = 0;
1476 if (timePart > 0.5)
1477 {
1478 /* Round the milliseconds, adjusting the time/date forward if needed */
1479 if (lpUdate->st.wSecond < 59)
1480 lpUdate->st.wSecond++;
1481 else
1482 {
1483 lpUdate->st.wSecond = 0;
1484 if (lpUdate->st.wMinute < 59)
1485 lpUdate->st.wMinute++;
1486 else
1487 {
1488 lpUdate->st.wMinute = 0;
1489 if (lpUdate->st.wHour < 23)
1490 lpUdate->st.wHour++;
1491 else
1492 {
1493 lpUdate->st.wHour = 0;
1494 /* Roll over a whole day */
1495 if (++lpUdate->st.wDay > 28)
1496 VARIANT_RollUdate(lpUdate);
1497 }
1498 }
1499 }
1500 }
1501 return S_OK;
1502 }
1503
1504 #define GET_NUMBER_TEXT(fld,name) \
1505 buff[0] = 0; \
1506 if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \
1507 WARN("buffer too small for " #fld "\n"); \
1508 else \
1509 if (buff[0]) lpChars->name = buff[0]; \
1510 TRACE("lcid 0x%x, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name)
1511
1512 /* Get the valid number characters for an lcid */
1513 static void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
1514 {
1515 static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',',','$',0,'.',',' };
1516 static CRITICAL_SECTION csLastChars = { NULL, -1, 0, 0, 0, 0 };
1517 static VARIANT_NUMBER_CHARS lastChars;
1518 static LCID lastLcid = -1;
1519 static DWORD lastFlags = 0;
1520 LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
1521 WCHAR buff[4];
1522
1523 /* To make caching thread-safe, a critical section is needed */
1524 EnterCriticalSection(&csLastChars);
1525
1526 /* Asking for default locale entries is very expensive: It is a registry
1527 server call. So cache one locally, as Microsoft does it too */
1528 if(lcid == lastLcid && dwFlags == lastFlags)
1529 {
1530 memcpy(lpChars, &lastChars, sizeof(defaultChars));
1531 LeaveCriticalSection(&csLastChars);
1532 return;
1533 }
1534
1535 memcpy(lpChars, &defaultChars, sizeof(defaultChars));
1536 GET_NUMBER_TEXT(LOCALE_SNEGATIVESIGN, cNegativeSymbol);
1537 GET_NUMBER_TEXT(LOCALE_SPOSITIVESIGN, cPositiveSymbol);
1538 GET_NUMBER_TEXT(LOCALE_SDECIMAL, cDecimalPoint);
1539 GET_NUMBER_TEXT(LOCALE_STHOUSAND, cDigitSeparator);
1540 GET_NUMBER_TEXT(LOCALE_SMONDECIMALSEP, cCurrencyDecimalPoint);
1541 GET_NUMBER_TEXT(LOCALE_SMONTHOUSANDSEP, cCurrencyDigitSeparator);
1542
1543 /* Local currency symbols are often 2 characters */
1544 lpChars->cCurrencyLocal2 = '\0';
1545 switch(GetLocaleInfoW(lcid, lctype|LOCALE_SCURRENCY, buff, sizeof(buff)/sizeof(WCHAR)))
1546 {
1547 case 3: lpChars->cCurrencyLocal2 = buff[1]; /* Fall through */
1548 case 2: lpChars->cCurrencyLocal = buff[0];
1549 break;
1550 default: WARN("buffer too small for LOCALE_SCURRENCY\n");
1551 }
1552 TRACE("lcid 0x%x, cCurrencyLocal =%d,%d '%c','%c'\n", lcid, lpChars->cCurrencyLocal,
1553 lpChars->cCurrencyLocal2, lpChars->cCurrencyLocal, lpChars->cCurrencyLocal2);
1554
1555 memcpy(&lastChars, lpChars, sizeof(defaultChars));
1556 lastLcid = lcid;
1557 lastFlags = dwFlags;
1558 LeaveCriticalSection(&csLastChars);
1559 }
1560
1561 /* Number Parsing States */
1562 #define B_PROCESSING_EXPONENT 0x1
1563 #define B_NEGATIVE_EXPONENT 0x2
1564 #define B_EXPONENT_START 0x4
1565 #define B_INEXACT_ZEROS 0x8
1566 #define B_LEADING_ZERO 0x10
1567 #define B_PROCESSING_HEX 0x20
1568 #define B_PROCESSING_OCT 0x40
1569
1570 /**********************************************************************
1571 * VarParseNumFromStr [OLEAUT32.46]
1572 *
1573 * Parse a string containing a number into a NUMPARSE structure.
1574 *
1575 * PARAMS
1576 * lpszStr [I] String to parse number from
1577 * lcid [I] Locale Id for the conversion
1578 * dwFlags [I] 0, or LOCALE_NOUSEROVERRIDE to use system default number chars
1579 * pNumprs [I/O] Destination for parsed number
1580 * rgbDig [O] Destination for digits read in
1581 *
1582 * RETURNS
1583 * Success: S_OK. pNumprs and rgbDig contain the parsed representation of
1584 * the number.
1585 * Failure: E_INVALIDARG, if any parameter is invalid.
1586 * DISP_E_TYPEMISMATCH, if the string is not a number or is formatted
1587 * incorrectly.
1588 * DISP_E_OVERFLOW, if rgbDig is too small to hold the number.
1589 *
1590 * NOTES
1591 * pNumprs must have the following fields set:
1592 * cDig: Set to the size of rgbDig.
1593 * dwInFlags: Set to the allowable syntax of the number using NUMPRS_ flags
1594 * from "oleauto.h".
1595 *
1596 * FIXME
1597 * - I am unsure if this function should parse non-Arabic (e.g. Thai)
1598 * numerals, so this has not been implemented.
1599 */
1600 HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
1601 NUMPARSE *pNumprs, BYTE *rgbDig)
1602 {
1603 VARIANT_NUMBER_CHARS chars;
1604 BYTE rgbTmp[1024];
1605 DWORD dwState = B_EXPONENT_START|B_INEXACT_ZEROS;
1606 int iMaxDigits = sizeof(rgbTmp) / sizeof(BYTE);
1607 int cchUsed = 0;
1608
1609 TRACE("(%s,%d,0x%08x,%p,%p)\n", debugstr_w(lpszStr), lcid, dwFlags, pNumprs, rgbDig);
1610
1611 if (!pNumprs || !rgbDig)
1612 return E_INVALIDARG;
1613
1614 if (pNumprs->cDig < iMaxDigits)
1615 iMaxDigits = pNumprs->cDig;
1616
1617 pNumprs->cDig = 0;
1618 pNumprs->dwOutFlags = 0;
1619 pNumprs->cchUsed = 0;
1620 pNumprs->nBaseShift = 0;
1621 pNumprs->nPwr10 = 0;
1622
1623 if (!lpszStr)
1624 return DISP_E_TYPEMISMATCH;
1625
1626 VARIANT_GetLocalisedNumberChars(&chars, lcid, dwFlags);
1627
1628 /* First consume all the leading symbols and space from the string */
1629 while (1)
1630 {
1631 if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && isspaceW(*lpszStr))
1632 {
1633 pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE;
1634 do
1635 {
1636 cchUsed++;
1637 lpszStr++;
1638 } while (isspaceW(*lpszStr));
1639 }
1640 else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS &&
1641 *lpszStr == chars.cPositiveSymbol &&
1642 !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS))
1643 {
1644 pNumprs->dwOutFlags |= NUMPRS_LEADING_PLUS;
1645 cchUsed++;
1646 lpszStr++;
1647 }
1648 else if (pNumprs->dwInFlags & NUMPRS_LEADING_MINUS &&
1649 *lpszStr == chars.cNegativeSymbol &&
1650 !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS))
1651 {
1652 pNumprs->dwOutFlags |= (NUMPRS_LEADING_MINUS|NUMPRS_NEG);
1653 cchUsed++;
1654 lpszStr++;
1655 }
1656 else if (pNumprs->dwInFlags & NUMPRS_CURRENCY &&
1657 !(pNumprs->dwOutFlags & NUMPRS_CURRENCY) &&
1658 *lpszStr == chars.cCurrencyLocal &&
1659 (!chars.cCurrencyLocal2 || lpszStr[1] == chars.cCurrencyLocal2))
1660 {
1661 pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
1662 cchUsed++;
1663 lpszStr++;
1664 /* Only accept currency characters */
1665 chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
1666 chars.cDigitSeparator = chars.cCurrencyDigitSeparator;
1667 }
1668 else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
1669 !(pNumprs->dwOutFlags & NUMPRS_PARENS))
1670 {
1671 pNumprs->dwOutFlags |= NUMPRS_PARENS;
1672 cchUsed++;
1673 lpszStr++;
1674 }
1675 else
1676 break;
1677 }
1678
1679 if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY))
1680 {
1681 /* Only accept non-currency characters */
1682 chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
1683 chars.cCurrencyDigitSeparator = chars.cDigitSeparator;
1684 }
1685
1686 if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
1687 pNumprs->dwInFlags & NUMPRS_HEX_OCT)
1688 {
1689 dwState |= B_PROCESSING_HEX;
1690 pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
1691 cchUsed=cchUsed+2;
1692 lpszStr=lpszStr+2;
1693 }
1694 else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
1695 pNumprs->dwInFlags & NUMPRS_HEX_OCT)
1696 {
1697 dwState |= B_PROCESSING_OCT;
1698 pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
1699 cchUsed=cchUsed+2;
1700 lpszStr=lpszStr+2;
1701 }
1702
1703 /* Strip Leading zeros */
1704 while (*lpszStr == '0')
1705 {
1706 dwState |= B_LEADING_ZERO;
1707 cchUsed++;
1708 lpszStr++;
1709 }
1710
1711 while (*lpszStr)
1712 {
1713 if (isdigitW(*lpszStr))
1714 {
1715 if (dwState & B_PROCESSING_EXPONENT)
1716 {
1717 int exponentSize = 0;
1718 if (dwState & B_EXPONENT_START)
1719 {
1720 if (!isdigitW(*lpszStr))
1721 break; /* No exponent digits - invalid */
1722 while (*lpszStr == '0')
1723 {
1724 /* Skip leading zero's in the exponent */
1725 cchUsed++;
1726 lpszStr++;
1727 }
1728 }
1729
1730 while (isdigitW(*lpszStr))
1731 {
1732 exponentSize *= 10;
1733 exponentSize += *lpszStr - '0';
1734 cchUsed++;
1735 lpszStr++;
1736 }
1737 if (dwState & B_NEGATIVE_EXPONENT)
1738 exponentSize = -exponentSize;
1739 /* Add the exponent into the powers of 10 */
1740 pNumprs->nPwr10 += exponentSize;
1741 dwState &= ~(B_PROCESSING_EXPONENT|B_EXPONENT_START);
1742 lpszStr--; /* back up to allow processing of next char */
1743 }
1744 else
1745 {
1746 if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
1747 && !(dwState & B_PROCESSING_OCT))
1748 {
1749 pNumprs->dwOutFlags |= NUMPRS_INEXACT;
1750
1751 if (*lpszStr != '0')
1752 dwState &= ~B_INEXACT_ZEROS; /* Inexact number with non-trailing zeros */
1753
1754 /* This digit can't be represented, but count it in nPwr10 */
1755 if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
1756 pNumprs->nPwr10--;
1757 else
1758 pNumprs->nPwr10++;
1759 }
1760 else
1761 {
1762 if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
1763 return DISP_E_TYPEMISMATCH;
1764 }
1765
1766 if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
1767 pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
1768
1769 rgbTmp[pNumprs->cDig] = *lpszStr - '0';
1770 }
1771 pNumprs->cDig++;
1772 cchUsed++;
1773 }
1774 }
1775 else if (*lpszStr == chars.cDigitSeparator && pNumprs->dwInFlags & NUMPRS_THOUSANDS)
1776 {
1777 pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
1778 cchUsed++;
1779 }
1780 else if (*lpszStr == chars.cDecimalPoint &&
1781 pNumprs->dwInFlags & NUMPRS_DECIMAL &&
1782 !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
1783 {
1784 pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
1785 cchUsed++;
1786
1787 /* If we have no digits so far, skip leading zeros */
1788 if (!pNumprs->cDig)
1789 {
1790 while (lpszStr[1] == '0')
1791 {
1792 dwState |= B_LEADING_ZERO;
1793 cchUsed++;
1794 lpszStr++;
1795 pNumprs->nPwr10--;
1796 }
1797 }
1798 }
1799 else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
1800 (*lpszStr >= 'A' && *lpszStr <= 'F')) &&
1801 dwState & B_PROCESSING_HEX)
1802 {
1803 if (pNumprs->cDig >= iMaxDigits)
1804 {
1805 return DISP_E_OVERFLOW;
1806 }
1807 else
1808 {
1809 if (*lpszStr >= 'a')
1810 rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
1811 else
1812 rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
1813 }
1814 pNumprs->cDig++;
1815 cchUsed++;
1816 }
1817 else if ((*lpszStr == 'e' || *lpszStr == 'E') &&
1818 pNumprs->dwInFlags & NUMPRS_EXPONENT &&
1819 !(pNumprs->dwOutFlags & NUMPRS_EXPONENT))
1820 {
1821 dwState |= B_PROCESSING_EXPONENT;
1822 pNumprs->dwOutFlags |= NUMPRS_EXPONENT;
1823 cchUsed++;
1824 }
1825 else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cPositiveSymbol)
1826 {
1827 cchUsed++; /* Ignore positive exponent */
1828 }
1829 else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cNegativeSymbol)
1830 {
1831 dwState |= B_NEGATIVE_EXPONENT;
1832 cchUsed++;
1833 }
1834 else
1835 break; /* Stop at an unrecognised character */
1836
1837 lpszStr++;
1838 }
1839
1840 if (!pNumprs->cDig && dwState & B_LEADING_ZERO)
1841 {
1842 /* Ensure a 0 on its own gets stored */
1843 pNumprs->cDig = 1;
1844 rgbTmp[0] = 0;
1845 }
1846
1847 if (pNumprs->dwOutFlags & NUMPRS_EXPONENT && dwState & B_PROCESSING_EXPONENT)
1848 {
1849 pNumprs->cchUsed = cchUsed;
1850 WARN("didn't completely parse exponent\n");
1851 return DISP_E_TYPEMISMATCH; /* Failed to completely parse the exponent */
1852 }
1853
1854 if (pNumprs->dwOutFlags & NUMPRS_INEXACT)
1855 {
1856 if (dwState & B_INEXACT_ZEROS)
1857 pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* All zeros doesn't set NUMPRS_INEXACT */
1858 } else if(pNumprs->dwInFlags & NUMPRS_HEX_OCT)
1859 {
1860 /* copy all of the digits into the output digit buffer */
1861 /* this is exactly what windows does although it also returns */
1862 /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
1863 memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
1864
1865 if (dwState & B_PROCESSING_HEX) {
1866 /* hex numbers have always the same format */
1867 pNumprs->nPwr10=0;
1868 pNumprs->nBaseShift=4;
1869 } else {
1870 if (dwState & B_PROCESSING_OCT) {
1871 /* oct numbers have always the same format */
1872 pNumprs->nPwr10=0;
1873 pNumprs->nBaseShift=3;
1874 } else {
1875 while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
1876 {
1877 pNumprs->nPwr10++;
1878 pNumprs->cDig--;
1879 }
1880 }
1881 }
1882 } else
1883 {
1884 /* Remove trailing zeros from the last (whole number or decimal) part */
1885 while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
1886 {
1887 pNumprs->nPwr10++;
1888 pNumprs->cDig--;
1889 }
1890 }
1891
1892 if (pNumprs->cDig <= iMaxDigits)
1893 pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* Ignore stripped zeros for NUMPRS_INEXACT */
1894 else
1895 pNumprs->cDig = iMaxDigits; /* Only return iMaxDigits worth of digits */
1896
1897 /* Copy the digits we processed into rgbDig */
1898 memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
1899
1900 /* Consume any trailing symbols and space */
1901 while (1)
1902 {
1903 if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && isspaceW(*lpszStr))
1904 {
1905 pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE;
1906 do
1907 {
1908 cchUsed++;
1909 lpszStr++;
1910 } while (isspaceW(*lpszStr));
1911 }
1912 else if (pNumprs->dwInFlags & NUMPRS_TRAILING_PLUS &&
1913 !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS) &&
1914 *lpszStr == chars.cPositiveSymbol)
1915 {
1916 pNumprs->dwOutFlags |= NUMPRS_TRAILING_PLUS;
1917 cchUsed++;
1918 lpszStr++;
1919 }
1920 else if (pNumprs->dwInFlags & NUMPRS_TRAILING_MINUS &&
1921 !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS) &&
1922 *lpszStr == chars.cNegativeSymbol)
1923 {
1924 pNumprs->dwOutFlags |= (NUMPRS_TRAILING_MINUS|NUMPRS_NEG);
1925 cchUsed++;
1926 lpszStr++;
1927 }
1928 else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == ')' &&
1929 pNumprs->dwOutFlags & NUMPRS_PARENS)
1930 {
1931 cchUsed++;
1932 lpszStr++;
1933 pNumprs->dwOutFlags |= NUMPRS_NEG;
1934 }
1935 else
1936 break;
1937 }
1938
1939 if (pNumprs->dwOutFlags & NUMPRS_PARENS && !(pNumprs->dwOutFlags & NUMPRS_NEG))
1940 {
1941 pNumprs->cchUsed = cchUsed;
1942 return DISP_E_TYPEMISMATCH; /* Opening parenthesis not matched */
1943 }
1944
1945 if (pNumprs->dwInFlags & NUMPRS_USE_ALL && *lpszStr != '\0')
1946 return DISP_E_TYPEMISMATCH; /* Not all chars were consumed */
1947
1948 if (!pNumprs->cDig)
1949 return DISP_E_TYPEMISMATCH; /* No Number found */
1950
1951 pNumprs->cchUsed = cchUsed;
1952 return S_OK;
1953 }
1954
1955 /* VTBIT flags indicating an integer value */
1956 #define INTEGER_VTBITS (VTBIT_I1|VTBIT_UI1|VTBIT_I2|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_I8|VTBIT_UI8)
1957 /* VTBIT flags indicating a real number value */
1958 #define REAL_VTBITS (VTBIT_R4|VTBIT_R8|VTBIT_CY)
1959
1960 /* Helper macros to check whether bit pattern fits in VARIANT (x is a ULONG64 ) */
1961 #define FITS_AS_I1(x) ((x) >> 8 == 0)
1962 #define FITS_AS_I2(x) ((x) >> 16 == 0)
1963 #define FITS_AS_I4(x) ((x) >> 32 == 0)
1964
1965 /**********************************************************************
1966 * VarNumFromParseNum [OLEAUT32.47]
1967 *
1968 * Convert a NUMPARSE structure into a numeric Variant type.
1969 *
1970 * PARAMS
1971 * pNumprs [I] Source for parsed number. cDig must be set to the size of rgbDig
1972 * rgbDig [I] Source for the numbers digits
1973 * dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types
1974 * pVarDst [O] Destination for the converted Variant value.
1975 *
1976 * RETURNS
1977 * Success: S_OK. pVarDst contains the converted value.
1978 * Failure: E_INVALIDARG, if any parameter is invalid.
1979 * DISP_E_OVERFLOW, if the number is too big for the types set in dwVtBits.
1980 *
1981 * NOTES
1982 * - The smallest favoured type present in dwVtBits that can represent the
1983 * number in pNumprs without losing precision is used.
1984 * - Signed types are preferred over unsigned types of the same size.
1985 * - Preferred types in order are: integer, float, double, currency then decimal.
1986 * - Rounding (dropping of decimal points) occurs without error. See VarI8FromR8()
1987 * for details of the rounding method.
1988 * - pVarDst is not cleared before the result is stored in it.
1989 * - WinXP and Win2003 support VTBIT_I8, VTBIT_UI8 but that's buggy (by
1990 * design?): If some other VTBIT's for integers are specified together
1991 * with VTBIT_I8 and the number will fit only in a VT_I8 Windows will "cast"
1992 * the number to the smallest requested integer truncating this way the
1993 * number. Wine doesn't implement this "feature" (yet?).
1994 */
1995 HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
1996 ULONG dwVtBits, VARIANT *pVarDst)
1997 {
1998 /* Scale factors and limits for double arithmetic */
1999 static const double dblMultipliers[11] = {
2000 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0,
2001 1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0
2002 };
2003 static const double dblMinimums[11] = {
2004 R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0,
2005 R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0,
2006 R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0
2007 };
2008 static const double dblMaximums[11] = {
2009 R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0,
2010 R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0,
2011 R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0
2012 };
2013
2014 int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0;
2015
2016 TRACE("(%p,%p,0x%x,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst);
2017
2018 if (pNumprs->nBaseShift)
2019 {
2020 /* nBaseShift indicates a hex or octal number */
2021 ULONG64 ul64 = 0;
2022 LONG64 l64;
2023 int i;
2024
2025 /* Convert the hex or octal number string into a UI64 */
2026 for (i = 0; i < pNumprs->cDig; i++)
2027 {
2028 if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
2029 {
2030 TRACE("Overflow multiplying digits\n");
2031 return DISP_E_OVERFLOW;
2032 }
2033 ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
2034 }
2035
2036 /* also make a negative representation */
2037 l64=-ul64;
2038
2039 /* Try signed and unsigned types in size order */
2040 if (dwVtBits & VTBIT_I1 && FITS_AS_I1(ul64))
2041 {
2042 V_VT(pVarDst) = VT_I1;
2043 V_I1(pVarDst) = ul64;
2044 return S_OK;
2045 }
2046 else if (dwVtBits & VTBIT_UI1 && FITS_AS_I1(ul64))
2047 {
2048 V_VT(pVarDst) = VT_UI1;
2049 V_UI1(pVarDst) = ul64;
2050 return S_OK;
2051 }
2052 else if (dwVtBits & VTBIT_I2 && FITS_AS_I2(ul64))
2053 {
2054 V_VT(pVarDst) = VT_I2;
2055 V_I2(pVarDst) = ul64;
2056 return S_OK;
2057 }
2058 else if (dwVtBits & VTBIT_UI2 && FITS_AS_I2(ul64))
2059 {
2060 V_VT(pVarDst) = VT_UI2;
2061 V_UI2(pVarDst) = ul64;
2062 return S_OK;
2063 }
2064 else if (dwVtBits & VTBIT_I4 && FITS_AS_I4(ul64))
2065 {
2066 V_VT(pVarDst) = VT_I4;
2067 V_I4(pVarDst) = ul64;
2068 return S_OK;
2069 }
2070 else if (dwVtBits & VTBIT_UI4 && FITS_AS_I4(ul64))
2071 {
2072 V_VT(pVarDst) = VT_UI4;
2073 V_UI4(pVarDst) = ul64;
2074 return S_OK;
2075 }
2076 else if (dwVtBits & VTBIT_I8 && ((ul64 <= I8_MAX)||(l64>=I8_MIN)))
2077 {
2078 V_VT(pVarDst) = VT_I8;
2079 V_I8(pVarDst) = ul64;
2080 return S_OK;
2081 }
2082 else if (dwVtBits & VTBIT_UI8)
2083 {
2084 V_VT(pVarDst) = VT_UI8;
2085 V_UI8(pVarDst) = ul64;
2086 return S_OK;
2087 }
2088 else if ((dwVtBits & VTBIT_DECIMAL) == VTBIT_DECIMAL)
2089 {
2090 V_VT(pVarDst) = VT_DECIMAL;
2091 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
2092 DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
2093 DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
2094 return S_OK;
2095 }
2096 else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
2097 {
2098 V_VT(pVarDst) = VT_R4;
2099 if (ul64 <= I4_MAX)
2100 V_R4(pVarDst) = ul64;
2101 else
2102 V_R4(pVarDst) = l64;
2103 return S_OK;
2104 }
2105 else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
2106 {
2107 V_VT(pVarDst) = VT_R8;
2108 if (ul64 <= I4_MAX)
2109 V_R8(pVarDst) = ul64;
2110 else
2111 V_R8(pVarDst) = l64;
2112 return S_OK;
2113 }
2114
2115 TRACE("Overflow: possible return types: 0x%x, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
2116 return DISP_E_OVERFLOW;
2117 }
2118
2119 /* Count the number of relevant fractional and whole digits stored,
2120 * And compute the divisor/multiplier to scale the number by.
2121 */
2122 if (pNumprs->nPwr10 < 0)
2123 {
2124 if (-pNumprs->nPwr10 >= pNumprs->cDig)
2125 {
2126 /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
2127 wholeNumberDigits = 0;
2128 fractionalDigits = pNumprs->cDig;
2129 divisor10 = -pNumprs->nPwr10;
2130 }
2131 else
2132 {
2133 /* An exactly represented real number e.g. 1.024 */
2134 wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10;
2135 fractionalDigits = pNumprs->cDig - wholeNumberDigits;
2136 divisor10 = pNumprs->cDig - wholeNumberDigits;
2137 }
2138 }
2139 else if (pNumprs->nPwr10 == 0)
2140 {
2141 /* An exactly represented whole number e.g. 1024 */
2142 wholeNumberDigits = pNumprs->cDig;
2143 fractionalDigits = 0;
2144 }
2145 else /* pNumprs->nPwr10 > 0 */
2146 {
2147 /* A whole number followed by nPwr10 0's e.g. 102400 */
2148 wholeNumberDigits = pNumprs->cDig;
2149 fractionalDigits = 0;
2150 multiplier10 = pNumprs->nPwr10;
2151 }
2152
2153 TRACE("cDig %d; nPwr10 %d, whole %d, frac %d mult %d; div %d\n",
2154 pNumprs->cDig, pNumprs->nPwr10, wholeNumberDigits, fractionalDigits,
2155 multiplier10, divisor10);
2156
2157 if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) &&
2158 (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL))))
2159 {
2160 /* We have one or more integer output choices, and either:
2161 * 1) An integer input value, or
2162 * 2) A real number input value but no floating output choices.
2163 * Alternately, we have a DECIMAL output available and an integer input.
2164 *
2165 * So, place the integer value into pVarDst, using the smallest type
2166 * possible and preferring signed over unsigned types.
2167 */
2168 BOOL bOverflow = FALSE, bNegative;
2169 ULONG64 ul64 = 0;
2170 int i;
2171
2172 /* Convert the integer part of the number into a UI8 */
2173 for (i = 0; i < wholeNumberDigits; i++)
2174 {
2175 if (ul64 > UI8_MAX / 10 || (ul64 == UI8_MAX / 10 && rgbDig[i] > UI8_MAX % 10))
2176 {
2177 TRACE("Overflow multiplying digits\n");
2178 bOverflow = TRUE;
2179 break;
2180 }
2181 ul64 = ul64 * 10 + rgbDig[i];
2182 }
2183
2184 /* Account for the scale of the number */
2185 if (!bOverflow && multiplier10)
2186 {
2187 for (i = 0; i < multiplier10; i++)
2188 {
2189 if (ul64 > (UI8_MAX / 10))
2190 {
2191 TRACE("Overflow scaling number\n");
2192 bOverflow = TRUE;
2193 break;
2194 }
2195 ul64 = ul64 * 10;
2196 }
2197 }
2198
2199 /* If we have any fractional digits, round the value.
2200 * Note we don't have to do this if divisor10 is < 1,
2201 * because this means the fractional part must be < 0.5
2202 */
2203 if (!bOverflow && fractionalDigits && divisor10 > 0)
2204 {
2205 const BYTE* fracDig = rgbDig + wholeNumberDigits;
2206 BOOL bAdjust = FALSE;
2207
2208 TRACE("first decimal value is %d\n", *fracDig);
2209
2210 if (*fracDig > 5)
2211 bAdjust = TRUE; /* > 0.5 */
2212 else if (*fracDig == 5)
2213 {
2214 for (i = 1; i < fractionalDigits; i++)
2215 {
2216 if (fracDig[i])
2217 {
2218 bAdjust = TRUE; /* > 0.5 */
2219 break;
2220 }
2221 }
2222 /* If exactly 0.5, round only odd values */
2223 if (i == fractionalDigits && (ul64 & 1))
2224 bAdjust = TRUE;
2225 }
2226
2227 if (bAdjust)
2228 {
2229 if (ul64 == UI8_MAX)
2230 {
2231 TRACE("Overflow after rounding\n");
2232 bOverflow = TRUE;
2233 }
2234 ul64++;
2235 }
2236 }
2237
2238 /* Zero is not a negative number */
2239 bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64;
2240
2241 TRACE("Integer value is 0x%s, bNeg %d\n", wine_dbgstr_longlong(ul64), bNegative);
2242
2243 /* For negative integers, try the signed types in size order */
2244 if (!bOverflow && bNegative)
2245 {
2246 if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8))
2247 {
2248 if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN)
2249 {
2250 V_VT(pVarDst) = VT_I1;
2251 V_I1(pVarDst) = -ul64;
2252 return S_OK;
2253 }
2254 else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN)
2255 {
2256 V_VT(pVarDst) = VT_I2;
2257 V_I2(pVarDst) = -ul64;
2258 return S_OK;
2259 }
2260 else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN))
2261 {
2262 V_VT(pVarDst) = VT_I4;
2263 V_I4(pVarDst) = -ul64;
2264 return S_OK;
2265 }
2266 else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1)
2267 {
2268 V_VT(pVarDst) = VT_I8;
2269 V_I8(pVarDst) = -ul64;
2270 return S_OK;
2271 }
2272 else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
2273 {
2274 /* Decimal is only output choice left - fast path */
2275 V_VT(pVarDst) = VT_DECIMAL;
2276 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
2277 DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
2278 DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
2279 return S_OK;
2280 }
2281 }
2282 }
2283 else if (!bOverflow)
2284 {
2285 /* For positive integers, try signed then unsigned types in size order */
2286 if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX)
2287 {
2288 V_VT(pVarDst) = VT_I1;
2289 V_I1(pVarDst) = ul64;
2290 return S_OK;
2291 }
2292 else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
2293 {
2294 V_VT(pVarDst) = VT_UI1;
2295 V_UI1(pVarDst) = ul64;
2296 return S_OK;
2297 }
2298 else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
2299 {
2300 V_VT(pVarDst) = VT_I2;
2301 V_I2(pVarDst) = ul64;
2302 return S_OK;
2303 }
2304 else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
2305 {
2306 V_VT(pVarDst) = VT_UI2;
2307 V_UI2(pVarDst) = ul64;
2308 return S_OK;
2309 }
2310 else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
2311 {
2312 V_VT(pVarDst) = VT_I4;
2313 V_I4(pVarDst) = ul64;
2314 return S_OK;
2315 }
2316 else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
2317 {
2318 V_VT(pVarDst) = VT_UI4;
2319 V_UI4(pVarDst) = ul64;
2320 return S_OK;
2321 }
2322 else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
2323 {
2324 V_VT(pVarDst) = VT_I8;
2325 V_I8(pVarDst) = ul64;
2326 return S_OK;
2327 }
2328 else if (dwVtBits & VTBIT_UI8)
2329 {
2330 V_VT(pVarDst) = VT_UI8;
2331 V_UI8(pVarDst) = ul64;
2332 return S_OK;
2333 }
2334 else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
2335 {
2336 /* Decimal is only output choice left - fast path */
2337 V_VT(pVarDst) = VT_DECIMAL;
2338 DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
2339 DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
2340 DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
2341 return S_OK;
2342 }
2343 }
2344 }
2345
2346 if (dwVtBits & REAL_VTBITS)
2347 {
2348 /* Try to put the number into a float or real */
2349 BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG;
2350 double whole = 0.0;
2351 int i;
2352
2353 /* Convert the number into a double */
2354 for (i = 0; i < pNumprs->cDig; i++)
2355 whole = whole * 10.0 + rgbDig[i];
2356
2357 TRACE("Whole double value is %16.16g\n", whole);
2358
2359 /* Account for the scale */
2360 while (multiplier10 > 10)
2361 {
2362 if (whole > dblMaximums[10])
2363 {
2364 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
2365 bOverflow = TRUE;
2366 break;
2367 }
2368 whole = whole * dblMultipliers[10];
2369 multiplier10 -= 10;
2370 }
2371 if (multiplier10 && !bOverflow)
2372 {
2373 if (whole > dblMaximums[multiplier10])
2374 {
2375 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
2376 bOverflow = TRUE;
2377 }
2378 else
2379 whole = whole * dblMultipliers[multiplier10];
2380 }
2381
2382 if (!bOverflow)
2383 TRACE("Scaled double value is %16.16g\n", whole);
2384
2385 while (divisor10 > 10 && !bOverflow)
2386 {
2387 if (whole < dblMinimums[10] && whole != 0)
2388 {
2389 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
2390 bOverflow = TRUE;
2391 break;
2392 }
2393 whole = whole / dblMultipliers[10];
2394 divisor10 -= 10;
2395 }
2396 if (divisor10 && !bOverflow)
2397 {
2398 if (whole < dblMinimums[divisor10] && whole != 0)
2399 {
2400 dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
2401 bOverflow = TRUE;
2402 }
2403 else
2404 whole = whole / dblMultipliers[divisor10];
2405 }
2406 if (!bOverflow)
2407 TRACE("Final double value is %16.16g\n", whole);
2408
2409 if (dwVtBits & VTBIT_R4 &&
2410 ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0))
2411 {
2412 TRACE("Set R4 to final value\n");
2413 V_VT(pVarDst) = VT_R4; /* Fits into a float */
2414 V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
2415 return S_OK;
2416 }
2417
2418 if (dwVtBits & VTBIT_R8)
2419 {
2420 TRACE("Set R8 to final value\n");
2421 V_VT(pVarDst) = VT_R8; /* Fits into a double */
2422 V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
2423 return S_OK;
2424 }
2425
2426 if (dwVtBits & VTBIT_CY)
2427 {
2428 if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst))))
2429 {
2430 V_VT(pVarDst) = VT_CY; /* Fits into a currency */
2431 TRACE("Set CY to final value\n");
2432 return S_OK;
2433 }
2434 TRACE("Value Overflows CY\n");
2435 }
2436 }
2437
2438 if (dwVtBits & VTBIT_DECIMAL)
2439 {
2440 int i;
2441 ULONG carry;
2442 ULONG64 tmp;
2443 DECIMAL* pDec = &V_DECIMAL(pVarDst);
2444
2445 DECIMAL_SETZERO(*pDec);
2446 DEC_LO32(pDec) = 0;
2447
2448 if (pNumprs->dwOutFlags & NUMPRS_NEG)
2449 DEC_SIGN(pDec) = DECIMAL_NEG;
2450 else
2451 DEC_SIGN(pDec) = DECIMAL_POS;
2452
2453 /* Factor the significant digits */
2454 for (i = 0; i < pNumprs->cDig; i++)
2455 {
2456 tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
2457 carry = (ULONG)(tmp >> 32);
2458 DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
2459 tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
2460 carry = (ULONG)(tmp >> 32);
2461 DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
2462 tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
2463 DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
2464
2465 if (tmp >> 32 & UI4_MAX)
2466 {
2467 VarNumFromParseNum_DecOverflow:
2468 TRACE("Overflow\n");
2469 DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
2470 return DISP_E_OVERFLOW;
2471 }
2472 }
2473
2474 /* Account for the scale of the number */
2475 while (multiplier10 > 0)
2476 {
2477 tmp = (ULONG64)DEC_LO32(pDec) * 10;
2478 carry = (ULONG)(tmp >> 32);
2479 DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
2480 tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
2481 carry = (ULONG)(tmp >> 32);
2482 DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
2483 tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
2484 DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
2485
2486 if (tmp >> 32 & UI4_MAX)
2487 goto VarNumFromParseNum_DecOverflow;
2488 multiplier10--;
2489 }
2490 DEC_SCALE(pDec) = divisor10;
2491
2492 V_VT(pVarDst) = VT_DECIMAL;
2493 return S_OK;
2494 }
2495 return DISP_E_OVERFLOW; /* No more output choices */
2496 }
2497
2498 /**********************************************************************
2499 * VarCat [OLEAUT32.318]
2500 *
2501 * Concatenates one variant onto another.
2502 *
2503 * PARAMS
2504 * left [I] First variant
2505 * right [I] Second variant
2506 * result [O] Result variant
2507 *
2508 * RETURNS
2509 * Success: S_OK.
2510 * Failure: An HRESULT error code indicating the error.
2511 */
2512 HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
2513 {
2514 VARTYPE leftvt,rightvt,resultvt;
2515 HRESULT hres;
2516 static WCHAR str_true[32];
2517 static WCHAR str_false[32];
2518 static const WCHAR sz_empty[] = {'\0'};
2519 leftvt = V_VT(left);
2520 rightvt = V_VT(right);
2521
2522 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
2523 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), out);
2524
2525 if (!str_true[0]) {
2526 VARIANT_GetLocalisedText(LOCALE_USER_DEFAULT, IDS_FALSE, str_false);
2527 VARIANT_GetLocalisedText(LOCALE_USER_DEFAULT, IDS_TRUE, str_true);
2528 }
2529
2530 /* when both left and right are NULL the result is NULL */
2531 if (leftvt == VT_NULL && rightvt == VT_NULL)
2532 {
2533 V_VT(out) = VT_NULL;
2534 return S_OK;
2535 }
2536
2537 hres = S_OK;
2538 resultvt = VT_EMPTY;
2539
2540 /* There are many special case for errors and return types */
2541 if (leftvt == VT_VARIANT && (rightvt == VT_ERROR ||
2542 rightvt == VT_DATE || rightvt == VT_DECIMAL))
2543 hres = DISP_E_TYPEMISMATCH;
2544 else if ((leftvt == VT_I2 || leftvt == VT_I4 ||
2545 leftvt == VT_R4 || leftvt == VT_R8 ||
2546 leftvt == VT_CY || leftvt == VT_BOOL ||
2547 leftvt == VT_BSTR || leftvt == VT_I1 ||
2548 leftvt == VT_UI1 || leftvt == VT_UI2 ||
2549 leftvt == VT_UI4 || leftvt == VT_I8 ||
2550 leftvt == VT_UI8 || leftvt == VT_INT ||
2551 leftvt == VT_UINT || leftvt == VT_EMPTY ||
2552 leftvt == VT_NULL || leftvt == VT_DATE ||
2553 leftvt == VT_DECIMAL || leftvt == VT_DISPATCH)
2554 &&
2555 (rightvt == VT_I2 || rightvt == VT_I4 ||
2556 rightvt == VT_R4 || rightvt == VT_R8 ||
2557 rightvt == VT_CY || rightvt == VT_BOOL ||
2558 rightvt == VT_BSTR || rightvt == VT_I1 ||
2559 rightvt == VT_UI1 || rightvt == VT_UI2 ||
2560 rightvt == VT_UI4 || rightvt == VT_I8 ||
2561 rightvt == VT_UI8 || rightvt == VT_INT ||
2562 rightvt == VT_UINT || rightvt == VT_EMPTY ||
2563 rightvt == VT_NULL || rightvt == VT_DATE ||
2564 rightvt == VT_DECIMAL || rightvt == VT_DISPATCH))
2565 resultvt = VT_BSTR;
2566 else if (rightvt == VT_ERROR && leftvt < VT_VOID)
2567 hres = DISP_E_TYPEMISMATCH;
2568 else if (leftvt == VT_ERROR && (rightvt == VT_DATE ||
2569 rightvt == VT_ERROR || rightvt == VT_DECIMAL))
2570 hres = DISP_E_TYPEMISMATCH;
2571 else if (rightvt == VT_DATE || rightvt == VT_ERROR ||
2572 rightvt == VT_DECIMAL)
2573 hres = DISP_E_BADVARTYPE;
2574 else if (leftvt == VT_ERROR || rightvt == VT_ERROR)
2575 hres = DISP_E_TYPEMISMATCH;
2576 else if (leftvt == VT_VARIANT)
2577 hres = DISP_E_TYPEMISMATCH;
2578 else if (rightvt == VT_VARIANT && (leftvt == VT_EMPTY ||
2579 leftvt == VT_NULL || leftvt == VT_I2 ||
2580 leftvt == VT_I4 || leftvt == VT_R4 ||
2581 leftvt == VT_R8 || leftvt == VT_CY ||
2582 leftvt == VT_DATE || leftvt == VT_BSTR ||
2583 leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
2584 leftvt == VT_I1 || leftvt == VT_UI1 ||
2585 leftvt == VT_UI2 || leftvt == VT_UI4 ||
2586 leftvt == VT_I8 || leftvt == VT_UI8 ||
2587 leftvt == VT_INT || leftvt == VT_UINT))
2588 hres = DISP_E_TYPEMISMATCH;
2589 else
2590 hres = DISP_E_BADVARTYPE;
2591
2592 /* if result type is not S_OK, then no need to go further */
2593 if (hres != S_OK)
2594 {
2595 V_VT(out) = resultvt;
2596 return hres;
2597 }
2598 /* Else proceed with formatting inputs to strings */
2599 else
2600 {
2601 VARIANT bstrvar_left, bstrvar_right;
2602 V_VT(out) = VT_BSTR;
2603
2604 VariantInit(&bstrvar_left);
2605 VariantInit(&bstrvar_right);
2606
2607 /* Convert left side variant to string */
2608 if (leftvt != VT_BSTR)
2609 {
2610 if (leftvt == VT_BOOL)
2611 {
2612 /* Bools are handled as localized True/False strings instead of 0/-1 as in MSDN */
2613 V_VT(&bstrvar_left) = VT_BSTR;
2614 if (V_BOOL(left))
2615 V_BSTR(&bstrvar_left) = SysAllocString(str_true);
2616 else
2617 V_BSTR(&bstrvar_left) = SysAllocString(str_false);
2618 }
2619 /* Fill with empty string for later concat with right side */
2620 else if (leftvt == VT_NULL)
2621 {
2622 V_VT(&bstrvar_left) = VT_BSTR;
2623 V_BSTR(&bstrvar_left) = SysAllocString(sz_empty);
2624 }
2625 else
2626 {
2627 hres = VariantChangeTypeEx(&bstrvar_left,left,0,0,VT_BSTR);
2628 if (hres != S_OK) {
2629 VariantClear(&bstrvar_left);
2630 VariantClear(&bstrvar_right);
2631 if (leftvt == VT_NULL && (rightvt == VT_EMPTY ||
2632 rightvt == VT_NULL || rightvt == VT_I2 ||
2633 rightvt == VT_I4 || rightvt == VT_R4 ||
2634 rightvt == VT_R8 || rightvt == VT_CY ||
2635 rightvt == VT_DATE || rightvt == VT_BSTR ||
2636 rightvt == VT_BOOL || rightvt == VT_DECIMAL ||
2637 rightvt == VT_I1 || rightvt == VT_UI1 ||
2638 rightvt == VT_UI2 || rightvt == VT_UI4 ||
2639 rightvt == VT_I8 || rightvt == VT_UI8 ||
2640 rightvt == VT_INT || rightvt == VT_UINT))
2641 return DISP_E_BADVARTYPE;
2642 return hres;
2643 }
2644 }
2645 }
2646
2647 /* convert right side variant to string */
2648 if (rightvt != VT_BSTR)
2649 {
2650 if (rightvt == VT_BOOL)
2651 {
2652 /* Bools are handled as localized True/False strings instead of 0/-1 as in MSDN */
2653 V_VT(&bstrvar_right) = VT_BSTR;
2654 if (V_BOOL(right))
2655 V_BSTR(&bstrvar_right) = SysAllocString(str_true);
2656 else
2657 V_BSTR(&bstrvar_right) = SysAllocString(str_false);
2658 }
2659 /* Fill with empty string for later concat with right side */
2660 else if (rightvt == VT_NULL)
2661 {
2662 V_VT(&bstrvar_right) = VT_BSTR;
2663 V_BSTR(&bstrvar_right) = SysAllocString(sz_empty);
2664 }
2665 else
2666 {
2667 hres = VariantChangeTypeEx(&bstrvar_right,right,0,0,VT_BSTR);
2668 if (hres != S_OK) {
2669 VariantClear(&bstrvar_left);
2670 VariantClear(&bstrvar_right);
2671 if (rightvt == VT_NULL && (leftvt == VT_EMPTY ||
2672 leftvt == VT_NULL || leftvt == VT_I2 ||
2673 leftvt == VT_I4 || leftvt == VT_R4 ||
2674 leftvt == VT_R8 || leftvt == VT_CY ||
2675 leftvt == VT_DATE || leftvt == VT_BSTR ||
2676 leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
2677 leftvt == VT_I1 || leftvt == VT_UI1 ||
2678 leftvt == VT_UI2 || leftvt == VT_UI4 ||
2679 leftvt == VT_I8 || leftvt == VT_UI8 ||
2680 leftvt == VT_INT || leftvt == VT_UINT))
2681 return DISP_E_BADVARTYPE;
2682 return hres;
2683 }
2684 }
2685 }
2686
2687 /* Concat the resulting strings together */
2688 if (leftvt == VT_BSTR && rightvt == VT_BSTR)
2689 VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out));
2690 else if (leftvt != VT_BSTR && rightvt != VT_BSTR)
2691 VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(&bstrvar_right), &V_BSTR(out));
2692 else if (leftvt != VT_BSTR && rightvt == VT_BSTR)
2693 VarBstrCat (V_BSTR(&bstrvar_left), V_BSTR(right), &V_BSTR(out));
2694 else if (leftvt == VT_BSTR && rightvt != VT_BSTR)
2695 VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar_right), &V_BSTR(out));
2696
2697 VariantClear(&bstrvar_left);
2698 VariantClear(&bstrvar_right);
2699 return S_OK;
2700 }
2701 }
2702
2703
2704 /* Wrapper around VariantChangeTypeEx() which permits changing a
2705 variant with VT_RESERVED flag set. Needed by VarCmp. */
2706 static HRESULT _VarChangeTypeExWrap (VARIANTARG* pvargDest,
2707 VARIANTARG* pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
2708 {
2709 VARIANTARG vtmpsrc = *pvargSrc;
2710
2711 V_VT(&vtmpsrc) &= ~VT_RESERVED;
2712 return VariantChangeTypeEx(pvargDest,&vtmpsrc,lcid,wFlags,vt);
2713 }
2714
2715 /**********************************************************************
2716 * VarCmp [OLEAUT32.176]
2717 *
2718 * Compare two variants.
2719 *
2720 * PARAMS
2721 * left [I] First variant
2722 * right [I] Second variant
2723 * lcid [I] LCID (locale identifier) for the comparison
2724 * flags [I] Flags to be used in the comparison:
2725 * NORM_IGNORECASE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS,
2726 * NORM_IGNOREWIDTH, NORM_IGNOREKANATYPE, NORM_IGNOREKASHIDA
2727 *
2728 * RETURNS
2729 * VARCMP_LT: left variant is less than right variant.
2730 * VARCMP_EQ: input variants are equal.
2731 * VARCMP_GT: left variant is greater than right variant.
2732 * VARCMP_NULL: either one of the input variants is NULL.
2733 * Failure: An HRESULT error code indicating the error.
2734 *
2735 * NOTES
2736 * Native VarCmp up to and including WinXP doesn't like I1, UI2, VT_UI4,
2737 * UI8 and UINT as input variants. INT is accepted only as left variant.
2738 *
2739 * If both input variants are ERROR then VARCMP_EQ will be returned, else
2740 * an ERROR variant will trigger an error.
2741 *
2742 * Both input variants can have VT_RESERVED flag set which is ignored
2743 * unless one and only one of the variants is a BSTR and the other one
2744 * is not an EMPTY variant. All four VT_RESERVED combinations have a
2745 * different meaning:
2746 * - BSTR and other: BSTR is always greater than the other variant.
2747 * - BSTR|VT_RESERVED and other: a string comparison is performed.
2748 * - BSTR and other|VT_RESERVED: If the BSTR is a number a numeric
2749 * comparison will take place else the BSTR is always greater.
2750 * - BSTR|VT_RESERVED and other|VT_RESERVED: It seems that the other
2751 * variant is ignored and the return value depends only on the sign
2752 * of the BSTR if it is a number else the BSTR is always greater. A
2753 * positive BSTR is greater, a negative one is smaller than the other
2754 * variant.
2755 *
2756 * SEE
2757 * VarBstrCmp for the lcid and flags usage.
2758 */
2759 HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
2760 {
2761 VARTYPE lvt, rvt, vt;
2762 VARIANT rv,lv;
2763 DWORD xmask;
2764 HRESULT rc;
2765
2766 TRACE("(%p->(%s%s),%p->(%s%s),0x%08x,0x%08x)\n", left, debugstr_VT(left),
2767 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), lcid, flags);
2768
2769 lvt = V_VT(left) & VT_TYPEMASK;
2770 rvt = V_VT(right) & VT_TYPEMASK;
2771 xmask = (1 << lvt) | (1 << rvt);
2772
2773 /* If we have any flag set except VT_RESERVED bail out.
2774 Same for the left input variant type > VT_INT and for the
2775 right input variant type > VT_I8. Yes, VT_INT is only supported
2776 as left variant. Go figure */
2777 if (((V_VT(left) | V_VT(right)) & ~VT_TYPEMASK & ~VT_RESERVED) ||
2778 lvt > VT_INT || rvt > VT_I8) {
2779 return DISP_E_BADVARTYPE;
2780 }
2781
2782 /* Don't ask me why but native VarCmp cannot handle: VT_I1, VT_UI2, VT_UI4,
2783 VT_UINT and VT_UI8. Tested with DCOM98, Win2k, WinXP */
2784 if (rvt == VT_INT || xmask & (VTBIT_I1 | VTBIT_UI2 | VTBIT_UI4 | VTBIT_UI8 |
2785 VTBIT_DISPATCH | VTBIT_VARIANT | VTBIT_UNKNOWN | VTBIT_15))
2786 return DISP_E_TYPEMISMATCH;
2787
2788 /* If both variants are VT_ERROR return VARCMP_EQ */
2789 if (xmask == VTBIT_ERROR)
2790 return VARCMP_EQ;
2791 else if (xmask & VTBIT_ERROR)
2792 return DISP_E_TYPEMISMATCH;
2793
2794 if (xmask & VTBIT_NULL)
2795 return VARCMP_NULL;
2796
2797 VariantInit(&lv);
2798 VariantInit(&rv);
2799
2800 /* Two BSTRs, ignore VT_RESERVED */
2801 if (xmask == VTBIT_BSTR)
2802 return VarBstrCmp(V_BSTR(left), V_BSTR(right), lcid, flags);
2803
2804 /* A BSTR and another variant; we have to take care of VT_RESERVED */
2805 if (xmask & VTBIT_BSTR) {
2806 VARIANT *bstrv, *nonbv;
2807 VARTYPE nonbvt;
2808 int swap = 0;
2809
2810 /* Swap the variants so the BSTR is always on the left */
2811 if (lvt == VT_BSTR) {
2812 bstrv = left;
2813 nonbv = right;
2814 nonbvt = rvt;
2815 } else {
2816 swap = 1;
2817 bstrv = right;
2818 nonbv = left;
2819 nonbvt = lvt;
2820 }
2821
2822 /* BSTR and EMPTY: ignore VT_RESERVED */
2823 if (nonbvt == VT_EMPTY)
2824 rc = (!V_BSTR(bstrv) || !*V_BSTR(bstrv)) ? VARCMP_EQ : VARCMP_GT;
2825 else {
2826 VARTYPE breserv = V_VT(bstrv) & ~VT_TYPEMASK;
2827 VARTYPE nreserv = V_VT(nonbv) & ~VT_TYPEMASK;
2828
2829 if (!breserv && !nreserv)
2830 /* No VT_RESERVED set ==> BSTR always greater */
2831 rc = VARCMP_GT;
2832 else if (breserv && !nreserv) {
2833 /* BSTR has VT_RESERVED set. Do a string comparison */
2834 rc = VariantChangeTypeEx(&rv,nonbv,lcid,0,VT_BSTR);
2835 if (FAILED(rc))
2836 return rc;
2837 rc = VarBstrCmp(V_BSTR(bstrv), V_BSTR(&rv), lcid, flags);
2838 VariantClear(&rv);
2839 } else if (V_BSTR(bstrv) && *V_BSTR(bstrv)) {
2840 /* Non NULL nor empty BSTR */
2841 /* If the BSTR is not a number the BSTR is greater */
2842 rc = _VarChangeTypeExWrap(&lv,bstrv,lcid,0,VT_R8);
2843 if (FAILED(rc))
2844 rc = VARCMP_GT;
2845 else if (breserv && nreserv)
2846 /* FIXME: This is strange: with both VT_RESERVED set it
2847 looks like the result depends only on the sign of
2848 the BSTR number */
2849 rc = (V_R8(&lv) >= 0) ? VARCMP_GT : VARCMP_LT;
2850 else
2851 /* Numeric comparison, will be handled below.
2852 VARCMP_NULL used only to break out. */
2853 rc = VARCMP_NULL;
2854 VariantClear(&lv);
2855 VariantClear(&rv);
2856 } else
2857 /* Empty or NULL BSTR */
2858 rc = VARCMP_GT;
2859 }
2860 /* Fixup the return code if we swapped left and right */
2861 if (swap) {
2862 if (rc == VARCMP_GT)
2863 rc = VARCMP_LT;
2864 else if (rc == VARCMP_LT)
2865 rc = VARCMP_GT;
2866 }
2867 if (rc != VARCMP_NULL)
2868 return rc;
2869 }
2870
2871 if (xmask & VTBIT_DECIMAL)
2872 vt = VT_DECIMAL;
2873 else if (xmask & VTBIT_BSTR)
2874 vt = VT_R8;
2875 else if (xmask & VTBIT_R4)
2876 vt = VT_R4;
2877 else if (xmask & (VTBIT_R8 | VTBIT_DATE))
2878 vt = VT_R8;
2879 else if (xmask & VTBIT_CY)
2880 vt = VT_CY;
2881 else
2882 /* default to I8 */
2883 vt = VT_I8;
2884
2885 /* Coerce the variants */
2886 rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt);
2887 if (rc == DISP_E_OVERFLOW && vt != VT_R8) {
2888 /* Overflow, change to R8 */
2889 vt = VT_R8;
2890 rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt);
2891 }
2892 if (FAILED(rc))
2893 return rc;
2894 rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt);
2895 if (rc == DISP_E_OVERFLOW && vt != VT_R8) {
2896 /* Overflow, change to R8 */
2897 vt = VT_R8;
2898 rc = _VarChangeTypeExWrap(&lv,left,lcid,0,vt);
2899 if (FAILED(rc))
2900 return rc;
2901 rc = _VarChangeTypeExWrap(&rv,right,lcid,0,vt);
2902 }
2903 if (FAILED(rc))
2904 return rc;
2905
2906 #define _VARCMP(a,b) \
2907 (((a) == (b)) ? VARCMP_EQ : (((a) < (b)) ? VARCMP_LT : VARCMP_GT))
2908
2909 switch (vt) {
2910 case VT_CY:
2911 return VarCyCmp(V_CY(&lv), V_CY(&rv));
2912 case VT_DECIMAL:
2913 return VarDecCmp(&V_DECIMAL(&lv), &V_DECIMAL(&rv));
2914 case VT_I8:
2915 return _VARCMP(V_I8(&lv), V_I8(&rv));
2916 case VT_R4:
2917 return _VARCMP(V_R4(&lv), V_R4(&rv));
2918 case VT_R8:
2919 return _VARCMP(V_R8(&lv), V_R8(&rv));
2920 default:
2921 /* We should never get here */
2922 return E_FAIL;
2923 }
2924 #undef _VARCMP
2925 }
2926
2927 static HRESULT VARIANT_FetchDispatchValue(LPVARIANT pvDispatch, LPVARIANT pValue)
2928 {
2929 HRESULT hres;
2930 static DISPPARAMS emptyParams = { NULL, NULL, 0, 0 };
2931
2932 if ((V_VT(pvDispatch) & VT_TYPEMASK) == VT_DISPATCH) {
2933 if (NULL == V_DISPATCH(pvDispatch)) return DISP_E_TYPEMISMATCH;
2934 hres = IDispatch_Invoke(V_DISPATCH(pvDispatch), DISPID_VALUE, &IID_NULL,
2935 LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &emptyParams, pValue,
2936 NULL, NULL);
2937 } else {
2938 hres = DISP_E_TYPEMISMATCH;
2939 }
2940 return hres;
2941 }
2942
2943 /**********************************************************************
2944 * VarAnd [OLEAUT32.142]
2945 *
2946 * Computes the logical AND of two variants.
2947 *
2948 * PARAMS
2949 * left [I] First variant
2950 * right [I] Second variant
2951 * result [O] Result variant
2952 *
2953 * RETURNS
2954 * Success: S_OK.
2955 * Failure: An HRESULT error code indicating the error.
2956 */
2957 HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
2958 {
2959 HRESULT hres = S_OK;
2960 VARTYPE resvt = VT_EMPTY;
2961 VARTYPE leftvt,rightvt;
2962 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
2963 VARIANT varLeft, varRight;
2964 VARIANT tempLeft, tempRight;
2965
2966 VariantInit(&varLeft);
2967 VariantInit(&varRight);
2968 VariantInit(&tempLeft);
2969 VariantInit(&tempRight);
2970
2971 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
2972 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
2973
2974 /* Handle VT_DISPATCH by storing and taking address of returned value */
2975 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
2976 {
2977 hres = VARIANT_FetchDispatchValue(left, &tempLeft);
2978 if (FAILED(hres)) goto VarAnd_Exit;
2979 left = &tempLeft;
2980 }
2981 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
2982 {
2983 hres = VARIANT_FetchDispatchValue(right, &tempRight);
2984 if (FAILED(hres)) goto VarAnd_Exit;
2985 right = &tempRight;
2986 }
2987
2988 leftvt = V_VT(left)&VT_TYPEMASK;
2989 rightvt = V_VT(right)&VT_TYPEMASK;
2990 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
2991 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
2992
2993 if (leftExtraFlags != rightExtraFlags)
2994 {
2995 hres = DISP_E_BADVARTYPE;
2996 goto VarAnd_Exit;
2997 }
2998 ExtraFlags = leftExtraFlags;
2999
3000 /* Native VarAnd always returns an error when using extra
3001 * flags or if the variant combination is I8 and INT.
3002 */
3003 if ((leftvt == VT_I8 && rightvt == VT_INT) ||
3004 (leftvt == VT_INT && rightvt == VT_I8) ||
3005 ExtraFlags != 0)
3006 {
3007 hres = DISP_E_BADVARTYPE;
3008 goto VarAnd_Exit;
3009 }
3010
3011 /* Determine return type */
3012 else if (leftvt == VT_I8 || rightvt == VT_I8)
3013 resvt = VT_I8;
3014 else if (leftvt == VT_I4 || rightvt == VT_I4 ||
3015 leftvt == VT_UINT || rightvt == VT_UINT ||
3016 leftvt == VT_INT || rightvt == VT_INT ||
3017 leftvt == VT_UINT || rightvt == VT_UINT ||
3018 leftvt == VT_R4 || rightvt == VT_R4 ||
3019 leftvt == VT_R8 || rightvt == VT_R8 ||
3020 leftvt == VT_CY || rightvt == VT_CY ||
3021 leftvt == VT_DATE || rightvt == VT_DATE ||
3022 leftvt == VT_I1 || rightvt == VT_I1 ||
3023 leftvt == VT_UI2 || rightvt == VT_UI2 ||
3024 leftvt == VT_UI4 || rightvt == VT_UI4 ||
3025 leftvt == VT_UI8 || rightvt == VT_UI8 ||
3026 leftvt == VT_DECIMAL || rightvt == VT_DECIMAL)
3027 resvt = VT_I4;
3028 else if (leftvt == VT_UI1 || rightvt == VT_UI1 ||
3029 leftvt == VT_I2 || rightvt == VT_I2 ||
3030 leftvt == VT_EMPTY || rightvt == VT_EMPTY)
3031 if ((leftvt == VT_NULL && rightvt == VT_UI1) ||
3032 (leftvt == VT_UI1 && rightvt == VT_NULL) ||
3033 (leftvt == VT_UI1 && rightvt == VT_UI1))
3034 resvt = VT_UI1;
3035 else
3036 resvt = VT_I2;
3037 else if (leftvt == VT_BOOL || rightvt == VT_BOOL ||
3038 (leftvt == VT_BSTR && rightvt == VT_BSTR))
3039 resvt = VT_BOOL;
3040 else if (leftvt == VT_NULL || rightvt == VT_NULL ||
3041 leftvt == VT_BSTR || rightvt == VT_BSTR)
3042 resvt = VT_NULL;
3043 else
3044 {
3045 hres = DISP_E_BADVARTYPE;
3046 goto VarAnd_Exit;
3047 }
3048
3049 if (leftvt == VT_NULL || rightvt == VT_NULL)
3050 {
3051 /*
3052 * Special cases for when left variant is VT_NULL
3053 * (VT_NULL & 0 = VT_NULL, VT_NULL & value = value)
3054 */
3055 if (leftvt == VT_NULL)
3056 {
3057 VARIANT_BOOL b;
3058 switch(rightvt)
3059 {
3060 case VT_I1: if (V_I1(right)) resvt = VT_NULL; break;
3061 case VT_UI1: if (V_UI1(right)) resvt = VT_NULL; break;
3062 case VT_I2: if (V_I2(right)) resvt = VT_NULL; break;
3063 case VT_UI2: if (V_UI2(right)) resvt = VT_NULL; break;
3064 case VT_I4: if (V_I4(right)) resvt = VT_NULL; break;
3065 case VT_UI4: if (V_UI4(right)) resvt = VT_NULL; break;
3066 case VT_I8: if (V_I8(right)) resvt = VT_NULL; break;
3067 case VT_UI8: if (V_UI8(right)) resvt = VT_NULL; break;
3068 case VT_INT: if (V_INT(right)) resvt = VT_NULL; break;
3069 case VT_UINT: if (V_UINT(right)) resvt = VT_NULL; break;
3070 case VT_BOOL: if (V_BOOL(right)) resvt = VT_NULL; break;
3071 case VT_R4: if (V_R4(right)) resvt = VT_NULL; break;
3072 case VT_R8: if (V_R8(right)) resvt = VT_NULL; break;
3073 case VT_CY:
3074 if(V_CY(right).int64)
3075 resvt = VT_NULL;
3076 break;
3077 case VT_DECIMAL:
3078 if (DEC_HI32(&V_DECIMAL(right)) ||
3079 DEC_LO64(&V_DECIMAL(right)))
3080 resvt = VT_NULL;
3081 break;
3082 case VT_BSTR:
3083 hres = VarBoolFromStr(V_BSTR(right),
3084 LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
3085 if (FAILED(hres))
3086 return hres;
3087 else if (b)
3088 V_VT(result) = VT_NULL;
3089 else
3090 {
3091 V_VT(result) = VT_BOOL;
3092 V_BOOL(result) = b;
3093 }
3094 goto VarAnd_Exit;
3095 }
3096 }
3097 V_VT(result) = resvt;
3098 goto VarAnd_Exit;
3099 }
3100
3101 hres = VariantCopy(&varLeft, left);
3102 if (FAILED(hres)) goto VarAnd_Exit;
3103
3104 hres = VariantCopy(&varRight, right);
3105 if (FAILED(hres)) goto VarAnd_Exit;
3106
3107 if (resvt == VT_I4 && V_VT(&varLeft) == VT_UI4)
3108 V_VT(&varLeft) = VT_I4; /* Don't overflow */
3109 else
3110 {
3111 double d;
3112
3113 if (V_VT(&varLeft) == VT_BSTR &&
3114 FAILED(VarR8FromStr(V_BSTR(&varLeft),
3115 LOCALE_USER_DEFAULT, 0, &d)))
3116 hres = VariantChangeType(&varLeft,&varLeft,
3117 VARIANT_LOCALBOOL, VT_BOOL);
3118 if (SUCCEEDED(hres) && V_VT(&varLeft) != resvt)
3119 hres = VariantChangeType(&varLeft,&varLeft,0,resvt);
3120 if (FAILED(hres)) goto VarAnd_Exit;
3121 }
3122
3123 if (resvt == VT_I4 && V_VT(&varRight) == VT_UI4)
3124 V_VT(&varRight) = VT_I4; /* Don't overflow */
3125 else
3126 {
3127 double d;
3128
3129 if (V_VT(&varRight) == VT_BSTR &&
3130 FAILED(VarR8FromStr(V_BSTR(&varRight),
3131 LOCALE_USER_DEFAULT, 0, &d)))
3132 hres = VariantChangeType(&varRight, &varRight,
3133 VARIANT_LOCALBOOL, VT_BOOL);
3134 if (SUCCEEDED(hres) && V_VT(&varRight) != resvt)
3135 hres = VariantChangeType(&varRight, &varRight, 0, resvt);
3136 if (FAILED(hres)) goto VarAnd_Exit;
3137 }
3138
3139 V_VT(result) = resvt;
3140 switch(resvt)
3141 {
3142 case VT_I8:
3143 V_I8(result) = V_I8(&varLeft) & V_I8(&varRight);
3144 break;
3145 case VT_I4:
3146 V_I4(result) = V_I4(&varLeft) & V_I4(&varRight);
3147 break;
3148 case VT_I2:
3149 V_I2(result) = V_I2(&varLeft) & V_I2(&varRight);
3150 break;
3151 case VT_UI1:
3152 V_UI1(result) = V_UI1(&varLeft) & V_UI1(&varRight);
3153 break;
3154 case VT_BOOL:
3155 V_BOOL(result) = V_BOOL(&varLeft) & V_BOOL(&varRight);
3156 break;
3157 default:
3158 FIXME("Couldn't bitwise AND variant types %d,%d\n",
3159 leftvt,rightvt);
3160 }
3161
3162 VarAnd_Exit:
3163 VariantClear(&varLeft);
3164 VariantClear(&varRight);
3165 VariantClear(&tempLeft);
3166 VariantClear(&tempRight);
3167
3168 return hres;
3169 }
3170
3171 /**********************************************************************
3172 * VarAdd [OLEAUT32.141]
3173 *
3174 * Add two variants.
3175 *
3176 * PARAMS
3177 * left [I] First variant
3178 * right [I] Second variant
3179 * result [O] Result variant
3180 *
3181 * RETURNS
3182 * Success: S_OK.
3183 * Failure: An HRESULT error code indicating the error.
3184 *
3185 * NOTES
3186 * Native VarAdd up to and including WinXP doesn't like I1, UI2, UI4,
3187 * UI8, INT and UINT as input variants.
3188 *
3189 * Native VarAdd doesn't check for NULL in/out pointers and crashes. We do the
3190 * same here.
3191 *
3192 * FIXME
3193 * Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that
3194 * case.
3195 */
3196 HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
3197 {
3198 HRESULT hres;
3199 VARTYPE lvt, rvt, resvt, tvt;
3200 VARIANT lv, rv, tv;
3201 VARIANT tempLeft, tempRight;
3202 double r8res;
3203
3204 /* Variant priority for coercion. Sorted from lowest to highest.
3205 VT_ERROR shows an invalid input variant type. */
3206 enum coerceprio { vt_EMPTY, vt_UI1, vt_I2, vt_I4, vt_I8, vt_BSTR,vt_R4,
3207 vt_R8, vt_CY, vt_DATE, vt_DECIMAL, vt_DISPATCH, vt_NULL,
3208 vt_ERROR };
3209 /* Mapping from priority to variant type. Keep in sync with coerceprio! */
3210 static const VARTYPE prio2vt[] = { VT_EMPTY, VT_UI1, VT_I2, VT_I4, VT_I8, VT_BSTR, VT_R4,
3211 VT_R8, VT_CY, VT_DATE, VT_DECIMAL, VT_DISPATCH,
3212 VT_NULL, VT_ERROR };
3213
3214 /* Mapping for coercion from input variant to priority of result variant. */
3215 static const VARTYPE coerce[] = {
3216 /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */
3217 vt_EMPTY, vt_NULL, vt_I2, vt_I4, vt_R4,
3218 /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */
3219 vt_R8, vt_CY, vt_DATE, vt_BSTR, vt_DISPATCH,
3220 /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */
3221 vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL,
3222 /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */
3223 vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8
3224 };
3225
3226 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
3227 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
3228 result);
3229
3230 VariantInit(&lv);
3231 VariantInit(&rv);
3232 VariantInit(&tv);
3233 VariantInit(&tempLeft);
3234 VariantInit(&tempRight);
3235
3236 /* Handle VT_DISPATCH by storing and taking address of returned value */
3237 if ((V_VT(left) & VT_TYPEMASK) != VT_NULL && (V_VT(right) & VT_TYPEMASK) != VT_NULL)
3238 {
3239 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
3240 {
3241 hres = VARIANT_FetchDispatchValue(left, &tempLeft);
3242 if (FAILED(hres)) goto end;
3243 left = &tempLeft;
3244 }
3245 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
3246 {
3247 hres = VARIANT_FetchDispatchValue(right, &tempRight);
3248 if (FAILED(hres)) goto end;
3249 right = &tempRight;
3250 }
3251 }
3252
3253 lvt = V_VT(left)&VT_TYPEMASK;
3254 rvt = V_VT(right)&VT_TYPEMASK;
3255
3256 /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out.
3257 Same for any input variant type > VT_I8 */
3258 if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK ||
3259 lvt > VT_I8 || rvt > VT_I8) {
3260 hres = DISP_E_BADVARTYPE;
3261 goto end;
3262 }
3263
3264 /* Determine the variant type to coerce to. */
3265 if (coerce[lvt] > coerce[rvt]) {
3266 resvt = prio2vt[coerce[lvt]];
3267 tvt = prio2vt[coerce[rvt]];
3268 } else {
3269 resvt = prio2vt[coerce[rvt]];
3270 tvt = prio2vt[coerce[lvt]];
3271 }
3272
3273 /* Special cases where the result variant type is defined by both
3274 input variants and not only that with the highest priority */
3275 if (resvt == VT_BSTR) {
3276 if (tvt == VT_EMPTY || tvt == VT_BSTR)
3277 resvt = VT_BSTR;
3278 else
3279 resvt = VT_R8;
3280 }
3281 if (resvt == VT_R4 && (tvt == VT_BSTR || tvt == VT_I8 || tvt == VT_I4))
3282 resvt = VT_R8;
3283
3284 /* For overflow detection use the biggest compatible type for the
3285 addition */
3286 switch (resvt) {
3287 case VT_ERROR:
3288 hres = DISP_E_BADVARTYPE;
3289 goto end;
3290 case VT_NULL:
3291 hres = S_OK;
3292 V_VT(result) = VT_NULL;
3293 goto end;
3294 case VT_DISPATCH:
3295 FIXME("cannot handle variant type VT_DISPATCH\n");
3296 hres = DISP_E_TYPEMISMATCH;
3297 goto end;
3298 case VT_EMPTY:
3299 resvt = VT_I2;
3300 /* Fall through */
3301 case VT_UI1:
3302 case VT_I2:
3303 case VT_I4:
3304 case VT_I8:
3305 tvt = VT_I8;
3306 break;
3307 case VT_DATE:
3308 case VT_R4:
3309 tvt = VT_R8;
3310 break;
3311 default:
3312 tvt = resvt;
3313 }
3314
3315 /* Now coerce the variants */
3316 hres = VariantChangeType(&lv, left, 0, tvt);
3317 if (FAILED(hres))
3318 goto end;
3319 hres = VariantChangeType(&rv, right, 0, tvt);
3320 if (FAILED(hres))
3321 goto end;
3322
3323 /* Do the math */
3324 hres = S_OK;
3325 V_VT(result) = resvt;
3326 switch (tvt) {
3327 case VT_DECIMAL:
3328 hres = VarDecAdd(&V_DECIMAL(&lv), &V_DECIMAL(&rv),
3329 &V_DECIMAL(result));
3330 goto end;
3331 case VT_CY:
3332 hres = VarCyAdd(V_CY(&lv), V_CY(&rv), &V_CY(result));
3333 goto end;
3334 case VT_BSTR:
3335 /* We do not add those, we concatenate them. */
3336 hres = VarBstrCat(V_BSTR(&lv), V_BSTR(&rv), &V_BSTR(result));
3337 goto end;
3338 case VT_I8:
3339 /* Overflow detection */
3340 r8res = (double)V_I8(&lv) + (double)V_I8(&rv);
3341 if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) {
3342 V_VT(result) = VT_R8;
3343 V_R8(result) = r8res;
3344 goto end;
3345 } else {
3346 V_VT(&tv) = tvt;
3347 V_I8(&tv) = V_I8(&lv) + V_I8(&rv);
3348 }
3349 break;
3350 case VT_R8:
3351 V_VT(&tv) = tvt;
3352 /* FIXME: overflow detection */
3353 V_R8(&tv) = V_R8(&lv) + V_R8(&rv);
3354 break;
3355 default:
3356 ERR("We shouldn't get here! tvt = %d!\n", tvt);
3357 break;
3358 }
3359 if (resvt != tvt) {
3360 if ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) {
3361 /* Overflow! Change to the vartype with the next higher priority.
3362 With one exception: I4 ==> R8 even if it would fit in I8 */
3363 if (resvt == VT_I4)
3364 resvt = VT_R8;
3365 else
3366 resvt = prio2vt[coerce[resvt] + 1];
3367 hres = VariantChangeType(result, &tv, 0, resvt);
3368 }
3369 } else
3370 hres = VariantCopy(result, &tv);
3371
3372 end:
3373 if (hres != S_OK) {
3374 V_VT(result) = VT_EMPTY;
3375 V_I4(result) = 0; /* No V_EMPTY */
3376 }
3377 VariantClear(&lv);
3378 VariantClear(&rv);
3379 VariantClear(&tv);
3380 VariantClear(&tempLeft);
3381 VariantClear(&tempRight);
3382 TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
3383 return hres;
3384 }
3385
3386 /**********************************************************************
3387 * VarMul [OLEAUT32.156]
3388 *
3389 * Multiply two variants.
3390 *
3391 * PARAMS
3392 * left [I] First variant
3393 * right [I] Second variant
3394 * result [O] Result variant
3395 *
3396 * RETURNS
3397 * Success: S_OK.
3398 * Failure: An HRESULT error code indicating the error.
3399 *
3400 * NOTES
3401 * Native VarMul up to and including WinXP doesn't like I1, UI2, UI4,
3402 * UI8, INT and UINT as input variants. But it can multiply apples with oranges.
3403 *
3404 * Native VarMul doesn't check for NULL in/out pointers and crashes. We do the
3405 * same here.
3406 *
3407 * FIXME
3408 * Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that
3409 * case.
3410 */
3411 HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
3412 {
3413 HRESULT hres;
3414 VARTYPE lvt, rvt, resvt, tvt;
3415 VARIANT lv, rv, tv;
3416 VARIANT tempLeft, tempRight;
3417 double r8res;
3418
3419 /* Variant priority for coercion. Sorted from lowest to highest.
3420 VT_ERROR shows an invalid input variant type. */
3421 enum coerceprio { vt_UI1 = 0, vt_I2, vt_I4, vt_I8, vt_CY, vt_R4, vt_R8,
3422 vt_DECIMAL, vt_NULL, vt_ERROR };
3423 /* Mapping from priority to variant type. Keep in sync with coerceprio! */
3424 static const VARTYPE prio2vt[] = { VT_UI1, VT_I2, VT_I4, VT_I8, VT_CY, VT_R4, VT_R8,
3425 VT_DECIMAL, VT_NULL, VT_ERROR };
3426
3427 /* Mapping for coercion from input variant to priority of result variant. */
3428 static const VARTYPE coerce[] = {
3429 /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */
3430 vt_UI1, vt_NULL, vt_I2, vt_I4, vt_R4,
3431 /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */
3432 vt_R8, vt_CY, vt_R8, vt_R8, vt_ERROR,
3433 /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */
3434 vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL,
3435 /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */
3436 vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8
3437 };
3438
3439 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
3440 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
3441 result);
3442
3443 VariantInit(&lv);
3444 VariantInit(&rv);
3445 VariantInit(&tv);
3446 VariantInit(&tempLeft);
3447 VariantInit(&tempRight);
3448
3449 /* Handle VT_DISPATCH by storing and taking address of returned value */
3450 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
3451 {
3452 hres = VARIANT_FetchDispatchValue(left, &tempLeft);
3453 if (FAILED(hres)) goto end;
3454 left = &tempLeft;
3455 }
3456 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
3457 {
3458 hres = VARIANT_FetchDispatchValue(right, &tempRight);
3459 if (FAILED(hres)) goto end;
3460 right = &tempRight;
3461 }
3462
3463 lvt = V_VT(left)&VT_TYPEMASK;
3464 rvt = V_VT(right)&VT_TYPEMASK;
3465
3466 /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out.
3467 Same for any input variant type > VT_I8 */
3468 if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK ||
3469 lvt > VT_I8 || rvt > VT_I8) {
3470 hres = DISP_E_BADVARTYPE;
3471 goto end;
3472 }
3473
3474 /* Determine the variant type to coerce to. */
3475 if (coerce[lvt] > coerce[rvt]) {
3476 resvt = prio2vt[coerce[lvt]];
3477 tvt = prio2vt[coerce[rvt]];
3478 } else {
3479 resvt = prio2vt[coerce[rvt]];
3480 tvt = prio2vt[coerce[lvt]];
3481 }
3482
3483 /* Special cases where the result variant type is defined by both
3484 input variants and not only that with the highest priority */
3485 if (resvt == VT_R4 && (tvt == VT_CY || tvt == VT_I8 || tvt == VT_I4))
3486 resvt = VT_R8;
3487 if (lvt == VT_EMPTY && rvt == VT_EMPTY)
3488 resvt = VT_I2;
3489
3490 /* For overflow detection use the biggest compatible type for the
3491 multiplication */
3492 switch (resvt) {
3493 case VT_ERROR:
3494 hres = DISP_E_BADVARTYPE;
3495 goto end;
3496 case VT_NULL:
3497 hres = S_OK;
3498 V_VT(result) = VT_NULL;
3499 goto end;
3500 case VT_UI1:
3501 case VT_I2:
3502 case VT_I4:
3503 case VT_I8:
3504 tvt = VT_I8;
3505 break;
3506 case VT_R4:
3507 tvt = VT_R8;
3508 break;
3509 default:
3510 tvt = resvt;
3511 }
3512
3513 /* Now coerce the variants */
3514 hres = VariantChangeType(&lv, left, 0, tvt);
3515 if (FAILED(hres))
3516 goto end;
3517 hres = VariantChangeType(&rv, right, 0, tvt);
3518 if (FAILED(hres))
3519 goto end;
3520
3521 /* Do the math */
3522 hres = S_OK;
3523 V_VT(&tv) = tvt;
3524 V_VT(result) = resvt;
3525 switch (tvt) {
3526 case VT_DECIMAL:
3527 hres = VarDecMul(&V_DECIMAL(&lv), &V_DECIMAL(&rv),
3528 &V_DECIMAL(result));
3529 goto end;
3530 case VT_CY:
3531 hres = VarCyMul(V_CY(&lv), V_CY(&rv), &V_CY(result));
3532 goto end;
3533 case VT_I8:
3534 /* Overflow detection */
3535 r8res = (double)V_I8(&lv) * (double)V_I8(&rv);
3536 if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) {
3537 V_VT(result) = VT_R8;
3538 V_R8(result) = r8res;
3539 goto end;
3540 } else
3541 V_I8(&tv) = V_I8(&lv) * V_I8(&rv);
3542 break;
3543 case VT_R8:
3544 /* FIXME: overflow detection */
3545 V_R8(&tv) = V_R8(&lv) * V_R8(&rv);
3546 break;
3547 default:
3548 ERR("We shouldn't get here! tvt = %d!\n", tvt);
3549 break;
3550 }
3551 if (resvt != tvt) {
3552 while ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) {
3553 /* Overflow! Change to the vartype with the next higher priority.
3554 With one exception: I4 ==> R8 even if it would fit in I8 */
3555 if (resvt == VT_I4)
3556 resvt = VT_R8;
3557 else
3558 resvt = prio2vt[coerce[resvt] + 1];
3559 }
3560 } else
3561 hres = VariantCopy(result, &tv);
3562
3563 end:
3564 if (hres != S_OK) {
3565 V_VT(result) = VT_EMPTY;
3566 V_I4(result) = 0; /* No V_EMPTY */
3567 }
3568 VariantClear(&lv);
3569 VariantClear(&rv);
3570 VariantClear(&tv);
3571 VariantClear(&tempLeft);
3572 VariantClear(&tempRight);
3573 TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
3574 return hres;
3575 }
3576
3577 /**********************************************************************
3578 * VarDiv [OLEAUT32.143]
3579 *
3580 * Divides one variant with another.
3581 *
3582 * PARAMS
3583 * left [I] First variant
3584 * right [I] Second variant
3585 * result [O] Result variant
3586 *
3587 * RETURNS
3588 * Success: S_OK.
3589 * Failure: An HRESULT error code indicating the error.
3590 */
3591 HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
3592 {
3593 HRESULT hres = S_OK;
3594 VARTYPE resvt = VT_EMPTY;
3595 VARTYPE leftvt,rightvt;
3596 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
3597 VARIANT lv,rv;
3598 VARIANT tempLeft, tempRight;
3599
3600 VariantInit(&tempLeft);
3601 VariantInit(&tempRight);
3602 VariantInit(&lv);
3603 VariantInit(&rv);
3604
3605 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
3606 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
3607
3608 /* Handle VT_DISPATCH by storing and taking address of returned value */
3609 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
3610 {
3611 hres = VARIANT_FetchDispatchValue(left, &tempLeft);
3612 if (FAILED(hres)) goto end;
3613 left = &tempLeft;
3614 }
3615 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
3616 {
3617 hres = VARIANT_FetchDispatchValue(right, &tempRight);
3618 if (FAILED(hres)) goto end;
3619 right = &tempRight;
3620 }
3621
3622 leftvt = V_VT(left)&VT_TYPEMASK;
3623 rightvt = V_VT(right)&VT_TYPEMASK;
3624 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
3625 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
3626
3627 if (leftExtraFlags != rightExtraFlags)
3628 {
3629 hres = DISP_E_BADVARTYPE;
3630 goto end;
3631 }
3632 ExtraFlags = leftExtraFlags;
3633
3634 /* Native VarDiv always returns an error when using extra flags */
3635 if (ExtraFlags != 0)
3636 {
3637 hres = DISP_E_BADVARTYPE;
3638 goto end;
3639 }
3640
3641 /* Determine return type */
3642 if (!(rightvt == VT_EMPTY))
3643 {
3644 if (leftvt == VT_NULL || rightvt == VT_NULL)
3645 {
3646 V_VT(result) = VT_NULL;
3647 hres = S_OK;
3648 goto end;
3649 }
3650 else if (leftvt == VT_DECIMAL || rightvt == VT_DECIMAL)
3651 resvt = VT_DECIMAL;
3652 else if (leftvt == VT_I8 || rightvt == VT_I8 ||
3653 leftvt == VT_CY || rightvt == VT_CY ||
3654 leftvt == VT_DATE || rightvt == VT_DATE ||
3655 leftvt == VT_I4 || rightvt == VT_I4 ||
3656 leftvt == VT_BSTR || rightvt == VT_BSTR ||
3657 leftvt == VT_I2 || rightvt == VT_I2 ||
3658 leftvt == VT_BOOL || rightvt == VT_BOOL ||
3659 leftvt == VT_R8 || rightvt == VT_R8 ||
3660 leftvt == VT_UI1 || rightvt == VT_UI1)
3661 {
3662 if ((leftvt == VT_UI1 && rightvt == VT_R4) ||
3663 (leftvt == VT_R4 && rightvt == VT_UI1))
3664 resvt = VT_R4;
3665 else if ((leftvt == VT_R4 && (rightvt == VT_BOOL ||
3666 rightvt == VT_I2)) || (rightvt == VT_R4 &&
3667 (leftvt == VT_BOOL || leftvt == VT_I2)))
3668 resvt = VT_R4;
3669 else
3670 resvt = VT_R8;
3671 }
3672 else if (leftvt == VT_R4 || rightvt == VT_R4)
3673 resvt = VT_R4;
3674 }
3675 else if (leftvt == VT_NULL && rightvt == VT_EMPTY)
3676 {
3677 V_VT(result) = VT_NULL;
3678 hres = S_OK;
3679 goto end;
3680 }
3681 else
3682 {
3683 hres = DISP_E_BADVARTYPE;
3684 goto end;
3685 }
3686
3687 /* coerce to the result type */
3688 hres = VariantChangeType(&lv, left, 0, resvt);
3689 if (hres != S_OK) goto end;
3690
3691 hres = VariantChangeType(&rv, right, 0, resvt);
3692 if (hres != S_OK) goto end;
3693
3694 /* do the math */
3695 V_VT(result) = resvt;
3696 switch (resvt)
3697 {
3698 case VT_R4:
3699 if (V_R4(&lv) == 0.0 && V_R4(&rv) == 0.0)
3700 {
3701 hres = DISP_E_OVERFLOW;
3702 V_VT(result) = VT_EMPTY;
3703 }
3704 else if (V_R4(&rv) == 0.0)
3705 {
3706 hres = DISP_E_DIVBYZERO;
3707 V_VT(result) = VT_EMPTY;
3708 }
3709 else
3710 V_R4(result) = V_R4(&lv) / V_R4(&rv);
3711 break;
3712 case VT_R8:
3713 if (V_R8(&lv) == 0.0 && V_R8(&rv) == 0.0)
3714 {
3715 hres = DISP_E_OVERFLOW;
3716 V_VT(result) = VT_EMPTY;
3717 }
3718 else if (V_R8(&rv) == 0.0)
3719 {
3720 hres = DISP_E_DIVBYZERO;
3721 V_VT(result) = VT_EMPTY;
3722 }
3723 else
3724 V_R8(result) = V_R8(&lv) / V_R8(&rv);
3725 break;
3726 case VT_DECIMAL:
3727 hres = VarDecDiv(&(V_DECIMAL(&lv)), &(V_DECIMAL(&rv)), &(V_DECIMAL(result)));
3728 break;
3729 }
3730
3731 end:
3732 VariantClear(&lv);
3733 VariantClear(&rv);
3734 VariantClear(&tempLeft);
3735 VariantClear(&tempRight);
3736 TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
3737 return hres;
3738 }
3739
3740 /**********************************************************************
3741 * VarSub [OLEAUT32.159]
3742 *
3743 * Subtract two variants.
3744 *
3745 * PARAMS
3746 * left [I] First variant
3747 * right [I] Second variant
3748 * result [O] Result variant
3749 *
3750 * RETURNS
3751 * Success: S_OK.
3752 * Failure: An HRESULT error code indicating the error.
3753 */
3754 HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
3755 {
3756 HRESULT hres = S_OK;
3757 VARTYPE resvt = VT_EMPTY;
3758 VARTYPE leftvt,rightvt;
3759 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
3760 VARIANT lv,rv;
3761 VARIANT tempLeft, tempRight;
3762
3763 VariantInit(&lv);
3764 VariantInit(&rv);
3765 VariantInit(&tempLeft);
3766 VariantInit(&tempRight);
3767
3768 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
3769 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
3770
3771 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH &&
3772 (V_VT(left)&(~VT_TYPEMASK)) == 0 &&
3773 (V_VT(right) & VT_TYPEMASK) != VT_NULL)
3774 {
3775 if (NULL == V_DISPATCH(left)) {
3776 if ((V_VT(right) & VT_TYPEMASK) >= VT_INT_PTR)
3777 hres = DISP_E_BADVARTYPE;
3778 else if ((V_VT(right) & VT_TYPEMASK) >= VT_UI8 &&
3779 (V_VT(right) & VT_TYPEMASK) < VT_RECORD)
3780 hres = DISP_E_BADVARTYPE;
3781 else switch (V_VT(right) & VT_TYPEMASK)
3782 {
3783 case VT_VARIANT:
3784 case VT_UNKNOWN:
3785 case 15:
3786 case VT_I1:
3787 case VT_UI2:
3788 case VT_UI4:
3789 hres = DISP_E_BADVARTYPE;
3790 }
3791 if (FAILED(hres)) goto end;
3792 }
3793 hres = VARIANT_FetchDispatchValue(left, &tempLeft);
3794 if (FAILED(hres)) goto end;
3795 left = &tempLeft;
3796 }
3797 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH &&
3798 (V_VT(right)&(~VT_TYPEMASK)) == 0 &&
3799 (V_VT(left) & VT_TYPEMASK) != VT_NULL)
3800 {
3801 if (NULL == V_DISPATCH(right))
3802 {
3803 if ((V_VT(left) & VT_TYPEMASK) >= VT_INT_PTR)
3804 hres = DISP_E_BADVARTYPE;
3805 else if ((V_VT(left) & VT_TYPEMASK) >= VT_UI8 &&
3806 (V_VT(left) & VT_TYPEMASK) < VT_RECORD)
3807 hres = DISP_E_BADVARTYPE;
3808 else switch (V_VT(left) & VT_TYPEMASK)
3809 {
3810 case VT_VARIANT:
3811 case VT_UNKNOWN:
3812 case 15:
3813 case VT_I1:
3814 case VT_UI2:
3815 case VT_UI4:
3816 hres = DISP_E_BADVARTYPE;
3817 }
3818 if (FAILED(hres)) goto end;
3819 }
3820 hres = VARIANT_FetchDispatchValue(right, &tempRight);
3821 if (FAILED(hres)) goto end;
3822 right = &tempRight;
3823 }
3824
3825 leftvt = V_VT(left)&VT_TYPEMASK;
3826 rightvt = V_VT(right)&VT_TYPEMASK;
3827 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
3828 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
3829
3830 if (leftExtraFlags != rightExtraFlags)
3831 {
3832 hres = DISP_E_BADVARTYPE;
3833 goto end;
3834 }
3835 ExtraFlags = leftExtraFlags;
3836
3837 /* determine return type and return code */
3838 /* All extra flags produce errors */
3839 if (ExtraFlags == (VT_VECTOR|VT_BYREF|VT_RESERVED) ||
3840 ExtraFlags == (VT_VECTOR|VT_RESERVED) ||
3841 ExtraFlags == (VT_VECTOR|VT_BYREF) ||
3842 ExtraFlags == (VT_BYREF|VT_RESERVED) ||
3843 ExtraFlags == VT_VECTOR ||
3844 ExtraFlags == VT_BYREF ||
3845 ExtraFlags == VT_RESERVED)
3846 {
3847 hres = DISP_E_BADVARTYPE;
3848 goto end;
3849 }
3850 else if (ExtraFlags >= VT_ARRAY)
3851 {
3852 hres = DISP_E_TYPEMISMATCH;
3853 goto end;
3854 }
3855 /* Native VarSub cannot handle: VT_I1, VT_UI2, VT_UI4,
3856 VT_INT, VT_UINT and VT_UI8. Tested with WinXP */
3857 else if (leftvt == VT_CLSID || rightvt == VT_CLSID ||
3858 leftvt == VT_VARIANT || rightvt == VT_VARIANT ||
3859 leftvt == VT_I1 || rightvt == VT_I1 ||
3860 leftvt == VT_UI2 || rightvt == VT_UI2 ||
3861 leftvt == VT_UI4 || rightvt == VT_UI4 ||
3862 leftvt == VT_UI8 || rightvt == VT_UI8 ||
3863 leftvt == VT_INT || rightvt == VT_INT ||
3864 leftvt == VT_UINT || rightvt == VT_UINT ||
3865 leftvt == VT_UNKNOWN || rightvt == VT_UNKNOWN ||
3866 leftvt == VT_RECORD || rightvt == VT_RECORD)
3867 {
3868 if (leftvt == VT_RECORD && rightvt == VT_I8)
3869 hres = DISP_E_TYPEMISMATCH;
3870 else if (leftvt < VT_UI1 && rightvt == VT_RECORD)
3871 hres = DISP_E_TYPEMISMATCH;
3872 else if (leftvt >= VT_UI1 && rightvt == VT_RECORD)
3873 hres = DISP_E_TYPEMISMATCH;
3874 else if (leftvt == VT_RECORD && rightvt <= VT_UI1)
3875 hres = DISP_E_TYPEMISMATCH;
3876 else if (leftvt == VT_RECORD && rightvt > VT_UI1)
3877 hres = DISP_E_BADVARTYPE;
3878 else
3879 hres = DISP_E_BADVARTYPE;
3880 goto end;
3881 }
3882 /* The following flags/types are invalid for left variant */
3883 else if (!((leftvt <= VT_LPWSTR || leftvt == VT_RECORD ||
3884 leftvt == VT_CLSID) && leftvt != (VARTYPE)15 /* undefined vt */ &&
3885 (leftvt < VT_VOID || leftvt > VT_LPWSTR)))
3886 {
3887 hres = DISP_E_BADVARTYPE;
3888 goto end;
3889 }
3890 /* The following flags/types are invalid for right variant */
3891 else if (!((rightvt <= VT_LPWSTR || rightvt == VT_RECORD ||
3892 rightvt == VT_CLSID) && rightvt != (VARTYPE)15 /* undefined vt */ &&
3893 (rightvt < VT_VOID || rightvt > VT_LPWSTR)))
3894 {
3895 hres = DISP_E_BADVARTYPE;
3896 goto end;
3897 }
3898 else if ((leftvt == VT_NULL && rightvt == VT_DISPATCH) ||
3899 (leftvt == VT_DISPATCH && rightvt == VT_NULL))
3900 resvt = VT_NULL;
3901 else if (leftvt == VT_DISPATCH || rightvt == VT_DISPATCH ||
3902 leftvt == VT_ERROR || rightvt == VT_ERROR)
3903 {
3904 hres = DISP_E_TYPEMISMATCH;
3905 goto end;
3906 }
3907 else if (leftvt == VT_NULL || rightvt == VT_NULL)
3908 resvt = VT_NULL;
3909 else if ((leftvt == VT_EMPTY && rightvt == VT_BSTR) ||
3910 (leftvt == VT_DATE && rightvt == VT_DATE) ||
3911 (leftvt == VT_BSTR && rightvt == VT_EMPTY) ||
3912 (leftvt == VT_BSTR && rightvt == VT_BSTR))
3913 resvt = VT_R8;
3914 else if (leftvt == VT_DECIMAL || rightvt == VT_DECIMAL)
3915 resvt = VT_DECIMAL;
3916 else if (leftvt == VT_DATE || rightvt == VT_DATE)
3917 resvt = VT_DATE;
3918 else if (leftvt == VT_CY || rightvt == VT_CY)
3919 resvt = VT_CY;
3920 else if (leftvt == VT_R8 || rightvt == VT_R8)
3921 resvt = VT_R8;
3922 else if (leftvt == VT_BSTR || rightvt == VT_BSTR)
3923 resvt = VT_R8;
3924 else if (leftvt == VT_R4 || rightvt == VT_R4)
3925 {
3926 if (leftvt == VT_I4 || rightvt == VT_I4 ||
3927 leftvt == VT_I8 || rightvt == VT_I8)
3928 resvt = VT_R8;
3929 else
3930 resvt = VT_R4;
3931 }
3932 else if (leftvt == VT_I8 || rightvt == VT_I8)
3933 resvt = VT_I8;
3934 else if (leftvt == VT_I4 || rightvt == VT_I4)
3935 resvt = VT_I4;
3936 else if (leftvt == VT_I2 || rightvt == VT_I2 ||
3937 leftvt == VT_BOOL || rightvt == VT_BOOL ||
3938 (leftvt == VT_EMPTY && rightvt == VT_EMPTY))
3939 resvt = VT_I2;
3940 else if (leftvt == VT_UI1 || rightvt == VT_UI1)
3941 resvt = VT_UI1;
3942 else
3943 {
3944 hres = DISP_E_TYPEMISMATCH;
3945 goto end;
3946 }
3947
3948 /* coerce to the result type */
3949 if (leftvt == VT_BSTR && rightvt == VT_DATE)
3950 hres = VariantChangeType(&lv, left, 0, VT_R8);
3951 else
3952 hres = VariantChangeType(&lv, left, 0, resvt);
3953 if (hres != S_OK) goto end;
3954 if (leftvt == VT_DATE && rightvt == VT_BSTR)
3955 hres = VariantChangeType(&rv, right, 0, VT_R8);
3956 else
3957 hres = VariantChangeType(&rv, right, 0, resvt);
3958 if (hres != S_OK) goto end;
3959
3960 /* do the math */
3961 V_VT(result) = resvt;
3962 switch (resvt)
3963 {
3964 case VT_NULL:
3965 break;
3966 case VT_DATE:
3967 V_DATE(result) = V_DATE(&lv) - V_DATE(&rv);
3968 break;
3969 case VT_CY:
3970 hres = VarCySub(V_CY(&lv), V_CY(&rv), &(V_CY(result)));
3971 break;
3972 case VT_R4:
3973 V_R4(result) = V_R4(&lv) - V_R4(&rv);
3974 break;
3975 case VT_I8:
3976 V_I8(result) = V_I8(&lv) - V_I8(&rv);
3977 break;
3978 case VT_I4:
3979 V_I4(result) = V_I4(&lv) - V_I4(&rv);
3980 break;
3981 case VT_I2:
3982 V_I2(result) = V_I2(&lv) - V_I2(&rv);
3983 break;
3984 case VT_I1:
3985 V_I1(result) = V_I1(&lv) - V_I1(&rv);
3986 break;
3987 case VT_UI1:
3988 V_UI1(result) = V_UI2(&lv) - V_UI1(&rv);
3989 break;
3990 case VT_R8:
3991 V_R8(result) = V_R8(&lv) - V_R8(&rv);
3992 break;
3993 case VT_DECIMAL:
3994 hres = VarDecSub(&(V_DECIMAL(&lv)), &(V_DECIMAL(&rv)), &(V_DECIMAL(result)));
3995 break;
3996 }
3997
3998 end:
3999 VariantClear(&lv);
4000 VariantClear(&rv);
4001 VariantClear(&tempLeft);
4002 VariantClear(&tempRight);
4003 TRACE("returning 0x%8x (variant type %s)\n", hres, debugstr_VT(result));
4004 return hres;
4005 }
4006
4007
4008 /**********************************************************************
4009 * VarOr [OLEAUT32.157]
4010 *
4011 * Perform a logical or (OR) operation on two variants.
4012 *
4013 * PARAMS
4014 * pVarLeft [I] First variant
4015 * pVarRight [I] Variant to OR with pVarLeft
4016 * pVarOut [O] Destination for OR result
4017 *
4018 * RETURNS
4019 * Success: S_OK. pVarOut contains the result of the operation with its type
4020 * taken from the table listed under VarXor().
4021 * Failure: An HRESULT error code indicating the error.
4022 *
4023 * NOTES
4024 * See the Notes section of VarXor() for further information.
4025 */
4026 HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
4027 {
4028 VARTYPE vt = VT_I4;
4029 VARIANT varLeft, varRight, varStr;
4030 HRESULT hRet;
4031 VARIANT tempLeft, tempRight;
4032
4033 VariantInit(&tempLeft);
4034 VariantInit(&tempRight);
4035 VariantInit(&varLeft);
4036 VariantInit(&varRight);
4037 VariantInit(&varStr);
4038
4039 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
4040 debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
4041 debugstr_VF(pVarRight), pVarOut);
4042
4043 /* Handle VT_DISPATCH by storing and taking address of returned value */
4044 if ((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH)
4045 {
4046 hRet = VARIANT_FetchDispatchValue(pVarLeft, &tempLeft);
4047 if (FAILED(hRet)) goto VarOr_Exit;
4048 pVarLeft = &tempLeft;
4049 }
4050 if ((V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH)
4051 {
4052 hRet = VARIANT_FetchDispatchValue(pVarRight, &tempRight);
4053 if (FAILED(hRet)) goto VarOr_Exit;
4054 pVarRight = &tempRight;
4055 }
4056
4057 if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
4058 V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
4059 V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH ||
4060 V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD)
4061 {
4062 hRet = DISP_E_BADVARTYPE;
4063 goto VarOr_Exit;
4064 }
4065
4066 V_VT(&varLeft) = V_VT(&varRight) = V_VT(&varStr) = VT_EMPTY;
4067
4068 if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
4069 {
4070 /* NULL OR Zero is NULL, NULL OR value is value */
4071 if (V_VT(pVarLeft) == VT_NULL)
4072 pVarLeft = pVarRight; /* point to the non-NULL var */
4073
4074 V_VT(pVarOut) = VT_NULL;
4075 V_I4(pVarOut) = 0;
4076
4077 switch (V_VT(pVarLeft))
4078 {
4079 case VT_DATE: case VT_R8:
4080 if (V_R8(pVarLeft))
4081 goto VarOr_AsEmpty;
4082 hRet = S_OK;
4083 goto VarOr_Exit;
4084 case VT_BOOL:
4085 if (V_BOOL(pVarLeft))
4086 *pVarOut = *pVarLeft;
4087 hRet = S_OK;
4088 goto VarOr_Exit;
4089 case VT_I2: case VT_UI2:
4090 if (V_I2(pVarLeft))
4091 goto VarOr_AsEmpty;
4092 hRet = S_OK;
4093 goto VarOr_Exit;
4094 case VT_I1:
4095 if (V_I1(pVarLeft))
4096 goto VarOr_AsEmpty;
4097 hRet = S_OK;
4098 goto VarOr_Exit;
4099 case VT_UI1:
4100 if (V_UI1(pVarLeft))
4101 *pVarOut = *pVarLeft;
4102 hRet = S_OK;
4103 goto VarOr_Exit;
4104 case VT_R4:
4105 if (V_R4(pVarLeft))
4106 goto VarOr_AsEmpty;
4107 hRet = S_OK;
4108 goto VarOr_Exit;
4109 case VT_I4: case VT_UI4: case VT_INT: case VT_UINT:
4110 if (V_I4(pVarLeft))
4111 goto VarOr_AsEmpty;
4112 hRet = S_OK;
4113 goto VarOr_Exit;
4114 case VT_CY:
4115 if (V_CY(pVarLeft).int64)
4116 goto VarOr_AsEmpty;
4117 hRet = S_OK;
4118 goto VarOr_Exit;
4119 case VT_I8: case VT_UI8:
4120 if (V_I8(pVarLeft))
4121 goto VarOr_AsEmpty;
4122 hRet = S_OK;
4123 goto VarOr_Exit;
4124 case VT_DECIMAL:
4125 if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft)))
4126 goto VarOr_AsEmpty;
4127 hRet = S_OK;
4128 goto VarOr_Exit;
4129 case VT_BSTR:
4130 {
4131 VARIANT_BOOL b;
4132
4133 if (!V_BSTR(pVarLeft))
4134 {
4135 hRet = DISP_E_BADVARTYPE;
4136 goto VarOr_Exit;
4137 }
4138
4139 hRet = VarBoolFromStr(V_BSTR(pVarLeft), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
4140 if (SUCCEEDED(hRet) && b)
4141 {
4142 V_VT(pVarOut) = VT_BOOL;
4143 V_BOOL(pVarOut) = b;
4144 }
4145 goto VarOr_Exit;
4146 }
4147 case VT_NULL: case VT_EMPTY:
4148 V_VT(pVarOut) = VT_NULL;
4149 hRet = S_OK;
4150 goto VarOr_Exit;
4151 default:
4152 hRet = DISP_E_BADVARTYPE;
4153 goto VarOr_Exit;
4154 }
4155 }
4156
4157 if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY)
4158 {
4159 if (V_VT(pVarLeft) == VT_EMPTY)
4160 pVarLeft = pVarRight; /* point to the non-EMPTY var */
4161
4162 VarOr_AsEmpty:
4163 /* Since one argument is empty (0), OR'ing it with the other simply
4164 * gives the others value (as 0|x => x). So just convert the other
4165 * argument to the required result type.
4166 */
4167 switch (V_VT(pVarLeft))
4168 {
4169 case VT_BSTR:
4170 if (!V_BSTR(pVarLeft))
4171 {
4172 hRet = DISP_E_BADVARTYPE;
4173 goto VarOr_Exit;
4174 }
4175
4176 hRet = VariantCopy(&varStr, pVarLeft);
4177 if (FAILED(hRet))
4178 goto VarOr_Exit;
4179 pVarLeft = &varStr;
4180 hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
4181 if (FAILED(hRet))
4182 goto VarOr_Exit;
4183 /* Fall Through ... */
4184 case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2:
4185 V_VT(pVarOut) = VT_I2;
4186 break;
4187 case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8:
4188 case VT_I1: case VT_UI2: case VT_I4: case VT_UI4:
4189 case VT_INT: case VT_UINT: case VT_UI8:
4190 V_VT(pVarOut) = VT_I4;
4191 break;
4192 case VT_I8:
4193 V_VT(pVarOut) = VT_I8;
4194 break;
4195 default:
4196 hRet = DISP_E_BADVARTYPE;
4197 goto VarOr_Exit;
4198 }
4199 hRet = VariantCopy(&varLeft, pVarLeft);
4200 if (FAILED(hRet))
4201 goto VarOr_Exit;
4202 pVarLeft = &varLeft;
4203 hRet = VariantChangeType(pVarOut, pVarLeft, 0, V_VT(pVarOut));
4204 goto VarOr_Exit;
4205 }
4206
4207 if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL)
4208 {
4209 V_VT(pVarOut) = VT_BOOL;
4210 V_BOOL(pVarOut) = V_BOOL(pVarLeft) | V_BOOL(pVarRight);
4211 hRet = S_OK;
4212 goto VarOr_Exit;
4213 }
4214
4215 if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1)
4216 {
4217 V_VT(pVarOut) = VT_UI1;
4218 V_UI1(pVarOut) = V_UI1(pVarLeft) | V_UI1(pVarRight);
4219 hRet = S_OK;
4220 goto VarOr_Exit;
4221 }
4222
4223 if (V_VT(pVarLeft) == VT_BSTR)
4224 {
4225 hRet = VariantCopy(&varStr, pVarLeft);
4226 if (FAILED(hRet))
4227 goto VarOr_Exit;
4228 pVarLeft = &varStr;
4229 hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
4230 if (FAILED(hRet))
4231 goto VarOr_Exit;
4232 }
4233
4234 if (V_VT(pVarLeft) == VT_BOOL &&
4235 (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_BSTR))
4236 {
4237 vt = VT_BOOL;
4238 }
4239 else if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 ||
4240 V_VT(pVarLeft) == VT_I2 || V_VT(pVarLeft) == VT_BSTR) &&
4241 (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 ||
4242 V_VT(pVarRight) == VT_I2 || V_VT(pVarRight) == VT_BSTR))
4243 {
4244 vt = VT_I2;
4245 }
4246 else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8)
4247 {
4248 if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
4249 {
4250 hRet = DISP_E_TYPEMISMATCH;
4251 goto VarOr_Exit;
4252 }
4253 vt = VT_I8;
4254 }
4255
4256 hRet = VariantCopy(&varLeft, pVarLeft);
4257 if (FAILED(hRet))
4258 goto VarOr_Exit;
4259
4260 hRet = VariantCopy(&varRight, pVarRight);
4261 if (FAILED(hRet))
4262 goto VarOr_Exit;
4263
4264 if (vt == VT_I4 && V_VT(&varLeft) == VT_UI4)
4265 V_VT(&varLeft) = VT_I4; /* Don't overflow */
4266 else
4267 {
4268 double d;
4269
4270 if (V_VT(&varLeft) == VT_BSTR &&
4271 FAILED(VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d)))
4272 hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, VT_BOOL);
4273 if (SUCCEEDED(hRet) && V_VT(&varLeft) != vt)
4274 hRet = VariantChangeType(&varLeft, &varLeft, 0, vt);
4275 if (FAILED(hRet))
4276 goto VarOr_Exit;
4277 }
4278
4279 if (vt == VT_I4 && V_VT(&varRight) == VT_UI4)
4280 V_VT(&varRight) = VT_I4; /* Don't overflow */
4281 else
4282 {
4283 double d;
4284
4285 if (V_VT(&varRight) == VT_BSTR &&
4286 FAILED(VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d)))
4287 hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, VT_BOOL);
4288 if (SUCCEEDED(hRet) && V_VT(&varRight) != vt)
4289 hRet = VariantChangeType(&varRight, &varRight, 0, vt);
4290 if (FAILED(hRet))
4291 goto VarOr_Exit;
4292 }
4293
4294 V_VT(pVarOut) = vt;
4295 if (vt == VT_I8)
4296 {
4297 V_I8(pVarOut) = V_I8(&varLeft) | V_I8(&varRight);
4298 }
4299 else if (vt == VT_I4)
4300 {
4301 V_I4(pVarOut) = V_I4(&varLeft) | V_I4(&varRight);
4302 }
4303 else
4304 {
4305 V_I2(pVarOut) = V_I2(&varLeft) | V_I2(&varRight);
4306 }
4307
4308 VarOr_Exit:
4309 VariantClear(&varStr);
4310 VariantClear(&varLeft);
4311 VariantClear(&varRight);
4312 VariantClear(&tempLeft);
4313 VariantClear(&tempRight);
4314 return hRet;
4315 }
4316
4317 /**********************************************************************
4318 * VarAbs [OLEAUT32.168]
4319 *
4320 * Convert a variant to its absolute value.
4321 *
4322 * PARAMS
4323 * pVarIn [I] Source variant
4324 * pVarOut [O] Destination for converted value
4325 *
4326 * RETURNS
4327 * Success: S_OK. pVarOut contains the absolute value of pVarIn.
4328 * Failure: An HRESULT error code indicating the error.
4329 *
4330 * NOTES
4331 * - This function does not process by-reference variants.
4332 * - The type of the value stored in pVarOut depends on the type of pVarIn,
4333 * according to the following table:
4334 *| Input Type Output Type
4335 *| ---------- -----------
4336 *| VT_BOOL VT_I2
4337 *| VT_BSTR VT_R8
4338 *| (All others) Unchanged
4339 */
4340 HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut)
4341 {
4342 VARIANT varIn;
4343 HRESULT hRet = S_OK;
4344 VARIANT temp;
4345
4346 VariantInit(&temp);
4347
4348 TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
4349 debugstr_VF(pVarIn), pVarOut);
4350
4351 /* Handle VT_DISPATCH by storing and taking address of returned value */
4352 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
4353 {
4354 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
4355 if (FAILED(hRet)) goto VarAbs_Exit;
4356 pVarIn = &temp;
4357 }
4358
4359 if (V_ISARRAY(pVarIn) || V_VT(pVarIn) == VT_UNKNOWN ||
4360 V_VT(pVarIn) == VT_DISPATCH || V_VT(pVarIn) == VT_RECORD ||
4361 V_VT(pVarIn) == VT_ERROR)
4362 {
4363 hRet = DISP_E_TYPEMISMATCH;
4364 goto VarAbs_Exit;
4365 }
4366 *pVarOut = *pVarIn; /* Shallow copy the value, and invert it if needed */
4367
4368 #define ABS_CASE(typ,min) \
4369 case VT_##typ: if (V_##typ(pVarIn) == min) hRet = DISP_E_OVERFLOW; \
4370 else if (V_##typ(pVarIn) < 0) V_##typ(pVarOut) = -V_##typ(pVarIn); \
4371 break
4372
4373 switch (V_VT(pVarIn))
4374 {
4375 ABS_CASE(I1,I1_MIN);
4376 case VT_BOOL:
4377 V_VT(pVarOut) = VT_I2;
4378 /* BOOL->I2, Fall through ... */
4379 ABS_CASE(I2,I2_MIN);
4380 case VT_INT:
4381 ABS_CASE(I4,I4_MIN);
4382 ABS_CASE(I8,I8_MIN);
4383 ABS_CASE(R4,R4_MIN);
4384 case VT_BSTR:
4385 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
4386 if (FAILED(hRet))
4387 break;
4388 V_VT(pVarOut) = VT_R8;
4389 pVarIn = &varIn;
4390 /* Fall through ... */
4391 case VT_DATE:
4392 ABS_CASE(R8,R8_MIN);
4393 case VT_CY:
4394 hRet = VarCyAbs(V_CY(pVarIn), & V_CY(pVarOut));
4395 break;
4396 case VT_DECIMAL:
4397 DEC_SIGN(&V_DECIMAL(pVarOut)) &= ~DECIMAL_NEG;
4398 break;
4399 case VT_UI1:
4400 case VT_UI2:
4401 case VT_UINT:
4402 case VT_UI4:
4403 case VT_UI8:
4404 /* No-Op */
4405 break;
4406 case VT_EMPTY:
4407 V_VT(pVarOut) = VT_I2;
4408 case VT_NULL:
4409 V_I2(pVarOut) = 0;
4410 break;
4411 default:
4412 hRet = DISP_E_BADVARTYPE;
4413 }
4414
4415 VarAbs_Exit:
4416 VariantClear(&temp);
4417 return hRet;
4418 }
4419
4420 /**********************************************************************
4421 * VarFix [OLEAUT32.169]
4422 *
4423 * Truncate a variants value to a whole number.
4424 *
4425 * PARAMS
4426 * pVarIn [I] Source variant
4427 * pVarOut [O] Destination for converted value
4428 *
4429 * RETURNS
4430 * Success: S_OK. pVarOut contains the converted value.
4431 * Failure: An HRESULT error code indicating the error.
4432 *
4433 * NOTES
4434 * - The type of the value stored in pVarOut depends on the type of pVarIn,
4435 * according to the following table:
4436 *| Input Type Output Type
4437 *| ---------- -----------
4438 *| VT_BOOL VT_I2
4439 *| VT_EMPTY VT_I2
4440 *| VT_BSTR VT_R8
4441 *| All Others Unchanged
4442 * - The difference between this function and VarInt() is that VarInt() rounds
4443 * negative numbers away from 0, while this function rounds them towards zero.
4444 */
4445 HRESULT WINAPI VarFix(LPVARIANT pVarIn, LPVARIANT pVarOut)
4446 {
4447 HRESULT hRet = S_OK;
4448 VARIANT temp;
4449
4450 VariantInit(&temp);
4451
4452 TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
4453 debugstr_VF(pVarIn), pVarOut);
4454
4455 /* Handle VT_DISPATCH by storing and taking address of returned value */
4456 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
4457 {
4458 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
4459 if (FAILED(hRet)) goto VarFix_Exit;
4460 pVarIn = &temp;
4461 }
4462 V_VT(pVarOut) = V_VT(pVarIn);
4463
4464 switch (V_VT(pVarIn))
4465 {
4466 case VT_UI1:
4467 V_UI1(pVarOut) = V_UI1(pVarIn);
4468 break;
4469 case VT_BOOL:
4470 V_VT(pVarOut) = VT_I2;
4471 /* Fall through */
4472 case VT_I2:
4473 V_I2(pVarOut) = V_I2(pVarIn);
4474 break;
4475 case VT_I4:
4476 V_I4(pVarOut) = V_I4(pVarIn);
4477 break;
4478 case VT_I8:
4479 V_I8(pVarOut) = V_I8(pVarIn);
4480 break;
4481 case VT_R4:
4482 if (V_R4(pVarIn) < 0.0f)
4483 V_R4(pVarOut) = (float)ceil(V_R4(pVarIn));
4484 else
4485 V_R4(pVarOut) = (float)floor(V_R4(pVarIn));
4486 break;
4487 case VT_BSTR:
4488 V_VT(pVarOut) = VT_R8;
4489 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
4490 pVarIn = pVarOut;
4491 /* Fall through */
4492 case VT_DATE:
4493 case VT_R8:
4494 if (V_R8(pVarIn) < 0.0)
4495 V_R8(pVarOut) = ceil(V_R8(pVarIn));
4496 else
4497 V_R8(pVarOut) = floor(V_R8(pVarIn));
4498 break;
4499 case VT_CY:
4500 hRet = VarCyFix(V_CY(pVarIn), &V_CY(pVarOut));
4501 break;
4502 case VT_DECIMAL:
4503 hRet = VarDecFix(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
4504 break;
4505 case VT_EMPTY:
4506 V_VT(pVarOut) = VT_I2;
4507 V_I2(pVarOut) = 0;
4508 break;
4509 case VT_NULL:
4510 /* No-Op */
4511 break;
4512 default:
4513 if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
4514 FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
4515 hRet = DISP_E_BADVARTYPE;
4516 else
4517 hRet = DISP_E_TYPEMISMATCH;
4518 }
4519 VarFix_Exit:
4520 if (FAILED(hRet))
4521 V_VT(pVarOut) = VT_EMPTY;
4522 VariantClear(&temp);
4523
4524 return hRet;
4525 }
4526
4527 /**********************************************************************
4528 * VarInt [OLEAUT32.172]
4529 *
4530 * Truncate a variants value to a whole number.
4531 *
4532 * PARAMS
4533 * pVarIn [I] Source variant
4534 * pVarOut [O] Destination for converted value
4535 *
4536 * RETURNS
4537 * Success: S_OK. pVarOut contains the converted value.
4538 * Failure: An HRESULT error code indicating the error.
4539 *
4540 * NOTES
4541 * - The type of the value stored in pVarOut depends on the type of pVarIn,
4542 * according to the following table:
4543 *| Input Type Output Type
4544 *| ---------- -----------
4545 *| VT_BOOL VT_I2
4546 *| VT_EMPTY VT_I2
4547 *| VT_BSTR VT_R8
4548 *| All Others Unchanged
4549 * - The difference between this function and VarFix() is that VarFix() rounds
4550 * negative numbers towards 0, while this function rounds them away from zero.
4551 */
4552 HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut)
4553 {
4554 HRESULT hRet = S_OK;
4555 VARIANT temp;
4556
4557 VariantInit(&temp);
4558
4559 TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
4560 debugstr_VF(pVarIn), pVarOut);
4561
4562 /* Handle VT_DISPATCH by storing and taking address of returned value */
4563 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
4564 {
4565 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
4566 if (FAILED(hRet)) goto VarInt_Exit;
4567 pVarIn = &temp;
4568 }
4569 V_VT(pVarOut) = V_VT(pVarIn);
4570
4571 switch (V_VT(pVarIn))
4572 {
4573 case VT_R4:
4574 V_R4(pVarOut) = (float)floor(V_R4(pVarIn));
4575 break;
4576 case VT_BSTR:
4577 V_VT(pVarOut) = VT_R8;
4578 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
4579 pVarIn = pVarOut;
4580 /* Fall through */
4581 case VT_DATE:
4582 case VT_R8:
4583 V_R8(pVarOut) = floor(V_R8(pVarIn));
4584 break;
4585 case VT_CY:
4586 hRet = VarCyInt(V_CY(pVarIn), &V_CY(pVarOut));
4587 break;
4588 case VT_DECIMAL:
4589 hRet = VarDecInt(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
4590 break;
4591 default:
4592 hRet = VarFix(pVarIn, pVarOut);
4593 }
4594 VarInt_Exit:
4595 VariantClear(&temp);
4596
4597 return hRet;
4598 }
4599
4600 /**********************************************************************
4601 * VarXor [OLEAUT32.167]
4602 *
4603 * Perform a logical exclusive-or (XOR) operation on two variants.
4604 *
4605 * PARAMS
4606 * pVarLeft [I] First variant
4607 * pVarRight [I] Variant to XOR with pVarLeft
4608 * pVarOut [O] Destination for XOR result
4609 *
4610 * RETURNS
4611 * Success: S_OK. pVarOut contains the result of the operation with its type
4612 * taken from the table below).
4613 * Failure: An HRESULT error code indicating the error.
4614 *
4615 * NOTES
4616 * - Neither pVarLeft or pVarRight are modified by this function.
4617 * - This function does not process by-reference variants.
4618 * - Input types of VT_BSTR may be numeric strings or boolean text.
4619 * - The type of result stored in pVarOut depends on the types of pVarLeft
4620 * and pVarRight, and will be one of VT_UI1, VT_I2, VT_I4, VT_I8, VT_BOOL,
4621 * or VT_NULL if the function succeeds.
4622 * - Type promotion is inconsistent and as a result certain combinations of
4623 * values will return DISP_E_OVERFLOW even when they could be represented.
4624 * This matches the behaviour of native oleaut32.
4625 */
4626 HRESULT WINAPI VarXor(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
4627 {
4628 VARTYPE vt;
4629 VARIANT varLeft, varRight;
4630 VARIANT tempLeft, tempRight;
4631 double d;
4632 HRESULT hRet;
4633
4634 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
4635 debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
4636 debugstr_VF(pVarRight), pVarOut);
4637
4638 if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
4639 V_VT(pVarLeft) > VT_UINT || V_VT(pVarRight) > VT_UINT ||
4640 V_VT(pVarLeft) == VT_VARIANT || V_VT(pVarRight) == VT_VARIANT ||
4641 V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
4642 V_VT(pVarLeft) == (VARTYPE)15 || V_VT(pVarRight) == (VARTYPE)15 ||
4643 V_VT(pVarLeft) == VT_ERROR || V_VT(pVarRight) == VT_ERROR)
4644 return DISP_E_BADVARTYPE;
4645
4646 if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
4647 {
4648 /* NULL XOR anything valid is NULL */
4649 V_VT(pVarOut) = VT_NULL;
4650 return S_OK;
4651 }
4652
4653 VariantInit(&tempLeft);
4654 VariantInit(&tempRight);
4655
4656 /* Handle VT_DISPATCH by storing and taking address of returned value */
4657 if ((V_VT(pVarLeft) & VT_TYPEMASK) == VT_DISPATCH)
4658 {
4659 hRet = VARIANT_FetchDispatchValue(pVarLeft, &tempLeft);
4660 if (FAILED(hRet)) goto VarXor_Exit;
4661 pVarLeft = &tempLeft;
4662 }
4663 if ((V_VT(pVarRight) & VT_TYPEMASK) == VT_DISPATCH)
4664 {
4665 hRet = VARIANT_FetchDispatchValue(pVarRight, &tempRight);
4666 if (FAILED(hRet)) goto VarXor_Exit;
4667 pVarRight = &tempRight;
4668 }
4669
4670 /* Copy our inputs so we don't disturb anything */
4671 V_VT(&varLeft) = V_VT(&varRight) = VT_EMPTY;
4672
4673 hRet = VariantCopy(&varLeft, pVarLeft);
4674 if (FAILED(hRet))
4675 goto VarXor_Exit;
4676
4677 hRet = VariantCopy(&varRight, pVarRight);
4678 if (FAILED(hRet))
4679 goto VarXor_Exit;
4680
4681 /* Try any strings first as numbers, then as VT_BOOL */
4682 if (V_VT(&varLeft) == VT_BSTR)
4683 {
4684 hRet = VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d);
4685 hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL,
4686 FAILED(hRet) ? VT_BOOL : VT_I4);
4687 if (FAILED(hRet))
4688 goto VarXor_Exit;
4689 }
4690
4691 if (V_VT(&varRight) == VT_BSTR)
4692 {
4693 hRet = VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d);
4694 hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL,
4695 FAILED(hRet) ? VT_BOOL : VT_I4);
4696 if (FAILED(hRet))
4697 goto VarXor_Exit;
4698 }
4699
4700 /* Determine the result type */
4701 if (V_VT(&varLeft) == VT_I8 || V_VT(&varRight) == VT_I8)
4702 {
4703 if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
4704 {
4705 hRet = DISP_E_TYPEMISMATCH;
4706 goto VarXor_Exit;
4707 }
4708 vt = VT_I8;
4709 }
4710 else
4711 {
4712 switch ((V_VT(&varLeft) << 16) | V_VT(&varRight))
4713 {
4714 case (VT_BOOL << 16) | VT_BOOL:
4715 vt = VT_BOOL;
4716 break;
4717 case (VT_UI1 << 16) | VT_UI1:
4718 vt = VT_UI1;
4719 break;
4720 case (VT_EMPTY << 16) | VT_EMPTY:
4721 case (VT_EMPTY << 16) | VT_UI1:
4722 case (VT_EMPTY << 16) | VT_I2:
4723 case (VT_EMPTY << 16) | VT_BOOL:
4724 case (VT_UI1 << 16) | VT_EMPTY:
4725 case (VT_UI1 << 16) | VT_I2:
4726 case (VT_UI1 << 16) | VT_BOOL:
4727 case (VT_I2 << 16) | VT_EMPTY:
4728 case (VT_I2 << 16) | VT_UI1:
4729 case (VT_I2 << 16) | VT_I2:
4730 case (VT_I2 << 16) | VT_BOOL:
4731 case (VT_BOOL << 16) | VT_EMPTY:
4732 case (VT_BOOL << 16) | VT_UI1:
4733 case (VT_BOOL << 16) | VT_I2:
4734 vt = VT_I2;
4735 break;
4736 default:
4737 vt = VT_I4;
4738 break;
4739 }
4740 }
4741
4742 /* VT_UI4 does not overflow */
4743 if (vt != VT_I8)
4744 {
4745 if (V_VT(&varLeft) == VT_UI4)
4746 V_VT(&varLeft) = VT_I4;
4747 if (V_VT(&varRight) == VT_UI4)
4748 V_VT(&varRight) = VT_I4;
4749 }
4750
4751 /* Convert our input copies to the result type */
4752 if (V_VT(&varLeft) != vt)
4753 hRet = VariantChangeType(&varLeft, &varLeft, 0, vt);
4754 if (FAILED(hRet))
4755 goto VarXor_Exit;
4756
4757 if (V_VT(&varRight) != vt)
4758 hRet = VariantChangeType(&varRight, &varRight, 0, vt);
4759 if (FAILED(hRet))
4760 goto VarXor_Exit;
4761
4762 V_VT(pVarOut) = vt;
4763
4764 /* Calculate the result */
4765 switch (vt)
4766 {
4767 case VT_I8:
4768 V_I8(pVarOut) = V_I8(&varLeft) ^ V_I8(&varRight);
4769 break;
4770 case VT_I4:
4771 V_I4(pVarOut) = V_I4(&varLeft) ^ V_I4(&varRight);
4772 break;
4773 case VT_BOOL:
4774 case VT_I2:
4775 V_I2(pVarOut) = V_I2(&varLeft) ^ V_I2(&varRight);
4776 break;
4777 case VT_UI1:
4778 V_UI1(pVarOut) = V_UI1(&varLeft) ^ V_UI1(&varRight);
4779 break;
4780 }
4781
4782 VarXor_Exit:
4783 VariantClear(&varLeft);
4784 VariantClear(&varRight);
4785 VariantClear(&tempLeft);
4786 VariantClear(&tempRight);
4787 return hRet;
4788 }
4789
4790 /**********************************************************************
4791 * VarEqv [OLEAUT32.172]
4792 *
4793 * Determine if two variants contain the same value.
4794 *
4795 * PARAMS
4796 * pVarLeft [I] First variant to compare
4797 * pVarRight [I] Variant to compare to pVarLeft
4798 * pVarOut [O] Destination for comparison result
4799 *
4800 * RETURNS
4801 * Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE
4802 * if equivalent or non-zero otherwise.
4803 * Failure: An HRESULT error code indicating the error.
4804 *
4805 * NOTES
4806 * - This function simply calls VarXor() on pVarLeft and pVarRight and inverts
4807 * the result.
4808 */
4809 HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
4810 {
4811 HRESULT hRet;
4812
4813 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
4814 debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
4815 debugstr_VF(pVarRight), pVarOut);
4816
4817 hRet = VarXor(pVarLeft, pVarRight, pVarOut);
4818 if (SUCCEEDED(hRet))
4819 {
4820 if (V_VT(pVarOut) == VT_I8)
4821 V_I8(pVarOut) = ~V_I8(pVarOut);
4822 else
4823 V_UI4(pVarOut) = ~V_UI4(pVarOut);
4824 }
4825 return hRet;
4826 }
4827
4828 /**********************************************************************
4829 * VarNeg [OLEAUT32.173]
4830 *
4831 * Negate the value of a variant.
4832 *
4833 * PARAMS
4834 * pVarIn [I] Source variant
4835 * pVarOut [O] Destination for converted value
4836 *
4837 * RETURNS
4838 * Success: S_OK. pVarOut contains the converted value.
4839 * Failure: An HRESULT error code indicating the error.
4840 *
4841 * NOTES
4842 * - The type of the value stored in pVarOut depends on the type of pVarIn,
4843 * according to the following table:
4844 *| Input Type Output Type
4845 *| ---------- -----------
4846 *| VT_EMPTY VT_I2
4847 *| VT_UI1 VT_I2
4848 *| VT_BOOL VT_I2
4849 *| VT_BSTR VT_R8
4850 *| All Others Unchanged (unless promoted)
4851 * - Where the negated value of a variant does not fit in its base type, the type
4852 * is promoted according to the following table:
4853 *| Input Type Promoted To
4854 *| ---------- -----------
4855 *| VT_I2 VT_I4
4856 *| VT_I4 VT_R8
4857 *| VT_I8 VT_R8
4858 * - The native version of this function returns DISP_E_BADVARTYPE for valid
4859 * variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH
4860 * for types which are not valid. Since this is in contravention of the
4861 * meaning of those error codes and unlikely to be relied on by applications,
4862 * this implementation returns errors consistent with the other high level
4863 * variant math functions.
4864 */
4865 HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut)
4866 {
4867 HRESULT hRet = S_OK;
4868 VARIANT temp;
4869
4870 VariantInit(&temp);
4871
4872 TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
4873 debugstr_VF(pVarIn), pVarOut);
4874
4875 /* Handle VT_DISPATCH by storing and taking address of returned value */
4876 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
4877 {
4878 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
4879 if (FAILED(hRet)) goto VarNeg_Exit;
4880 pVarIn = &temp;
4881 }
4882 V_VT(pVarOut) = V_VT(pVarIn);
4883
4884 switch (V_VT(pVarIn))
4885 {
4886 case VT_UI1:
4887 V_VT(pVarOut) = VT_I2;
4888 V_I2(pVarOut) = -V_UI1(pVarIn);
4889 break;
4890 case VT_BOOL:
4891 V_VT(pVarOut) = VT_I2;
4892 /* Fall through */
4893 case VT_I2:
4894 if (V_I2(pVarIn) == I2_MIN)
4895 {
4896 V_VT(pVarOut) = VT_I4;
4897 V_I4(pVarOut) = -(int)V_I2(pVarIn);
4898 }
4899 else
4900 V_I2(pVarOut) = -V_I2(pVarIn);
4901 break;
4902 case VT_I4:
4903 if (V_I4(pVarIn) == I4_MIN)
4904 {
4905 V_VT(pVarOut) = VT_R8;
4906 V_R8(pVarOut) = -(double)V_I4(pVarIn);
4907 }
4908 else
4909 V_I4(pVarOut) = -V_I4(pVarIn);
4910 break;
4911 case VT_I8:
4912 if (V_I8(pVarIn) == I8_MIN)
4913 {
4914 V_VT(pVarOut) = VT_R8;
4915 hRet = VarR8FromI8(V_I8(pVarIn), &V_R8(pVarOut));
4916 V_R8(pVarOut) *= -1.0;
4917 }
4918 else
4919 V_I8(pVarOut) = -V_I8(pVarIn);
4920 break;
4921 case VT_R4:
4922 V_R4(pVarOut) = -V_R4(pVarIn);
4923 break;
4924 case VT_DATE:
4925 case VT_R8:
4926 V_R8(pVarOut) = -V_R8(pVarIn);
4927 break;
4928 case VT_CY:
4929 hRet = VarCyNeg(V_CY(pVarIn), &V_CY(pVarOut));
4930 break;
4931 case VT_DECIMAL:
4932 hRet = VarDecNeg(&V_DECIMAL(pVarIn), &V_DECIMAL(pVarOut));
4933 break;
4934 case VT_BSTR:
4935 V_VT(pVarOut) = VT_R8;
4936 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(pVarOut));
4937 V_R8(pVarOut) = -V_R8(pVarOut);
4938 break;
4939 case VT_EMPTY:
4940 V_VT(pVarOut) = VT_I2;
4941 V_I2(pVarOut) = 0;
4942 break;
4943 case VT_NULL:
4944 /* No-Op */
4945 break;
4946 default:
4947 if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
4948 FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
4949 hRet = DISP_E_BADVARTYPE;
4950 else
4951 hRet = DISP_E_TYPEMISMATCH;
4952 }
4953 VarNeg_Exit:
4954 if (FAILED(hRet))
4955 V_VT(pVarOut) = VT_EMPTY;
4956 VariantClear(&temp);
4957
4958 return hRet;
4959 }
4960
4961 /**********************************************************************
4962 * VarNot [OLEAUT32.174]
4963 *
4964 * Perform a not operation on a variant.
4965 *
4966 * PARAMS
4967 * pVarIn [I] Source variant
4968 * pVarOut [O] Destination for converted value
4969 *
4970 * RETURNS
4971 * Success: S_OK. pVarOut contains the converted value.
4972 * Failure: An HRESULT error code indicating the error.
4973 *
4974 * NOTES
4975 * - Strictly speaking, this function performs a bitwise ones complement
4976 * on the variants value (after possibly converting to VT_I4, see below).
4977 * This only behaves like a boolean not operation if the value in
4978 * pVarIn is either VARIANT_TRUE or VARIANT_FALSE and the type is signed.
4979 * - To perform a genuine not operation, convert the variant to a VT_BOOL
4980 * before calling this function.
4981 * - This function does not process by-reference variants.
4982 * - The type of the value stored in pVarOut depends on the type of pVarIn,
4983 * according to the following table:
4984 *| Input Type Output Type
4985 *| ---------- -----------
4986 *| VT_EMPTY VT_I2
4987 *| VT_R4 VT_I4
4988 *| VT_R8 VT_I4
4989 *| VT_BSTR VT_I4
4990 *| VT_DECIMAL VT_I4
4991 *| VT_CY VT_I4
4992 *| (All others) Unchanged
4993 */
4994 HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut)
4995 {
4996 VARIANT varIn;
4997 HRESULT hRet = S_OK;
4998 VARIANT temp;
4999
5000 VariantInit(&temp);
5001
5002 TRACE("(%p->(%s%s),%p)\n", pVarIn, debugstr_VT(pVarIn),
5003 debugstr_VF(pVarIn), pVarOut);
5004
5005 /* Handle VT_DISPATCH by storing and taking address of returned value */
5006 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
5007 {
5008 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
5009 if (FAILED(hRet)) goto VarNot_Exit;
5010 pVarIn = &temp;
5011 }
5012
5013 if (V_VT(pVarIn) == VT_BSTR)
5014 {
5015 V_VT(&varIn) = VT_R8;
5016 hRet = VarR8FromStr( V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn) );
5017 if (FAILED(hRet))
5018 {
5019 V_VT(&varIn) = VT_BOOL;
5020 hRet = VarBoolFromStr( V_BSTR(pVarIn), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &V_BOOL(&varIn) );
5021 }
5022 if (FAILED(hRet)) goto VarNot_Exit;
5023 pVarIn = &varIn;
5024 }
5025
5026 V_VT(pVarOut) = V_VT(pVarIn);
5027
5028 switch (V_VT(pVarIn))
5029 {
5030 case VT_I1:
5031 V_I4(pVarOut) = ~V_I1(pVarIn);
5032 V_VT(pVarOut) = VT_I4;
5033 break;
5034 case VT_UI1: V_UI1(pVarOut) = ~V_UI1(pVarIn); break;
5035 case VT_BOOL:
5036 case VT_I2: V_I2(pVarOut) = ~V_I2(pVarIn); break;
5037 case VT_UI2:
5038 V_I4(pVarOut) = ~V_UI2(pVarIn);
5039 V_VT(pVarOut) = VT_I4;
5040 break;
5041 case VT_DECIMAL:
5042 hRet = VarI4FromDec(&V_DECIMAL(pVarIn), &V_I4(&varIn));
5043 if (FAILED(hRet))
5044 break;
5045 pVarIn = &varIn;
5046 /* Fall through ... */
5047 case VT_INT:
5048 V_VT(pVarOut) = VT_I4;
5049 /* Fall through ... */
5050 case VT_I4: V_I4(pVarOut) = ~V_I4(pVarIn); break;
5051 case VT_UINT:
5052 case VT_UI4:
5053 V_I4(pVarOut) = ~V_UI4(pVarIn);
5054 V_VT(pVarOut) = VT_I4;
5055 break;
5056 case VT_I8: V_I8(pVarOut) = ~V_I8(pVarIn); break;
5057 case VT_UI8:
5058 V_I4(pVarOut) = ~V_UI8(pVarIn);
5059 V_VT(pVarOut) = VT_I4;
5060 break;
5061 case VT_R4:
5062 hRet = VarI4FromR4(V_R4(pVarIn), &V_I4(pVarOut));
5063 V_I4(pVarOut) = ~V_I4(pVarOut);
5064 V_VT(pVarOut) = VT_I4;
5065 break;
5066 case VT_DATE:
5067 case VT_R8:
5068 hRet = VarI4FromR8(V_R8(pVarIn), &V_I4(pVarOut));
5069 V_I4(pVarOut) = ~V_I4(pVarOut);
5070 V_VT(pVarOut) = VT_I4;
5071 break;
5072 case VT_CY:
5073 hRet = VarI4FromCy(V_CY(pVarIn), &V_I4(pVarOut));
5074 V_I4(pVarOut) = ~V_I4(pVarOut);
5075 V_VT(pVarOut) = VT_I4;
5076 break;
5077 case VT_EMPTY:
5078 V_I2(pVarOut) = ~0;
5079 V_VT(pVarOut) = VT_I2;
5080 break;
5081 case VT_NULL:
5082 /* No-Op */
5083 break;
5084 default:
5085 if (V_TYPE(pVarIn) == VT_CLSID || /* VT_CLSID is a special case */
5086 FAILED(VARIANT_ValidateType(V_VT(pVarIn))))
5087 hRet = DISP_E_BADVARTYPE;
5088 else
5089 hRet = DISP_E_TYPEMISMATCH;
5090 }
5091 VarNot_Exit:
5092 if (FAILED(hRet))
5093 V_VT(pVarOut) = VT_EMPTY;
5094 VariantClear(&temp);
5095
5096 return hRet;
5097 }
5098
5099 /**********************************************************************
5100 * VarRound [OLEAUT32.175]
5101 *
5102 * Perform a round operation on a variant.
5103 *
5104 * PARAMS
5105 * pVarIn [I] Source variant
5106 * deci [I] Number of decimals to round to
5107 * pVarOut [O] Destination for converted value
5108 *
5109 * RETURNS
5110 * Success: S_OK. pVarOut contains the converted value.
5111 * Failure: An HRESULT error code indicating the error.
5112 *
5113 * NOTES
5114 * - Floating point values are rounded to the desired number of decimals.
5115 * - Some integer types are just copied to the return variable.
5116 * - Some other integer types are not handled and fail.
5117 */
5118 HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut)
5119 {
5120 VARIANT varIn;
5121 HRESULT hRet = S_OK;
5122 float factor;
5123 VARIANT temp;
5124
5125 VariantInit(&temp);
5126
5127 TRACE("(%p->(%s%s),%d)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), deci);
5128
5129 /* Handle VT_DISPATCH by storing and taking address of returned value */
5130 if ((V_VT(pVarIn) & VT_TYPEMASK) == VT_DISPATCH && ((V_VT(pVarIn) & ~VT_TYPEMASK) == 0))
5131 {
5132 hRet = VARIANT_FetchDispatchValue(pVarIn, &temp);
5133 if (FAILED(hRet)) goto VarRound_Exit;
5134 pVarIn = &temp;
5135 }
5136
5137 switch (V_VT(pVarIn))
5138 {
5139 /* cases that fail on windows */
5140 case VT_I1:
5141 case VT_I8:
5142 case VT_UI2:
5143 case VT_UI4:
5144 hRet = DISP_E_BADVARTYPE;
5145 break;
5146
5147 /* cases just copying in to out */
5148 case VT_UI1:
5149 V_VT(pVarOut) = V_VT(pVarIn);
5150 V_UI1(pVarOut) = V_UI1(pVarIn);
5151 break;
5152 case VT_I2:
5153 V_VT(pVarOut) = V_VT(pVarIn);
5154 V_I2(pVarOut) = V_I2(pVarIn);
5155 break;
5156 case VT_I4:
5157 V_VT(pVarOut) = V_VT(pVarIn);
5158 V_I4(pVarOut) = V_I4(pVarIn);
5159 break;
5160 case VT_NULL:
5161 V_VT(pVarOut) = V_VT(pVarIn);
5162 /* value unchanged */
5163 break;
5164
5165 /* cases that change type */
5166 case VT_EMPTY:
5167 V_VT(pVarOut) = VT_I2;
5168 V_I2(pVarOut) = 0;
5169 break;
5170 case VT_BOOL:
5171 V_VT(pVarOut) = VT_I2;
5172 V_I2(pVarOut) = V_BOOL(pVarIn);
5173 break;
5174 case VT_BSTR:
5175 hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
5176 if (FAILED(hRet))
5177 break;
5178 V_VT(&varIn)=VT_R8;
5179 pVarIn = &varIn;
5180 /* Fall through ... */
5181
5182 /* cases we need to do math */
5183 case VT_R8:
5184 if (V_R8(pVarIn)>0) {
5185 V_R8(pVarOut)=floor(V_R8(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
5186 } else {
5187 V_R8(pVarOut)=ceil(V_R8(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
5188 }
5189 V_VT(pVarOut) = V_VT(pVarIn);
5190 break;
5191 case VT_R4:
5192 if (V_R4(pVarIn)>0) {
5193 V_R4(pVarOut)=floor(V_R4(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
5194 } else {
5195 V_R4(pVarOut)=ceil(V_R4(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
5196 }
5197 V_VT(pVarOut) = V_VT(pVarIn);
5198 break;
5199 case VT_DATE:
5200 if (V_DATE(pVarIn)>0) {
5201 V_DATE(pVarOut)=floor(V_DATE(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
5202 } else {
5203 V_DATE(pVarOut)=ceil(V_DATE(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
5204 }
5205 V_VT(pVarOut) = V_VT(pVarIn);
5206 break;
5207 case VT_CY:
5208 if (deci>3)
5209 factor=1;
5210 else
5211 factor=pow(10, 4-deci);
5212
5213 if (V_CY(pVarIn).int64>0) {
5214 V_CY(pVarOut).int64=floor(V_CY(pVarIn).int64/factor)*factor;
5215 } else {
5216 V_CY(pVarOut).int64=ceil(V_CY(pVarIn).int64/factor)*factor;
5217 }
5218 V_VT(pVarOut) = V_VT(pVarIn);
5219 break;
5220
5221 /* cases we don't know yet */
5222 default:
5223 FIXME("unimplemented part, V_VT(pVarIn) == 0x%X, deci == %d\n",
5224 V_VT(pVarIn) & VT_TYPEMASK, deci);
5225 hRet = DISP_E_BADVARTYPE;
5226 }
5227 VarRound_Exit:
5228 if (FAILED(hRet))
5229 V_VT(pVarOut) = VT_EMPTY;
5230 VariantClear(&temp);
5231
5232 TRACE("returning 0x%08x (%s%s),%f\n", hRet, debugstr_VT(pVarOut),
5233 debugstr_VF(pVarOut), (V_VT(pVarOut) == VT_R4) ? V_R4(pVarOut) :
5234 (V_VT(pVarOut) == VT_R8) ? V_R8(pVarOut) : 0);
5235
5236 return hRet;
5237 }
5238
5239 /**********************************************************************
5240 * VarIdiv [OLEAUT32.153]
5241 *
5242 * Converts input variants to integers and divides them.
5243 *
5244 * PARAMS
5245 * left [I] Left hand variant
5246 * right [I] Right hand variant
5247 * result [O] Destination for quotient
5248 *
5249 * RETURNS
5250 * Success: S_OK. result contains the quotient.
5251 * Failure: An HRESULT error code indicating the error.
5252 *
5253 * NOTES
5254 * If either expression is null, null is returned, as per MSDN
5255 */
5256 HRESULT WINAPI VarIdiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
5257 {
5258 HRESULT hres = S_OK;
5259 VARTYPE resvt = VT_EMPTY;
5260 VARTYPE leftvt,rightvt;
5261 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
5262 VARIANT lv,rv;
5263 VARIANT tempLeft, tempRight;
5264
5265 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
5266 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
5267
5268 VariantInit(&lv);
5269 VariantInit(&rv);
5270 VariantInit(&tempLeft);
5271 VariantInit(&tempRight);
5272
5273 leftvt = V_VT(left)&VT_TYPEMASK;
5274 rightvt = V_VT(right)&VT_TYPEMASK;
5275 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
5276 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
5277
5278 if (leftExtraFlags != rightExtraFlags)
5279 {
5280 hres = DISP_E_BADVARTYPE;
5281 goto end;
5282 }
5283 ExtraFlags = leftExtraFlags;
5284
5285 /* Native VarIdiv always returns an error when using extra
5286 * flags or if the variant combination is I8 and INT.
5287 */
5288 if ((leftvt == VT_I8 && rightvt == VT_INT) ||
5289 (leftvt == VT_INT && rightvt == VT_I8) ||
5290 (rightvt == VT_EMPTY && leftvt != VT_NULL) ||
5291 ExtraFlags != 0)
5292 {
5293 hres = DISP_E_BADVARTYPE;
5294 goto end;
5295 }
5296
5297 /* Determine variant type */
5298 else if (leftvt == VT_NULL || rightvt == VT_NULL)
5299 {
5300 V_VT(result) = VT_NULL;
5301 hres = S_OK;
5302 goto end;
5303 }
5304 else if (leftvt == VT_I8 || rightvt == VT_I8)
5305 resvt = VT_I8;
5306 else if (leftvt == VT_I4 || rightvt == VT_I4 ||
5307 leftvt == VT_INT || rightvt == VT_INT ||
5308 leftvt == VT_UINT || rightvt == VT_UINT ||
5309 leftvt == VT_UI8 || rightvt == VT_UI8 ||
5310 leftvt == VT_UI4 || rightvt == VT_UI4 ||
5311 leftvt == VT_UI2 || rightvt == VT_UI2 ||
5312 leftvt == VT_I1 || rightvt == VT_I1 ||
5313 leftvt == VT_BSTR || rightvt == VT_BSTR ||
5314 leftvt == VT_DATE || rightvt == VT_DATE ||
5315 leftvt == VT_CY || rightvt == VT_CY ||
5316 leftvt == VT_DECIMAL || rightvt == VT_DECIMAL ||
5317 leftvt == VT_R8 || rightvt == VT_R8 ||
5318 leftvt == VT_R4 || rightvt == VT_R4)
5319 resvt = VT_I4;
5320 else if (leftvt == VT_I2 || rightvt == VT_I2 ||
5321 leftvt == VT_BOOL || rightvt == VT_BOOL ||
5322 leftvt == VT_EMPTY)
5323 resvt = VT_I2;
5324 else if (leftvt == VT_UI1 || rightvt == VT_UI1)
5325 resvt = VT_UI1;
5326 else
5327 {
5328 hres = DISP_E_BADVARTYPE;
5329 goto end;
5330 }
5331
5332 /* coerce to the result type */
5333 hres = VariantChangeType(&lv, left, 0, resvt);
5334 if (hres != S_OK) goto end;
5335 hres = VariantChangeType(&rv, right, 0, resvt);
5336 if (hres != S_OK) goto end;
5337
5338 /* do the math */
5339 V_VT(result) = resvt;
5340 switch (resvt)
5341 {
5342 case VT_UI1:
5343 if (V_UI1(&rv) == 0)
5344 {
5345 hres = DISP_E_DIVBYZERO;
5346 V_VT(result) = VT_EMPTY;
5347 }
5348 else
5349 V_UI1(result) = V_UI1(&lv) / V_UI1(&rv);
5350 break;
5351 case VT_I2:
5352 if (V_I2(&rv) == 0)
5353 {
5354 hres = DISP_E_DIVBYZERO;
5355 V_VT(result) = VT_EMPTY;
5356 }
5357 else
5358 V_I2(result) = V_I2(&lv) / V_I2(&rv);
5359 break;
5360 case VT_I4:
5361 if (V_I4(&rv) == 0)
5362 {
5363 hres = DISP_E_DIVBYZERO;
5364 V_VT(result) = VT_EMPTY;
5365 }
5366 else
5367 V_I4(result) = V_I4(&lv) / V_I4(&rv);
5368 break;
5369 case VT_I8:
5370 if (V_I8(&rv) == 0)
5371 {
5372 hres = DISP_E_DIVBYZERO;
5373 V_VT(result) = VT_EMPTY;
5374 }
5375 else
5376 V_I8(result) = V_I8(&lv) / V_I8(&rv);
5377 break;
5378 default:
5379 FIXME("Couldn't integer divide variant types %d,%d\n",
5380 leftvt,rightvt);
5381 }
5382
5383 end:
5384 VariantClear(&lv);
5385 VariantClear(&rv);
5386 VariantClear(&tempLeft);
5387 VariantClear(&tempRight);
5388
5389 return hres;
5390 }
5391
5392
5393 /**********************************************************************
5394 * VarMod [OLEAUT32.155]
5395 *
5396 * Perform the modulus operation of the right hand variant on the left
5397 *
5398 * PARAMS
5399 * left [I] Left hand variant
5400 * right [I] Right hand variant
5401 * result [O] Destination for converted value
5402 *
5403 * RETURNS
5404 * Success: S_OK. result contains the remainder.
5405 * Failure: An HRESULT error code indicating the error.
5406 *
5407 * NOTE:
5408 * If an error occurs the type of result will be modified but the value will not be.
5409 * Doesn't support arrays or any special flags yet.
5410 */
5411 HRESULT WINAPI VarMod(LPVARIANT left, LPVARIANT right, LPVARIANT result)
5412 {
5413 BOOL lOk = TRUE;
5414 HRESULT rc = E_FAIL;
5415 int resT = 0;
5416 VARIANT lv,rv;
5417 VARIANT tempLeft, tempRight;
5418
5419 VariantInit(&tempLeft);
5420 VariantInit(&tempRight);
5421 VariantInit(&lv);
5422 VariantInit(&rv);
5423
5424 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
5425 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
5426
5427 /* Handle VT_DISPATCH by storing and taking address of returned value */
5428 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
5429 {
5430 rc = VARIANT_FetchDispatchValue(left, &tempLeft);
5431 if (FAILED(rc)) goto end;
5432 left = &tempLeft;
5433 }
5434 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
5435 {
5436 rc = VARIANT_FetchDispatchValue(right, &tempRight);
5437 if (FAILED(rc)) goto end;
5438 right = &tempRight;
5439 }
5440
5441 /* check for invalid inputs */
5442 lOk = TRUE;
5443 switch (V_VT(left) & VT_TYPEMASK) {
5444 case VT_BOOL :
5445 case VT_I1 :
5446 case VT_I2 :
5447 case VT_I4 :
5448 case VT_I8 :
5449 case VT_INT :
5450 case VT_UI1 :
5451 case VT_UI2 :
5452 case VT_UI4 :
5453 case VT_UI8 :
5454 case VT_UINT :
5455 case VT_R4 :
5456 case VT_R8 :
5457 case VT_CY :
5458 case VT_EMPTY:
5459 case VT_DATE :
5460 case VT_BSTR :
5461 case VT_DECIMAL:
5462 break;
5463 case VT_VARIANT:
5464 case VT_UNKNOWN:
5465 V_VT(result) = VT_EMPTY;
5466 rc = DISP_E_TYPEMISMATCH;
5467 goto end;
5468 case VT_ERROR:
5469 rc = DISP_E_TYPEMISMATCH;
5470 goto end;
5471 case VT_RECORD:
5472 V_VT(result) = VT_EMPTY;
5473 rc = DISP_E_TYPEMISMATCH;
5474 goto end;
5475 case VT_NULL:
5476 break;
5477 default:
5478 V_VT(result) = VT_EMPTY;
5479 rc = DISP_E_BADVARTYPE;
5480 goto end;
5481 }
5482
5483
5484 switch (V_VT(right) & VT_TYPEMASK) {
5485 case VT_BOOL :
5486 case VT_I1 :
5487 case VT_I2 :
5488 case VT_I4 :
5489 case VT_I8 :
5490 if((V_VT(left) == VT_INT) && (V_VT(right) == VT_I8))
5491 {
5492 V_VT(result) = VT_EMPTY;
5493 rc = DISP_E_TYPEMISMATCH;
5494 goto end;
5495 }
5496 case VT_INT :
5497 if((V_VT(right) == VT_INT) && (V_VT(left) == VT_I8))
5498 {
5499 V_VT(result) = VT_EMPTY;
5500 rc = DISP_E_TYPEMISMATCH;
5501 goto end;
5502 }
5503 case VT_UI1 :
5504 case VT_UI2 :
5505 case VT_UI4 :
5506 case VT_UI8 :
5507 case VT_UINT :
5508 case VT_R4 :
5509 case VT_R8 :
5510 case VT_CY :
5511 if(V_VT(left) == VT_EMPTY)
5512 {
5513 V_VT(result) = VT_I4;
5514 rc = S_OK;
5515 goto end;
5516 }
5517 case VT_EMPTY:
5518 case VT_DATE :
5519 case VT_DECIMAL:
5520 if(V_VT(left) == VT_ERROR)
5521 {
5522 V_VT(result) = VT_EMPTY;
5523 rc = DISP_E_TYPEMISMATCH;
5524 goto end;
5525 }
5526 case VT_BSTR:
5527 if(V_VT(left) == VT_NULL)
5528 {
5529 V_VT(result) = VT_NULL;
5530 rc = S_OK;
5531 goto end;
5532 }
5533 break;
5534
5535 case VT_VOID:
5536 V_VT(result) = VT_EMPTY;
5537 rc = DISP_E_BADVARTYPE;
5538 goto end;
5539 case VT_NULL:
5540 if(V_VT(left) == VT_VOID)
5541 {
5542 V_VT(result) = VT_EMPTY;
5543 rc = DISP_E_BADVARTYPE;
5544 } else if((V_VT(left) == VT_NULL) || (V_VT(left) == VT_EMPTY) || (V_VT(left) == VT_ERROR) ||
5545 lOk)
5546 {
5547 V_VT(result) = VT_NULL;
5548 rc = S_OK;
5549 } else
5550 {
5551 V_VT(result) = VT_NULL;
5552 rc = DISP_E_BADVARTYPE;
5553 }
5554 goto end;
5555 case VT_VARIANT:
5556 case VT_UNKNOWN:
5557 V_VT(result) = VT_EMPTY;
5558 rc = DISP_E_TYPEMISMATCH;
5559 goto end;
5560 case VT_ERROR:
5561 rc = DISP_E_TYPEMISMATCH;
5562 goto end;
5563 case VT_RECORD:
5564 if((V_VT(left) == 15) || ((V_VT(left) >= 24) && (V_VT(left) <= 35)) || !lOk)
5565 {
5566 V_VT(result) = VT_EMPTY;
5567 rc = DISP_E_BADVARTYPE;
5568 } else
5569 {
5570 V_VT(result) = VT_EMPTY;
5571 rc = DISP_E_TYPEMISMATCH;
5572 }
5573 goto end;
5574 default:
5575 V_VT(result) = VT_EMPTY;
5576 rc = DISP_E_BADVARTYPE;
5577 goto end;
5578 }
5579
5580 /* determine the result type */
5581 if((V_VT(left) == VT_I8) || (V_VT(right) == VT_I8)) resT = VT_I8;
5582 else if((V_VT(left) == VT_UI1) && (V_VT(right) == VT_BOOL)) resT = VT_I2;
5583 else if((V_VT(left) == VT_UI1) && (V_VT(right) == VT_UI1)) resT = VT_UI1;
5584 else if((V_VT(left) == VT_UI1) && (V_VT(right) == VT_I2)) resT = VT_I2;
5585 else if((V_VT(left) == VT_I2) && (V_VT(right) == VT_BOOL)) resT = VT_I2;
5586 else if((V_VT(left) == VT_I2) && (V_VT(right) == VT_UI1)) resT = VT_I2;
5587 else if((V_VT(left) == VT_I2) && (V_VT(right) == VT_I2)) resT = VT_I2;
5588 else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_BOOL)) resT = VT_I2;
5589 else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_UI1)) resT = VT_I2;
5590 else if((V_VT(left) == VT_BOOL) && (V_VT(right) == VT_I2)) resT = VT_I2;
5591 else resT = VT_I4; /* most outputs are I4 */
5592
5593 /* convert to I8 for the modulo */
5594 rc = VariantChangeType(&lv, left, 0, VT_I8);
5595 if(FAILED(rc))
5596 {
5597 FIXME("Could not convert left type %d to %d? rc == 0x%X\n", V_VT(left), VT_I8, rc);
5598 goto end;
5599 }
5600
5601 rc = VariantChangeType(&rv, right, 0, VT_I8);
5602 if(FAILED(rc))
5603 {
5604 FIXME("Could not convert right type %d to %d? rc == 0x%X\n", V_VT(right), VT_I8, rc);
5605 goto end;
5606 }
5607
5608 /* if right is zero set VT_EMPTY and return divide by zero */
5609 if(V_I8(&rv) == 0)
5610 {
5611 V_VT(result) = VT_EMPTY;
5612 rc = DISP_E_DIVBYZERO;
5613 goto end;
5614 }
5615
5616 /* perform the modulo operation */
5617 V_VT(result) = VT_I8;
5618 V_I8(result) = V_I8(&lv) % V_I8(&rv);
5619
5620 TRACE("V_I8(left) == %s, V_I8(right) == %s, V_I8(result) == %s\n",
5621 wine_dbgstr_longlong(V_I8(&lv)), wine_dbgstr_longlong(V_I8(&rv)),
5622 wine_dbgstr_longlong(V_I8(result)));
5623
5624 /* convert left and right to the destination type */
5625 rc = VariantChangeType(result, result, 0, resT);
5626 if(FAILED(rc))
5627 {
5628 FIXME("Could not convert 0x%x to %d?\n", V_VT(result), resT);
5629 /* fall to end of function */
5630 }
5631
5632 end:
5633 VariantClear(&lv);
5634 VariantClear(&rv);
5635 VariantClear(&tempLeft);
5636 VariantClear(&tempRight);
5637 return rc;
5638 }
5639
5640 /**********************************************************************
5641 * VarPow [OLEAUT32.158]
5642 *
5643 * Computes the power of one variant to another variant.
5644 *
5645 * PARAMS
5646 * left [I] First variant
5647 * right [I] Second variant
5648 * result [O] Result variant
5649 *
5650 * RETURNS
5651 * Success: S_OK.
5652 * Failure: An HRESULT error code indicating the error.
5653 */
5654 HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result)
5655 {
5656 HRESULT hr = S_OK;
5657 VARIANT dl,dr;
5658 VARTYPE resvt = VT_EMPTY;
5659 VARTYPE leftvt,rightvt;
5660 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
5661 VARIANT tempLeft, tempRight;
5662
5663 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left),
5664 right, debugstr_VT(right), debugstr_VF(right), result);
5665
5666 VariantInit(&dl);
5667 VariantInit(&dr);
5668 VariantInit(&tempLeft);
5669 VariantInit(&tempRight);
5670
5671 /* Handle VT_DISPATCH by storing and taking address of returned value */
5672 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
5673 {
5674 hr = VARIANT_FetchDispatchValue(left, &tempLeft);
5675 if (FAILED(hr)) goto end;
5676 left = &tempLeft;
5677 }
5678 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
5679 {
5680 hr = VARIANT_FetchDispatchValue(right, &tempRight);
5681 if (FAILED(hr)) goto end;
5682 right = &tempRight;
5683 }
5684
5685 leftvt = V_VT(left)&VT_TYPEMASK;
5686 rightvt = V_VT(right)&VT_TYPEMASK;
5687 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
5688 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
5689
5690 if (leftExtraFlags != rightExtraFlags)
5691 {
5692 hr = DISP_E_BADVARTYPE;
5693 goto end;
5694 }
5695 ExtraFlags = leftExtraFlags;
5696
5697 /* Native VarPow always returns an error when using extra flags */
5698 if (ExtraFlags != 0)
5699 {
5700 hr = DISP_E_BADVARTYPE;
5701 goto end;
5702 }
5703
5704 /* Determine return type */
5705 else if (leftvt == VT_NULL || rightvt == VT_NULL) {
5706 V_VT(result) = VT_NULL;
5707 hr = S_OK;
5708 goto end;
5709 }
5710 else if ((leftvt == VT_EMPTY || leftvt == VT_I2 ||
5711 leftvt == VT_I4 || leftvt == VT_R4 ||
5712 leftvt == VT_R8 || leftvt == VT_CY ||
5713 leftvt == VT_DATE || leftvt == VT_BSTR ||
5714 leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
5715 (leftvt >= VT_I1 && leftvt <= VT_UINT)) &&
5716 (rightvt == VT_EMPTY || rightvt == VT_I2 ||
5717 rightvt == VT_I4 || rightvt == VT_R4 ||
5718 rightvt == VT_R8 || rightvt == VT_CY ||
5719 rightvt == VT_DATE || rightvt == VT_BSTR ||
5720 rightvt == VT_BOOL || rightvt == VT_DECIMAL ||
5721 (rightvt >= VT_I1 && rightvt <= VT_UINT)))
5722 resvt = VT_R8;
5723 else
5724 {
5725 hr = DISP_E_BADVARTYPE;
5726 goto end;
5727 }
5728
5729 hr = VariantChangeType(&dl,left,0,resvt);
5730 if (FAILED(hr)) {
5731 ERR("Could not change passed left argument to VT_R8, handle it differently.\n");
5732 hr = E_FAIL;
5733 goto end;
5734 }
5735
5736 hr = VariantChangeType(&dr,right,0,resvt);
5737 if (FAILED(hr)) {
5738 ERR("Could not change passed right argument to VT_R8, handle it differently.\n");
5739 hr = E_FAIL;
5740 goto end;
5741 }
5742
5743 V_VT(result) = VT_R8;
5744 V_R8(result) = pow(V_R8(&dl),V_R8(&dr));
5745
5746 end:
5747 VariantClear(&dl);
5748 VariantClear(&dr);
5749 VariantClear(&tempLeft);
5750 VariantClear(&tempRight);
5751
5752 return hr;
5753 }
5754
5755 /**********************************************************************
5756 * VarImp [OLEAUT32.154]
5757 *
5758 * Bitwise implication of two variants.
5759 *
5760 * PARAMS
5761 * left [I] First variant
5762 * right [I] Second variant
5763 * result [O] Result variant
5764 *
5765 * RETURNS
5766 * Success: S_OK.
5767 * Failure: An HRESULT error code indicating the error.
5768 */
5769 HRESULT WINAPI VarImp(LPVARIANT left, LPVARIANT right, LPVARIANT result)
5770 {
5771 HRESULT hres = S_OK;
5772 VARTYPE resvt = VT_EMPTY;
5773 VARTYPE leftvt,rightvt;
5774 VARTYPE rightExtraFlags,leftExtraFlags,ExtraFlags;
5775 VARIANT lv,rv;
5776 double d;
5777 VARIANT tempLeft, tempRight;
5778
5779 VariantInit(&lv);
5780 VariantInit(&rv);
5781 VariantInit(&tempLeft);
5782 VariantInit(&tempRight);
5783
5784 TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
5785 debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
5786
5787 /* Handle VT_DISPATCH by storing and taking address of returned value */
5788 if ((V_VT(left) & VT_TYPEMASK) == VT_DISPATCH)
5789 {
5790 hres = VARIANT_FetchDispatchValue(left, &tempLeft);
5791 if (FAILED(hres)) goto VarImp_Exit;
5792 left = &tempLeft;
5793 }
5794 if ((V_VT(right) & VT_TYPEMASK) == VT_DISPATCH)
5795 {
5796 hres = VARIANT_FetchDispatchValue(right, &tempRight);
5797 if (FAILED(hres)) goto VarImp_Exit;
5798 right = &tempRight;
5799 }
5800
5801 leftvt = V_VT(left)&VT_TYPEMASK;
5802 rightvt = V_VT(right)&VT_TYPEMASK;
5803 leftExtraFlags = V_VT(left)&(~VT_TYPEMASK);
5804 rightExtraFlags = V_VT(right)&(~VT_TYPEMASK);
5805
5806 if (leftExtraFlags != rightExtraFlags)
5807 {
5808 hres = DISP_E_BADVARTYPE;
5809 goto VarImp_Exit;
5810 }
5811 ExtraFlags = leftExtraFlags;
5812
5813 /* Native VarImp always returns an error when using extra
5814 * flags or if the variants are I8 and INT.
5815 */
5816 if ((leftvt == VT_I8 && rightvt == VT_INT) ||
5817 ExtraFlags != 0)
5818 {
5819 hres = DISP_E_BADVARTYPE;
5820 goto VarImp_Exit;
5821 }
5822
5823 /* Determine result type */
5824 else if ((leftvt == VT_NULL && rightvt == VT_NULL) ||
5825 (leftvt == VT_NULL && rightvt == VT_EMPTY))
5826 {
5827 V_VT(result) = VT_NULL;
5828 hres = S_OK;
5829 goto VarImp_Exit;
5830 }
5831 else if (leftvt == VT_I8 || rightvt == VT_I8)
5832 resvt = VT_I8;
5833 else if (leftvt == VT_I4 || rightvt == VT_I4 ||
5834 leftvt == VT_INT || rightvt == VT_INT ||
5835 leftvt == VT_UINT || rightvt == VT_UINT ||
5836 leftvt == VT_UI4 || rightvt == VT_UI4 ||
5837 leftvt == VT_UI8 || rightvt == VT_UI8 ||
5838 leftvt == VT_UI2 || rightvt == VT_UI2 ||
5839 leftvt == VT_DECIMAL || rightvt == VT_DECIMAL ||
5840 leftvt == VT_DATE || rightvt == VT_DATE ||
5841 leftvt == VT_CY || rightvt == VT_CY ||
5842 leftvt == VT_R8 || rightvt == VT_R8 ||
5843 leftvt == VT_R4 || rightvt == VT_R4 ||
5844 leftvt == VT_I1 || rightvt == VT_I1)
5845 resvt = VT_I4;
5846 else if ((leftvt == VT_UI1 && rightvt == VT_UI1) ||
5847 (leftvt == VT_UI1 && rightvt == VT_NULL) ||
5848 (leftvt == VT_NULL && rightvt == VT_UI1))
5849 resvt = VT_UI1;
5850 else if (leftvt == VT_EMPTY || rightvt == VT_EMPTY ||
5851 leftvt == VT_I2 || rightvt == VT_I2 ||
5852 leftvt == VT_UI1 || rightvt == VT_UI1)
5853 resvt = VT_I2;
5854 else if (leftvt == VT_BOOL || rightvt == VT_BOOL ||
5855 leftvt == VT_BSTR || rightvt == VT_BSTR)
5856 resvt = VT_BOOL;
5857
5858 /* VT_NULL requires special handling for when the opposite
5859 * variant is equal to something other than -1.
5860 * (NULL Imp 0 = NULL, NULL Imp n = n)
5861 */
5862 if (leftvt == VT_NULL)
5863 {
5864 VARIANT_BOOL b;
5865 switch(rightvt)
5866 {
5867 case VT_I1: if (!V_I1(right)) resvt = VT_NULL; break;
5868 case VT_UI1: if (!V_UI1(right)) resvt = VT_NULL; break;
5869 case VT_I2: if (!V_I2(right)) resvt = VT_NULL; break;
5870 case VT_UI2: if (!V_UI2(right)) resvt = VT_NULL; break;
5871 case VT_I4: if (!V_I4(right)) resvt = VT_NULL; break;
5872 case VT_UI4: if (!V_UI4(right)) resvt = VT_NULL; break;
5873 case VT_I8: if (!V_I8(right)) resvt = VT_NULL; break;
5874 case VT_UI8: if (!V_UI8(right)) resvt = VT_NULL; break;
5875 case VT_INT: if (!V_INT(right)) resvt = VT_NULL; break;
5876 case VT_UINT: if (!V_UINT(right)) resvt = VT_NULL; break;
5877 case VT_BOOL: if (!V_BOOL(right)) resvt = VT_NULL; break;
5878 case VT_R4: if (!V_R4(right)) resvt = VT_NULL; break;
5879 case VT_R8: if (!V_R8(right)) resvt = VT_NULL; break;
5880 case VT_DATE: if (!V_DATE(right)) resvt = VT_NULL; break;
5881 case VT_CY: if (!V_CY(right).int64) resvt = VT_NULL; break;
5882 case VT_DECIMAL:
5883 if (!(DEC_HI32(&V_DECIMAL(right)) || DEC_LO64(&V_DECIMAL(right))))
5884 resvt = VT_NULL;
5885 break;
5886 case VT_BSTR:
5887 hres = VarBoolFromStr(V_BSTR(right),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
5888 if (FAILED(hres)) goto VarImp_Exit;
5889 else if (!b)
5890 V_VT(result) = VT_NULL;
5891 else
5892 {
5893 V_VT(result) = VT_BOOL;
5894 V_BOOL(result) = b;
5895 }
5896 goto VarImp_Exit;
5897 }
5898 if (resvt == VT_NULL)
5899 {
5900 V_VT(result) = resvt;
5901 goto VarImp_Exit;
5902 }
5903 else
5904 {
5905 hres = VariantChangeType(result,right,0,resvt);
5906 goto VarImp_Exit;
5907 }
5908 }
5909
5910 /* Special handling is required when NULL is the right variant.
5911 * (-1 Imp NULL = NULL, n Imp NULL = n Imp 0)
5912 */
5913 else if (rightvt == VT_NULL)
5914 {
5915 VARIANT_BOOL b;
5916 switch(leftvt)
5917 {
5918 case VT_I1: if (V_I1(left) == -1) resvt = VT_NULL; break;
5919 case VT_UI1: if (V_UI1(left) == 0xff) resvt = VT_NULL; break;
5920 case VT_I2: if (V_I2(left) == -1) resvt = VT_NULL; break;
5921 case VT_UI2: if (V_UI2(left) == 0xffff) resvt = VT_NULL; break;
5922 case VT_INT: if (V_INT(left) == -1) resvt = VT_NULL; break;
5923 case VT_UINT: if (V_UINT(left) == ~0u) resvt = VT_NULL; break;
5924 case VT_I4: if (V_I4(left) == -1) resvt = VT_NULL; break;
5925 case VT_UI4: if (V_UI4(left) == ~0u) resvt = VT_NULL; break;
5926 case VT_I8: if (V_I8(left) == -1) resvt = VT_NULL; break;
5927 case VT_UI8: if (V_UI8(left) == ~(ULONGLONG)0) resvt = VT_NULL; break;
5928 case VT_BOOL: if (V_BOOL(left) == VARIANT_TRUE) resvt = VT_NULL; break;
5929 case VT_R4: if (V_R4(left) == -1.0) resvt = VT_NULL; break;
5930 case VT_R8: if (V_R8(left) == -1.0) resvt = VT_NULL; break;
5931 case VT_CY: if (V_CY(left).int64 == -1) resvt = VT_NULL; break;
5932 case VT_DECIMAL:
5933 if (DEC_HI32(&V_DECIMAL(left)) == 0xffffffff)
5934 resvt = VT_NULL;
5935 break;
5936 case VT_BSTR:
5937 hres = VarBoolFromStr(V_BSTR(left),LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
5938 if (FAILED(hres)) goto VarImp_Exit;
5939 else if (b == VARIANT_TRUE)
5940 resvt = VT_NULL;
5941 }
5942 if (resvt == VT_NULL)
5943 {
5944 V_VT(result) = resvt;
5945 goto VarImp_Exit;
5946 }
5947 }
5948
5949 hres = VariantCopy(&lv, left);
5950 if (FAILED(hres)) goto VarImp_Exit;
5951
5952 if (rightvt == VT_NULL)
5953 {
5954 memset( &rv, 0, sizeof(rv) );
5955 V_VT(&rv) = resvt;
5956 }
5957 else
5958 {
5959 hres = VariantCopy(&rv, right);
5960 if (FAILED(hres)) goto VarImp_Exit;
5961 }
5962
5963 if (V_VT(&lv) == VT_BSTR &&
5964 FAILED(VarR8FromStr(V_BSTR(&lv),LOCALE_USER_DEFAULT, 0, &d)))
5965 hres = VariantChangeType(&lv,&lv,VARIANT_LOCALBOOL, VT_BOOL);
5966 if (SUCCEEDED(hres) && V_VT(&lv) != resvt)
5967 hres = VariantChangeType(&lv,&lv,0,resvt);
5968 if (FAILED(hres)) goto VarImp_Exit;
5969
5970 if (V_VT(&rv) == VT_BSTR &&
5971 FAILED(VarR8FromStr(V_BSTR(&rv),LOCALE_USER_DEFAULT, 0, &d)))
5972 hres = VariantChangeType(&rv, &rv,VARIANT_LOCALBOOL, VT_BOOL);
5973 if (SUCCEEDED(hres) && V_VT(&rv) != resvt)
5974 hres = VariantChangeType(&rv, &rv, 0, resvt);
5975 if (FAILED(hres)) goto VarImp_Exit;
5976
5977 /* do the math */
5978 V_VT(result) = resvt;
5979 switch (resvt)
5980 {
5981 case VT_I8:
5982 V_I8(result) = (~V_I8(&lv)) | V_I8(&rv);
5983 break;
5984 case VT_I4:
5985 V_I4(result) = (~V_I4(&lv)) | V_I4(&rv);
5986 break;
5987 case VT_I2:
5988 V_I2(result) = (~V_I2(&lv)) | V_I2(&rv);
5989 break;
5990 case VT_UI1:
5991 V_UI1(result) = (~V_UI1(&lv)) | V_UI1(&rv);
5992 break;
5993 case VT_BOOL:
5994 V_BOOL(result) = (~V_BOOL(&lv)) | V_BOOL(&rv);
5995 break;
5996 default:
5997 FIXME("Couldn't perform bitwise implication on variant types %d,%d\n",
5998 leftvt,rightvt);
5999 }
6000
6001 VarImp_Exit:
6002
6003 VariantClear(&lv);
6004 VariantClear(&rv);
6005 VariantClear(&tempLeft);
6006 VariantClear(&tempRight);
6007
6008 return hres;
6009 }