mirror of
https://github.com/reactos/reactos.git
synced 2025-05-06 10:28:45 +00:00
[MSVCRT_WINETEST]: Sync to Wine 1.5.13.
CORE-6415 svn path=/trunk/; revision=57432
This commit is contained in:
parent
7c9b5e3f6c
commit
c1abf5e96b
8 changed files with 1140 additions and 259 deletions
|
@ -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__ */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue