[MSVCRT_WINETEST] Sync to wine-10.0

This commit is contained in:
Timo Kreuzer 2025-01-30 12:42:59 +02:00
parent 736fea6c44
commit 063c818c72
13 changed files with 3692 additions and 1657 deletions

View file

@ -1,4 +1,6 @@
remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS)
list(APPEND SOURCE
cpp.c
data.c
@ -15,7 +17,7 @@ list(APPEND SOURCE
time.c)
list(APPEND PCH_SKIP_SOURCE
printf.c # _CRT_NON_CONFORMING_SWPRINTFS
printf.c
testlist.c)
add_executable(msvcrt_winetest
@ -25,6 +27,8 @@ add_executable(msvcrt_winetest
target_compile_definitions(msvcrt_winetest PRIVATE
WINETEST_USE_DBGSTR_LONGLONG
_CRT_NONSTDC_NO_DEPRECATE
_USE_MATH_DEFINES
WIN32_NO_STATUS=
__msvcrt_ulong=ULONG)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
@ -34,13 +38,14 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
endif()
endif()
set_module_type(msvcrt_winetest win32cui)
add_importlibs(msvcrt_winetest advapi32 msvcrt kernel32)
target_link_libraries(msvcrt_winetest oldnames)
if(MSVC)
add_importlibs(msvcrt_winetest ntdll)
# 'swscanf' : unknown type field character '\xe1' in format specifier
target_compile_options(msvcrt_winetest PRIVATE /wd4476)
endif()
set_module_type(msvcrt_winetest win32cui)
add_importlibs(msvcrt_winetest advapi32 msvcrt kernel32 ntdll)
target_link_libraries(msvcrt_winetest oldnames)
add_pch(msvcrt_winetest precomp.h "${PCH_SKIP_SOURCE}")
add_rostests_file(TARGET msvcrt_winetest)

View file

@ -44,12 +44,8 @@ typedef struct __type_info
#endif
/* Function pointers. We need to use these to call these funcs as __thiscall */
static HMODULE hMsvcrt;
static void* (__cdecl *poperator_new)(unsigned int);
static void* (__cdecl *poperator_new)(size_t);
static void (__cdecl *poperator_delete)(void*);
static void* (__cdecl *pmalloc)(unsigned int);
static void (__cdecl *pfree)(void*);
/* exception */
static void (__thiscall *pexception_ctor)(exception*,LPCSTR*);
@ -112,9 +108,6 @@ static void* (__cdecl *p__RTDynamicCast)(void*,int,void*,void*,int);
static char* (__cdecl *p__unDName)(char*,const char*,int,void*,void*,unsigned short int);
/* _very_ early native versions have serious RTTI bugs, so we check */
static void* bAncientVersion;
/* Emulate a __thiscall */
#ifdef __i386__
@ -157,23 +150,12 @@ static void init_thiscall_thunk(void)
#endif /* __i386__ */
/* Some exports are only available in later versions */
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hmsvcrt,y)
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
static BOOL InitFunctionPtrs(void)
{
hMsvcrt = GetModuleHandleA("msvcrt.dll");
if (!hMsvcrt)
hMsvcrt = GetModuleHandleA("msvcrtd.dll");
ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
if (!hMsvcrt)
{
win_skip("Could not load msvcrt.dll\n");
return FALSE;
}
SET(pmalloc, "malloc");
SET(pfree, "free");
HMODULE hmsvcrt = GetModuleHandleA("msvcrt.dll");
SET(pexception_vtable, "??_7exception@@6B@");
SET(pbad_typeid_vtable, "??_7bad_typeid@@6B@");
@ -187,7 +169,6 @@ static BOOL InitFunctionPtrs(void)
SET(p__unDName,"__unDName");
/* Extremely early versions export logic_error, and crash in RTTI */
SETNOFAIL(bAncientVersion, "??0logic_error@@QAE@ABQBD@Z");
if (sizeof(void *) > sizeof(int)) /* 64-bit initialization */
{
SETNOFAIL(poperator_new, "??_U@YAPEAX_K@Z");
@ -242,50 +223,50 @@ static BOOL InitFunctionPtrs(void)
SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
SET(pexception_ctor, "??0exception@std@@QAA@ABQBD@Z");
SET(pexception_copy_ctor, "??0exception@std@@QAA@ABV01@@Z");
SET(pexception_default_ctor, "??0exception@std@@QAA@XZ");
SET(pexception_dtor, "??1exception@std@@UAA@XZ");
SET(pexception_opequals, "??4exception@std@@QAAAAV01@ABV01@@Z");
SET(pexception_what, "?what@exception@std@@UBAPBDXZ");
SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");/**/
SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");/**/
SET(pexception_ctor, "??0exception@@QAA@ABQBD@Z");
SET(pexception_copy_ctor, "??0exception@@QAA@ABV0@@Z");
SET(pexception_default_ctor, "??0exception@@QAA@XZ");
SET(pexception_dtor, "??1exception@@UAA@XZ");
SET(pexception_opequals, "??4exception@@QAAAAV0@ABV0@@Z");
SET(pexception_what, "?what@exception@@UBAPBDXZ");
pexception_vector_dtor = (void*)pexception_vtable[0];
pexception_scalar_dtor = (void*)pexception_vtable[0];
SET(pbad_typeid_ctor, "??0bad_typeid@std@@QAA@PBD@Z");
SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@std@@QAAXXZ");
SET(pbad_typeid_copy_ctor, "??0bad_typeid@std@@QAA@ABV01@@Z");
SET(pbad_typeid_dtor, "??1bad_typeid@std@@UAA@XZ");
SET(pbad_typeid_opequals, "??4bad_typeid@std@@QAAAAV01@ABV01@@Z");
SET(pbad_typeid_what, "?what@exception@std@@UBAPBDXZ");
SET(pbad_typeid_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
SET(pbad_typeid_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
SET(pbad_typeid_ctor, "??0bad_typeid@@QAA@PBD@Z");
SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QAAXXZ");
SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QAA@ABV0@@Z");
SET(pbad_typeid_dtor, "??1bad_typeid@@UAA@XZ");
SET(pbad_typeid_opequals, "??4bad_typeid@@QAAAAV0@ABV0@@Z");
SET(pbad_typeid_what, "?what@exception@@UBAPBDXZ");
pbad_typeid_vector_dtor = (void*)pbad_typeid_vtable[0];
pbad_typeid_scalar_dtor = (void*)pbad_typeid_vtable[0];
SETNOFAIL(pbad_cast_ctor, "??0bad_cast@@QAE@ABQBD@Z");
if (!pbad_cast_ctor)
SET(pbad_cast_ctor, "??0bad_cast@std@@AAA@PBQBD@Z");
SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@std@@QAA@PBD@Z");
SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@std@@QAAXXZ");
/* FIXME: No ARM equivalent for "??0bad_cast@@QAE@ABV0@@Z" */
SET(pbad_cast_dtor, "??1bad_cast@std@@UAA@XZ");
SET(pbad_cast_opequals, "??4bad_cast@std@@QAAAAV01@ABV01@@Z");
SET(pbad_cast_what, "?what@exception@std@@UBAPBDXZ");
SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
SET(pbad_cast_ctor, "??0bad_cast@@AAA@PBQBD@Z");
SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@@QAA@PBD@Z");
SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@@QAAXXZ");
SET(pbad_cast_copy_ctor, "??0bad_cast@@QAA@ABV0@@Z");
SET(pbad_cast_dtor, "??1bad_cast@@UAA@XZ");
SET(pbad_cast_opequals, "??4bad_cast@@QAAAAV0@ABV0@@Z");
SET(pbad_cast_what, "?what@exception@@UBAPBDXZ");
pbad_cast_vector_dtor = (void*)pbad_cast_vtable[0];
pbad_cast_scalar_dtor = (void*)pbad_cast_vtable[0];
SET(p__non_rtti_object_ctor, "??0__non_rtti_object@std@@QAA@PBD@Z");
SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@std@@QAA@ABV01@@Z");
SET(p__non_rtti_object_dtor, "??1__non_rtti_object@std@@UAA@XZ");
SET(p__non_rtti_object_opequals, "??4__non_rtti_object@std@@QAAAAV01@ABV01@@Z");
SET(p__non_rtti_object_what, "?what@exception@std@@UBAPBDXZ");
SET(p__non_rtti_object_vector_dtor, "??_E__non_rtti_object@@UAEPAXI@Z");
SET(p__non_rtti_object_scalar_dtor, "??_G__non_rtti_object@@UAEPAXI@Z");
SET(p__non_rtti_object_ctor, "??0__non_rtti_object@@QAA@PBD@Z");
SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QAA@ABV0@@Z");
SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UAA@XZ");
SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QAAAAV0@ABV0@@Z");
SET(p__non_rtti_object_what, "?what@exception@@UBAPBDXZ");
p__non_rtti_object_vector_dtor = (void*)p__non_rtti_object_vtable[0];
p__non_rtti_object_scalar_dtor = (void*)p__non_rtti_object_vtable[0];
SET(ptype_info_dtor, "??1type_info@@UAA@XZ");
SET(ptype_info_raw_name, "?raw_name@type_info@@QBAPBDXZ");
SET(ptype_info_name, "?name@type_info@@QBEPBDXZ");
SET(ptype_info_before, "?before@type_info@@QBA_NABV1@@Z");
SET(ptype_info_opequals_equals, "??8type_info@@QBA_NABV0@@Z");
SET(ptype_info_opnot_equals, "??9type_info@@QBA_NABV0@@Z");
SET(ptype_info_name, "?name@type_info@@QBAPBDXZ");
SET(ptype_info_before, "?before@type_info@@QBAHABV1@@Z");
SET(ptype_info_opequals_equals, "??8type_info@@QBAHABV0@@Z");
SET(ptype_info_opnot_equals, "??9type_info@@QBAHABV0@@Z");
#else
SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
@ -338,9 +319,9 @@ static BOOL InitFunctionPtrs(void)
}
if (!poperator_new)
poperator_new = pmalloc;
poperator_new = malloc;
if (!poperator_delete)
poperator_delete = pfree;
poperator_delete = free;
init_thiscall_thunk();
return TRUE;
@ -448,7 +429,7 @@ static void test_exception(void)
name = call_func1(pexception_what, &e);
ok(e.name == name, "Bad exception name from vtable e::what()\n");
if (p__RTtypeid && !bAncientVersion)
if (p__RTtypeid)
{
/* Check the rtti */
type_info *ti = p__RTtypeid(&e);
@ -571,7 +552,7 @@ static void test_bad_typeid(void)
name = call_func1(pbad_typeid_what, &e);
ok(e.name == name, "Bad bad_typeid name from vtable e::what()\n");
if (p__RTtypeid && !bAncientVersion)
if (p__RTtypeid)
{
/* Check the rtti */
type_info *ti = p__RTtypeid(&e);
@ -699,7 +680,7 @@ static void test_bad_cast(void)
name = call_func1(pbad_cast_what, &e);
ok(e.name == name, "Bad bad_cast name from vtable e::what()\n");
if (p__RTtypeid && !bAncientVersion)
if (p__RTtypeid)
{
/* Check the rtti */
type_info *ti = p__RTtypeid(&e);
@ -801,7 +782,7 @@ static void test___non_rtti_object(void)
name = call_func1(p__non_rtti_object_what, &e);
ok(e.name == name, "Bad __non_rtti_object name from vtable e::what()\n");
if (p__RTtypeid && !bAncientVersion)
if (p__RTtypeid)
{
/* Check the rtti */
type_info *ti = p__RTtypeid(&e);
@ -818,14 +799,14 @@ static void test_type_info(void)
char* name;
int res;
if (!pmalloc || !pfree || !ptype_info_dtor || !ptype_info_raw_name ||
if (!ptype_info_dtor || !ptype_info_raw_name ||
!ptype_info_name || !ptype_info_before ||
!ptype_info_opequals_equals || !ptype_info_opnot_equals)
return;
/* Test calling the dtors */
call_func1(ptype_info_dtor, &t1); /* No effect, since name is NULL */
t1.name = pmalloc(64);
t1.name = malloc(64);
strcpy(t1.name, "foo");
call_func1(ptype_info_dtor, &t1); /* Frees t1.name using 'free' */
@ -888,7 +869,7 @@ static inline void/*rtti_object_locator*/ *get_obj_locator( void *cppobj )
return (void *)vtable[-1];
}
#ifndef __x86_64__
#ifdef __i386__
#define DEFINE_RTTI_REF(type, name) type *name
#define RTTI_REF(instance, name) &instance.name
#define RTTI_REF_SIG0(instance, name, base) RTTI_REF(instance, name)
@ -910,33 +891,36 @@ static void test_rtti(void)
DEFINE_RTTI_REF(void, object_locator);
} *obj_locator;
struct _rtti_base_descriptor
{
DEFINE_RTTI_REF(type_info, type_descriptor);
int num_base_classes;
struct {
int this_offset;
int vbase_descr;
int vbase_offset;
} this_ptr_offsets;
unsigned int attributes;
};
struct _rtti_base_array {
DEFINE_RTTI_REF(struct _rtti_base_descriptor, bases[4]);
};
struct _rtti_object_hierarchy {
unsigned int signature;
unsigned int attributes;
int array_len;
DEFINE_RTTI_REF(struct _rtti_base_array, base_classes);
};
struct rtti_data
{
type_info type_info[4];
struct _rtti_base_descriptor
{
DEFINE_RTTI_REF(type_info, type_descriptor);
int num_base_classes;
struct {
int this_offset;
int vbase_descr;
int vbase_offset;
} this_ptr_offsets;
unsigned int attributes;
} base_descriptor[4];
struct _rtti_base_array {
DEFINE_RTTI_REF(struct _rtti_base_descriptor, bases[4]);
} base_array;
struct _rtti_object_hierarchy {
unsigned int signature;
unsigned int attributes;
int array_len;
DEFINE_RTTI_REF(struct _rtti_base_array, base_classes);
} object_hierarchy;
struct _rtti_base_descriptor base_descriptor[4];
struct _rtti_base_array base_array;
struct _rtti_object_hierarchy object_hierarchy;
struct _object_locator object_locator;
} simple_class_rtti = {
{ {NULL, NULL, "simple_class"} },
@ -962,11 +946,17 @@ static void test_rtti(void)
void *simple_class_vtbl[2] = {&simple_class_rtti.object_locator};
void *simple_class = &simple_class_vtbl[1];
void *child_class_vtbl[2] = {&child_class_rtti.object_locator};
void *child_class = &child_class_vtbl[1];
struct {
void *vtbl;
char data[4];
} child_class = { &child_class_vtbl[1] };
void *simple_class_sig0_vtbl[2] = {&simple_class_sig0_rtti.object_locator};
void *simple_class_sig0 = &simple_class_sig0_vtbl[1];
void *child_class_sig0_vtbl[2] = {&child_class_sig0_rtti.object_locator};
void *child_class_sig0 = &child_class_sig0_vtbl[1];
struct {
void *vtbl;
char data[4];
} child_class_sig0 = { &child_class_sig0_vtbl[1] };
void *virtual_base_class_vtbl[2] = {&virtual_base_class_rtti.object_locator};
int virtual_base_class_vbtbl[2] = {0, 0x100};
struct {
@ -980,12 +970,11 @@ static void test_rtti(void)
exception e,b;
void *casted;
BOOL old_signature;
#ifdef __x86_64__
#ifndef __i386__
char *base = (char*)GetModuleHandleW(NULL);
#endif
if (bAncientVersion ||
!p__RTCastToVoid || !p__RTtypeid || !pexception_ctor || !pbad_typeid_ctor
if (!p__RTCastToVoid || !p__RTtypeid || !pexception_ctor || !pbad_typeid_ctor
|| !p__RTDynamicCast || !pexception_dtor || !pbad_typeid_dtor)
return;
@ -1099,46 +1088,32 @@ static void test_demangle_datatype(void)
{
char * name;
struct _demangle demangle[]={
/* { "BlaBla"," ?? ::Bla", FALSE}, */
{ "ABVVec4@ref2@dice@@","class dice::ref2::Vec4 const &",TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0H@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,7>", TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HO@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,126>",TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOA@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,2016>",TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOAA@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,32256>",TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@", "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@", FALSE},
/* { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$011@@@", "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$011@@@",FALSE}, */
{ "BlaBla"," ?? ::Bla", FALSE},
{ "ABVVec4@ref2@dice@@", "class dice::ref2::Vec4 const &", TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0H@@@",
"class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,7>", TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HO@@@",
"class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,126>",TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOA@@@",
"class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,2016>",TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOAA@@@",
"class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,32256>",TRUE},
{ "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@",
"?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@", FALSE},
{ "P8test@@AACXZ", "signed char (__cdecl test::*)(void)", TRUE},
{ "P8test@@BACXZ", "signed char (__cdecl test::*)(void)const ", TRUE},
};
int i, num_test = ARRAY_SIZE(demangle);
for (i = 0; i < num_test; i++)
{
name = p__unDName(0, demangle[i].mangled, 0, pmalloc, pfree, 0x2800);
name = p__unDName(0, demangle[i].mangled, 0, malloc, free, 0x2800);
todo_wine_if (!demangle[i].test_in_wine)
ok(name != NULL && !strcmp(name,demangle[i].result), "Got name \"%s\" for %d\n", name, i);
if(name)
pfree(name);
free(name);
}
}
/* Compare two strings treating multiple spaces (' ', ascii 0x20) in s2
as single space. Needed for test_demangle as __unDName() returns sometimes
two spaces instead of one in some older native msvcrt dlls. */
static int strcmp_space(const char *s1, const char *s2)
{
const char* s2start = s2;
do {
while (*s1 == *s2 && *s1) {
s1++;
s2++;
}
if (*s2 == ' ' && s2 > s2start && *(s2 - 1) == ' ')
s2++;
else
break;
} while (*s1 && *s2);
return *s1 - *s2;
}
static void test_demangle(void)
{
static struct {const char* in; const char* out; const char *broken; unsigned int flags;} test[] = {
@ -1202,7 +1177,7 @@ static void test_demangle(void)
/* 23 */ {"??0streambuf@@QAE@ABV0@@Z", "public: __thiscall streambuf::streambuf(class streambuf const &)"},
/* 24 */ {"??0strstreambuf@@QAE@ABV0@@Z", "public: __thiscall strstreambuf::strstreambuf(class strstreambuf const &)"},
/* 25 */ {"??0strstreambuf@@QAE@H@Z", "public: __thiscall strstreambuf::strstreambuf(int)"},
/* 26 */ {"??0strstreambuf@@QAE@P6APAXJ@ZP6AXPAX@Z@Z", "public: __thiscall strstreambuf::strstreambuf(void * (__cdecl*)(long),void (__cdecl*)(void *))"},
/* 26 */ {"??0strstreambuf@@QAE@Q6APAXJ@ZS6AXPAX@Z@Z", "public: __thiscall strstreambuf::strstreambuf(void * (__cdecl*const)(long),void (__cdecl*const volatile)(void *))"},
/* 27 */ {"??0strstreambuf@@QAE@PADH0@Z", "public: __thiscall strstreambuf::strstreambuf(char *,int,char *)"},
/* 28 */ {"??0strstreambuf@@QAE@PAEH0@Z", "public: __thiscall strstreambuf::strstreambuf(unsigned char *,int,unsigned char *)"},
/* 29 */ {"??0strstreambuf@@QAE@XZ", "public: __thiscall strstreambuf::strstreambuf(void)"},
@ -1237,7 +1212,7 @@ static void test_demangle(void)
/* 58 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::ios_base &,int &,long &)const "},
/* 59 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::ios_base &,int &,unsigned long &)const "},
/* 60 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::ios_base &,int &,float &)const "},
/* 61 */ {"?_query_new_handler@@YAP6AHI@ZXZ", "int (__cdecl*__cdecl _query_new_handler(void))(unsigned int)"},
/* 61 */ {"?_query_new_handler@@YAR6AHI@ZXZ", "int (__cdecl*__cdecl _query_new_handler(void))(unsigned int)"},
/* 62 */ {"?register_callback@ios_base@std@@QAEXP6AXW4event@12@AAV12@H@ZH@Z", "public: void __thiscall std::ios_base::register_callback(void (__cdecl*)(enum std::ios_base::event,class std::ios_base &,int),int)"},
/* 63 */ {"?seekg@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV12@JW4seekdir@ios_base@2@@Z", "public: class std::basic_istream<char,struct std::char_traits<char> > & __thiscall std::basic_istream<char,struct std::char_traits<char> >::seekg(long,enum std::ios_base::seekdir)"},
/* 64 */ {"?seekg@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV12@V?$fpos@H@2@@Z", "public: class std::basic_istream<char,struct std::char_traits<char> > & __thiscall std::basic_istream<char,struct std::char_traits<char> >::seekg(class std::fpos<int>)"},
@ -1325,22 +1300,54 @@ static void test_demangle(void)
"??$run@XVTask_Render_Preview@@@QtConcurrent@@YA?AV?$QFuture@X@@PEAVTask_Render_Preview@@P82@EAAXXZ@Z"},
/* 130 */ {"??_E?$TStrArray@$$BY0BAA@D$0BA@@@UAEPAXI@Z",
"public: virtual void * __thiscall TStrArray<char [256],16>::`vector deleting destructor'(unsigned int)"},
/* 131 */ {"??_R0?AVCC@DD@@@8", "class DD::CC `RTTI Type Descriptor'"},
/* 132 */ {"??$meth@FD@DD@CC@@QAE_NK@Z", "public: bool __thiscall CC::DD::meth<short,char>(unsigned long)"},
/* 133 */ {"?func@@YAXPIFAH@Z", "void __cdecl func(int __unaligned * __restrict)"},
/* 135 */ {"?x@@3PAY02HA", "int (* x)[3]"},
/* 136 */ {"?Qux@Bar@@0PAPAP6AHPAV1@AAH1PAH@ZA",
"private: static int (__cdecl** * Bar::Qux)(class Bar *,int &,int &,int *)"}, /* variation of 105: note white space handling! */
/* 137 */ {"?x@@3PAW4myenum@@A", "enum myenum * x"},
/* 138 */ {"?pfunc@@3PAY0E@P6AXF@ZA", "void (__cdecl*(* pfunc)[4])(short)"},
/* 139 */ {"??$?0AEAVzzz@BB4@AA@@AEAV012@$0A@@?$pair@Vzzz@BB4@AA@@V123@@std@@QEAA@AEAVzzz@BB4@AA@@0@Z",
"public: __cdecl std::pair<class AA::BB4::zzz,class AA::BB4::zzz>::pair<class AA::BB4::zzz,class AA::BB4::zzz><class AA::BB4::zzz & __ptr64,class AA::BB4::zzz & __ptr64,0>(class AA::BB4::zzz & __ptr64,class AA::BB4::zzz & __ptr64) __ptr64"},
/* 140 */ {"??$?BH@?$foo@N@@QEAAHXZ", "public: __cdecl foo<double>::operator<int> int(void) __ptr64"},
/* 141 */ {"??Bcastop@@QAEHXZ", "public: __thiscall castop::operator int(void)"},
/* 142 */ {"??Bcastop@@QAE?BHXZ", "public: __thiscall castop::operator int const (void)"},
/* 143 */ {"?pfield@@3PTAA@@DT1@", "char const volatile AA::* const volatile pfield"},
/* 144 */ {"?ptititi1@@3PEQtititi@@IEQ1@", "unsigned int tititi::* __ptr64 __ptr64 ptititi1"},
/* 145 */ {"?ptititi2@@3PERtititi@@IER1@", "unsigned int const tititi::* __ptr64 const __ptr64 ptititi2"},
/* 146 */ {"?ptititi3@@3PEStititi@@IES1@", "unsigned int volatile tititi::* __ptr64 volatile __ptr64 ptititi3"},
/* 147 */ {"?ptititi4@@3PETtititi@@IET1@", "unsigned int const volatile tititi::* __ptr64 const volatile __ptr64 ptititi4"},
/* 148 */ {"?ptititi4v@@3RETtititi@@IET1@", "unsigned int const volatile tititi::* __ptr64 const volatile __ptr64 ptititi4v"},
/* 149 */ {"?meth@AAA@@QFCEXXZ", "public: void __thiscall AAA::meth(void)volatile __unaligned "},
/* 150 */ {"?RegisterModuleUninitializer@<CrtImplementationDetails>@@YAXP$AAVEventHandler@System@@@Z",
"void __cdecl <CrtImplementationDetails>::RegisterModuleUninitializer(class System::EventHandler ^)"},
/* 151 */ {"?RegisterModuleUninitializer@<CrtImplementationDetails>@@YAXBE$AAVEventHandler@System@@@Z",
"void __cdecl <CrtImplementationDetails>::RegisterModuleUninitializer(class System::EventHandler % __ptr64 volatile)"},
/* 152 */ {"??$forward@AEAUFFIValue@?1??call@FFIFunctionBinder@@CAHPEAUlua_State@@@Z@@std@@YAAEAUFFIValue@?1??call@"
"FFIFunctionBinder@@CAHPEAUxlua_State@@@Z@AEAU1?1??23@CAH0@Z@@Z",
"struct `private: static int __cdecl FFIFunctionBinder::call(struct xlua_State * __ptr64)'::`2'::FFIValue & "
"__ptr64 __cdecl std::forward<struct `private: static int __cdecl FFIFunctionBinder::call(struct lua_State "
"* __ptr64)'::`2'::FFIValue & __ptr64>(struct `private: static int __cdecl FFIFunctionBinder::call(struct "
"xlua_State * __ptr64)'::`2'::FFIValue & __ptr64)"},
/* 153 */ {"?$AAA@XX", "AAA<void,void>"},
/* 154 */ {"?$AAA@", "AAA<>"},
};
int i, num_test = ARRAY_SIZE(test);
int i;
char* name;
for (i = 0; i < num_test; i++)
for (i = 0; i < ARRAY_SIZE(test); i++)
{
name = p__unDName(0, test[i].in, 0, pmalloc, pfree, test[i].flags);
name = p__unDName(0, test[i].in, 0, malloc, free, test[i].flags);
ok(name != NULL, "%u: unDName failed\n", i);
if (!name) continue;
ok( !strcmp_space(test[i].out, name) ||
broken(test[i].broken && !strcmp_space(test[i].broken, name)),
ok( !strcmp(test[i].out, name) ||
broken(test[i].broken && !strcmp(test[i].broken, name)),
"%u: Got name \"%s\"\n", i, name );
ok( !strcmp_space(test[i].out, name) ||
broken(test[i].broken && !strcmp_space(test[i].broken, name)),
ok( !strcmp(test[i].out, name) ||
broken(test[i].broken && !strcmp(test[i].broken, name)),
"%u: Expected \"%s\"\n", i, test[i].out );
pfree(name);
free(name);
}
}

View file

@ -32,7 +32,11 @@
#include <errno.h>
#include <direct.h>
void __cdecl __getmainargs(int *, char ***, char ***, int, int *);
#ifdef __REACTOS__
_CRTIMP void __cdecl __getmainargs(int *, char ***, char ***, int, int *);
_CRTIMP void __cdecl __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);
#endif
static int* (__cdecl *p___p___argc)(void);
static char*** (__cdecl *p___p___argv)(void);
@ -92,12 +96,12 @@ static void test_initvar( HMODULE hmsvcrt )
winminor = *pp_winminor;
winmajor = *pp_winmajor;
GetVersionExA( &osvi);
ok( winminor == osvi.dwMinorVersion, "Wrong value for _winminor %02x expected %02x\n",
ok( winminor == osvi.dwMinorVersion, "Wrong value for _winminor %02x expected %02lx\n",
winminor, osvi.dwMinorVersion);
ok( winmajor == osvi.dwMajorVersion, "Wrong value for _winmajor %02x expected %02x\n",
ok( winmajor == osvi.dwMajorVersion, "Wrong value for _winmajor %02x expected %02lx\n",
winmajor, osvi.dwMajorVersion);
ok( winver == ((osvi.dwMajorVersion << 8) | osvi.dwMinorVersion),
"Wrong value for _winver %02x expected %02x\n",
"Wrong value for _winver %02x expected %02lx\n",
winver, ((osvi.dwMajorVersion << 8) | osvi.dwMinorVersion));
if( !pp_osver || !pp_osplatform ) {
win_skip("_osver variables are not available\n");
@ -108,10 +112,10 @@ static void test_initvar( HMODULE hmsvcrt )
ok( osver == (osvi.dwBuildNumber & 0xffff) ||
((osvi.dwBuildNumber >> 24) == osvi.dwMajorVersion &&
((osvi.dwBuildNumber >> 16) & 0xff) == osvi.dwMinorVersion), /* 95/98/ME */
"Wrong value for _osver %04x expected %04x\n",
"Wrong value for _osver %04x expected %04lx\n",
osver, osvi.dwBuildNumber);
ok(osplatform == osvi.dwPlatformId,
"Wrong value for _osplatform %x expected %x\n",
"Wrong value for _osplatform %x expected %lx\n",
osplatform, osvi.dwPlatformId);
}
@ -133,7 +137,7 @@ static void test___getmainargs(void)
{
int argc, new_argc, mode;
char **argv, **new_argv, **envp;
char tmppath[MAX_PATH], filepath[MAX_PATH];
char tmppath[MAX_PATH], filepath[MAX_PATH + 14];
FILE *f;
ok(GetTempPathA(MAX_PATH, tmppath) != 0, "GetTempPath failed\n");
@ -194,7 +198,7 @@ static void test___getmainargs(void)
static void test___getmainargs_parent(char *name)
{
char cmdline[3*MAX_PATH];
char tmppath[MAX_PATH], filepath[MAX_PATH];
char tmppath[MAX_PATH], filepath[MAX_PATH + 14];
STARTUPINFOA startup;
PROCESS_INFORMATION proc;
FILE *f;
@ -218,7 +222,7 @@ static void test___getmainargs_parent(char *name)
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
winetest_wait_child_process(proc.hProcess);
wait_child_process(proc.hProcess);
_unlink(filepath);
sprintf(filepath, "%swine_test\\a", tmppath);

View file

@ -138,36 +138,6 @@ static void test_makepath(void)
}
}
static const WCHAR expected0[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'};
static const WCHAR expected1[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'};
static const WCHAR expected2[] = {'\0',':','X','X','X','X','X','X','X','X','X','X','X'};
static const WCHAR expected3[] = {'\0',':','d','X','X','X','X','X','X','X','X','X','X'};
static const WCHAR expected4[] = {'\0',':','d','\\','X','X','X','X','X','X','X','X','X'};
static const WCHAR expected5[] = {'\0',':','d','\\','f','X','X','X','X','X','X','X','X'};
static const WCHAR expected6[] = {'\0',':','d','\\','f','i','X','X','X','X','X','X','X'};
static const WCHAR expected7[] = {'\0',':','d','\\','f','i','l','X','X','X','X','X','X'};
static const WCHAR expected8[] = {'\0',':','d','\\','f','i','l','e','X','X','X','X','X'};
static const WCHAR expected9[] = {'\0',':','d','\\','f','i','l','e','.','X','X','X','X'};
static const WCHAR expected10[] = {'\0',':','d','\\','f','i','l','e','.','e','X','X','X'};
static const WCHAR expected11[] = {'\0',':','d','\\','f','i','l','e','.','e','x','X','X'};
static const WCHAR expected12[] = {'\0',':','X','X','X','X','X','X','X','X'};
static const WCHAR expected13[] = {'\0',':','d','X','X','X','X','X','X','X'};
static const WCHAR expected14[] = {'\0',':','d','i','X','X','X','X','X','X'};
static const WCHAR expected15[] = {'\0',':','d','i','r','X','X','X','X','X'};
static const WCHAR expected16[] = {'\0',':','d','i','r','\\','X','X','X','X'};
static const WCHAR expected17[] = {'\0','o','o'};
static const WCHAR expected18[] = {'\0','o','o','\0','X'};
static const WCHAR expected19[] = {'\0','o','o','\0'};
static const WCHAR expected20[] = {'\0','o','o','\0','X','X','X','X','X'};
static const WCHAR expected21[] = {'\0','o','o','\\','f','i','l','X','X'};
static const WCHAR expected22[] = {'\0','o','o','\0','X','X','X','X','X','X','X','X','X'};
static const WCHAR expected23[] = {'\0','o','o','\\','f','i','l','X','X','X','X','X','X'};
static const WCHAR expected24[] = {'\0','o','o','\\','f','i','l','e','.','e','x','X','X'};
static const WCHAR expected25[] = {'\0','o','o','\0','X','X','X','X'};
static const WCHAR expected26[] = {'\0','o','o','.','e','x','X','X'};
typedef struct
{
const char* buffer;
@ -184,35 +154,35 @@ typedef struct
static const makepath_s_case makepath_s_cases[] =
{
/* Behavior with directory parameter containing backslash. */
{NULL, 1, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected0, 13},
{NULL, 2, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected1, 13},
{NULL, 3, "c:", "d\\", "file", "ext", "\0:XXXXXXXXXXX", expected2, 13},
{NULL, 4, "c:", "d\\", "file", "ext", "\0:dXXXXXXXXXX", expected3, 13},
{NULL, 5, "c:", "d\\", "file", "ext", "\0:d\\XXXXXXXXX", expected4, 13},
{NULL, 6, "c:", "d\\", "file", "ext", "\0:d\\fXXXXXXXX", expected5, 13},
{NULL, 7, "c:", "d\\", "file", "ext", "\0:d\\fiXXXXXXX", expected6, 13},
{NULL, 8, "c:", "d\\", "file", "ext", "\0:d\\filXXXXXX", expected7, 13},
{NULL, 9, "c:", "d\\", "file", "ext", "\0:d\\fileXXXXX", expected8, 13},
{NULL, 10, "c:", "d\\", "file", "ext", "\0:d\\file.XXXX", expected9, 13},
{NULL, 11, "c:", "d\\", "file", "ext", "\0:d\\file.eXXX", expected10, 13},
{NULL, 12, "c:", "d\\", "file", "ext", "\0:d\\file.exXX", expected11, 13},
{NULL, 1, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", L"\0XXXXXXXXXXXX", 13},
{NULL, 2, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", L"\0XXXXXXXXXXXX", 13},
{NULL, 3, "c:", "d\\", "file", "ext", "\0:XXXXXXXXXXX", L"\0:XXXXXXXXXXX", 13},
{NULL, 4, "c:", "d\\", "file", "ext", "\0:dXXXXXXXXXX", L"\0:dXXXXXXXXXX", 13},
{NULL, 5, "c:", "d\\", "file", "ext", "\0:d\\XXXXXXXXX", L"\0:d\\XXXXXXXXX", 13},
{NULL, 6, "c:", "d\\", "file", "ext", "\0:d\\fXXXXXXXX", L"\0:d\\fXXXXXXXX", 13},
{NULL, 7, "c:", "d\\", "file", "ext", "\0:d\\fiXXXXXXX", L"\0:d\\fiXXXXXXX", 13},
{NULL, 8, "c:", "d\\", "file", "ext", "\0:d\\filXXXXXX", L"\0:d\\filXXXXXX", 13},
{NULL, 9, "c:", "d\\", "file", "ext", "\0:d\\fileXXXXX", L"\0:d\\fileXXXXX", 13},
{NULL, 10, "c:", "d\\", "file", "ext", "\0:d\\file.XXXX", L"\0:d\\file.XXXX", 13},
{NULL, 11, "c:", "d\\", "file", "ext", "\0:d\\file.eXXX", L"\0:d\\file.eXXX", 13},
{NULL, 12, "c:", "d\\", "file", "ext", "\0:d\\file.exXX", L"\0:d\\file.exXX", 13},
/* Behavior with directory parameter lacking backslash. */
{NULL, 3, "c:", "dir", "f", "ext", "\0:XXXXXXXX", expected12, 10},
{NULL, 4, "c:", "dir", "f", "ext", "\0:dXXXXXXX", expected13, 10},
{NULL, 5, "c:", "dir", "f", "ext", "\0:diXXXXXX", expected14, 10},
{NULL, 6, "c:", "dir", "f", "ext", "\0:dirXXXXX", expected15, 10},
{NULL, 7, "c:", "dir", "f", "ext", "\0:dir\\XXXX", expected16, 10},
{NULL, 3, "c:", "dir", "f", "ext", "\0:XXXXXXXX", L"\0:XXXXXXXX", 10},
{NULL, 4, "c:", "dir", "f", "ext", "\0:dXXXXXXX", L"\0:dXXXXXXX", 10},
{NULL, 5, "c:", "dir", "f", "ext", "\0:diXXXXXX", L"\0:diXXXXXX", 10},
{NULL, 6, "c:", "dir", "f", "ext", "\0:dirXXXXX", L"\0:dirXXXXX", 10},
{NULL, 7, "c:", "dir", "f", "ext", "\0:dir\\XXXX", L"\0:dir\\XXXX", 10},
/* Behavior with overlapped buffer. */
{"foo", 2, USE_BUFF, NULL, NULL, NULL, "\0oo", expected17, 3},
{"foo", 4, NULL, USE_BUFF, NULL, NULL, "\0oo\0X", expected18, 5},
{"foo", 3, NULL, NULL, USE_BUFF, NULL, "\0oo\0", expected19, 4},
{"foo", 4, NULL, USE_BUFF, "file", NULL, "\0oo\0XXXXX", expected20, 9},
{"foo", 8, NULL, USE_BUFF, "file", NULL, "\0oo\\filXX", expected21, 9},
{"foo", 4, NULL, USE_BUFF, "file", "ext", "\0oo\0XXXXXXXXX", expected22, 13},
{"foo", 8, NULL, USE_BUFF, "file", "ext", "\0oo\\filXXXXXX", expected23, 13},
{"foo", 12, NULL, USE_BUFF, "file", "ext", "\0oo\\file.exXX", expected24, 13},
{"foo", 4, NULL, NULL, USE_BUFF, "ext", "\0oo\0XXXX", expected25, 8},
{"foo", 7, NULL, NULL, USE_BUFF, "ext", "\0oo.exXX", expected26, 8},
{"foo", 2, USE_BUFF, NULL, NULL, NULL, "\0oo", L"\0oo", 3},
{"foo", 4, NULL, USE_BUFF, NULL, NULL, "\0oo\0X", L"\0oo\0X", 5},
{"foo", 3, NULL, NULL, USE_BUFF, NULL, "\0oo\0", L"\0oo", 4},
{"foo", 4, NULL, USE_BUFF, "file", NULL, "\0oo\0XXXXX", L"\0oo\0XXXXX", 9},
{"foo", 8, NULL, USE_BUFF, "file", NULL, "\0oo\\filXX", L"\0oo\\filXX", 9},
{"foo", 4, NULL, USE_BUFF, "file", "ext", "\0oo\0XXXXXXXXX", L"\0oo\0XXXXXXXXX", 13},
{"foo", 8, NULL, USE_BUFF, "file", "ext", "\0oo\\filXXXXXX", L"\0oo\\filXXXXXX", 13},
{"foo", 12, NULL, USE_BUFF, "file", "ext", "\0oo\\file.exXX", L"\0oo\\file.exXX", 13},
{"foo", 4, NULL, NULL, USE_BUFF, "ext", "\0oo\0XXXX", L"\0oo\0XXXX", 8},
{"foo", 7, NULL, NULL, USE_BUFF, "ext", "\0oo.exXX", L"\0oo.exXX", 8},
};
static void test_makepath_s(void)
@ -438,10 +408,6 @@ static void test_searchenv(void)
"\\search_env_test\\dir3longer\\3.dat"
};
const WCHAR env_w[] = {'T','E','S','T','_','P','A','T','H',0};
const WCHAR dat1_w[] = {'1','.','d','a','t',0};
const WCHAR dat3_w[] = {'3','.','d','a','t',0};
char env1[4*MAX_PATH], env2[4*MAX_PATH], tmppath[MAX_PATH], path[2*MAX_PATH];
char result[MAX_PATH], exp[2*MAX_PATH];
WCHAR result_w[MAX_PATH];
@ -510,13 +476,13 @@ static void test_searchenv(void)
}
memset(result_w, 'x', sizeof(result_w));
_wsearchenv(dat1_w, env_w, result_w);
_wsearchenv(L"1.dat", L"TEST_PATH", result_w);
WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
if (p_wsearchenv_s) {
memset(result_w, 'x', sizeof(result_w));
i = p_wsearchenv_s(dat1_w, env_w, result_w, MAX_PATH);
i = p_wsearchenv_s(L"1.dat", L"TEST_PATH", result_w, MAX_PATH);
ok(!i, "wsearchenv_s returned %d\n", i);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
}
@ -535,13 +501,13 @@ static void test_searchenv(void)
}
memset(result_w, 'x', sizeof(result_w));
_wsearchenv(dat3_w, env_w, result_w);
_wsearchenv(L"3.dat", L"TEST_PATH", result_w);
WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
if (p_wsearchenv_s) {
memset(result_w, 'x', sizeof(result_w));
i = p_wsearchenv_s(dat3_w, env_w, result_w, MAX_PATH);
i = p_wsearchenv_s(L"3.dat", L"TEST_PATH", result_w, MAX_PATH);
ok(!i, "wsearchenv_s returned %d\n", i);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
}
@ -561,13 +527,13 @@ static void test_searchenv(void)
}
memset(result_w, 'x', sizeof(result_w));
_wsearchenv(dat1_w, env_w, result_w);
_wsearchenv(L"1.dat", L"TEST_PATH", result_w);
WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
if (p_wsearchenv_s) {
memset(result_w, 'x', sizeof(result_w));
i = p_wsearchenv_s(dat1_w, env_w, result_w, MAX_PATH);
i = p_wsearchenv_s(L"1.dat", L"TEST_PATH", result_w, MAX_PATH);
ok(!i, "wsearchenv_s returned %d\n", i);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
}
@ -586,17 +552,31 @@ static void test_searchenv(void)
}
memset(result_w, 'x', sizeof(result_w));
_wsearchenv(dat3_w, env_w, result_w);
_wsearchenv(L"3.dat", L"TEST_PATH", result_w);
WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
if (p_wsearchenv_s) {
memset(result_w, 'x', sizeof(result_w));
i = p_wsearchenv_s(dat3_w, env_w, result_w, MAX_PATH);
i = p_wsearchenv_s(L"3.dat", L"TEST_PATH", result_w, MAX_PATH);
ok(!i, "wsearchenv_s returned %d\n", i);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
}
strcpy(env1, "TEST_PATH=");
strcat(env1, tmppath);
strcat(env1, "\"\\search_env_test\\\"d\"i\"r\"1");
putenv(env1);
strcpy(exp, tmppath);
strcat(exp, files[0]);
_searchenv("1.dat", "TEST_PATH", result);
ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp);
strcat(env1, ";");
putenv(env1);
_searchenv("1.dat", "TEST_PATH", result);
ok(!result[0], "got %s, expected ''\n", result);
putenv("TEST_PATH=");
for (i=ARRAY_SIZE(files)-1; i>=0; i--) {

View file

@ -19,7 +19,15 @@
*/
#include "wine/test.h"
#include <errno.h>
#include <stdlib.h>
#include <process.h>
#include <winnls.h>
#ifdef __REACTOS__
_CRTIMP void __cdecl __getmainargs(int *, char ***, char ***, int, int *);
_CRTIMP void __cdecl __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);
#endif
static const char *a_very_long_env_string =
"LIBRARY_PATH="
@ -42,13 +50,15 @@ static const char *a_very_long_env_string =
"/usr/lib/mingw32/3.4.2/;"
"/usr/lib/";
void __cdecl __getmainargs(int *, char ***, char ***, int, int *);
void __cdecl __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);
static char ***(__cdecl *p__p__environ)(void);
static WCHAR ***(__cdecl *p__p__wenviron)(void);
static void (*p_get_environ)(char ***);
static void (*p_get_wenviron)(WCHAR ***);
static char ***(__cdecl *p__p___initenv)(void);
static wchar_t ***(__cdecl *p__p___winitenv)(void);
static void (__cdecl *p_get_environ)(char ***);
static void (__cdecl *p_get_wenviron)(WCHAR ***);
static errno_t (__cdecl *p_putenv_s)(const char*, const char*);
static errno_t (__cdecl *p_wputenv_s)(const wchar_t*, const wchar_t*);
static errno_t (__cdecl *p_getenv_s)(size_t*, char*, size_t, const char*);
static char ***p_environ;
static WCHAR ***p_wenviron;
@ -59,10 +69,15 @@ static void init(void)
p__p__environ = (void *)GetProcAddress(hmod, "__p__environ");
p__p__wenviron = (void *)GetProcAddress(hmod, "__p__wenviron");
p__p___initenv = (void *)GetProcAddress(hmod, "__p___initenv");
p__p___winitenv = (void *)GetProcAddress(hmod, "__p___winitenv");
p_environ = (void *)GetProcAddress(hmod, "_environ");
p_wenviron = (void *)GetProcAddress(hmod, "_wenviron");
p_get_environ = (void *)GetProcAddress(hmod, "_get_environ");
p_get_wenviron = (void *)GetProcAddress(hmod, "_get_wenviron");
p_putenv_s = (void *)GetProcAddress(hmod, "_putenv_s");
p_wputenv_s = (void *)GetProcAddress(hmod, "_wputenv_s");
p_getenv_s = (void *)GetProcAddress(hmod, "getenv_s");
}
static void test_system(void)
@ -74,30 +89,46 @@ static void test_system(void)
ok(ret == 0, "Expected system to return 0, got %d\n", ret);
}
static unsigned env_get_entry_countA( char **env )
{
unsigned count;
if (!env) return 0;
for (count = 0; env[count] != NULL; count++) {}
return count;
}
static wchar_t *env_get_valueW( wchar_t **envp, const wchar_t *var )
{
unsigned i;
size_t len = wcslen( var );
if (!envp) return NULL;
for (i = 0; envp[i] != NULL; i++)
{
wchar_t *ptr;
if (!(ptr = wcschr( envp[i], L'=' ))) continue;
if (ptr - envp[i] == len && !memcmp( envp[i], var, len * sizeof(wchar_t) ))
return ptr + 1;
}
return NULL;
}
static void test__environ(void)
{
int argc;
char **argv, **envp = NULL;
int i, mode = 0;
char **argv, **envp = NULL, **initenv = NULL;
int mode = 0;
ok( p_environ != NULL, "Expected the pointer to _environ to be non-NULL\n" );
if (p_environ)
ok( *p_environ != NULL, "Expected _environ to be initialized on startup\n" );
ok( *p_environ != NULL, "Expected _environ to be initialized on startup\n" );
if (!p_environ || !*p_environ)
{
skip( "_environ pointers are not valid\n" );
return;
}
/* Examine the returned pointer from __p__environ(), if available. */
if (p__p__environ)
{
ok( *p__p__environ() == *p_environ,
"Expected _environ pointers to be identical\n" );
}
if (sizeof(void*) != sizeof(int))
ok( !p__p__environ, "__p__environ() should be 32-bit only\n");
else
skip( "__p__environ() is not available\n" );
ok( *p__p__environ() == *p_environ, "Expected _environ pointers to be identical\n" );
if (p_get_environ)
{
@ -109,76 +140,74 @@ static void test__environ(void)
else
win_skip( "_get_environ() is not available\n" );
if (p__p___initenv)
{
initenv = *p__p___initenv();
ok( initenv == *p_environ,
"Expected _environ to be equal to initial env\n" );
}
else
skip( "__p___initenv() is not available\n" );
/* Note that msvcrt from Windows versions older than Vista
* expects the mode pointer parameter to be valid.*/
__getmainargs(&argc, &argv, &envp, 0, &mode);
ok( envp != NULL, "Expected initial environment block pointer to be non-NULL\n" );
if (!envp)
{
skip( "Initial environment block pointer is not valid\n" );
return;
}
ok( envp != NULL,
"Expected initial environment block pointer to be non-NULL\n" );
ok( envp == *p_environ,
"Expected initial environment to be equal to _environ\n" );
for (i = 0; ; i++)
ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" );
if (p__p___initenv)
{
if ((*p_environ)[i])
{
ok( envp[i] != NULL, "Expected environment block pointer element to be non-NULL\n" );
ok( !strcmp((*p_environ)[i], envp[i]),
"Expected _environ and environment block pointer strings (%s vs. %s) to match\n",
(*p_environ)[i], envp[i] );
}
else
{
ok( !envp[i], "Expected environment block pointer element to be NULL, got %p\n", envp[i] );
break;
}
char **retptr = *p__p___initenv();
ok( retptr != *p_environ,
"Expected _environ[] not to be equal to initial env\n" );
ok( retptr == initenv,
"Unexpected modification of initial env\n" );
}
ok( _putenv("cat=") == 0, "failed setting cat=\n" );
}
static void test__wenviron(void)
{
static const WCHAR cat_eq_dogW[] = {'c','a','t','=','d','o','g',0};
static const WCHAR cat_eqW[] = {'c','a','t','=',0};
int argc;
char **argv, **envp = NULL;
WCHAR **wargv, **wenvp = NULL;
int i, mode = 0;
int mode = 0;
ok( p_wenviron != NULL, "Expected the pointer to _wenviron to be non-NULL\n" );
if (p_wenviron)
ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron );
else
{
win_skip( "Pointer to _wenviron is not valid\n" );
return;
}
ok( !*p_wenviron, "Expected _wenviron[] to be NULL, got %p\n", *p_wenviron );
/* Examine the returned pointer from __p__wenviron(), if available. */
if (p__p__wenviron)
{
ok( *p__p__wenviron() == NULL,
"Expected _wenviron pointers to be NULL\n" );
}
if (sizeof(void*) != sizeof(int))
ok( !p__p__wenviron, "__p__wenviron() should be 32-bit only\n");
else
skip( "__p__wenviron() is not available\n" );
ok( !*p__p__wenviron(), "Expected _wenviron to be NULL, got %p\n", *p_wenviron );
if (p_get_wenviron)
{
WCHAR **retptr;
p_get_wenviron(&retptr);
ok( retptr == NULL,
"Expected _wenviron pointers to be NULL\n" );
ok( retptr == *p_wenviron, "Expected _wenviron pointers to be NULL\n" );
}
else
win_skip( "_get_wenviron() is not available\n" );
if (p__p___winitenv)
{
wchar_t ***retptr = p__p___winitenv();
ok( !*retptr, "Expected initial env to be NULL\n" );
}
else
skip( "__p___winitenv() is not available\n" );
/* __getmainargs doesn't initialize _wenviron. */
__getmainargs(&argc, &argv, &envp, 0, &mode);
ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron);
ok( !*p_wenviron, "Expected _wenviron to be NULL\n");
ok( envp != NULL, "Expected initial environment block pointer to be non-NULL\n" );
if (!envp)
{
@ -188,24 +217,31 @@ static void test__wenviron(void)
/* Neither does calling the non-Unicode environment manipulation functions. */
ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" );
ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron);
ok( _putenv("cat=") == 0, "failed deleting cat\n" );
ok( !*p_wenviron, "Expected _wenviron to be NULL\n" );
/* _wenviron isn't initialized until __wgetmainargs is called or
* one of the Unicode environment manipulation functions is called. */
ok( _wputenv(cat_eq_dogW) == 0, "failed setting cat=dog\n" );
ok( _wputenv(L"cat=dog2") == 0, "failed setting cat=dog2\n" );
ok( *p_wenviron != NULL, "Expected _wenviron to be non-NULL\n" );
ok( _wputenv(cat_eqW) == 0, "failed deleting cat\n" );
__wgetmainargs(&argc, &wargv, &wenvp, 0, &mode);
ok( *p_wenviron != NULL, "Expected _wenviron to be non-NULL\n" );
ok( wenvp != NULL, "Expected initial environment block pointer to be non-NULL\n" );
if (!wenvp)
ok( wenvp == *p_wenviron, "Expected initial environment to be _wenviron[]\n" );
if (p__p___winitenv)
{
skip( "Initial environment block pointer is not valid\n" );
return;
wchar_t ***retptr = p__p___winitenv();
wchar_t *value;
ok( *retptr != NULL, "Expected *__p___winitenv() to be NULL\n" );
ok( *retptr != *p_wenviron,
"Expected _wenviron to be different from __p___winitenv() %p %p\n", *retptr, *p_wenviron );
/* test that w-initial env is derived from current _environ[] and not from ansi initial env */
value = env_get_valueW( *retptr, L"cat" );
ok( value && !wcscmp( value, L"dog" ),
"Expecting initial env to be derived from current env (got %ls)\n", value );
}
_putenv("cat=");
/* Examine the returned pointer from __p__wenviron(),
* if available, after _wenviron is initialized. */
@ -222,29 +258,27 @@ static void test__wenviron(void)
ok( retptr == *p_wenviron,
"Expected _wenviron pointers to be identical\n" );
}
for (i = 0; ; i++)
{
if ((*p_wenviron)[i])
{
ok( wenvp[i] != NULL, "Expected environment block pointer element to be non-NULL\n" );
ok( !winetest_strcmpW((*p_wenviron)[i], wenvp[i]),
"Expected _wenviron and environment block pointer strings (%s vs. %s) to match\n",
wine_dbgstr_w((*p_wenviron)[i]), wine_dbgstr_w(wenvp[i]) );
}
else
{
ok( !wenvp[i], "Expected environment block pointer element to be NULL, got %p\n", wenvp[i] );
break;
}
}
}
static void test_environment_manipulation(void)
{
char buf[256];
errno_t ret;
size_t len;
unsigned count;
char* first;
char* second;
ok( _putenv("cat=") == 0, "_putenv failed on deletion of nonexistent environment variable\n" );
ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" );
ok( strcmp(getenv("cat"), "dog") == 0, "getenv did not return 'dog'\n" );
if (p_getenv_s)
{
ret = p_getenv_s(&len, buf, sizeof(buf), "cat");
ok( !ret, "getenv_s returned %d\n", ret );
ok( len == 4, "getenv_s returned length is %Id\n", len);
ok( !strcmp(buf, "dog"), "getenv_s did not return 'dog'\n");
}
ok( _putenv("cat=") == 0, "failed deleting cat\n" );
ok( _putenv("=") == -1, "should not accept '=' as input\n" );
@ -252,16 +286,190 @@ static void test_environment_manipulation(void)
ok( _putenv(a_very_long_env_string) == 0, "_putenv failed for long environment string\n");
ok( getenv("nonexistent") == NULL, "getenv should fail with nonexistent var name\n" );
if (p_putenv_s)
{
ret = p_putenv_s(NULL, "dog");
ok( ret == EINVAL, "_putenv_s returned %d\n", ret);
ret = p_putenv_s("cat", NULL);
ok( ret == EINVAL, "_putenv_s returned %d\n", ret);
ret = p_putenv_s("a=b", NULL);
ok( ret == EINVAL, "_putenv_s returned %d\n", ret);
ret = p_putenv_s("cat", "a=b");
ok( !ret, "_putenv_s returned %d\n", ret);
ret = p_putenv_s("cat", "");
ok( !ret, "_putenv_s returned %d\n", ret);
}
if (p_wputenv_s)
{
ret = p_wputenv_s(NULL, L"dog");
ok( ret == EINVAL, "_wputenv_s returned %d\n", ret);
ret = p_wputenv_s(L"cat", NULL);
ok( ret == EINVAL, "_wputenv_s returned %d\n", ret);
ret = p_wputenv_s(L"a=b", NULL);
ok( ret == EINVAL, "_wputenv_s returned %d\n", ret);
ret = p_wputenv_s(L"cat", L"a=b");
ok( !ret, "_wputenv_s returned %d\n", ret);
ret = p_wputenv_s(L"cat", L"");
ok( !ret, "_wputenv_s returned %d\n", ret);
}
if (p_getenv_s)
{
buf[0] = 'x';
len = 1;
errno = 0xdeadbeef;
ret = p_getenv_s(&len, buf, sizeof(buf), "nonexistent");
ok( !ret, "_getenv_s returned %d\n", ret);
ok( !len, "getenv_s returned length is %Id\n", len);
ok( !buf[0], "buf = %s\n", buf);
ok( errno == 0xdeadbeef, "errno = %d\n", errno);
buf[0] = 'x';
len = 1;
errno = 0xdeadbeef;
ret = p_getenv_s(&len, buf, sizeof(buf), NULL);
ok( !ret, "_getenv_s returned %d\n", ret);
ok( !len, "getenv_s returned length is %Id\n", len);
ok( !buf[0], "buf = %s\n", buf);
ok( errno == 0xdeadbeef, "errno = %d\n", errno);
}
/* test stability of _environ[] pointers */
ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env var\n" );
ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" );
count = env_get_entry_countA( *p_environ );
ok( _putenv( "__winetest_cat=mew") == 0, "Couldn't set env var\n" );
ok( !strcmp( (*p_environ)[count], "__winetest_cat=mew"), "Unexpected env var value\n" );
first = (*p_environ)[count];
ok( getenv("__winetest_cat") == strchr( (*p_environ)[count], '=') + 1, "Expected getenv() to return pointer inside _environ[] entry\n" );
ok( _putenv( "__winetest_dog=bark" ) == 0, "Couldn't set env var\n" );
ok( !strcmp( (*p_environ)[count + 1], "__winetest_dog=bark" ), "Unexpected env var value\n" );
ok( getenv( "__winetest_dog" ) == strchr( (*p_environ)[count + 1], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" );
ok( first == (*p_environ)[count], "Expected stability of _environ[count] pointer\n" );
second = (*p_environ)[count + 1];
ok( count + 2 == env_get_entry_countA( *p_environ ), "Unexpected count\n" );
ok( _putenv( "__winetest_cat=purr" ) == 0, "Couldn't set env var\n" );
ok( !strcmp( (*p_environ)[count], "__winetest_cat=purr" ), "Unexpected env var value\n" );
ok( getenv( "__winetest_cat" ) == strchr( (*p_environ)[count], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" );
ok( second == (*p_environ)[count + 1], "Expected stability of _environ[count] pointer\n" );
ok( !strcmp( (*p_environ)[count + 1], "__winetest_dog=bark" ), "Couldn't get env var value\n" );
ok( getenv( "__winetest_dog" ) == strchr( (*p_environ)[count + 1], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" );
ok( count + 2 == env_get_entry_countA( *p_environ ), "Unexpected count\n" );
ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env vat\n" );
ok( second == (*p_environ)[count], "Expected _environ[count] to be second\n" );
ok( !strcmp( (*p_environ)[count], "__winetest_dog=bark" ), "Unexpected env var value\n" );
ok( count + 1 == env_get_entry_countA( *p_environ ), "Unexpected count\n" );
ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" );
ok( count == env_get_entry_countA( *p_environ ), "Unexpected count\n" );
/* in putenv, only changed variable is updated (no other reload of kernel info is done) */
ret = SetEnvironmentVariableA( "__winetest_cat", "meow" );
ok( ret, "SetEnvironmentVariableA failed: %lu\n", GetLastError() );
ok( _putenv( "__winetest_dog=bark" ) == 0, "Couldn't set env var\n" );
ok( getenv( "__winetest_cat" ) == NULL, "msvcrt env cache shouldn't have been updated\n" );
ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env var\n" );
ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" );
/* test setting unicode bits */
count = env_get_entry_countA( *p_environ );
ret = WideCharToMultiByte( CP_ACP, 0, L"\u263a", -1, buf, ARRAY_SIZE(buf), 0, 0 );
ok( ret, "WideCharToMultiByte failed: %lu\n", GetLastError() );
ok( _wputenv( L"__winetest_cat=\u263a" ) == 0, "Couldn't set env var\n" );
ok( _wgetenv( L"__winetest_cat" ) && !wcscmp( _wgetenv( L"__winetest_cat" ), L"\u263a" ), "Couldn't retrieve env var\n" );
ok( getenv( "__winetest_cat" ) && !strcmp( getenv( "__winetest_cat" ), buf ), "Couldn't retrieve env var\n" );
ok( _wputenv( L"__winetest_cat=" ) == 0, "Couldn't reset env var\n" );
ret = WideCharToMultiByte( CP_ACP, 0, L"__winetest_\u263a", -1, buf, ARRAY_SIZE(buf), 0, 0 );
ok( ret, "WideCharToMultiByte failed: %lu\n", GetLastError() );
ok( _wputenv( L"__winetest_\u263a=bark" ) == 0, "Couldn't set env var\n" );
ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"bark"), "Couldn't retrieve env var\n" );
ok( getenv( buf ) && !strcmp( getenv( buf ), "bark"), "Couldn't retrieve env var %s\n", wine_dbgstr_a(buf) );
ok( _wputenv( L"__winetest_\u263a=" ) == 0, "Couldn't reset env var\n" );
ok( count == env_get_entry_countA( *p_environ ), "Unexpected modification of _environ[]\n" );
}
static void test_child_env(char** argv)
{
STARTUPINFOA si = {sizeof(si)};
WCHAR *cur_env, *env, *p, *q;
PROCESS_INFORMATION pi;
char tmp[1024];
BOOL ret;
int len;
cur_env = GetEnvironmentStringsW();
ok( cur_env != NULL, "GetEnvironemntStrings failed\n" );
p = cur_env;
while (*p) p += wcslen( p ) + 1;
len = p - cur_env;
env = malloc( (len + 1024) * sizeof(*env) );
memcpy(env, cur_env, len * sizeof(*env) );
q = env + len;
FreeEnvironmentStringsW( cur_env );
wcscpy( q, L"__winetest_dog=bark" );
q += wcslen( L"__winetest_dog=bark" ) + 1;
wcscpy( q, L"__winetest_\u263a=\u03b2" );
q += wcslen( L"__winetest_\u263a=\u03b2" ) + 1;
*q = 0;
snprintf( tmp, sizeof(tmp), "%s %s create", argv[0], argv[1] );
ret = CreateProcessA( NULL, tmp, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, env, NULL, &si, &pi );
ok( ret, "Couldn't create child process %s\n", tmp );
winetest_wait_child_process( pi.hProcess );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
free( env );
}
static void test_case_insensitive(void)
{
const char *uppercase_env = getenv("APPDATA");
const char *lowercase_env = getenv("appdata");
const wchar_t *uppercase_wenv = _wgetenv(L"APPDATA");
const wchar_t *lowercase_wenv = _wgetenv(L"appdata");
ok( uppercase_env == lowercase_env, "getenv() must be case insensitive, %p should be %p\n",
lowercase_env, uppercase_env );
ok( uppercase_wenv == lowercase_wenv, "_wgetenv() must be case insensitive, %p should be %p\n",
lowercase_wenv, uppercase_wenv );
ok( !_putenv("cAt=bar"), "Failed to set CAT=bar\n" );
ok( !_putenv("CAT=BAR"), "Failed to set CAT=BAR\n" );
ok( !strcmp(getenv("cAt"), "BAR"), "_putenv() must be case insensitive\n" );
ok( !_wputenv(L"cAt=bar"), "Failed to set CAT=bar\n" );
ok( !_wputenv(L"CAT=BAR"), "Failed to set CAT=BAR\n" );
ok( !wcscmp(_wgetenv(L"cAt"), L"BAR"), "_wputenv() must be case insensitive\n" );
_putenv("cat=");
}
START_TEST(environ)
{
char **argv;
int argc;
init();
/* The environ tests should always be run first, as they assume
* that the process has not manipulated the environment. */
argc = winetest_get_mainargs( &argv );
if (argc == 3 && !strcmp( argv[2], "create" ))
{
ok( getenv( "__winetest_dog" ) && !strcmp( getenv( "__winetest_dog" ), "bark" ),
"Couldn't find env var\n" );
ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"\u03b2" ),
"Couldn't find unicode env var\n" );
return;
}
test__environ();
test__wenviron();
test_environment_manipulation();
test_child_env(argv);
test_system();
test_case_insensitive();
}

File diff suppressed because it is too large Load diff

View file

@ -23,17 +23,13 @@
#include <errno.h>
#include "wine/test.h"
#ifdef __REACTOS__
#if defined(__GNUC__) && __GNUC__ >= 7
#pragma GCC diagnostic ignored "-Walloc-size-larger-than=9223372036854775807"
#endif
#endif
static void (__cdecl *p_aligned_free)(void*) = NULL;
static void * (__cdecl *p_aligned_malloc)(size_t,size_t) = NULL;
static void * (__cdecl *p_aligned_offset_malloc)(size_t,size_t,size_t) = NULL;
static void * (__cdecl *p_aligned_realloc)(void*,size_t,size_t) = NULL;
static void * (__cdecl *p_aligned_offset_realloc)(void*,size_t,size_t,size_t) = NULL;
static void (__cdecl *p_aligned_free)(void*);
static void * (__cdecl *p_aligned_malloc)(size_t,size_t);
static void * (__cdecl *p_aligned_offset_malloc)(size_t,size_t,size_t);
static void * (__cdecl *p_aligned_realloc)(void*,size_t,size_t);
static void * (__cdecl *p_aligned_offset_realloc)(void*,size_t,size_t,size_t);
static int (__cdecl *p__set_sbh_threshold)(size_t);
static size_t (__cdecl *p__get_sbh_threshold)(void);
static void test_aligned_malloc(unsigned int size, unsigned int alignment)
{
@ -421,28 +417,37 @@ static void test_aligned(void)
static void test_sbheap(void)
{
HMODULE msvcrt = GetModuleHandleA("msvcrt.dll");
void *mem;
int threshold;
p__set_sbh_threshold = (void*)GetProcAddress(msvcrt, "_set_sbh_threshold");
p__get_sbh_threshold = (void*)GetProcAddress(msvcrt, "_get_sbh_threshold");
if (!p__set_sbh_threshold || !p__get_sbh_threshold)
{
win_skip("_set_sbh_threshold not available\n");
return;
}
if(sizeof(void*) == 8) {
ok(!_set_sbh_threshold(0), "_set_sbh_threshold succeeded\n");
ok(!_set_sbh_threshold(1000), "_set_sbh_threshold succeeded\n");
ok(!p__set_sbh_threshold(0), "_set_sbh_threshold succeeded\n");
ok(!p__set_sbh_threshold(1000), "_set_sbh_threshold succeeded\n");
return;
}
mem = malloc(1);
ok(mem != NULL, "malloc failed\n");
ok(_set_sbh_threshold(1), "_set_sbh_threshold failed\n");
threshold = _get_sbh_threshold();
ok(p__set_sbh_threshold(1), "_set_sbh_threshold failed\n");
threshold = p__get_sbh_threshold();
ok(threshold == 16, "threshold = %d\n", threshold);
ok(_set_sbh_threshold(8), "_set_sbh_threshold failed\n");
threshold = _get_sbh_threshold();
ok(p__set_sbh_threshold(8), "_set_sbh_threshold failed\n");
threshold = p__get_sbh_threshold();
ok(threshold == 16, "threshold = %d\n", threshold);
ok(_set_sbh_threshold(1000), "_set_sbh_threshold failed\n");
threshold = _get_sbh_threshold();
ok(p__set_sbh_threshold(1000), "_set_sbh_threshold failed\n");
threshold = p__get_sbh_threshold();
ok(threshold == 1008, "threshold = %d\n", threshold);
free(mem);
@ -455,13 +460,42 @@ static void test_sbheap(void)
ok(mem != NULL, "realloc failed\n");
ok(!((UINT_PTR)mem & 0xf), "incorrect alignment (%p)\n", mem);
ok(_set_sbh_threshold(0), "_set_sbh_threshold failed\n");
threshold = _get_sbh_threshold();
ok(p__set_sbh_threshold(0), "_set_sbh_threshold failed\n");
threshold = p__get_sbh_threshold();
ok(threshold == 0, "threshold = %d\n", threshold);
free(mem);
}
static void test_malloc(void)
{
/* use function pointers to bypass gcc builtins */
void *(__cdecl *p_malloc)(size_t);
void *(__cdecl *p_realloc)(void *,size_t);
void *mem;
p_malloc = (void *)GetProcAddress( GetModuleHandleA("msvcrt.dll"), "malloc");
p_realloc = (void *)GetProcAddress( GetModuleHandleA("msvcrt.dll"), "realloc");
mem = p_malloc(0);
ok(mem != NULL, "memory not allocated for size 0\n");
free(mem);
mem = p_realloc(NULL, 10);
ok(mem != NULL, "memory not allocated\n");
mem = p_realloc(mem, 20);
ok(mem != NULL, "memory not reallocated\n");
mem = p_realloc(mem, 0);
ok(mem == NULL, "memory not freed\n");
mem = p_realloc(NULL, 0);
ok(mem != NULL, "memory not (re)allocated for size 0\n");
free(mem);
}
static void test_calloc(void)
{
/* use function pointer to bypass gcc builtin */
@ -489,29 +523,16 @@ static void test_calloc(void)
free(ptr);
}
static void test__get_heap_handle(void)
{
ok((HANDLE)_get_heap_handle() != GetProcessHeap(), "Expected _get_heap_handle() not to return GetProcessHeap()\n");
}
START_TEST(heap)
{
void *mem;
mem = malloc(0);
ok(mem != NULL, "memory not allocated for size 0\n");
free(mem);
mem = realloc(NULL, 10);
ok(mem != NULL, "memory not allocated\n");
mem = realloc(mem, 20);
ok(mem != NULL, "memory not reallocated\n");
mem = realloc(mem, 0);
ok(mem == NULL, "memory not freed\n");
mem = realloc(NULL, 0);
ok(mem != NULL, "memory not (re)allocated for size 0\n");
free(mem);
test_aligned();
test_sbheap();
test_malloc();
test_calloc();
test__get_heap_handle();
}

View file

@ -19,6 +19,7 @@
*/
#include <locale.h>
#include <process.h>
#include "wine/test.h"
#include "winnls.h"
@ -27,6 +28,9 @@ static BOOL (__cdecl *p__crtGetStringTypeW)(DWORD, DWORD, const wchar_t*, int, W
static int (__cdecl *pmemcpy_s)(void *, size_t, void*, size_t);
static int (__cdecl *p___mb_cur_max_func)(void);
static int *(__cdecl *p__p___mb_cur_max)(void);
static _locale_t(__cdecl *p_create_locale)(int, const char*);
static void(__cdecl *p_free_locale)(_locale_t);
static int (__cdecl *p_wcsicmp_l)(const wchar_t*, const wchar_t*, _locale_t);
void* __cdecl _Gettnames(void);
static void init(void)
@ -37,6 +41,9 @@ static void init(void)
pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s");
p___mb_cur_max_func = (void*)GetProcAddress(hmod, "___mb_cur_max_func");
p__p___mb_cur_max = (void*)GetProcAddress(hmod, "__p___mb_cur_max");
p_create_locale = (void*)GetProcAddress(hmod, "_create_locale");
p_free_locale = (void*)GetProcAddress(hmod, "_free_locale");
p_wcsicmp_l = (void*)GetProcAddress(hmod, "_wcsicmp_l");
}
static void test_setlocale(void)
@ -45,6 +52,8 @@ static void test_setlocale(void)
"LC_MONETARY=Greek_Greece.1253;LC_NUMERIC=Polish_Poland.1250;LC_TIME=C";
char *ret, buf[100];
char *ptr;
int len;
ret = setlocale(20, "C");
ok(ret == NULL, "ret = %s\n", ret);
@ -571,12 +580,14 @@ static void test_setlocale(void)
ret = setlocale(LC_ALL, "trk");
ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
if(ret)
ok(!strcmp(ret, "Turkish_Turkey.1254"), "ret = %s\n", ret);
ok(!strcmp(ret, "Turkish_Turkey.1254")
|| !strcmp(ret, "Turkish_T\xfcrkiye.1254"), "ret = %s\n", ret);
ret = setlocale(LC_ALL, "turkish");
ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
if(ret)
ok(!strcmp(ret, "Turkish_Turkey.1254"), "ret = %s\n", ret);
ok(!strcmp(ret, "Turkish_Turkey.1254")
|| !strcmp(ret, "Turkish_T\xfcrkiye.1254"), "ret = %s\n", ret);
ret = setlocale(LC_ALL, "uk");
ok(ret != NULL, "ret == NULL\n");
@ -612,6 +623,27 @@ static void test_setlocale(void)
ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf);
}
GetLocaleInfoA(GetUserDefaultLCID(), LOCALE_IDEFAULTCODEPAGE, buf, sizeof(buf));
if(IsValidCodePage(atoi(buf))) {
ret = setlocale(LC_ALL, ".OCP");
ok(ret != NULL, "ret == NULL\n");
ptr = strchr(ret, '.');
ok(ptr && !strcmp(ptr + 1, buf), "ret %s, buf %s.\n", ret, buf);
}
len = GetLocaleInfoA(GetUserDefaultLCID(), LOCALE_IDEFAULTANSICODEPAGE, buf, sizeof(buf)) - 1;
if(buf[0] == '0' && !buf[1])
len = sprintf(buf, "%d", GetACP());
ret = setlocale(LC_ALL, ".ACP");
ok(ret != NULL, "ret == NULL\n");
ptr = strchr(ret, '.');
ok(ptr && !strncmp(ptr + 1, buf, len), "ret %s, buf %s.\n", ret, buf);
ret = setlocale(LC_ALL, ".1250");
ok(ret != NULL, "ret == NULL\n");
ptr = strchr(ret, '.');
ok(ptr && !strcmp(ptr, ".1250"), "ret %s, buf %s.\n", ret, buf);
ret = setlocale(LC_ALL, "English_United States.UTF8");
ok(ret == NULL, "ret != NULL\n");
@ -621,13 +653,7 @@ static void test_setlocale(void)
static void test_crtGetStringTypeW(void)
{
static const wchar_t str0[] = { '0', '\0' };
static const wchar_t strA[] = { 'A', '\0' };
static const wchar_t str_space[] = { ' ', '\0' };
static const wchar_t str_null[] = { '\0', '\0' };
static const wchar_t str_rand[] = { 1234, '\0' };
const wchar_t *str[] = { str0, strA, str_space, str_null, str_rand };
const wchar_t *str[] = { L"0", L"A", L" ", L"\0", L"\x04d2" };
WORD out_crt, out;
BOOL ret_crt, ret;
@ -712,10 +738,14 @@ static void test__Gettnames(void)
{
size = GetLocaleInfoA(MAKELCID(LANG_ENGLISH, SORT_DEFAULT),
time_data[i], buf, sizeof(buf));
ok(size, "GetLocaleInfo failed: %x\n", GetLastError());
ok(size, "GetLocaleInfo failed: %lx\n", GetLastError());
ok(!strcmp(ret->str[i], buf), "ret->str[%i] = %s, expected %s\n", i, ret->str[i], buf);
}
ok(ret->wstr[0] != NULL, "ret->wstr[0] = NULL\n");
ok(ret->str[42] + strlen(ret->str[42])+1 != (char*)ret->wstr[0],
"ret->str[42] = %p len = %Id, ret->wstr[0] = %p\n",
ret->str[42], strlen(ret->str[42]), ret->wstr[0]);
free(ret);
if(!setlocale(LC_TIME, "german"))
@ -726,7 +756,7 @@ static void test__Gettnames(void)
{
size = GetLocaleInfoA(MAKELCID(LANG_GERMAN, SORT_DEFAULT),
time_data[i], buf, sizeof(buf));
ok(size, "GetLocaleInfo failed: %x\n", GetLastError());
ok(size, "GetLocaleInfo failed: %lx\n", GetLastError());
ok(!strcmp(ret->str[i], buf), "ret->str[%i] = %s, expected %s\n", i, ret->str[i], buf);
}
free(ret);
@ -775,6 +805,178 @@ static void test___mb_cur_max_func(void)
}
}
static void test__wcsicmp_l(void)
{
const struct {
const wchar_t *str1;
const wchar_t *str2;
int exp;
const char *loc;
} tests[] = {
{ L"i", L"i", 0 },
{ L"I", L"i", 0 },
{ L"I", L"i", 0, "Turkish" },
{ L"i", L"a", 8 },
{ L"a", L"i", -8 },
{ L"i", L"a", 8, "Turkish" },
};
int ret, i;
if (!p_wcsicmp_l || !p_create_locale)
{
win_skip("_wcsicmp_l or _create_locale not available\n");
return;
}
ok(!!p_free_locale, "_free_locale not available\n");
for(i=0; i<ARRAY_SIZE(tests); i++) {
_locale_t loc = NULL;
if(tests[i].loc && !(loc = p_create_locale(LC_ALL, tests[i].loc))) {
win_skip("locale %s not available. skipping\n", tests[i].loc);
continue;
}
ret = p_wcsicmp_l(tests[i].str1, tests[i].str2, loc);
ok(ret == tests[i].exp, "_wcsicmp_l = %d, expected %d for test %d '%ls' vs '%ls' using %s locale\n",
ret, tests[i].exp, i, tests[i].str1, tests[i].str2, loc ? tests[i].loc : "current");
if(loc)
p_free_locale(loc);
}
}
static unsigned __stdcall test_thread_setlocale_func(void *arg)
{
char *ret;
ret = setlocale(LC_ALL, NULL);
ok(!strcmp(ret, "C"), "expected ret=C, but received ret=%s\n", ret);
ret = setlocale(LC_ALL, "");
ok(strcmp(ret, "Invariant Language_Invariant Country.0"), "expected valid locale\n");
return 0;
}
static void test_thread_setlocale(void)
{
HANDLE hThread;
hThread = (HANDLE)_beginthreadex(NULL, 0, test_thread_setlocale_func, NULL, 0, NULL);
ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
WaitForSingleObject(hThread, 5000);
CloseHandle(hThread);
}
static void test_locale_info(void)
{
pthreadlocinfo locinfo, locinfo2;
_locale_t locale, locale2;
int ret;
if (!p_create_locale)
{
win_skip("_create_locale isn't available.\n");
return;
}
if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
skip("Skip language-specific tests on Japanese system.\n");
else
{
locale = p_create_locale(LC_ALL, "Japanese_Japan.932");
locale2 = p_create_locale(LC_ALL, ".932");
locinfo = locale->locinfo;
locinfo2 = locale2->locinfo;
ok(locinfo->mb_cur_max == locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n",
locinfo->mb_cur_max, locinfo2->mb_cur_max);
ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n",
locinfo->ctype1_refcount, locinfo2->ctype1_refcount);
ok(locinfo->lc_codepage == 932 && locinfo->lc_codepage == locinfo2->lc_codepage,
"Got wrong codepage %d vs %d.\n", locinfo->lc_codepage, locinfo2->lc_codepage);
ok(locinfo->lc_id[LC_CTYPE].wCodePage == 932
&& locinfo->lc_id[LC_CTYPE].wCodePage == locinfo2->lc_id[LC_CTYPE].wCodePage,
"Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage,
locinfo2->lc_id[LC_CTYPE].wCodePage);
ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale);
ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale,
locinfo2->lc_category[LC_CTYPE].locale);
ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1));
ok(!ret, "Got wrong ctype1 data.\n");
ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap));
ok(!ret, "Got wrong pclmap data.\n");
ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap));
ok(!ret, "Got wrong pcumap data.\n");
ok(locinfo->lc_handle[LC_CTYPE] != locinfo2->lc_handle[LC_CTYPE],
"Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]);
p_free_locale(locale2);
locale2 = p_create_locale(LC_ALL, "Japanese_Japan.1252");
locinfo2 = locale2->locinfo;
ok(locinfo->mb_cur_max != locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n",
locinfo->mb_cur_max, locinfo2->mb_cur_max);
ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n",
locinfo->ctype1_refcount, locinfo2->ctype1_refcount);
ok(locinfo2->lc_codepage == 1252, "Got wrong codepage %d.\n", locinfo2->lc_codepage);
ok(locinfo2->lc_id[LC_CTYPE].wCodePage == 1252, "Got wrong LC_CTYPE codepage %d.\n",
locinfo2->lc_id[LC_CTYPE].wCodePage);
ok(locinfo->lc_codepage != locinfo2->lc_codepage, "Got wrong codepage %d vs %d.\n",
locinfo->lc_codepage, locinfo2->lc_codepage);
ok(locinfo->lc_id[LC_CTYPE].wCodePage != locinfo2->lc_id[LC_CTYPE].wCodePage,
"Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage,
locinfo2->lc_id[LC_CTYPE].wCodePage);
ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale);
ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale,
locinfo2->lc_category[LC_CTYPE].locale);
ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1));
ok(!!ret, "Got wrong ctype1 data.\n");
ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap));
ok(!!ret, "Got wrong pclmap data.\n");
ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap));
ok(!!ret, "Got wrong pcumap data.\n");
ok(locinfo->lc_handle[LC_CTYPE] == locinfo2->lc_handle[LC_CTYPE],
"Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]);
p_free_locale(locale2);
locale2 = p_create_locale(LC_ALL, "Japanese_Japan.3000"); /* an invalid codepage */
ok(!locale2, "Got %p.\n", locale2);
p_free_locale(locale);
}
locale = p_create_locale(LC_ALL, "German_Germany.437");
locale2 = p_create_locale(LC_ALL, "German_Germany.1252");
locinfo = locale->locinfo;
locinfo2 = locale2->locinfo;
ok(locinfo->mb_cur_max == locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n",
locinfo->mb_cur_max, locinfo2->mb_cur_max);
ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n",
locinfo->ctype1_refcount, locinfo2->ctype1_refcount);
ok(locinfo->lc_codepage != locinfo2->lc_codepage, "Got wrong codepage %d vs %d.\n",
locinfo->lc_codepage, locinfo2->lc_codepage);
ok(locinfo->lc_id[LC_CTYPE].wCodePage != locinfo2->lc_id[LC_CTYPE].wCodePage,
"Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage,
locinfo2->lc_id[LC_CTYPE].wCodePage);
ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale);
ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale,
locinfo2->lc_category[LC_CTYPE].locale);
ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1));
ok(!!ret, "Got wrong ctype1 data.\n");
ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap));
ok(!!ret, "Got wrong pclmap data.\n");
ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap));
ok(!!ret, "Got wrong pcumap data.\n");
ok(locinfo->lc_handle[LC_CTYPE] == locinfo2->lc_handle[LC_CTYPE],
"Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]);
p_free_locale(locale2);
p_free_locale(locale);
}
START_TEST(locale)
{
init();
@ -783,4 +985,7 @@ START_TEST(locale)
test_setlocale();
test__Gettnames();
test___mb_cur_max_func();
test__wcsicmp_l();
test_thread_setlocale();
test_locale_info();
}

View file

@ -20,31 +20,12 @@
#include "wine/test.h"
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <math.h>
#include "msvcrt.h"
#include <process.h>
static inline float __port_infinity(void)
{
static const unsigned __inf_bytes = 0x7f800000;
return *(const float *)&__inf_bytes;
}
#ifdef __REACTOS__
#undef INFINITY
#endif
#define INFINITY __port_infinity()
static inline float __port_nan(void)
{
static const unsigned __nan_bytes = 0x7fc00000;
return *(const float *)&__nan_bytes;
}
#ifdef __REACTOS__
#undef NAN
#endif
#define NAN __port_nan()
static inline BOOL almost_equal(double d1, double d2) {
if(d1-d2>-1e-30 && d1-d2<1e-30)
return TRUE;
@ -56,14 +37,14 @@ struct uld { ULONG lo, hi, exp; };
static int (__cdecl *prand_s)(unsigned int *);
static int (__cdecl *pI10_OUTPUT)(struct uld, int, int, void*);
static int (__cdecl *pstrerror_s)(char *, MSVCRT_size_t, int);
static int (__cdecl *pstrerror_s)(char *, size_t, int);
static int (__cdecl *p_get_doserrno)(int *);
static int (__cdecl *p_get_errno)(int *);
static int (__cdecl *p_set_doserrno)(int);
static int (__cdecl *p_set_errno)(int);
static void (__cdecl *p__invalid_parameter)(const wchar_t*,
const wchar_t*, const wchar_t*, unsigned int, uintptr_t);
static void (__cdecl *p_qsort_s)(void*, MSVCRT_size_t, MSVCRT_size_t,
static void (__cdecl *p_qsort_s)(void*, size_t, size_t,
int (__cdecl*)(void*, const void*, const void*), void*);
static double (__cdecl *p_atan)(double);
static double (__cdecl *p_exp)(double);
@ -194,7 +175,7 @@ static void test_I10_OUTPUT(void)
j = strlen(I10_OUTPUT_tests[i].remain);
todo_wine_if(j && I10_OUTPUT_tests[i].remain[j-1]=='9')
ok(!strncmp(out.str+out.len+1, I10_OUTPUT_tests[i].remain, j),
"%d: &out.str[%d] = %.25s...\n", i, out.len+1, out.str+out.len+1);
"%d: &out.str[%d] = %.25s...\n", i, out.len+1, out.str+out.len+1);
for(j=out.len+strlen(I10_OUTPUT_tests[i].remain)+1; j<sizeof(out.str); j++)
if(out.str[j] != '#')
@ -233,7 +214,7 @@ static void test_strerror_s(void)
memset(buf, 'X', sizeof(buf));
ret = pstrerror_s(buf, 1, 0);
ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret);
ok(strlen(buf) == 0, "Expected output buffer to be null terminated\n");
ok(buf[0] == 0, "Expected output buffer to be null terminated\n");
memset(buf, 'X', sizeof(buf));
ret = pstrerror_s(buf, 2, 0);
@ -263,7 +244,7 @@ static void test__get_doserrno(void)
errno = EBADF;
ret = p_get_doserrno(NULL);
ok(ret == EINVAL, "Expected _get_doserrno to return EINVAL, got %d\n", ret);
ok(_doserrno == ERROR_INVALID_CMM, "Expected _doserrno to be ERROR_INVALID_CMM, got %d\n", _doserrno);
ok(_doserrno == ERROR_INVALID_CMM, "Expected _doserrno to be ERROR_INVALID_CMM, got %ld\n", _doserrno);
ok(errno == EBADF, "Expected errno to be EBADF, got %d\n", errno);
_doserrno = ERROR_INVALID_CMM;
@ -310,19 +291,19 @@ static void test__set_doserrno(void)
ret = p_set_doserrno(ERROR_FILE_NOT_FOUND);
ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret);
ok(_doserrno == ERROR_FILE_NOT_FOUND,
"Expected _doserrno to be ERROR_FILE_NOT_FOUND, got %d\n", _doserrno);
"Expected _doserrno to be ERROR_FILE_NOT_FOUND, got %ld\n", _doserrno);
_doserrno = ERROR_INVALID_CMM;
ret = p_set_doserrno(-1);
ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret);
ok(_doserrno == -1,
"Expected _doserrno to be -1, got %d\n", _doserrno);
"Expected _doserrno to be -1, got %ld\n", _doserrno);
_doserrno = ERROR_INVALID_CMM;
ret = p_set_doserrno(0xdeadbeef);
ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret);
ok(_doserrno == 0xdeadbeef,
"Expected _doserrno to be 0xdeadbeef, got %d\n", _doserrno);
"Expected _doserrno to be 0xdeadbeef, got %ld\n", _doserrno);
}
static void test__set_errno(void)
@ -351,21 +332,42 @@ static void test__set_errno(void)
ok(errno == 0xdeadbeef, "Expected errno to be 0xdeadbeef, got %d\n", errno);
}
static void test__popen_child(void)
static void test__popen_child(int fd)
{
/* don't execute any tests here */
/* ExitProcess is used to set return code of _pclose */
printf("child output\n");
if ((HANDLE)_get_osfhandle(fd) != INVALID_HANDLE_VALUE)
ExitProcess(1);
ExitProcess(0x37);
}
static void test__popen_read_child(void)
{
char buf[1024], *rets;
rets = fgets(buf, sizeof(buf), stdin);
if (strcmp(buf, "child-to-parent\n") != 0)
ExitProcess(1);
rets = fgets(buf, sizeof(buf), stdin);
if (rets)
ExitProcess(2);
ExitProcess(3);
}
static void test__popen(const char *name)
{
FILE *pipe;
char buf[1024];
int ret;
char *tempf, buf[1024];
int ret, fd;
sprintf(buf, "\"%s\" misc popen", name);
tempf = _tempnam(".", "wne");
ok(tempf != NULL, "_tempnam failed\n");
fd = _open(tempf, _O_CREAT | _O_WRONLY);
ok(fd != -1, "open failed\n");
sprintf(buf, "\"%s\" misc popen %d", name, fd);
pipe = _popen(buf, "r");
ok(pipe != NULL, "_popen failed with error: %d\n", errno);
@ -374,12 +376,25 @@ static void test__popen(const char *name)
ret = _pclose(pipe);
ok(ret == 0x37, "_pclose returned %x, expected 0x37\n", ret);
_close(fd);
_unlink(tempf);
free(tempf);
errno = 0xdeadbeef;
ret = _pclose((FILE*)0xdeadbeef);
ok(ret == -1, "_pclose returned %x, expected -1\n", ret);
if(p_set_errno)
ok(errno == EBADF, "errno = %d\n", errno);
sprintf(buf, "\"%s\" misc popen_read", name);
pipe = _popen(buf, "w");
ok(pipe != NULL, "_popen failed with error: %d\n", errno);
ret = fputs("child-to-parent\n", pipe);
ok(ret != EOF, "fputs returned %x\n", ret);
ret = _pclose(pipe);
ok(ret == 0x3, "_pclose returned %x, expected 0x3\n", ret);
}
static void test__invalid_parameter(void)
@ -512,8 +527,35 @@ static void test_qsort_s(void)
ok(tab[i] == i, "data sorted incorrectly on position %d: %d\n", i, tab[i]);
}
static int eq_nan(UINT64 ai, double b)
{
UINT64 bi = *(UINT64*)&b;
UINT64 mask;
#if defined(__i386__)
mask = 0xFFFFFFFF00000000ULL;
#else
mask = ~0;
#endif
ok((ai & mask) == (bi & mask), "comparing %s and %s\n",
wine_dbgstr_longlong(ai), wine_dbgstr_longlong(bi));
return (ai & mask) == (bi & mask);
}
static int eq_nanf(DWORD ai, float b)
{
DWORD bi = *(DWORD*)&b;
ok(ai == bi, "comparing %08lx and %08lx\n", ai, bi);
return ai == bi;
}
static void test_math_functions(void)
{
static const UINT64 test_nan_i = 0xFFF0000123456780ULL;
static const DWORD test_nanf_i = 0xFF801234;
double test_nan = *(double*)&test_nan_i;
float test_nanf = *(float*)&test_nanf_i;
double ret;
errno = 0xdeadbeef;
@ -546,6 +588,13 @@ static void test_math_functions(void)
errno = 0xdeadbeef;
p_exp(INFINITY);
ok(errno == 0xdeadbeef, "errno = %d\n", errno);
ok(eq_nan(test_nan_i | (1ULL << 51), cosh(test_nan)), "cosh not preserving nan\n");
ok(eq_nan(test_nan_i | (1ULL << 51), sinh(test_nan)), "sinh not preserving nan\n");
ok(eq_nan(test_nan_i | (1ULL << 51), tanh(test_nan)), "tanh not preserving nan\n");
ok(eq_nanf(test_nanf_i | (1 << 22), coshf(test_nanf)), "coshf not preserving nan\n");
ok(eq_nanf(test_nanf_i | (1 << 22), sinhf(test_nanf)), "sinhf not preserving nan\n");
ok(eq_nanf(test_nanf_i | (1 << 22), tanhf(test_nanf)), "tanhf not preserving nan\n");
}
static void __cdecl test_thread_func(void *end_thread_type)
@ -574,38 +623,51 @@ static void test_thread_handle_close(void)
ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
WaitForSingleObject(hThread, INFINITE);
ret = CloseHandle(hThread);
ok(!ret, "ret = %d\n", ret);
ok(!ret, "ret = %ld\n", ret);
hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)1);
ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
WaitForSingleObject(hThread, INFINITE);
ret = CloseHandle(hThread);
ok(!ret, "ret = %d\n", ret);
ok(!ret, "ret = %ld\n", ret);
hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)2);
ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
Sleep(150);
ret = WaitForSingleObject(hThread, INFINITE);
ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret);
ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret);
ret = CloseHandle(hThread);
ok(ret, "ret = %d\n", ret);
ok(ret, "ret = %ld\n", ret);
hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)3);
ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
Sleep(150);
ret = WaitForSingleObject(hThread, INFINITE);
ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret);
ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret);
ret = CloseHandle(hThread);
ok(ret, "ret = %d\n", ret);
ok(ret, "ret = %ld\n", ret);
/* _beginthreadex: handle is not closed on _endthread */
hThread = (HANDLE)_beginthreadex(NULL,0, test_thread_func_ex, NULL, 0, NULL);
ok(hThread != NULL, "_beginthreadex failed (%d)\n", errno);
Sleep(150);
ret = WaitForSingleObject(hThread, INFINITE);
ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret);
ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret);
ret = CloseHandle(hThread);
ok(ret, "ret = %d\n", ret);
ok(ret, "ret = %ld\n", ret);
}
static void test_thread_suspended(void)
{
HANDLE hThread;
DWORD ret;
hThread = (HANDLE)_beginthreadex(NULL, 0, test_thread_func_ex, NULL, CREATE_SUSPENDED, NULL);
ok(hThread != NULL, "_beginthreadex failed (%d)\n", errno);
ret = ResumeThread(hThread);
ok(ret == 1, "suspend count = %ld\n", ret);
ret = WaitForSingleObject(hThread, 200);
ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret);
}
static int __cdecl _lfind_s_comp(void *ctx, const void *l, const void *r)
@ -685,8 +747,10 @@ START_TEST(misc)
arg_c = winetest_get_mainargs(&arg_v);
if(arg_c >= 3) {
if(!strcmp(arg_v[2], "popen"))
test__popen_child();
if (!strcmp(arg_v[2], "popen_read"))
test__popen_read_child();
else if(arg_c == 4 && !strcmp(arg_v[2], "popen"))
test__popen_child(atoi(arg_v[3]));
else
ok(0, "invalid argument '%s'\n", arg_v[2]);
@ -705,5 +769,6 @@ START_TEST(misc)
test_qsort_s();
test_math_functions();
test_thread_handle_close();
test_thread_suspended();
test__lfind_s();
}

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,41 @@
#include "wine/test.h"
static void test_fscanf( void )
{
static const char file_name[] = "fscanf.tst";
static const char contents[] =
"line1\n"
"line2 "
;
char buf[1024];
FILE *fp;
int ret;
fp = fopen(file_name, "wb");
ok(fp != NULL, "fp = %p\n", fp);
if(!fp) {
skip("failed to create temporary test file\n");
return;
}
ret = fprintf(fp, contents);
fclose(fp);
fp = fopen(file_name, "rb");
ret = fscanf(fp, "%s", buf);
ok(ret == 1, "ret = %d\n", ret);
ok(strcmp(buf, "line1") == 0, "buf = %s\n", buf);
ret = fscanf(fp, "%s", buf);
ok(ret == 1, "ret = %d\n", ret);
ok(strcmp(buf, "line2") == 0, "buf = %s\n", buf);
ret = fscanf(fp, "%s", buf);
ok(ret == EOF, "ret = %d\n", ret);
fclose(fp);
unlink(file_name);
}
static void test_sscanf( void )
{
/* use function pointers to bypass gcc builtin */
@ -48,6 +83,14 @@ static void test_sscanf( void )
ret = p_sscanf(buffer, "%d", &result);
ok( ret == EOF,"sscanf returns %x instead of %x\n", ret, EOF );
ret = p_sscanf(" \t\n\n", "%s", buffer);
ok( ret == EOF, "ret = %d\n", ret );
buffer1[0] = 'a';
ret = p_sscanf("test\n", "%s%c", buffer, buffer1);
ok( ret == 2, "ret = %d\n", ret );
ok( buffer1[0] == '\n', "buffer1[0] = %d\n", buffer1[0] );
/* check %p */
ok( p_sscanf("000000000046F170", "%p", &ptr) == 1, "sscanf failed\n" );
ok( ptr == (void *)0x46F170,"sscanf reads %p instead of %x\n", ptr, 0x46F170 );
@ -122,6 +165,12 @@ static void test_sscanf( void )
ok(double_res >= 1.1e-30-1e-45 && double_res <= 1.1e-30+1e-45,
"Got %.18le, expected %.18le\n", double_res, 1.1e-30);
buffer[0] = 0;
double_res = 1;
ret = p_sscanf(buffer, "%lf", &double_res);
ok(ret == -1, "expected 0, got %u\n", ret);
ok(double_res == 1, "Got %lf, expected 1\n", double_res);
/* check strings */
ret = p_sprintf(buffer," %s", pname);
ok( ret == 26, "expected 26, got %u\n", ret);
@ -137,6 +186,22 @@ static void test_sscanf( void )
ok( ret == 1, "Error with format \"%s\"\n","%*[a-cd-dg-e]%c");
ok( buffer[0] == 'h', "Error with \"abcefgdh\" \"%c\"\n", buffer[0]);
ret = p_sscanf("-123", "%[-0-9]", buffer);
ok( ret == 1, "Error with format \"%s\"\n", "%[-0-9]");
ok( strcmp("-123", buffer) == 0, "Error with \"-123\" \"%s\"\n", buffer);
ret = p_sscanf("-321", "%[0-9-]", buffer);
ok( ret == 1, "Error with format \"%s\"\n", "%[0-9-]");
ok( strcmp("-321", buffer) == 0, "Error with \"-321\" \"%s\"\n", buffer);
ret = p_sscanf("-4123", "%[1-2-4]", buffer);
ok( ret == 1, "Error with format \"%s\"\n", "%[1-2-4]");
ok( strcmp("-412", buffer) == 0, "Error with \"-412\" \"%s\"\n", buffer);
ret = p_sscanf("-456123", "%[1-2-45-6]", buffer);
ok( ret == 1, "Error with format \"%s\"\n", "%[1-2-45-6]");
ok( strcmp("-45612", buffer) == 0, "Error with \"-45612\" \"%s\"\n", buffer);
buffer1[0] = 'b';
ret = p_sscanf("a","%s%s", buffer, buffer1);
ok( ret == 1, "expected 1, got %u\n", ret);
@ -162,6 +227,30 @@ static void test_sscanf( void )
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ok(result == 0xdead614e, "Wrong number read (%x)\n", result);
result = 0xdeadbeef;
strcpy(buffer,"12345678");
ret = p_sscanf(buffer, "%02hd", &result);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ok(result == 0xdead000c, "Wrong number read (%x)\n", result);
result = 0xdeadbeef;
strcpy(buffer,"12345678");
ret = p_sscanf(buffer, "%h02d", &result);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ok(result == 0xdead000c, "Wrong number read (%x)\n", result);
result = 0xdeadbeef;
strcpy(buffer,"12345678");
ret = p_sscanf(buffer, "%000h02d", &result);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ok(result == 0xdead000c, "Wrong number read (%x)\n", result);
result = 0xdeadbeef;
strcpy(buffer,"12345678");
ret = p_sscanf(buffer, "%2h0d", &result);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ok(result == 0xdead614e, "Wrong number read (%x)\n", result);
result = 0xdeadbeef;
ret = p_sscanf(buffer, "%hhd", &result);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
@ -313,35 +402,34 @@ static void test_sscanf_s(void)
static void test_swscanf( void )
{
wchar_t buffer[100];
wchar_t buffer[100], results[100];
int result, ret;
static const WCHAR formatd[] = {'%','d',0};
const WCHAR format2[] = {'a',0x1234,'%',0x1234,'%','c',0};
WCHAR c;
/* check WEOF */
/* WEOF is an unsigned short -1 but swscanf returns int
so it should be sign-extended */
buffer[0] = 0;
ret = swscanf(buffer, formatd, &result);
ret = swscanf(buffer, L"%d", &result);
/* msvcrt returns 0 but should return -1 (later versions do) */
ok( ret == (short)WEOF || broken(ret == 0),
"swscanf returns %x instead of %x\n", ret, WEOF );
ret = swscanf(L" \t\n\n", L"%s", results);
/* sscanf returns EOF under this case, but swscanf does not return WEOF */
ok( ret == 0, "ret = %d\n", ret );
buffer[0] = 'a';
buffer[1] = 0x1234;
buffer[2] = 0x1234;
buffer[3] = 'b';
ret = swscanf(buffer, format2, &c);
ret = swscanf(buffer, L"a\x1234%\x1234%c", &c);
ok(ret == 1, "swscanf returned %d\n", ret);
ok(c == 'b', "c = %x\n", c);
}
static void test_swscanf_s(void)
{
static const wchar_t fmt1[] = {'%','c',0};
static const wchar_t fmt2[] = {'%','[','a','-','z',']',0};
int (WINAPIV *pswscanf_s)(const wchar_t*,const wchar_t*,...);
HMODULE hmod = GetModuleHandleA("msvcrt.dll");
wchar_t buf[2], out[2];
@ -356,15 +444,15 @@ static void test_swscanf_s(void)
buf[0] = 'a';
buf[1] = '1';
out[1] = 'b';
ret = pswscanf_s(buf, fmt1, out, 1);
ret = pswscanf_s(buf, L"%c", out, 1);
ok(ret == 1, "swscanf_s returned %d\n", ret);
ok(out[0] == 'a', "out[0] = %x\n", out[0]);
ok(out[1] == 'b', "out[1] = %x\n", out[1]);
ret = pswscanf_s(buf, fmt2, out, 1);
ret = pswscanf_s(buf, L"%[a-z]", out, 1);
ok(!ret, "swscanf_s returned %d\n", ret);
ret = pswscanf_s(buf, fmt2, out, 2);
ret = pswscanf_s(buf, L"%[a-z]", out, 2);
ok(ret == 1, "swscanf_s returned %d\n", ret);
ok(out[0] == 'a', "out[0] = %x\n", out[0]);
ok(!out[1], "out[1] = %x\n", out[1]);
@ -372,6 +460,7 @@ static void test_swscanf_s(void)
START_TEST(scanf)
{
test_fscanf();
test_sscanf();
test_sscanf_s();
test_swscanf();

File diff suppressed because it is too large Load diff

View file

@ -36,10 +36,27 @@
#define MINSPERHOUR 60
#define HOURSPERDAY 24
typedef struct {
const char *short_wday[7];
const char *wday[7];
const char *short_mon[12];
const char *mon[12];
const char *am;
const char *pm;
const char *short_date;
const char *date;
const char *time;
LCID lcid;
int unk;
int refcount;
} __lc_time_data;
static __time32_t (__cdecl *p_mkgmtime32)(struct tm*);
static struct tm* (__cdecl *p_gmtime32)(__time32_t*);
static struct tm* (__cdecl *p_gmtime)(time_t*);
static errno_t (__cdecl *p_gmtime32_s)(struct tm*, __time32_t*);
static struct tm* (__cdecl *p_gmtime64)(__time64_t*);
static errno_t (__cdecl *p_gmtime64_s)(struct tm*, __time64_t*);
static errno_t (__cdecl *p_strtime_s)(char*,size_t);
static errno_t (__cdecl *p_strdate_s)(char*,size_t);
static errno_t (__cdecl *p_localtime32_s)(struct tm*, __time32_t*);
@ -50,6 +67,7 @@ static long* (__cdecl *p___p__dstbias)(void);
static long* (__cdecl *p__dstbias)(void);
static long* (__cdecl *p___p__timezone)(void);
static size_t (__cdecl *p_strftime)(char *, size_t, const char *, const struct tm *);
static size_t (__cdecl *p__Strftime)(char*, size_t, const char*, const struct tm*, void*);
static size_t (__cdecl *p_wcsftime)(wchar_t *, size_t, const wchar_t *, const struct tm *);
static char* (__cdecl *p_asctime)(const struct tm *);
@ -60,6 +78,8 @@ static void init(void)
p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
p_gmtime = (void*)GetProcAddress(hmod, "gmtime");
p_gmtime32_s = (void*)GetProcAddress(hmod, "_gmtime32_s");
p_gmtime64 = (void*)GetProcAddress(hmod, "_gmtime64");
p_gmtime64_s = (void*)GetProcAddress(hmod, "_gmtime64_s");
p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
p_strdate_s = (void*)GetProcAddress(hmod, "_strdate_s");
@ -71,6 +91,7 @@ static void init(void)
p__dstbias = (void*)GetProcAddress(hmod, "__dstbias");
p___p__timezone = (void*)GetProcAddress(hmod, "__p__timezone");
p_strftime = (void*)GetProcAddress(hmod, "strftime");
p__Strftime = (void*)GetProcAddress(hmod, "_Strftime");
p_wcsftime = (void*)GetProcAddress(hmod, "wcsftime");
p_asctime = (void*)GetProcAddress(hmod, "asctime");
}
@ -134,21 +155,21 @@ static void test_gmtime(void)
gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
gmt = p_mkgmtime32(gmt_tm);
ok(gmt == valid, "gmt = %u\n", gmt);
ok(gmt == valid, "gmt = %lu\n", gmt);
ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
gmt_tm->tm_isdst = -1;
gmt = p_mkgmtime32(gmt_tm);
ok(gmt == valid, "gmt = %u\n", gmt);
ok(gmt == valid, "gmt = %lu\n", gmt);
ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
gmt_tm->tm_wday = gmt_tm->tm_yday = 0;
gmt_tm->tm_isdst = 1;
gmt = p_mkgmtime32(gmt_tm);
ok(gmt == valid, "gmt = %u\n", gmt);
ok(gmt == valid, "gmt = %lu\n", gmt);
ok(gmt_tm->tm_wday == 4, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
ok(gmt_tm->tm_yday == 0, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
@ -161,13 +182,13 @@ static void test_gmtime(void)
gmt_tm->tm_isdst = -1;
gmt = p_mkgmtime32(gmt_tm);
ok(gmt == valid, "gmt = %u\n", gmt);
ok(gmt == valid, "gmt = %lu\n", gmt);
ok(gmt_tm->tm_wday == 6, "gmt_tm->tm_wday = %d\n", gmt_tm->tm_wday);
ok(gmt_tm->tm_yday == 2, "gmt_tm->tm_yday = %d\n", gmt_tm->tm_yday);
gmt_tm->tm_isdst = 1;
gmt = p_mkgmtime32(gmt_tm);
ok(gmt == valid, "gmt = %u\n", gmt);
ok(gmt == valid, "gmt = %lu\n", gmt);
if(!p_gmtime32_s) {
win_skip("Skipping _gmtime32_s tests\n");
@ -191,6 +212,78 @@ static void test_gmtime(void)
}
}
static void test_gmtime64(void)
{
struct tm *ptm, tm;
__time64_t t;
int ret;
t = -1;
memset(&tm, 0xcc, sizeof(tm));
ptm = p_gmtime64(&t);
if (!ptm)
{
skip("Old gmtime64 limits, skipping tests.\n");
return;
}
ok(!!ptm, "got NULL.\n");
ret = p_gmtime64_s(&tm, &t);
ok(!ret, "got %d.\n", ret);
ok(tm.tm_year == 69 && tm.tm_hour == 23 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
t = -43200;
memset(&tm, 0xcc, sizeof(tm));
ptm = p_gmtime64(&t);
ok(!!ptm, "got NULL.\n");
ret = p_gmtime64_s(&tm, &t);
ok(!ret, "got %d.\n", ret);
ok(tm.tm_year == 69 && tm.tm_hour == 12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
ptm = p_gmtime32((__time32_t *)&t);
ok(!!ptm, "got NULL.\n");
memset(&tm, 0xcc, sizeof(tm));
ret = p_gmtime32_s(&tm, (__time32_t *)&t);
ok(!ret, "got %d.\n", ret);
todo_wine_if(tm.tm_year == 69 && tm.tm_hour == 12)
ok(tm.tm_year == 70 && tm.tm_hour == -12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
t = -43201;
ptm = p_gmtime64(&t);
ok(!ptm, "got non-NULL.\n");
memset(&tm, 0xcc, sizeof(tm));
ret = p_gmtime64_s(&tm, &t);
ok(ret == EINVAL, "got %d.\n", ret);
ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
ptm = p_gmtime32((__time32_t *)&t);
ok(!ptm, "got NULL.\n");
memset(&tm, 0xcc, sizeof(tm));
ret = p_gmtime32_s(&tm, (__time32_t *)&t);
ok(ret == EINVAL, "got %d.\n", ret);
ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
t = _MAX__TIME64_T + 46800;
memset(&tm, 0xcc, sizeof(tm));
ptm = p_gmtime64(&t);
ok(!!ptm, "got NULL.\n");
ret = p_gmtime64_s(&tm, &t);
ok(!ret, "got %d.\n", ret);
ok(tm.tm_year == 1101 && tm.tm_hour == 20 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
t = _MAX__TIME64_T + 46801;
ptm = p_gmtime64(&t);
ok(!ptm, "got non-NULL.\n");
memset(&tm, 0xcc, sizeof(tm));
ret = p_gmtime64_s(&tm, &t);
ok(ret == EINVAL, "got %d.\n", ret);
ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
}
static void test_mktime(void)
{
TIME_ZONE_INFORMATION tzinfo;
@ -207,7 +300,7 @@ static void test_mktime(void)
ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
WideCharToMultiByte( CP_ACP, 0, tzinfo.StandardName, -1, buffer, sizeof(buffer), NULL, NULL );
trace( "bias %d std %d dst %d zone %s\n",
trace( "bias %ld std %ld dst %ld zone %s\n",
tzinfo.Bias, tzinfo.StandardBias, tzinfo.DaylightBias, buffer );
/* Bias may be positive or negative, to use offset of one day */
my_tm = *localtime(&ref); /* retrieve current dst flag */
@ -227,14 +320,14 @@ static void test_mktime(void)
sav_tm = my_tm;
local_time = mktime(&my_tm);
ok(local_time == ref, "mktime returned %u, expected %u\n",
ok(local_time == ref, "mktime returned %lu, expected %lu\n",
(DWORD)local_time, (DWORD)ref);
/* now test some unnormalized struct tm's */
my_tm = sav_tm;
my_tm.tm_sec += 60;
my_tm.tm_min -= 1;
local_time = mktime(&my_tm);
ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
(DWORD)local_time, (DWORD)ref);
ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
@ -248,7 +341,7 @@ static void test_mktime(void)
my_tm.tm_min -= 60;
my_tm.tm_hour += 1;
local_time = mktime(&my_tm);
ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
(DWORD)local_time, (DWORD)ref);
ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
@ -262,7 +355,7 @@ static void test_mktime(void)
my_tm.tm_mon -= 12;
my_tm.tm_year += 1;
local_time = mktime(&my_tm);
ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
(DWORD)local_time, (DWORD)ref);
ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
@ -276,7 +369,7 @@ static void test_mktime(void)
my_tm.tm_mon += 12;
my_tm.tm_year -= 1;
local_time = mktime(&my_tm);
ok(local_time == ref, "Unnormalized mktime returned %u, expected %u\n",
ok(local_time == ref, "Unnormalized mktime returned %lu, expected %lu\n",
(DWORD)local_time, (DWORD)ref);
ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon &&
my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour &&
@ -298,7 +391,7 @@ static void test_mktime(void)
_snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
putenv("TZ=GMT");
nulltime = mktime(&my_tm);
ok(nulltime == ref,"mktime returned 0x%08x\n",(DWORD)nulltime);
ok(nulltime == ref,"mktime returned 0x%08lx\n",(DWORD)nulltime);
putenv(TZ_env);
}
@ -425,13 +518,12 @@ static void test_wstrdate(void)
{
wchar_t date[16], * result;
int month, day, year, count, len;
wchar_t format[] = { '%','0','2','d','/','%','0','2','d','/','%','0','2','d',0 };
result = _wstrdate(date);
ok(result == date, "Wrong return value\n");
len = wcslen(date);
ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
count = swscanf(date, format, &month, &day, &year);
count = swscanf(date, L"%02d/%02d/%02d", &month, &day, &year);
ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
}
@ -439,13 +531,12 @@ static void test_wstrtime(void)
{
wchar_t time[16], * result;
int hour, minute, second, count, len;
wchar_t format[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',0 };
result = _wstrtime(time);
ok(result == time, "Wrong return value\n");
len = wcslen(time);
ok(len == 8, "Wrong length: returned %d, should be 8\n", len);
count = swscanf(time, format, &hour, &minute, &second);
count = swscanf(time, L"%02d:%02d:%02d", &hour, &minute, &second);
ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
}
@ -575,26 +666,148 @@ static void test_daylight(void)
return;
}
if (!p___p__daylight)
/* Examine the returned pointer from __p__environ(), if available. */
if (sizeof(void*) != sizeof(int))
ok( !p___p__daylight, "___p__daylight() should be 32-bit only\n");
else
{
skip("__p__daylight not available\n");
return;
ret1 = p__daylight();
ret2 = p___p__daylight();
ok(ret1 && ret1 == ret2, "got %p\n", ret1);
}
ret1 = p__daylight();
ret2 = p___p__daylight();
ok(ret1 && ret1 == ret2, "got %p\n", ret1);
}
static void test_strftime(void)
{
static const wchar_t cW[] = { '%','c',0 };
static const char expected[] = "01/01/70 00:00:00";
const struct {
const char *format;
} tests_einval[] = {
{"%C"},
{"%D"},
{"%e"},
{"%F"},
{"%h"},
{"%n"},
{"%R"},
{"%t"},
{"%T"},
{"%u"},
};
const struct {
const char *format;
const char *ret;
struct tm tm;
BOOL todo;
} tests[] = {
{"e%#%e", "e%e", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%c", "01/01/70 00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%c", "02/30/70 00:00:00", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
{"%#c", "Thursday, January 01, 1970 00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%#c", "Thursday, February 30, 1970 00:00:00", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
{"%x", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%x", "02/30/70", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
{"%#x", "Thursday, January 01, 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%#x", "Thursday, February 30, 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
{"%X", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%X", "14:00:00", { 0, 0, 14, 1, 0, 70, 4, 0, 0 }},
{"%a", "Thu", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%A", "Thursday", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%b", "Jan", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%B", "January", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%d", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%#d", "1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%H", "00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%I", "12", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%j", "001", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%m", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%#M", "0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%p", "AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%U", "00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%W", "00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
{"%U", "01", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{"%W", "00", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{"%U", "53", { 0, 0, 0, 1, 0, 70, 0, 365, 0 }},
{"%W", "52", { 0, 0, 0, 1, 0, 70, 0, 365, 0 }},
};
const struct {
const char *format;
const char *ret;
const char *short_date;
const char *date;
const char *time;
struct tm tm;
BOOL todo;
} tests_td[] = {
{ "%c", "x z", "x", "y", "z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#c", "y z", "x", "y", "z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "m1", 0, 0, "MMM", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
{ "%X", "1", 0, 0, "h", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
{ "%X", "01", 0, 0, "hh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
{ "%X", "h01", 0, 0, "hhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
{ "%X", "hh01", 0, 0, "hhhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
{ "%X", "1", 0, 0, "H", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
{ "%X", "01", 0, 0, "HH", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
{ "%X", "H13", 0, 0, "HHH", { 0, 0, 13, 1, 0, 70, 0, 0, 0 }},
{ "%X", "0", 0, 0, "m", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "00", 0, 0, "mm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "0", 0, 0, "s", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "00", 0, 0, "ss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "s00", 0, 0, "sss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "t", 0, 0, "t", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "tam", 0, 0, "tt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "tam", 0, 0, "ttttttttt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "tam", 0, 0, "a", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "tam", 0, 0, "aaaaa", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "tam", 0, 0, "A", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%X", "tam", 0, 0, "AAAAA", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "1", "d", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "01", "dd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "d1", "ddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "day1", "dddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "dday1", "ddddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "1", "M", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "01", "MM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "m1", "MMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "mon1", "MMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "Mmon1", "MMMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "y", "y", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "70", "yy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "y70", "yyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "1970", "yyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "y1970", "yyyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%x", "ggggggggggg", "ggggggggggg", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "1", 0, "d", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "01", 0, "dd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "d1", 0, "ddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "day1", 0, "dddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "dday1", 0, "ddddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "1", 0, "M", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "01", 0, "MM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "m1", 0, "MMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "mon1", 0, "MMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "Mmon1", 0, "MMMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "y", 0, "y", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "70", 0, "yy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "y70", 0, "yyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "1970", 0, "yyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
{ "%#x", "y1970", 0, "yyyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
};
__lc_time_data time_data = {
{ "d1", "d2", "d3", "d4", "d5", "d6", "d7" },
{ "day1", "day2", "day3", "day4", "day5", "day6", "day7" },
{ "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9", "m10", "m11", "m12" },
{ "mon1", "mon2", "mon3", "mon4", "mon5", "mon6", "mon7", "mon8", "mon9", "mon10", "mon11", "mon12" },
"tam", "tpm"
};
time_t gmt;
struct tm* gmt_tm;
char buf[256], bufA[256];
WCHAR bufW[256];
long retA, retW;
int i;
if (!p_strftime || !p_wcsftime || !p_gmtime)
{
@ -608,55 +821,13 @@ static void test_strftime(void)
gmt_tm = p_gmtime(&gmt);
ok(gmt_tm != NULL, "gmtime failed\n");
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%C", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%D", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%e", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%F", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%h", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%n", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%R", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%t", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%T", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, "%u", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
for (i=0; i<ARRAY_SIZE(tests_einval); i++)
{
errno = 0xdeadbeef;
retA = p_strftime(bufA, 256, tests_einval[i].format, gmt_tm);
ok(retA == 0, "%d) ret = %ld\n", i, retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "%d) errno = %d\n", i, errno);
}
errno = 0xdeadbeef;
retA = p_strftime(NULL, 0, "copy", gmt_tm);
@ -691,15 +862,18 @@ static void test_strftime(void)
ok(errno == EINVAL, "errno = %d\n", errno);
}
retA = p_strftime(bufA, 256, "e%#%e", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "e%e"), "got %s\n", bufA);
for (i=0; i<ARRAY_SIZE(tests); i++)
{
retA = p_strftime(bufA, 256, tests[i].format, &tests[i].tm);
todo_wine_if(tests[i].todo) {
ok(retA == strlen(tests[i].ret), "%d) ret = %ld\n", i, retA);
ok(!strcmp(bufA, tests[i].ret), "%d) buf = \"%s\", expected \"%s\"\n",
i, bufA, tests[i].ret);
}
}
retA = p_strftime(bufA, 256, "%c", gmt_tm);
ok(retA == 17, "expected 17, got %ld\n", retA);
ok(strcmp(bufA, expected) == 0, "expected %s, got %s\n", expected, bufA);
retW = p_wcsftime(bufW, 256, cW, gmt_tm);
retW = p_wcsftime(bufW, 256, L"%c", gmt_tm);
ok(retW == 17, "expected 17, got %ld\n", retW);
ok(retA == retW, "expected %ld, got %ld\n", retA, retW);
buf[0] = 0;
@ -707,96 +881,6 @@ static void test_strftime(void)
buf[retA] = 0;
ok(strcmp(bufA, buf) == 0, "expected %s, got %s\n", bufA, buf);
retA = p_strftime(bufA, 256, "%x", gmt_tm);
ok(retA == 8, "expected 8, got %ld\n", retA);
ok(!strcmp(bufA, "01/01/70"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%X", gmt_tm);
ok(retA == 8, "expected 8, got %ld\n", retA);
ok(!strcmp(bufA, "00:00:00"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%a", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "Thu"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%A", gmt_tm);
ok(retA == 8, "expected 8, got %ld\n", retA);
ok(!strcmp(bufA, "Thursday"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%b", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "Jan"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%B", gmt_tm);
ok(retA == 7, "expected 7, got %ld\n", retA);
ok(!strcmp(bufA, "January"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%d", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "01"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%#d", gmt_tm);
ok(retA == 1, "expected 1, got %ld\n", retA);
ok(!strcmp(bufA, "1"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%H", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "00"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%I", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "12"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%j", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "001"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%m", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "01"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%#M", gmt_tm);
ok(retA == 1, "expected 1, got %ld\n", retA);
ok(!strcmp(bufA, "0"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%p", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "AM"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%U", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "00"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%W", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "00"), "got %s\n", bufA);
gmt_tm->tm_wday = 0;
retA = p_strftime(bufA, 256, "%U", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "01"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%W", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "00"), "got %s\n", bufA);
gmt_tm->tm_yday = 365;
retA = p_strftime(bufA, 256, "%U", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "53"), "got %s\n", bufA);
retA = p_strftime(bufA, 256, "%W", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "52"), "got %s\n", bufA);
gmt_tm->tm_mon = 1;
gmt_tm->tm_mday = 30;
retA = p_strftime(bufA, 256, "%c", gmt_tm);
todo_wine {
ok(retA == 17, "expected 17, got %ld\n", retA);
ok(!strcmp(bufA, "02/30/70 00:00:00"), "got %s\n", bufA);
}
if(!setlocale(LC_ALL, "Japanese_Japan.932")) {
win_skip("Japanese_Japan.932 locale not available\n");
return;
@ -806,6 +890,27 @@ static void test_strftime(void)
retA = p_strftime(bufA, 256, "\x82%c", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "\x82%c"), "got %s\n", bufA);
setlocale(LC_ALL, "C");
if(!p__Strftime) {
win_skip("_Strftime is not available\n");
return;
}
/* TODO: find meaning of unk */
time_data.unk = 1;
for (i=0; i<ARRAY_SIZE(tests_td); i++)
{
time_data.short_date = tests_td[i].short_date;
time_data.date = tests_td[i].date;
time_data.time = tests_td[i].time;
retA = p__Strftime(buf, sizeof(buf), tests_td[i].format, &tests_td[i].tm, &time_data);
ok(retA == strlen(buf), "%d) ret = %ld\n", i, retA);
todo_wine_if(tests_td[i].todo) {
ok(!strcmp(buf, tests_td[i].ret), "%d) buf = \"%s\", expected \"%s\"\n",
i, buf, tests_td[i].ret);
}
}
}
static void test_asctime(void)
@ -878,8 +983,11 @@ static void test__tzset(void)
char TZ_env[256];
int ret;
if(!p___p__daylight || !p___p__timezone || !p___p__dstbias) {
skip("__p__daylight, __p__timezone or __p__dstbias is not available\n");
if (sizeof(void*) != sizeof(int))
{
ok(!p___p__daylight, "___p__daylight() should be 32-bit only\n");
ok(!p___p__timezone, "___p__timezone() should be 32-bit only\n");
ok(!p___p__dstbias, "___p__dstbias() should be 32-bit only\n");
return;
}
@ -931,6 +1039,7 @@ START_TEST(time)
test_strftime();
test_ctime();
test_gmtime();
test_gmtime64();
test_mktime();
test_localtime();
test_strdate();