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