[MSVCRT_WINETEST]: Sync to Wine 1.5.13.

CORE-6415

svn path=/trunk/; revision=57432
This commit is contained in:
Amine Khaldi 2012-09-29 14:28:48 +00:00
parent 7c9b5e3f6c
commit c1abf5e96b
8 changed files with 1140 additions and 259 deletions

View file

@ -15,43 +15,34 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* NOTES
* This tests is only valid for ix86 platforms, on others it's a no-op.
* Some tests cannot be checked with ok(), for example the dtors. We simply
* call them to ensure we don't crash ;-)
*
* If we build this test with VC++ in debug mode, we will fail in _chkstk()
* or at program exit malloc() checking if these methods haven't been
* implemented correctly (they have).
*
* Tested with a range of native msvcrt's from v4 -> v7.
*/
#include "wine/test.h"
#include "winbase.h"
#include "winnt.h"
#ifndef __i386__
/* Skip these tests for non x86 platforms */
START_TEST(cpp)
{
}
#else
typedef void (*vtable_ptr)(void);
typedef struct __exception
{
void *vtable;
vtable_ptr *vtable;
char *name;
int do_free;
} exception;
typedef struct __type_info
{
void *vtable;
vtable_ptr *vtable;
char *name;
char mangled[16];
} type_info;
#undef __thiscall
#ifdef __i386__
#define __thiscall __stdcall
#else
#define __thiscall __cdecl
#endif
/* Function pointers. We need to use these to call these funcs as __thiscall */
static HMODULE hMsvcrt;
@ -61,56 +52,56 @@ static void* (__cdecl *pmalloc)(unsigned int);
static void (__cdecl *pfree)(void*);
/* exception */
static void (WINAPI *pexception_ctor)(exception*,LPCSTR*);
static void (WINAPI *pexception_copy_ctor)(exception*,exception*);
static void (WINAPI *pexception_default_ctor)(exception*);
static void (WINAPI *pexception_dtor)(exception*);
static exception* (WINAPI *pexception_opequals)(exception*,exception*);
static char* (WINAPI *pexception_what)(exception*);
static void* (WINAPI *pexception_vtable)(exception*);
static void (WINAPI *pexception_vector_dtor)(exception*,unsigned int);
static void (WINAPI *pexception_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *pexception_ctor)(exception*,LPCSTR*);
static void (__thiscall *pexception_copy_ctor)(exception*,exception*);
static void (__thiscall *pexception_default_ctor)(exception*);
static void (__thiscall *pexception_dtor)(exception*);
static exception* (__thiscall *pexception_opequals)(exception*,exception*);
static char* (__thiscall *pexception_what)(exception*);
static vtable_ptr *pexception_vtable;
static void (__thiscall *pexception_vector_dtor)(exception*,unsigned int);
static void (__thiscall *pexception_scalar_dtor)(exception*,unsigned int);
/* bad_typeid */
static void (WINAPI *pbad_typeid_ctor)(exception*,LPCSTR);
static void (WINAPI *pbad_typeid_ctor_closure)(exception*);
static void (WINAPI *pbad_typeid_copy_ctor)(exception*,exception*);
static void (WINAPI *pbad_typeid_dtor)(exception*);
static exception* (WINAPI *pbad_typeid_opequals)(exception*,exception*);
static char* (WINAPI *pbad_typeid_what)(exception*);
static void* (WINAPI *pbad_typeid_vtable)(exception*);
static void (WINAPI *pbad_typeid_vector_dtor)(exception*,unsigned int);
static void (WINAPI *pbad_typeid_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_typeid_ctor)(exception*,LPCSTR);
static void (__thiscall *pbad_typeid_ctor_closure)(exception*);
static void (__thiscall *pbad_typeid_copy_ctor)(exception*,exception*);
static void (__thiscall *pbad_typeid_dtor)(exception*);
static exception* (__thiscall *pbad_typeid_opequals)(exception*,exception*);
static char* (__thiscall *pbad_typeid_what)(exception*);
static vtable_ptr *pbad_typeid_vtable;
static void (__thiscall *pbad_typeid_vector_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_typeid_scalar_dtor)(exception*,unsigned int);
/* bad_cast */
static void (WINAPI *pbad_cast_ctor)(exception*,LPCSTR*);
static void (WINAPI *pbad_cast_ctor2)(exception*,LPCSTR);
static void (WINAPI *pbad_cast_ctor_closure)(exception*);
static void (WINAPI *pbad_cast_copy_ctor)(exception*,exception*);
static void (WINAPI *pbad_cast_dtor)(exception*);
static exception* (WINAPI *pbad_cast_opequals)(exception*,exception*);
static char* (WINAPI *pbad_cast_what)(exception*);
static void* (WINAPI *pbad_cast_vtable)(exception*);
static void (WINAPI *pbad_cast_vector_dtor)(exception*,unsigned int);
static void (WINAPI *pbad_cast_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_cast_ctor)(exception*,LPCSTR*);
static void (__thiscall *pbad_cast_ctor2)(exception*,LPCSTR);
static void (__thiscall *pbad_cast_ctor_closure)(exception*);
static void (__thiscall *pbad_cast_copy_ctor)(exception*,exception*);
static void (__thiscall *pbad_cast_dtor)(exception*);
static exception* (__thiscall *pbad_cast_opequals)(exception*,exception*);
static char* (__thiscall *pbad_cast_what)(exception*);
static vtable_ptr *pbad_cast_vtable;
static void (__thiscall *pbad_cast_vector_dtor)(exception*,unsigned int);
static void (__thiscall *pbad_cast_scalar_dtor)(exception*,unsigned int);
/* __non_rtti_object */
static void (WINAPI *p__non_rtti_object_ctor)(exception*,LPCSTR);
static void (WINAPI *p__non_rtti_object_copy_ctor)(exception*,exception*);
static void (WINAPI *p__non_rtti_object_dtor)(exception*);
static exception* (WINAPI *p__non_rtti_object_opequals)(exception*,exception*);
static char* (WINAPI *p__non_rtti_object_what)(exception*);
static void* (WINAPI *p__non_rtti_object_vtable)(exception*);
static void (WINAPI *p__non_rtti_object_vector_dtor)(exception*,unsigned int);
static void (WINAPI *p__non_rtti_object_scalar_dtor)(exception*,unsigned int);
static void (__thiscall *p__non_rtti_object_ctor)(exception*,LPCSTR);
static void (__thiscall *p__non_rtti_object_copy_ctor)(exception*,exception*);
static void (__thiscall *p__non_rtti_object_dtor)(exception*);
static exception* (__thiscall *p__non_rtti_object_opequals)(exception*,exception*);
static char* (__thiscall *p__non_rtti_object_what)(exception*);
static vtable_ptr *p__non_rtti_object_vtable;
static void (__thiscall *p__non_rtti_object_vector_dtor)(exception*,unsigned int);
static void (__thiscall *p__non_rtti_object_scalar_dtor)(exception*,unsigned int);
/* type_info */
static void (WINAPI *ptype_info_dtor)(type_info*);
static char* (WINAPI *ptype_info_raw_name)(type_info*);
static char* (WINAPI *ptype_info_name)(type_info*);
static int (WINAPI *ptype_info_before)(type_info*,type_info*);
static int (WINAPI *ptype_info_opequals_equals)(type_info*,type_info*);
static int (WINAPI *ptype_info_opnot_equals)(type_info*,type_info*);
static void (__thiscall *ptype_info_dtor)(type_info*);
static char* (__thiscall *ptype_info_raw_name)(type_info*);
static char* (__thiscall *ptype_info_name)(type_info*);
static int (__thiscall *ptype_info_before)(type_info*,type_info*);
static int (__thiscall *ptype_info_opequals_equals)(type_info*,type_info*);
static int (__thiscall *ptype_info_opnot_equals)(type_info*,type_info*);
/* RTTI */
static type_info* (__cdecl *p__RTtypeid)(void*);
@ -125,137 +116,69 @@ static char* (__cdecl *p__unDName)(char*,const char*,int,void*,void*,unsigned sh
static void* bAncientVersion;
/* Emulate a __thiscall */
#ifdef _MSC_VER
static inline void* do_call_func1(void *func, void *_this)
#ifdef __i386__
#include "pshpack1.h"
struct thiscall_thunk
{
volatile void* retval = 0;
__asm
{
push ecx
mov ecx, _this
call func
mov retval, eax
pop ecx
}
return (void*)retval;
BYTE pop_eax; /* popl %eax (ret addr) */
BYTE pop_edx; /* popl %edx (func) */
BYTE pop_ecx; /* popl %ecx (this) */
BYTE push_eax; /* pushl %eax */
WORD jmp_edx; /* jmp *%edx */
};
#include "poppack.h"
static void * (WINAPI *call_thiscall_func1)( void *func, void *this );
static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
static void init_thiscall_thunk(void)
{
struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
MEM_COMMIT, PAGE_EXECUTE_READWRITE );
thunk->pop_eax = 0x58; /* popl %eax */
thunk->pop_edx = 0x5a; /* popl %edx */
thunk->pop_ecx = 0x59; /* popl %ecx */
thunk->push_eax = 0x50; /* pushl %eax */
thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
call_thiscall_func1 = (void *)thunk;
call_thiscall_func2 = (void *)thunk;
}
static inline void* do_call_func2(void *func, void *_this, const void* arg)
{
volatile void* retval = 0;
__asm
{
push ecx
push arg
mov ecx, _this
call func
mov retval, eax
pop ecx
}
return (void*)retval;
}
#define call_func1(func,_this) call_thiscall_func1(func,_this)
#define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)a)
#else
static void* do_call_func1(void *func, void *_this)
{
void *ret, *dummy;
__asm__ __volatile__ ("call *%2"
: "=a" (ret), "=c" (dummy)
: "g" (func), "1" (_this)
: "edx", "memory" );
return ret;
}
static void* do_call_func2(void *func, void *_this, const void* arg)
{
void *ret, *dummy;
__asm__ __volatile__ ("pushl %3\n\tcall *%2"
: "=a" (ret), "=c" (dummy)
: "r" (func), "r" (arg), "1" (_this)
: "edx", "memory" );
return ret;
}
#endif
#define call_func1(x,y) do_call_func1((void*)x,(void*)y)
#define call_func2(x,y,z) do_call_func2((void*)x,(void*)y,(const void*)z)
#define init_thiscall_thunk() do { } while(0)
#define call_func1(func,_this) func(_this)
#define call_func2(func,_this,a) func(_this,a)
#endif /* __i386__ */
/* Some exports are only available in later versions */
#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 void InitFunctionPtrs(void)
static BOOL InitFunctionPtrs(void)
{
hMsvcrt = GetModuleHandleA("msvcrt.dll");
if (!hMsvcrt)
hMsvcrt = GetModuleHandleA("msvcrtd.dll");
ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
if (hMsvcrt)
{
if (sizeof(void *) > sizeof(int)) /* 64-bit has different names */
hMsvcrt = GetModuleHandleA("msvcrt.dll");
if (!hMsvcrt)
hMsvcrt = GetModuleHandleA("msvcrtd.dll");
ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
if (!hMsvcrt)
{
SETNOFAIL(poperator_new, "??_U@YAPEAX_K@Z");
SETNOFAIL(poperator_delete, "??_V@YAXPEAX@Z");
}
else
{
SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
win_skip("Could not load msvcrt.dll\n");
return FALSE;
}
SET(pmalloc, "malloc");
SET(pfree, "free");
if (!poperator_new)
poperator_new = pmalloc;
if (!poperator_delete)
poperator_delete = pfree;
SET(pexception_ctor, "??0exception@@QAE@ABQBD@Z");
SET(pexception_copy_ctor, "??0exception@@QAE@ABV0@@Z");
SET(pexception_default_ctor, "??0exception@@QAE@XZ");
SET(pexception_dtor, "??1exception@@UAE@XZ");
SET(pexception_opequals, "??4exception@@QAEAAV0@ABV0@@Z");
SET(pexception_what, "?what@exception@@UBEPBDXZ");
SET(pexception_vtable, "??_7exception@@6B@");
SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");
SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");
SET(pbad_typeid_ctor, "??0bad_typeid@@QAE@PBD@Z");
SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QAEXXZ");
SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QAE@ABV0@@Z");
SET(pbad_typeid_dtor, "??1bad_typeid@@UAE@XZ");
SET(pbad_typeid_opequals, "??4bad_typeid@@QAEAAV0@ABV0@@Z");
SET(pbad_typeid_what, "?what@exception@@UBEPBDXZ");
SET(pbad_typeid_vtable, "??_7bad_typeid@@6B@");
SET(pbad_typeid_vector_dtor, "??_Ebad_typeid@@UAEPAXI@Z");
SET(pbad_typeid_scalar_dtor, "??_Gbad_typeid@@UAEPAXI@Z");
SETNOFAIL(pbad_cast_ctor, "??0bad_cast@@QAE@ABQBD@Z");
if (!pbad_cast_ctor)
SET(pbad_cast_ctor, "??0bad_cast@@AAE@PBQBD@Z");
SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@@QAE@PBD@Z");
SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@@QAEXXZ");
SET(pbad_cast_copy_ctor, "??0bad_cast@@QAE@ABV0@@Z");
SET(pbad_cast_dtor, "??1bad_cast@@UAE@XZ");
SET(pbad_cast_opequals, "??4bad_cast@@QAEAAV0@ABV0@@Z");
SET(pbad_cast_what, "?what@exception@@UBEPBDXZ");
SET(pbad_cast_vtable, "??_7bad_cast@@6B@");
SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
SET(p__non_rtti_object_ctor, "??0__non_rtti_object@@QAE@PBD@Z");
SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QAE@ABV0@@Z");
SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UAE@XZ");
SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QAEAAV0@ABV0@@Z");
SET(p__non_rtti_object_what, "?what@exception@@UBEPBDXZ");
SET(p__non_rtti_object_vtable, "??_7__non_rtti_object@@6B@");
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(ptype_info_dtor, "??1type_info@@UAE@XZ");
SET(ptype_info_raw_name, "?raw_name@type_info@@QBEPBDXZ");
SET(ptype_info_name, "?name@type_info@@QBEPBDXZ");
SET(ptype_info_before, "?before@type_info@@QBEHABV1@@Z");
SET(ptype_info_opequals_equals, "??8type_info@@QBEHABV0@@Z");
SET(ptype_info_opnot_equals, "??9type_info@@QBEHABV0@@Z");
SET(p__RTtypeid, "__RTtypeid");
SET(p__RTCastToVoid, "__RTCastToVoid");
@ -265,7 +188,112 @@ static void InitFunctionPtrs(void)
/* 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");
SETNOFAIL(poperator_delete, "??_V@YAXPEAX@Z");
SET(pexception_ctor, "??0exception@@QEAA@AEBQEBD@Z");
SET(pexception_copy_ctor, "??0exception@@QEAA@AEBV0@@Z");
SET(pexception_default_ctor, "??0exception@@QEAA@XZ");
SET(pexception_dtor, "??1exception@@UEAA@XZ");
SET(pexception_opequals, "??4exception@@QEAAAEAV0@AEBV0@@Z");
SET(pexception_what, "?what@exception@@UEBAPEBDXZ");
pexception_vector_dtor = (void*)pexception_vtable[0];
pexception_scalar_dtor = (void*)pexception_vtable[0];
SET(pbad_typeid_ctor, "??0bad_typeid@@QEAA@PEBD@Z");
SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QEAAXXZ");
SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QEAA@AEBV0@@Z");
SET(pbad_typeid_dtor, "??1bad_typeid@@UEAA@XZ");
SET(pbad_typeid_opequals, "??4bad_typeid@@QEAAAEAV0@AEBV0@@Z");
SET(pbad_typeid_what, "?what@exception@@UEBAPEBDXZ");
pbad_typeid_vector_dtor = (void*)pbad_typeid_vtable[0];
pbad_typeid_scalar_dtor = (void*)pbad_typeid_vtable[0];
SET(pbad_cast_ctor, "??0bad_cast@@QEAA@AEBQEBD@Z");
SET(pbad_cast_ctor2, "??0bad_cast@@QEAA@PEBD@Z");
SET(pbad_cast_ctor_closure, "??_Fbad_cast@@QEAAXXZ");
SET(pbad_cast_copy_ctor, "??0bad_cast@@QEAA@AEBV0@@Z");
SET(pbad_cast_dtor, "??1bad_cast@@UEAA@XZ");
SET(pbad_cast_opequals, "??4bad_cast@@QEAAAEAV0@AEBV0@@Z");
SET(pbad_cast_what, "?what@exception@@UEBAPEBDXZ");
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@@QEAA@PEBD@Z");
SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QEAA@AEBV0@@Z");
SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UEAA@XZ");
SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QEAAAEAV0@AEBV0@@Z");
SET(p__non_rtti_object_what, "?what@exception@@UEBAPEBDXZ");
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@@UEAA@XZ");
SET(ptype_info_raw_name, "?raw_name@type_info@@QEBAPEBDXZ");
SET(ptype_info_name, "?name@type_info@@QEBAPEBDXZ");
SET(ptype_info_before, "?before@type_info@@QEBAHAEBV1@@Z");
SET(ptype_info_opequals_equals, "??8type_info@@QEBAHAEBV0@@Z");
SET(ptype_info_opnot_equals, "??9type_info@@QEBAHAEBV0@@Z");
}
else
{
SETNOFAIL(poperator_new, "??_U@YAPAXI@Z");
SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z");
SET(pexception_ctor, "??0exception@@QAE@ABQBD@Z");
SET(pexception_copy_ctor, "??0exception@@QAE@ABV0@@Z");
SET(pexception_default_ctor, "??0exception@@QAE@XZ");
SET(pexception_dtor, "??1exception@@UAE@XZ");
SET(pexception_opequals, "??4exception@@QAEAAV0@ABV0@@Z");
SET(pexception_what, "?what@exception@@UBEPBDXZ");
SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");
SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");
SET(pbad_typeid_ctor, "??0bad_typeid@@QAE@PBD@Z");
SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QAEXXZ");
SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QAE@ABV0@@Z");
SET(pbad_typeid_dtor, "??1bad_typeid@@UAE@XZ");
SET(pbad_typeid_opequals, "??4bad_typeid@@QAEAAV0@ABV0@@Z");
SET(pbad_typeid_what, "?what@exception@@UBEPBDXZ");
SET(pbad_typeid_vector_dtor, "??_Ebad_typeid@@UAEPAXI@Z");
SET(pbad_typeid_scalar_dtor, "??_Gbad_typeid@@UAEPAXI@Z");
SETNOFAIL(pbad_cast_ctor, "??0bad_cast@@QAE@ABQBD@Z");
if (!pbad_cast_ctor)
SET(pbad_cast_ctor, "??0bad_cast@@AAE@PBQBD@Z");
SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@@QAE@PBD@Z");
SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@@QAEXXZ");
SET(pbad_cast_copy_ctor, "??0bad_cast@@QAE@ABV0@@Z");
SET(pbad_cast_dtor, "??1bad_cast@@UAE@XZ");
SET(pbad_cast_opequals, "??4bad_cast@@QAEAAV0@ABV0@@Z");
SET(pbad_cast_what, "?what@exception@@UBEPBDXZ");
SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z");
SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z");
SET(p__non_rtti_object_ctor, "??0__non_rtti_object@@QAE@PBD@Z");
SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QAE@ABV0@@Z");
SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UAE@XZ");
SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QAEAAV0@ABV0@@Z");
SET(p__non_rtti_object_what, "?what@exception@@UBEPBDXZ");
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(ptype_info_dtor, "??1type_info@@UAE@XZ");
SET(ptype_info_raw_name, "?raw_name@type_info@@QBEPBDXZ");
SET(ptype_info_name, "?name@type_info@@QBEPBDXZ");
SET(ptype_info_before, "?before@type_info@@QBEHABV1@@Z");
SET(ptype_info_opequals_equals, "??8type_info@@QBEHABV0@@Z");
SET(ptype_info_opnot_equals, "??9type_info@@QBEHABV0@@Z");
}
if (!poperator_new)
poperator_new = pmalloc;
if (!poperator_delete)
poperator_delete = pfree;
init_thiscall_thunk();
return TRUE;
}
static void test_exception(void)
@ -346,14 +374,14 @@ static void test_exception(void)
call_func2(pexception_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
char name[] = "a constant";
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(pexception_ctor, &pe[0], &e_name);
call_func2(pexception_ctor, &pe[1], &e_name);
call_func2(pexception_ctor, &pe[2], &e_name);
@ -471,13 +499,13 @@ static void test_bad_typeid(void)
call_func2(pbad_typeid_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(pbad_typeid_ctor, &pe[0], e_name);
call_func2(pbad_typeid_ctor, &pe[1], e_name);
call_func2(pbad_typeid_ctor, &pe[2], e_name);
@ -599,13 +627,13 @@ static void test_bad_cast(void)
call_func2(pbad_cast_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(pbad_cast_ctor, &pe[0], &e_name);
call_func2(pbad_cast_ctor, &pe[1], &e_name);
call_func2(pbad_cast_ctor, &pe[2], &e_name);
@ -701,13 +729,13 @@ static void test___non_rtti_object(void)
call_func2(p__non_rtti_object_vector_dtor, pe, 1); /* Should delete pe as single element*/
}
pe = poperator_new(sizeof(exception) * 4 + sizeof(int));
pe = poperator_new(sizeof(exception) * 4 + sizeof(size_t));
ok(pe != NULL, "new() failed\n");
if (pe)
{
/* vector dtor, multiple elements */
*((int*)pe) = 3;
pe = (exception*)((int*)pe + 1);
*((size_t*)pe) = 3;
pe = (exception*)((size_t*)pe + 1);
call_func2(p__non_rtti_object_ctor, &pe[0], e_name);
call_func2(p__non_rtti_object_ctor, &pe[1], e_name);
call_func2(p__non_rtti_object_ctor, &pe[2], e_name);
@ -733,7 +761,6 @@ static void test___non_rtti_object(void)
call_func2(p__non_rtti_object_vector_dtor, &e, 0); /* Should delete e.name, but not e */
}
static void test_type_info(void)
{
static type_info t1 = { NULL, NULL,{'.','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
@ -801,13 +828,99 @@ static void test_type_info(void)
ok(res == 1, "expected 1, got %d\n", res);
}
static inline vtable_ptr *get_vtable( void *obj )
{
return *(vtable_ptr **)obj;
}
static inline void/*rtti_object_locator*/ *get_obj_locator( void *cppobj )
{
const vtable_ptr *vtable = get_vtable( cppobj );
return (void *)vtable[-1];
}
#ifndef __x86_64__
#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)
#else
#define DEFINE_RTTI_REF(type, name) unsigned name
#define RTTI_REF(instance, name) FIELD_OFFSET(struct rtti_data, name)
#define RTTI_REF_SIG0(instance, name, base) ((char*)&instance.name-base)
#endif
/* Test RTTI functions */
static void test_rtti(void)
{
struct _object_locator
{
unsigned int signature;
int base_class_offset;
unsigned int flags;
DEFINE_RTTI_REF(type_info, type_descriptor);
DEFINE_RTTI_REF(struct _rtti_object_hierarchy, type_hierarchy);
DEFINE_RTTI_REF(void, object_locator);
} *obj_locator;
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 _object_locator object_locator;
} simple_class_rtti = {
{ {NULL, NULL, "simple_class"} },
{ {RTTI_REF(simple_class_rtti, type_info[0]), 0, {0, 0, 0}, 0} },
{ {RTTI_REF(simple_class_rtti, base_descriptor[0])} },
{0, 0, 1, RTTI_REF(simple_class_rtti, base_array)},
{1, 0, 0, RTTI_REF(simple_class_rtti, type_info[0]), RTTI_REF(simple_class_rtti, object_hierarchy), RTTI_REF(simple_class_rtti, object_locator)}
}, child_class_rtti = {
{ {NULL, NULL, "simple_class"}, {NULL, NULL, "child_class"} },
{ {RTTI_REF(child_class_rtti, type_info[1]), 0, {4, -1, 0}, 0}, {RTTI_REF(child_class_rtti, type_info[0]), 0, {8, -1, 0}, 0} },
{ {RTTI_REF(child_class_rtti, base_descriptor[0]), RTTI_REF(child_class_rtti, base_descriptor[1])} },
{0, 0, 2, RTTI_REF(child_class_rtti, base_array)},
{1, 0, 0, RTTI_REF(child_class_rtti, type_info[1]), RTTI_REF(child_class_rtti, object_hierarchy), RTTI_REF(child_class_rtti, object_locator)}
};
static struct rtti_data simple_class_sig0_rtti, child_class_sig0_rtti;
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];
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];
static const char* e_name = "name";
type_info *ti,*bti;
exception e,b;
void *casted;
BOOL old_signature;
#ifdef __x86_64__
char *base = (char*)GetModuleHandleW(NULL);
#endif
if (bAncientVersion ||
!p__RTCastToVoid || !p__RTtypeid || !pexception_ctor || !pbad_typeid_ctor
@ -817,6 +930,12 @@ static void test_rtti(void)
call_func2(pexception_ctor, &e, &e_name);
call_func2(pbad_typeid_ctor, &b, e_name);
obj_locator = get_obj_locator(&e);
if(obj_locator->signature!=1 && sizeof(void*)>sizeof(int))
old_signature = TRUE;
else
old_signature = FALSE;
/* dynamic_cast to void* */
casted = p__RTCastToVoid(&e);
ok (casted == (void*)&e, "failed cast to void\n");
@ -838,6 +957,75 @@ static void test_rtti(void)
call_func1(pexception_dtor, &e);
call_func1(pbad_typeid_dtor, &b);
memcpy(&simple_class_sig0_rtti, &simple_class_rtti, sizeof(struct rtti_data));
simple_class_sig0_rtti.object_locator.signature = 0;
simple_class_sig0_rtti.base_descriptor[0].type_descriptor = RTTI_REF_SIG0(simple_class_sig0_rtti, type_info[0], base);
simple_class_sig0_rtti.base_array.bases[0] = RTTI_REF_SIG0(simple_class_sig0_rtti, base_descriptor[0], base);
simple_class_sig0_rtti.object_hierarchy.base_classes = RTTI_REF_SIG0(simple_class_sig0_rtti, base_array, base);
simple_class_sig0_rtti.object_locator.type_descriptor = RTTI_REF_SIG0(simple_class_sig0_rtti, type_info[0], base);
simple_class_sig0_rtti.object_locator.type_hierarchy = RTTI_REF_SIG0(simple_class_sig0_rtti, object_hierarchy, base);
memcpy(&child_class_sig0_rtti, &child_class_rtti, sizeof(struct rtti_data));
child_class_sig0_rtti.object_locator.signature = 0;
child_class_sig0_rtti.base_descriptor[0].type_descriptor = RTTI_REF_SIG0(child_class_sig0_rtti, type_info[1], base);
child_class_sig0_rtti.base_descriptor[1].type_descriptor = RTTI_REF_SIG0(child_class_sig0_rtti, type_info[0], base);
child_class_sig0_rtti.base_array.bases[0] = RTTI_REF_SIG0(child_class_sig0_rtti, base_descriptor[0], base);
child_class_sig0_rtti.base_array.bases[1] = RTTI_REF_SIG0(child_class_sig0_rtti, base_descriptor[1], base);
child_class_sig0_rtti.object_hierarchy.base_classes = RTTI_REF_SIG0(child_class_sig0_rtti, base_array, base);
child_class_sig0_rtti.object_locator.type_descriptor = RTTI_REF_SIG0(child_class_sig0_rtti, type_info[1], base);
child_class_sig0_rtti.object_locator.type_hierarchy = RTTI_REF_SIG0(child_class_sig0_rtti, object_hierarchy, base);
ti = p__RTtypeid(&simple_class_sig0);
ok (ti && ti->mangled && !strcmp(ti->mangled, "simple_class"),
"incorrect rtti data\n");
casted = p__RTCastToVoid(&simple_class_sig0);
ok (casted == (void*)&simple_class_sig0, "failed cast to void\n");
ti = p__RTtypeid(&child_class_sig0);
ok (ti && ti->mangled && !strcmp(ti->mangled, "child_class"),
"incorrect rtti data\n");
casted = p__RTCastToVoid(&child_class_sig0);
ok (casted == (void*)&child_class_sig0, "failed cast to void\n");
casted = p__RTDynamicCast(&child_class_sig0, 0, NULL, simple_class_sig0_rtti.type_info, 0);
if(casted)
{
ok (casted == (char*)&child_class_sig0+8, "failed cast to simple_class (%p %p)\n", casted, &child_class_sig0);
}
casted = p__RTDynamicCast(&child_class_sig0, 0, &child_class_sig0_rtti.type_info[0], &child_class_sig0_rtti.type_info[1], 0);
ok(casted == (char*)&child_class_sig0+4, "failed cast to child class (%p %p)\n", casted, &child_class_sig0);
if(old_signature) {
skip("signature==1 is not supported\n");
return;
}
ti = p__RTtypeid(&simple_class);
ok (ti && ti->mangled && !strcmp(ti->mangled, "simple_class"),
"incorrect rtti data\n");
casted = p__RTCastToVoid(&simple_class);
ok (casted == (void*)&simple_class, "failed cast to void\n");
ti = p__RTtypeid(&child_class);
ok (ti && ti->mangled && !strcmp(ti->mangled, "child_class"),
"incorrect rtti data\n");
casted = p__RTCastToVoid(&child_class);
ok (casted == (void*)&child_class, "failed cast to void\n");
casted = p__RTDynamicCast(&child_class, 0, NULL, simple_class_rtti.type_info, 0);
if(casted)
{
ok (casted == (char*)&child_class+8, "failed cast to simple_class (%p %p)\n", casted, &child_class);
}
casted = p__RTDynamicCast(&child_class, 0, &child_class_rtti.type_info[0], &child_class_rtti.type_info[1], 0);
ok(casted == (char*)&child_class+4, "failed cast to child class (%p %p)\n", casted, &child_class);
}
struct _demangle {
@ -1081,7 +1269,8 @@ static void test_demangle(void)
START_TEST(cpp)
{
InitFunctionPtrs();
if (!InitFunctionPtrs())
return;
test_exception();
test_bad_typeid();
@ -1092,4 +1281,3 @@ START_TEST(cpp)
test_demangle_datatype();
test_demangle();
}
#endif /* __i386__ */

View file

@ -434,6 +434,37 @@ static void test_asciimode2(void)
unlink("ascii2.tst");
}
static void test_filemodeT(void)
{
char DATA [] = {26, 't', 'e', 's' ,'t'};
char DATA2 [100];
char temppath[MAX_PATH];
char tempfile[MAX_PATH];
FILE* f;
size_t bytesWritten;
size_t bytesRead;
WIN32_FIND_DATA findData;
HANDLE h;
GetTempPath (MAX_PATH, temppath);
GetTempFileName (temppath, "", 0, tempfile);
f = fopen(tempfile, "w+bDT");
bytesWritten = fwrite(DATA, 1, sizeof(DATA), f);
rewind(f);
bytesRead = fread(DATA2, 1, sizeof(DATA2), f);
fclose(f);
ok (bytesRead == bytesWritten && bytesRead == sizeof(DATA),
"fopen file mode 'T' wrongly interpreted as 't'\n" );
h = FindFirstFile(tempfile, &findData);
ok (h == INVALID_HANDLE_VALUE, "file wasn't deleted when closed.\n" );
if (h != INVALID_HANDLE_VALUE) FindClose(h);
}
static WCHAR* AtoW( const char* p )
{
WCHAR* buffer;
@ -544,10 +575,21 @@ static void test_flsbuf( void )
bufmodes[bufmode], 0, ret);
ret = _flsbuf(0xff,tempfh);
ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
bufmodes[bufmode], 0, ret);
bufmodes[bufmode], 0xff, ret);
ret = _flsbuf(0xffffffff,tempfh);
ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
bufmodes[bufmode], 0, ret);
bufmodes[bufmode], 0xff, ret);
if(tempfh->_base) {
fputc('x', tempfh);
tempfh->_cnt = -1;
tempfh->_base[1] = 'a';
ret = _flsbuf(0xab,tempfh);
ok(ret == 0xab, "_flsbuf(0xab,tempfh) with bufmode %x expected 0xab got %x\n",
bufmodes[bufmode], ret);
ok(tempfh->_base[1] == 'a', "tempfh->_base[1] should not be changed (%d)\n",
tempfh->_base[1]);
}
fclose(tempfh);
}
@ -580,6 +622,58 @@ static void test_flsbuf( void )
free(tempf);
}
static void test_fflush( void )
{
static const char obuf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
char buf1[16], buf2[24];
char *tempf;
FILE *tempfh;
int ret;
tempf=_tempnam(".","wne");
/* Prepare the file. */
tempfh = fopen(tempf,"wb");
ok(tempfh != NULL, "Can't open test file.\n");
fwrite(obuf, 1, sizeof(obuf), tempfh);
fclose(tempfh);
/* Open the file for input. */
tempfh = fopen(tempf,"rb");
ok(tempfh != NULL, "Can't open test file.\n");
fread(buf1, 1, sizeof(buf1), tempfh);
/* Using fflush() on input stream is undefined in ANSI.
* But MSDN says that it clears input buffer. */
_lseek(_fileno(tempfh), 0, SEEK_SET);
ret = fflush(tempfh);
ok(ret == 0, "expected 0, got %d\n", ret);
memset(buf2, '?', sizeof(buf2));
fread(buf2, 1, sizeof(buf2), tempfh);
ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
/* fflush(NULL) doesn't clear input buffer. */
_lseek(_fileno(tempfh), 0, SEEK_SET);
ret = fflush(NULL);
ok(ret == 0, "expected 0, got %d\n", ret);
memset(buf2, '?', sizeof(buf2));
fread(buf2, 1, sizeof(buf2), tempfh);
ok(memcmp(buf1, buf2, sizeof(buf1)) != 0, "Got unexpected data (%c)\n", buf2[0]);
/* _flushall() clears input buffer. */
_lseek(_fileno(tempfh), 0, SEEK_SET);
ret = _flushall();
ok(ret >= 0, "unexpected ret %d\n", ret);
memset(buf2, '?', sizeof(buf2));
fread(buf2, 1, sizeof(buf2), tempfh);
ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
fclose(tempfh);
unlink(tempf);
free(tempf);
}
static void test_fgetwc( void )
{
#define LLEN 512
@ -1565,12 +1659,14 @@ START_TEST(file)
test_fileops();
test_asciimode();
test_asciimode2();
test_filemodeT();
test_readmode(FALSE); /* binary mode */
test_readmode(TRUE); /* ascii mode */
test_readboundary();
test_fgetc();
test_fputc();
test_flsbuf();
test_fflush();
test_fgetwc();
test_ctrlz();
test_file_put_get();

View file

@ -25,6 +25,7 @@
static BOOL (__cdecl *p__crtGetStringTypeW)(DWORD, DWORD, const wchar_t*, int, WORD*);
static int (__cdecl *pmemcpy_s)(void *, size_t, void*, size_t);
void* __cdecl _Gettnames(void);
static void init(void)
{
@ -471,10 +472,11 @@ static void test_setlocale(void)
if(ret)
ok(!strcmp(ret, "Polish_Poland.1250"), "ret = %s\n", ret);
ret = setlocale(LC_ALL, "portugese");
ret = setlocale(LC_ALL, "portuguese");
ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
if(ret)
ok(!strcmp(ret, "Portuguese_Brazil.1252"), "ret = %s\n", ret);
ok(!strcmp(ret, "Portuguese_Brazil.1252")
|| broken(!strcmp(ret, "Portuguese_Portugal.1252")) /* NT4 */, "ret = %s\n", ret);
ret = setlocale(LC_ALL, "portuguese-brazil");
ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
@ -616,10 +618,131 @@ static void test_crtGetStringTypeW(void)
ok(!ret, "ret == TRUE\n");
}
static void test__Gettnames(void)
{
struct {
char *str[43];
LCID lcid;
int unk[2];
wchar_t *wstr[43];
char data[1];
} *ret;
int size;
if(!setlocale(LC_ALL, "english"))
return;
ret = _Gettnames();
size = ret->data-(char*)ret;
/* Newer version of the structure stores both ascii and unicode strings.
* Unicode strings are only initialized on Windows 7
*/
if(sizeof(void*) == 8)
ok(size==0x2c0 || broken(size==0x170), "strucure size: %x\n", size);
else
ok(size==0x164 || broken(size==0xb8), "strucure size: %x\n", size);
ok(!strcmp(ret->str[0], "Sun"), "ret->str[0] = %s\n", ret->str[0]);
ok(!strcmp(ret->str[1], "Mon"), "ret->str[1] = %s\n", ret->str[1]);
ok(!strcmp(ret->str[2], "Tue"), "ret->str[2] = %s\n", ret->str[2]);
ok(!strcmp(ret->str[3], "Wed"), "ret->str[3] = %s\n", ret->str[3]);
ok(!strcmp(ret->str[4], "Thu"), "ret->str[4] = %s\n", ret->str[4]);
ok(!strcmp(ret->str[5], "Fri"), "ret->str[5] = %s\n", ret->str[5]);
ok(!strcmp(ret->str[6], "Sat"), "ret->str[6] = %s\n", ret->str[6]);
ok(!strcmp(ret->str[7], "Sunday"), "ret->str[7] = %s\n", ret->str[7]);
ok(!strcmp(ret->str[8], "Monday"), "ret->str[8] = %s\n", ret->str[8]);
ok(!strcmp(ret->str[9], "Tuesday"), "ret->str[9] = %s\n", ret->str[9]);
ok(!strcmp(ret->str[10], "Wednesday"), "ret->str[10] = %s\n", ret->str[10]);
ok(!strcmp(ret->str[11], "Thursday"), "ret->str[11] = %s\n", ret->str[11]);
ok(!strcmp(ret->str[12], "Friday"), "ret->str[12] = %s\n", ret->str[12]);
ok(!strcmp(ret->str[13], "Saturday"), "ret->str[13] = %s\n", ret->str[13]);
ok(!strcmp(ret->str[14], "Jan"), "ret->str[14] = %s\n", ret->str[14]);
ok(!strcmp(ret->str[15], "Feb"), "ret->str[15] = %s\n", ret->str[15]);
ok(!strcmp(ret->str[16], "Mar"), "ret->str[16] = %s\n", ret->str[16]);
ok(!strcmp(ret->str[17], "Apr"), "ret->str[17] = %s\n", ret->str[17]);
ok(!strcmp(ret->str[18], "May"), "ret->str[18] = %s\n", ret->str[18]);
ok(!strcmp(ret->str[19], "Jun"), "ret->str[19] = %s\n", ret->str[19]);
ok(!strcmp(ret->str[20], "Jul"), "ret->str[20] = %s\n", ret->str[20]);
ok(!strcmp(ret->str[21], "Aug"), "ret->str[21] = %s\n", ret->str[21]);
ok(!strcmp(ret->str[22], "Sep"), "ret->str[22] = %s\n", ret->str[22]);
ok(!strcmp(ret->str[23], "Oct"), "ret->str[23] = %s\n", ret->str[23]);
ok(!strcmp(ret->str[24], "Nov"), "ret->str[24] = %s\n", ret->str[24]);
ok(!strcmp(ret->str[25], "Dec"), "ret->str[25] = %s\n", ret->str[25]);
ok(!strcmp(ret->str[26], "January"), "ret->str[26] = %s\n", ret->str[26]);
ok(!strcmp(ret->str[27], "February"), "ret->str[27] = %s\n", ret->str[27]);
ok(!strcmp(ret->str[28], "March"), "ret->str[28] = %s\n", ret->str[28]);
ok(!strcmp(ret->str[29], "April"), "ret->str[29] = %s\n", ret->str[29]);
ok(!strcmp(ret->str[30], "May"), "ret->str[30] = %s\n", ret->str[30]);
ok(!strcmp(ret->str[31], "June"), "ret->str[31] = %s\n", ret->str[31]);
ok(!strcmp(ret->str[32], "July"), "ret->str[32] = %s\n", ret->str[32]);
ok(!strcmp(ret->str[33], "August"), "ret->str[33] = %s\n", ret->str[33]);
ok(!strcmp(ret->str[34], "September"), "ret->str[34] = %s\n", ret->str[34]);
ok(!strcmp(ret->str[35], "October"), "ret->str[35] = %s\n", ret->str[35]);
ok(!strcmp(ret->str[36], "November"), "ret->str[36] = %s\n", ret->str[36]);
ok(!strcmp(ret->str[37], "December"), "ret->str[37] = %s\n", ret->str[37]);
ok(!strcmp(ret->str[38], "AM"), "ret->str[38] = %s\n", ret->str[38]);
ok(!strcmp(ret->str[39], "PM"), "ret->str[39] = %s\n", ret->str[39]);
ok(!strcmp(ret->str[40], "M/d/yyyy") || broken(!strcmp(ret->str[40], "M/d/yy"))/*NT*/,
"ret->str[40] = %s\n", ret->str[40]);
ok(!strcmp(ret->str[41], "dddd, MMMM dd, yyyy"), "ret->str[41] = %s\n", ret->str[41]);
free(ret);
if(!setlocale(LC_TIME, "german"))
return;
ret = _Gettnames();
ok(!strcmp(ret->str[0], "So"), "ret->str[0] = %s\n", ret->str[0]);
ok(!strcmp(ret->str[1], "Mo"), "ret->str[1] = %s\n", ret->str[1]);
ok(!strcmp(ret->str[2], "Di"), "ret->str[2] = %s\n", ret->str[2]);
ok(!strcmp(ret->str[3], "Mi"), "ret->str[3] = %s\n", ret->str[3]);
ok(!strcmp(ret->str[4], "Do"), "ret->str[4] = %s\n", ret->str[4]);
ok(!strcmp(ret->str[5], "Fr"), "ret->str[5] = %s\n", ret->str[5]);
ok(!strcmp(ret->str[6], "Sa"), "ret->str[6] = %s\n", ret->str[6]);
ok(!strcmp(ret->str[7], "Sonntag"), "ret->str[7] = %s\n", ret->str[7]);
ok(!strcmp(ret->str[8], "Montag"), "ret->str[8] = %s\n", ret->str[8]);
ok(!strcmp(ret->str[9], "Dienstag"), "ret->str[9] = %s\n", ret->str[9]);
ok(!strcmp(ret->str[10], "Mittwoch"), "ret->str[10] = %s\n", ret->str[10]);
ok(!strcmp(ret->str[11], "Donnerstag"), "ret->str[11] = %s\n", ret->str[11]);
ok(!strcmp(ret->str[12], "Freitag"), "ret->str[12] = %s\n", ret->str[12]);
ok(!strcmp(ret->str[13], "Samstag"), "ret->str[13] = %s\n", ret->str[13]);
ok(!strcmp(ret->str[14], "Jan"), "ret->str[14] = %s\n", ret->str[14]);
ok(!strcmp(ret->str[15], "Feb"), "ret->str[15] = %s\n", ret->str[15]);
ok(!strcmp(ret->str[16], "Mrz"), "ret->str[16] = %s\n", ret->str[16]);
ok(!strcmp(ret->str[17], "Apr"), "ret->str[17] = %s\n", ret->str[17]);
ok(!strcmp(ret->str[18], "Mai"), "ret->str[18] = %s\n", ret->str[18]);
ok(!strcmp(ret->str[19], "Jun"), "ret->str[19] = %s\n", ret->str[19]);
ok(!strcmp(ret->str[20], "Jul"), "ret->str[20] = %s\n", ret->str[20]);
ok(!strcmp(ret->str[21], "Aug"), "ret->str[21] = %s\n", ret->str[21]);
ok(!strcmp(ret->str[22], "Sep"), "ret->str[22] = %s\n", ret->str[22]);
ok(!strcmp(ret->str[23], "Okt"), "ret->str[23] = %s\n", ret->str[23]);
ok(!strcmp(ret->str[24], "Nov"), "ret->str[24] = %s\n", ret->str[24]);
ok(!strcmp(ret->str[25], "Dez"), "ret->str[25] = %s\n", ret->str[25]);
ok(!strcmp(ret->str[26], "Januar"), "ret->str[26] = %s\n", ret->str[26]);
ok(!strcmp(ret->str[27], "Februar"), "ret->str[27] = %s\n", ret->str[27]);
ok(!strcmp(ret->str[29], "April"), "ret->str[29] = %s\n", ret->str[29]);
ok(!strcmp(ret->str[30], "Mai"), "ret->str[30] = %s\n", ret->str[30]);
ok(!strcmp(ret->str[31], "Juni"), "ret->str[31] = %s\n", ret->str[31]);
ok(!strcmp(ret->str[32], "Juli"), "ret->str[32] = %s\n", ret->str[32]);
ok(!strcmp(ret->str[33], "August"), "ret->str[33] = %s\n", ret->str[33]);
ok(!strcmp(ret->str[34], "September"), "ret->str[34] = %s\n", ret->str[34]);
ok(!strcmp(ret->str[35], "Oktober"), "ret->str[35] = %s\n", ret->str[35]);
ok(!strcmp(ret->str[36], "November"), "ret->str[36] = %s\n", ret->str[36]);
ok(!strcmp(ret->str[37], "Dezember"), "ret->str[37] = %s\n", ret->str[37]);
ok(!strcmp(ret->str[38], ""), "ret->str[38] = %s\n", ret->str[38]);
ok(!strcmp(ret->str[39], ""), "ret->str[39] = %s\n", ret->str[39]);
ok(!strcmp(ret->str[40], "dd.MM.yyyy") || broken(!strcmp(ret->str[40], "dd.MM.yy"))/*NT*/,
"ret->str[40] = %s\n", ret->str[40]);
ok(!strcmp(ret->str[41], "dddd, d. MMMM yyyy"), "ret->str[41] = %s\n", ret->str[41]);
free(ret);
setlocale(LC_ALL, "C");
}
START_TEST(locale)
{
init();
test_crtGetStringTypeW();
test_setlocale();
test__Gettnames();
}

View file

@ -23,7 +23,6 @@
#include "msvcrt.h"
static int (__cdecl *prand_s)(unsigned int *);
static int (__cdecl *pmemcpy_s)(void *, MSVCRT_size_t, void*, MSVCRT_size_t);
static int (__cdecl *pI10_OUTPUT)(long double, int, int, void*);
static int (__cdecl *pstrerror_s)(char *, MSVCRT_size_t, int);
static int (__cdecl *p_get_doserrno)(int *);
@ -36,7 +35,6 @@ static void init(void)
HMODULE hmod = GetModuleHandleA("msvcrt.dll");
prand_s = (void *)GetProcAddress(hmod, "rand_s");
pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s");
pI10_OUTPUT = (void*)GetProcAddress(hmod, "$I10_OUTPUT");
pstrerror_s = (void *)GetProcAddress(hmod, "strerror_s");
p_get_doserrno = (void *)GetProcAddress(hmod, "_get_doserrno");
@ -65,57 +63,6 @@ static void test_rand_s(void)
ok(ret == 0, "Expected rand_s to return 0, got %d\n", ret);
}
static void test_memcpy_s(void)
{
static char data[] = "data\0to\0be\0copied";
static char dest[32];
int ret;
if(!pmemcpy_s)
{
win_skip("memcpy_s is not available\n");
return;
}
errno = 0xdeadbeef;
ret = pmemcpy_s(NULL, 0, NULL, 0);
ok(ret == 0, "ret = %x\n", ret);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
errno = 0xdeadbeef;
dest[0] = 'x';
ret = pmemcpy_s(dest, 10, NULL, 0);
ok(ret == 0, "ret = %x\n", ret);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
ok(dest[0] == 'x', "dest[0] != \'x\'\n");
errno = 0xdeadbeef;
ret = pmemcpy_s(NULL, 10, data, 10);
ok(ret == EINVAL, "ret = %x\n", ret);
ok(errno == EINVAL, "errno = %x\n", errno);
errno = 0xdeadbeef;
dest[7] = 'x';
ret = pmemcpy_s(dest, 10, data, 5);
ok(ret == 0, "ret = %x\n", ret);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
ok(memcmp(dest, data, 10), "All data copied\n");
ok(!memcmp(dest, data, 5), "First five bytes are different\n");
errno = 0xdeadbeef;
ret = pmemcpy_s(data, 10, data, 10);
ok(ret == 0, "ret = %x\n", ret);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
ok(!memcmp(dest, data, 5), "data was destroyed during overwriting\n");
errno = 0xdeadbeef;
dest[0] = 'x';
ret = pmemcpy_s(dest, 5, data, 10);
ok(ret == ERANGE, "ret = %x\n", ret);
ok(errno == ERANGE, "errno = %x\n", errno);
ok(dest[0] == '\0', "dest[0] != \'\\0\'\n");
}
typedef struct _I10_OUTPUT_data {
short pos;
char sign;
@ -367,7 +314,6 @@ START_TEST(misc)
init();
test_rand_s();
test_memcpy_s();
test_I10_OUTPUT();
test_strerror_s();
test__get_doserrno();

View file

@ -323,6 +323,22 @@ static void test_sprintf( void )
ok(!strcmp(buffer,"1 "),"Character zero-padded and/or not left-adjusted \"%s\"\n",buffer);
ok( r==4, "return count wrong\n");
format = "%#012x";
r = sprintf(buffer,format,1);
ok(!strcmp(buffer,"0x0000000001"),"Hexadecimal zero-padded \"%s\"\n",buffer);
format = "%#04.8x";
r = sprintf(buffer,format,1);
ok(!strcmp(buffer,"0x00000001"), "Hexadecimal zero-padded precision \"%s\"\n",buffer);
format = "%#-08.2x";
r = sprintf(buffer,format,1);
ok(!strcmp(buffer,"0x01 "), "Hexadecimal zero-padded not left-adjusted \"%s\"\n",buffer);
format = "%#08o";
r = sprintf(buffer,format,1);
ok(!strcmp(buffer,"00000001"), "Octal zero-padded \"%s\"\n",buffer);
if (sizeof(void *) == 8)
{
format = "%p";
@ -591,6 +607,16 @@ static void test_sprintf( void )
r = sprintf(buffer, format);
ok(!strcmp(buffer,"%0"), "failed: \"%s\"\n", buffer);
ok( r==2, "return count wrong\n");
format = "%hx";
r = sprintf(buffer, format, 0x12345);
ok(!strcmp(buffer,"2345"), "failed \"%s\"\n", buffer);
format = "%hhx";
r = sprintf(buffer, format, 0x123);
ok(!strcmp(buffer,"123"), "failed: \"%s\"\n", buffer);
r = sprintf(buffer, format, 0x12345);
ok(!strcmp(buffer,"2345"), "failed \"%s\"\n", buffer);
}
static void test_swprintf( void )

View file

@ -27,6 +27,7 @@ static void test_sscanf( void )
char buffer[100], buffer1[100];
char format[20];
int result, ret;
LONGLONG result64;
char c;
void *ptr;
float res1= -82.6267f, res2= 27.76f, res11, res12;
@ -125,6 +126,25 @@ static void test_sscanf( void )
ok(ret == 0 , "problem with format arg \"%%*c%%n\"\n");
ok(number_so_far == 1,"Read wrong arg for \"%%n\" %d instead of 2\n",number_so_far);
result = 0xdeadbeef;
strcpy(buffer,"12345678");
ret = sscanf(buffer, "%hd", &result);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ok(result == 0xdead614e, "Wrong number read (%x)\n", result);
result = 0xdeadbeef;
ret = sscanf(buffer, "%hhd", &result);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ok(result == 0xbc614e, "Wrong number read (%x)\n", result);
strcpy(buffer,"12345678901234");
ret = sscanf(buffer, "%lld", &result64);
ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
ret = sprintf(buffer1, "%lld", result64);
ok(ret==14 || broken(ret==10), "sprintf retuned %d\n", ret);
if(ret == 14)
ok(!strcmp(buffer, buffer1), "got %s, expected %s\n", buffer1, buffer);
/* Check %i according to bug 1878 */
strcpy(buffer,"123");
ret = sscanf(buffer, "%i", &result);
@ -243,8 +263,25 @@ static void test_sscanf_s(void)
ok(i==123, "i = %d\n", i);
}
static void test_swscanf( void )
{
wchar_t buffer[100];
int result, ret;
static const WCHAR formatd[] = {'%','d',0};
/* 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);
/* 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 );
}
START_TEST(scanf)
{
test_sscanf();
test_sscanf_s();
test_swscanf();
}

View file

@ -58,6 +58,8 @@ static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
#define expect_bin(buf, value, len) { ok(memcmp((buf), value, len) == 0, "Binary buffer mismatch - expected %s, got %s\n", buf_to_string((unsigned char *)value, len, 1), buf_to_string((buf), len, 0)); }
static void* (__cdecl *pmemcpy)(void *, const void *, size_t n);
static int (__cdecl *p_memcpy_s)(void *, size_t, const void *, size_t);
static int (__cdecl *p_memmove_s)(void *, size_t, const void *, size_t);
static int* (__cdecl *pmemcmp)(void *, const void *, size_t n);
static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src);
static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src);
@ -500,6 +502,148 @@ static void test_strcpy_s(void)
ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret);
}
#define NUMELMS(array) (sizeof(array)/sizeof((array)[0]))
#define okchars(dst, b0, b1, b2, b3, b4, b5, b6, b7) \
ok(dst[0] == b0 && dst[1] == b1 && dst[2] == b2 && dst[3] == b3 && \
dst[4] == b4 && dst[5] == b5 && dst[6] == b6 && dst[7] == b7, \
"Bad result: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",\
dst[0], dst[1], dst[2], dst[3], dst[4], dst[5], dst[6], dst[7])
static void test_memcpy_s(void)
{
static char dest[8];
static const char tiny[] = {'T',0,'I','N','Y',0};
static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
int ret;
if (!p_memcpy_s) {
skip("memcpy_s not found\n");
return;
}
if (p_set_invalid_parameter_handler)
ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
"Invalid parameter handler was already set\n");
/* Normal */
memset(dest, 'X', sizeof(dest));
ret = p_memcpy_s(dest, NUMELMS(dest), tiny, NUMELMS(tiny));
ok(ret == 0, "Copying a buffer into a big enough destination returned %d, expected 0\n", ret);
okchars(dest, tiny[0], tiny[1], tiny[2], tiny[3], tiny[4], tiny[5], 'X', 'X');
/* Vary source size */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memcpy_s(dest, NUMELMS(dest), big, NUMELMS(big));
ok(ret == ERANGE, "Copying a big buffer to a small destination returned %d, expected ERANGE\n", ret);
ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
okchars(dest, 0, 0, 0, 0, 0, 0, 0, 0);
/* Replace source with NULL */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memcpy_s(dest, NUMELMS(dest), NULL, NUMELMS(tiny));
ok(ret == EINVAL, "Copying a NULL source buffer returned %d, expected EINVAL\n", ret);
ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
okchars(dest, 0, 0, 0, 0, 0, 0, 0, 0);
/* Vary dest size */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memcpy_s(dest, 0, tiny, NUMELMS(tiny));
ok(ret == ERANGE, "Copying into a destination of size 0 returned %d, expected ERANGE\n", ret);
ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
/* Replace dest with NULL */
errno = 0xdeadbeef;
ret = p_memcpy_s(NULL, NUMELMS(dest), tiny, NUMELMS(tiny));
ok(ret == EINVAL, "Copying a tiny buffer to a big NULL destination returned %d, expected EINVAL\n", ret);
ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
/* Combinations */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memcpy_s(dest, 0, NULL, NUMELMS(tiny));
ok(ret == EINVAL, "Copying a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
if (p_set_invalid_parameter_handler)
ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
"Cannot reset invalid parameter handler\n");
}
static void test_memmove_s(void)
{
static char dest[8];
static const char tiny[] = {'T',0,'I','N','Y',0};
static const char big[] = {'a','t','o','o','l','o','n','g','s','t','r','i','n','g',0};
int ret;
if (!p_memmove_s) {
skip("memmove_s not found\n");
return;
}
if (p_set_invalid_parameter_handler)
ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
"Invalid parameter handler was already set\n");
/* Normal */
memset(dest, 'X', sizeof(dest));
ret = p_memmove_s(dest, NUMELMS(dest), tiny, NUMELMS(tiny));
ok(ret == 0, "Moving a buffer into a big enough destination returned %d, expected 0\n", ret);
okchars(dest, tiny[0], tiny[1], tiny[2], tiny[3], tiny[4], tiny[5], 'X', 'X');
/* Overlapping */
memcpy(dest, big, sizeof(dest));
ret = p_memmove_s(dest+1, NUMELMS(dest)-1, dest, NUMELMS(dest)-1);
ok(ret == 0, "Moving a buffer up one char returned %d, expected 0\n", ret);
okchars(dest, big[0], big[0], big[1], big[2], big[3], big[4], big[5], big[6]);
/* Vary source size */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memmove_s(dest, NUMELMS(dest), big, NUMELMS(big));
ok(ret == ERANGE, "Moving a big buffer to a small destination returned %d, expected ERANGE\n", ret);
ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
/* Replace source with NULL */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memmove_s(dest, NUMELMS(dest), NULL, NUMELMS(tiny));
ok(ret == EINVAL, "Moving a NULL source buffer returned %d, expected EINVAL\n", ret);
ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
/* Vary dest size */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memmove_s(dest, 0, tiny, NUMELMS(tiny));
ok(ret == ERANGE, "Moving into a destination of size 0 returned %d, expected ERANGE\n", ret);
ok(errno == ERANGE, "errno is %d, expected ERANGE\n", errno);
okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
/* Replace dest with NULL */
errno = 0xdeadbeef;
ret = p_memmove_s(NULL, NUMELMS(dest), tiny, NUMELMS(tiny));
ok(ret == EINVAL, "Moving a tiny buffer to a big NULL destination returned %d, expected EINVAL\n", ret);
ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
/* Combinations */
errno = 0xdeadbeef;
memset(dest, 'X', sizeof(dest));
ret = p_memmove_s(dest, 0, NULL, NUMELMS(tiny));
ok(ret == EINVAL, "Moving a NULL buffer into a destination of size 0 returned %d, expected EINVAL\n", ret);
ok(errno == EINVAL, "errno is %d, expected EINVAL\n", errno);
okchars(dest, 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
if (p_set_invalid_parameter_handler)
ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
"Cannot reset invalid parameter handler\n");
}
static void test_strcat_s(void)
{
char dest[8];
@ -685,6 +829,22 @@ static void test_wcscpy_s(void)
ret = p_wcsncpy_s(szDestShort, 8, szLongText, sizeof(szLongText)/sizeof(WCHAR));
ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
szDest[0] = 'A';
ret = p_wcsncpy_s(szDest, 5, szLongText, -1);
ok(ret == STRUNCATE, "expected STRUNCATE got %d\n", ret);
ok(szDest[4] == 0, "szDest[4] not 0\n");
ok(!memcmp(szDest, szLongText, 4*sizeof(WCHAR)), "szDest = %s\n", wine_dbgstr_w(szDest));
ret = p_wcsncpy_s(NULL, 0, (void*)0xdeadbeef, 0);
ok(ret == 0, "ret = %d\n", ret);
szDestShort[0] = '1';
szDestShort[1] = 0;
ret = p_wcsncpy_s(szDestShort+1, 4, szDestShort, -1);
ok(ret == STRUNCATE, "expected ERROR_SUCCESS got %d\n", ret);
ok(szDestShort[0]=='1' && szDestShort[1]=='1' && szDestShort[2]=='1' && szDestShort[3]=='1',
"szDestShort = %s\n", wine_dbgstr_w(szDestShort));
}
static void test__wcsupr_s(void)
@ -866,21 +1026,79 @@ static void test_mbcjisjms(void)
/* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
unsigned int jisjms[][2] = { {0x2020, 0}, {0x2021, 0}, {0x2120, 0}, {0x2121, 0x8140},
{0x7f7f, 0}, {0x7f7e, 0}, {0x7e7f, 0}, {0x7e7e, 0xeffc},
{0x255f, 0x837e}, {0x2560, 0x8380}, {0x2561, 0x8381},
{0x2121FFFF, 0}, {0x2223, 0x81a1}, {0x237e, 0x829e}, {0, 0}};
unsigned int ret, exp, i;
int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
unsigned int i, j;
int prev_cp = _getmbcp();
i = 0;
do
for (i = 0; i < sizeof(cp)/sizeof(cp[0]); i++)
{
ret = _mbcjistojms(jisjms[i][0]);
_setmbcp(cp[i]);
for (j = 0; jisjms[j][0] != 0; j++)
{
unsigned int ret, exp;
ret = _mbcjistojms(jisjms[j][0]);
exp = (cp[i] == 932) ? jisjms[j][1] : jisjms[j][0];
ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage=%d)\n",
exp, ret, jisjms[j][0], cp[i]);
}
}
_setmbcp(prev_cp);
}
if(_getmbcp() == 932) /* Japanese codepage? */
exp = jisjms[i][1];
else
exp = jisjms[i][0]; /* If not, no conversion */
static void test_mbcjmsjis(void)
{
/* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
unsigned int jmsjis[][2] = { {0x80fc, 0}, {0x813f, 0}, {0x8140, 0x2121},
{0x817e, 0x215f}, {0x817f, 0}, {0x8180, 0x2160},
{0x819e, 0x217e}, {0x819f, 0x2221}, {0x81fc, 0x227e},
{0x81fd, 0}, {0x9ffc, 0x5e7e}, {0x9ffd, 0},
{0xa040, 0}, {0xdffc, 0}, {0xe040, 0x5f21},
{0xeffc, 0x7e7e}, {0xf040, 0}, {0x21, 0}, {0, 0}};
int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
unsigned int i, j;
int prev_cp = _getmbcp();
ok(ret == exp, "Expected 0x%x, got 0x%x\n", exp, ret);
} while(jisjms[i++][0] != 0);
for (i = 0; i < sizeof(cp)/sizeof(cp[0]); i++)
{
_setmbcp(cp[i]);
for (j = 0; jmsjis[j][0] != 0; j++)
{
unsigned int ret, exp;
ret = _mbcjmstojis(jmsjis[j][0]);
exp = (cp[i] == 932) ? jmsjis[j][1] : jmsjis[j][0];
ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage=%d)\n",
exp, ret, jmsjis[j][0], cp[i]);
}
}
_setmbcp(prev_cp);
}
static void test_mbbtombc(void)
{
static const unsigned int mbbmbc[][2] = {
{0x1f, 0x1f}, {0x20, 0x8140}, {0x39, 0x8258}, {0x40, 0x8197},
{0x41, 0x8260}, {0x5e, 0x814f}, {0x7e, 0x8150}, {0x7f, 0x7f},
{0x80, 0x80}, {0x81, 0x81}, {0xa0, 0xa0}, {0xa7, 0x8340},
{0xb0, 0x815b}, {0xd1, 0x8380}, {0xff, 0xff}, {0,0}};
int cp[] = { 932, 936, 939, 950, 1361, _MB_CP_SBCS };
int i, j;
int prev_cp = _getmbcp();
for (i = 0; i < sizeof(cp)/sizeof(cp[0]); i++)
{
_setmbcp(cp[i]);
for (j = 0; mbbmbc[j][0] != 0; j++)
{
unsigned int exp, ret;
ret = _mbbtombc(mbbmbc[j][0]);
exp = (cp[i] == 932) ? mbbmbc[j][1] : mbbmbc[j][0];
ok(ret == exp, "Expected 0x%x, got 0x%x (0x%x, codepage %d)\n",
exp, ret, mbbmbc[j][0], cp[i]);
}
}
_setmbcp(prev_cp);
}
static void test_mbctombb(void)
@ -1586,7 +1804,7 @@ static void test__strlwr_s(void)
ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
"Expected the output buffer to be \"gorrIsTeR\"\n");
"Expected the output buffer to be \"\\0oRrIsTeR\"\n");
strcpy(buffer, "GoRrIsTeR");
errno = EBADF;
@ -1594,7 +1812,7 @@ static void test__strlwr_s(void)
ok(ret == EINVAL, "Expected _strlwr_s to return EINVAL, got %d\n", ret);
ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
ok(!memcmp(buffer, "\0oRrIsTeR", sizeof("\0oRrIsTeR")),
"Expected the output buffer to be \"gorrIsTeR\"\n");
"Expected the output buffer to be \"\\0oRrIsTeR\"\n");
strcpy(buffer, "GoRrIsTeR");
ret = p_strlwr_s(buffer, sizeof("GoRrIsTeR"));
@ -2005,6 +2223,9 @@ static void test_wctob(void)
ret = p_wctob(0x81);
ok(ret == (int)(char)0x81, "ret = %x\n", ret);
ret = p_wctob(0x9f);
ok(ret == (int)(char)0x9f, "ret = %x\n", ret);
ret = p_wctob(0xe0);
ok(ret == (int)(char)0xe0, "ret = %x\n", ret);
}
@ -2055,6 +2276,8 @@ START_TEST(string)
hMsvcrt = GetModuleHandleA("msvcrtd.dll");
ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
SET(pmemcpy,"memcpy");
p_memcpy_s = (void*)GetProcAddress( hMsvcrt, "memcpy_s" );
p_memmove_s = (void*)GetProcAddress( hMsvcrt, "memmove_s" );
SET(pmemcmp,"memcmp");
SET(p_mbctype,"_mbctype");
SET(p__mb_cur_max,"__mb_cur_max");
@ -2102,9 +2325,13 @@ START_TEST(string)
/* test _strdup */
test_strdup();
test_strcpy_s();
test_memcpy_s();
test_memmove_s();
test_strcat_s();
test__mbsnbcpy_s();
test_mbcjisjms();
test_mbcjmsjis();
test_mbbtombc();
test_mbctombb();
test_ismbclegal();
test_strtok();

View file

@ -25,6 +25,7 @@
#include <stdlib.h> /*setenv*/
#include <stdio.h> /*printf*/
#include <locale.h>
#include <errno.h>
#define _MAX__TIME64_T (((__time64_t)0x00000007 << 32) | 0x93406FFF)
@ -37,6 +38,7 @@
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 errno_t (__cdecl *p_strtime_s)(char*,size_t);
static errno_t (__cdecl *p_strdate_s)(char*,size_t);
@ -44,12 +46,16 @@ static errno_t (__cdecl *p_localtime32_s)(struct tm*, __time32_t*);
static errno_t (__cdecl *p_localtime64_s)(struct tm*, __time64_t*);
static int* (__cdecl *p__daylight)(void);
static int* (__cdecl *p___p__daylight)(void);
static size_t (__cdecl *p_strftime)(char *, size_t, const char *, const struct tm *);
static size_t (__cdecl *p_wcsftime)(wchar_t *, size_t, const wchar_t *, const struct tm *);
static char* (__cdecl *p_asctime)(const struct tm *);
static void init(void)
{
HMODULE hmod = GetModuleHandleA("msvcrt.dll");
HMODULE hmod = LoadLibrary("msvcrt.dll");
p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
p_gmtime = (void*)GetProcAddress(hmod, "gmtime");
p_gmtime32_s = (void*)GetProcAddress(hmod, "_gmtime32_s");
p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
@ -58,6 +64,9 @@ static void init(void)
p_localtime64_s = (void*)GetProcAddress(hmod, "_localtime64_s");
p__daylight = (void*)GetProcAddress(hmod, "__daylight");
p___p__daylight = (void*)GetProcAddress(hmod, "__p__daylight");
p_strftime = (void*)GetProcAddress(hmod, "strftime");
p_wcsftime = (void*)GetProcAddress(hmod, "wcsftime");
p_asctime = (void*)GetProcAddress(hmod, "asctime");
}
static int get_test_year(time_t *start)
@ -568,10 +577,238 @@ static void test_daylight(void)
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";
time_t gmt;
struct tm* gmt_tm;
char buf[256], bufA[256];
WCHAR bufW[256];
long retA, retW;
if (!p_strftime || !p_wcsftime || !p_gmtime)
{
win_skip("strftime, wcsftime or gmtime is not available\n");
return;
}
setlocale(LC_TIME, "C");
gmt = 0;
gmt_tm = p_gmtime(&gmt);
ok(gmt_tm != NULL, "gmtime failed\n");
errno = 0xdeadbeef;
retA = strftime(NULL, 0, "copy", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
retA = strftime(bufA, 256, "copy", NULL);
ok(retA == 4, "expected 4, got %ld\n", retA);
ok(!strcmp(bufA, "copy"), "got %s\n", bufA);
retA = strftime(bufA, 256, "copy it", gmt_tm);
ok(retA == 7, "expected 7, got %ld\n", retA);
ok(!strcmp(bufA, "copy it"), "got %s\n", bufA);
errno = 0xdeadbeef;
retA = strftime(bufA, 2, "copy", gmt_tm);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(!strcmp(bufA, "") || broken(!strcmp(bufA, "copy it")), "got %s\n", bufA);
ok(errno==ERANGE || errno==0xdeadbeef, "errno = %d\n", errno);
errno = 0xdeadbeef;
retA = strftime(bufA, 256, "a%e", gmt_tm);
ok(retA==0 || broken(retA==1), "expected 0, got %ld\n", retA);
ok(!strcmp(bufA, "") || broken(!strcmp(bufA, "a")), "got %s\n", bufA);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
if(0) { /* crashes on Win2k */
errno = 0xdeadbeef;
retA = strftime(bufA, 256, "%c", NULL);
ok(retA == 0, "expected 0, got %ld\n", retA);
ok(!strcmp(bufA, ""), "got %s\n", bufA);
ok(errno == EINVAL, "errno = %d\n", errno);
}
retA = 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);
retA = 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 = wcsftime(bufW, 256, cW, gmt_tm);
ok(retW == 17, "expected 17, got %ld\n", retW);
ok(retA == retW, "expected %ld, got %ld\n", retA, retW);
buf[0] = 0;
retA = WideCharToMultiByte(CP_ACP, 0, bufW, retW, buf, 256, NULL, NULL);
buf[retA] = 0;
ok(strcmp(bufA, buf) == 0, "expected %s, got %s\n", bufA, buf);
retA = 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 = 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 = strftime(bufA, 256, "%a", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "Thu"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%A", gmt_tm);
ok(retA == 8, "expected 8, got %ld\n", retA);
ok(!strcmp(bufA, "Thursday"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%b", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "Jan"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%B", gmt_tm);
ok(retA == 7, "expected 7, got %ld\n", retA);
ok(!strcmp(bufA, "January"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%d", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "01"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%#d", gmt_tm);
ok(retA == 1, "expected 1, got %ld\n", retA);
ok(!strcmp(bufA, "1"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%H", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "00"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%I", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "12"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%j", gmt_tm);
ok(retA == 3, "expected 3, got %ld\n", retA);
ok(!strcmp(bufA, "001"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%m", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "01"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%#M", gmt_tm);
ok(retA == 1, "expected 1, got %ld\n", retA);
ok(!strcmp(bufA, "0"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%p", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "AM"), "got %s\n", bufA);
retA = strftime(bufA, 256, "%U", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "00"), "got %s\n", bufA);
retA = 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 = strftime(bufA, 256, "%U", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "01"), "got %s\n", bufA);
retA = 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 = strftime(bufA, 256, "%U", gmt_tm);
ok(retA == 2, "expected 2, got %ld\n", retA);
ok(!strcmp(bufA, "53"), "got %s\n", bufA);
retA = 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 = 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);
}
}
static void test_asctime(void)
{
struct tm* gmt_tm;
time_t gmt;
char *ret;
if(!p_asctime || !p_gmtime)
{
win_skip("asctime or gmtime is not available\n");
return;
}
gmt = 0;
gmt_tm = p_gmtime(&gmt);
ret = p_asctime(gmt_tm);
ok(!strcmp(ret, "Thu Jan 01 00:00:00 1970\n"), "asctime retunred %s\n", ret);
gmt = 312433121;
gmt_tm = p_gmtime(&gmt);
ret = p_asctime(gmt_tm);
ok(!strcmp(ret, "Mon Nov 26 02:58:41 1979\n"), "asctime retunred %s\n", ret);
/* Week day is only checked if it's in 0..6 range */
gmt_tm->tm_wday = 3;
ret = p_asctime(gmt_tm);
ok(!strcmp(ret, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret);
errno = 0xdeadbeef;
gmt_tm->tm_wday = 7;
ret = p_asctime(gmt_tm);
ok(!ret || broken(!ret[0]), "asctime returned %s\n", ret);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
/* Year day is ignored */
gmt_tm->tm_wday = 3;
gmt_tm->tm_yday = 1300;
ret = p_asctime(gmt_tm);
ok(!strcmp(ret, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret);
/* Dates that can't be displayed using 26 characters are broken */
gmt_tm->tm_mday = 28;
gmt_tm->tm_year = 8100;
ret = p_asctime(gmt_tm);
ok(!strcmp(ret, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret);
gmt_tm->tm_year = 264100;
ret = p_asctime(gmt_tm);
ok(!strcmp(ret, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret);
/* asctime works from year 1900 */
errno = 0xdeadbeef;
gmt_tm->tm_year = -1;
ret = p_asctime(gmt_tm);
ok(!ret || broken(!strcmp(ret, "Wed Nov 28 02:58:41 190/\n")), "asctime returned %s\n", ret);
ok(errno==EINVAL || broken(errno == 0xdeadbeef), "errno = %d\n", errno);
errno = 0xdeadbeef;
gmt_tm->tm_mon = 1;
gmt_tm->tm_mday = 30;
gmt_tm->tm_year = 79;
ret = p_asctime(gmt_tm);
ok(!ret || broken(!strcmp(ret, "Wed Feb 30 02:58:41 1979\n")), "asctime returned %s\n", ret);
ok(errno==EINVAL || broken(errno==0xdeadbeef), "errno = %d\n", errno);
}
START_TEST(time)
{
init();
test_strftime();
test_ctime();
test_gmtime();
test_mktime();
@ -583,4 +820,5 @@ START_TEST(time)
test_localtime32_s();
test_localtime64_s();
test_daylight();
test_asctime();
}