[OLEAUT32_WINETEST] Add a PCH.
[reactos.git] / modules / rostests / winetests / oleaut32 / vartest.c
1 /*
2 * VARIANT test program
3 *
4 * Copyright 1998 Jean-Claude Cote
5 * Copyright 2006 Google (Benjamin Arai)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "precomp.h"
23
24 #include <float.h>
25
26 static HMODULE hOleaut32;
27
28 static HRESULT (WINAPI *pVarUdateFromDate)(DATE,ULONG,UDATE*);
29 static HRESULT (WINAPI *pVarDateFromUdate)(UDATE*,ULONG,DATE*);
30 static INT (WINAPI *pSystemTimeToVariantTime)(LPSYSTEMTIME,double*);
31 static INT (WINAPI *pVariantTimeToSystemTime)(double,LPSYSTEMTIME);
32 static INT (WINAPI *pDosDateTimeToVariantTime)(USHORT,USHORT,double*);
33 static INT (WINAPI *pVariantTimeToDosDateTime)(double,USHORT*,USHORT *);
34
35 static const WCHAR sz12[] = {'1','2','\0'};
36 /* the strings are localized */
37 static WCHAR sz12_false[32];
38 static WCHAR sz12_true[32];
39
40 /* Get a conversion function ptr, return if function not available */
41 #define CHECKPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func); \
42 if (!p##func) { win_skip("function " # func " not available, not testing it\n"); return; }
43
44 /* Has I8/UI8 data type? */
45 static BOOL has_i8;
46
47 /* When comparing floating point values we cannot expect an exact match
48 * because the rounding errors depend on the exact algorithm.
49 */
50 #define EQ_DOUBLE(a,b) (fabs((a)-(b)) / (1.0+fabs(a)+fabs(b)) < 1e-14)
51 #define EQ_FLOAT(a,b) (fabs((a)-(b)) / (1.0+fabs(a)+fabs(b)) < 1e-7)
52
53 #define SKIPTESTS(a) if((a > VT_CLSID+10) && (a < VT_BSTR_BLOB-10)) continue
54
55 /* Allow our test macros to work for VT_NULL and VT_EMPTY too */
56 #define V_EMPTY(v) V_I4(v)
57 #define V_NULL(v) V_I4(v)
58
59 /* Size constraints for overflow tests */
60 #define I1_MAX 0x7f
61 #define I1_MIN ((-I1_MAX)-1)
62 #define UI1_MAX 0xff
63 #define UI1_MIN 0
64 #define I2_MAX 0x7fff
65 #define I2_MIN ((-I2_MAX)-1)
66 #define UI2_MAX 0xffff
67 #define UI2_MIN 0
68 #define I4_MAX 0x7fffffff
69 #define I4_MIN ((-I4_MAX)-1)
70 #define UI4_MAX 0xffffffff
71 #define UI4_MIN 0
72 #define I8_MAX (((LONGLONG)I4_MAX << 32) | UI4_MAX)
73 #define I8_MIN ((-I8_MAX)-1)
74 #define UI8_MAX (((ULONGLONG)UI4_MAX << 32) | UI4_MAX)
75 #define UI8_MIN 0
76 #define DATE_MAX 2958465
77 #define DATE_MIN -657434
78 #define R4_MAX FLT_MAX
79 #define R4_MIN FLT_MIN
80 #define R8_MAX DBL_MAX
81 #define R8_MIN DBL_MIN
82
83 #define DEFINE_EXPECT(func) \
84 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
85
86 #define SET_EXPECT(func) \
87 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
88
89 #define CHECK_EXPECT2(func) \
90 do { \
91 ok(expect_ ##func, "unexpected call " #func "\n"); \
92 called_ ## func = TRUE; \
93 }while(0)
94
95 #define CHECK_EXPECT(func) \
96 do { \
97 CHECK_EXPECT2(func); \
98 expect_ ## func = FALSE; \
99 }while(0)
100
101 #define CHECK_CALLED(func) \
102 do { \
103 ok(called_ ## func, "expected " #func "\n"); \
104 expect_ ## func = called_ ## func = FALSE; \
105 }while(0)
106
107 DEFINE_EXPECT(dispatch_invoke);
108
109 typedef struct
110 {
111 IDispatch IDispatch_iface;
112 VARTYPE vt;
113 HRESULT result;
114 } DummyDispatch;
115
116 static inline DummyDispatch *impl_from_IDispatch(IDispatch *iface)
117 {
118 return CONTAINING_RECORD(iface, DummyDispatch, IDispatch_iface);
119 }
120
121 static ULONG WINAPI DummyDispatch_AddRef(IDispatch *iface)
122 {
123 return 2;
124 }
125
126 static ULONG WINAPI DummyDispatch_Release(IDispatch *iface)
127 {
128 return 1;
129 }
130
131 static HRESULT WINAPI DummyDispatch_QueryInterface(IDispatch *iface,
132 REFIID riid,
133 void** ppvObject)
134 {
135 *ppvObject = NULL;
136
137 if (IsEqualIID(riid, &IID_IDispatch) ||
138 IsEqualIID(riid, &IID_IUnknown))
139 {
140 *ppvObject = iface;
141 IDispatch_AddRef(iface);
142 }
143
144 return *ppvObject ? S_OK : E_NOINTERFACE;
145 }
146
147 static HRESULT WINAPI DummyDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
148 {
149 ok(0, "Unexpected call\n");
150 return E_NOTIMPL;
151 }
152
153 static HRESULT WINAPI DummyDispatch_GetTypeInfo(IDispatch *iface, UINT tinfo, LCID lcid, ITypeInfo **ti)
154 {
155 ok(0, "Unexpected call\n");
156 return E_NOTIMPL;
157 }
158
159 static HRESULT WINAPI DummyDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names,
160 UINT cnames, LCID lcid, DISPID *dispid)
161 {
162 ok(0, "Unexpected call\n");
163 return E_NOTIMPL;
164 }
165
166 static HRESULT WINAPI DummyDispatch_Invoke(IDispatch *iface,
167 DISPID dispid, REFIID riid,
168 LCID lcid, WORD wFlags,
169 DISPPARAMS *params,
170 VARIANT *res,
171 EXCEPINFO *ei,
172 UINT *arg_err)
173 {
174 DummyDispatch *This = impl_from_IDispatch(iface);
175
176 CHECK_EXPECT(dispatch_invoke);
177
178 ok(dispid == DISPID_VALUE, "got dispid %d\n", dispid);
179 ok(IsEqualIID(riid, &IID_NULL), "go riid %s\n", wine_dbgstr_guid(riid));
180 ok(wFlags == DISPATCH_PROPERTYGET, "Flags wrong\n");
181
182 ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
183 ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
184 ok(params->cArgs == 0, "got %d\n", params->cArgs);
185 ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
186
187 ok(res != NULL, "got %p\n", res);
188 ok(V_VT(res) == VT_EMPTY, "got %d\n", V_VT(res));
189 ok(ei == NULL, "got %p\n", ei);
190 ok(arg_err == NULL, "got %p\n", arg_err);
191
192 if (FAILED(This->result))
193 return This->result;
194
195 V_VT(res) = This->vt;
196 if (This->vt == VT_UI1)
197 V_UI1(res) = 34;
198 else if (This->vt == VT_NULL)
199 {
200 V_VT(res) = VT_NULL;
201 V_BSTR(res) = NULL;
202 }
203 else
204 memset(res, 0, sizeof(*res));
205
206 return S_OK;
207 }
208
209 static const IDispatchVtbl DummyDispatch_VTable =
210 {
211 DummyDispatch_QueryInterface,
212 DummyDispatch_AddRef,
213 DummyDispatch_Release,
214 DummyDispatch_GetTypeInfoCount,
215 DummyDispatch_GetTypeInfo,
216 DummyDispatch_GetIDsOfNames,
217 DummyDispatch_Invoke
218 };
219
220 static void init_test_dispatch(VARTYPE vt, DummyDispatch *dispatch)
221 {
222 dispatch->IDispatch_iface.lpVtbl = &DummyDispatch_VTable;
223 dispatch->vt = vt;
224 dispatch->result = S_OK;
225 }
226
227 typedef struct IRecordInfoImpl
228 {
229 IRecordInfo IRecordInfo_iface;
230 LONG ref;
231 unsigned int recordclear;
232 unsigned int getsize;
233 unsigned int recordcopy;
234 struct __tagBRECORD *rec;
235 } IRecordInfoImpl;
236
237 static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface)
238 {
239 return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
240 }
241
242 static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj)
243 {
244 *obj = NULL;
245
246 if (IsEqualIID(riid, &IID_IUnknown) ||
247 IsEqualIID(riid, &IID_IRecordInfo))
248 {
249 *obj = iface;
250 IRecordInfo_AddRef(iface);
251 return S_OK;
252 }
253
254 return E_NOINTERFACE;
255 }
256
257 static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface)
258 {
259 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
260 return InterlockedIncrement(&This->ref);
261 }
262
263 static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface)
264 {
265 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
266 ULONG ref = InterlockedDecrement(&This->ref);
267
268 if (!ref)
269 HeapFree(GetProcessHeap(), 0, This);
270
271 return ref;
272 }
273
274 static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew)
275 {
276 ok(0, "unexpected call\n");
277 return E_NOTIMPL;
278 }
279
280 static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, void *data)
281 {
282 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
283 This->recordclear++;
284 This->rec->pvRecord = NULL;
285 return S_OK;
286 }
287
288 static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, void *src, void *dest)
289 {
290 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
291 This->recordcopy++;
292 ok(src == (void*)0xdeadbeef, "wrong src pointer %p\n", src);
293 return S_OK;
294 }
295
296 static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
297 {
298 ok(0, "unexpected call\n");
299 return E_NOTIMPL;
300 }
301
302 static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
303 {
304 ok(0, "unexpected call\n");
305 return E_NOTIMPL;
306 }
307
308 static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size)
309 {
310 IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
311 This->getsize++;
312 *size = 0;
313 return S_OK;
314 }
315
316 static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
317 {
318 ok(0, "unexpected call\n");
319 return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData,
323 LPCOLESTR szFieldName, VARIANT *pvarField)
324 {
325 ok(0, "unexpected call\n");
326 return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
330 LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
331 {
332 ok(0, "unexpected call\n");
333 return E_NOTIMPL;
334 }
335
336 static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
337 LPCOLESTR szFieldName, VARIANT *pvarField)
338 {
339 ok(0, "unexpected call\n");
340 return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
344 PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
345 {
346 ok(0, "unexpected call\n");
347 return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
351 BSTR *rgBstrNames)
352 {
353 ok(0, "unexpected call\n");
354 return E_NOTIMPL;
355 }
356
357 static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
358 {
359 ok(0, "unexpected call\n");
360 return FALSE;
361 }
362
363 static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface)
364 {
365 ok(0, "unexpected call\n");
366 return NULL;
367 }
368
369 static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
370 PVOID *ppvDest)
371 {
372 ok(0, "unexpected call\n");
373 return E_NOTIMPL;
374 }
375
376 static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
377 {
378 ok(0, "unexpected call\n");
379 return E_NOTIMPL;
380 }
381
382 static const IRecordInfoVtbl RecordInfoVtbl =
383 {
384 RecordInfo_QueryInterface,
385 RecordInfo_AddRef,
386 RecordInfo_Release,
387 RecordInfo_RecordInit,
388 RecordInfo_RecordClear,
389 RecordInfo_RecordCopy,
390 RecordInfo_GetGuid,
391 RecordInfo_GetName,
392 RecordInfo_GetSize,
393 RecordInfo_GetTypeInfo,
394 RecordInfo_GetField,
395 RecordInfo_GetFieldNoCopy,
396 RecordInfo_PutField,
397 RecordInfo_PutFieldNoCopy,
398 RecordInfo_GetFieldNames,
399 RecordInfo_IsMatchingType,
400 RecordInfo_RecordCreate,
401 RecordInfo_RecordCreateCopy,
402 RecordInfo_RecordDestroy
403 };
404
405 static IRecordInfoImpl *get_test_recordinfo(void)
406 {
407 IRecordInfoImpl *rec;
408
409 rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
410 rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl;
411 rec->ref = 1;
412 rec->recordclear = 0;
413 rec->getsize = 0;
414 rec->recordcopy = 0;
415
416 return rec;
417 }
418
419 static void init(void)
420 {
421 BSTR bstr;
422 HRESULT res;
423
424 res = VarBstrFromBool(VARIANT_TRUE, LANG_USER_DEFAULT, VAR_LOCALBOOL, &bstr);
425 ok(res == S_OK && bstr[0], "Expected localized string for 'True'\n");
426 /* lstrcpyW / lstrcatW do not work on win95 */
427 memcpy(sz12_true, sz12, sizeof(sz12));
428 if (bstr) memcpy(&sz12_true[2], bstr, SysStringByteLen(bstr) + sizeof(WCHAR));
429 SysFreeString(bstr);
430
431 res = VarBstrFromBool(VARIANT_FALSE, LANG_USER_DEFAULT, VAR_LOCALBOOL, &bstr);
432 ok(res == S_OK && bstr[0], "Expected localized string for 'False'\n");
433 memcpy(sz12_false, sz12, sizeof(sz12));
434 if (bstr) memcpy(&sz12_false[2], bstr, SysStringByteLen(bstr) + sizeof(WCHAR));
435 SysFreeString(bstr);
436
437 hOleaut32 = GetModuleHandleA("oleaut32.dll");
438 has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
439 if (!has_i8)
440 skip("No support for I8 and UI8 data types\n");
441 }
442
443 /* Functions to set a DECIMAL */
444 static void setdec(DECIMAL* dec, BYTE scl, BYTE sgn, ULONG hi32, ULONG64 lo64)
445 {
446 S(U(*dec)).scale = scl;
447 S(U(*dec)).sign = sgn;
448 dec->Hi32 = hi32;
449 U1(*dec).Lo64 = lo64;
450 }
451
452 static void setdec64(DECIMAL* dec, BYTE scl, BYTE sgn, ULONG hi32, ULONG mid32, ULONG lo32)
453 {
454 S(U(*dec)).scale = scl;
455 S(U(*dec)).sign = sgn;
456 dec->Hi32 = hi32;
457 S1(U1(*dec)).Mid32 = mid32;
458 S1(U1(*dec)).Lo32 = lo32;
459 }
460
461 /* return the string text of a given variant type */
462 static char vtstr_buffer[16][256];
463 static int vtstr_current=0;
464 static const char *vtstr(int x)
465 {
466 switch(x) {
467 #define CASE(vt) case VT_##vt: return #vt
468 CASE(EMPTY);
469 CASE(NULL);
470 CASE(I2);
471 CASE(I4);
472 CASE(R4);
473 CASE(R8);
474 CASE(CY);
475 CASE(DATE);
476 CASE(BSTR);
477 CASE(DISPATCH);
478 CASE(ERROR);
479 CASE(BOOL);
480 CASE(VARIANT);
481 CASE(UNKNOWN);
482 CASE(DECIMAL);
483 CASE(I1);
484 CASE(UI1);
485 CASE(UI2);
486 CASE(UI4);
487 CASE(I8);
488 CASE(UI8);
489 CASE(INT);
490 CASE(UINT);
491 CASE(VOID);
492 CASE(HRESULT);
493 CASE(PTR);
494 CASE(SAFEARRAY);
495 CASE(CARRAY);
496 CASE(USERDEFINED);
497 CASE(LPSTR);
498 CASE(LPWSTR);
499 CASE(RECORD);
500 CASE(INT_PTR);
501 CASE(UINT_PTR);
502 CASE(FILETIME);
503 CASE(BLOB);
504 CASE(STREAM);
505 CASE(STORAGE);
506 CASE(STREAMED_OBJECT);
507 CASE(STORED_OBJECT);
508 CASE(BLOB_OBJECT);
509 CASE(CF);
510 CASE(CLSID);
511 CASE(VERSIONED_STREAM);
512 CASE(VECTOR);
513 CASE(ARRAY);
514 CASE(BYREF);
515 CASE(RESERVED);
516 CASE(ILLEGAL);
517 #undef CASE
518
519 case 0xfff:
520 return "VT_BSTR_BLOB/VT_ILLEGALMASKED/VT_TYPEMASK";
521
522 default:
523 vtstr_current %= sizeof(vtstr_buffer)/sizeof(*vtstr_buffer);
524 sprintf(vtstr_buffer[vtstr_current], "unknown variant type %d", x);
525 return vtstr_buffer[vtstr_current++];
526 }
527 }
528
529 static const char *variantstr( const VARIANT *var )
530 {
531 vtstr_current %= sizeof(vtstr_buffer)/sizeof(*vtstr_buffer);
532 switch(V_VT(var))
533 {
534 case VT_I1:
535 sprintf( vtstr_buffer[vtstr_current], "VT_I1(%d)", V_I1(var) ); break;
536 case VT_I2:
537 sprintf( vtstr_buffer[vtstr_current], "VT_I2(%d)", V_I2(var) ); break;
538 case VT_I4:
539 sprintf( vtstr_buffer[vtstr_current], "VT_I4(%d)", V_I4(var) ); break;
540 case VT_INT:
541 sprintf( vtstr_buffer[vtstr_current], "VT_INT(%d)", V_INT(var) ); break;
542 case VT_I8:
543 sprintf( vtstr_buffer[vtstr_current], "VT_I8(%x%08x)", (UINT)(V_I8(var) >> 32), (UINT)V_I8(var) ); break;
544 case VT_UI8:
545 sprintf( vtstr_buffer[vtstr_current], "VT_UI8(%x%08x)", (UINT)(V_UI8(var) >> 32), (UINT)V_UI8(var) ); break;
546 case VT_R4:
547 sprintf( vtstr_buffer[vtstr_current], "VT_R4(%g)", V_R4(var) ); break;
548 case VT_R8:
549 sprintf( vtstr_buffer[vtstr_current], "VT_R8(%g)", V_R8(var) ); break;
550 case VT_UI1:
551 sprintf( vtstr_buffer[vtstr_current], "VT_UI1(%u)", V_UI1(var) ); break;
552 case VT_UI2:
553 sprintf( vtstr_buffer[vtstr_current], "VT_UI2(%u)", V_UI2(var) ); break;
554 case VT_UI4:
555 sprintf( vtstr_buffer[vtstr_current], "VT_UI4(%u)", V_UI4(var) ); break;
556 case VT_UINT:
557 sprintf( vtstr_buffer[vtstr_current], "VT_UINT(%d)", V_UINT(var) ); break;
558 case VT_CY:
559 sprintf( vtstr_buffer[vtstr_current], "VT_CY(%x%08x)", S(V_CY(var)).Hi, S(V_CY(var)).Lo ); break;
560 case VT_DATE:
561 sprintf( vtstr_buffer[vtstr_current], "VT_DATE(%g)", V_DATE(var) ); break;
562 default:
563 return vtstr(V_VT(var));
564 }
565 return vtstr_buffer[vtstr_current++];
566 }
567
568 static BOOL is_expected_variant( const VARIANT *result, const VARIANT *expected )
569 {
570 if (V_VT(result) != V_VT(expected)) return FALSE;
571 switch(V_VT(expected))
572 {
573 case VT_EMPTY:
574 case VT_NULL:
575 return TRUE;
576
577 #define CASE(vt) case VT_##vt: return (V_##vt(result) == V_##vt(expected))
578 CASE(BOOL);
579 CASE(I1);
580 CASE(UI1);
581 CASE(I2);
582 CASE(UI2);
583 CASE(I4);
584 CASE(UI4);
585 CASE(I8);
586 CASE(UI8);
587 CASE(INT);
588 CASE(UINT);
589 #undef CASE
590
591 case VT_DATE:
592 return EQ_FLOAT(V_DATE(result), V_DATE(expected));
593 case VT_R4:
594 return EQ_FLOAT(V_R4(result), V_R4(expected));
595 case VT_R8:
596 return EQ_FLOAT(V_R8(result), V_R8(expected));
597 case VT_CY:
598 return (V_CY(result).int64 == V_CY(expected).int64);
599 case VT_BSTR:
600 return !lstrcmpW( V_BSTR(result), V_BSTR(expected) );
601 case VT_DECIMAL:
602 return !memcmp( &V_DECIMAL(result), &V_DECIMAL(expected), sizeof(DECIMAL) );
603 default:
604 ok(0, "unhandled variant type %s\n",vtstr(V_VT(expected)));
605 return FALSE;
606 }
607 }
608
609 static void test_var_call1( int line, HRESULT (WINAPI *func)(LPVARIANT,LPVARIANT),
610 VARIANT *arg, VARIANT *expected )
611 {
612 VARIANT old_arg = *arg;
613 VARIANT result;
614 HRESULT hres;
615
616 memset( &result, 0, sizeof(result) );
617 hres = func( arg, &result );
618 ok_(__FILE__,line)( hres == S_OK, "wrong result %x\n", hres );
619 if (hres == S_OK)
620 ok_(__FILE__,line)( is_expected_variant( &result, expected ),
621 "got %s expected %s\n", variantstr(&result), variantstr(expected) );
622 ok_(__FILE__,line)( is_expected_variant( arg, &old_arg ), "Modified argument %s / %s\n",
623 variantstr(&old_arg), variantstr(arg));
624 VariantClear( &result );
625 }
626
627 static void test_var_call2( int line, HRESULT (WINAPI *func)(LPVARIANT,LPVARIANT,LPVARIANT),
628 VARIANT *left, VARIANT *right, VARIANT *expected )
629 {
630 VARIANT old_left = *left, old_right = *right;
631 VARIANT result;
632 HRESULT hres;
633
634 memset( &result, 0, sizeof(result) );
635 hres = func( left, right, &result );
636 ok_(__FILE__,line)( hres == S_OK, "wrong result %x\n", hres );
637 if (hres == S_OK)
638 ok_(__FILE__,line)( is_expected_variant( &result, expected ),
639 "got %s expected %s\n", variantstr(&result), variantstr(expected) );
640 ok_(__FILE__,line)( is_expected_variant( left, &old_left ), "Modified left argument %s / %s\n",
641 variantstr(&old_left), variantstr(left));
642 ok_(__FILE__,line)( is_expected_variant( right, &old_right ), "Modified right argument %s / %s\n",
643 variantstr(&old_right), variantstr(right));
644 VariantClear( &result );
645 }
646
647 static int strcmp_wa(const WCHAR *strw, const char *stra)
648 {
649 WCHAR buf[512];
650 MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(buf[0]));
651 return lstrcmpW(strw, buf);
652 }
653
654 #define test_bstr_var(a,b) _test_bstr_var(__LINE__,a,b)
655 static void _test_bstr_var(unsigned line, const VARIANT *v, const char *str)
656 {
657 ok_(__FILE__,line)(V_VT(v) == VT_BSTR, "unexpected vt=%d\n", V_VT(v));
658 if(V_VT(v) == VT_BSTR)
659 ok(!strcmp_wa(V_BSTR(v), str), "v=%s, expected %s\n", wine_dbgstr_w(V_BSTR(v)), str);
660 }
661
662 static void test_VariantInit(void)
663 {
664 VARIANT v;
665
666 memset(&v, -1, sizeof(v));
667 VariantInit(&v);
668 ok(V_VT(&v) == VT_EMPTY, "VariantInit() returned vt %d\n", V_VT(&v));
669 }
670
671 /* All possible combinations of extra V_VT() flags */
672 static const VARTYPE ExtraFlags[16] =
673 {
674 0,
675 VT_VECTOR,
676 VT_ARRAY,
677 VT_BYREF,
678 VT_RESERVED,
679 VT_VECTOR|VT_ARRAY,
680 VT_VECTOR|VT_BYREF,
681 VT_VECTOR|VT_RESERVED,
682 VT_VECTOR|VT_ARRAY|VT_BYREF,
683 VT_VECTOR|VT_ARRAY|VT_RESERVED,
684 VT_VECTOR|VT_BYREF|VT_RESERVED,
685 VT_VECTOR|VT_ARRAY|VT_BYREF|VT_RESERVED,
686 VT_ARRAY|VT_BYREF,
687 VT_ARRAY|VT_RESERVED,
688 VT_ARRAY|VT_BYREF|VT_RESERVED,
689 VT_BYREF|VT_RESERVED,
690 };
691
692 /* Determine if a vt is valid for VariantClear() */
693 static BOOL IsValidVariantClearVT(VARTYPE vt, VARTYPE extraFlags)
694 {
695 BOOL ret = FALSE;
696
697 /* Only the following flags/types are valid */
698 if ((vt <= VT_LPWSTR || vt == VT_RECORD || vt == VT_CLSID) &&
699 vt != (VARTYPE)15 &&
700 (vt < (VARTYPE)24 || vt > (VARTYPE)31) &&
701 (!(extraFlags & (VT_BYREF|VT_ARRAY)) || vt > VT_NULL) &&
702 (extraFlags == 0 || extraFlags == VT_BYREF || extraFlags == VT_ARRAY ||
703 extraFlags == (VT_ARRAY|VT_BYREF)))
704 ret = TRUE; /* ok */
705
706 if (!has_i8 && (vt == VT_I8 || vt == VT_UI8))
707 ret = FALSE; /* Old versions of oleaut32 */
708 return ret;
709 }
710
711 typedef struct
712 {
713 IUnknown IUnknown_iface;
714 LONG ref;
715 LONG events;
716 } test_VariantClearImpl;
717
718 static inline test_VariantClearImpl *impl_from_IUnknown(IUnknown *iface)
719 {
720 return CONTAINING_RECORD(iface, test_VariantClearImpl, IUnknown_iface);
721 }
722
723 static HRESULT WINAPI VC_QueryInterface(LPUNKNOWN iface,REFIID riid,LPVOID *ppobj)
724 {
725 test_VariantClearImpl *This = impl_from_IUnknown(iface);
726 This->events |= 0x1;
727 return E_NOINTERFACE;
728 }
729
730 static ULONG WINAPI VC_AddRef(LPUNKNOWN iface) {
731 test_VariantClearImpl *This = impl_from_IUnknown(iface);
732 This->events |= 0x2;
733 return InterlockedIncrement(&This->ref);
734 }
735
736 static ULONG WINAPI VC_Release(LPUNKNOWN iface) {
737 test_VariantClearImpl *This = impl_from_IUnknown(iface);
738 /* static class, won't be freed */
739 This->events |= 0x4;
740 return InterlockedDecrement(&This->ref);
741 }
742
743 static const IUnknownVtbl test_VariantClear_vtbl = {
744 VC_QueryInterface,
745 VC_AddRef,
746 VC_Release,
747 };
748
749 static test_VariantClearImpl test_myVariantClearImpl = {{&test_VariantClear_vtbl}, 1, 0};
750
751 static void test_VariantClear(void)
752 {
753 struct __tagBRECORD *rec;
754 IRecordInfoImpl *recinfo;
755 HRESULT hres;
756 VARIANTARG v;
757 VARIANT v2;
758 size_t i;
759 LONG i4;
760 IUnknown *punk;
761
762 /* Crashes: Native does not test input for NULL, so neither does Wine */
763 if (0)
764 VariantClear(NULL);
765
766 /* Only the type field is set, to VT_EMPTY */
767 V_VT(&v) = VT_UI4;
768 V_UI4(&v) = ~0u;
769 hres = VariantClear(&v);
770 ok((hres == S_OK && V_VT(&v) == VT_EMPTY),
771 "VariantClear: Type set to %d, res %08x\n", V_VT(&v), hres);
772 ok(V_UI4(&v) == ~0u, "VariantClear: Overwrote value\n");
773
774 /* Test all possible V_VT values.
775 * Also demonstrates that null pointers in 'v' are not dereferenced.
776 * Individual variant tests should test VariantClear() with non-NULL values.
777 */
778 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
779 {
780 VARTYPE vt;
781
782 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
783 {
784 HRESULT hExpected = DISP_E_BADVARTYPE;
785
786 SKIPTESTS(vt);
787
788 memset(&v, 0, sizeof(v));
789 V_VT(&v) = vt | ExtraFlags[i];
790
791 hres = VariantClear(&v);
792
793 if (IsValidVariantClearVT(vt, ExtraFlags[i]))
794 hExpected = S_OK;
795
796 ok(hres == hExpected, "VariantClear: expected 0x%X, got 0x%X for vt %d | 0x%X\n",
797 hExpected, hres, vt, ExtraFlags[i]);
798 }
799 }
800
801 /* Some BYREF tests with non-NULL ptrs */
802
803 /* VARIANT BYREF */
804 V_VT(&v2) = VT_I4;
805 V_I4(&v2) = 0x1234;
806 V_VT(&v) = VT_VARIANT | VT_BYREF;
807 V_VARIANTREF(&v) = &v2;
808
809 hres = VariantClear(&v);
810 ok(hres == S_OK, "ret %08x\n", hres);
811 ok(V_VT(&v) == 0, "vt %04x\n", V_VT(&v));
812 ok(V_VARIANTREF(&v) == &v2, "variant ref %p\n", V_VARIANTREF(&v2));
813 ok(V_VT(&v2) == VT_I4, "vt %04x\n", V_VT(&v2));
814 ok(V_I4(&v2) == 0x1234, "i4 %04x\n", V_I4(&v2));
815
816 /* I4 BYREF */
817 i4 = 0x4321;
818 V_VT(&v) = VT_I4 | VT_BYREF;
819 V_I4REF(&v) = &i4;
820
821 hres = VariantClear(&v);
822 ok(hres == S_OK, "ret %08x\n", hres);
823 ok(V_VT(&v) == 0, "vt %04x\n", V_VT(&v));
824 ok(V_I4REF(&v) == &i4, "i4 ref %p\n", V_I4REF(&v2));
825 ok(i4 == 0x4321, "i4 changed %08x\n", i4);
826
827
828 /* UNKNOWN */
829 V_VT(&v) = VT_UNKNOWN;
830 V_UNKNOWN(&v) = &test_myVariantClearImpl.IUnknown_iface;
831 test_myVariantClearImpl.events = 0;
832 hres = VariantClear(&v);
833 ok(hres == S_OK, "ret %08x\n", hres);
834 ok(V_VT(&v) == 0, "vt %04x\n", V_VT(&v));
835 ok(V_UNKNOWN(&v) == &test_myVariantClearImpl.IUnknown_iface, "unknown %p\n", V_UNKNOWN(&v));
836 /* Check that Release got called, but nothing else */
837 ok(test_myVariantClearImpl.events == 0x4, "Unexpected call. events %08x\n", test_myVariantClearImpl.events);
838
839 /* UNKNOWN BYREF */
840 punk = &test_myVariantClearImpl.IUnknown_iface;
841 V_VT(&v) = VT_UNKNOWN | VT_BYREF;
842 V_UNKNOWNREF(&v) = &punk;
843 test_myVariantClearImpl.events = 0;
844 hres = VariantClear(&v);
845 ok(hres == S_OK, "ret %08x\n", hres);
846 ok(V_VT(&v) == 0, "vt %04x\n", V_VT(&v));
847 ok(V_UNKNOWNREF(&v) == &punk, "unknown ref %p\n", V_UNKNOWNREF(&v));
848 /* Check that nothing got called */
849 ok(test_myVariantClearImpl.events == 0, "Unexpected call. events %08x\n", test_myVariantClearImpl.events);
850
851 /* DISPATCH */
852 V_VT(&v) = VT_DISPATCH;
853 V_DISPATCH(&v) = (IDispatch*)&test_myVariantClearImpl.IUnknown_iface;
854 test_myVariantClearImpl.events = 0;
855 hres = VariantClear(&v);
856 ok(hres == S_OK, "ret %08x\n", hres);
857 ok(V_VT(&v) == 0, "vt %04x\n", V_VT(&v));
858 ok(V_DISPATCH(&v) == (IDispatch*)&test_myVariantClearImpl.IUnknown_iface,
859 "dispatch %p\n", V_DISPATCH(&v));
860 /* Check that Release got called, but nothing else */
861 ok(test_myVariantClearImpl.events == 0x4, "Unexpected call. events %08x\n", test_myVariantClearImpl.events);
862
863 /* DISPATCH BYREF */
864 punk = &test_myVariantClearImpl.IUnknown_iface;
865 V_VT(&v) = VT_DISPATCH | VT_BYREF;
866 V_DISPATCHREF(&v) = (IDispatch**)&punk;
867 test_myVariantClearImpl.events = 0;
868 hres = VariantClear(&v);
869 ok(hres == S_OK, "ret %08x\n", hres);
870 ok(V_VT(&v) == 0, "vt %04x\n", V_VT(&v));
871 ok(V_DISPATCHREF(&v) == (IDispatch**)&punk, "dispatch ref %p\n", V_DISPATCHREF(&v));
872 /* Check that nothing got called */
873 ok(test_myVariantClearImpl.events == 0, "Unexpected call. events %08x\n", test_myVariantClearImpl.events);
874
875 /* RECORD */
876 recinfo = get_test_recordinfo();
877 V_VT(&v) = VT_RECORD;
878 rec = &V_UNION(&v, brecVal);
879 rec->pRecInfo = &recinfo->IRecordInfo_iface;
880 rec->pvRecord = (void*)0xdeadbeef;
881 recinfo->recordclear = 0;
882 recinfo->ref = 2;
883 recinfo->rec = rec;
884 hres = VariantClear(&v);
885 ok(hres == S_OK, "ret %08x\n", hres);
886 ok(rec->pvRecord == NULL, "got %p\n", rec->pvRecord);
887 ok(recinfo->recordclear == 1, "got %d\n", recinfo->recordclear);
888 ok(recinfo->ref == 1, "got %d\n", recinfo->ref);
889 IRecordInfo_Release(&recinfo->IRecordInfo_iface);
890 }
891
892 static void test_VariantCopy(void)
893 {
894 struct __tagBRECORD *rec;
895 IRecordInfoImpl *recinfo;
896 VARIANTARG vSrc, vDst;
897 VARTYPE vt;
898 size_t i;
899 HRESULT hres, hExpected;
900
901 /* Establish that the failure/other cases are dealt with. Individual tests
902 * for each type should verify that data is copied correctly, references
903 * are updated, etc.
904 */
905
906 /* vSrc == vDst */
907 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
908 {
909 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
910 {
911 SKIPTESTS(vt);
912
913 memset(&vSrc, 0, sizeof(vSrc));
914 V_VT(&vSrc) = vt | ExtraFlags[i];
915
916 hExpected = DISP_E_BADVARTYPE;
917 /* src is allowed to be a VT_CLSID */
918 if (vt != VT_CLSID && IsValidVariantClearVT(vt, ExtraFlags[i]))
919 hExpected = S_OK;
920
921 hres = VariantCopy(&vSrc, &vSrc);
922
923 ok(hres == hExpected,
924 "Copy(src==dst): expected 0x%X, got 0x%X for src==dest vt %d|0x%X\n",
925 hExpected, hres, vt, ExtraFlags[i]);
926 }
927 }
928
929 /* Test that if VariantClear() fails on dest, the function fails. This also
930 * shows that dest is in fact cleared and not just overwritten
931 */
932 memset(&vSrc, 0, sizeof(vSrc));
933 V_VT(&vSrc) = VT_UI1;
934
935 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
936 {
937 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
938 {
939 SKIPTESTS(vt);
940
941 hExpected = DISP_E_BADVARTYPE;
942
943 memset(&vDst, 0, sizeof(vDst));
944 V_VT(&vDst) = vt | ExtraFlags[i];
945
946 if (IsValidVariantClearVT(vt, ExtraFlags[i]))
947 hExpected = S_OK;
948
949 hres = VariantCopy(&vDst, &vSrc);
950
951 ok(hres == hExpected,
952 "Copy(bad dst): expected 0x%X, got 0x%X for dest vt %d|0x%X\n",
953 hExpected, hres, vt, ExtraFlags[i]);
954 if (hres == S_OK)
955 ok(V_VT(&vDst) == VT_UI1,
956 "Copy(bad dst): expected vt = VT_UI1, got %d\n", V_VT(&vDst));
957 }
958 }
959
960 /* Test that VariantClear() checks vSrc for validity before copying */
961 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
962 {
963 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
964 {
965 SKIPTESTS(vt);
966
967 hExpected = DISP_E_BADVARTYPE;
968
969 memset(&vDst, 0, sizeof(vDst));
970 V_VT(&vDst) = VT_EMPTY;
971
972 memset(&vSrc, 0, sizeof(vSrc));
973 V_VT(&vSrc) = vt | ExtraFlags[i];
974
975 /* src is allowed to be a VT_CLSID */
976 if (vt != VT_CLSID && IsValidVariantClearVT(vt, ExtraFlags[i]))
977 hExpected = S_OK;
978
979 hres = VariantCopy(&vDst, &vSrc);
980
981 ok(hres == hExpected,
982 "Copy(bad src): expected 0x%X, got 0x%X for src vt %d|0x%X\n",
983 hExpected, hres, vt, ExtraFlags[i]);
984 if (hres == S_OK)
985 {
986 ok(V_VT(&vDst) == (vt|ExtraFlags[i]),
987 "Copy(bad src): expected vt = %d, got %d\n",
988 vt | ExtraFlags[i], V_VT(&vDst));
989 VariantClear(&vDst);
990 }
991 }
992 }
993
994 /* Test that copying a NULL BSTR results in an empty BSTR */
995 memset(&vDst, 0, sizeof(vDst));
996 V_VT(&vDst) = VT_EMPTY;
997 memset(&vSrc, 0, sizeof(vSrc));
998 V_VT(&vSrc) = VT_BSTR;
999 hres = VariantCopy(&vDst, &vSrc);
1000 ok(hres == S_OK, "Copy(NULL BSTR): Failed to copy a NULL BSTR\n");
1001 if (hres == S_OK)
1002 {
1003 ok((V_VT(&vDst) == VT_BSTR) && V_BSTR(&vDst),
1004 "Copy(NULL BSTR): should have non-NULL result\n");
1005 if ((V_VT(&vDst) == VT_BSTR) && V_BSTR(&vDst))
1006 {
1007 ok(*V_BSTR(&vDst) == 0, "Copy(NULL BSTR): result not empty\n");
1008 }
1009 VariantClear(&vDst);
1010 }
1011
1012 /* copy RECORD */
1013 recinfo = get_test_recordinfo();
1014
1015 memset(&vDst, 0, sizeof(vDst));
1016 V_VT(&vDst) = VT_EMPTY;
1017
1018 V_VT(&vSrc) = VT_RECORD;
1019 rec = &V_UNION(&vSrc, brecVal);
1020 rec->pRecInfo = &recinfo->IRecordInfo_iface;
1021 rec->pvRecord = (void*)0xdeadbeef;
1022
1023 recinfo->recordclear = 0;
1024 recinfo->recordcopy = 0;
1025 recinfo->getsize = 0;
1026 recinfo->rec = rec;
1027 hres = VariantCopy(&vDst, &vSrc);
1028 ok(hres == S_OK, "ret %08x\n", hres);
1029
1030 rec = &V_UNION(&vDst, brecVal);
1031 ok(rec->pvRecord != (void*)0xdeadbeef && rec->pvRecord != NULL, "got %p\n", rec->pvRecord);
1032 ok(rec->pRecInfo == &recinfo->IRecordInfo_iface, "got %p\n", rec->pRecInfo);
1033 ok(recinfo->getsize == 1, "got %d\n", recinfo->recordclear);
1034 ok(recinfo->recordcopy == 1, "got %d\n", recinfo->recordclear);
1035
1036 VariantClear(&vDst);
1037 VariantClear(&vSrc);
1038 }
1039
1040 /* Determine if a vt is valid for VariantCopyInd() */
1041 static BOOL IsValidVariantCopyIndVT(VARTYPE vt, VARTYPE extraFlags)
1042 {
1043 BOOL ret = FALSE;
1044
1045 if ((extraFlags & VT_ARRAY) ||
1046 (vt > VT_NULL && vt != (VARTYPE)15 && vt < VT_VOID &&
1047 !(extraFlags & (VT_VECTOR|VT_RESERVED))))
1048 {
1049 ret = TRUE; /* ok */
1050 }
1051 return ret;
1052 }
1053
1054 static void test_VariantCopyInd(void)
1055 {
1056 VARIANTARG vSrc, vDst, vRef, vRef2;
1057 VARTYPE vt;
1058 size_t i;
1059 BYTE buffer[64];
1060 HRESULT hres, hExpected;
1061
1062 memset(buffer, 0, sizeof(buffer));
1063
1064 /* vSrc == vDst */
1065 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
1066 {
1067 if (ExtraFlags[i] & VT_ARRAY)
1068 continue; /* Native crashes on NULL safearray */
1069
1070 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
1071 {
1072 SKIPTESTS(vt);
1073
1074 memset(&vSrc, 0, sizeof(vSrc));
1075 V_VT(&vSrc) = vt | ExtraFlags[i];
1076
1077 hExpected = DISP_E_BADVARTYPE;
1078 if (!(ExtraFlags[i] & VT_BYREF))
1079 {
1080 /* if src is not by-reference, acts as VariantCopy() */
1081 if (vt != VT_CLSID && IsValidVariantClearVT(vt, ExtraFlags[i]))
1082 hExpected = S_OK;
1083 }
1084 else
1085 {
1086 if (vt == VT_SAFEARRAY || vt == VT_BSTR || vt == VT_UNKNOWN ||
1087 vt == VT_DISPATCH || vt == VT_RECORD)
1088 continue; /* Need valid ptrs for deep copies */
1089
1090 V_BYREF(&vSrc) = &buffer;
1091 hExpected = E_INVALIDARG;
1092
1093 if ((vt == VT_I8 || vt == VT_UI8) &&
1094 ExtraFlags[i] == VT_BYREF)
1095 {
1096 if (has_i8)
1097 hExpected = S_OK; /* Only valid if I8 is a known type */
1098 }
1099 else if (IsValidVariantCopyIndVT(vt, ExtraFlags[i]))
1100 hExpected = S_OK;
1101 }
1102
1103 hres = VariantCopyInd(&vSrc, &vSrc);
1104
1105 ok(hres == hExpected,
1106 "CopyInd(src==dst): expected 0x%X, got 0x%X for src==dst vt %d|0x%X\n",
1107 hExpected, hres, vt, ExtraFlags[i]);
1108 }
1109 }
1110
1111 /* Bad dest */
1112 memset(&vSrc, 0, sizeof(vSrc));
1113 V_VT(&vSrc) = VT_UI1|VT_BYREF;
1114 V_BYREF(&vSrc) = &buffer;
1115
1116 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
1117 {
1118 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
1119 {
1120 SKIPTESTS(vt);
1121
1122 memset(&vDst, 0, sizeof(vDst));
1123 V_VT(&vDst) = vt | ExtraFlags[i];
1124
1125 hExpected = DISP_E_BADVARTYPE;
1126
1127 if (IsValidVariantClearVT(vt, ExtraFlags[i]))
1128 hExpected = S_OK;
1129
1130 hres = VariantCopyInd(&vDst, &vSrc);
1131
1132 ok(hres == hExpected,
1133 "CopyInd(bad dst): expected 0x%X, got 0x%X for dst vt %d|0x%X\n",
1134 hExpected, hres, vt, ExtraFlags[i]);
1135 if (hres == S_OK)
1136 ok(V_VT(&vDst) == VT_UI1,
1137 "CopyInd(bad dst): expected vt = VT_UI1, got %d\n", V_VT(&vDst));
1138 }
1139 }
1140
1141 /* bad src */
1142 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
1143 {
1144 if (ExtraFlags[i] & VT_ARRAY)
1145 continue; /* Native crashes on NULL safearray */
1146
1147 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
1148 {
1149 SKIPTESTS(vt);
1150
1151 memset(&vDst, 0, sizeof(vDst));
1152 V_VT(&vDst) = VT_EMPTY;
1153
1154 memset(&vSrc, 0, sizeof(vSrc));
1155 V_VT(&vSrc) = vt | ExtraFlags[i];
1156
1157 hExpected = DISP_E_BADVARTYPE;
1158 if (!(ExtraFlags[i] & VT_BYREF))
1159 {
1160 /* if src is not by-reference, acts as VariantCopy() */
1161 if (vt != VT_CLSID && IsValidVariantClearVT(vt, ExtraFlags[i]))
1162 hExpected = S_OK;
1163 }
1164 else
1165 {
1166 if (vt == VT_SAFEARRAY || vt == VT_BSTR || vt == VT_UNKNOWN ||
1167 vt == VT_DISPATCH || vt == VT_RECORD)
1168 continue; /* Need valid ptrs for deep copies, see vartype.c */
1169
1170 V_BYREF(&vSrc) = &buffer;
1171
1172 hExpected = E_INVALIDARG;
1173
1174 if ((vt == VT_I8 || vt == VT_UI8) &&
1175 ExtraFlags[i] == VT_BYREF)
1176 {
1177 if (has_i8)
1178 hExpected = S_OK; /* Only valid if I8 is a known type */
1179 }
1180 else if (IsValidVariantCopyIndVT(vt, ExtraFlags[i]))
1181 hExpected = S_OK;
1182 }
1183
1184 hres = VariantCopyInd(&vDst, &vSrc);
1185
1186 ok(hres == hExpected,
1187 "CopyInd(bad src): expected 0x%X, got 0x%X for src vt %d|0x%X\n",
1188 hExpected, hres, vt, ExtraFlags[i]);
1189 if (hres == S_OK)
1190 {
1191 if (vt == VT_VARIANT && ExtraFlags[i] == VT_BYREF)
1192 {
1193 /* Type of vDst should be the type of the referenced variant.
1194 * Since we set the buffer to all zeros, its type should be
1195 * VT_EMPTY.
1196 */
1197 ok(V_VT(&vDst) == VT_EMPTY,
1198 "CopyInd(bad src): expected dst vt = VT_EMPTY, got %d|0x%X\n",
1199 V_VT(&vDst) & VT_TYPEMASK, V_VT(&vDst) & ~VT_TYPEMASK);
1200 }
1201 else
1202 {
1203 ok(V_VT(&vDst) == (vt|(ExtraFlags[i] & ~VT_BYREF)),
1204 "CopyInd(bad src): expected dst vt = %d|0x%X, got %d|0x%X\n",
1205 vt, ExtraFlags[i] & ~VT_BYREF,
1206 V_VT(&vDst) & VT_TYPEMASK, V_VT(&vDst) & ~VT_TYPEMASK);
1207 }
1208 VariantClear(&vDst);
1209 }
1210 }
1211 }
1212
1213 /* By-reference variants are dereferenced */
1214 V_VT(&vRef) = VT_UI1;
1215 V_UI1(&vRef) = 0x77;
1216 V_VT(&vSrc) = VT_VARIANT|VT_BYREF;
1217 V_VARIANTREF(&vSrc) = &vRef;
1218 VariantInit(&vDst);
1219
1220 hres = VariantCopyInd(&vDst, &vSrc);
1221 ok(hres == S_OK, "VariantCopyInd failed: 0x%08x\n", hres);
1222 ok(V_VT(&vDst) == VT_UI1 && V_UI1(&vDst) == 0x77,
1223 "CopyInd(deref): expected dst vt = VT_UI1, val 0x77, got %d|0x%X, 0x%2X\n",
1224 V_VT(&vDst) & VT_TYPEMASK, V_VT(&vDst) & ~VT_TYPEMASK, V_UI1(&vDst));
1225
1226 /* By-reference variant to a by-reference type succeeds */
1227 V_VT(&vRef) = VT_UI1|VT_BYREF;
1228 V_UI1REF(&vRef) = buffer; buffer[0] = 0x88;
1229 V_VT(&vSrc) = VT_VARIANT|VT_BYREF;
1230 V_VARIANTREF(&vSrc) = &vRef;
1231 VariantInit(&vDst);
1232
1233 hres = VariantCopyInd(&vDst, &vSrc);
1234 ok(hres == S_OK, "VariantCopyInd failed: 0x%08x\n", hres);
1235 ok(V_VT(&vDst) == VT_UI1 && V_UI1(&vDst) == 0x88,
1236 "CopyInd(deref): expected dst vt = VT_UI1, val 0x77, got %d|0x%X, 0x%2X\n",
1237 V_VT(&vDst) & VT_TYPEMASK, V_VT(&vDst) & ~VT_TYPEMASK, V_UI1(&vDst));
1238
1239 /* But a by-reference variant to a by-reference variant fails */
1240 V_VT(&vRef2) = VT_UI1;
1241 V_UI1(&vRef2) = 0x77;
1242 V_VT(&vRef) = VT_VARIANT|VT_BYREF;
1243 V_VARIANTREF(&vRef) = &vRef2;
1244 V_VT(&vSrc) = VT_VARIANT|VT_BYREF;
1245 V_VARIANTREF(&vSrc) = &vRef;
1246 VariantInit(&vDst);
1247
1248 hres = VariantCopyInd(&vDst, &vSrc);
1249 ok(hres == E_INVALIDARG,
1250 "CopyInd(ref->ref): expected E_INVALIDARG, got 0x%08x\n", hres);
1251 }
1252
1253 static HRESULT (WINAPI *pVarParseNumFromStr)(OLECHAR*,LCID,ULONG,NUMPARSE*,BYTE*);
1254
1255 /* Macros for converting and testing the result of VarParseNumFromStr */
1256 #define FAILDIG 255
1257
1258 static HRESULT convert_str( const char *str, INT dig, ULONG flags,
1259 NUMPARSE *np, BYTE rgb[128], LCID lcid )
1260 {
1261 OLECHAR buff[128];
1262 MultiByteToWideChar( CP_ACP,0, str, -1, buff, sizeof(buff)/sizeof(WCHAR) );
1263 memset( rgb, FAILDIG, 128 );
1264 memset( np, 255, sizeof(*np) );
1265 np->cDig = dig;
1266 np->dwInFlags = flags;
1267 return pVarParseNumFromStr( buff, lcid, LOCALE_NOUSEROVERRIDE, np, rgb);
1268 }
1269
1270 static void expect_NumFromStr( int line, HRESULT hres, NUMPARSE *np, INT a, ULONG b, ULONG c,
1271 INT d, INT e, INT f )
1272 {
1273 if (hres == (HRESULT)S_OK)
1274 {
1275 ok_(__FILE__,line)(np->cDig == a, "Expected cDig = %d, got %d\n", a, np->cDig);
1276 ok_(__FILE__,line)(np->dwInFlags == b, "Expected dwInFlags = 0x%x, got 0x%x\n", b, np->dwInFlags);
1277 ok_(__FILE__,line)(np->dwOutFlags == c, "Expected dwOutFlags = 0x%x, got 0x%x\n", c, np->dwOutFlags);
1278 ok_(__FILE__,line)(np->cchUsed == d, "Expected cchUsed = %d, got %d\n", d, np->cchUsed);
1279 ok_(__FILE__,line)(np->nBaseShift == e, "Expected nBaseShift = %d, got %d\n", e, np->nBaseShift);
1280 ok_(__FILE__,line)(np->nPwr10 == f, "Expected nPwr10 = %d, got %d\n", f, np->nPwr10);
1281 }
1282 }
1283
1284 #define CONVERTN(str,dig,flags) hres = convert_str( str, dig, flags, &np, rgb, lcid )
1285 #define CONVERT(str,flags) CONVERTN(str,sizeof(rgb),flags)
1286 #define EXPECT(a,b,c,d,e,f) expect_NumFromStr( __LINE__, hres, &np, a, b, c, d, e, f )
1287 #define EXPECTRGB(a,b) ok(rgb[a] == b, "Digit[%d], expected %d, got %d\n", a, b, rgb[a])
1288 #define EXPECTFAIL ok(hres == (HRESULT)DISP_E_TYPEMISMATCH, "Call succeeded, hres = %08x\n", hres)
1289 #define EXPECT2(a,b) EXPECTRGB(0,a); EXPECTRGB(1,b)
1290
1291 static void test_VarParseNumFromStr(void)
1292 {
1293 HRESULT hres;
1294 /* Ensure all tests are using the same locale characters for '$', ',' etc */
1295 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
1296 NUMPARSE np;
1297 BYTE rgb[128];
1298
1299 /** No flags **/
1300
1301 CHECKPTR(VarParseNumFromStr);
1302
1303 /* Consume a single digit */
1304 CONVERT("7", 0);
1305 EXPECT(1,0,0,1,0,0);
1306 EXPECT2(7,FAILDIG);
1307
1308 /* cDig is not literal digits - zeros are suppressed and nPwr10 is increased */
1309 CONVERT("10", 0);
1310 EXPECT(1,0,0,2,0,1);
1311 /* Note: Win32 writes the trailing zeros if they are within cDig's limits,
1312 * but then excludes them from the returned cDig count.
1313 * In our implementation we don't bother writing them at all.
1314 */
1315 EXPECTRGB(0, 1);
1316
1317 /* if cDig is too small and numbers follow, sets INEXACT */
1318 CONVERTN("11",1, 0);
1319 EXPECT(1,0,NUMPRS_INEXACT,2,0,1);
1320 EXPECT2(1,FAILDIG);
1321
1322 /* Strips leading zeros */
1323 CONVERT("01", 0);
1324 EXPECT(1,0,0,2,0,0);
1325 EXPECT2(1,FAILDIG);
1326
1327 /* Strips leading zeros */
1328 CONVERTN("01",1, 0);
1329 EXPECT(1,0,0,2,0,0);
1330 EXPECT2(1,FAILDIG);
1331
1332
1333 /* Fails on non digits */
1334 CONVERT("a", 0);
1335 EXPECTFAIL;
1336 EXPECTRGB(0,FAILDIG);
1337
1338 /** NUMPRS_LEADING_WHITE/NUMPRS_TRAILING_WHITE **/
1339
1340 /* Without flag, fails on whitespace */
1341 CONVERT(" 0", 0);
1342 EXPECTFAIL;
1343 EXPECTRGB(0,FAILDIG);
1344
1345
1346 /* With flag, consumes whitespace */
1347 CONVERT(" 0", NUMPRS_LEADING_WHITE);
1348 EXPECT(1,NUMPRS_LEADING_WHITE,NUMPRS_LEADING_WHITE,2,0,0);
1349 EXPECT2(0,FAILDIG);
1350
1351 /* Test TAB once, then assume it acts as space for all cases */
1352 CONVERT("\t0", NUMPRS_LEADING_WHITE);
1353 EXPECT(1,NUMPRS_LEADING_WHITE,NUMPRS_LEADING_WHITE,2,0,0);
1354 EXPECT2(0,FAILDIG);
1355
1356
1357 /* Doesn't pick up trailing whitespace without flag */
1358 CONVERT("0 ", 0);
1359 EXPECT(1,0,0,1,0,0);
1360 EXPECT2(0,FAILDIG);
1361
1362 /* With flag, consumes trailing whitespace */
1363 CONVERT("0 ", NUMPRS_TRAILING_WHITE);
1364 EXPECT(1,NUMPRS_TRAILING_WHITE,NUMPRS_TRAILING_WHITE,2,0,0);
1365 EXPECT2(0,FAILDIG);
1366
1367 /* Leading flag only consumes leading */
1368 CONVERT(" 0 ", NUMPRS_LEADING_WHITE);
1369 EXPECT(1,NUMPRS_LEADING_WHITE,NUMPRS_LEADING_WHITE,2,0,0);
1370 EXPECT2(0,FAILDIG);
1371
1372 /* Both flags consumes both */
1373 CONVERT(" 0 ", NUMPRS_LEADING_WHITE|NUMPRS_TRAILING_WHITE);
1374 EXPECT(1,NUMPRS_LEADING_WHITE|NUMPRS_TRAILING_WHITE,NUMPRS_LEADING_WHITE|NUMPRS_TRAILING_WHITE,3,0,0);
1375 EXPECT2(0,FAILDIG);
1376
1377 /** NUMPRS_LEADING_PLUS/NUMPRS_TRAILING_PLUS **/
1378
1379 /* Without flag, fails on + */
1380 CONVERT("+0", 0);
1381 EXPECTFAIL;
1382 EXPECTRGB(0,FAILDIG);
1383
1384 /* With flag, consumes + */
1385 CONVERT("+0", NUMPRS_LEADING_PLUS);
1386 EXPECT(1,NUMPRS_LEADING_PLUS,NUMPRS_LEADING_PLUS,2,0,0);
1387 EXPECT2(0,FAILDIG);
1388
1389 /* Without flag, doesn't consume trailing + */
1390 CONVERT("0+", 0);
1391 EXPECT(1,0,0,1,0,0);
1392 EXPECT2(0,FAILDIG);
1393
1394 /* With flag, consumes trailing + */
1395 CONVERT("0+", NUMPRS_TRAILING_PLUS);
1396 EXPECT(1,NUMPRS_TRAILING_PLUS,NUMPRS_TRAILING_PLUS,2,0,0);
1397 EXPECT2(0,FAILDIG);
1398
1399 /* With leading flag, doesn't consume trailing + */
1400 CONVERT("+0+", NUMPRS_LEADING_PLUS);
1401 EXPECT(1,NUMPRS_LEADING_PLUS,NUMPRS_LEADING_PLUS,2,0,0);
1402 EXPECT2(0,FAILDIG);
1403
1404 /* Trailing + doesn't get consumed if we specify both (unlike whitespace) */
1405 CONVERT("+0+", NUMPRS_LEADING_PLUS|NUMPRS_TRAILING_PLUS);
1406 EXPECT(1,NUMPRS_LEADING_PLUS|NUMPRS_TRAILING_PLUS,NUMPRS_LEADING_PLUS,2,0,0);
1407 EXPECT2(0,FAILDIG);
1408
1409 /** NUMPRS_LEADING_MINUS/NUMPRS_TRAILING_MINUS **/
1410
1411 /* Without flag, fails on - */
1412 CONVERT("-0", 0);
1413 EXPECTFAIL;
1414 EXPECTRGB(0,FAILDIG);
1415
1416 /* With flag, consumes - */
1417 CONVERT("-0", NUMPRS_LEADING_MINUS);
1418 EXPECT(1,NUMPRS_LEADING_MINUS,NUMPRS_NEG|NUMPRS_LEADING_MINUS,2,0,0);
1419 EXPECT2(0,FAILDIG);
1420
1421 /* Without flag, doesn't consume trailing - */
1422 CONVERT("0-", 0);
1423 EXPECT(1,0,0,1,0,0);
1424 EXPECT2(0,FAILDIG);
1425
1426 /* With flag, consumes trailing - */
1427 CONVERT("0-", NUMPRS_TRAILING_MINUS);
1428 EXPECT(1,NUMPRS_TRAILING_MINUS,NUMPRS_NEG|NUMPRS_TRAILING_MINUS,2,0,0);
1429 EXPECT2(0,FAILDIG);
1430
1431 /* With leading flag, doesn't consume trailing - */
1432 CONVERT("-0-", NUMPRS_LEADING_MINUS);
1433 EXPECT(1,NUMPRS_LEADING_MINUS,NUMPRS_NEG|NUMPRS_LEADING_MINUS,2,0,0);
1434 EXPECT2(0,FAILDIG);
1435
1436 /* Trailing - doesn't get consumed if we specify both (unlike whitespace) */
1437 CONVERT("-0-", NUMPRS_LEADING_MINUS|NUMPRS_TRAILING_MINUS);
1438 EXPECT(1,NUMPRS_LEADING_MINUS|NUMPRS_TRAILING_MINUS,NUMPRS_NEG|NUMPRS_LEADING_MINUS,2,0,0);
1439 EXPECT2(0,FAILDIG);
1440
1441 /** NUMPRS_HEX_OCT **/
1442
1443 /* Could be hex, octal or decimal - With flag reads as decimal */
1444 CONVERT("0", NUMPRS_HEX_OCT);
1445 EXPECT(1,NUMPRS_HEX_OCT,0,1,0,0);
1446 EXPECT2(0,FAILDIG);
1447
1448 /* Doesn't recognise hex in .asm syntax */
1449 CONVERT("0h", NUMPRS_HEX_OCT);
1450 EXPECT(1,NUMPRS_HEX_OCT,0,1,0,0);
1451 EXPECT2(0,FAILDIG);
1452
1453 /* Doesn't fail with valid leading string but no digits */
1454 CONVERT("0x", NUMPRS_HEX_OCT);
1455 EXPECT(1,NUMPRS_HEX_OCT,0,1,0,0);
1456 EXPECT2(0,FAILDIG);
1457
1458 /* Doesn't recognise hex format numbers at all! */
1459 CONVERT("0x0", NUMPRS_HEX_OCT);
1460 EXPECT(1,NUMPRS_HEX_OCT,0,1,0,0);
1461 EXPECT2(0,FAILDIG);
1462
1463 /* Doesn't recognise plain hex digits either */
1464 CONVERT("FE", NUMPRS_HEX_OCT);
1465 EXPECTFAIL;
1466 EXPECTRGB(0,FAILDIG);
1467
1468 /* Octal */
1469 CONVERT("0100", NUMPRS_HEX_OCT);
1470 EXPECT(1,NUMPRS_HEX_OCT,0,4,0,2);
1471 EXPECTRGB(0,1);
1472 EXPECTRGB(1,0);
1473 EXPECTRGB(2,0);
1474 EXPECTRGB(3,FAILDIG);
1475
1476 /* VB hex */
1477 CONVERT("&HF800", NUMPRS_HEX_OCT);
1478 EXPECT(4,NUMPRS_HEX_OCT,0x40,6,4,0);
1479 EXPECTRGB(0,15);
1480 EXPECTRGB(1,8);
1481 EXPECTRGB(2,0);
1482 EXPECTRGB(3,0);
1483 EXPECTRGB(4,FAILDIG);
1484
1485 /* VB hex lower case and leading zero */
1486 CONVERT("&h0abcdef", NUMPRS_HEX_OCT);
1487 EXPECT(6,NUMPRS_HEX_OCT,0x40,9,4,0);
1488 EXPECTRGB(0,10);
1489 EXPECTRGB(1,11);
1490 EXPECTRGB(2,12);
1491 EXPECTRGB(3,13);
1492 EXPECTRGB(4,14);
1493 EXPECTRGB(5,15);
1494 EXPECTRGB(6,FAILDIG);
1495
1496 /* VB oct */
1497 CONVERT("&O300", NUMPRS_HEX_OCT);
1498 EXPECT(3,NUMPRS_HEX_OCT,0x40,5,3,0);
1499 EXPECTRGB(0,3);
1500 EXPECTRGB(1,0);
1501 EXPECTRGB(2,0);
1502 EXPECTRGB(3,FAILDIG);
1503
1504 /* VB oct lower case and leading zero */
1505 CONVERT("&o0777", NUMPRS_HEX_OCT);
1506 EXPECT(3,NUMPRS_HEX_OCT,0x40,6,3,0);
1507 EXPECTRGB(0,7);
1508 EXPECTRGB(1,7);
1509 EXPECTRGB(2,7);
1510 EXPECTRGB(3,FAILDIG);
1511
1512 /* VB oct char bigger than 7 */
1513 CONVERT("&o128", NUMPRS_HEX_OCT);
1514 EXPECT(2,NUMPRS_HEX_OCT,0x40,4,3,0);
1515 EXPECTRGB(0,1);
1516 EXPECTRGB(1,2);
1517 EXPECTRGB(3,FAILDIG);
1518
1519 /** NUMPRS_PARENS **/
1520
1521 /* Empty parens = error */
1522 CONVERT("()", NUMPRS_PARENS);
1523 EXPECTFAIL;
1524 EXPECTRGB(0,FAILDIG);
1525
1526 /* With flag, trailing parens not consumed */
1527 CONVERT("0()", NUMPRS_PARENS);
1528 EXPECT(1,NUMPRS_PARENS,0,1,0,0);
1529 EXPECT2(0,FAILDIG);
1530
1531 /* With flag, Number in parens made negative and parens consumed */
1532 CONVERT("(0)", NUMPRS_PARENS);
1533 EXPECT(1,NUMPRS_PARENS,NUMPRS_NEG|NUMPRS_PARENS,3,0,0);
1534 EXPECT2(0,FAILDIG);
1535
1536 /** NUMPRS_THOUSANDS **/
1537
1538 /* With flag, thousands sep. not needed */
1539 CONVERT("0", NUMPRS_THOUSANDS);
1540 EXPECT(1,NUMPRS_THOUSANDS,0,1,0,0);
1541 EXPECT2(0,FAILDIG);
1542
1543 /* With flag, thousands sep. and following digits consumed */
1544 CONVERT("1,000", NUMPRS_THOUSANDS);
1545 EXPECT(1,NUMPRS_THOUSANDS,NUMPRS_THOUSANDS,5,0,3);
1546 EXPECTRGB(0,1);
1547
1548 /* With flag and decimal point, thousands sep. but not decimals consumed */
1549 CONVERT("1,000.0", NUMPRS_THOUSANDS);
1550 EXPECT(1,NUMPRS_THOUSANDS,NUMPRS_THOUSANDS,5,0,3);
1551 EXPECTRGB(0,1);
1552
1553 /** NUMPRS_CURRENCY **/
1554
1555 /* Without flag, chokes on currency sign */
1556 CONVERT("$11", 0);
1557 EXPECTFAIL;
1558 EXPECTRGB(0,FAILDIG);
1559
1560 /* With flag, consumes currency sign */
1561 CONVERT("$11", NUMPRS_CURRENCY);
1562 EXPECT(2,NUMPRS_CURRENCY,NUMPRS_CURRENCY,3,0,0);
1563 EXPECT2(1,1);
1564 EXPECTRGB(2,FAILDIG);
1565
1566 /* With flag only, doesn't consume decimal point */
1567 CONVERT("$11.1", NUMPRS_CURRENCY);
1568 EXPECT(2,NUMPRS_CURRENCY,NUMPRS_CURRENCY,3,0,0);
1569 EXPECT2(1,1);
1570 EXPECTRGB(2,FAILDIG);
1571
1572 /* With flag and decimal flag, consumes decimal point and following digits */
1573 CONVERT("$11.1", NUMPRS_CURRENCY|NUMPRS_DECIMAL);
1574 EXPECT(3,NUMPRS_CURRENCY|NUMPRS_DECIMAL,NUMPRS_CURRENCY|NUMPRS_DECIMAL,5,0,-1);
1575 EXPECT2(1,1);
1576 EXPECTRGB(2,1);
1577 EXPECTRGB(3,FAILDIG);
1578
1579 /* Thousands flag can only be used with currency */
1580 CONVERT("$1,234", NUMPRS_CURRENCY|NUMPRS_THOUSANDS);
1581 EXPECT(4,NUMPRS_CURRENCY|NUMPRS_THOUSANDS,NUMPRS_CURRENCY|NUMPRS_THOUSANDS,6,0,0);
1582 EXPECT2(1,2);
1583 EXPECTRGB(2,3);
1584 EXPECTRGB(3,4);
1585 EXPECTRGB(4,FAILDIG);
1586
1587 /** NUMPRS_DECIMAL **/
1588
1589 /* With flag, consumes decimal point */
1590 CONVERT("1.1", NUMPRS_DECIMAL);
1591 EXPECT(2,NUMPRS_DECIMAL,NUMPRS_DECIMAL,3,0,-1);
1592 EXPECT2(1,1);
1593 EXPECTRGB(2,FAILDIG);
1594
1595 /* With flag, consumes decimal point. Skipping the decimal part is not an error */
1596 CONVERT("1.", NUMPRS_DECIMAL);
1597 EXPECT(1,NUMPRS_DECIMAL,NUMPRS_DECIMAL,2,0,0);
1598 EXPECT2(1,FAILDIG);
1599
1600 /* Consumes only one decimal point */
1601 CONVERT("1.1.", NUMPRS_DECIMAL);
1602 EXPECT(2,NUMPRS_DECIMAL,NUMPRS_DECIMAL,3,0,-1);
1603 EXPECT2(1,1);
1604 EXPECTRGB(2,FAILDIG);
1605
1606 /** NUMPRS_EXPONENT **/
1607
1608 /* Without flag, doesn't consume exponent */
1609 CONVERT("1e1", 0);
1610 EXPECT(1,0,0,1,0,0);
1611 EXPECT2(1,FAILDIG);
1612
1613 /* With flag, consumes exponent */
1614 CONVERT("1e1", NUMPRS_EXPONENT);
1615 EXPECT(1,NUMPRS_EXPONENT,NUMPRS_EXPONENT,3,0,1);
1616 EXPECT2(1,FAILDIG);
1617
1618 /* Negative exponents are accepted without flags */
1619 CONVERT("1e-1", NUMPRS_EXPONENT);
1620 EXPECT(1,NUMPRS_EXPONENT,NUMPRS_EXPONENT,4,0,-1);
1621 EXPECT2(1,FAILDIG);
1622
1623 /* As are positive exponents and leading exponent 0s */
1624 CONVERT("1e+01", NUMPRS_EXPONENT);
1625 EXPECT(1,NUMPRS_EXPONENT,NUMPRS_EXPONENT,5,0,1);
1626 EXPECT2(1,FAILDIG);
1627
1628 /* The same for zero exponents */
1629 CONVERT("1e0", NUMPRS_EXPONENT);
1630 EXPECT(1,NUMPRS_EXPONENT,NUMPRS_EXPONENT,3,0,0);
1631 EXPECT2(1,FAILDIG);
1632
1633 /* Sign on a zero exponent doesn't matter */
1634 CONVERT("1e+0", NUMPRS_EXPONENT);
1635 EXPECT(1,NUMPRS_EXPONENT,NUMPRS_EXPONENT,4,0,0);
1636 EXPECT2(1,FAILDIG);
1637
1638 CONVERT("1e-0", NUMPRS_EXPONENT);
1639 EXPECT(1,NUMPRS_EXPONENT,NUMPRS_EXPONENT,4,0,0);
1640 EXPECT2(1,FAILDIG);
1641
1642 /* Doesn't consume a real number exponent */
1643 CONVERT("1e1.", NUMPRS_EXPONENT);
1644 EXPECT(1,NUMPRS_EXPONENT,NUMPRS_EXPONENT,3,0,1);
1645 EXPECT2(1,FAILDIG);
1646
1647 /* Powers of 10 are calculated from the position of any decimal point */
1648 CONVERT("1.5e20", NUMPRS_EXPONENT|NUMPRS_DECIMAL);
1649 EXPECT(2,NUMPRS_EXPONENT|NUMPRS_DECIMAL,NUMPRS_EXPONENT|NUMPRS_DECIMAL,6,0,19);
1650 EXPECT2(1,5);
1651
1652 CONVERT("1.5e-20", NUMPRS_EXPONENT|NUMPRS_DECIMAL);
1653 EXPECT(2,NUMPRS_EXPONENT|NUMPRS_DECIMAL,NUMPRS_EXPONENT|NUMPRS_DECIMAL,7,0,-21);
1654 EXPECT2(1,5);
1655
1656 /** NUMPRS_USE_ALL **/
1657
1658 /* Flag expects all digits */
1659 CONVERT("0", NUMPRS_USE_ALL);
1660 EXPECT(1,NUMPRS_USE_ALL,0,1,0,0);
1661 EXPECT2(0,FAILDIG);
1662
1663 /* Rejects anything trailing */
1664 CONVERT("0 ", NUMPRS_USE_ALL);
1665 EXPECTFAIL;
1666 EXPECT2(0,FAILDIG);
1667
1668 /* Unless consumed by trailing flag */
1669 CONVERT("0 ", NUMPRS_USE_ALL|NUMPRS_TRAILING_WHITE);
1670 EXPECT(1,NUMPRS_USE_ALL|NUMPRS_TRAILING_WHITE,NUMPRS_TRAILING_WHITE,2,0,0);
1671 EXPECT2(0,FAILDIG);
1672
1673 /** Combinations **/
1674
1675 /* Leading whitespace and plus, doesn't consume trailing whitespace */
1676 CONVERT("+ 0 ", NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE);
1677 EXPECT(1,NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE,NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE,3,0,0);
1678 EXPECT2(0,FAILDIG);
1679
1680 /* Order of whitespace and plus is unimportant */
1681 CONVERT(" +0", NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE);
1682 EXPECT(1,NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE,NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE,3,0,0);
1683 EXPECT2(0,FAILDIG);
1684
1685 /* Leading whitespace can be repeated */
1686 CONVERT(" + 0", NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE);
1687 EXPECT(1,NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE,NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE,4,0,0);
1688 EXPECT2(0,FAILDIG);
1689
1690 /* But plus/minus etc. cannot */
1691 CONVERT("+ +0", NUMPRS_LEADING_PLUS|NUMPRS_LEADING_WHITE);
1692 EXPECTFAIL;
1693 EXPECTRGB(0,FAILDIG);
1694
1695 /* Inexact is not set if trailing zeros are removed */
1696 CONVERTN("10", 1, 0);
1697 EXPECT(1,0,0,2,0,1);
1698 EXPECT2(1,FAILDIG);
1699
1700 /* Make sure a leading 0 is stripped but decimals after it get read */
1701 CONVERT("-0.51", NUMPRS_STD);
1702 EXPECT(2,NUMPRS_STD,NUMPRS_NEG|NUMPRS_DECIMAL|NUMPRS_LEADING_MINUS,5,0,-2);
1703 EXPECT2(5,1);
1704
1705 /* Keep trailing zeros on whole number part of a decimal */
1706 CONVERT("10.1", NUMPRS_STD);
1707 EXPECT(3,NUMPRS_STD,NUMPRS_DECIMAL,4,0,-1);
1708 EXPECT2(1,0);
1709 EXPECTRGB(2,1);
1710
1711 /* Zeros after decimal sign */
1712 CONVERT("0.01", NUMPRS_STD);
1713 EXPECT(1,NUMPRS_STD,NUMPRS_DECIMAL,4,0,-2);
1714 EXPECT2(1,FAILDIG);
1715
1716 /* Trailing zeros after decimal part */
1717 CONVERT("0.10", NUMPRS_STD);
1718 EXPECT(1,NUMPRS_STD,NUMPRS_DECIMAL,4,0,-1);
1719 EXPECT2(1,0);
1720 }
1721
1722 static HRESULT (WINAPI *pVarNumFromParseNum)(NUMPARSE*,BYTE*,ULONG,VARIANT*);
1723
1724 /* Macros for converting and testing the result of VarNumFromParseNum */
1725 #define SETRGB(indx,val) if (!indx) memset(rgb, FAILDIG, sizeof(rgb)); rgb[indx] = val
1726 #undef CONVERT
1727 #define CONVERT(a,b,c,d,e,f,bits) \
1728 np.cDig = (a); np.dwInFlags = (b); np.dwOutFlags = (c); np.cchUsed = (d); \
1729 np.nBaseShift = (e); np.nPwr10 = (f); hres = pVarNumFromParseNum(&np, rgb, bits, &vOut)
1730 static const char *szFailOverflow = "Expected overflow, hres = %08x\n";
1731 #define EXPECT_OVERFLOW ok(hres == (HRESULT)DISP_E_OVERFLOW, szFailOverflow, hres)
1732 static const char *szFailOk = "Call failed, hres = %08x\n";
1733 #define EXPECT_OK ok(hres == (HRESULT)S_OK, szFailOk, hres); \
1734 if (hres == (HRESULT)S_OK)
1735 #define EXPECT_TYPE(typ) ok(V_VT(&vOut) == typ,"Expected Type = " #typ ", got %d\n", V_VT(&vOut))
1736 #define EXPECT_I1(val) EXPECT_OK { EXPECT_TYPE(VT_I1); \
1737 ok(V_I1(&vOut) == val, "Expected i1 = %d, got %d\n", (signed char)val, V_I1(&vOut)); }
1738 #define EXPECT_UI1(val) EXPECT_OK { EXPECT_TYPE(VT_UI1); \
1739 ok(V_UI1(&vOut) == val, "Expected ui1 = %d, got %d\n", (BYTE)val, V_UI1(&vOut)); }
1740 #define EXPECT_I2(val) EXPECT_OK { EXPECT_TYPE(VT_I2); \
1741 ok(V_I2(&vOut) == val, "Expected i2 = %d, got %d\n", (SHORT)val, V_I2(&vOut)); }
1742 #define EXPECT_UI2(val) EXPECT_OK { EXPECT_TYPE(VT_UI2); \
1743 ok(V_UI2(&vOut) == val, "Expected ui2 = %d, got %d\n", (USHORT)val, V_UI2(&vOut)); }
1744 #define EXPECT_I4(val) EXPECT_OK { EXPECT_TYPE(VT_I4); \
1745 ok(V_I4(&vOut) == val, "Expected i4 = %d, got %d\n", (LONG)val, V_I4(&vOut)); }
1746 #define EXPECT_UI4(val) EXPECT_OK { EXPECT_TYPE(VT_UI4); \
1747 ok(V_UI4(&vOut) == val, "Expected ui4 = %d, got %d\n", (ULONG)val, V_UI4(&vOut)); }
1748 #define EXPECT_I8(high,low) EXPECT_OK { EXPECT_TYPE(VT_I8); \
1749 ok(V_I8(&vOut) == ((((ULONG64)(high))<<32)|(low)), "Expected i8 = %x%08x, got %x%08x\n", \
1750 (LONG)(high), (LONG)(low), (LONG)(V_I8(&vOut)>>32), (LONG)V_I8(&vOut) ); }
1751 #define EXPECT_UI8(val) EXPECT_OK { EXPECT_TYPE(VT_UI8); \
1752 ok(V_UI8(&vOut) == val, "Expected ui8 = 0x%x%08x, got 0x%x%08x\n", \
1753 (DWORD)((ULONG64)val >> 32), (DWORD)(ULONG64)val, (DWORD)(V_UI8(&vOut) >> 32), (DWORD)V_UI8(&vOut)); }
1754 #define EXPECT_R4(val) EXPECT_OK { EXPECT_TYPE(VT_R4); \
1755 ok(V_R4(&vOut) == val, "Expected r4 = %f, got %f\n", val, V_R4(&vOut)); }
1756 #define EXPECT_R8(val) EXPECT_OK { EXPECT_TYPE(VT_R8); \
1757 ok(V_R8(&vOut) == val, "Expected r8 = %g, got %g\n", val, V_R8(&vOut)); }
1758 #define CY_MULTIPLIER 10000
1759 #define EXPECT_CY(val) EXPECT_OK { EXPECT_TYPE(VT_CY); \
1760 ok(V_CY(&vOut).int64 == (LONG64)(val * CY_MULTIPLIER), "Expected r8 = 0x%x%08x, got 0x%x%08x\n", \
1761 (DWORD)((LONG64)val >> 23), (DWORD)(LONG64)val, (DWORD)(V_CY(&vOut).int64 >>32), (DWORD)V_CY(&vOut).int64); }
1762 #define EXPECT_DECIMAL(valHi, valMid, valLo) EXPECT_OK { EXPECT_TYPE(VT_DECIMAL); \
1763 ok((V_DECIMAL(&vOut).Hi32 == valHi) && (S1(U1(V_DECIMAL(&vOut))).Mid32 == valMid) && \
1764 (S1(U1(V_DECIMAL(&vOut))).Lo32 == valLo), \
1765 "Expected decimal = %x/0x%x%08x, got %x/0x%x%08x\n", valHi, valMid, valLo, \
1766 V_DECIMAL(&vOut).Hi32, S1(U1(V_DECIMAL(&vOut))).Mid32, S1(U1(V_DECIMAL(&vOut))).Lo32); }
1767
1768 static void test_VarNumFromParseNum(void)
1769 {
1770 HRESULT hres;
1771 NUMPARSE np;
1772 BYTE rgb[128];
1773 VARIANT vOut;
1774
1775 CHECKPTR(VarNumFromParseNum);
1776
1777 /* Convert the number 1 to different types */
1778 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_I1); EXPECT_I1(1);
1779 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_UI1); EXPECT_UI1(1);
1780 /* Prefers a signed type to unsigned of the same size */
1781 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_I1|VTBIT_UI1); EXPECT_I1(1);
1782 /* But takes the smaller size if possible */
1783 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_I2|VTBIT_UI1); EXPECT_UI1(1);
1784
1785 /* Try different integer sizes */
1786 #define INTEGER_VTBITS (VTBIT_I1|VTBIT_UI1|VTBIT_I2|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|VTBIT_I8|VTBIT_UI8)
1787
1788 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, INTEGER_VTBITS); EXPECT_I1(1);
1789 /* 127 */
1790 SETRGB(0, 1); SETRGB(1, 2); SETRGB(2, 7);
1791 CONVERT(3,0,0,3,0,0, INTEGER_VTBITS); EXPECT_I1(127);
1792 /* 128 */
1793 SETRGB(0, 1); SETRGB(1, 2); SETRGB(2, 8);
1794 CONVERT(3,0,0,3,0,0, INTEGER_VTBITS); EXPECT_UI1(128);
1795 /* 255 */
1796 SETRGB(0, 2); SETRGB(1, 5); SETRGB(2, 5);
1797 CONVERT(3,0,0,3,0,0, INTEGER_VTBITS); EXPECT_UI1(255);
1798 /* 256 */
1799 SETRGB(0, 2); SETRGB(1, 5); SETRGB(2, 6);
1800 CONVERT(3,0,0,3,0,0, INTEGER_VTBITS); EXPECT_I2(256);
1801 /* 32767 */
1802 SETRGB(0, 3); SETRGB(1, 2); SETRGB(2, 7); SETRGB(3, 6); SETRGB(4, 7);
1803 CONVERT(5,0,0,5,0,0, INTEGER_VTBITS); EXPECT_I2(32767);
1804 /* 32768 */
1805 SETRGB(0, 3); SETRGB(1, 2); SETRGB(2, 7); SETRGB(3, 6); SETRGB(4, 8);
1806 CONVERT(5,0,0,5,0,0, INTEGER_VTBITS); EXPECT_UI2(32768);
1807
1808 /* Assume the above pattern holds for remaining positive integers; test negative */
1809
1810 /* -128 */
1811 SETRGB(0, 1); SETRGB(1, 2); SETRGB(2, 8);
1812 CONVERT(3,0,NUMPRS_NEG,3,0,0, INTEGER_VTBITS); EXPECT_I1(-128);
1813 /* -129 */
1814 SETRGB(0, 1); SETRGB(1, 2); SETRGB(2, 9);
1815 CONVERT(3,0,NUMPRS_NEG,3,0,0, INTEGER_VTBITS); EXPECT_I2(-129);
1816 /* -32768 */
1817 SETRGB(0, 3); SETRGB(1, 2); SETRGB(2, 7); SETRGB(3, 6); SETRGB(4, 8);
1818 CONVERT(5,0,NUMPRS_NEG,5,0,0, INTEGER_VTBITS); EXPECT_I2(-32768);
1819 /* -32768 */
1820 SETRGB(0, 3); SETRGB(1, 2); SETRGB(2, 7); SETRGB(3, 6); SETRGB(4, 9);
1821 CONVERT(5,0,NUMPRS_NEG,5,0,0, INTEGER_VTBITS); EXPECT_I4(-32769);
1822
1823 /* Assume the above pattern holds for remaining negative integers */
1824
1825 /* Test hexadecimal conversions */
1826 SETRGB(0, 1); CONVERT(1,0,0,1,4,0, INTEGER_VTBITS); EXPECT_I1(0x01);
1827 /* 0x7f */
1828 SETRGB(0, 7); SETRGB(1, 0xf);
1829 CONVERT(2,0,0,2,4,0, INTEGER_VTBITS); EXPECT_I1(0x7f);
1830 SETRGB(0, 7); SETRGB(1, 0xf);
1831 CONVERT(2,0,0,2,4,0, VTBIT_DECIMAL); EXPECT_DECIMAL(0,0,0x7f);
1832 /* 0x7fff */
1833 SETRGB(0, 7); SETRGB(1, 0xf); SETRGB(2, 0xf); SETRGB(3, 0xf);
1834 CONVERT(4,0,0,4,4,0, INTEGER_VTBITS); EXPECT_I2(0x7fff);
1835 /* 0x7fffffff */
1836 SETRGB(0, 7); SETRGB(1, 0xf); SETRGB(2, 0xf); SETRGB(3, 0xf);
1837 SETRGB(4, 0xf); SETRGB(5, 0xf); SETRGB(6, 0xf); SETRGB(7, 0xf);
1838 CONVERT(8,0,0,8,4,0, INTEGER_VTBITS); EXPECT_I4(0x7fffffffL);
1839 /* 0x7fffffffffffffff (64 bits) */
1840 SETRGB(0, 7); SETRGB(1, 0xf); SETRGB(2, 0xf); SETRGB(3, 0xf);
1841 SETRGB(4, 0xf); SETRGB(5, 0xf); SETRGB(6, 0xf); SETRGB(7, 0xf);
1842 SETRGB(8, 0xf); SETRGB(9, 0xf); SETRGB(10, 0xf); SETRGB(11, 0xf);
1843 SETRGB(12, 0xf); SETRGB(13, 0xf); SETRGB(14, 0xf); SETRGB(15, 0xf);
1844 if (has_i8)
1845 {
1846 /* We cannot use INTEGER_VTBITS as WinXP and Win2003 are broken(?). They
1847 truncate the number to the smallest integer size requested:
1848 CONVERT(16,0,0,16,4,0, INTEGER_VTBITS); EXPECT_I1((signed char)0xff); */
1849 CONVERT(16,0,0,16,4,0, VTBIT_I8); EXPECT_I8(0x7fffffff,0xffffffff);
1850 }
1851
1852 /* Assume the above pattern holds for numbers without hi-bit set, test (preservation of) hi-bit */
1853 /* 0x82 */
1854 SETRGB(0, 8); SETRGB(1, 2);
1855 CONVERT(2,0,0,2,4,0, INTEGER_VTBITS);
1856 EXPECT_I1((signed char)0x82);
1857 /* 0x8002 */
1858 SETRGB(0, 8); SETRGB(1, 0); SETRGB(2, 0); SETRGB(3, 2);
1859 CONVERT(4,0,0,4,4,0, INTEGER_VTBITS);
1860 EXPECT_I2((signed short)0x8002);
1861 /* 0x80000002 */
1862 SETRGB(0, 8); SETRGB(1, 0); SETRGB(2, 0); SETRGB(3, 0);
1863 SETRGB(4, 0); SETRGB(5, 0); SETRGB(6, 0); SETRGB(7, 2);
1864 CONVERT(8,0,0,8,4,0, INTEGER_VTBITS); EXPECT_I4(0x80000002);
1865 /* 0x8000000000000002 (64 bits) */
1866 SETRGB(0, 8); SETRGB(1, 0); SETRGB(2, 0); SETRGB(3, 0);
1867 SETRGB(4, 0); SETRGB(5, 0); SETRGB(6, 0); SETRGB(7, 0);
1868 SETRGB(8, 0); SETRGB(9, 0); SETRGB(10, 0); SETRGB(11, 0);
1869 SETRGB(12, 0); SETRGB(13, 0); SETRGB(14, 0); SETRGB(15, 2);
1870 if (has_i8)
1871 {
1872 /* We cannot use INTEGER_VTBITS as WinXP and Win2003 are broken(?). They
1873 truncate the number to the smallest integer size requested:
1874 CONVERT(16,0,0,16,4,0, INTEGER_VTBITS & ~VTBIT_I1);
1875 EXPECT_I2((signed short)0x0002); */
1876 CONVERT(16,0,0,16,4,0, VTBIT_I8); EXPECT_I8(0x80000000,0x00000002);
1877 }
1878
1879 /* Test (preservation of) hi-bit with STRICT type requesting */
1880 /* 0x82 */
1881 SETRGB(0, 8); SETRGB(1, 2);
1882 CONVERT(2,0,0,2,4,0, VTBIT_I1);
1883 EXPECT_I1((signed char)0x82);
1884 /* 0x8002 */
1885 SETRGB(0, 8); SETRGB(1, 0); SETRGB(2, 0); SETRGB(3, 2);
1886 CONVERT(4,0,0,4,4,0, VTBIT_I2);
1887 EXPECT_I2((signed short)0x8002);
1888 /* 0x80000002 */
1889 SETRGB(0, 8); SETRGB(1, 0); SETRGB(2, 0); SETRGB(3, 0);
1890 SETRGB(4, 0); SETRGB(5, 0); SETRGB(6, 0); SETRGB(7, 2);
1891 CONVERT(8,0,0,8,4,0, VTBIT_I4); EXPECT_I4(0x80000002);
1892 /* 0x8000000000000002 (64 bits) */
1893 SETRGB(0, 8); SETRGB(1, 0); SETRGB(2, 0); SETRGB(3, 0);
1894 SETRGB(4, 0); SETRGB(5, 0); SETRGB(6, 0); SETRGB(7, 0);
1895 SETRGB(8, 0); SETRGB(9, 0); SETRGB(10, 0); SETRGB(11, 0);
1896 SETRGB(12, 0); SETRGB(13, 0); SETRGB(14, 0); SETRGB(15, 2);
1897 if (has_i8)
1898 {
1899 CONVERT(16,0,0,16,4,0, VTBIT_I8); EXPECT_I8(0x80000000,0x00000002);
1900 }
1901 /* Assume the above pattern holds for numbers with hi-bit set */
1902
1903 /* Negative numbers overflow if we have only unsigned outputs */
1904 /* -1 */
1905 SETRGB(0, 1); CONVERT(1,0,NUMPRS_NEG,1,0,0, VTBIT_UI1); EXPECT_OVERFLOW;
1906 /* -0.6 */
1907 SETRGB(0, 6); CONVERT(1,0,NUMPRS_NEG,1,0,~0u, VTBIT_UI1); EXPECT_OVERFLOW;
1908
1909 /* Except that rounding is done first, so -0.5 to 0 are accepted as 0 */
1910 /* -0.5 */
1911 SETRGB(0, 5); CONVERT(1,0,NUMPRS_NEG,1,0,~0u, VTBIT_UI1); EXPECT_UI1(0);
1912
1913 /* Floating point zero is OK */
1914 /* 0.00000000E0 */
1915 SETRGB(0, 0); CONVERT(1,0,NUMPRS_DECIMAL|NUMPRS_EXPONENT,12,0,-8, VTBIT_R8);
1916 EXPECT_R8(0.0);
1917
1918 /* Float is acceptable for an integer input value */
1919 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_R4); EXPECT_R4(1.0f);
1920 /* As is double */
1921 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_R8); EXPECT_R8(1.0);
1922 /* As is currency */
1923 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_CY); EXPECT_CY(1);
1924
1925 /* Float is preferred over double */
1926 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_R4|VTBIT_R8); EXPECT_R4(1.0f);
1927
1928 /* Double is preferred over currency */
1929 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_R8|VTBIT_CY); EXPECT_R8(1.0);
1930
1931 /* Currency is preferred over decimal */
1932 SETRGB(0, 1); CONVERT(1,0,0,1,0,0, VTBIT_CY|VTBIT_DECIMAL); EXPECT_CY(1);
1933 }
1934
1935
1936 static void test_UdateFromDate( int line, DATE dt, ULONG flags, HRESULT r, WORD d, WORD m, WORD y,
1937 WORD h, WORD mn, WORD s, WORD ms, WORD dw, WORD dy)
1938 {
1939 UDATE ud;
1940 HRESULT res;
1941
1942 memset(&ud, 0, sizeof(ud));
1943 res = pVarUdateFromDate(dt, flags, &ud);
1944 ok_(__FILE__,line)(r == res && (res != S_OK || (ud.st.wYear == y && ud.st.wMonth == m && ud.st.wDay == d &&
1945 ud.st.wHour == h && ud.st.wMinute == mn && ud.st.wSecond == s &&
1946 ud.st.wMilliseconds == ms && ud.st.wDayOfWeek == dw && ud.wDayOfYear == dy)),
1947 "%.16g expected res(%x) %d,%d,%d,%d,%d,%d,%d %d %d, got res(%x) %d,%d,%d,%d,%d,%d,%d %d %d\n",
1948 dt, r, d, m, y, h, mn, s, ms, dw, dy,
1949 res, ud.st.wDay, ud.st.wMonth, ud.st.wYear, ud.st.wHour, ud.st.wMinute,
1950 ud.st.wSecond, ud.st.wMilliseconds, ud.st.wDayOfWeek, ud.wDayOfYear );
1951 }
1952 #define DT2UD(dt,flags,r,d,m,y,h,mn,s,ms,dw,dy) test_UdateFromDate(__LINE__,dt,flags,r,d,m,y,h,mn,s,ms,dw,dy)
1953
1954 static void test_VarUdateFromDate(void)
1955 {
1956 CHECKPTR(VarUdateFromDate);
1957 DT2UD(29221.0,0,S_OK,1,1,1980,0,0,0,0,2,1); /* 1 Jan 1980 */
1958 DT2UD(29222.0,0,S_OK,2,1,1980,0,0,0,0,3,2); /* 2 Jan 1980 */
1959 DT2UD(33238.0,0,S_OK,31,12,1990,0,0,0,0,1,365); /* 31 Dec 1990 */
1960 DT2UD(0.0,0,S_OK,30,12,1899,0,0,0,0,6,364); /* 30 Dec 1899 - VT_DATE 0.0 */
1961 DT2UD(-657434.0,0,S_OK,1,1,100,0,0,0,0,5,1); /* 1 Jan 100 - Min */
1962 DT2UD(-657435.0,0,E_INVALIDARG,0,0,0,0,0,0,0,0,0); /* < 1 Jan 100 => err */
1963 DT2UD(2958465.0,0,S_OK,31,12,9999,0,0,0,0,5,365); /* 31 Dec 9999 - Max */
1964 DT2UD(2958466.0,0,E_INVALIDARG,0,0,0,0,0,0,0,0,0); /* > 31 Dec 9999 => err */
1965
1966 /* VAR_VALIDDATE doesn't prevent upper and lower bounds being checked */
1967 DT2UD(-657435.0,VAR_VALIDDATE,E_INVALIDARG,0,0,0,0,0,0,0,0,0);
1968 DT2UD(2958466.0,VAR_VALIDDATE,E_INVALIDARG,0,0,0,0,0,0,0,0,0);
1969
1970 /* Times */
1971 DT2UD(29221.25,0,S_OK,1,1,1980,6,0,0,0,2,1); /* 6 AM */
1972 DT2UD(29221.33333333,0,S_OK,1,1,1980,8,0,0,0,2,1); /* 8 AM */
1973 DT2UD(29221.5,0,S_OK,1,1,1980,12,0,0,0,2,1); /* 12 AM */
1974 DT2UD(29221.9888884444,0,S_OK,1,1,1980,23,44,0,0,2,1); /* 11:44 PM */
1975 DT2UD(29221.7508765432,0,S_OK,1,1,1980,18,1,16,0,2,1); /* 6:18:02 PM */
1976
1977 /* Test handling of times on dates prior to the epoch */
1978 DT2UD(-5.25,0,S_OK,25,12,1899,6,0,0,0,1,359);
1979 DT2UD(-5.9999884259259,0,S_OK,25,12,1899,23,59,59,0,1,359);
1980 /* This just demonstrates the non-linear nature of values prior to the epoch */
1981 DT2UD(-4.0,0,S_OK,26,12,1899,0,0,0,0,2,360);
1982 /* Numerical oddity: for 0.0 < x < 1.0, x and -x represent the same datetime */
1983 DT2UD(-0.25,0,S_OK,30,12,1899,6,0,0,0,6,364);
1984 DT2UD(0.25,0,S_OK,30,12,1899,6,0,0,0,6,364);
1985 }
1986
1987
1988 static void test_DateFromUDate( int line, WORD d, WORD m, WORD y, WORD h, WORD mn, WORD s, WORD ms,
1989 WORD dw, WORD dy, ULONG flags, HRESULT r, DATE dt )
1990 {
1991 UDATE ud;
1992 double out;
1993 HRESULT res;
1994
1995 ud.st.wYear = y;
1996 ud.st.wMonth = m;
1997 ud.st.wDay = d;
1998 ud.st.wHour = h;
1999 ud.st.wMinute = mn;
2000 ud.st.wSecond = s;
2001 ud.st.wMilliseconds = ms;
2002 ud.st.wDayOfWeek = dw;
2003 ud.wDayOfYear = dy;
2004 res = pVarDateFromUdate(&ud, flags, &out);
2005 ok_(__FILE__,line)(r == res && (r != S_OK || EQ_DOUBLE(out, dt)),
2006 "expected %x, %.16g, got %x, %.16g\n", r, dt, res, out);
2007 }
2008 #define UD2T(d,m,y,h,mn,s,ms,dw,dy,flags,r,dt) test_DateFromUDate(__LINE__,d,m,y,h,mn,s,ms,dw,dy,flags,r,dt)
2009
2010 static void test_VarDateFromUdate(void)
2011 {
2012 CHECKPTR(VarDateFromUdate);
2013 UD2T(1,1,1980,0,0,0,0,2,1,0,S_OK,29221.0); /* 1 Jan 1980 */
2014 UD2T(2,1,1980,0,0,0,0,3,2,0,S_OK,29222.0); /* 2 Jan 1980 */
2015 UD2T(2,1,1980,0,0,0,0,4,5,0,S_OK,29222.0); /* 2 Jan 1980 */
2016 UD2T(31,12,1990,0,0,0,0,0,0,0,S_OK,33238.0); /* 31 Dec 1990 */
2017 UD2T(31,12,90,0,0,0,0,0,0,0,S_OK,33238.0); /* year < 100 is 1900+year! */
2018 UD2T(30,12,1899,0,0,0,0,6,364,0,S_OK,0.0); /* 30 Dec 1899 - VT_DATE 0.0 */
2019 UD2T(1,1,100,0,0,0,0,0,0,0,S_OK,-657434.0); /* 1 Jan 100 - Min */
2020 UD2T(31,12,9999,0,0,0,0,0,0,0,S_OK,2958465.0); /* 31 Dec 9999 - Max */
2021 UD2T(1,1,10000,0,0,0,0,0,0,0,E_INVALIDARG,0.0); /* > 31 Dec 9999 => err */
2022 UD2T(1,1,-10000,0,0,0,0,0,0,0,E_INVALIDARG,0.0);/* < -9999 => err */
2023
2024 UD2T(30,12,1899,0,0,0,0,0,0,0,S_OK,0.0); /* 30 Dec 1899 0:00:00 */
2025 UD2T(30,12,1899,0,0,0,999,0,0,0,S_OK,0.0); /* Ignore milliseconds */
2026
2027 UD2T(1,1,1980,18,1,16,0,2,1,0,S_OK,29221.75087962963); /* 6:18:02 PM */
2028 UD2T(1,300,1980,18,1,16,0,2,1,0,S_OK,38322.75087962963); /* Test fwdrolled month */
2029 UD2T(300,1,1980,18,1,16,0,2,1,0,S_OK,29520.75087962963); /* Test fwdrolled days */
2030 UD2T(0,1,1980,42,1,16,0,2,1,0,S_OK,29221.75087962963); /* Test fwdrolled hours */
2031 UD2T(1,1,1980,17,61,16,0,2,1,0,S_OK,29221.75087962963); /* Test fwdrolled minutes */
2032 UD2T(1,1,1980,18,0,76,0,2,1,0,S_OK,29221.75087962963); /* Test fwdrolled seconds */
2033 UD2T(1,-300,1980,18,1,16,0,2,1,0,S_OK,20059.75087962963); /* Test backrolled month */
2034 UD2T(-300,1,1980,18,1,16,0,2,1,0,S_OK,28920.75087962963); /* Test backrolled days */
2035 UD2T(3,1,1980,-30,1,16,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled hours */
2036 UD2T(1,1,1980,20,-119,16,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled minutes */
2037 UD2T(1,1,1980,18,3,-104,0,2,1,0,S_OK,29221.75087962963); /* Test backrolled seconds */
2038 UD2T(1,12001,-1020,18,1,16,0,0,0,0,S_OK,29221.75087962963); /* Test rolled year and month */
2039 UD2T(1,-23,1982,18,1,16,0,0,0,0,S_OK,29221.75087962963); /* Test backrolled month */
2040 UD2T(-59,3,1980,18,1,16,0,0,0,0,S_OK,29221.75087962963); /* Test backrolled days */
2041 UD2T(1,1,0,0,0,0,0,0,0,0,S_OK,36526); /* Test zero year */
2042 UD2T(0,0,1980,0,0,0,0,0,0,0,S_OK,29189); /* Test zero day and month */
2043 UD2T(0,1,1980,0,0,0,0,2,1,0,S_OK,29220.0); /* Test zero day = LastDayOfMonth */
2044 UD2T(-1,1,1980,18,1,16,0,0,0,0,S_OK,29219.75087962963); /* Test day -1 = LastDayOfMonth - 1 */
2045 UD2T(1,1,-1,18,1,16,0,0,0,0,S_OK,36161.75087962963); /* Test year -1 = 1999 */
2046 UD2T(1,-1,1980,18,1,16,0,0,0,0,S_OK,29160.7508796296); /* Test month -1 = 11 */
2047 UD2T(1,13,1980,0,0,0,0,2,1,0,S_OK,29587.0); /* Rolls fwd to 1/1/1981 */
2048
2049 /* Test handling of times on dates prior to the epoch */
2050 UD2T(25,12,1899,6,0,0,0,1,359,0,S_OK,-5.25);
2051 UD2T(25,12,1899,23,59,59,0,1,359,0,S_OK,-5.9999884259259);
2052 /* This just demonstrates the non-linear nature of values prior to the epoch */
2053 UD2T(26,12,1899,0,0,0,0,2,360,0,S_OK,-4.0);
2054 /* for DATE values 0.0 < x < 1.0, x and -x represent the same datetime */
2055 /* but when converting to DATE, prefer the positive versions */
2056 UD2T(30,12,1899,6,0,0,0,6,364,0,S_OK,0.25);
2057
2058 UD2T(1,1,1980,18,1,16,0,2,1,VAR_TIMEVALUEONLY,S_OK,0.7508796296296296);
2059 UD2T(1,1,1980,18,1,16,0,2,1,VAR_DATEVALUEONLY,S_OK,29221.0);
2060 UD2T(25,12,1899,6,0,0,0,1,359,VAR_TIMEVALUEONLY,S_OK,0.25);
2061 UD2T(25,12,1899,6,0,0,0,1,359,VAR_DATEVALUEONLY,S_OK,-5.0);
2062 UD2T(1,-1,1980,18,1,16,0,0,0,VAR_TIMEVALUEONLY|VAR_DATEVALUEONLY,S_OK,0.7508796296296296);
2063 }
2064
2065 static void test_st2dt(int line, WORD d, WORD m, WORD y, WORD h, WORD mn,
2066 WORD s, WORD ms, INT r, double dt)
2067 {
2068 SYSTEMTIME st;
2069 double out;
2070 INT res;
2071
2072 st.wYear = y;
2073 st.wMonth = m;
2074 st.wDay = d;
2075 st.wHour = h;
2076 st.wMinute = mn;
2077 st.wSecond = s;
2078 st.wMilliseconds = ms;
2079 st.wDayOfWeek = 0;
2080 res = pSystemTimeToVariantTime(&st, &out);
2081 ok_(__FILE__,line)(r == res && (!r || EQ_DOUBLE(out, dt)),
2082 "expected %d, %.16g, got %d, %.16g\n", r, dt, res, out);
2083 }
2084 #define ST2DT(d,m,y,h,mn,s,ms,r,dt) test_st2dt(__LINE__,d,m,y,h,mn,s,ms,r,dt)
2085
2086 static void test_SystemTimeToVariantTime(void)
2087 {
2088 CHECKPTR(SystemTimeToVariantTime);
2089 ST2DT(1,1,1980,0,0,0,0,TRUE,29221.0);
2090 ST2DT(2,1,1980,0,0,0,0,TRUE,29222.0);
2091 ST2DT(0,1,1980,0,0,0,0,TRUE,29220.0); /* Rolls back to 31 Dec 1899 */
2092 ST2DT(1,13,1980,0,0,0,0,FALSE,29587.0); /* Fails on invalid month */
2093 ST2DT(32,1,1980,0,0,0,0,FALSE,0.0); /* Fails on invalid day */
2094 ST2DT(1,1,-1,0,0,0,0,FALSE,0.0); /* Fails on invalid year */
2095 ST2DT(1,1,10000,0,0,0,0,FALSE,0.0); /* Fails on invalid year */
2096 ST2DT(1,1,9999,0,0,0,0,TRUE,2958101.0); /* 9999 is last valid year */
2097 ST2DT(31,12,90,0,0,0,0,TRUE,33238.0); /* 30 <= year < 100 is 1900+year */
2098 ST2DT(1,1,30,0,0,0,0,TRUE,10959.0); /* 30 <= year < 100 is 1900+year */
2099 ST2DT(1,1,29,0,0,0,0,TRUE,47119.0); /* 0 <= year < 30 is 2000+year */
2100 ST2DT(1,1,0,0,0,0,0,TRUE,36526.0); /* 0 <= year < 30 is 2000+year */
2101 }
2102
2103 static void test_dt2st(int line, double dt, INT r, WORD d, WORD m, WORD y,
2104 WORD h, WORD mn, WORD s, WORD ms)
2105 {
2106 SYSTEMTIME st;
2107 INT res;
2108
2109 memset(&st, 0, sizeof(st));
2110 res = pVariantTimeToSystemTime(dt, &st);
2111 ok_(__FILE__,line)(r == res &&
2112 (!r || (st.wYear == y && st.wMonth == m && st.wDay == d &&
2113 st.wHour == h && st.wMinute == mn &&
2114 st.wSecond == s && st.wMilliseconds == ms)),
2115 "%.16g expected %d, %d,%d,%d,%d,%d,%d,%d, got %d, %d,%d,%d,%d,%d,%d,%d\n",
2116 dt, r, d, m, y, h, mn, s, ms, res, st.wDay, st.wMonth,
2117 st.wYear, st.wHour, st.wMinute, st.wSecond,
2118 st.wMilliseconds);
2119 }
2120 #define DT2ST(dt,r,d,m,y,h,mn,s,ms) test_dt2st(__LINE__,dt,r,d,m,y,h,mn,s,ms)
2121
2122 static void test_VariantTimeToSystemTime(void)
2123 {
2124 CHECKPTR(VariantTimeToSystemTime);
2125 DT2ST(29221.0,1,1,1,1980,0,0,0,0);
2126 DT2ST(29222.0,1,2,1,1980,0,0,0,0);
2127 }
2128
2129 #define MKDOSDATE(d,m,y) ((d & 0x1f) | ((m & 0xf) << 5) | (((y-1980) & 0x7f) << 9))
2130 #define MKDOSTIME(h,m,s) (((s>>1) & 0x1f) | ((m & 0x3f) << 5) | ((h & 0x1f) << 11))
2131
2132 static void test_dos2dt(int line, WORD d, WORD m, WORD y, WORD h, WORD mn,
2133 WORD s, INT r, double dt)
2134 {
2135 unsigned short dosDate, dosTime;
2136 double out;
2137 INT res;
2138
2139 out = 0.0;
2140 dosDate = MKDOSDATE(d, m, y);
2141 dosTime = MKDOSTIME(h, mn, s);
2142 res = pDosDateTimeToVariantTime(dosDate, dosTime, &out);
2143 ok_(__FILE__,line)(r == res && (!r || EQ_DOUBLE(out, dt)),
2144 "expected %d, %.16g, got %d, %.16g\n", r, dt, res, out);
2145 }
2146 #define DOS2DT(d,m,y,h,mn,s,r,dt) test_dos2dt(__LINE__,d,m,y,h,mn,s,r,dt)
2147
2148 static void test_DosDateTimeToVariantTime(void)
2149 {
2150 CHECKPTR(DosDateTimeToVariantTime);
2151
2152 /* Date */
2153 DOS2DT(1,1,1980,0,0,0,1,29221.0); /* 1/1/1980 */
2154 DOS2DT(31,12,2099,0,0,0,1,73050.0); /* 31/12/2099 */
2155 /* Dates are limited to the dos date max of 31/12/2099 */
2156 DOS2DT(31,12,2100,0,0,0,0,0.0); /* 31/12/2100 */
2157 /* Days and months of 0 cause date to roll back 1 day or month */
2158 DOS2DT(0,1,1980,0,0,0,1,29220.0); /* 0 Day => 31/12/1979 */
2159 DOS2DT(1,0,1980,0,0,0,1,29190.0); /* 0 Mth => 1/12/1979 */
2160 DOS2DT(0,0,1980,0,0,0,1,29189.0); /* 0 D/M => 30/11/1979 */
2161 /* Days > days in the month cause date to roll forward 1 month */
2162 DOS2DT(29,2,1981,0,0,0,1,29646.0); /* 29/2/1981 -> 3/1/1980 */
2163 DOS2DT(30,2,1981,0,0,0,1,29647.0); /* 30/2/1981 -> 4/1/1980 */
2164 /* Takes leap years into account when rolling forward */
2165 DOS2DT(29,2,1980,0,0,0,1,29280.0); /* 2/29/1980 */
2166 /* Months > 12 cause an error */
2167 DOS2DT(2,13,1980,0,0,0,0,0.0);
2168
2169 /* Time */
2170 DOS2DT(1,1,1980,0,0,29,1,29221.00032407407); /* 1/1/1980 12:00:28 AM */
2171 DOS2DT(1,1,1980,0,0,31,1,29221.00034722222); /* 1/1/1980 12:00:30 AM */
2172 DOS2DT(1,1,1980,0,59,0,1,29221.04097222222); /* 1/1/1980 12:59:00 AM */
2173 DOS2DT(1,1,1980,0,60,0,0,0.0); /* Invalid minutes */
2174 DOS2DT(1,1,1980,0,0,60,0,0.0); /* Invalid seconds */
2175 DOS2DT(1,1,1980,23,0,0,1,29221.95833333333); /* 1/1/1980 11:00:00 PM */
2176 DOS2DT(1,1,1980,24,0,0,0,0.0); /* Invalid hours */
2177
2178 DOS2DT(1,1,1980,0,0,1,1,29221.0);
2179 DOS2DT(2,1,1980,0,0,0,1,29222.0);
2180 DOS2DT(2,1,1980,0,0,0,1,29222.0);
2181 DOS2DT(31,12,1990,0,0,0,1,33238.0);
2182 DOS2DT(31,12,90,0,0,0,1,40543.0);
2183 DOS2DT(30,12,1899,0,0,0,1,46751.0);
2184 DOS2DT(1,1,100,0,0,0,1,43831.0);
2185 DOS2DT(31,12,9999,0,0,0,1,59901.0);
2186 DOS2DT(1,1,10000,0,0,0,1,59902.0);
2187 DOS2DT(1,1,-10000,0,0,0,1,48214.0);
2188
2189 DOS2DT(30,12,1899,0,0,0,1,46751.0);
2190 DOS2DT(30,12,1899,0,0,1,1,46751.0);
2191
2192 DOS2DT(1,1,1980,18,1,16,1,29221.75087962963);
2193 DOS2DT(1,300,1980,18,1,16,1,29556.75087962963);
2194 DOS2DT(300,1,1980,18,1,16,1,29232.75087962963);
2195 DOS2DT(0,1,1980,42,1,16,1,29220.4175462963);
2196 DOS2DT(1,1,1980,17,61,16,0,0.0);
2197 DOS2DT(1,1,1980,18,0,76,1,29221.75013888889);
2198 DOS2DT(1,-300,1980,18,1,16,1,29312.75087962963);
2199 DOS2DT(-300,1,1980,18,1,16,1,29240.75087962963);
2200 DOS2DT(3,1,1980,-30,1,16,1,29223.08421296296);
2201 DOS2DT(1,1,1980,20,-119,16,1,29221.83976851852);
2202 DOS2DT(1,1,1980,18,3,-104,1,29221.75236111111);
2203 DOS2DT(1,12001,-1020,18,1,16,1,55519.75087962963);
2204 DOS2DT(1,-23,1982,18,1,16,1,30195.75087962963);
2205 DOS2DT(-59,3,1980,18,1,16,1,29285.75087962963);
2206 DOS2DT(1,1,0,0,0,0,1,54058.0);
2207 DOS2DT(0,0,1980,0,0,0,1,29189.0);
2208 DOS2DT(0,1,1980,0,0,0,1,29220.0);
2209 DOS2DT(-1,1,1980,18,1,16,1,29251.75087962963);
2210 DOS2DT(1,1,-1,18,1,16,1,53693.75087962963);
2211 DOS2DT(1,-1,1980,18,1,16,0,0);
2212 }
2213
2214 static void test_dt2dos(int line, double dt, INT r, WORD d, WORD m, WORD y,
2215 WORD h, WORD mn, WORD s)
2216 {
2217 unsigned short dosDate, dosTime, expDosDate, expDosTime;
2218 INT res;
2219
2220 dosTime = dosDate = 0;
2221 expDosDate = MKDOSDATE(d,m,y);
2222 expDosTime = MKDOSTIME(h,mn,s);
2223 res = pVariantTimeToDosDateTime(dt, &dosDate, &dosTime);
2224 ok_(__FILE__,line)(r == res && (!r || (dosTime == expDosTime && dosDate == expDosDate)),
2225 "%g: expected %d,%d(%d/%d/%d),%d(%d:%d:%d) got %d,%d(%d/%d/%d),%d(%d:%d:%d)\n",
2226 dt, r, expDosDate, expDosDate & 0x1f,
2227 (expDosDate >> 5) & 0xf, 1980 + (expDosDate >> 9),
2228 expDosTime, expDosTime >> 11, (expDosTime >> 5) & 0x3f,
2229 (expDosTime & 0x1f),
2230 res, dosDate, dosDate & 0x1f, (dosDate >> 5) & 0xf,
2231 1980 + (dosDate >> 9), dosTime, dosTime >> 11,
2232 (dosTime >> 5) & 0x3f, (dosTime & 0x1f));
2233 }
2234 #define DT2DOS(dt,r,d,m,y,h,mn,s) test_dt2dos(__LINE__,dt,r,d,m,y,h,mn,s)
2235
2236 static void test_VariantTimeToDosDateTime(void)
2237 {
2238 CHECKPTR(VariantTimeToDosDateTime);
2239
2240 /* Date */
2241 DT2DOS(29221.0,1,1,1,1980,0,0,0); /* 1/1/1980 */
2242 DT2DOS(73050.0,1,31,12,2099,0,0,0); /* 31/12/2099 */
2243 DT2DOS(29220.0,0,0,0,0,0,0,0); /* 31/12/1979 - out of range */
2244 DT2DOS(73415.0,0,0,0,0,0,0,0); /* 31/12/2100 - out of range */
2245
2246 /* Time */
2247 DT2DOS(29221.00032407407,1,1,1,1980,0,0,29); /* 1/1/1980 12:00:28 AM */
2248 DT2DOS(29221.00034722222,1,1,1,1980,0,0,31); /* 1/1/1980 12:00:30 AM */
2249 DT2DOS(29221.04097222222,1,1,1,1980,0,59,0); /* 1/1/1980 12:59:00 AM */
2250 DT2DOS(29221.95833333333,1,1,1,1980,23,0,0); /* 1/1/1980 11:00:00 PM */
2251 }
2252
2253 static HRESULT (WINAPI *pVarAbs)(LPVARIANT,LPVARIANT);
2254
2255 #define VARABS(vt,val,rvt,rval) \
2256 V_VT(&v) = VT_##vt; V_##vt(&v) = val; \
2257 V_VT(&exp) = VT_##rvt; V_##rvt(&exp) = rval; \
2258 test_var_call1( __LINE__, pVarAbs, &v, &exp )
2259
2260 static void test_VarAbs(void)
2261 {
2262 static WCHAR szNum[] = {'-','1','.','1','\0' };
2263 char buff[8];
2264 HRESULT hres;
2265 VARIANT v, vDst, exp;
2266 size_t i;
2267
2268 CHECKPTR(VarAbs);
2269
2270 /* Test all possible V_VT values.
2271 */
2272 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
2273 {
2274 VARTYPE vt;
2275
2276 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
2277 {
2278 HRESULT hExpected = DISP_E_BADVARTYPE;
2279
2280 SKIPTESTS(vt);
2281
2282 memset(&v, 0, sizeof(v));
2283 V_VT(&v) = vt | ExtraFlags[i];
2284 V_VT(&vDst) = VT_EMPTY;
2285
2286 hres = pVarAbs(&v,&vDst);
2287 if (ExtraFlags[i] & VT_ARRAY ||
2288 (!ExtraFlags[i] && (vt == VT_UNKNOWN || vt == VT_BSTR ||
2289 vt == VT_DISPATCH || vt == VT_ERROR || vt == VT_RECORD)))
2290 {
2291 hExpected = DISP_E_TYPEMISMATCH;
2292 }
2293 else if (ExtraFlags[i] || vt >= VT_CLSID || vt == VT_VARIANT)
2294 {
2295 hExpected = DISP_E_BADVARTYPE;
2296 }
2297 else if (IsValidVariantClearVT(vt, ExtraFlags[i]))
2298 hExpected = S_OK;
2299
2300 /* Native always fails on some vartypes that should be valid. don't
2301 * check that Wine does the same; these are bugs in native.
2302 */
2303 if (vt == VT_I8 || vt == VT_UI8 || vt == VT_INT || vt == VT_UINT ||
2304 vt == VT_I1 || vt == VT_UI2 || vt == VT_UI4)
2305 continue;
2306 ok(hres == hExpected, "VarAbs: expected 0x%X, got 0x%X for vt %d | 0x%X\n",
2307 hExpected, hres, vt, ExtraFlags[i]);
2308 }
2309 }
2310
2311 /* BOOL->I2, BSTR->R8, all others remain the same */
2312 VARABS(BOOL,VARIANT_TRUE,I2,-VARIANT_TRUE);
2313 VARABS(BOOL,VARIANT_FALSE,I2,VARIANT_FALSE);
2314 VARABS(EMPTY,0,I2,0);
2315 VARABS(EMPTY,1,I2,0);
2316 VARABS(NULL,0,NULL,0);
2317 VARABS(NULL,1,NULL,0);
2318 VARABS(I2,1,I2,1);
2319 VARABS(I2,-1,I2,1);
2320 VARABS(I4,1,I4,1);
2321 VARABS(I4,-1,I4,1);
2322 VARABS(UI1,1,UI1,1);
2323 VARABS(R4,1,R4,1);
2324 VARABS(R4,-1,R4,1);
2325 VARABS(R8,1,R8,1);
2326 VARABS(R8,-1,R8,1);
2327 VARABS(DATE,1,DATE,1);
2328 VARABS(DATE,-1,DATE,1);
2329 V_VT(&v) = VT_CY;
2330 V_CY(&v).int64 = -10000;
2331 memset(&vDst,0,sizeof(vDst));
2332 hres = pVarAbs(&v,&vDst);
2333 ok(hres == S_OK && V_VT(&vDst) == VT_CY && V_CY(&vDst).int64 == 10000,
2334 "VarAbs(CY): expected 0x0 got 0x%X\n", hres);
2335 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buff, sizeof(buff)/sizeof(char));
2336 if (buff[1])
2337 {
2338 trace("Skipping VarAbs(BSTR) as decimal separator is '%s'\n", buff);
2339 return;
2340 } else {
2341 szNum[2] = buff[0];
2342 }
2343 V_VT(&v) = VT_BSTR;
2344 V_BSTR(&v) = (BSTR)szNum;
2345 memset(&vDst,0,sizeof(vDst));
2346 hres = pVarAbs(&v,&vDst);
2347 ok(hres == S_OK && V_VT(&vDst) == VT_R8 && V_R8(&vDst) == 1.1,
2348 "VarAbs: expected 0x0,%d,%g, got 0x%X,%d,%g\n", VT_R8, 1.1, hres, V_VT(&vDst), V_R8(&vDst));
2349 }
2350
2351 static HRESULT (WINAPI *pVarNot)(LPVARIANT,LPVARIANT);
2352
2353 #define VARNOT(vt,val,rvt,rval) \
2354 V_VT(&v) = VT_##vt; V_##vt(&v) = val; \
2355 V_VT(&exp) = VT_##rvt; V_##rvt(&exp) = rval; \
2356 test_var_call1( __LINE__, pVarNot, &v, &exp )
2357
2358 static void test_VarNot(void)
2359 {
2360 static const WCHAR szNum0[] = {'0','\0' };
2361 static const WCHAR szNum1[] = {'1','\0' };
2362 static const WCHAR szFalse[] = { '#','F','A','L','S','E','#','\0' };
2363 static const WCHAR szTrue[] = { '#','T','R','U','E','#','\0' };
2364 HRESULT hres;
2365 VARIANT v, exp, vDst;
2366 DECIMAL *pdec = &V_DECIMAL(&v);
2367 CY *pcy = &V_CY(&v);
2368 size_t i;
2369
2370 CHECKPTR(VarNot);
2371
2372 /* Test all possible V_VT values */
2373 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
2374 {
2375 VARTYPE vt;
2376
2377 for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
2378 {
2379 HRESULT hExpected = DISP_E_BADVARTYPE;
2380
2381 SKIPTESTS(vt);
2382
2383 memset(&v, 0, sizeof(v));
2384 V_VT(&v) = vt | ExtraFlags[i];
2385 V_VT(&vDst) = VT_EMPTY;
2386
2387 switch (V_VT(&v))
2388 {
2389 case VT_I1: case VT_UI1: case VT_I2: case VT_UI2:
2390 case VT_INT: case VT_UINT: case VT_I4: case VT_UI4:
2391 case VT_R4: case VT_R8:
2392 case VT_DECIMAL: case VT_BOOL: case VT_NULL: case VT_EMPTY:
2393 case VT_DATE: case VT_CY:
2394 hExpected = S_OK;
2395 break;
2396 case VT_I8: case VT_UI8:
2397 if (has_i8)
2398 hExpected = S_OK;
2399 break;
2400 case VT_RECORD:
2401 hExpected = DISP_E_TYPEMISMATCH;
2402 break;
2403 case VT_UNKNOWN: case VT_BSTR: case VT_DISPATCH: case VT_ERROR:
2404 hExpected = DISP_E_TYPEMISMATCH;
2405 break;
2406 default:
2407 if (IsValidVariantClearVT(vt, ExtraFlags[i]) && vt != VT_CLSID)
2408 hExpected = DISP_E_TYPEMISMATCH;
2409 break;
2410 }
2411
2412 hres = pVarNot(&v,&vDst);
2413 ok(hres == hExpected, "VarNot: expected 0x%X, got 0x%X vt %d|0x%X\n",
2414 hExpected, hres, vt, ExtraFlags[i]);
2415 }
2416 }
2417 /* Test the values returned by all cases that can succeed */
2418 VARNOT(EMPTY,0,I2,-1);
2419 VARNOT(EMPTY,1,I2,-1);
2420 VARNOT(NULL,0,NULL,0);
2421 VARNOT(NULL,1,NULL,0);
2422 VARNOT(BOOL,VARIANT_TRUE,BOOL,VARIANT_FALSE);
2423 VARNOT(BOOL,VARIANT_FALSE,BOOL,VARIANT_TRUE);
2424 VARNOT(I1,-1,I4,0);
2425 VARNOT(I1,0,I4,-1);
2426 VARNOT(I2,-1,I2,0);
2427 VARNOT(I2,0,I2,-1);
2428 VARNOT(I2,1,I2,-2);
2429 VARNOT(I4,1,I4,-2);
2430 VARNOT(I4,0,I4,-1);
2431 VARNOT(UI1,1,UI1,254);
2432 VARNOT(UI1,0,UI1,255);
2433 VARNOT(UI2,0,I4,-1);
2434 VARNOT(UI2,1,I4,-2);
2435 VARNOT(UI4,0,I4,-1);
2436 VARNOT(UI4,1,I4,-2);
2437 VARNOT(INT,0,I4,-1);
2438 VARNOT(INT,1,I4,-2);
2439 VARNOT(UINT,0,I4,-1);
2440 VARNOT(UINT,1,I4,-2);
2441 if (has_i8)
2442 {
2443 VARNOT(I8,1,I8,-2);
2444 VARNOT(I8,0,I8,-1);
2445 VARNOT(UI8,0,I4,-1);
2446 VARNOT(UI8,1,I4,-2);
2447 }
2448 VARNOT(R4,1,I4,-2);
2449 VARNOT(R4,0,I4,-1);
2450 VARNOT(R8,1,I4,-2);
2451 VARNOT(R8,0,I4,-1);
2452 VARNOT(DATE,1,I4,-2);
2453 VARNOT(DATE,0,I4,-1);
2454 VARNOT(BSTR,(BSTR)szNum0,I4,-1);
2455 ok(V_VT(&v) == VT_BSTR && V_BSTR(&v) == szNum0, "VarNot(0): changed input\n");
2456 VARNOT(BSTR,(BSTR)szNum1,I4,-2);
2457 ok(V_VT(&v) == VT_BSTR && V_BSTR(&v) == szNum1, "VarNot(1): changed input\n");
2458 VARNOT(BSTR, (BSTR)szTrue, BOOL, VARIANT_FALSE);
2459 VARNOT(BSTR, (BSTR)szFalse, BOOL, VARIANT_TRUE);
2460
2461 S(U(*pdec)).sign = DECIMAL_NEG;
2462 S(U(*pdec)).scale = 0;
2463 pdec->Hi32 = 0;
2464 S1(U1(*pdec)).Mid32 = 0;
2465 S1(U1(*pdec)).Lo32 = 1;
2466 VARNOT(DECIMAL,*pdec,I4,0);
2467
2468 pcy->int64 = 10000;
2469 VARNOT(CY,*pcy,I4,-2);
2470
2471 pcy->int64 = 0;
2472 VARNOT(CY,*pcy,I4,-1);
2473
2474 pcy->int64 = -1;
2475 VARNOT(CY,*pcy,I4,-1);
2476 }
2477
2478 static HRESULT (WINAPI *pVarSub)(LPVARIANT,LPVARIANT,LPVARIANT);
2479
2480 #define VARSUB(vt1,val1,vt2,val2,rvt,rval) \
2481 V_VT(&left) = VT_##vt1; V_##vt1(&left) = val1; \
2482 V_VT(&right) = VT_##vt2; V_##vt2(&right) = val2; \
2483 V_VT(&exp) = VT_##rvt; V_##rvt(&exp) = rval; \
2484 test_var_call2( __LINE__, pVarSub, &left, &right, &exp )
2485
2486 static void test_VarSub(void)
2487 {
2488 VARIANT left, right, exp, result, cy, dec;
2489 VARTYPE i;
2490 BSTR lbstr, rbstr;
2491 HRESULT hres, expectedhres;
2492 double r;
2493
2494 CHECKPTR(VarSub);
2495
2496 lbstr = SysAllocString(sz12);
2497 rbstr = SysAllocString(sz12);
2498
2499 VariantInit(&left);
2500 VariantInit(&right);
2501 VariantInit(&result);
2502
2503 /* Test all possible flag/vt combinations & the resulting vt type */
2504 for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
2505 {
2506
2507 VARTYPE leftvt, rightvt, resvt;
2508
2509 for (leftvt = 0; leftvt <= VT_BSTR_BLOB; leftvt++)
2510 {
2511
2512 SKIPTESTS(leftvt);
2513
2514 for (rightvt = 0; rightvt <= VT_BSTR_BLOB; rightvt++)
2515 {
2516
2517 SKIPTESTS(rightvt);
2518 expectedhres = S_OK;
2519
2520 memset(&left, 0, sizeof(left));
2521 memset(&right, 0, sizeof(right));
2522 V_VT(&left) = leftvt | ExtraFlags[i];
2523 if (leftvt == VT_BSTR)
2524 V_BSTR(&left) = lbstr;
2525 V_VT(&right) = rightvt | ExtraFlags[i];
2526 if (rightvt == VT_BSTR)
2527 V_BSTR(&right) = rbstr;
2528 V_VT(&result) = VT_EMPTY;
2529
2530 /* All extra flags produce errors */
2531 if (ExtraFlags[i] == (VT_VECTOR|VT_BYREF|VT_RESERVED) ||
2532 ExtraFlags[i] == (VT_VECTOR|VT_RESERVED) ||
2533 ExtraFlags[i] == (VT_VECTOR|VT_BYREF) ||
2534 ExtraFlags[i] == (VT_BYREF|VT_RESERVED) ||
2535 ExtraFlags[i] == VT_VECTOR ||
2536 ExtraFlags[i] == VT_BYREF ||
2537 ExtraFlags[i] == VT_RESERVED)
2538 {
2539 expectedhres = DISP_E_BADVARTYPE;
2540 resvt = VT_EMPTY;
2541 }
2542 else if (ExtraFlags[i] >= VT_ARRAY)
2543 {
2544 expectedhres = DISP_E_TYPEMISMATCH;
2545 resvt = VT_EMPTY;
2546 }
2547 /* Nativ