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