Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
85602c21
Commit
85602c21
authored
Dec 09, 2003
by
Jon Griffiths
Committed by
Alexandre Julliard
Dec 09, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix the tests to pass when locale settings are user-overriden.
Fix those tests which pass now. Test copying, formatting, VarAbs, VarNot.
parent
7e7ca4ac
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
826 additions
and
90 deletions
+826
-90
vartest.c
dlls/oleaut32/tests/vartest.c
+826
-90
No files found.
dlls/oleaut32/tests/vartest.c
View file @
85602c21
...
...
@@ -19,10 +19,6 @@
*
* NOTES
* - Does not test IDispatch, IUnknown, IRecordInfo, DECIMAL, CY, I8/UI8
* - VarDateFromStr is not implemented yet.
* - The date and floating point format may not be the exact same
* format has the one inwindows depending on what the Internatinal
* setting are in windows.
*/
#include <stdarg.h>
...
...
@@ -32,6 +28,8 @@
#include <float.h>
#include <time.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winsock.h"
...
...
@@ -77,11 +75,23 @@ static INT (WINAPI *pSystemTimeToVariantTime)(LPSYSTEMTIME,double*);
static
INT
(
WINAPI
*
pVariantTimeToSystemTime
)(
double
,
LPSYSTEMTIME
);
static
INT
(
WINAPI
*
pDosDateTimeToVariantTime
)(
USHORT
,
USHORT
,
double
*
);
static
INT
(
WINAPI
*
pVariantTimeToDosDateTime
)(
double
,
USHORT
*
,
USHORT
*
);
static
HRESULT
(
WINAPI
*
pVarFormatNumber
)(
LPVARIANT
,
int
,
int
,
int
,
int
,
ULONG
,
BSTR
*
);
static
HRESULT
(
WINAPI
*
pVarFormat
)(
LPVARIANT
,
LPOLESTR
,
int
,
int
,
ULONG
,
BSTR
*
);
/* Get a conversion function ptr, return if function not available */
#define CHECKPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func); \
if (!p##func) { trace("function " # func " not available, not testing it\n"); return; }
/* Is a given function exported from oleaut32? */
#define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
/* Have IRecordInfo data type? */
#define HAVE_OLEAUT32_RECORD HAVE_FUNC(SafeArraySetRecordInfo)
/* Have CY data type? */
#define HAVE_OLEAUT32_CY HAVE_FUNC(VarCyAdd)
/* Have I8/UI8 data type? */
#define HAVE_OLEAUT32_I8 HAVE_FUNC(VarI8FromI1)
/* When comparing floating point values we cannot expect an exact match
* because the rounding errors depend on the exact algorithm.
*/
...
...
@@ -108,6 +118,12 @@ static OLECHAR* AtoW( const char* p )
return
buffer
;
}
static
inline
int
strcmpW
(
const
WCHAR
*
str1
,
const
WCHAR
*
str2
)
{
while
(
*
str1
&&
(
*
str1
==
*
str2
))
{
str1
++
;
str2
++
;
}
return
*
str1
-
*
str2
;
}
static
const
struct
_vartypes
{
int
ind
;
HRESULT
vcind1
,
vcind2
,
vcex1
,
vcex2
;
...
...
@@ -2267,30 +2283,14 @@ static void test_variant(void)
for
(
i
=
0
;
i
<
NB_OLE_STRINGS
;
i
++
)
{
*
pDouble
=
42
.
0
;
rc
=
VarDateFromStr
(
pOleChar
[
i
],
lcid
,
0
,
pDouble
);
if
(
strrets_DATE
[
i
].
todo_rc
)
{
todo_wine
{
ok
(
rc
==
strrets_DATE
[
i
].
error
,
"VarDateFromStr([%d]=
\"
%s
\"
) rc= %lx instead of %lx"
,
i
,
_pTestStrA
[
i
],
rc
,
strrets_DATE
[
i
].
error
);
}
}
else
{
ok
(
rc
==
strrets_DATE
[
i
].
error
,
"VarDateFromStr([%d]=
\"
%s
\"
) rc= %lx instead of %lx"
,
i
,
_pTestStrA
[
i
],
rc
,
strrets_DATE
[
i
].
error
);
}
rc
=
VarDateFromStr
(
pOleChar
[
i
],
lcid
,
LOCALE_NOUSEROVERRIDE
,
pDouble
);
ok
(
i
==
94
/* FIXME: Bug in native */
||
rc
==
strrets_DATE
[
i
].
error
,
"VarDateFromStr([%d]=
\"
%s
\"
) rc= %lx instead of %lx"
,
i
,
_pTestStrA
[
i
],
rc
,
strrets_DATE
[
i
].
error
);
if
(
rc
==
0
&&
strrets_DATE
[
i
].
error
==
0
)
{
if
(
strrets_DATE
[
i
].
todo_rc
||
strrets_DATE
[
i
].
todo_val
)
{
todo_wine
{
ok
(
EQ_DOUBLE
(
*
pDouble
,
strrets_DATE
[
i
].
retval
),
"VarDateFromStr([%d]=
\"
%s
\"
) got %.15f instead of %.15f"
,
i
,
_pTestStrA
[
i
],
*
pDouble
,
strrets_DATE
[
i
].
retval
);
}
}
else
{
ok
(
EQ_DOUBLE
(
*
pDouble
,
strrets_DATE
[
i
].
retval
),
"VarDateFromStr([%d]=
\"
%s
\"
) got %.15f instead of %.15f"
,
i
,
_pTestStrA
[
i
],
*
pDouble
,
strrets_DATE
[
i
].
retval
);
}
ok
(
EQ_DOUBLE
(
*
pDouble
,
strrets_DATE
[
i
].
retval
),
"VarDateFromStr([%d]=
\"
%s
\"
) got %.15f instead of %.15f"
,
i
,
_pTestStrA
[
i
],
*
pDouble
,
strrets_DATE
[
i
].
retval
);
}
}
/* bool from ...
...
...
@@ -2534,53 +2534,39 @@ static void test_variant(void)
ok
(
S_OK
==
VarBstrFromBool
(
0xFF
,
lcid
,
0
,
&
bstr
),
XOK
);
ok
(
!
strcmp
(
WtoA
(
bstr
),
"
\"
True
\"
"
),
"should be 'True'"
);
ok
(
S_OK
==
VarBstrFromDate
(
0
.
0
,
lcid
,
0
,
&
bstr
),
XOK
);
todo_wine
{
ok
(
!
strcmp
(
WtoA
(
bstr
),
"
\"
12:00:00 AM
\"
"
),
"should be '12:00:00 AM', but is %s
\n
"
,
WtoA
(
bstr
));
}
ok
(
S_OK
==
VarBstrFromDate
(
0
.
0
,
lcid
,
LOCALE_NOUSEROVERRIDE
,
&
bstr
),
XOK
);
ok
(
!
strcmp
(
WtoA
(
bstr
),
"
\"
12:00:00 AM
\"
"
),
"should be '12:00:00 AM', but is %s
\n
"
,
WtoA
(
bstr
));
ok
(
S_OK
==
VarBstrFromDate
(
3
.
34
,
lcid
,
0
,
&
bstr
),
XOK
);
todo_wine
{
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
1/2/1900 8:09:36 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
1/2/00 8:09:36 AM
\"
"
)
==
0
/* Win95 */
,
"should be '1/2/1900 8:09:36 AM', but is %s
\n
"
,
WtoA
(
bstr
));
}
ok
(
S_OK
==
VarBstrFromDate
(
3
.
34
,
lcid
,
LOCALE_NOUSEROVERRIDE
,
&
bstr
),
XOK
);
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
1/2/1900 8:09:36 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
1/2/00 8:09:36 AM
\"
"
)
==
0
/* Win95 */
,
"should be '1/2/1900 8:09:36 AM', but is %s
\n
"
,
WtoA
(
bstr
));
ok
(
S_OK
==
VarBstrFromDate
(
3339
.
34
,
lcid
,
0
,
&
bstr
),
XOK
);
todo_wine
{
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
2/20/1909 8:09:36 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
2/20/09 8:09:36 AM
\"
"
)
==
0
/* Win95 */
,
"should be '2/20/1909 8:09:36 AM', but is %s
\n
"
,
WtoA
(
bstr
));
}
ok
(
S_OK
==
VarBstrFromDate
(
3339
.
34
,
lcid
,
LOCALE_NOUSEROVERRIDE
,
&
bstr
),
XOK
);
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
2/20/1909 8:09:36 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
2/20/09 8:09:36 AM
\"
"
)
==
0
/* Win95 */
,
"should be '2/20/1909 8:09:36 AM', but is %s
\n
"
,
WtoA
(
bstr
));
ok
(
S_OK
==
VarBstrFromDate
(
365
.
00
,
lcid
,
0
,
&
bstr
),
XOK
);
todo_wine
{
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/1900
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/00
\"
"
)
==
0
/* Win95 */
,
"should be '12/30/1900', but is %s
\n
"
,
WtoA
(
bstr
));
}
ok
(
S_OK
==
VarBstrFromDate
(
365
.
00
,
lcid
,
LOCALE_NOUSEROVERRIDE
,
&
bstr
),
XOK
);
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/1900
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/00
\"
"
)
==
0
/* Win95 */
,
"should be '12/30/1900', but is %s
\n
"
,
WtoA
(
bstr
));
ok
(
S_OK
==
VarBstrFromDate
(
365
.
25
,
lcid
,
0
,
&
bstr
),
XOK
);
todo_wine
{
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/1900 6:00:00 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/00 6:00:00 AM
\"
"
)
==
0
/* Win95 */
,
"should be '12/30/1900 6:00:00 AM', but is %s
\n
"
,
WtoA
(
bstr
));
}
ok
(
S_OK
==
VarBstrFromDate
(
365
.
25
,
lcid
,
LOCALE_NOUSEROVERRIDE
,
&
bstr
),
XOK
);
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/1900 6:00:00 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/30/00 6:00:00 AM
\"
"
)
==
0
/* Win95 */
,
"should be '12/30/1900 6:00:00 AM', but is %s
\n
"
,
WtoA
(
bstr
));
ok
(
S_OK
==
VarBstrFromDate
(
1461
.
0
,
lcid
,
0
,
&
bstr
),
XOK
);
todo_wine
{
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/1903
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/03
\"
"
)
==
0
/* Win95 */
,
"should be '12/31/1903', but is %s
\n
"
,
WtoA
(
bstr
));
}
ok
(
S_OK
==
VarBstrFromDate
(
1461
.
0
,
lcid
,
LOCALE_NOUSEROVERRIDE
,
&
bstr
),
XOK
);
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/1903
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/03
\"
"
)
==
0
/* Win95 */
,
"should be '12/31/1903', but is %s
\n
"
,
WtoA
(
bstr
));
ok
(
S_OK
==
VarBstrFromDate
(
1461
.
5
,
lcid
,
0
,
&
bstr
),
XOK
);
todo_wine
{
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/1903 12:00:00 PM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/03 12:00:00 PM
\"
"
)
==
0
/* Win95 */
,
"should be '12/31/1903 12:00:00 PM', but is %s
\n
"
,
WtoA
(
bstr
));
}
ok
(
S_OK
==
VarBstrFromDate
(
1461
.
5
,
lcid
,
LOCALE_NOUSEROVERRIDE
,
&
bstr
),
XOK
);
ok
(
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/1903 12:00:00 PM
\"
"
)
==
0
||
strcmp
(
WtoA
(
bstr
),
"
\"
12/31/03 12:00:00 PM
\"
"
)
==
0
/* Win95 */
,
"should be '12/31/1903 12:00:00 PM', but is %s
\n
"
,
WtoA
(
bstr
));
/* Test variant API...
*/
...
...
@@ -2649,12 +2635,10 @@ static void test_variant(void)
V_VT
(
&
va
)
=
VT_DATE
;
V_UNION
(
&
va
,
date
)
=
34465
.
332431
;
ok
(
S_OK
==
VariantChangeTypeEx
(
&
vb
,
&
va
,
lcid
,
0
,
VT_BSTR
),
XOK
);
todo_wine
{
ok
(
strcmp
(
WtoA
(
V_BSTR
(
&
vb
)),
"
\"
5/11/1994 7:58:42 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
V_BSTR
(
&
vb
)),
"
\"
5/11/94 7:58:42 AM
\"
"
)
==
0
/* Win95 */
,
"should be 5/11/94 7:58:42 AM got %s"
,
WtoA
(
V_BSTR
(
&
vb
)));
}
ok
(
S_OK
==
VariantChangeTypeEx
(
&
vb
,
&
va
,
lcid
,
VARIANT_NOUSEROVERRIDE
,
VT_BSTR
),
XOK
);
ok
(
strcmp
(
WtoA
(
V_BSTR
(
&
vb
)),
"
\"
5/11/1994 7:58:42 AM
\"
"
)
==
0
||
strcmp
(
WtoA
(
V_BSTR
(
&
vb
)),
"
\"
5/11/94 7:58:42 AM
\"
"
)
==
0
/* Win95 */
,
"should be 5/11/94 7:58:42 AM got %s"
,
WtoA
(
V_BSTR
(
&
vb
)));
bstr
=
pOleChar
[
4
];
V_VT
(
&
va
)
=
VT_BSTR
;
...
...
@@ -2699,17 +2683,9 @@ static void test_variant(void)
d
=
4
.
123
;
V_UNION
(
&
va
,
pdblVal
)
=
&
d
;
rc
=
VariantCopyInd
(
&
vb
,
&
va
);
if
(
vartypes
[
i
].
todoind2
)
{
todo_wine
{
ok
(
vartypes
[
i
].
vcind2
==
rc
,
"%d: vt %d, return value %lx, expected was %lx"
,
i
,
vartypes
[
i
].
ind
,
rc
,
vartypes
[
i
].
vcind2
);
}
}
else
{
ok
(
vartypes
[
i
].
vcind2
==
rc
,
"%d: vt %d, return value %lx, expected was %lx"
,
i
,
vartypes
[
i
].
ind
,
rc
,
vartypes
[
i
].
vcind2
);
}
V_VT
(
&
va
)
=
VT_R8
;
d
=
4
.
123
;
V_UNION
(
&
va
,
dblVal
)
=
d
;
...
...
@@ -2788,6 +2764,26 @@ static const VARTYPE ExtraFlags[16] =
VT_BYREF
|
VT_RESERVED
,
};
/* Determine if a vt is valid for VariantClear() */
static
int
IsValidVariantClearVT
(
VARTYPE
vt
,
VARTYPE
extraFlags
)
{
int
ret
=
0
;
/* Only the following flags/types are valid */
if
((
vt
<=
VT_LPWSTR
||
vt
==
VT_RECORD
||
vt
==
VT_CLSID
)
&&
vt
!=
(
VARTYPE
)
15
&&
(
vt
<
(
VARTYPE
)
24
||
vt
>
(
VARTYPE
)
31
)
&&
(
!
(
extraFlags
&
(
VT_BYREF
|
VT_ARRAY
))
||
vt
>
VT_NULL
)
&&
(
extraFlags
==
0
||
extraFlags
==
VT_BYREF
||
extraFlags
==
VT_ARRAY
||
extraFlags
==
(
VT_ARRAY
|
VT_BYREF
)))
ret
=
1
;
/* ok */
if
((
vt
==
VT_RECORD
&&
!
HAVE_OLEAUT32_RECORD
)
||
((
vt
==
VT_I8
||
vt
==
VT_UI8
)
&&
!
HAVE_OLEAUT32_I8
))
ret
=
0
;
/* Old versions of oleaut32 */
return
ret
;
}
static
void
test_VariantClear
(
void
)
{
HRESULT
hres
;
...
...
@@ -2823,13 +2819,7 @@ static void test_VariantClear(void)
hres
=
VariantClear
(
&
v
);
/* Only the following flags/types are valid */
if
((
vt
<=
VT_LPWSTR
||
vt
==
VT_RECORD
||
vt
==
VT_CLSID
)
&&
vt
!=
(
VARTYPE
)
15
&&
(
vt
<
(
VARTYPE
)
24
||
vt
>
(
VARTYPE
)
31
)
&&
(
!
(
ExtraFlags
[
i
]
&
(
VT_BYREF
|
VT_ARRAY
))
||
vt
>
VT_NULL
)
&&
(
ExtraFlags
[
i
]
==
0
||
ExtraFlags
[
i
]
==
VT_BYREF
||
ExtraFlags
[
i
]
==
VT_ARRAY
||
ExtraFlags
[
i
]
==
(
VT_ARRAY
|
VT_BYREF
)))
if
(
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
ok
(
hres
==
hExpected
,
"VariantClear: expected 0x%lX, got 0x%lX for vt %d | 0x%X
\n
"
,
...
...
@@ -2838,11 +2828,307 @@ static void test_VariantClear(void)
}
}
static
void
test_VariantCopy
(
void
)
{
VARIANTARG
vSrc
,
vDst
;
VARTYPE
vt
;
size_t
i
;
HRESULT
hres
,
hExpected
;
/* Establish that the failure/other cases are dealt with. Individual tests
* for each type should verify that data is copied correctly, references
* are updated, etc.
*/
/* vSrc == vDst */
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
memset
(
&
vSrc
,
0
,
sizeof
(
vSrc
));
V_VT
(
&
vSrc
)
=
vt
|
ExtraFlags
[
i
];
hExpected
=
DISP_E_BADVARTYPE
;
/* src is allowed to be a VT_CLSID */
if
(
vt
!=
VT_CLSID
&&
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
hres
=
VariantCopy
(
&
vSrc
,
&
vSrc
);
ok
(
hres
==
hExpected
,
"Copy(src==dst): expected 0x%lX, got 0x%lX for src==dest vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
}
}
/* Test that if VariantClear() fails on dest, the function fails. This also
* shows that dest is in fact cleared and not just overwritten
*/
memset
(
&
vSrc
,
0
,
sizeof
(
vSrc
));
V_VT
(
&
vSrc
)
=
VT_UI1
;
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
hExpected
=
DISP_E_BADVARTYPE
;
memset
(
&
vDst
,
0
,
sizeof
(
vDst
));
V_VT
(
&
vDst
)
=
vt
|
ExtraFlags
[
i
];
if
(
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
hres
=
VariantCopy
(
&
vDst
,
&
vSrc
);
ok
(
hres
==
hExpected
,
"Copy(bad dst): expected 0x%lX, got 0x%lX for dest vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
if
(
hres
==
S_OK
)
ok
(
V_VT
(
&
vDst
)
==
VT_UI1
,
"Copy(bad dst): expected vt = VT_UI1, got %d
\n
"
,
V_VT
(
&
vDst
));
}
}
/* Test that VariantClear() checks vSrc for validity before copying */
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
hExpected
=
DISP_E_BADVARTYPE
;
memset
(
&
vDst
,
0
,
sizeof
(
vDst
));
V_VT
(
&
vDst
)
=
VT_EMPTY
;
memset
(
&
vSrc
,
0
,
sizeof
(
vSrc
));
V_VT
(
&
vSrc
)
=
vt
|
ExtraFlags
[
i
];
/* src is allowed to be a VT_CLSID */
if
(
vt
!=
VT_CLSID
&&
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
hres
=
VariantCopy
(
&
vDst
,
&
vSrc
);
ok
(
hres
==
hExpected
,
"Copy(bad src): expected 0x%lX, got 0x%lX for src vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
if
(
hres
==
S_OK
)
ok
(
V_VT
(
&
vDst
)
==
(
vt
|
ExtraFlags
[
i
]),
"Copy(bad src): expected vt = %d, got %d
\n
"
,
vt
|
ExtraFlags
[
i
],
V_VT
(
&
vDst
));
}
}
}
/* Determine if a vt is valid for VariantCopyInd() */
static
int
IsValidVariantCopyIndVT
(
VARTYPE
vt
,
VARTYPE
extraFlags
)
{
int
ret
=
0
;
if
((
extraFlags
&
VT_ARRAY
)
||
(
vt
>
VT_NULL
&&
vt
!=
(
VARTYPE
)
15
&&
vt
<
VT_VOID
&&
!
(
extraFlags
&
(
VT_VECTOR
|
VT_RESERVED
))))
{
ret
=
1
;
/* ok */
}
return
ret
;
}
static
void
test_VariantCopyInd
(
void
)
{
VARIANTARG
vSrc
,
vDst
,
vRef
,
vRef2
;
VARTYPE
vt
;
size_t
i
;
BYTE
buffer
[
64
];
HRESULT
hres
,
hExpected
;
memset
(
buffer
,
0
,
sizeof
(
buffer
));
/* vSrc == vDst */
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
if
(
ExtraFlags
[
i
]
&
VT_ARRAY
)
continue
;
/* Native crashes on NULL safearray */
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
memset
(
&
vSrc
,
0
,
sizeof
(
vSrc
));
V_VT
(
&
vSrc
)
=
vt
|
ExtraFlags
[
i
];
hExpected
=
DISP_E_BADVARTYPE
;
if
(
!
(
ExtraFlags
[
i
]
&
VT_BYREF
))
{
/* if src is not by-reference, acts as VariantCopy() */
if
(
vt
!=
VT_CLSID
&&
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
}
else
{
if
(
vt
==
VT_SAFEARRAY
||
vt
==
VT_BSTR
||
vt
==
VT_UNKNOWN
||
vt
==
VT_DISPATCH
||
vt
==
VT_RECORD
)
continue
;
/* Need valid ptrs for deep copies */
V_BYREF
(
&
vSrc
)
=
&
buffer
;
hExpected
=
E_INVALIDARG
;
if
((
vt
==
VT_I8
||
vt
==
VT_UI8
)
&&
ExtraFlags
[
i
]
==
VT_BYREF
)
{
if
(
HAVE_OLEAUT32_I8
)
hExpected
=
S_OK
;
/* Only valid if I8 is a known type */
}
else
if
(
IsValidVariantCopyIndVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
}
hres
=
VariantCopyInd
(
&
vSrc
,
&
vSrc
);
ok
(
hres
==
hExpected
,
"CopyInd(src==dst): expected 0x%lX, got 0x%lX for src==dst vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
}
}
/* Bad dest */
memset
(
&
vSrc
,
0
,
sizeof
(
vSrc
));
V_VT
(
&
vSrc
)
=
VT_UI1
|
VT_BYREF
;
V_BYREF
(
&
vSrc
)
=
&
buffer
;
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
memset
(
&
vDst
,
0
,
sizeof
(
vDst
));
V_VT
(
&
vDst
)
=
vt
|
ExtraFlags
[
i
];
hExpected
=
DISP_E_BADVARTYPE
;
if
(
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
hres
=
VariantCopyInd
(
&
vDst
,
&
vSrc
);
ok
(
hres
==
hExpected
,
"CopyInd(bad dst): expected 0x%lX, got 0x%lX for dst vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
if
(
hres
==
S_OK
)
ok
(
V_VT
(
&
vDst
)
==
VT_UI1
,
"CopyInd(bad dst): expected vt = VT_UI1, got %d
\n
"
,
V_VT
(
&
vDst
));
}
}
/* bad src */
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
if
(
ExtraFlags
[
i
]
&
VT_ARRAY
)
continue
;
/* Native crashes on NULL safearray */
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
memset
(
&
vDst
,
0
,
sizeof
(
vDst
));
V_VT
(
&
vDst
)
=
VT_EMPTY
;
memset
(
&
vSrc
,
0
,
sizeof
(
vSrc
));
V_VT
(
&
vSrc
)
=
vt
|
ExtraFlags
[
i
];
hExpected
=
DISP_E_BADVARTYPE
;
if
(
!
(
ExtraFlags
[
i
]
&
VT_BYREF
))
{
/* if src is not by-reference, acts as VariantCopy() */
if
(
vt
!=
VT_CLSID
&&
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
}
else
{
if
(
vt
==
VT_SAFEARRAY
||
vt
==
VT_BSTR
||
vt
==
VT_UNKNOWN
||
vt
==
VT_DISPATCH
||
vt
==
VT_RECORD
)
continue
;
/* Need valid ptrs for deep copies, see vartype.c */
V_BYREF
(
&
vSrc
)
=
&
buffer
;
hExpected
=
E_INVALIDARG
;
if
((
vt
==
VT_I8
||
vt
==
VT_UI8
)
&&
ExtraFlags
[
i
]
==
VT_BYREF
)
{
if
(
HAVE_OLEAUT32_I8
)
hExpected
=
S_OK
;
/* Only valid if I8 is a known type */
}
else
if
(
IsValidVariantCopyIndVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
}
hres
=
VariantCopyInd
(
&
vDst
,
&
vSrc
);
ok
(
hres
==
hExpected
,
"CopyInd(bad src): expected 0x%lX, got 0x%lX for src vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
if
(
hres
==
S_OK
)
{
if
(
vt
==
VT_VARIANT
&&
ExtraFlags
[
i
]
==
VT_BYREF
)
{
/* Type of vDst should be the type of the referenced variant.
* Since we set the buffer to all zeros, its type should be
* VT_EMPTY.
*/
ok
(
V_VT
(
&
vDst
)
==
VT_EMPTY
,
"CopyInd(bad src): expected dst vt = VT_EMPTY, got %d|0x%X
\n
"
,
V_VT
(
&
vDst
)
&
VT_TYPEMASK
,
V_VT
(
&
vDst
)
&
~
VT_TYPEMASK
);
}
else
{
ok
(
V_VT
(
&
vDst
)
==
(
vt
|
(
ExtraFlags
[
i
]
&
~
VT_BYREF
)),
"CopyInd(bad src): expected dst vt = %d|0x%X, got %d|0x%X
\n
"
,
vt
,
ExtraFlags
[
i
]
&
~
VT_BYREF
,
V_VT
(
&
vDst
)
&
VT_TYPEMASK
,
V_VT
(
&
vDst
)
&
~
VT_TYPEMASK
);
}
}
}
}
/* By-reference variants are dereferenced */
V_VT
(
&
vRef
)
=
VT_UI1
;
V_UI1
(
&
vRef
)
=
0x77
;
V_VT
(
&
vSrc
)
=
VT_VARIANT
|
VT_BYREF
;
V_VARIANTREF
(
&
vSrc
)
=
&
vRef
;
VariantInit
(
&
vDst
);
hres
=
VariantCopyInd
(
&
vDst
,
&
vSrc
);
ok
(
V_VT
(
&
vDst
)
==
VT_UI1
&&
V_UI1
(
&
vDst
)
==
0x77
,
"CopyInd(deref): expected dst vt = VT_UI1, val 0x77, got %d|0x%X, 0x%2X
\n
"
,
V_VT
(
&
vDst
)
&
VT_TYPEMASK
,
V_VT
(
&
vDst
)
&
~
VT_TYPEMASK
,
V_UI1
(
&
vDst
));
/* By-reference variant to a by-reference type succeeds */
V_VT
(
&
vRef
)
=
VT_UI1
|
VT_BYREF
;
V_UI1REF
(
&
vRef
)
=
buffer
;
buffer
[
0
]
=
0x88
;
V_VT
(
&
vSrc
)
=
VT_VARIANT
|
VT_BYREF
;
V_VARIANTREF
(
&
vSrc
)
=
&
vRef
;
VariantInit
(
&
vDst
);
hres
=
VariantCopyInd
(
&
vDst
,
&
vSrc
);
ok
(
V_VT
(
&
vDst
)
==
VT_UI1
&&
V_UI1
(
&
vDst
)
==
0x88
,
"CopyInd(deref): expected dst vt = VT_UI1, val 0x77, got %d|0x%X, 0x%2X
\n
"
,
V_VT
(
&
vDst
)
&
VT_TYPEMASK
,
V_VT
(
&
vDst
)
&
~
VT_TYPEMASK
,
V_UI1
(
&
vDst
));
/* But a by-reference variant to a by-reference variant fails */
V_VT
(
&
vRef2
)
=
VT_UI1
;
V_UI1
(
&
vRef2
)
=
0x77
;
V_VT
(
&
vRef
)
=
VT_VARIANT
|
VT_BYREF
;
V_VARIANTREF
(
&
vRef
)
=
&
vRef2
;
V_VT
(
&
vSrc
)
=
VT_VARIANT
|
VT_BYREF
;
V_VARIANTREF
(
&
vSrc
)
=
&
vRef
;
VariantInit
(
&
vDst
);
hres
=
VariantCopyInd
(
&
vDst
,
&
vSrc
);
ok
(
hres
==
E_INVALIDARG
,
"CopyInd(ref->ref): expected E_INVALIDARG, got 0x%08lx
\n
"
,
hres
);
}
/* Macros for converting and testing the result of VarParseNumFromStr */
#define FAILDIG 255
#define CONVERTN(str,dig,flags) MultiByteToWideChar(CP_ACP,0,str,-1,buff,sizeof(buff)); \
memset(rgb, FAILDIG, sizeof(rgb)); memset(&np,-1,sizeof(np)); np.cDig = dig; np.dwInFlags = flags; \
hres = VarParseNumFromStr(buff,lcid,
0
,&np,rgb)
hres = VarParseNumFromStr(buff,lcid,
LOCALE_NOUSEROVERRIDE
,&np,rgb)
#define CONVERT(str,flags) CONVERTN(str,sizeof(rgb),flags)
#define EXPECT(a,b,c,d,e,f) ok(hres == (HRESULT)S_OK, "Call failed, hres = %08lx\n", hres); \
if (hres == (HRESULT)S_OK) { \
...
...
@@ -3518,6 +3804,450 @@ static void test_VariantTimeToDosDateTime(void)
DT2DOS
(
29221
.
95833333333
,
1
,
1
,
1
,
1980
,
23
,
0
,
0
);
/* 1/1/1980 11:00:00 PM */
}
#define FMT_NUMBER(vt,val) \
VariantInit(&v); V_VT(&v) = vt; val(&v) = 1; \
hres = pVarFormatNumber(&v,2,0,0,0,0,&str); \
ok(hres == S_OK, "VarFormatNumber (vt %d): returned %8lx\n", vt, hres); \
if (hres == S_OK) \
ok(str && strcmpW(str,szResult1) == 0, \
"VarFormatNumber (vt %d): string different\n", vt)
static
void
test_VarFormatNumber
(
void
)
{
static
WCHAR
szSrc1
[]
=
{
'1'
,
'\0'
};
static
WCHAR
szResult1
[]
=
{
'1'
,
'.'
,
'0'
,
'0'
,
'\0'
};
static
WCHAR
szSrc2
[]
=
{
'-'
,
'1'
,
'\0'
};
static
WCHAR
szResult2
[]
=
{
'('
,
'1'
,
'.'
,
'0'
,
'0'
,
')'
,
'\0'
};
char
buff
[
8
];
HRESULT
hres
;
VARIANT
v
;
BSTR
str
=
NULL
;
CHECKPTR
(
VarFormatNumber
);
GetLocaleInfoA
(
LOCALE_USER_DEFAULT
,
LOCALE_SDECIMAL
,
buff
,
sizeof
(
buff
)
/
sizeof
(
char
));
if
(
buff
[
0
]
!=
'.'
||
buff
[
1
])
{
trace
(
"Skipping VarFormatNumber tests as decimal seperator is '%s'
\n
"
,
buff
);
return
;
}
FMT_NUMBER
(
VT_I1
,
V_I1
);
FMT_NUMBER
(
VT_UI1
,
V_UI1
);
FMT_NUMBER
(
VT_I2
,
V_I2
);
FMT_NUMBER
(
VT_UI2
,
V_UI2
);
FMT_NUMBER
(
VT_I4
,
V_I4
);
FMT_NUMBER
(
VT_UI4
,
V_UI4
);
todo_wine
{
FMT_NUMBER
(
VT_I8
,
V_I8
);
FMT_NUMBER
(
VT_UI8
,
V_UI8
);
}
FMT_NUMBER
(
VT_R4
,
V_R4
);
FMT_NUMBER
(
VT_R8
,
V_R8
);
FMT_NUMBER
(
VT_BOOL
,
V_BOOL
);
V_VT
(
&
v
)
=
VT_BSTR
;
V_BSTR
(
&
v
)
=
SysAllocString
(
szSrc1
);
hres
=
pVarFormatNumber
(
&
v
,
2
,
0
,
0
,
0
,
0
,
&
str
);
ok
(
hres
==
S_OK
,
"VarFormatNumber (bstr): returned %8lx
\n
"
,
hres
);
if
(
hres
==
S_OK
)
ok
(
str
&&
strcmpW
(
str
,
szResult1
)
==
0
,
"VarFormatNumber (bstr): string different
\n
"
);
SysFreeString
(
V_BSTR
(
&
v
));
SysFreeString
(
str
);
V_BSTR
(
&
v
)
=
SysAllocString
(
szSrc2
);
hres
=
pVarFormatNumber
(
&
v
,
2
,
0
,
-
1
,
0
,
0
,
&
str
);
ok
(
hres
==
S_OK
,
"VarFormatNumber (bstr): returned %8lx
\n
"
,
hres
);
if
(
hres
==
S_OK
)
ok
(
str
&&
strcmpW
(
str
,
szResult2
)
==
0
,
"VarFormatNumber (-bstr): string different
\n
"
);
SysFreeString
(
V_BSTR
(
&
v
));
SysFreeString
(
str
);
}
#define SIGNED_VTBITS (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8|VTBIT_R4|VTBIT_R8)
#define VARFMT(vt,v,val,fmt,ret,str) do { \
if (out) SysFreeString(out); out = NULL; \
V_VT(&in) = (vt); v(&in) = val; \
if (fmt) MultiByteToWideChar(CP_ACP, 0, fmt, -1, buffW, sizeof(buffW)/sizeof(WCHAR)); \
hres = pVarFormat(&in,fmt ? buffW : NULL,fd,fw,flags,&out); \
if (SUCCEEDED(hres)) WideCharToMultiByte(CP_ACP, 0, out, -1, buff, sizeof(buff),0,0); \
else buff[0] = '\0'; \
ok(hres == ret && (FAILED(ret) || !strcmp(buff, str)), \
"VT %d|0x%04x Format %s: expected 0x%08lx, '%s', got 0x%08lx, '%s'\n", \
(vt)&VT_TYPEMASK,(vt)&~VT_TYPEMASK,fmt?fmt:"<null>",ret,str,hres,buff); \
} while(0)
typedef
struct
tagFMTRES
{
LPCSTR
fmt
;
LPCSTR
one_res
;
LPCSTR
zero_res
;
}
FMTRES
;
static
const
FMTRES
VarFormat_results
[]
=
{
{
NULL
,
"1"
,
"0"
},
{
""
,
"1"
,
"0"
},
{
"General Number"
,
"1"
,
"0"
},
{
"Percent"
,
"100.00%"
,
"0.00%"
},
{
"Standard"
,
"1.00"
,
"0.00"
},
{
"Scientific"
,
"1.00E+00"
,
"0.00E+00"
},
{
"True/False"
,
"True"
,
"False"
},
/* { "On/Off", "On", "Off" },
{ "Yes/No", "Yes", "No")}, */
{
"#"
,
"1"
,
""
},
{
"##"
,
"1"
,
""
},
{
"#.#"
,
"1."
,
"."
},
{
"0"
,
"1"
,
"0"
},
{
"00"
,
"01"
,
"00"
},
{
"0.0"
,
"1.0"
,
"0.0"
},
{
"00
\\
c
\\
o
\\
p
\\
y"
,
"01copy"
,
"00copy"
},
{
"
\"
pos
\"
;
\"
neg
\"
"
,
"pos"
,
"pos"
},
{
"
\"
pos
\"
;
\"
neg
\"
;
\"
zero
\"
"
,
"pos"
,
"zero"
}
};
typedef
struct
tagFMTDATERES
{
DATE
val
;
LPCSTR
fmt
;
LPCSTR
res
;
}
FMTDATERES
;
static
const
FMTDATERES
VarFormat_date_results
[]
=
{
{
0
.
0
,
"w"
,
"7"
},
{
0
.
0
,
"w"
,
"6"
},
{
0
.
0
,
"w"
,
"5"
},
{
0
.
0
,
"w"
,
"4"
},
{
0
.
0
,
"w"
,
"3"
},
{
0
.
0
,
"w"
,
"2"
},
{
0
.
0
,
"w"
,
"1"
},
/* First 7 entries must remain in this order! */
{
2
.
525
,
"am/pm"
,
"pm"
},
{
2
.
525
,
"AM/PM"
,
"PM"
},
{
2
.
525
,
"A/P"
,
"P"
},
{
2
.
525
,
"a/p"
,
"p"
},
{
2
.
525
,
"q"
,
"1"
},
{
2
.
525
,
"d"
,
"1"
},
{
2
.
525
,
"dd"
,
"01"
},
{
2
.
525
,
"ddd"
,
"Mon"
},
{
2
.
525
,
"dddd"
,
"Monday"
},
{
2
.
525
,
"mmm"
,
"Jan"
},
{
2
.
525
,
"mmmm"
,
"January"
},
{
2
.
525
,
"y"
,
"1"
},
{
2
.
525
,
"yy"
,
"00"
},
{
2
.
525
,
"yyy"
,
"001"
},
{
2
.
525
,
"yyyy"
,
"1900"
},
{
2
.
525
,
"dd mm yyyy hh:mm:ss"
,
"01 01 1900 12:36:00"
},
{
2
.
525
,
"dd mm yyyy mm"
,
"01 01 1900 01"
},
{
2
.
525
,
"dd mm yyyy :mm"
,
"01 01 1900 :01"
},
{
2
.
525
,
"dd mm yyyy hh:mm"
,
"01 01 1900 12:36"
},
{
2
.
525
,
"mm mm"
,
"01 01"
},
{
2
.
525
,
"mm :mm:ss"
,
"01 :01:00"
},
{
2
.
525
,
"mm :ss:mm"
,
"01 :00:01"
},
{
2
.
525
,
"hh:mm :ss:mm"
,
"12:36 :00:01"
},
{
2
.
525
,
"hh:dd :mm:mm"
,
"12:01 :01:01"
},
{
2
.
525
,
"dd:hh :mm:mm"
,
"01:12 :36:01"
},
{
2
.
525
,
"hh :mm:mm"
,
"12 :36:01"
},
{
2
.
525
,
"dd :mm:mm"
,
"01 :01:01"
},
{
2
.
525
,
"dd :mm:nn"
,
"01 :01:36"
},
{
2
.
725
,
"hh:nn:ss A/P"
,
"05:24:00 P"
}
};
#define VNUMFMT(vt,v) \
for (i = 0; i < sizeof(VarFormat_results)/sizeof(FMTRES); i++) \
{ \
VARFMT(vt,v,1,VarFormat_results[i].fmt,S_OK,VarFormat_results[i].one_res); \
VARFMT(vt,v,0,VarFormat_results[i].fmt,S_OK,VarFormat_results[i].zero_res); \
} \
if ((1 << vt) & SIGNED_VTBITS) \
{ \
VARFMT(vt,v,-1,"\"pos\";\"neg\"",S_OK,"neg"); \
VARFMT(vt,v,-1,"\"pos\";\"neg\";\"zero\"",S_OK,"neg"); \
}
static
void
test_VarFormat
(
void
)
{
static
const
WCHAR
szTesting
[]
=
{
't'
,
'e'
,
's'
,
't'
,
'i'
,
'n'
,
'g'
,
'\0'
};
size_t
i
;
WCHAR
buffW
[
256
];
char
buff
[
256
];
VARIANT
in
;
VARIANT_BOOL
bTrue
=
VARIANT_TRUE
,
bFalse
=
VARIANT_FALSE
;
int
fd
=
0
,
fw
=
0
;
ULONG
flags
=
0
;
BSTR
bstrin
,
out
=
NULL
;
HRESULT
hres
;
CHECKPTR
(
VarFormat
);
if
(
PRIMARYLANGID
(
LANGIDFROMLCID
(
GetUserDefaultLCID
()))
!=
LANG_ENGLISH
)
{
trace
(
"Skipping VarFormat tests for non english language
\n
"
);
return
;
}
GetLocaleInfoA
(
LOCALE_USER_DEFAULT
,
LOCALE_SDECIMAL
,
buff
,
sizeof
(
buff
)
/
sizeof
(
char
));
if
(
buff
[
0
]
!=
'.'
||
buff
[
1
])
{
trace
(
"Skipping VarFormat tests as decimal seperator is '%s'
\n
"
,
buff
);
return
;
}
GetLocaleInfoA
(
LOCALE_USER_DEFAULT
,
LOCALE_IDIGITS
,
buff
,
sizeof
(
buff
)
/
sizeof
(
char
));
if
(
buff
[
0
]
!=
'2'
||
buff
[
1
])
{
trace
(
"Skipping VarFormat tests as decimal places is '%s'
\n
"
,
buff
);
return
;
}
VARFMT
(
VT_BOOL
,
V_BOOL
,
VARIANT_TRUE
,
"True/False"
,
S_OK
,
"True"
);
VARFMT
(
VT_BOOL
,
V_BOOL
,
VARIANT_FALSE
,
"True/False"
,
S_OK
,
"False"
);
VNUMFMT
(
VT_I1
,
V_I1
);
VNUMFMT
(
VT_I2
,
V_I2
);
VNUMFMT
(
VT_I4
,
V_I4
);
todo_wine
{
VNUMFMT
(
VT_I8
,
V_I8
);
}
VNUMFMT
(
VT_INT
,
V_INT
);
VNUMFMT
(
VT_UI1
,
V_UI1
);
VNUMFMT
(
VT_UI2
,
V_UI2
);
VNUMFMT
(
VT_UI4
,
V_UI4
);
todo_wine
{
VNUMFMT
(
VT_UI8
,
V_UI8
);
}
VNUMFMT
(
VT_UINT
,
V_UINT
);
VNUMFMT
(
VT_R4
,
V_R4
);
VNUMFMT
(
VT_R8
,
V_R8
);
/* Reference types are dereferenced */
VARFMT
(
VT_BOOL
|
VT_BYREF
,
V_BOOLREF
,
&
bTrue
,
"True/False"
,
S_OK
,
"True"
);
VARFMT
(
VT_BOOL
|
VT_BYREF
,
V_BOOLREF
,
&
bFalse
,
"True/False"
,
S_OK
,
"False"
);
/* Dates */
for
(
i
=
0
;
i
<
sizeof
(
VarFormat_date_results
)
/
sizeof
(
FMTDATERES
);
i
++
)
{
if
(
i
<
7
)
fd
=
i
+
1
;
/* Test first day */
else
fd
=
0
;
VARFMT
(
VT_DATE
,
V_DATE
,
VarFormat_date_results
[
i
].
val
,
VarFormat_date_results
[
i
].
fmt
,
S_OK
,
VarFormat_date_results
[
i
].
res
);
}
/* Strings */
bstrin
=
SysAllocString
(
szTesting
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
""
,
S_OK
,
"testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"@"
,
S_OK
,
"testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"&"
,
S_OK
,
"testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"
\\
x@
\\
x@"
,
S_OK
,
"xtxesting"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"
\\
x&
\\
x&"
,
S_OK
,
"xtxesting"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"@
\\
x"
,
S_OK
,
"txesting"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"@@@@@@@@"
,
S_OK
,
" testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"@
\\
x@@@@@@@"
,
S_OK
,
" xtesting"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"&&&&&&&&"
,
S_OK
,
"testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"!&&&&&&&"
,
S_OK
,
"testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"&&&&&&&!"
,
S_OK
,
"testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
">&&"
,
S_OK
,
"TESTING"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"<&&"
,
S_OK
,
"testing"
);
VARFMT
(
VT_BSTR
,
V_BSTR
,
bstrin
,
"<&>&"
,
S_OK
,
"testing"
);
SysFreeString
(
bstrin
);
/* Numeric values are converted to strings then output */
VARFMT
(
VT_I1
,
V_I1
,
1
,
"<&>&"
,
S_OK
,
"1"
);
/* 'out' is not cleared */
out
=
(
BSTR
)
0x1
;
pVarFormat
(
&
in
,
NULL
,
fd
,
fw
,
flags
,
&
out
);
/* Would crash if out is cleared */
out
=
NULL
;
/* Invalid args */
hres
=
pVarFormat
(
&
in
,
NULL
,
fd
,
fw
,
flags
,
NULL
);
ok
(
hres
==
E_INVALIDARG
,
"Null out: expected E_INVALIDARG, got 0x%08lx
\n
"
,
hres
);
hres
=
pVarFormat
(
NULL
,
NULL
,
fd
,
fw
,
flags
,
&
out
);
ok
(
hres
==
E_INVALIDARG
,
"Null in: expected E_INVALIDARG, got 0x%08lx
\n
"
,
hres
);
fd
=
-
1
;
VARFMT
(
VT_BOOL
,
V_BOOL
,
VARIANT_TRUE
,
""
,
E_INVALIDARG
,
""
);
fd
=
8
;
VARFMT
(
VT_BOOL
,
V_BOOL
,
VARIANT_TRUE
,
""
,
E_INVALIDARG
,
""
);
fd
=
0
;
fw
=
-
1
;
VARFMT
(
VT_BOOL
,
V_BOOL
,
VARIANT_TRUE
,
""
,
E_INVALIDARG
,
""
);
fw
=
4
;
VARFMT
(
VT_BOOL
,
V_BOOL
,
VARIANT_TRUE
,
""
,
E_INVALIDARG
,
""
);
}
static
HRESULT
(
WINAPI
*
pVarAbs
)(
LPVARIANT
,
LPVARIANT
);
#define VARABS(vt,val,rvt,rval) V_VT(&v) = VT_##vt; V_##vt(&v) = val; \
memset(&vDst,0,sizeof(vDst)); hres = pVarAbs(&v,&vDst); \
ok(hres == S_OK && V_VT(&vDst) == VT_##rvt && V_##rvt(&vDst) == (rval), \
"VarAbs: expected 0x0,%d,%d, got 0x%lX,%d,%d\n", VT_##rvt, (int)(rval), \
hres, V_VT(&vDst), (int)V_##rvt(&vDst))
static
void
test_VarAbs
(
void
)
{
static
const
WCHAR
szNum
[]
=
{
'-'
,
'1'
,
'.'
,
'1'
,
'\0'
};
HRESULT
hres
;
VARIANT
v
,
vDst
;
size_t
i
;
CHECKPTR
(
VarAbs
);
/* Test all possible V_VT values.
*/
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
VARTYPE
vt
;
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
HRESULT
hExpected
=
DISP_E_BADVARTYPE
;
memset
(
&
v
,
0
,
sizeof
(
v
));
V_VT
(
&
v
)
=
vt
|
ExtraFlags
[
i
];
V_VT
(
&
vDst
)
=
VT_EMPTY
;
hres
=
pVarAbs
(
&
v
,
&
vDst
);
if
(
ExtraFlags
[
i
]
&
(
VT_ARRAY
|
VT_ARRAY
)
||
(
!
ExtraFlags
[
i
]
&&
(
vt
==
VT_UNKNOWN
||
vt
==
VT_BSTR
||
vt
==
VT_DISPATCH
||
vt
==
VT_ERROR
||
vt
==
VT_RECORD
)))
{
hExpected
=
DISP_E_TYPEMISMATCH
;
}
else
if
(
ExtraFlags
[
i
]
||
vt
>=
VT_CLSID
||
vt
==
VT_VARIANT
)
{
hExpected
=
DISP_E_BADVARTYPE
;
}
else
if
(
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
]))
hExpected
=
S_OK
;
/* Native always fails on some vartypes that should be valid. don't
* check that Wine does the same; these are bugs in native.
*/
if
(
vt
==
VT_I8
||
vt
==
VT_UI8
||
vt
==
VT_INT
||
vt
==
VT_UINT
||
vt
==
VT_I1
||
vt
==
VT_UI2
||
vt
==
VT_UI4
)
continue
;
ok
(
hres
==
hExpected
,
"VarAbs: expected 0x%lX, got 0x%lX for vt %d | 0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
}
}
/* BOOL->I2, BSTR->R8, all others remain the same */
VARABS
(
BOOL
,
VARIANT_TRUE
,
I2
,
-
VARIANT_TRUE
);
VARABS
(
BOOL
,
VARIANT_FALSE
,
I2
,
VARIANT_FALSE
);
VARABS
(
I2
,
1
,
I2
,
1
);
VARABS
(
I2
,
-
1
,
I2
,
1
);
VARABS
(
I4
,
1
,
I4
,
1
);
VARABS
(
I4
,
-
1
,
I4
,
1
);
VARABS
(
UI1
,
1
,
UI1
,
1
);
VARABS
(
R4
,
1
,
R4
,
1
);
VARABS
(
R4
,
-
1
,
R4
,
1
);
VARABS
(
R8
,
1
,
R8
,
1
);
VARABS
(
R8
,
-
1
,
R8
,
1
);
V_VT
(
&
v
)
=
VT_BSTR
;
V_BSTR
(
&
v
)
=
(
BSTR
)
szNum
;
memset
(
&
vDst
,
0
,
sizeof
(
vDst
));
hres
=
pVarAbs
(
&
v
,
&
vDst
);
ok
(
hres
==
S_OK
&&
V_VT
(
&
vDst
)
==
VT_R8
&&
V_R8
(
&
vDst
)
==
1
.
1
,
"VarAbs: expected 0x0,%d,%g, got 0x%lX,%d,%g
\n
"
,
VT_R8
,
1
.
1
,
hres
,
V_VT
(
&
vDst
),
V_R8
(
&
vDst
));
}
static
HRESULT
(
WINAPI
*
pVarNot
)(
LPVARIANT
,
LPVARIANT
);
#define VARNOT(vt,val,rvt,rval) V_VT(&v) = VT_##vt; V_##vt(&v) = val; \
memset(&vDst,0,sizeof(vDst)); hres = pVarNot(&v,&vDst); \
ok(hres == S_OK && V_VT(&vDst) == VT_##rvt && V_##rvt(&vDst) == (rval), \
"VarNot: expected 0x0,%d,%d, got 0x%lX,%d,%d\n", VT_##rvt, (int)(rval), \
hres, V_VT(&vDst), (int)V_##rvt(&vDst))
static
void
test_VarNot
(
void
)
{
static
const
WCHAR
szNum0
[]
=
{
'0'
,
'\0'
};
static
const
WCHAR
szNum1
[]
=
{
'1'
,
'\0'
};
HRESULT
hres
;
VARIANT
v
,
vDst
;
DECIMAL
*
pdec
=
&
V_DECIMAL
(
&
v
);
CY
*
pcy
=
&
V_CY
(
&
v
);
size_t
i
;
CHECKPTR
(
VarNot
);
/* Test all possible V_VT values */
for
(
i
=
0
;
i
<
sizeof
(
ExtraFlags
)
/
sizeof
(
ExtraFlags
[
0
]);
i
++
)
{
VARTYPE
vt
;
for
(
vt
=
0
;
vt
<=
VT_BSTR_BLOB
;
vt
++
)
{
HRESULT
hExpected
=
DISP_E_BADVARTYPE
;
memset
(
&
v
,
0
,
sizeof
(
v
));
V_VT
(
&
v
)
=
vt
|
ExtraFlags
[
i
];
V_VT
(
&
vDst
)
=
VT_EMPTY
;
hres
=
pVarNot
(
&
v
,
&
vDst
);
switch
(
V_VT
(
&
v
))
{
case
VT_I1
:
case
VT_UI1
:
case
VT_I2
:
case
VT_UI2
:
case
VT_INT
:
case
VT_UINT
:
case
VT_I4
:
case
VT_UI4
:
case
VT_I8
:
case
VT_UI8
:
case
VT_R4
:
case
VT_R8
:
case
VT_DECIMAL
:
case
VT_BOOL
:
case
VT_NULL
:
case
VT_EMPTY
:
case
VT_DATE
:
case
VT_CY
:
hExpected
=
S_OK
;
break
;
case
VT_UNKNOWN
:
case
VT_BSTR
:
case
VT_DISPATCH
:
case
VT_ERROR
:
case
VT_RECORD
:
hExpected
=
DISP_E_TYPEMISMATCH
;
break
;
default:
if
(
IsValidVariantClearVT
(
vt
,
ExtraFlags
[
i
])
&&
vt
!=
VT_CLSID
)
hExpected
=
DISP_E_TYPEMISMATCH
;
break
;
}
hres
=
pVarNot
(
&
v
,
&
vDst
);
if
(
V_VT
(
&
v
)
==
VT_DECIMAL
)
{
todo_wine
{
ok
(
hres
==
hExpected
,
"VarNot: expected 0x%lX, got 0x%lX vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
}
}
else
ok
(
hres
==
hExpected
,
"VarNot: expected 0x%lX, got 0x%lX vt %d|0x%X
\n
"
,
hExpected
,
hres
,
vt
,
ExtraFlags
[
i
]);
}
}
/* R4,R8,BSTR,DECIMAL,CY->I4, all others remain the same */
VARNOT
(
BOOL
,
VARIANT_TRUE
,
BOOL
,
VARIANT_FALSE
);
VARNOT
(
BOOL
,
VARIANT_FALSE
,
BOOL
,
VARIANT_TRUE
);
VARNOT
(
I2
,
-
1
,
I2
,
0
);
VARNOT
(
I2
,
0
,
I2
,
-
1
);
VARNOT
(
I2
,
1
,
I2
,
-
2
);
VARNOT
(
I4
,
1
,
I4
,
-
2
);
VARNOT
(
I4
,
0
,
I4
,
-
1
);
VARNOT
(
UI1
,
1
,
UI1
,
254
);
VARNOT
(
UI1
,
0
,
UI1
,
255
);
VARNOT
(
R4
,
1
,
I4
,
-
2
);
VARNOT
(
R4
,
0
,
I4
,
-
1
);
VARNOT
(
R8
,
1
,
I4
,
-
2
);
VARNOT
(
R8
,
0
,
I4
,
-
1
);
VARNOT
(
BSTR
,(
BSTR
)
szNum0
,
I4
,
-
1
);
VARNOT
(
BSTR
,(
BSTR
)
szNum1
,
I4
,
-
2
);
todo_wine
{
V_VT
(
&
v
)
=
VT_DECIMAL
;
pdec
->
u
.
s
.
sign
=
DECIMAL_NEG
;
pdec
->
u
.
s
.
scale
=
0
;
pdec
->
Hi32
=
0
;
pdec
->
u1
.
s1
.
Mid32
=
0
;
pdec
->
u1
.
s1
.
Lo32
=
1
;
VARNOT
(
DECIMAL
,
*
pdec
,
I4
,
0
);
pcy
->
int64
=
10000
;
VARNOT
(
CY
,
*
pcy
,
I4
,
-
2
);
}
}
START_TEST
(
vartest
)
{
hOleaut32
=
LoadLibraryA
(
"oleaut32.dll"
);
...
...
@@ -3525,6 +4255,8 @@ START_TEST(vartest)
test_variant
();
test_VariantInit
();
test_VariantClear
();
test_VariantCopy
();
test_VariantCopyInd
();
test_VarParseNumFromStr
();
test_VarNumFromParseNum
();
test_VarUdateFromDate
();
...
...
@@ -3533,4 +4265,8 @@ START_TEST(vartest)
test_VariantTimeToSystemTime
();
test_DosDateTimeToVariantTime
();
test_VariantTimeToDosDateTime
();
test_VarFormatNumber
();
test_VarFormat
();
test_VarAbs
();
test_VarNot
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment