diff --git a/dll/win32/mshtml/ifacewrap.c b/dll/win32/mshtml/ifacewrap.c index cc22246a72b..e78464d88b0 100644 --- a/dll/win32/mshtml/ifacewrap.c +++ b/dll/win32/mshtml/ifacewrap.c @@ -17,6 +17,7 @@ */ #include "mshtml_private.h" +#include /* * This object wraps any unrecognized interface overriding its IUnknown methods, allowing diff --git a/dll/win32/msi/custom.c b/dll/win32/msi/custom.c index 310a1441738..8680b7214b3 100644 --- a/dll/win32/msi/custom.c +++ b/dll/win32/msi/custom.c @@ -20,6 +20,7 @@ #include "config.h" #include "wine/port.h" +#include "wine/asm.h" #define COBJMACROS diff --git a/dll/win32/msvcrt/msvcrt.spec b/dll/win32/msvcrt/msvcrt.spec index 576b9800eb0..4e0c07aa950 100644 --- a/dll/win32/msvcrt/msvcrt.spec +++ b/dll/win32/msvcrt/msvcrt.spec @@ -1,64 +1,64 @@ # msvcrt.dll - MS VC++ Run Time Library # **************** x86 C++ functions **************** -@ cdecl -i386 -norelay ??0__non_rtti_object@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT___non_rtti_object_copy_ctor # public: __thiscall __non_rtti_object::__non_rtti_object(class __non_rtti_object const &) -@ cdecl -i386 -norelay ??0__non_rtti_object@@QAE@PBD@Z(ptr) __thiscall_MSVCRT___non_rtti_object_ctor # public: __thiscall __non_rtti_object::__non_rtti_object(char const *) -@ cdecl -i386 -norelay ??0bad_cast@@AAE@PBQBD@Z(ptr) __thiscall_MSVCRT_bad_cast_ctor # private: __thiscall bad_cast::bad_cast(char const * const *) -@ cdecl -i386 -norelay ??0bad_cast@@QAE@ABQBD@Z(ptr) __thiscall_MSVCRT_bad_cast_ctor # public: __thiscall bad_cast::bad_cast(char const * const &) -@ cdecl -i386 -norelay ??0bad_cast@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_cast_copy_ctor # public: __thiscall bad_cast::bad_cast(class bad_cast const &) -@ cdecl -i386 -norelay ??0bad_cast@@QAE@PBD@Z(ptr) __thiscall_MSVCRT_bad_cast_ctor_charptr # public: __thiscall bad_cast::bad_cast(char const *) -@ cdecl -i386 -norelay ??0bad_typeid@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_typeid_copy_ctor # public: __thiscall bad_typeid::bad_typeid(class bad_typeid const &) -@ cdecl -i386 -norelay ??0bad_typeid@@QAE@PBD@Z(ptr) __thiscall_MSVCRT_bad_typeid_ctor # public: __thiscall bad_typeid::bad_typeid(char const *) -@ cdecl -i386 -norelay ??0exception@@QAE@ABQBD@Z(ptr) __thiscall_MSVCRT_exception_ctor # public: __thiscall exception::exception(char const * const &) -@ cdecl -i386 -norelay ??0exception@@QAE@ABQBDH@Z(ptr long) __thiscall_MSVCRT_exception_ctor_noalloc # public: __thiscall exception::exception(char const * const &,int) -@ cdecl -i386 -norelay ??0exception@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_exception_copy_ctor # public: __thiscall exception::exception(class exception const &) -@ cdecl -i386 -norelay ??0exception@@QAE@XZ() __thiscall_MSVCRT_exception_default_ctor # public: __thiscall exception::exception(void) -@ cdecl -i386 -norelay ??1__non_rtti_object@@UAE@XZ() __thiscall_MSVCRT___non_rtti_object_dtor # public: virtual __thiscall __non_rtti_object::~__non_rtti_object(void) -@ cdecl -i386 -norelay ??1bad_cast@@UAE@XZ() __thiscall_MSVCRT_bad_cast_dtor # public: virtual __thiscall bad_cast::~bad_cast(void) -@ cdecl -i386 -norelay ??1bad_typeid@@UAE@XZ() __thiscall_MSVCRT_bad_typeid_dtor # public: virtual __thiscall bad_typeid::~bad_typeid(void) -@ cdecl -i386 -norelay ??1exception@@UAE@XZ() __thiscall_MSVCRT_exception_dtor # public: virtual __thiscall exception::~exception(void) -@ cdecl -i386 -norelay ??1type_info@@UAE@XZ() __thiscall_MSVCRT_type_info_dtor # public: virtual __thiscall type_info::~type_info(void) +@ cdecl -i386 -norelay ??0__non_rtti_object@@QAE@ABV0@@Z(ptr) MSVCRT___non_rtti_object_copy_ctor # public: __thiscall __non_rtti_object::__non_rtti_object(class __non_rtti_object const &) +@ cdecl -i386 -norelay ??0__non_rtti_object@@QAE@PBD@Z(ptr) MSVCRT___non_rtti_object_ctor # public: __thiscall __non_rtti_object::__non_rtti_object(char const *) +@ cdecl -i386 -norelay ??0bad_cast@@AAE@PBQBD@Z(ptr) MSVCRT_bad_cast_ctor # private: __thiscall bad_cast::bad_cast(char const * const *) +@ cdecl -i386 -norelay ??0bad_cast@@QAE@ABQBD@Z(ptr) MSVCRT_bad_cast_ctor # public: __thiscall bad_cast::bad_cast(char const * const &) +@ cdecl -i386 -norelay ??0bad_cast@@QAE@ABV0@@Z(ptr) MSVCRT_bad_cast_copy_ctor # public: __thiscall bad_cast::bad_cast(class bad_cast const &) +@ cdecl -i386 -norelay ??0bad_cast@@QAE@PBD@Z(ptr) MSVCRT_bad_cast_ctor_charptr # public: __thiscall bad_cast::bad_cast(char const *) +@ cdecl -i386 -norelay ??0bad_typeid@@QAE@ABV0@@Z(ptr) MSVCRT_bad_typeid_copy_ctor # public: __thiscall bad_typeid::bad_typeid(class bad_typeid const &) +@ cdecl -i386 -norelay ??0bad_typeid@@QAE@PBD@Z(ptr) MSVCRT_bad_typeid_ctor # public: __thiscall bad_typeid::bad_typeid(char const *) +@ cdecl -i386 -norelay ??0exception@@QAE@ABQBD@Z(ptr) MSVCRT_exception_ctor # public: __thiscall exception::exception(char const * const &) +@ cdecl -i386 -norelay ??0exception@@QAE@ABQBDH@Z(ptr long) MSVCRT_exception_ctor_noalloc # public: __thiscall exception::exception(char const * const &,int) +@ cdecl -i386 -norelay ??0exception@@QAE@ABV0@@Z(ptr) MSVCRT_exception_copy_ctor # public: __thiscall exception::exception(class exception const &) +@ cdecl -i386 -norelay ??0exception@@QAE@XZ() MSVCRT_exception_default_ctor # public: __thiscall exception::exception(void) +@ cdecl -i386 -norelay ??1__non_rtti_object@@UAE@XZ() MSVCRT___non_rtti_object_dtor # public: virtual __thiscall __non_rtti_object::~__non_rtti_object(void) +@ cdecl -i386 -norelay ??1bad_cast@@UAE@XZ() MSVCRT_bad_cast_dtor # public: virtual __thiscall bad_cast::~bad_cast(void) +@ cdecl -i386 -norelay ??1bad_typeid@@UAE@XZ() MSVCRT_bad_typeid_dtor # public: virtual __thiscall bad_typeid::~bad_typeid(void) +@ cdecl -i386 -norelay ??1exception@@UAE@XZ() MSVCRT_exception_dtor # public: virtual __thiscall exception::~exception(void) +@ cdecl -i386 -norelay ??1type_info@@UAE@XZ() MSVCRT_type_info_dtor # public: virtual __thiscall type_info::~type_info(void) @ cdecl -i386 ??2@YAPAXI@Z(long) MSVCRT_operator_new # void * __cdecl operator new(unsigned int) ;@ cdecl -i386 ??2@YAPAXIHPBDH@Z(long long str long) MSVCRT_operator_new_dbg # void * __cdecl operator new(unsigned int,int,char const *,int) @ cdecl -i386 ??3@YAXPAX@Z(ptr) MSVCRT_operator_delete # void __cdecl operator delete(void *) -@ cdecl -i386 -norelay ??4__non_rtti_object@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT___non_rtti_object_opequals # public: class __non_rtti_object & __thiscall __non_rtti_object::operator=(class __non_rtti_object const &) -@ cdecl -i386 -norelay ??4bad_cast@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_cast_opequals # public: class bad_cast & __thiscall bad_cast::operator=(class bad_cast const &) -@ cdecl -i386 -norelay ??4bad_typeid@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_typeid_opequals # public: class bad_typeid & __thiscall bad_typeid::operator=(class bad_typeid const &) -@ cdecl -i386 -norelay ??4exception@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_exception_opequals # public: class exception & __thiscall exception::operator=(class exception const &) -@ cdecl -i386 -norelay ??8type_info@@QBEHABV0@@Z(ptr) __thiscall_MSVCRT_type_info_opequals_equals # public: int __thiscall type_info::operator==(class type_info const &)const -@ cdecl -i386 -norelay ??9type_info@@QBEHABV0@@Z(ptr) __thiscall_MSVCRT_type_info_opnot_equals # public: int __thiscall type_info::operator!=(class type_info const &)const +@ cdecl -i386 -norelay ??4__non_rtti_object@@QAEAAV0@ABV0@@Z(ptr) MSVCRT___non_rtti_object_opequals # public: class __non_rtti_object & __thiscall __non_rtti_object::operator=(class __non_rtti_object const &) +@ cdecl -i386 -norelay ??4bad_cast@@QAEAAV0@ABV0@@Z(ptr) MSVCRT_bad_cast_opequals # public: class bad_cast & __thiscall bad_cast::operator=(class bad_cast const &) +@ cdecl -i386 -norelay ??4bad_typeid@@QAEAAV0@ABV0@@Z(ptr) MSVCRT_bad_typeid_opequals # public: class bad_typeid & __thiscall bad_typeid::operator=(class bad_typeid const &) +@ cdecl -i386 -norelay ??4exception@@QAEAAV0@ABV0@@Z(ptr) MSVCRT_exception_opequals # public: class exception & __thiscall exception::operator=(class exception const &) +@ cdecl -i386 -norelay ??8type_info@@QBEHABV0@@Z(ptr) MSVCRT_type_info_opequals_equals # public: int __thiscall type_info::operator==(class type_info const &)const +@ cdecl -i386 -norelay ??9type_info@@QBEHABV0@@Z(ptr) MSVCRT_type_info_opnot_equals # public: int __thiscall type_info::operator!=(class type_info const &)const @ extern -i386 ??_7__non_rtti_object@@6B@ MSVCRT___non_rtti_object_vtable # const __non_rtti_object::`vftable' @ extern -i386 ??_7bad_cast@@6B@ MSVCRT_bad_cast_vtable # const bad_cast::`vftable' @ extern -i386 ??_7bad_typeid@@6B@ MSVCRT_bad_typeid_vtable # const bad_typeid::`vftable' @ extern -i386 ??_7exception@@6B@ MSVCRT_exception_vtable # const exception::`vftable' -@ cdecl -i386 -norelay ??_E__non_rtti_object@@UAEPAXI@Z(long) __thiscall_MSVCRT___non_rtti_object_vector_dtor # public: virtual void * __thiscall __non_rtti_object::`vector deleting destructor'(unsigned int) -@ cdecl -i386 -norelay ??_Ebad_cast@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_cast_vector_dtor # public: virtual void * __thiscall bad_cast::`vector deleting destructor'(unsigned int) -@ cdecl -i386 -norelay ??_Ebad_typeid@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_typeid_vector_dtor # public: virtual void * __thiscall bad_typeid::`vector deleting destructor'(unsigned int) -@ cdecl -i386 -norelay ??_Eexception@@UAEPAXI@Z(long) __thiscall_MSVCRT_exception_vector_dtor # public: virtual void * __thiscall exception::`vector deleting destructor'(unsigned int) -@ cdecl -i386 -norelay ??_Fbad_cast@@QAEXXZ() __thiscall_MSVCRT_bad_cast_default_ctor # public: void __thiscall bad_cast::`default constructor closure'(void) -@ cdecl -i386 -norelay ??_Fbad_typeid@@QAEXXZ() __thiscall_MSVCRT_bad_typeid_default_ctor # public: void __thiscall bad_typeid::`default constructor closure'(void) -@ cdecl -i386 -norelay ??_G__non_rtti_object@@UAEPAXI@Z(long) __thiscall_MSVCRT___non_rtti_object_scalar_dtor # public: virtual void * __thiscall __non_rtti_object::`scalar deleting destructor'(unsigned int) -@ cdecl -i386 -norelay ??_Gbad_cast@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_cast_scalar_dtor # public: virtual void * __thiscall bad_cast::`scalar deleting destructor'(unsigned int) -@ cdecl -i386 -norelay ??_Gbad_typeid@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_typeid_scalar_dtor # public: virtual void * __thiscall bad_typeid::`scalar deleting destructor'(unsigned int) -@ cdecl -i386 -norelay ??_Gexception@@UAEPAXI@Z(long) __thiscall_MSVCRT_exception_scalar_dtor # public: virtual void * __thiscall exception::`scalar deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_E__non_rtti_object@@UAEPAXI@Z(long) MSVCRT___non_rtti_object_vector_dtor # public: virtual void * __thiscall __non_rtti_object::`vector deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_Ebad_cast@@UAEPAXI@Z(long) MSVCRT_bad_cast_vector_dtor # public: virtual void * __thiscall bad_cast::`vector deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_Ebad_typeid@@UAEPAXI@Z(long) MSVCRT_bad_typeid_vector_dtor # public: virtual void * __thiscall bad_typeid::`vector deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_Eexception@@UAEPAXI@Z(long) MSVCRT_exception_vector_dtor # public: virtual void * __thiscall exception::`vector deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_Fbad_cast@@QAEXXZ() MSVCRT_bad_cast_default_ctor # public: void __thiscall bad_cast::`default constructor closure'(void) +@ cdecl -i386 -norelay ??_Fbad_typeid@@QAEXXZ() MSVCRT_bad_typeid_default_ctor # public: void __thiscall bad_typeid::`default constructor closure'(void) +@ cdecl -i386 -norelay ??_G__non_rtti_object@@UAEPAXI@Z(long) MSVCRT___non_rtti_object_scalar_dtor # public: virtual void * __thiscall __non_rtti_object::`scalar deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_Gbad_cast@@UAEPAXI@Z(long) MSVCRT_bad_cast_scalar_dtor # public: virtual void * __thiscall bad_cast::`scalar deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_Gbad_typeid@@UAEPAXI@Z(long) MSVCRT_bad_typeid_scalar_dtor # public: virtual void * __thiscall bad_typeid::`scalar deleting destructor'(unsigned int) +@ cdecl -i386 -norelay ??_Gexception@@UAEPAXI@Z(long) MSVCRT_exception_scalar_dtor # public: virtual void * __thiscall exception::`scalar deleting destructor'(unsigned int) @ cdecl -i386 ??_U@YAPAXI@Z(long) MSVCRT_operator_new # void * __cdecl operator new[](unsigned int) ;@ cdecl -i386 ??_U@YAPAXIHPBDH@Z(long long str long) MSVCRT_operator_new_dbg # void * __cdecl operator new[](unsigned int,int,char const *,int) @ cdecl -i386 ??_V@YAXPAX@Z(ptr) MSVCRT_operator_delete # void __cdecl operator delete[](void *) -@ cdecl -i386 -norelay __uncaught_exception(ptr) +@ cdecl -i386 -norelay __uncaught_exception(ptr) MSVCRT___uncaught_exception @ cdecl -i386 -norelay ?_query_new_handler@@YAP6AHI@ZXZ() MSVCRT__query_new_handler # int (__cdecl*__cdecl _query_new_handler(void))(unsigned int) @ cdecl -i386 ?_query_new_mode@@YAHXZ() MSVCRT__query_new_mode # int __cdecl _query_new_mode(void) @ cdecl -i386 -norelay ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) MSVCRT__set_new_handler # int (__cdecl*__cdecl _set_new_handler(int (__cdecl*)(unsigned int)))(unsigned int) @ cdecl -i386 ?_set_new_mode@@YAHH@Z(long) MSVCRT__set_new_mode # int __cdecl _set_new_mode(int) @ cdecl -i386 -norelay ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) MSVCRT__set_se_translator # void (__cdecl*__cdecl _set_se_translator(void (__cdecl*)(unsigned int,struct _EXCEPTION_POINTERS *)))(unsigned int,struct _EXCEPTION_POINTERS *) -@ cdecl -i386 -norelay ?before@type_info@@QBEHABV1@@Z(ptr) __thiscall_MSVCRT_type_info_before # public: int __thiscall type_info::before(class type_info const &)const -@ cdecl -i386 -norelay ?name@type_info@@QBEPBDXZ() __thiscall_MSVCRT_type_info_name # public: char const * __thiscall type_info::name(void)const -@ cdecl -i386 -norelay ?raw_name@type_info@@QBEPBDXZ() __thiscall_MSVCRT_type_info_raw_name # public: char const * __thiscall type_info::raw_name(void)const +@ cdecl -i386 -norelay ?before@type_info@@QBEHABV1@@Z(ptr) MSVCRT_type_info_before # public: int __thiscall type_info::before(class type_info const &)const +@ cdecl -i386 -norelay ?name@type_info@@QBEPBDXZ() MSVCRT_type_info_name # public: char const * __thiscall type_info::name(void)const +@ cdecl -i386 -norelay ?raw_name@type_info@@QBEPBDXZ() MSVCRT_type_info_raw_name # public: char const * __thiscall type_info::raw_name(void)const @ cdecl -i386 ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_new_handler # void (__cdecl*__cdecl set_new_handler(void (__cdecl*)(void)))(void) @ cdecl -i386 ?set_terminate@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_terminate # void (__cdecl*__cdecl set_terminate(void (__cdecl*)(void)))(void) @ cdecl -i386 ?set_unexpected@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_unexpected # void (__cdecl*__cdecl set_unexpected(void (__cdecl*)(void)))(void) @ cdecl -i386 ?terminate@@YAXXZ() MSVCRT_terminate # void __cdecl terminate(void) @ cdecl -i386 ?unexpected@@YAXXZ() MSVCRT_unexpected # void __cdecl unexpected(void) -@ cdecl -i386 -norelay ?what@exception@@UBEPBDXZ() __thiscall_MSVCRT_what_exception # public: virtual char const * __thiscall exception::what(void)const +@ cdecl -i386 -norelay ?what@exception@@UBEPBDXZ() MSVCRT_what_exception # public: virtual char const * __thiscall exception::what(void)const # **************** win64 C++ functions **************** @ cdecl -arch=win64 ??0__non_rtti_object@@QEAA@AEBV0@@Z(ptr) MSVCRT___non_rtti_object_copy_ctor # public: __cdecl __non_rtti_object::__non_rtti_object(class __non_rtti_object const & __ptr64) __ptr64 @@ -94,7 +94,7 @@ @ cdecl -arch=win64 ??_Fbad_typeid@@QEAAXXZ() MSVCRT_bad_typeid_default_ctor # public: void __cdecl bad_typeid::`default constructor closure'(void) __ptr64 @ cdecl -arch=win64 ??_U@YAPEAX_K@Z(long) MSVCRT_operator_new # void * __ptr64 __cdecl operator new[](unsigned __int64) @ cdecl -arch=win64 ??_V@YAXPEAX@Z(ptr) MSVCRT_operator_delete # void __cdecl operator delete[](void * __ptr64) -@ cdecl -arch=win64 __uncaught_exception(ptr) +@ cdecl -arch=win64 __uncaught_exception(ptr) MSVCRT___uncaught_exception @ cdecl -arch=win64 ?_query_new_handler@@YAP6AH_K@ZXZ() MSVCRT__query_new_handler # int (__cdecl*__cdecl _query_new_handler(void))(unsigned __int64) @ cdecl -arch=win64 ?_query_new_mode@@YAHXZ() MSVCRT__query_new_mode # int __cdecl _query_new_mode(void) @ cdecl -arch=win64 ?_set_new_handler@@YAP6AH_K@ZP6AH0@Z@Z(ptr) MSVCRT__set_new_handler # int (__cdecl*__cdecl _set_new_handler(int (__cdecl*)(unsigned __int64)))(unsigned __int64) @@ -108,7 +108,7 @@ @ cdecl -arch=win64 ?set_unexpected@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_unexpected # void (__cdecl*__cdecl set_unexpected(void (__cdecl*)(void)))(void) @ cdecl -arch=win64 ?terminate@@YAXXZ() MSVCRT_terminate # void __cdecl terminate(void) @ cdecl -arch=win64 ?unexpected@@YAXXZ() MSVCRT_unexpected # void __cdecl unexpected(void) -@ cdecl -arch=win64 -stub ?what@exception@@UEBAPEBDXZ() MSVCRT_what_exception # public: virtual char const * __ptr64 __cdecl exception::what(void)const __ptr64 +@ cdecl -arch=win64 ?what@exception@@UEBAPEBDXZ() MSVCRT_what_exception # public: virtual char const * __ptr64 __cdecl exception::what(void)const __ptr64 # **************** ARM C++ functions **************** @ cdecl -arch=arm ??0__non_rtti_object@@QAA@ABV0@@Z() MSVCRT___non_rtti_object_copy_ctor # public: __cdecl __non_rtti_object::__non_rtti_object(class __non_rtti_object const &) @@ -204,14 +204,14 @@ # stub __CxxCallUnwindDtor # stub __CxxCallUnwindVecDtor @ cdecl __CxxDetectRethrow(ptr) -# stub __CxxExceptionFilter +@ cdecl __CxxExceptionFilter() @ cdecl -arch=i386,x86_64 -norelay __CxxFrameHandler(ptr ptr ptr ptr) @ cdecl -arch=i386 -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler @ cdecl -arch=arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) @ stdcall -i386 __CxxLongjmpUnwind(ptr) @ cdecl -i386 __CxxQueryExceptionSize() -# stub -i386 __CxxRegisterExceptionObject -# stub -i386 __CxxUnregisterExceptionObject +@ cdecl -i386 __CxxRegisterExceptionObject() +@ cdecl -i386 __CxxUnregisterExceptionObject() @ cdecl -version=0x600+ __DestructExceptionObject(ptr) @ cdecl __RTCastToVoid(ptr) MSVCRT___RTCastToVoid @ cdecl __RTDynamicCast(ptr long ptr ptr long) MSVCRT___RTDynamicCast @@ -329,7 +329,7 @@ @ cdecl _callnewh(long) @ cdecl _cexit() @ cdecl _cgets(str) -# stub _cgetws +@ cdecl -stub _cgetws(wstr) @ cdecl _chdir(str) @ cdecl _chdrive(long) @ cdecl _chgsign(double) @@ -347,14 +347,14 @@ @ cdecl -arch=x86_64,arm _copysignf(long long) @ varargs _cprintf(str) @ cdecl _cputs(str) -# stub _cputws +@ cdecl -stub _cputws(wstr) @ cdecl _creat(str long) @ varargs _cscanf(str) @ cdecl _ctime64(ptr) @ extern _ctype @ cdecl _cwait(ptr long long) @ varargs _cwprintf(wstr) -# @ varargs _cwscanf(wstr) +@ varargs -stub _cwscanf(wstr) @ extern _daylight @ extern _dstbias @ cdecl _dup(long) @@ -431,8 +431,8 @@ @ cdecl _getpid() kernel32.GetCurrentProcessId @ cdecl _getsystime(ptr) @ cdecl _getw(ptr) -# stub _getwch -# stub _getwche +@ cdecl -stub _getwch() +@ cdecl -stub _getwche() @ cdecl _getws(ptr) @ cdecl -i386 _global_unwind2(ptr) @ cdecl _gmtime64(ptr) diff --git a/dll/win32/msvcrt40/msvcrt40.spec b/dll/win32/msvcrt40/msvcrt40.spec index fab52fec803..d1efd557b46 100644 --- a/dll/win32/msvcrt40/msvcrt40.spec +++ b/dll/win32/msvcrt40/msvcrt40.spec @@ -1,14 +1,14 @@ @ stub ??0Iostream_init@@QAE@AAVios@@H@Z @ stub ??0Iostream_init@@QAE@XZ -@ cdecl -i386 ??0__non_rtti_object@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT___non_rtti_object_copy_ctor -@ cdecl -i386 ??0__non_rtti_object@@QAE@PBD@Z(ptr) __thiscall_MSVCRT___non_rtti_object_ctor -@ cdecl -i386 ??0bad_cast@@QAE@ABQBD@Z(ptr) __thiscall_MSVCRT_bad_cast_ctor -@ cdecl -i386 ??0bad_cast@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_cast_copy_ctor -@ cdecl -i386 ??0bad_typeid@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_typeid_copy_ctor -@ cdecl -i386 ??0bad_typeid@@QAE@PBD@Z(ptr) __thiscall_MSVCRT_bad_typeid_ctor -@ cdecl -i386 ??0exception@@QAE@ABQBD@Z(ptr) __thiscall_MSVCRT_exception_ctor -@ cdecl -i386 ??0exception@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_exception_copy_ctor -@ cdecl -i386 ??0exception@@QAE@XZ() __thiscall_MSVCRT_exception_default_ctor +@ cdecl -i386 ??0__non_rtti_object@@QAE@ABV0@@Z(ptr) MSVCRT___non_rtti_object_copy_ctor +@ cdecl -i386 ??0__non_rtti_object@@QAE@PBD@Z(ptr) MSVCRT___non_rtti_object_ctor +@ cdecl -i386 ??0bad_cast@@QAE@ABQBD@Z(ptr) MSVCRT_bad_cast_ctor +@ cdecl -i386 ??0bad_cast@@QAE@ABV0@@Z(ptr) MSVCRT_bad_cast_copy_ctor +@ cdecl -i386 ??0bad_typeid@@QAE@ABV0@@Z(ptr) MSVCRT_bad_typeid_copy_ctor +@ cdecl -i386 ??0bad_typeid@@QAE@PBD@Z(ptr) MSVCRT_bad_typeid_ctor +@ cdecl -i386 ??0exception@@QAE@ABQBD@Z(ptr) MSVCRT_exception_ctor +@ cdecl -i386 ??0exception@@QAE@ABV0@@Z(ptr) MSVCRT_exception_copy_ctor +@ cdecl -i386 ??0exception@@QAE@XZ() MSVCRT_exception_default_ctor @ stub ??0filebuf@@QAE@ABV0@@Z @ stub ??0filebuf@@QAE@H@Z @ stub ??0filebuf@@QAE@HPADH@Z @@ -70,10 +70,10 @@ @ stub ??0strstreambuf@@QAE@PADH0@Z @ stub ??0strstreambuf@@QAE@XZ @ stub ??1Iostream_init@@QAE@XZ -@ cdecl -i386 ??1__non_rtti_object@@UAE@XZ() __thiscall_MSVCRT___non_rtti_object_dtor -@ cdecl -i386 ??1bad_cast@@UAE@XZ() __thiscall_MSVCRT_bad_cast_dtor -@ cdecl -i386 ??1bad_typeid@@UAE@XZ() __thiscall_MSVCRT_bad_typeid_dtor -@ cdecl -i386 ??1exception@@UAE@XZ() __thiscall_MSVCRT_exception_dtor +@ cdecl -i386 ??1__non_rtti_object@@UAE@XZ() MSVCRT___non_rtti_object_dtor +@ cdecl -i386 ??1bad_cast@@UAE@XZ() MSVCRT_bad_cast_dtor +@ cdecl -i386 ??1bad_typeid@@UAE@XZ() MSVCRT_bad_typeid_dtor +@ cdecl -i386 ??1exception@@UAE@XZ() MSVCRT_exception_dtor @ stub ??1filebuf@@UAE@XZ @ stub ??1fstream@@UAE@XZ @ stub ??1ifstream@@UAE@XZ @@ -92,16 +92,16 @@ @ stub ??1streambuf@@UAE@XZ @ stub ??1strstream@@UAE@XZ @ stub ??1strstreambuf@@UAE@XZ -@ cdecl -i386 ??1type_info@@UAE@XZ() __thiscall_MSVCRT_type_info_dtor +@ cdecl -i386 ??1type_info@@UAE@XZ() MSVCRT_type_info_dtor @ cdecl -arch=win32 ??2@YAPAXI@Z(long) MSVCRT_operator_new @ cdecl -arch=win64 ??2@YAPEAX_K@Z(double) MSVCRT_operator_new @ cdecl -arch=win32 ??3@YAXPAX@Z(ptr) MSVCRT_operator_delete @ cdecl -arch=win64 ??3@YAXPEAX@Z(ptr) MSVCRT_operator_delete @ stub ??4Iostream_init@@QAEAAV0@ABV0@@Z -@ cdecl -i386 ??4__non_rtti_object@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT___non_rtti_object_opequals -@ cdecl -i386 ??4bad_cast@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_cast_opequals -@ cdecl -i386 ??4bad_typeid@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_typeid_opequals -@ cdecl -i386 ??4exception@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_exception_opequals +@ cdecl -i386 ??4__non_rtti_object@@QAEAAV0@ABV0@@Z(ptr) MSVCRT___non_rtti_object_opequals +@ cdecl -i386 ??4bad_cast@@QAEAAV0@ABV0@@Z(ptr) MSVCRT_bad_cast_opequals +@ cdecl -i386 ??4bad_typeid@@QAEAAV0@ABV0@@Z(ptr) MSVCRT_bad_typeid_opequals +@ cdecl -i386 ??4exception@@QAEAAV0@ABV0@@Z(ptr) MSVCRT_exception_opequals @ stub ??4filebuf@@QAEAAV0@ABV0@@Z @ stub ??4fstream@@QAEAAV0@AAV0@@Z @ stub ??4ifstream@@QAEAAV0@ABV0@@Z @@ -165,8 +165,8 @@ @ stub ??6ostream@@QAEAAV0@PBE@Z @ stub ??6ostream@@QAEAAV0@PBX@Z @ stub ??7ios@@QBEHXZ -@ cdecl -i386 ??8type_info@@QBEHABV0@@Z(ptr) __thiscall_MSVCRT_type_info_opequals_equals -@ cdecl -i386 ??9type_info@@QBEHABV0@@Z(ptr) __thiscall_MSVCRT_type_info_opnot_equals +@ cdecl -i386 ??8type_info@@QBEHABV0@@Z(ptr) MSVCRT_type_info_opequals_equals +@ cdecl -i386 ??9type_info@@QBEHABV0@@Z(ptr) MSVCRT_type_info_opnot_equals @ stub ??Bios@@QBEPAXXZ @ extern -i386 ??_7__non_rtti_object@@6B@ MSVCRT___non_rtti_object_vtable @ extern -i386 ??_7bad_cast@@6B@ MSVCRT_bad_cast_vtable @@ -219,10 +219,10 @@ @ stub ??_Dstdiostream@@QAEXXZ @ stub ??_Dstrstream@@QAEXXZ @ stub ??_EIostream_init@@QAEPAXI@Z -@ cdecl -i386 ??_E__non_rtti_object@@UAEPAXI@Z(long) __thiscall_MSVCRT___non_rtti_object_vector_dtor -@ cdecl -i386 ??_Ebad_cast@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_cast_vector_dtor -@ cdecl -i386 ??_Ebad_typeid@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_typeid_vector_dtor -@ cdecl -i386 ??_Eexception@@UAEPAXI@Z(long) __thiscall_MSVCRT_exception_vector_dtor +@ cdecl -i386 ??_E__non_rtti_object@@UAEPAXI@Z(long) MSVCRT___non_rtti_object_vector_dtor +@ cdecl -i386 ??_Ebad_cast@@UAEPAXI@Z(long) MSVCRT_bad_cast_vector_dtor +@ cdecl -i386 ??_Ebad_typeid@@UAEPAXI@Z(long) MSVCRT_bad_typeid_vector_dtor +@ cdecl -i386 ??_Eexception@@UAEPAXI@Z(long) MSVCRT_exception_vector_dtor @ stub ??_Efilebuf@@UAEPAXI@Z @ stub ??_Efstream@@UAEPAXI@Z @ stub ??_Eifstream@@UAEPAXI@Z @@ -242,10 +242,10 @@ @ stub ??_Estrstream@@UAEPAXI@Z @ stub ??_Estrstreambuf@@UAEPAXI@Z @ stub ??_GIostream_init@@QAEPAXI@Z -@ cdecl -i386 ??_G__non_rtti_object@@UAEPAXI@Z(long) __thiscall_MSVCRT___non_rtti_object_scalar_dtor -@ cdecl -i386 ??_Gbad_cast@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_cast_scalar_dtor -@ cdecl -i386 ??_Gbad_typeid@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_typeid_scalar_dtor -@ cdecl -i386 ??_Gexception@@UAEPAXI@Z(long) __thiscall_MSVCRT_exception_scalar_dtor +@ cdecl -i386 ??_G__non_rtti_object@@UAEPAXI@Z(long) MSVCRT___non_rtti_object_scalar_dtor +@ cdecl -i386 ??_Gbad_cast@@UAEPAXI@Z(long) MSVCRT_bad_cast_scalar_dtor +@ cdecl -i386 ??_Gbad_typeid@@UAEPAXI@Z(long) MSVCRT_bad_typeid_scalar_dtor +@ cdecl -i386 ??_Gexception@@UAEPAXI@Z(long) MSVCRT_exception_scalar_dtor @ stub ??_Gfilebuf@@UAEPAXI@Z @ stub ??_Gfstream@@UAEPAXI@Z @ stub ??_Gifstream@@UAEPAXI@Z @@ -278,7 +278,7 @@ @ stub ?bad@ios@@QBEHXZ @ stub ?base@streambuf@@IBEPADXZ @ stub ?basefield@ios@@2JB -@ cdecl -i386 ?before@type_info@@QBEHABV1@@Z(ptr) __thiscall_MSVCRT_type_info_before +@ cdecl -i386 ?before@type_info@@QBEHABV1@@Z(ptr) MSVCRT_type_info_before @ stub ?binary@filebuf@@2HB @ stub ?bitalloc@ios@@SAJXZ @ stub ?blen@streambuf@@IBEHXZ @@ -356,7 +356,7 @@ @ stub ?lockc@ios@@KAXXZ @ stub ?lockptr@ios@@IAEPAU_CRT_CRITICAL_SECTION@@XZ @ stub ?lockptr@streambuf@@IAEPAU_CRT_CRITICAL_SECTION@@XZ -@ cdecl -i386 ?name@type_info@@QBEPBDXZ() __thiscall_MSVCRT_type_info_name +@ cdecl -i386 ?name@type_info@@QBEPBDXZ() MSVCRT_type_info_name @ stub ?oct@@YAAAVios@@AAV1@@Z @ stub ?open@filebuf@@QAEPAV1@PBDHH@Z @ stub ?open@fstream@@QAEXPBDHH@Z @@ -384,7 +384,7 @@ @ stub ?put@ostream@@QAEAAV1@E@Z @ stub ?putback@istream@@QAEAAV1@D@Z @ stub ?pword@ios@@QBEAAPAXH@Z -@ cdecl -i386 ?raw_name@type_info@@QBEPBDXZ() __thiscall_MSVCRT_type_info_raw_name +@ cdecl -i386 ?raw_name@type_info@@QBEPBDXZ() MSVCRT_type_info_raw_name @ stub ?rdbuf@fstream@@QBEPAVfilebuf@@XZ @ stub ?rdbuf@ifstream@@QBEPAVfilebuf@@XZ @ stub ?rdbuf@ios@@QBEPAVstreambuf@@XZ @@ -467,7 +467,7 @@ @ stub ?unlockbuf@ios@@QAAXXZ @ stub ?unlockc@ios@@KAXXZ @ stub ?unsetf@ios@@QAEJJ@Z -@ cdecl -i386 ?what@exception@@UBEPBDXZ() __thiscall_MSVCRT_what_exception +@ cdecl -i386 ?what@exception@@UBEPBDXZ() MSVCRT_what_exception @ stub ?width@ios@@QAEHH@Z @ stub ?width@ios@@QBEHXZ @ stub ?write@ostream@@QAEAAV1@PBCH@Z diff --git a/sdk/include/reactos/wine/asm.h b/sdk/include/reactos/wine/asm.h index 41a5de32026..14406b784eb 100644 --- a/sdk/include/reactos/wine/asm.h +++ b/sdk/include/reactos/wine/asm.h @@ -99,6 +99,10 @@ /* thiscall support */ +#ifdef _MSC_VER +#define __thiscall __stdcall +#endif + #if defined(__i386__) && !defined(__MINGW32__) # ifdef _MSC_VER diff --git a/sdk/include/reactos/wine/config.h b/sdk/include/reactos/wine/config.h index 670320898e4..7fd05d526e3 100644 --- a/sdk/include/reactos/wine/config.h +++ b/sdk/include/reactos/wine/config.h @@ -1316,43 +1316,6 @@ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ -/* Define to a macro to output a .cfi assembly pseudo-op */ -#define __ASM_CFI(str) str - -/* Define to a macro to define an assembly function */ -#ifndef _MSC_VER -#ifndef NO_UNDERSCORE_PREFIX -#define __ASM_DEFINE_FUNC(name,suffix,code) asm(".text\n\t.align 4\n\t.globl _" #name suffix "\n\t.def _" #name suffix "; .scl 2; .type 32; .endef\n_" #name suffix ":\n\t.cfi_startproc\n\t" code "\n\t.cfi_endproc"); -#else -#define __ASM_DEFINE_FUNC(name,suffix,code) asm(".text\n\t.align 4\n\t.globl " #name suffix "\n\t.def " #name suffix "; .scl 2; .type 32; .endef\n" #name suffix ":\n\t.cfi_startproc\n\t" code "\n\t.cfi_endproc"); -#endif -#else -#define __ASM_DEFINE_FUNC(name,suffix,code) -#endif - -/* Define to a macro to generate an assembly function directive */ -#define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef" - -/* Define to a macro to generate an assembly function with C calling - convention */ -#define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(name,"",code) - -/* Define to a macro to generate an assembly name from a C symbol */ -#ifndef NO_UNDERSCORE_PREFIX -#define __ASM_NAME(name) "_" name -#else -#define __ASM_NAME(name) name -#endif - -/* Define to a macro to generate an stdcall suffix */ -#define __ASM_STDCALL(args) "@" #args - -/* Define to a macro to generate an assembly function with stdcall calling - convention */ -#ifndef _MSC_VER -#define __ASM_STDCALL_FUNC(name,args,code) __ASM_DEFINE_FUNC(name,__ASM_STDCALL(args),code) -#endif - /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ diff --git a/sdk/include/reactos/wine/exception.h b/sdk/include/reactos/wine/exception.h index b16d502f826..9b29f2e470f 100644 --- a/sdk/include/reactos/wine/exception.h +++ b/sdk/include/reactos/wine/exception.h @@ -16,6 +16,8 @@ extern "C" { #define EH_EXIT_UNWIND 0x04 #define EH_STACK_INVALID 0x08 #define EH_NESTED_CALL 0x10 +#define EH_TARGET_UNWIND 0x20 +#define EH_COLLIDED_UNWIND 0x40 #define EXCEPTION_WINE_STUB 0x80000100 #define EXCEPTION_WINE_ASSERTION 0x80000101 @@ -56,6 +58,7 @@ typedef struct _WINE_EXCEPTION_REGISTRATION_RECORD #define __TRY _SEH2_TRY #define __EXCEPT(func) _SEH2_EXCEPT(func(_SEH2_GetExceptionInformation())) +#define __EXCEPT_CTX(func, ctx) _SEH2_EXCEPT((func)(GetExceptionInformation(), ctx)) #define __EXCEPT_PAGE_FAULT _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION) #define __EXCEPT_ALL _SEH2_EXCEPT(_SEH_EXECUTE_HANDLER) #define __ENDTRY _SEH2_END diff --git a/sdk/lib/crt/crt.cmake b/sdk/lib/crt/crt.cmake index 144a6000976..91f186013b6 100644 --- a/sdk/lib/crt/crt.cmake +++ b/sdk/lib/crt/crt.cmake @@ -20,12 +20,8 @@ list(APPEND CRT_SOURCE direct/wgetdcwd.c direct/wmkdir.c direct/wrmdir.c - except/cpp.c - except/cppexcept.c - except/except.c except/matherr.c except/stack.c - except/xcptfil.c float/chgsign.c float/copysign.c float/fpclass.c @@ -360,7 +356,11 @@ list(APPEND CRT_SOURCE wstring/wcsstr.c wstring/wcstok.c wstring/wcsupr.c - wstring/wcsxfrm.c + wstring/wcsxfrm.c) + +list(APPEND CRT_WINE_SOURCE + wine/cpp.c + wine/except.c wine/heap.c wine/undname.c) @@ -424,7 +424,6 @@ if(ARCH STREQUAL "i386") string/i386/wcsrchr_asm.s) list(APPEND CRT_SOURCE - except/i386/unwind.c float/i386/clearfp.c float/i386/cntrlfp.c float/i386/fpreset.c @@ -437,6 +436,8 @@ if(ARCH STREQUAL "i386") math/i386/cisin.c math/i386/cisqrt.c math/i386/ldexp.c) + list(APPEND CRT_WINE_SOURCE + wine/except_i386.c) if(MSVC) list(APPEND CRT_ASM_SOURCE except/i386/cpp.s) @@ -477,6 +478,8 @@ elseif(ARCH STREQUAL "amd64") except/amd64/ehandler.c float/i386/cntrlfp.c float/i386/statfp.c) + list(APPEND CRT_WINE_SOURCE + wine/except_x86_64.c) if(MSVC) list(APPEND CRT_ASM_SOURCE except/amd64/cpp.s) @@ -491,6 +494,9 @@ elseif(ARCH STREQUAL "arm") math/arm/__rt_udiv.c math/arm/__rt_udiv64_worker.c ) + list(APPEND CRT_WINE_SOURCE + wine/except_arm.c + ) list(APPEND CRT_ASM_SOURCE except/arm/_abnormal_termination.s except/arm/_except_handler2.s @@ -584,6 +590,9 @@ if(NOT ARCH STREQUAL "i386") string/wcsrchr.c) endif() +# includes for wine code +include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) + set_source_files_properties(${CRT_ASM_SOURCE} PROPERTIES COMPILE_DEFINITIONS "__MINGW_IMPORT=extern;USE_MSVCRT_PREFIX;_MSVCRT_LIB_;_MSVCRT_;_MT;CRTDLL") add_asm_files(crt_asm ${CRT_ASM_SOURCE}) @@ -593,7 +602,7 @@ if(USE_CLANG_CL) set_property(SOURCE stdlib/rot.c APPEND_STRING PROPERTY COMPILE_FLAGS " /fallback") endif() -add_library(crt ${CRT_SOURCE} ${crt_asm}) +add_library(crt ${CRT_SOURCE} ${CRT_WINE_SOURCE} ${crt_asm}) target_link_libraries(crt chkstk) add_target_compile_definitions(crt __MINGW_IMPORT=extern diff --git a/sdk/lib/crt/except/amd64/ehandler.c b/sdk/lib/crt/except/amd64/ehandler.c index 3705e4a7ed7..6e28e78e604 100644 --- a/sdk/lib/crt/except/amd64/ehandler.c +++ b/sdk/lib/crt/except/amd64/ehandler.c @@ -16,15 +16,7 @@ __C_specific_handler( return 0; } -DWORD -__CxxFrameHandler( - PEXCEPTION_RECORD rec, - EXCEPTION_REGISTRATION_RECORD* ExceptionRegistrationFrame, - PCONTEXT context, - EXCEPTION_REGISTRATION_RECORD** _ExceptionRecord) +void __cdecl _local_unwind(void* frame, void* target) { - UNIMPLEMENTED; - __debugbreak(); - return 0; + RtlUnwind(frame, target, NULL, 0); } - diff --git a/sdk/lib/crt/except/amd64/seh.s b/sdk/lib/crt/except/amd64/seh.s index 06bd671721d..77d0f368e4d 100644 --- a/sdk/lib/crt/except/amd64/seh.s +++ b/sdk/lib/crt/except/amd64/seh.s @@ -18,7 +18,6 @@ /* GLOBALS *******************************************************************/ PUBLIC _global_unwind2 -PUBLIC _local_unwind PUBLIC _local_unwind2 PUBLIC _abnormal_termination PUBLIC _except_handler2 @@ -42,11 +41,6 @@ FUNC _abnormal_termination ret ENDFUNC -FUNC _local_unwind - .endprolog - ret -ENDFUNC - FUNC _local_unwind2 .endprolog ret diff --git a/sdk/lib/crt/except/cpp.c b/sdk/lib/crt/except/cpp.c deleted file mode 100644 index 67fd29674d2..00000000000 --- a/sdk/lib/crt/except/cpp.c +++ /dev/null @@ -1,1266 +0,0 @@ -/* - * msvcrt.dll C++ objects - * - * Copyright 2000 Jon Griffiths - * Copyright 2003, 2004 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 - */ - -#include - -#include -#include -#include - -typedef exception bad_cast; -typedef exception bad_typeid; -typedef exception __non_rtti_object; - -typedef struct _rtti_base_descriptor -{ - const type_info *type_descriptor; - int num_base_classes; - this_ptr_offsets offsets; /* offsets for computing the this pointer */ - unsigned int attributes; -} rtti_base_descriptor; - -typedef struct _rtti_base_array -{ - const rtti_base_descriptor *bases[3]; /* First element is the class itself */ -} rtti_base_array; - -typedef struct _rtti_object_hierarchy -{ - unsigned int signature; - unsigned int attributes; - int array_len; /* Size of the array pointed to by 'base_classes' */ - const rtti_base_array *base_classes; -} rtti_object_hierarchy; - -typedef struct _rtti_object_locator -{ - unsigned int signature; - int base_class_offset; - unsigned int flags; - const type_info *type_descriptor; - const rtti_object_hierarchy *type_hierarchy; -} rtti_object_locator; - -#ifdef __i386__ /* thiscall functions are i386-specific */ - -#define THISCALL(func) __thiscall_ ## func -#define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func) - -#ifdef _MSC_VER -#include -#else -#define DEFINE_THISCALL_WRAPPER(func,args) \ - extern void THISCALL(func)(void); \ - __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ - "popl %eax\n\t" \ - "pushl %ecx\n\t" \ - "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) -#endif /* _MSC_VER */ - -#else /* __i386__ */ - -#define THISCALL(func) func -#define THISCALL_NAME(func) __ASM_NAME(#func) -#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ - -#endif /* __i386__ */ - -extern const vtable_ptr MSVCRT_exception_vtable; -extern const vtable_ptr MSVCRT_bad_typeid_vtable; -extern const vtable_ptr MSVCRT_bad_cast_vtable; -extern const vtable_ptr MSVCRT___non_rtti_object_vtable; -extern const vtable_ptr MSVCRT_type_info_vtable; - -/* get the vtable pointer for a C++ object */ -static inline const vtable_ptr *get_vtable( void *obj ) -{ - return *(const vtable_ptr **)obj; -} - -static inline const rtti_object_locator *get_obj_locator( void *cppobj ) -{ - const vtable_ptr *vtable = get_vtable( cppobj ); - return (const rtti_object_locator *)vtable[-1]; -} - -static void dump_obj_locator( const rtti_object_locator *ptr ) -{ - int i; - const rtti_object_hierarchy *h = ptr->type_hierarchy; - - TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n", - ptr, ptr->signature, ptr->base_class_offset, ptr->flags, - ptr->type_descriptor, dbgstr_type_info(ptr->type_descriptor), ptr->type_hierarchy ); - TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n", - h->signature, h->attributes, h->array_len, h->base_classes ); - for (i = 0; i < h->array_len; i++) - { - TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n", - h->base_classes->bases[i], - h->base_classes->bases[i]->num_base_classes, - h->base_classes->bases[i]->offsets.this_offset, - h->base_classes->bases[i]->offsets.vbase_descr, - h->base_classes->bases[i]->offsets.vbase_offset, - h->base_classes->bases[i]->attributes, - h->base_classes->bases[i]->type_descriptor, - dbgstr_type_info(h->base_classes->bases[i]->type_descriptor) ); - } -} - -/* Internal common ctor for exception */ -static void EXCEPTION_ctor(exception *_this, const char** name) -{ - _this->vtable = &MSVCRT_exception_vtable; - if (*name) - { - size_t name_len = strlen(*name) + 1; - _this->name = MSVCRT_malloc(name_len); - memcpy(_this->name, *name, name_len); - _this->do_free = TRUE; - } - else - { - _this->name = NULL; - _this->do_free = FALSE; - } -} - -/****************************************************************** - * ??0exception@@QAE@ABQBD@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8) -exception * __stdcall MSVCRT_exception_ctor(exception * _this, const char ** name) -{ - TRACE("(%p,%s)\n", _this, *name); - EXCEPTION_ctor(_this, name); - return _this; -} - -/****************************************************************** - * ??0exception@@QAE@ABQBDH@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12) -exception * __stdcall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc) -{ - TRACE("(%p,%s)\n", _this, *name); - _this->vtable = &MSVCRT_exception_vtable; - _this->name = *name; - _this->do_free = FALSE; - return _this; -} - -/****************************************************************** - * ??0exception@@QAE@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8) -exception * __stdcall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs) -{ - TRACE("(%p,%p)\n", _this, rhs); - - if (!rhs->do_free) - { - _this->vtable = &MSVCRT_exception_vtable; - _this->name = rhs->name; - _this->do_free = FALSE; - } - else - EXCEPTION_ctor(_this, (const char**)&rhs->name); - TRACE("name = %s\n", _this->name); - return _this; -} - -/****************************************************************** - * ??0exception@@QAE@XZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4) -exception * __stdcall MSVCRT_exception_default_ctor(exception * _this) -{ - static const char* empty = NULL; - - TRACE("(%p)\n", _this); - EXCEPTION_ctor(_this, &empty); - return _this; -} - -/****************************************************************** - * ??1exception@@UAE@XZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4) -void __stdcall MSVCRT_exception_dtor(exception * _this) -{ - TRACE("(%p)\n", _this); - _this->vtable = &MSVCRT_exception_vtable; - if (_this->do_free) MSVCRT_free(_this->name); -} - -/****************************************************************** - * ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8) -exception * __stdcall MSVCRT_exception_opequals(exception * _this, const exception * rhs) -{ - TRACE("(%p %p)\n", _this, rhs); - if (_this != rhs) - { - MSVCRT_exception_dtor(_this); - MSVCRT_exception_copy_ctor(_this, rhs); - } - TRACE("name = %s\n", _this->name); - return _this; -} - -/****************************************************************** - * ??_Eexception@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8) -void * __stdcall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - if (flags & 2) - { - /* we have an array, with the number of elements stored before the first object */ - int i, *ptr = (int *)_this - 1; - - for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i); - MSVCRT_operator_delete(ptr); - } - else - { - MSVCRT_exception_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - } - return _this; -} - -/****************************************************************** - * ??_Gexception@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8) -void * __stdcall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - MSVCRT_exception_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - return _this; -} - -/****************************************************************** - * ?what@exception@@UBEPBDXZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4) -const char * __stdcall MSVCRT_what_exception(exception * _this) -{ - TRACE("(%p) returning %s\n", _this, _this->name); - return _this->name ? _this->name : "Unknown exception"; -} - -/****************************************************************** - * ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8) -bad_typeid * __stdcall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs) -{ - TRACE("(%p %p)\n", _this, rhs); - MSVCRT_exception_copy_ctor(_this, rhs); - _this->vtable = &MSVCRT_bad_typeid_vtable; - return _this; -} - -/****************************************************************** - * ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8) -bad_typeid * __stdcall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name) -{ - TRACE("(%p %s)\n", _this, name); - EXCEPTION_ctor(_this, &name); - _this->vtable = &MSVCRT_bad_typeid_vtable; - return _this; -} - -/****************************************************************** - * ??_Fbad_typeid@@QAEXXZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4) -bad_typeid * __stdcall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this) -{ - return MSVCRT_bad_typeid_ctor( _this, "bad typeid" ); -} - -/****************************************************************** - * ??1bad_typeid@@UAE@XZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4) -void __stdcall MSVCRT_bad_typeid_dtor(bad_typeid * _this) -{ - TRACE("(%p)\n", _this); - MSVCRT_exception_dtor(_this); -} - -/****************************************************************** - * ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8) -bad_typeid * __stdcall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs) -{ - TRACE("(%p %p)\n", _this, rhs); - MSVCRT_exception_opequals(_this, rhs); - return _this; -} - -/****************************************************************** - * ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8) -void * __stdcall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - if (flags & 2) - { - /* we have an array, with the number of elements stored before the first object */ - int i, *ptr = (int *)_this - 1; - - for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i); - MSVCRT_operator_delete(ptr); - } - else - { - MSVCRT_bad_typeid_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - } - return _this; -} - -/****************************************************************** - * ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8) -void * __stdcall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - MSVCRT_bad_typeid_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - return _this; -} - -/****************************************************************** - * ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8) -__non_rtti_object * __stdcall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this, - const __non_rtti_object * rhs) -{ - TRACE("(%p %p)\n", _this, rhs); - MSVCRT_bad_typeid_copy_ctor(_this, rhs); - _this->vtable = &MSVCRT___non_rtti_object_vtable; - return _this; -} - -/****************************************************************** - * ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8) -__non_rtti_object * __stdcall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this, - const char * name) -{ - TRACE("(%p %s)\n", _this, name); - EXCEPTION_ctor(_this, &name); - _this->vtable = &MSVCRT___non_rtti_object_vtable; - return _this; -} - -/****************************************************************** - * ??1__non_rtti_object@@UAE@XZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4) -void __stdcall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this) -{ - TRACE("(%p)\n", _this); - MSVCRT_bad_typeid_dtor(_this); -} - -/****************************************************************** - * ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8) -__non_rtti_object * __stdcall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this, - const __non_rtti_object *rhs) -{ - TRACE("(%p %p)\n", _this, rhs); - MSVCRT_bad_typeid_opequals(_this, rhs); - return _this; -} - -/****************************************************************** - * ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8) -void * __stdcall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - if (flags & 2) - { - /* we have an array, with the number of elements stored before the first object */ - int i, *ptr = (int *)_this - 1; - - for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i); - MSVCRT_operator_delete(ptr); - } - else - { - MSVCRT___non_rtti_object_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - } - return _this; -} - -/****************************************************************** - * ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8) -void * __stdcall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - MSVCRT___non_rtti_object_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - return _this; -} - -/****************************************************************** - * ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@) - * ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8) -bad_cast * __stdcall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name) -{ - TRACE("(%p %s)\n", _this, *name); - EXCEPTION_ctor(_this, name); - _this->vtable = &MSVCRT_bad_cast_vtable; - return _this; -} - -/****************************************************************** - * ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8) -bad_cast * __stdcall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs) -{ - TRACE("(%p %p)\n", _this, rhs); - MSVCRT_exception_copy_ctor(_this, rhs); - _this->vtable = &MSVCRT_bad_cast_vtable; - return _this; -} - -/****************************************************************** - * ??0bad_cast@@QAE@PBD@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8) -bad_cast * __stdcall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name) -{ - TRACE("(%p %s)\n", _this, name); - EXCEPTION_ctor(_this, &name); - _this->vtable = &MSVCRT_bad_cast_vtable; - return _this; -} - -/****************************************************************** - * ??_Fbad_cast@@QAEXXZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4) -bad_cast * __stdcall MSVCRT_bad_cast_default_ctor(bad_cast * _this) -{ - return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" ); -} - -/****************************************************************** - * ??1bad_cast@@UAE@XZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4) -void __stdcall MSVCRT_bad_cast_dtor(bad_cast * _this) -{ - TRACE("(%p)\n", _this); - MSVCRT_exception_dtor(_this); -} - -/****************************************************************** - * ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8) -bad_cast * __stdcall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs) -{ - TRACE("(%p %p)\n", _this, rhs); - MSVCRT_exception_opequals(_this, rhs); - return _this; -} - -/****************************************************************** - * ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8) -void * __stdcall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - if (flags & 2) - { - /* we have an array, with the number of elements stored before the first object */ - int i, *ptr = (int *)_this - 1; - - for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i); - MSVCRT_operator_delete(ptr); - } - else - { - MSVCRT_bad_cast_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - } - return _this; -} - -/****************************************************************** - * ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8) -void * __stdcall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - MSVCRT_bad_cast_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - return _this; -} - -/****************************************************************** - * ??8type_info@@QBEHABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8) -int __stdcall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs) -{ - int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1); - TRACE("(%p %p) returning %d\n", _this, rhs, ret); - return ret; -} - -/****************************************************************** - * ??9type_info@@QBEHABV0@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8) -int __stdcall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs) -{ - int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1); - TRACE("(%p %p) returning %d\n", _this, rhs, ret); - return ret; -} - -/****************************************************************** - * ?before@type_info@@QBEHABV1@@Z (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8) -int __stdcall MSVCRT_type_info_before(type_info * _this, const type_info * rhs) -{ - int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0; - TRACE("(%p %p) returning %d\n", _this, rhs, ret); - return ret; -} - -/****************************************************************** - * ??1type_info@@UAE@XZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4) -void __stdcall MSVCRT_type_info_dtor(type_info * _this) -{ - TRACE("(%p)\n", _this); - MSVCRT_free(_this->name); -} - -/****************************************************************** - * ?name@type_info@@QBEPBDXZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4) -const char * __stdcall MSVCRT_type_info_name(type_info * _this) -{ - if (!_this->name) - { - /* Create and set the demangled name */ - /* Note: mangled name in type_info struct always starts with a '.', while - * it isn't valid for mangled name. - * Is this '.' really part of the mangled name, or has it some other meaning ? - */ - char* name = __unDName(0, _this->mangled + 1, 0, - MSVCRT_malloc, MSVCRT_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE); - if (name) - { - size_t len = strlen(name); - - /* It seems _unDName may leave blanks at the end of the demangled name */ - while (len && name[--len] == ' ') - name[len] = '\0'; - - if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL)) - { - /* Another thread set this member since we checked above - use it */ - MSVCRT_free(name); - } - } - } - TRACE("(%p) returning %s\n", _this, _this->name); - return _this->name; -} - -/****************************************************************** - * ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@) - */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4) -const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this) -{ - TRACE("(%p) returning %s\n", _this, _this->mangled); - return _this->mangled; -} - -/* Unexported */ -DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8) -void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags) -{ - TRACE("(%p %x)\n", _this, flags); - if (flags & 2) - { - /* we have an array, with the number of elements stored before the first object */ - int i, *ptr = (int *)_this - 1; - - for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i); - MSVCRT_operator_delete(ptr); - } - else - { - MSVCRT_type_info_dtor(_this); - if (flags & 1) MSVCRT_operator_delete(_this); - } - return _this; -} - -/* vtables */ - -#ifdef __GNUC__ -#ifdef _WIN64 - -#define __ASM_VTABLE(name,funcs) \ - __asm__(".data\n" \ - "\t.align 8\n" \ - "\t.quad " __ASM_NAME(#name "_rtti") "\n" \ - "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \ - __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \ - "\t.quad " THISCALL_NAME(MSVCRT_ ## name ## _vector_dtor) "\n" \ - funcs "\n\t.text"); - -#define __ASM_EXCEPTION_VTABLE(name) \ - __ASM_VTABLE(name, "\t.quad " THISCALL_NAME(MSVCRT_what_exception) ) - -#else - -#define __ASM_VTABLE(name,funcs) \ - __asm__(".data\n" \ - "\t.align 4\n" \ - "\t.long " __ASM_NAME(#name "_rtti") "\n" \ - "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \ - __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \ - "\t.long " THISCALL_NAME(MSVCRT_ ## name ## _vector_dtor) "\n" \ - funcs "\n\t.text"); - -#define __ASM_EXCEPTION_VTABLE(name) \ - __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCRT_what_exception) ) - -#endif /* _WIN64 */ - -#ifndef __GNUC__ -void __asm_dummy_vtables(void) { -#endif - -__ASM_VTABLE(type_info,"") -__ASM_EXCEPTION_VTABLE(exception) -__ASM_EXCEPTION_VTABLE(bad_typeid) -__ASM_EXCEPTION_VTABLE(bad_cast) -__ASM_EXCEPTION_VTABLE(__non_rtti_object) - -#ifndef __GNUC__ -} -#endif -#endif - -/* Static RTTI for exported objects */ - -static const type_info exception_type_info = -{ - &MSVCRT_type_info_vtable, - NULL, - ".?AVexception@@" -}; - -static const rtti_base_descriptor exception_rtti_base_descriptor = -{ - &exception_type_info, - 0, - { 0, -1, 0 }, - 0 -}; - -static const rtti_base_array exception_rtti_base_array = -{ - { - &exception_rtti_base_descriptor, - NULL, - NULL - } -}; - -static const rtti_object_hierarchy exception_type_hierarchy = -{ - 0, - 0, - 1, - &exception_rtti_base_array -}; - -const rtti_object_locator exception_rtti = -{ - 0, - 0, - 0, - &exception_type_info, - &exception_type_hierarchy -}; - -static const cxx_type_info exception_cxx_type_info = -{ - 0, - &exception_type_info, - { 0, -1, 0 }, - sizeof(exception), - (cxx_copy_ctor)THISCALL(MSVCRT_exception_copy_ctor) -}; - -static const type_info bad_typeid_type_info = -{ - &MSVCRT_type_info_vtable, - NULL, - ".?AVbad_typeid@@" -}; - -static const rtti_base_descriptor bad_typeid_rtti_base_descriptor = -{ - &bad_typeid_type_info, - 1, - { 0, -1, 0 }, - 0 -}; - -static const rtti_base_array bad_typeid_rtti_base_array = -{ - { - &bad_typeid_rtti_base_descriptor, - &exception_rtti_base_descriptor, - NULL - } -}; - -static const rtti_object_hierarchy bad_typeid_type_hierarchy = -{ - 0, - 0, - 2, - &bad_typeid_rtti_base_array -}; - -const rtti_object_locator bad_typeid_rtti = -{ - 0, - 0, - 0, - &bad_typeid_type_info, - &bad_typeid_type_hierarchy -}; - -static const cxx_type_info bad_typeid_cxx_type_info = -{ - 0, - &bad_typeid_type_info, - { 0, -1, 0 }, - sizeof(exception), - (cxx_copy_ctor)THISCALL(MSVCRT_bad_typeid_copy_ctor) -}; - -static const type_info bad_cast_type_info = -{ - &MSVCRT_type_info_vtable, - NULL, - ".?AVbad_cast@@" -}; - -static const rtti_base_descriptor bad_cast_rtti_base_descriptor = -{ - &bad_cast_type_info, - 1, - { 0, -1, 0 }, - 0 -}; - -static const rtti_base_array bad_cast_rtti_base_array = -{ - { - &bad_cast_rtti_base_descriptor, - &exception_rtti_base_descriptor, - NULL - } -}; - -static const rtti_object_hierarchy bad_cast_type_hierarchy = -{ - 0, - 0, - 2, - &bad_cast_rtti_base_array -}; - -const rtti_object_locator bad_cast_rtti = -{ - 0, - 0, - 0, - &bad_cast_type_info, - &bad_cast_type_hierarchy -}; - -static const cxx_type_info bad_cast_cxx_type_info = -{ - 0, - &bad_cast_type_info, - { 0, -1, 0 }, - sizeof(exception), - (cxx_copy_ctor)THISCALL(MSVCRT_bad_cast_copy_ctor) -}; - -static const type_info __non_rtti_object_type_info = -{ - &MSVCRT_type_info_vtable, - NULL, - ".?AV__non_rtti_object@@" -}; - -static const rtti_base_descriptor __non_rtti_object_rtti_base_descriptor = -{ - &__non_rtti_object_type_info, - 2, - { 0, -1, 0 }, - 0 -}; - -static const rtti_base_array __non_rtti_object_rtti_base_array = -{ - { - &__non_rtti_object_rtti_base_descriptor, - &bad_typeid_rtti_base_descriptor, - &exception_rtti_base_descriptor - } -}; - -static const rtti_object_hierarchy __non_rtti_object_type_hierarchy = -{ - 0, - 0, - 3, - &__non_rtti_object_rtti_base_array -}; - -const rtti_object_locator __non_rtti_object_rtti = -{ - 0, - 0, - 0, - &__non_rtti_object_type_info, - &__non_rtti_object_type_hierarchy -}; - -static const cxx_type_info __non_rtti_object_cxx_type_info = -{ - 0, - &__non_rtti_object_type_info, - { 0, -1, 0 }, - sizeof(exception), - (cxx_copy_ctor)THISCALL(MSVCRT___non_rtti_object_copy_ctor) -}; - -static const type_info type_info_type_info = -{ - &MSVCRT_type_info_vtable, - NULL, - ".?AVtype_info@@" -}; - -static const rtti_base_descriptor type_info_rtti_base_descriptor = -{ - &type_info_type_info, - 0, - { 0, -1, 0 }, - 0 -}; - -static const rtti_base_array type_info_rtti_base_array = -{ - { - &type_info_rtti_base_descriptor, - NULL, - NULL - } -}; - -static const rtti_object_hierarchy type_info_type_hierarchy = -{ - 0, - 0, - 1, - &type_info_rtti_base_array -}; - -const rtti_object_locator type_info_rtti = -{ - 0, - 0, - 0, - &type_info_type_info, - &type_info_type_hierarchy -}; - -/* - * Exception RTTI for cpp objects - */ -static const cxx_type_info_table bad_cast_type_info_table = -{ - 3, - { - &__non_rtti_object_cxx_type_info, - &bad_typeid_cxx_type_info, - &exception_cxx_type_info - } -}; - -static const cxx_exception_type bad_cast_exception_type = -{ - 0, - (void*)THISCALL(MSVCRT_bad_cast_dtor), - NULL, - &bad_cast_type_info_table -}; - -static const cxx_type_info_table bad_typeid_type_info_table = -{ - 2, - { - &bad_cast_cxx_type_info, - &exception_cxx_type_info, - NULL - } -}; - -static const cxx_exception_type bad_typeid_exception_type = -{ - 0, - (void*)THISCALL(MSVCRT_bad_typeid_dtor), - NULL, - &bad_cast_type_info_table -}; - -static const cxx_exception_type __non_rtti_object_exception_type = -{ - 0, - (void*)THISCALL(MSVCRT___non_rtti_object_dtor), - NULL, - &bad_typeid_type_info_table -}; - - -/****************************************************************** - * ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@) - * - * Install a handler to be called when terminate() is called. - * - * PARAMS - * func [I] Handler function to install - * - * RETURNS - * The previously installed handler function, if any. - */ -terminate_function CDECL MSVCRT_set_terminate(terminate_function func) -{ - thread_data_t *data = msvcrt_get_thread_data(); - terminate_function previous = data->terminate_handler; - TRACE("(%p) returning %p\n",func,previous); - data->terminate_handler = func; - return previous; -} - -/****************************************************************** - * _get_terminate (MSVCRT.@) - */ -terminate_function CDECL _get_terminate(void) -{ - thread_data_t *data = msvcrt_get_thread_data(); - return data->terminate_handler; -} - -/****************************************************************** - * ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@) - * - * Install a handler to be called when unexpected() is called. - * - * PARAMS - * func [I] Handler function to install - * - * RETURNS - * The previously installed handler function, if any. - */ -unexpected_function CDECL MSVCRT_set_unexpected(unexpected_function func) -{ - thread_data_t *data = msvcrt_get_thread_data(); - unexpected_function previous = data->unexpected_handler; - TRACE("(%p) returning %p\n",func,previous); - data->unexpected_handler = func; - return previous; -} - -/****************************************************************** - * _get_unexpected (MSVCRT.@) - */ -unexpected_function CDECL _get_unexpected(void) -{ - thread_data_t *data = msvcrt_get_thread_data(); - return data->unexpected_handler; -} - -/****************************************************************** - * ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z (MSVCRT.@) - */ -_se_translator_function CDECL MSVCRT__set_se_translator(_se_translator_function func) -{ - thread_data_t *data = msvcrt_get_thread_data(); - _se_translator_function previous = data->se_translator; - TRACE("(%p) returning %p\n",func,previous); - data->se_translator = func; - return previous; -} - -/****************************************************************** - * ?terminate@@YAXXZ (MSVCRT.@) - * - * Default handler for an unhandled exception. - * - * PARAMS - * None. - * - * RETURNS - * This function does not return. Either control resumes from any - * handler installed by calling set_terminate(), or (by default) abort() - * is called. - */ -void CDECL MSVCRT_terminate(void) -{ - thread_data_t *data = msvcrt_get_thread_data(); - if (data->terminate_handler) data->terminate_handler(); - abort(); -} - -/****************************************************************** - * ?unexpected@@YAXXZ (MSVCRT.@) - */ -void CDECL MSVCRT_unexpected(void) -{ - thread_data_t *data = msvcrt_get_thread_data(); - if (data->unexpected_handler) data->unexpected_handler(); - MSVCRT_terminate(); -} - - -/****************************************************************** - * __RTtypeid (MSVCRT.@) - * - * Retrieve the Run Time Type Information (RTTI) for a C++ object. - * - * PARAMS - * cppobj [I] C++ object to get type information for. - * - * RETURNS - * Success: A type_info object describing cppobj. - * Failure: If the object to be cast has no RTTI, a __non_rtti_object - * exception is thrown. If cppobj is NULL, a bad_typeid exception - * is thrown. In either case, this function does not return. - * - * NOTES - * This function is usually called by compiler generated code as a result - * of using one of the C++ dynamic cast statements. - */ -const type_info* CDECL MSVCRT___RTtypeid(void *cppobj) -{ - const type_info *ret; - - if (!cppobj) - { - bad_typeid e; - MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" ); - _CxxThrowException( &e, &bad_typeid_exception_type ); - return NULL; - } - - __TRY - { - const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); - ret = obj_locator->type_descriptor; - } - __EXCEPT_PAGE_FAULT - { - __non_rtti_object e; - MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" ); - _CxxThrowException( &e, &__non_rtti_object_exception_type ); - return NULL; - } - __ENDTRY - return ret; -} - -/****************************************************************** - * __RTDynamicCast (MSVCRT.@) - * - * Dynamically cast a C++ object to one of its base classes. - * - * PARAMS - * cppobj [I] Any C++ object to cast - * unknown [I] Reserved, set to 0 - * src [I] type_info object describing cppobj - * dst [I] type_info object describing the base class to cast to - * do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't - * - * RETURNS - * Success: The address of cppobj, cast to the object described by dst. - * Failure: NULL, If the object to be cast has no RTTI, or dst is not a - * valid cast for cppobj. If do_throw is TRUE, a bad_cast exception - * is thrown and this function does not return. - * - * NOTES - * This function is usually called by compiler generated code as a result - * of using one of the C++ dynamic cast statements. - */ -void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown, - type_info *src, type_info *dst, - int do_throw) -{ - void *ret; - - if (!cppobj) return NULL; - - TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n", - cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw); - - /* To cast an object at runtime: - * 1.Find out the true type of the object from the typeinfo at vtable[-1] - * 2.Search for the destination type in the class hierarchy - * 3.If destination type is found, return base object address + dest offset - * Otherwise, fail the cast - * - * FIXME: the unknown parameter doesn't seem to be used for anything - */ - __TRY - { - int i; - const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); - const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy; - const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases; - - if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator); - - ret = NULL; - for (i = 0; i < obj_bases->array_len; i++) - { - const type_info *typ = base_desc[i]->type_descriptor; - - if (!strcmp(typ->mangled, dst->mangled)) - { - /* compute the correct this pointer for that base class */ - void *this_ptr = (char *)cppobj - obj_locator->base_class_offset; - ret = get_this_pointer( &base_desc[i]->offsets, this_ptr ); - break; - } - } - /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned - * to a reference, since references cannot be NULL. - */ - if (!ret && do_throw) - { - const char *msg = "Bad dynamic_cast!"; - bad_cast e; - MSVCRT_bad_cast_ctor( &e, &msg ); - _CxxThrowException( &e, &bad_cast_exception_type ); - } - } - __EXCEPT_PAGE_FAULT - { - __non_rtti_object e; - MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" ); - _CxxThrowException( &e, &__non_rtti_object_exception_type ); - return NULL; - } - __ENDTRY - return ret; -} - - -/****************************************************************** - * __RTCastToVoid (MSVCRT.@) - * - * Dynamically cast a C++ object to a void*. - * - * PARAMS - * cppobj [I] The C++ object to cast - * - * RETURNS - * Success: The base address of the object as a void*. - * Failure: NULL, if cppobj is NULL or has no RTTI. - * - * NOTES - * This function is usually called by compiler generated code as a result - * of using one of the C++ dynamic cast statements. - */ -void* CDECL MSVCRT___RTCastToVoid(void *cppobj) -{ - void *ret; - - if (!cppobj) return NULL; - - __TRY - { - const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); - ret = (char *)cppobj - obj_locator->base_class_offset; - } - __EXCEPT_PAGE_FAULT - { - __non_rtti_object e; - MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" ); - _CxxThrowException( &e, &__non_rtti_object_exception_type ); - return NULL; - } - __ENDTRY - return ret; -} diff --git a/sdk/lib/crt/except/cppexcept.c b/sdk/lib/crt/except/cppexcept.c deleted file mode 100644 index e1352a608be..00000000000 --- a/sdk/lib/crt/except/cppexcept.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - * msvcrt C++ exception handling - * - * Copyright 2002 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 - * A good reference is the article "How a C++ compiler implements - * exception handling" by Vishal Kochhar, available on - * www.thecodeproject.com. - */ - -#define __WINE_DEBUG_CHANNEL__ -#include -#include - -#include -#include -#include - -#ifdef __i386__ /* CxxFrameHandler is not supported on non-i386 */ - -WINE_DEFAULT_DEBUG_CHANNEL(seh); - -DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame, - PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch, - const cxx_function_descr *descr, - EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel ); - -/* call a function with a given ebp */ -#ifdef _MSC_VER -#pragma warning(disable:4731) // don't warn about modification of ebp -#endif -static inline void *call_ebp_func( void *func, void *_ebp ) -{ - void *result; -#ifdef _MSC_VER - __asm - { - mov eax, func - push ebx - push ebp - mov ebp, _ebp - call eax - pop ebp - pop ebx - mov result, eax - } -#else - int dummy; - __asm__ __volatile__ ("pushl %%ebx\n\t" - "pushl %%ebp\n\t" - "movl %4,%%ebp\n\t" - "call *%%eax\n\t" - "popl %%ebp\n\t" - "popl %%ebx" - : "=a" (result), "=S" (dummy), "=D" (dummy) - : "0" (func), "1" (_ebp) : "ecx", "edx", "memory" ); -#endif - return result; -} -#ifdef _MSC_VER -#pragma warning(default:4731) -#endif - -/* call a copy constructor */ -static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase ) -{ - TRACE( "calling copy ctor %p object %p src %p\n", func, this, src ); -#ifdef _MSC_VER - if (has_vbase) - { - __asm - { - mov ecx, this - push 1 - push src - call func - } - } - else - { - __asm - { - mov ecx, this - push src - call func - } - } -#else - if (has_vbase) - /* in that case copy ctor takes an extra bool indicating whether to copy the base class */ - __asm__ __volatile__("pushl $1; pushl %2; call *%0" - : : "r" (func), "c" (this), "r" (src) : "eax", "edx", "memory" ); - else - __asm__ __volatile__("pushl %2; call *%0" - : : "r" (func), "c" (this), "r" (src) : "eax", "edx", "memory" ); -#endif -} - -/* call the destructor of the exception object */ -static inline void call_dtor( void *func, void *object ) -{ -#ifdef _MSC_VER - __asm - { - mov ecx, object - call func - } -#else - __asm__ __volatile__("call *%0" : : "r" (func), "c" (object) : "eax", "edx", "memory" ); -#endif -} - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4731) -/* continue execution to the specified address after exception is caught */ -__forceinline void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr ) -{ - __asm - { - mov eax, addr - mov edx, frame - mov esp, [edx-4] - lea ebp, [edx+12] - jmp eax - } - for (;;) ; /* unreached */ -} -#pragma warning(pop) -#else -/* continue execution to the specified address after exception is caught */ -static inline void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr ) -{ - __asm__ __volatile__("movl -4(%0),%%esp; leal 12(%0),%%ebp; jmp *%1" - : : "r" (frame), "a" (addr) ); - for (;;) ; /* unreached */ -} -#endif - -static inline void dump_type( const cxx_type_info *type ) -{ - TRACE( "flags %x type %p %s offsets %d,%d,%d size %d copy ctor %p\n", - type->flags, type->type_info, dbgstr_type_info(type->type_info), - type->offsets.this_offset, type->offsets.vbase_descr, type->offsets.vbase_offset, - type->size, type->copy_ctor ); -} - -static void dump_exception_type( const cxx_exception_type *type ) -{ - UINT i; - - TRACE( "flags %x destr %p handler %p type info %p\n", - type->flags, type->destructor, type->custom_handler, type->type_info_table ); - for (i = 0; i < type->type_info_table->count; i++) - { - TRACE( " %d: ", i ); - dump_type( type->type_info_table->info[i] ); - } -} - -static void dump_function_descr( const cxx_function_descr *descr ) -{ -#ifndef WINE_NO_TRACE_MSGS - UINT i; - int j; - - TRACE( "magic %x\n", descr->magic ); - TRACE( "unwind table: %p %d\n", descr->unwind_table, descr->unwind_count ); - for (i = 0; i < descr->unwind_count; i++) - { - TRACE( " %d: prev %d func %p\n", i, - descr->unwind_table[i].prev, descr->unwind_table[i].handler ); - } - TRACE( "try table: %p %d\n", descr->tryblock, descr->tryblock_count ); - for (i = 0; i < descr->tryblock_count; i++) - { - TRACE( " %d: start %d end %d catchlevel %d catch %p %d\n", i, - descr->tryblock[i].start_level, descr->tryblock[i].end_level, - descr->tryblock[i].catch_level, descr->tryblock[i].catchblock, - descr->tryblock[i].catchblock_count ); - for (j = 0; j < descr->tryblock[i].catchblock_count; j++) - { - const catchblock_info *ptr = &descr->tryblock[i].catchblock[j]; - TRACE( " %d: flags %x offset %d handler %p type %p %s\n", - j, ptr->flags, ptr->offset, ptr->handler, - ptr->type_info, dbgstr_type_info( ptr->type_info ) ); - } - } -#endif - if (descr->magic <= CXX_FRAME_MAGIC_VC6) return; - TRACE( "expect list: %p\n", descr->expect_list ); - if (descr->magic <= CXX_FRAME_MAGIC_VC7) return; - TRACE( "flags: %08x\n", descr->flags ); -} - -/* check if the exception type is caught by a given catch block, and return the type that matched */ -static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type, - const catchblock_info *catchblock ) -{ - UINT i; - - for (i = 0; i < exc_type->type_info_table->count; i++) - { - const cxx_type_info *type = exc_type->type_info_table->info[i]; - - if (!catchblock->type_info) return type; /* catch(...) matches any type */ - if (catchblock->type_info != type->type_info) - { - if (strcmp( catchblock->type_info->mangled, type->type_info->mangled )) continue; - } - /* type is the same, now check the flags */ - if ((exc_type->flags & TYPE_FLAG_CONST) && - !(catchblock->flags & TYPE_FLAG_CONST)) continue; - if ((exc_type->flags & TYPE_FLAG_VOLATILE) && - !(catchblock->flags & TYPE_FLAG_VOLATILE)) continue; - return type; /* it matched */ - } - return NULL; -} - - -/* copy the exception object where the catch block wants it */ -static void copy_exception( void *object, cxx_exception_frame *frame, - const catchblock_info *catchblock, const cxx_type_info *type ) -{ - void **dest_ptr; - - if (!catchblock->type_info || !catchblock->type_info->mangled[0]) return; - if (!catchblock->offset) return; - dest_ptr = (void **)((char *)&frame->ebp + catchblock->offset); - - if (catchblock->flags & TYPE_FLAG_REFERENCE) - { - *dest_ptr = get_this_pointer( &type->offsets, object ); - } - else if (type->flags & CLASS_IS_SIMPLE_TYPE) - { - memmove( dest_ptr, object, type->size ); - /* if it is a pointer, adjust it */ - if (type->size == sizeof(void *)) *dest_ptr = get_this_pointer( &type->offsets, *dest_ptr ); - } - else /* copy the object */ - { - if (type->copy_ctor) - call_copy_ctor( type->copy_ctor, dest_ptr, get_this_pointer(&type->offsets,object), - (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) ); - else - memmove( dest_ptr, get_this_pointer(&type->offsets,object), type->size ); - } -} - -/* unwind the local function up to a given trylevel */ -static void cxx_local_unwind( cxx_exception_frame* frame, const cxx_function_descr *descr, int last_level) -{ - void (*handler)(void); - int trylevel = frame->trylevel; - - while (trylevel != last_level) - { - if (trylevel < 0 || (unsigned)trylevel >= descr->unwind_count) - { - ERR( "invalid trylevel %d\n", trylevel ); - MSVCRT_terminate(); - } - handler = descr->unwind_table[trylevel].handler; - if (handler) - { - TRACE( "calling unwind handler %p trylevel %d last %d ebp %p\n", - handler, trylevel, last_level, &frame->ebp ); - call_ebp_func( handler, &frame->ebp ); - } - trylevel = descr->unwind_table[trylevel].prev; - } - frame->trylevel = last_level; -} - -/* exception frame for nested exceptions in catch block */ -struct catch_func_nested_frame -{ - EXCEPTION_REGISTRATION_RECORD frame; /* standard exception frame */ - EXCEPTION_RECORD *prev_rec; /* previous record to restore in thread data */ - cxx_exception_frame *cxx_frame; /* frame of parent exception */ - const cxx_function_descr *descr; /* descriptor of parent exception */ - int trylevel; /* current try level */ - EXCEPTION_RECORD *rec; /* rec associated with frame */ -}; - -/* handler for exceptions happening while calling a catch function */ -static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, - CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) -{ - struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame; - - if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) - { - msvcrt_get_thread_data()->exc_record = nested_frame->prev_rec; - return ExceptionContinueSearch; - } - - TRACE( "got nested exception in catch function\n" ); - - if(rec->ExceptionCode == CXX_EXCEPTION) - { - PEXCEPTION_RECORD prev_rec = nested_frame->rec; - if(rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) - { - /* exception was rethrown */ - rec->ExceptionInformation[1] = prev_rec->ExceptionInformation[1]; - rec->ExceptionInformation[2] = prev_rec->ExceptionInformation[2]; - TRACE("detect rethrow: re-propagate: obj: %lx, type: %lx\n", - rec->ExceptionInformation[1], rec->ExceptionInformation[2]); - } - else { - /* new exception in exception handler, destroy old */ - void *object = (void*)prev_rec->ExceptionInformation[1]; - cxx_exception_type *info = (cxx_exception_type*) prev_rec->ExceptionInformation[2]; - TRACE("detect threw new exception in catch block - destroy old(obj: %p type: %p)\n", - object, info); - if(info && info->destructor) - call_dtor( info->destructor, object ); - } - } - - return cxx_frame_handler( rec, nested_frame->cxx_frame, context, - NULL, nested_frame->descr, &nested_frame->frame, - nested_frame->trylevel ); -} - -/* find and call the appropriate catch block for an exception */ -/* returns the address to continue execution to after the catch block was called */ -static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame, - const cxx_function_descr *descr, int nested_trylevel, - cxx_exception_type *info ) -{ - UINT i; - int j; - void *addr, *object = (void *)rec->ExceptionInformation[1]; - struct catch_func_nested_frame nested_frame; - int trylevel = frame->trylevel; - thread_data_t *thread_data = msvcrt_get_thread_data(); - DWORD save_esp = ((DWORD*)frame)[-1]; - - for (i = 0; i < descr->tryblock_count; i++) - { - const tryblock_info *tryblock = &descr->tryblock[i]; - - if (trylevel < tryblock->start_level) continue; - if (trylevel > tryblock->end_level) continue; - - /* got a try block */ - for (j = 0; j < tryblock->catchblock_count; j++) - { - const catchblock_info *catchblock = &tryblock->catchblock[j]; - if(info) - { - const cxx_type_info *type = find_caught_type( info, catchblock ); - if (!type) continue; - - TRACE( "matched type %p in tryblock %d catchblock %d\n", type, i, j ); - - /* copy the exception to its destination on the stack */ - copy_exception( object, frame, catchblock, type ); - } - else - { - /* no CXX_EXCEPTION only proceed with a catch(...) block*/ - if(catchblock->type_info) - continue; - TRACE("found catch(...) block\n"); - } - - /* unwind the stack */ - RtlUnwind( frame, 0, rec, 0 ); - cxx_local_unwind( frame, descr, tryblock->start_level ); - frame->trylevel = tryblock->end_level + 1; - - /* call the catch block */ - TRACE( "calling catch block %p addr %p ebp %p\n", - catchblock, catchblock->handler, &frame->ebp ); - - /* setup an exception block for nested exceptions */ - - nested_frame.frame.Handler = (PEXCEPTION_ROUTINE)catch_function_nested_handler; - nested_frame.prev_rec = thread_data->exc_record; - nested_frame.cxx_frame = frame; - nested_frame.descr = descr; - nested_frame.trylevel = nested_trylevel + 1; - nested_frame.rec = rec; - - __wine_push_frame( &nested_frame.frame ); - thread_data->exc_record = rec; - addr = call_ebp_func( catchblock->handler, &frame->ebp ); - thread_data->exc_record = nested_frame.prev_rec; - __wine_pop_frame( &nested_frame.frame ); - - ((DWORD*)frame)[-1] = save_esp; - if (info && info->destructor) call_dtor( info->destructor, object ); - TRACE( "done, continuing at %p\n", addr ); - - continue_after_catch( frame, addr ); - } - } -} - - -/********************************************************************* - * cxx_frame_handler - * - * Implementation of __CxxFrameHandler. - */ -DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame, - PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch, - const cxx_function_descr *descr, - EXCEPTION_REGISTRATION_RECORD* nested_frame, - int nested_trylevel ) -{ - cxx_exception_type *exc_type; - - if (descr->magic < CXX_FRAME_MAGIC_VC6 || descr->magic > CXX_FRAME_MAGIC_VC8) - { - ERR( "invalid frame magic %x\n", descr->magic ); - return ExceptionContinueSearch; - } - if (descr->magic >= CXX_FRAME_MAGIC_VC8 && - (descr->flags & FUNC_DESCR_SYNCHRONOUS) && - (rec->ExceptionCode != CXX_EXCEPTION)) - return ExceptionContinueSearch; /* handle only c++ exceptions */ - - if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND)) - { - if (descr->unwind_count && !nested_trylevel) cxx_local_unwind( frame, descr, -1 ); - return ExceptionContinueSearch; - } - if (!descr->tryblock_count) return ExceptionContinueSearch; - - if(rec->ExceptionCode == CXX_EXCEPTION) - { - exc_type = (cxx_exception_type *)rec->ExceptionInformation[2]; - - if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8 && - exc_type->custom_handler) - { - return exc_type->custom_handler( rec, frame, context, dispatch, - descr, nested_trylevel, nested_frame, 0 ); - } - - if (TRACE_ON(seh)) - { - TRACE("handling C++ exception rec %p frame %p trylevel %d descr %p nested_frame %p\n", - rec, frame, frame->trylevel, descr, nested_frame ); - dump_exception_type( exc_type ); - dump_function_descr( descr ); - } - } - else - { - exc_type = NULL; - TRACE("handling C exception code %x rec %p frame %p trylevel %d descr %p nested_frame %p\n", - rec->ExceptionCode, rec, frame, frame->trylevel, descr, nested_frame ); - } - - call_catch_block( rec, frame, descr, frame->trylevel, exc_type ); - return ExceptionContinueSearch; -} - - -/********************************************************************* - * __CxxFrameHandler (MSVCRT.@) - */ -extern DWORD CDECL __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame, - PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch ); -#ifdef _MSC_VER -DWORD _declspec(naked) __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame, - PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch ) -{ - __asm - { - push 0 - push 0 - push eax - push [esp + 28] - push [esp + 28] - push [esp + 28] - push [esp + 28] - call cxx_frame_handler - add esp, 28 - ret - } -} -#else -__ASM_GLOBAL_FUNC( __CxxFrameHandler, - "pushl $0\n\t" /* nested_trylevel */ - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "pushl $0\n\t" /* nested_frame */ - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "pushl %eax\n\t" /* descr */ - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "pushl 28(%esp)\n\t" /* dispatch */ - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "pushl 28(%esp)\n\t" /* context */ - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "pushl 28(%esp)\n\t" /* frame */ - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "pushl 28(%esp)\n\t" /* rec */ - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "call " __ASM_NAME("cxx_frame_handler") "\n\t" - "add $28,%esp\n\t" - __ASM_CFI(".cfi_adjust_cfa_offset -28\n\t") - "ret" ) -#endif - -/********************************************************************* - * __CxxLongjmpUnwind (MSVCRT.@) - * - * Callback meant to be used as UnwindFunc for setjmp/longjmp. - */ -void __stdcall __CxxLongjmpUnwind( const struct __JUMP_BUFFER *buf ) -{ - cxx_exception_frame *frame = (cxx_exception_frame *)buf->Registration; - const cxx_function_descr *descr = (const cxx_function_descr *)buf->UnwindData[0]; - - TRACE( "unwinding frame %p descr %p trylevel %ld\n", frame, descr, buf->TryLevel ); - cxx_local_unwind( frame, descr, buf->TryLevel ); -} - -#endif /* __i386__ */ - - -/********************************************************************* - * __CppXcptFilter (MSVCRT.@) - */ -int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr) -{ - /* only filter c++ exceptions */ - if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH; - return _XcptFilter( ex, ptr ); -} - -/********************************************************************* - * _CxxThrowException (MSVCRT.@) - */ -void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type ) -{ - ULONG_PTR args[3]; - - args[0] = CXX_FRAME_MAGIC_VC6; - args[1] = (ULONG_PTR)object; - args[2] = (ULONG_PTR)type; - RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args ); -} - -/********************************************************************* - * __CxxDetectRethrow (MSVCRT.@) - */ -BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs) -{ - PEXCEPTION_RECORD rec; - - if (!ptrs) - return FALSE; - - rec = ptrs->ExceptionRecord; - - if (rec->ExceptionCode == CXX_EXCEPTION && - rec->NumberParameters == 3 && - rec->ExceptionInformation[0] == CXX_FRAME_MAGIC_VC6 && - rec->ExceptionInformation[2]) - { - ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record; - return TRUE; - } - return (msvcrt_get_thread_data()->exc_record == rec); -} - -/********************************************************************* - * __CxxQueryExceptionSize (MSVCRT.@) - */ -unsigned int CDECL __CxxQueryExceptionSize(void) -{ - return sizeof(cxx_exception_type); -} diff --git a/sdk/lib/crt/except/except.c b/sdk/lib/crt/except/except.c deleted file mode 100644 index a3ed19bf545..00000000000 --- a/sdk/lib/crt/except/except.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * msvcrt.dll exception handling - * - * Copyright 2000 Jon Griffiths - * Copyright 2005 Juan Lang - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * 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 - * - * FIXME: Incomplete support for nested exceptions/try block cleanup. - */ - -#include -#include "excpt.h" -#include "cppexcept.h" -#include - -void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame); - -typedef void (__cdecl *MSVCRT_security_error_handler)(int, void *); -static MSVCRT_security_error_handler security_error_handler; - -/* VC++ extensions to Win32 SEH */ -typedef struct _SCOPETABLE -{ - int previousTryLevel; - int (*lpfnFilter)(PEXCEPTION_POINTERS); - int (*lpfnHandler)(void); -} SCOPETABLE, *PSCOPETABLE; - -typedef struct _MSVCRT_EXCEPTION_FRAME -{ - EXCEPTION_REGISTRATION_RECORD *prev; - void (*handler)(PEXCEPTION_RECORD, EXCEPTION_REGISTRATION_RECORD*, - PCONTEXT, PEXCEPTION_RECORD); - PSCOPETABLE scopetable; - int trylevel; - int _ebp; - PEXCEPTION_POINTERS xpointers; -} MSVCRT_EXCEPTION_FRAME; - -typedef struct -{ - int gs_cookie_offset; - ULONG gs_cookie_xor; - int eh_cookie_offset; - ULONG eh_cookie_xor; - SCOPETABLE entries[1]; -} SCOPETABLE_V4; - -#ifdef __i386__ - -static const SCOPETABLE_V4 *get_scopetable_v4( MSVCRT_EXCEPTION_FRAME *frame, ULONG_PTR cookie ) -{ - return (const SCOPETABLE_V4 *)((ULONG_PTR)frame->scopetable ^ cookie); -} - -#if defined(__GNUC__) -static inline void call_finally_block( void *code_block, void *base_ptr ) -{ - __asm__ __volatile__ ("movl %1,%%ebp; call *%%eax" - : : "a" (code_block), "g" (base_ptr)); -} - -static inline int call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *ebp ) -{ - int ret; - __asm__ __volatile__ ("pushl %%ebp; pushl %3; movl %2,%%ebp; call *%%eax; popl %%ebp; popl %%ebp" - : "=a" (ret) - : "0" (func), "r" (ebp), "r" (arg) - : "ecx", "edx", "memory" ); - return ret; -} -static inline int call_unwind_func( int (*func)(void), void *ebp ) -{ - int ret; - __asm__ __volatile__ ("pushl %%ebp\n\t" - "pushl %%ebx\n\t" - "pushl %%esi\n\t" - "pushl %%edi\n\t" - "movl %2,%%ebp\n\t" - "call *%0\n\t" - "popl %%edi\n\t" - "popl %%esi\n\t" - "popl %%ebx\n\t" - "popl %%ebp" - : "=a" (ret) - : "0" (func), "r" (ebp) - : "ecx", "edx", "memory" ); - return ret; -} -#elif defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4731) // Don't complain about changing ebp -void __inline call_finally_block( void *code_block, void *base_ptr ) -{ - __asm - { - mov eax, code_block - mov ebp, base_ptr - call [eax] - } -} - -int __inline call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *_ebp ) -{ - int _ret; - __asm - { - push ebp - mov eax, arg - push eax - mov ebp, _ebp - mov eax, func - call [eax] - mov _ret, eax - pop ebp - pop ebp - } - return _ret; -} -int __inline call_unwind_func( int (*func)(void), void *_ebp ) -{ - int _ret; - - __asm - { - push ebp - push ebx - push esi - push edi - mov ebp, _ebp - call dword ptr [func] - mov _ret, eax - pop edi - pop esi - pop ebx - pop ebp - } - return _ret; -} -#pragma warning(pop) -#endif - -static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec, - EXCEPTION_REGISTRATION_RECORD* frame, - PCONTEXT context, - EXCEPTION_REGISTRATION_RECORD** dispatch) -{ - if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))) - return ExceptionContinueSearch; - *dispatch = frame; - return ExceptionCollidedUnwind; -} - -void msvcrt_local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp ) -{ - EXCEPTION_REGISTRATION_RECORD reg; - const SCOPETABLE_V4 *scopetable = get_scopetable_v4( frame, *cookie ); - - TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel); - - /* Register a handler in case of a nested exception */ - reg.Handler = (PEXCEPTION_ROUTINE)MSVCRT_nested_handler; - reg.Prev = NtCurrentTeb()->NtTib.ExceptionList; - __wine_push_frame(®); - - while (frame->trylevel != -2 && frame->trylevel != trylevel) - { - int level = frame->trylevel; - frame->trylevel = scopetable->entries[level].previousTryLevel; - if (!scopetable->entries[level].lpfnFilter) - { - TRACE( "__try block cleanup level %d handler %p ebp %p\n", - level, scopetable->entries[level].lpfnHandler, ebp ); - call_unwind_func( scopetable->entries[level].lpfnHandler, ebp ); - } - } - __wine_pop_frame(®); - TRACE("unwound OK\n"); -} - -/********************************************************************* - * _except_handler4_common (MSVCRT.@) - */ -int CDECL _except_handler4_common( ULONG *cookie, void (*check_cookie)(void), - EXCEPTION_RECORD *rec, MSVCRT_EXCEPTION_FRAME *frame, - CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) -{ - int retval, trylevel; - EXCEPTION_POINTERS exceptPtrs; - const SCOPETABLE_V4 *scope_table = get_scopetable_v4( frame, *cookie ); - - TRACE( "exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x\n", - rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, - frame->handler, context, dispatcher, *cookie, scope_table, - scope_table->gs_cookie_offset, scope_table->gs_cookie_xor, - scope_table->eh_cookie_offset, scope_table->eh_cookie_xor ); - - /* FIXME: no cookie validation yet */ - - if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) - { - /* Unwinding the current frame */ - msvcrt_local_unwind4( cookie, frame, -2, &frame->_ebp ); - TRACE("unwound current frame, returning ExceptionContinueSearch\n"); - return ExceptionContinueSearch; - } - else - { - /* Hunting for handler */ - exceptPtrs.ExceptionRecord = rec; - exceptPtrs.ContextRecord = context; - *((DWORD *)frame-1) = (DWORD)&exceptPtrs; - trylevel = frame->trylevel; - - while (trylevel != -2) - { - TRACE( "level %d prev %d filter %p\n", trylevel, - scope_table->entries[trylevel].previousTryLevel, - scope_table->entries[trylevel].lpfnFilter ); - if (scope_table->entries[trylevel].lpfnFilter) - { - retval = call_filter( scope_table->entries[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp ); - - TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ? - "CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ? - "EXECUTE_HANDLER" : "CONTINUE_SEARCH"); - - if (retval == EXCEPTION_CONTINUE_EXECUTION) - return ExceptionContinueExecution; - - if (retval == EXCEPTION_EXECUTE_HANDLER) - { - /* Unwind all higher frames, this one will handle the exception */ - _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame); - msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp ); - - /* Set our trylevel to the enclosing block, and call the __finally - * code, which won't return - */ - frame->trylevel = scope_table->entries[trylevel].previousTryLevel; - TRACE("__finally block %p\n",scope_table->entries[trylevel].lpfnHandler); - call_finally_block(scope_table->entries[trylevel].lpfnHandler, &frame->_ebp); - ERR("Returned from __finally block - expect crash!\n"); - } - } - trylevel = scope_table->entries[trylevel].previousTryLevel; - } - } - TRACE("reached -2, returning ExceptionContinueSearch\n"); - return ExceptionContinueSearch; -} - -/******************************************************************* - * _local_unwind4 (MSVCRT.@) - */ -void CDECL _local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel ) -{ - msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp ); -} - -/********************************************************************* - * _seh_longjmp_unwind4 (MSVCRT.@) - */ -void __stdcall _seh_longjmp_unwind4(struct __JUMP_BUFFER *jmp) -{ - msvcrt_local_unwind4( (void *)jmp->Cookie, (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, - jmp->TryLevel, (void *)jmp->Ebp ); -} - -#endif - -/****************************************************************** - * __uncaught_exception - */ -BOOL CDECL __uncaught_exception(void) -{ - return FALSE; -} - -/* _set_security_error_handler - not exported in native msvcrt, added in msvcr70 */ -MSVCRT_security_error_handler CDECL _set_security_error_handler( - MSVCRT_security_error_handler handler ) -{ - MSVCRT_security_error_handler old = security_error_handler; - - TRACE("(%p)\n", handler); - - security_error_handler = handler; - return old; -} - -/********************************************************************* - * __DestructExceptionObject (MSVCRT.@) - */ -void CDECL __DestructExceptionObject(EXCEPTION_RECORD* rec) -{ - cxx_exception_type* info = (cxx_exception_type*)rec->ExceptionInformation[2]; - void* object = (void*)rec->ExceptionInformation[1]; - - TRACE("(%p)\n", rec); - - if (rec->ExceptionCode != CXX_EXCEPTION) return; -#ifndef __x86_64__ - if (rec->NumberParameters != 3) return; -#else - if (rec->NumberParameters != 4) return; -#endif - if (rec->ExceptionInformation[0] < CXX_FRAME_MAGIC_VC6 || - rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8) return; - - if (!info || !info->destructor) - return; - -#if defined(__i386__) - #ifdef _MSC_VER - ((void(__fastcall*)(void*))info->destructor)(object); - #else - __asm__ __volatile__("call *%0" : : "r" (info->destructor), "c" (object) : "eax", "edx", "memory"); - #endif -#elif defined(__x86_64__) - ((void(__cdecl*)(void*))(info->destructor + rec->ExceptionInformation[3]))(object); -#else - ((void(__cdecl*)(void*))info->destructor)(object); -#endif -} diff --git a/sdk/lib/crt/except/i386/cpp.s b/sdk/lib/crt/except/i386/cpp.s index a77d02aa93d..0eaa5bc64f7 100644 --- a/sdk/lib/crt/except/i386/cpp.s +++ b/sdk/lib/crt/except/i386/cpp.s @@ -5,53 +5,53 @@ .code .align 4 -MACRO(DEFINE_THISCALL_WRAPPER, cxxname, stdcallname) -EXTERN &stdcallname:PROC -PUBLIC &cxxname -&cxxname: - pop eax - push ecx - push eax - jmp &stdcallname +MACRO(DEFINE_THISCALL_ALIAS, cxxname, target) +#ifdef _USE_ML + EXTERN ___thiscall&target:PROC + ALIAS <&cxxname> = <___thiscall&target> +#else + PUBLIC cxxname + .weakref &cxxname, &target +#endif ENDM -DEFINE_THISCALL_WRAPPER ??0exception@@QAE@ABQBD@Z, _MSVCRT_exception_ctor@8 -DEFINE_THISCALL_WRAPPER ??0exception@@QAE@ABQBDH@Z, _MSVCRT_exception_ctor_noalloc@12 -DEFINE_THISCALL_WRAPPER ??0exception@@QAE@ABV0@@Z, _MSVCRT_exception_copy_ctor@8 -DEFINE_THISCALL_WRAPPER ??0exception@@QAE@XZ, _MSVCRT_exception_default_ctor@4 -DEFINE_THISCALL_WRAPPER ??1exception@@UAE@XZ, _MSVCRT_exception_dtor@4 -DEFINE_THISCALL_WRAPPER ??4exception@@QAEAAV0@ABV0@@Z, _MSVCRT_exception_opequals@8 -DEFINE_THISCALL_WRAPPER ??_Eexception@@UAEPAXI@Z, _MSVCRT_exception_vector_dtor@8 -DEFINE_THISCALL_WRAPPER ??_Gexception@@UAEPAXI@Z, _MSVCRT_exception_scalar_dtor@8 -DEFINE_THISCALL_WRAPPER ?what@exception@@UBEPBDXZ, _MSVCRT_what_exception@4 -DEFINE_THISCALL_WRAPPER ??0bad_typeid@@QAE@ABV0@@Z, _MSVCRT_bad_typeid_copy_ctor@8 -DEFINE_THISCALL_WRAPPER ??0bad_typeid@@QAE@PBD@Z, _MSVCRT_bad_typeid_ctor@8 -DEFINE_THISCALL_WRAPPER ??_Fbad_typeid@@QAEXXZ, _MSVCRT_bad_typeid_default_ctor@4 -DEFINE_THISCALL_WRAPPER ??1bad_typeid@@UAE@XZ, _MSVCRT_bad_typeid_dtor@4 -DEFINE_THISCALL_WRAPPER ??4bad_typeid@@QAEAAV0@ABV0@@Z, _MSVCRT_bad_typeid_opequals@8 -DEFINE_THISCALL_WRAPPER ??_Ebad_typeid@@UAEPAXI@Z, _MSVCRT_bad_typeid_vector_dtor@8 -DEFINE_THISCALL_WRAPPER ??_Gbad_typeid@@UAEPAXI@Z, _MSVCRT_bad_typeid_scalar_dtor@8 -DEFINE_THISCALL_WRAPPER ??0__non_rtti_object@@QAE@ABV0@@Z, _MSVCRT___non_rtti_object_copy_ctor@8 -DEFINE_THISCALL_WRAPPER ??0__non_rtti_object@@QAE@PBD@Z, _MSVCRT___non_rtti_object_ctor@8 -DEFINE_THISCALL_WRAPPER ??1__non_rtti_object@@UAE@XZ, _MSVCRT___non_rtti_object_dtor@4 -DEFINE_THISCALL_WRAPPER ??4__non_rtti_object@@QAEAAV0@ABV0@@Z, _MSVCRT___non_rtti_object_opequals@8 -DEFINE_THISCALL_WRAPPER ??_E__non_rtti_object@@UAEPAXI@Z, _MSVCRT___non_rtti_object_vector_dtor@8 -DEFINE_THISCALL_WRAPPER ??_G__non_rtti_object@@UAEPAXI@Z, _MSVCRT___non_rtti_object_scalar_dtor@8 -DEFINE_THISCALL_WRAPPER ??0bad_cast@@AAE@PBQBD@Z, _MSVCRT_bad_cast_ctor@8 -DEFINE_THISCALL_WRAPPER ??0bad_cast@@QAE@ABQBD@Z, _MSVCRT_bad_cast_ctor@8 -DEFINE_THISCALL_WRAPPER ??0bad_cast@@QAE@ABV0@@Z, _MSVCRT_bad_cast_copy_ctor@8 -DEFINE_THISCALL_WRAPPER ??0bad_cast@@QAE@PBD@Z, _MSVCRT_bad_cast_ctor_charptr@8 -DEFINE_THISCALL_WRAPPER ??_Fbad_cast@@QAEXXZ, _MSVCRT_bad_cast_default_ctor@4 -DEFINE_THISCALL_WRAPPER ??1bad_cast@@UAE@XZ, _MSVCRT_bad_cast_dtor@4 -DEFINE_THISCALL_WRAPPER ??4bad_cast@@QAEAAV0@ABV0@@Z, _MSVCRT_bad_cast_opequals@8 -DEFINE_THISCALL_WRAPPER ??_Ebad_cast@@UAEPAXI@Z, _MSVCRT_bad_cast_vector_dtor@8 -DEFINE_THISCALL_WRAPPER ??_Gbad_cast@@UAEPAXI@Z, _MSVCRT_bad_cast_scalar_dtor@8 -DEFINE_THISCALL_WRAPPER ??8type_info@@QBEHABV0@@Z, _MSVCRT_type_info_opequals_equals@8 -DEFINE_THISCALL_WRAPPER ??9type_info@@QBEHABV0@@Z, _MSVCRT_type_info_opnot_equals@8 -DEFINE_THISCALL_WRAPPER ?before@type_info@@QBEHABV1@@Z, _MSVCRT_type_info_before@8 -DEFINE_THISCALL_WRAPPER ??1type_info@@UAE@XZ, _MSVCRT_type_info_dtor@4 -DEFINE_THISCALL_WRAPPER ?name@type_info@@QBEPBDXZ, _MSVCRT_type_info_name@4 -DEFINE_THISCALL_WRAPPER ?raw_name@type_info@@QBEPBDXZ, _MSVCRT_type_info_raw_name@4 +DEFINE_THISCALL_ALIAS ??0exception@@QAE@ABQBD@Z, _MSVCRT_exception_ctor +DEFINE_THISCALL_ALIAS ??0exception@@QAE@ABQBDH@Z, _MSVCRT_exception_ctor_noalloc +DEFINE_THISCALL_ALIAS ??0exception@@QAE@ABV0@@Z, _MSVCRT_exception_copy_ctor +DEFINE_THISCALL_ALIAS ??0exception@@QAE@XZ, _MSVCRT_exception_default_ctor +DEFINE_THISCALL_ALIAS ??1exception@@UAE@XZ, _MSVCRT_exception_dtor +DEFINE_THISCALL_ALIAS ??4exception@@QAEAAV0@ABV0@@Z, _MSVCRT_exception_opequals +DEFINE_THISCALL_ALIAS ??_Eexception@@UAEPAXI@Z, _MSVCRT_exception_vector_dtor +DEFINE_THISCALL_ALIAS ??_Gexception@@UAEPAXI@Z, _MSVCRT_exception_scalar_dtor +DEFINE_THISCALL_ALIAS ?what@exception@@UBEPBDXZ, _MSVCRT_what_exception +DEFINE_THISCALL_ALIAS ??0bad_typeid@@QAE@ABV0@@Z, _MSVCRT_bad_typeid_copy_ctor +DEFINE_THISCALL_ALIAS ??0bad_typeid@@QAE@PBD@Z, _MSVCRT_bad_typeid_ctor +DEFINE_THISCALL_ALIAS ??_Fbad_typeid@@QAEXXZ, _MSVCRT_bad_typeid_default_ctor +DEFINE_THISCALL_ALIAS ??1bad_typeid@@UAE@XZ, _MSVCRT_bad_typeid_dtor +DEFINE_THISCALL_ALIAS ??4bad_typeid@@QAEAAV0@ABV0@@Z, _MSVCRT_bad_typeid_opequals +DEFINE_THISCALL_ALIAS ??_Ebad_typeid@@UAEPAXI@Z, _MSVCRT_bad_typeid_vector_dtor +DEFINE_THISCALL_ALIAS ??_Gbad_typeid@@UAEPAXI@Z, _MSVCRT_bad_typeid_scalar_dtor +DEFINE_THISCALL_ALIAS ??0__non_rtti_object@@QAE@ABV0@@Z, _MSVCRT___non_rtti_object_copy_ctor +DEFINE_THISCALL_ALIAS ??0__non_rtti_object@@QAE@PBD@Z, _MSVCRT___non_rtti_object_ctor +DEFINE_THISCALL_ALIAS ??1__non_rtti_object@@UAE@XZ, _MSVCRT___non_rtti_object_dtor +DEFINE_THISCALL_ALIAS ??4__non_rtti_object@@QAEAAV0@ABV0@@Z, _MSVCRT___non_rtti_object_opequals +DEFINE_THISCALL_ALIAS ??_E__non_rtti_object@@UAEPAXI@Z, _MSVCRT___non_rtti_object_vector_dtor +DEFINE_THISCALL_ALIAS ??_G__non_rtti_object@@UAEPAXI@Z, _MSVCRT___non_rtti_object_scalar_dtor +DEFINE_THISCALL_ALIAS ??0bad_cast@@AAE@PBQBD@Z, _MSVCRT_bad_cast_ctor +DEFINE_THISCALL_ALIAS ??0bad_cast@@QAE@ABQBD@Z, _MSVCRT_bad_cast_ctor +DEFINE_THISCALL_ALIAS ??0bad_cast@@QAE@ABV0@@Z, _MSVCRT_bad_cast_copy_ctor +DEFINE_THISCALL_ALIAS ??0bad_cast@@QAE@PBD@Z, _MSVCRT_bad_cast_ctor_charptr +DEFINE_THISCALL_ALIAS ??_Fbad_cast@@QAEXXZ, _MSVCRT_bad_cast_default_ctor +DEFINE_THISCALL_ALIAS ??1bad_cast@@UAE@XZ, _MSVCRT_bad_cast_dtor +DEFINE_THISCALL_ALIAS ??4bad_cast@@QAEAAV0@ABV0@@Z, _MSVCRT_bad_cast_opequals +DEFINE_THISCALL_ALIAS ??_Ebad_cast@@UAEPAXI@Z, _MSVCRT_bad_cast_vector_dtor +DEFINE_THISCALL_ALIAS ??_Gbad_cast@@UAEPAXI@Z, _MSVCRT_bad_cast_scalar_dtor +DEFINE_THISCALL_ALIAS ??8type_info@@QBEHABV0@@Z, _MSVCRT_type_info_opequals_equals +DEFINE_THISCALL_ALIAS ??9type_info@@QBEHABV0@@Z, _MSVCRT_type_info_opnot_equals +DEFINE_THISCALL_ALIAS ?before@type_info@@QBEHABV1@@Z, _MSVCRT_type_info_before +DEFINE_THISCALL_ALIAS ??1type_info@@UAE@XZ, _MSVCRT_type_info_dtor +DEFINE_THISCALL_ALIAS ?name@type_info@@QBEPBDXZ, _MSVCRT_type_info_name +DEFINE_THISCALL_ALIAS ?raw_name@type_info@@QBEPBDXZ, _MSVCRT_type_info_raw_name #undef _MSVCRT_ @@ -108,5 +108,63 @@ DEFINE_ALIAS ?terminate@@YAXXZ, _MSVCRT_terminate, PROC DEFINE_ALIAS ?unexpected@@YAXXZ, _MSVCRT_unexpected, PROC +// void call_copy_ctor( void *func, void *this, void *src, int has_vbase ); +PUBLIC _call_copy_ctor +_call_copy_ctor: + push ebp + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET ebp, 0 + mov ebp, esp + CFI_DEF_CFA_REGISTER ebp + push 1 + mov ecx, [ebp + 12] + push dword ptr [ebp + 16] + call dword ptr [ebp + 8] + leave + CFI_DEF_CFA esp, 4 + CFI_SAME_VALUE ebp + ret + +// void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr ); +PUBLIC _continue_after_catch +_continue_after_catch: + mov edx, [esp + 4] + mov eax, [esp + 8] + mov esp, [edx - 4] + lea ebp, [edx + 12] + jmp eax + +// void DECLSPEC_NORETURN call_finally_block( void *code_block, void *base_ptr ); +PUBLIC _call_finally_block +_call_finally_block: + mov ebp, [esp +8] + jmp dword ptr [esp + 4] + +// int call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *ebp ); +PUBLIC _call_filter +_call_filter: + push ebp + push [esp + 12] + mov ebp, [esp + 20] + call dword ptr [esp + 12] + pop ebp + pop ebp + ret + +// void *call_handler( void * (*func)(void), void *ebp ); +PUBLIC _call_handler +_call_handler: + push ebp + push ebx + push esi + push edi + mov ebp, [esp + 24] + call dword ptr [esp + 29] + pop edi + pop esi + pop ebx + pop ebp + ret + END diff --git a/sdk/lib/crt/except/i386/unwind.c b/sdk/lib/crt/except/i386/unwind.c deleted file mode 100644 index f2317bd826b..00000000000 --- a/sdk/lib/crt/except/i386/unwind.c +++ /dev/null @@ -1,39 +0,0 @@ -#define WIN32_NO_STATUS -#include -#define NTOS_MODE_USER -#include -#include -#include -#include - -/* VC++ extensions to Win32 SEH */ -typedef struct _SCOPETABLE -{ - int previousTryLevel; - int (*lpfnFilter)(PEXCEPTION_POINTERS); - int (*lpfnHandler)(void); -} SCOPETABLE, *PSCOPETABLE; - -typedef struct _MSVCRT_EXCEPTION_FRAME -{ - PEXCEPTION_REGISTRATION_RECORD *prev; - void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION_RECORD, - PCONTEXT, PEXCEPTION_RECORD); - PSCOPETABLE scopetable; - int trylevel; - int _ebp; - PEXCEPTION_POINTERS xpointers; -} MSVCRT_EXCEPTION_FRAME; - -void -_local_unwind2(MSVCRT_EXCEPTION_FRAME *RegistrationFrame, - LONG TryLevel); - -/* - * @implemented -*/ - -void __stdcall _seh_longjmp_unwind(_JUMP_BUFFER *jmp) -{ - _local_unwind2((MSVCRT_EXCEPTION_FRAME*) jmp->Registration, jmp->TryLevel); -} diff --git a/sdk/lib/crt/except/matherr.c b/sdk/lib/crt/except/matherr.c index da94b71ffc4..d7e6c5bf35b 100644 --- a/sdk/lib/crt/except/matherr.c +++ b/sdk/lib/crt/except/matherr.c @@ -47,19 +47,3 @@ void CDECL __setusermatherr(MSVCRT_matherr_func func) MSVCRT_default_matherr_func = func; TRACE(":new matherr handler %p\n", func); } - - -#define _FPIEEE_RECORD void - -/* - * @unimplemented - */ -int _fpieee_flt( - unsigned long exception_code, - struct _EXCEPTION_POINTERS* ExceptionPointer, - int (*handler)(_FPIEEE_RECORD*) - ) -{ - FIXME("Unimplemented!\n"); - return 0; -} diff --git a/sdk/lib/crt/except/xcptfil.c b/sdk/lib/crt/except/xcptfil.c deleted file mode 100644 index c5b8d1d1e76..00000000000 --- a/sdk/lib/crt/except/xcptfil.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include "internal/wine/msvcrt.h" -#include "internal/wine/cppexcept.h" - -typedef void (*sighandler_t)(int); -static sighandler_t sighandlers[NSIG] = { SIG_DFL }; - -/* The exception codes are actually NTSTATUS values */ -static const struct -{ - NTSTATUS status; - int signal; -} float_exception_map[] = { - { EXCEPTION_FLT_DENORMAL_OPERAND, _FPE_DENORMAL }, - { EXCEPTION_FLT_DIVIDE_BY_ZERO, _FPE_ZERODIVIDE }, - { EXCEPTION_FLT_INEXACT_RESULT, _FPE_INEXACT }, - { EXCEPTION_FLT_INVALID_OPERATION, _FPE_INVALID }, - { EXCEPTION_FLT_OVERFLOW, _FPE_OVERFLOW }, - { EXCEPTION_FLT_STACK_CHECK, _FPE_STACKOVERFLOW }, - { EXCEPTION_FLT_UNDERFLOW, _FPE_UNDERFLOW }, -}; - -/* - * @implemented - */ -int CDECL -_XcptFilter(NTSTATUS ExceptionCode, - struct _EXCEPTION_POINTERS * except) -{ - LONG ret = EXCEPTION_CONTINUE_SEARCH; - sighandler_t handler; - - if (!except || !except->ExceptionRecord) - return EXCEPTION_CONTINUE_SEARCH; - - switch (except->ExceptionRecord->ExceptionCode) - { - case EXCEPTION_ACCESS_VIOLATION: - if ((handler = sighandlers[SIGSEGV]) != SIG_DFL) - { - if (handler != SIG_IGN) - { - sighandlers[SIGSEGV] = SIG_DFL; - handler(SIGSEGV); - } - ret = EXCEPTION_CONTINUE_EXECUTION; - } - break; - /* According to msdn, - * the FPE signal handler takes as a second argument the type of - * floating point exception. - */ - case EXCEPTION_FLT_DENORMAL_OPERAND: - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - case EXCEPTION_FLT_INEXACT_RESULT: - case EXCEPTION_FLT_INVALID_OPERATION: - case EXCEPTION_FLT_OVERFLOW: - case EXCEPTION_FLT_STACK_CHECK: - case EXCEPTION_FLT_UNDERFLOW: - if ((handler = sighandlers[SIGFPE]) != SIG_DFL) - { - if (handler != SIG_IGN) - { - unsigned int i; - int float_signal = _FPE_INVALID; - - sighandlers[SIGFPE] = SIG_DFL; - for (i = 0; i < sizeof(float_exception_map) / - sizeof(float_exception_map[0]); i++) - { - if (float_exception_map[i].status == - except->ExceptionRecord->ExceptionCode) - { - float_signal = float_exception_map[i].signal; - break; - } - } - ((float_handler)handler)(SIGFPE, float_signal); - } - ret = EXCEPTION_CONTINUE_EXECUTION; - } - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - case EXCEPTION_PRIV_INSTRUCTION: - if ((handler = sighandlers[SIGILL]) != SIG_DFL) - { - if (handler != SIG_IGN) - { - sighandlers[SIGILL] = SIG_DFL; - handler(SIGILL); - } - ret = EXCEPTION_CONTINUE_EXECUTION; - } - break; - } - return ret; -} - diff --git a/sdk/lib/crt/include/internal/wine_msc.h b/sdk/lib/crt/include/internal/wine_msc.h index d7c799a09f2..ebe023b48d0 100644 --- a/sdk/lib/crt/include/internal/wine_msc.h +++ b/sdk/lib/crt/include/internal/wine_msc.h @@ -1,50 +1,100 @@ -#define DEFINE_THISCALL_WRAPPER(func, args) \ - void __declspec(naked) __thiscall_ ## func (void) \ - { \ - __asm { pop eax } \ - __asm { push ecx } \ - __asm { push eax } \ - __asm { jmp func } \ - } - -exception * __stdcall MSVCRT_exception_ctor(exception * _this, const char ** name); -exception * __stdcall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc); -exception * __stdcall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs); -exception * __stdcall MSVCRT_exception_default_ctor(exception * _this); -void __stdcall MSVCRT_exception_dtor(exception * _this); -exception * __stdcall MSVCRT_exception_opequals(exception * _this, const exception * rhs); -void * __stdcall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags); -void * __stdcall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags); -const char * __stdcall MSVCRT_what_exception(exception * _this); -bad_typeid * __stdcall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs); -bad_typeid * __stdcall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name); -bad_typeid * __stdcall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this); -void __stdcall MSVCRT_bad_typeid_dtor(bad_typeid * _this); -bad_typeid * __stdcall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs); -void * __stdcall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags); -void * __stdcall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags); -__non_rtti_object * __stdcall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this, const __non_rtti_object * rhs); -__non_rtti_object * __stdcall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this, const char * name); -void __stdcall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this); -__non_rtti_object * __stdcall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this, const __non_rtti_object *rhs); -void * __stdcall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags); -void * __stdcall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags); -bad_cast * __stdcall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name); -bad_cast * __stdcall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs); -bad_cast * __stdcall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name); -bad_cast * __stdcall MSVCRT_bad_cast_default_ctor(bad_cast * _this); -void __stdcall MSVCRT_bad_cast_dtor(bad_cast * _this); -bad_cast * __stdcall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs); -void * __stdcall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags); -void * __stdcall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags); -int __stdcall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs); -int __stdcall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs); -int __stdcall MSVCRT_type_info_before(type_info * _this, const type_info * rhs); -void __stdcall MSVCRT_type_info_dtor(type_info * _this); -const char * __stdcall MSVCRT_type_info_name(type_info * _this); -const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this); -void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags); - -#define __ASM_VTABLE(name,funcs) -//void *MSVCRT_ ## name ##_vtable[] = +exception * __thiscall MSVCRT_exception_ctor(exception * _this, const char ** name); +exception * __thiscall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc); +exception * __thiscall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs); +exception * __thiscall MSVCRT_exception_default_ctor(exception * _this); +void __thiscall MSVCRT_exception_dtor(exception * _this); +exception * __thiscall MSVCRT_exception_opequals(exception * _this, const exception * rhs); +void * __thiscall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags); +void * __thiscall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags); +const char * __thiscall MSVCRT_what_exception(exception * _this); +bad_typeid * __thiscall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs); +bad_typeid * __thiscall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name); +bad_typeid * __thiscall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this); +void __thiscall MSVCRT_bad_typeid_dtor(bad_typeid * _this); +bad_typeid * __thiscall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs); +void * __thiscall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags); +void * __thiscall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags); +__non_rtti_object * __thiscall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this, const __non_rtti_object * rhs); +__non_rtti_object * __thiscall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this, const char * name); +void __thiscall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this); +__non_rtti_object * __thiscall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this, const __non_rtti_object *rhs); +void * __thiscall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags); +void * __thiscall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags); +bad_cast * __thiscall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name); +bad_cast * __thiscall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs); +bad_cast * __thiscall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name); +bad_cast * __thiscall MSVCRT_bad_cast_default_ctor(bad_cast * _this); +void __thiscall MSVCRT_bad_cast_dtor(bad_cast * _this); +bad_cast * __thiscall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs); +void * __thiscall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags); +void * __thiscall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags); +int __thiscall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs); +int __thiscall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs); +int __thiscall MSVCRT_type_info_before(type_info * _this, const type_info * rhs); +void __thiscall MSVCRT_type_info_dtor(type_info * _this); +const char * __thiscall MSVCRT_type_info_name(type_info * _this); +const char * __thiscall MSVCRT_type_info_raw_name(type_info * _this); +void * __thiscall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags); +#if _MSVCR_VER >= 80 +bad_alloc* __thiscall MSVCRT_bad_alloc_copy_ctor(bad_alloc* _this, const bad_alloc* rhs); +bad_alloc* __thiscall MSVCRT_bad_alloc_copy_ctor(bad_alloc* _this, const bad_alloc* rhs); +void __thiscall MSVCRT_bad_alloc_dtor(bad_alloc* _this); +#endif /* _MSVCR_VER >= 80 */ +#if _MSVCR_VER >= 100 +scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor_name( + scheduler_resource_allocation_error* this, const char* name, HRESULT hr); +scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor( + scheduler_resource_allocation_error* this, HRESULT hr); +scheduler_resource_allocation_error* __thiscall MSVCRT_scheduler_resource_allocation_error_copy_ctor( + scheduler_resource_allocation_error* this, + const scheduler_resource_allocation_error* rhs); +HRESULT __thiscall scheduler_resource_allocation_error_get_error_code( + const scheduler_resource_allocation_error* this); +void __thiscall MSVCRT_scheduler_resource_allocation_error_dtor( + scheduler_resource_allocation_error* this); +improper_lock* __thiscall improper_lock_ctor_str(improper_lock* this, const char* str); +improper_lock* __thiscall improper_lock_ctor(improper_lock* this); +improper_lock* __thiscall MSVCRT_improper_lock_copy_ctor(improper_lock* _this, const improper_lock* rhs); +void __thiscall MSVCRT_improper_lock_dtor(improper_lock* _this); +invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor_str( + invalid_scheduler_policy_key* this, const char* str); +invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor( + invalid_scheduler_policy_key* this); +invalid_scheduler_policy_key* __thiscall MSVCRT_invalid_scheduler_policy_key_copy_ctor( + invalid_scheduler_policy_key* _this, const invalid_scheduler_policy_key* rhs); +void __thiscall MSVCRT_invalid_scheduler_policy_key_dtor( + invalid_scheduler_policy_key* _this); +invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor_str( + invalid_scheduler_policy_value* this, const char* str); +invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor( + invalid_scheduler_policy_value* this); +invalid_scheduler_policy_value* __thiscall MSVCRT_invalid_scheduler_policy_value_copy_ctor( + invalid_scheduler_policy_value* _this, const invalid_scheduler_policy_value* rhs); +void __thiscall MSVCRT_invalid_scheduler_policy_value_dtor( + invalid_scheduler_policy_value* _this); +invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor_str( + invalid_scheduler_policy_thread_specification* this, const char* str); +invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor( + invalid_scheduler_policy_thread_specification* this); +invalid_scheduler_policy_thread_specification* __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_copy_ctor( + invalid_scheduler_policy_thread_specification* _this, const invalid_scheduler_policy_thread_specification* rhs); +void __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_dtor( + invalid_scheduler_policy_thread_specification* _this); +improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor_str( + improper_scheduler_attach* this, const char* str); +improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor( + improper_scheduler_attach* this); +improper_scheduler_attach* __thiscall MSVCRT_improper_scheduler_attach_copy_ctor( + improper_scheduler_attach* _this, const improper_scheduler_attach* rhs); +void __thiscall MSVCRT_improper_scheduler_attach_dtor( + improper_scheduler_attach* _this); +improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor_str( + improper_scheduler_detach* this, const char* str); +improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor( + improper_scheduler_detach* this); +improper_scheduler_detach* __thiscall MSVCRT_improper_scheduler_detach_copy_ctor( + improper_scheduler_detach* _this, const improper_scheduler_detach* rhs); +void __thiscall MSVCRT_improper_scheduler_detach_dtor( + improper_scheduler_detach* _this); +#endif diff --git a/sdk/lib/crt/wine/cpp.c b/sdk/lib/crt/wine/cpp.c new file mode 100644 index 00000000000..4b12b2dfbe1 --- /dev/null +++ b/sdk/lib/crt/wine/cpp.c @@ -0,0 +1,2189 @@ +/* + * msvcrt.dll C++ objects + * + * Copyright 2000 Jon Griffiths + * Copyright 2003, 2004 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + */ + +#include "config.h" +#include "wine/port.h" + +#include + +#include "windef.h" +#include "winternl.h" +#include "wine/exception.h" +#include "wine/debug.h" +#include "msvcrt.h" +#include "cppexcept.h" +#include "mtdll.h" +#include "cxx.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); + +struct __type_info_node +{ + void *memPtr; + struct __type_info_node* next; +}; + +typedef exception bad_cast; +typedef exception bad_typeid; +typedef exception __non_rtti_object; + +extern const vtable_ptr MSVCRT_exception_vtable; +extern const vtable_ptr MSVCRT_bad_typeid_vtable; +extern const vtable_ptr MSVCRT_bad_cast_vtable; +extern const vtable_ptr MSVCRT___non_rtti_object_vtable; +extern const vtable_ptr MSVCRT_type_info_vtable; + +/* get the vtable pointer for a C++ object */ +static inline const vtable_ptr *get_vtable( void *obj ) +{ + return *(const vtable_ptr **)obj; +} + +static inline const rtti_object_locator *get_obj_locator( void *cppobj ) +{ + const vtable_ptr *vtable = get_vtable( cppobj ); + return (const rtti_object_locator *)vtable[-1]; +} + +#ifndef __x86_64__ +static void dump_obj_locator( const rtti_object_locator *ptr ) +{ + int i; + const rtti_object_hierarchy *h = ptr->type_hierarchy; + + TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n", + ptr, ptr->signature, ptr->base_class_offset, ptr->flags, + ptr->type_descriptor, dbgstr_type_info(ptr->type_descriptor), ptr->type_hierarchy ); + TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n", + h->signature, h->attributes, h->array_len, h->base_classes ); + for (i = 0; i < h->array_len; i++) + { + TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n", + h->base_classes->bases[i], + h->base_classes->bases[i]->num_base_classes, + h->base_classes->bases[i]->offsets.this_offset, + h->base_classes->bases[i]->offsets.vbase_descr, + h->base_classes->bases[i]->offsets.vbase_offset, + h->base_classes->bases[i]->attributes, + h->base_classes->bases[i]->type_descriptor, + dbgstr_type_info(h->base_classes->bases[i]->type_descriptor) ); + } +} + +#else + +static void dump_obj_locator( const rtti_object_locator *ptr ) +{ + int i; + char *base = ptr->signature == 0 ? RtlPcToFileHeader((void*)ptr, (void**)&base) : (char*)ptr - ptr->object_locator; + const rtti_object_hierarchy *h = (const rtti_object_hierarchy*)(base + ptr->type_hierarchy); + const type_info *type_descriptor = (const type_info*)(base + ptr->type_descriptor); + + TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n", + ptr, ptr->signature, ptr->base_class_offset, ptr->flags, + type_descriptor, dbgstr_type_info(type_descriptor), h ); + TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n", + h->signature, h->attributes, h->array_len, base + h->base_classes ); + for (i = 0; i < h->array_len; i++) + { + const rtti_base_descriptor *bases = (rtti_base_descriptor*)(base + + ((const rtti_base_array*)(base + h->base_classes))->bases[i]); + + TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n", + bases, + bases->num_base_classes, + bases->offsets.this_offset, + bases->offsets.vbase_descr, + bases->offsets.vbase_offset, + bases->attributes, + base + bases->type_descriptor, + dbgstr_type_info((const type_info*)(base + bases->type_descriptor)) ); + } +} +#endif + +/* Internal common ctor for exception */ +static void EXCEPTION_ctor(exception *_this, const char** name) +{ + _this->vtable = &MSVCRT_exception_vtable; + if (*name) + { + unsigned int name_len = strlen(*name) + 1; + _this->name = MSVCRT_malloc(name_len); + memcpy(_this->name, *name, name_len); + _this->do_free = TRUE; + } + else + { + _this->name = NULL; + _this->do_free = FALSE; + } +} + +#ifdef __REACTOS__ +#include +#endif /* __REACTOS__ */ + +/****************************************************************** + * ??0exception@@QAE@ABQBD@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8) +exception * __thiscall MSVCRT_exception_ctor(exception * _this, const char ** name) +{ + TRACE("(%p,%s)\n", _this, *name); + EXCEPTION_ctor(_this, name); + return _this; +} + +/****************************************************************** + * ??0exception@@QAE@ABQBDH@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12) +exception * __thiscall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc) +{ + TRACE("(%p,%s)\n", _this, *name); + _this->vtable = &MSVCRT_exception_vtable; + _this->name = *name; + _this->do_free = FALSE; + return _this; +} + +/****************************************************************** + * ??0exception@@QAE@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8) +exception * __thiscall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs) +{ + TRACE("(%p,%p)\n", _this, rhs); + + if (!rhs->do_free) + { + _this->vtable = &MSVCRT_exception_vtable; + _this->name = rhs->name; + _this->do_free = FALSE; + } + else + EXCEPTION_ctor(_this, (const char**)&rhs->name); + TRACE("name = %s\n", _this->name); + return _this; +} + +/****************************************************************** + * ??0exception@@QAE@XZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4) +exception * __thiscall MSVCRT_exception_default_ctor(exception * _this) +{ + static const char* empty = NULL; + + TRACE("(%p)\n", _this); + EXCEPTION_ctor(_this, &empty); + return _this; +} + +/****************************************************************** + * ??1exception@@UAE@XZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4) +void __thiscall MSVCRT_exception_dtor(exception * _this) +{ + TRACE("(%p)\n", _this); + _this->vtable = &MSVCRT_exception_vtable; + if (_this->do_free) MSVCRT_free(_this->name); +} + +/****************************************************************** + * ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8) +exception * __thiscall MSVCRT_exception_opequals(exception * _this, const exception * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + if (_this != rhs) + { + MSVCRT_exception_dtor(_this); + MSVCRT_exception_copy_ctor(_this, rhs); + } + TRACE("name = %s\n", _this->name); + return _this; +} + +/****************************************************************** + * ??_Eexception@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8) +void * __thiscall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + if (flags & 2) + { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)_this - 1; + + for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i); + MSVCRT_operator_delete(ptr); + } + else + { + MSVCRT_exception_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + } + return _this; +} + +/****************************************************************** + * ??_Gexception@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8) +void * __thiscall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + MSVCRT_exception_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + return _this; +} + +/****************************************************************** + * ?what@exception@@UBEPBDXZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4) +const char * __thiscall MSVCRT_what_exception(exception * _this) +{ + TRACE("(%p) returning %s\n", _this, _this->name); + return _this->name ? _this->name : "Unknown exception"; +} + +/****************************************************************** + * ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8) +bad_typeid * __thiscall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_bad_typeid_vtable; + return _this; +} + +/****************************************************************** + * ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8) +bad_typeid * __thiscall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name) +{ + TRACE("(%p %s)\n", _this, name); + EXCEPTION_ctor(_this, &name); + _this->vtable = &MSVCRT_bad_typeid_vtable; + return _this; +} + +/****************************************************************** + * ??_Fbad_typeid@@QAEXXZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4) +bad_typeid * __thiscall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this) +{ + return MSVCRT_bad_typeid_ctor( _this, "bad typeid" ); +} + +/****************************************************************** + * ??1bad_typeid@@UAE@XZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4) +void __thiscall MSVCRT_bad_typeid_dtor(bad_typeid * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +/****************************************************************** + * ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8) +bad_typeid * __thiscall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_opequals(_this, rhs); + return _this; +} + +/****************************************************************** + * ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8) +void * __thiscall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + if (flags & 2) + { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)_this - 1; + + for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i); + MSVCRT_operator_delete(ptr); + } + else + { + MSVCRT_bad_typeid_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + } + return _this; +} + +/****************************************************************** + * ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8) +void * __thiscall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + MSVCRT_bad_typeid_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + return _this; +} + +/****************************************************************** + * ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8) +__non_rtti_object * __thiscall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this, + const __non_rtti_object * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_bad_typeid_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT___non_rtti_object_vtable; + return _this; +} + +/****************************************************************** + * ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8) +__non_rtti_object * __thiscall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this, + const char * name) +{ + TRACE("(%p %s)\n", _this, name); + EXCEPTION_ctor(_this, &name); + _this->vtable = &MSVCRT___non_rtti_object_vtable; + return _this; +} + +/****************************************************************** + * ??1__non_rtti_object@@UAE@XZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4) +void __thiscall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_bad_typeid_dtor(_this); +} + +/****************************************************************** + * ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8) +__non_rtti_object * __thiscall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this, + const __non_rtti_object *rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_bad_typeid_opequals(_this, rhs); + return _this; +} + +/****************************************************************** + * ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8) +void * __thiscall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + if (flags & 2) + { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)_this - 1; + + for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i); + MSVCRT_operator_delete(ptr); + } + else + { + MSVCRT___non_rtti_object_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + } + return _this; +} + +/****************************************************************** + * ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8) +void * __thiscall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + MSVCRT___non_rtti_object_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + return _this; +} + +/****************************************************************** + * ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@) + * ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8) +bad_cast * __thiscall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name) +{ + TRACE("(%p %s)\n", _this, *name); + EXCEPTION_ctor(_this, name); + _this->vtable = &MSVCRT_bad_cast_vtable; + return _this; +} + +/****************************************************************** + * ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8) +bad_cast * __thiscall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_bad_cast_vtable; + return _this; +} + +/****************************************************************** + * ??0bad_cast@@QAE@PBD@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8) +bad_cast * __thiscall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name) +{ + TRACE("(%p %s)\n", _this, name); + EXCEPTION_ctor(_this, &name); + _this->vtable = &MSVCRT_bad_cast_vtable; + return _this; +} + +/****************************************************************** + * ??_Fbad_cast@@QAEXXZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4) +bad_cast * __thiscall MSVCRT_bad_cast_default_ctor(bad_cast * _this) +{ + return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" ); +} + +/****************************************************************** + * ??1bad_cast@@UAE@XZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4) +void __thiscall MSVCRT_bad_cast_dtor(bad_cast * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +/****************************************************************** + * ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8) +bad_cast * __thiscall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_opequals(_this, rhs); + return _this; +} + +/****************************************************************** + * ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8) +void * __thiscall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + if (flags & 2) + { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)_this - 1; + + for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i); + MSVCRT_operator_delete(ptr); + } + else + { + MSVCRT_bad_cast_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + } + return _this; +} + +/****************************************************************** + * ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8) +void * __thiscall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + MSVCRT_bad_cast_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + return _this; +} + +/****************************************************************** + * ??8type_info@@QBEHABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8) +int __thiscall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs) +{ + int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1); + TRACE("(%p %p) returning %d\n", _this, rhs, ret); + return ret; +} + +/****************************************************************** + * ??9type_info@@QBEHABV0@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8) +int __thiscall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs) +{ + int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1); + TRACE("(%p %p) returning %d\n", _this, rhs, ret); + return ret; +} + +/****************************************************************** + * ?before@type_info@@QBEHABV1@@Z (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8) +int __thiscall MSVCRT_type_info_before(type_info * _this, const type_info * rhs) +{ + int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0; + TRACE("(%p %p) returning %d\n", _this, rhs, ret); + return ret; +} + +/****************************************************************** + * ??1type_info@@UAE@XZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4) +void __thiscall MSVCRT_type_info_dtor(type_info * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_free(_this->name); +} + +/****************************************************************** + * ?name@type_info@@QBEPBDXZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4) +const char * __thiscall MSVCRT_type_info_name(type_info * _this) +{ + if (!_this->name) + { + /* Create and set the demangled name */ + /* Note: mangled name in type_info struct always starts with a '.', while + * it isn't valid for mangled name. + * Is this '.' really part of the mangled name, or has it some other meaning ? + */ + char* name = __unDName(0, _this->mangled + 1, 0, + MSVCRT_malloc, MSVCRT_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE); + if (name) + { + unsigned int len = strlen(name); + + /* It seems _unDName may leave blanks at the end of the demangled name */ + while (len && name[--len] == ' ') + name[len] = '\0'; + + if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL)) + { + /* Another thread set this member since we checked above - use it */ + MSVCRT_free(name); + } + } + } + TRACE("(%p) returning %s\n", _this, _this->name); + return _this->name; +} + +/****************************************************************** + * ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@) + */ +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4) +const char * __thiscall MSVCRT_type_info_raw_name(type_info * _this) +{ + TRACE("(%p) returning %s\n", _this, _this->mangled); + return _this->mangled; +} + +/* Unexported */ +DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8) +void * __thiscall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags) +{ + TRACE("(%p %x)\n", _this, flags); + if (flags & 2) + { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)_this - 1; + + for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i); + MSVCRT_operator_delete(ptr); + } + else + { + MSVCRT_type_info_dtor(_this); + if (flags & 1) MSVCRT_operator_delete(_this); + } + return _this; +} + +#if _MSVCR_VER >= 80 + +typedef exception bad_alloc; +extern const vtable_ptr MSVCRT_bad_alloc_vtable; + +static void bad_alloc_ctor(bad_alloc *this, const char **name) +{ + MSVCRT_exception_ctor(this, name); + this->vtable = &MSVCRT_bad_alloc_vtable; +} + +/* bad_alloc class implementation */ +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_alloc_copy_ctor,8) +bad_alloc * __thiscall MSVCRT_bad_alloc_copy_ctor(bad_alloc * _this, const bad_alloc * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_bad_alloc_vtable; + return _this; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_bad_alloc_dtor,4) +void __thiscall MSVCRT_bad_alloc_dtor(bad_alloc * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +#endif /* _MSVCR_VER >= 80 */ + +#if _MSVCR_VER >= 100 + +typedef struct { + exception e; + HRESULT hr; +} scheduler_resource_allocation_error; +extern const vtable_ptr MSVCRT_scheduler_resource_allocation_error_vtable; + +/* ??0scheduler_resource_allocation_error@Concurrency@@QAE@PBDJ@Z */ +/* ??0scheduler_resource_allocation_error@Concurrency@@QEAA@PEBDJ@Z */ +DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_ctor_name, 12) +scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor_name( + scheduler_resource_allocation_error *this, const char *name, HRESULT hr) +{ + TRACE("(%p %s %x)\n", this, wine_dbgstr_a(name), hr); + MSVCRT_exception_ctor(&this->e, &name); + this->e.vtable = &MSVCRT_scheduler_resource_allocation_error_vtable; + this->hr = hr; + return this; +} + +/* ??0scheduler_resource_allocation_error@Concurrency@@QAE@J@Z */ +/* ??0scheduler_resource_allocation_error@Concurrency@@QEAA@J@Z */ +DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_ctor, 8) +scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor( + scheduler_resource_allocation_error *this, HRESULT hr) +{ + return scheduler_resource_allocation_error_ctor_name(this, NULL, hr); +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_scheduler_resource_allocation_error_copy_ctor,8) +scheduler_resource_allocation_error* __thiscall MSVCRT_scheduler_resource_allocation_error_copy_ctor( + scheduler_resource_allocation_error *this, + const scheduler_resource_allocation_error *rhs) +{ + TRACE("(%p,%p)\n", this, rhs); + + if (!rhs->e.do_free) + memcpy(this, rhs, sizeof(*this)); + else + scheduler_resource_allocation_error_ctor_name(this, rhs->e.name, rhs->hr); + return this; +} + +/* ?get_error_code@scheduler_resource_allocation_error@Concurrency@@QBEJXZ */ +/* ?get_error_code@scheduler_resource_allocation_error@Concurrency@@QEBAJXZ */ +DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_get_error_code, 4) +HRESULT __thiscall scheduler_resource_allocation_error_get_error_code( + const scheduler_resource_allocation_error *this) +{ + TRACE("(%p)\n", this); + return this->hr; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_scheduler_resource_allocation_error_dtor,4) +void __thiscall MSVCRT_scheduler_resource_allocation_error_dtor( + scheduler_resource_allocation_error * this) +{ + TRACE("(%p)\n", this); + MSVCRT_exception_dtor(&this->e); +} + +typedef exception improper_lock; +extern const vtable_ptr MSVCRT_improper_lock_vtable; + +/* ??0improper_lock@Concurrency@@QAE@PBD@Z */ +/* ??0improper_lock@Concurrency@@QEAA@PEBD@Z */ +DEFINE_THISCALL_WRAPPER(improper_lock_ctor_str, 8) +improper_lock* __thiscall improper_lock_ctor_str(improper_lock *this, const char *str) +{ + TRACE("(%p %p)\n", this, str); + MSVCRT_exception_ctor(this, &str); + this->vtable = &MSVCRT_improper_lock_vtable; + return this; +} + +/* ??0improper_lock@Concurrency@@QAE@XZ */ +/* ??0improper_lock@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(improper_lock_ctor, 4) +improper_lock* __thiscall improper_lock_ctor(improper_lock *this) +{ + return improper_lock_ctor_str(this, NULL); +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_improper_lock_copy_ctor,8) +improper_lock * __thiscall MSVCRT_improper_lock_copy_ctor(improper_lock * _this, const improper_lock * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_improper_lock_vtable; + return _this; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_improper_lock_dtor,4) +void __thiscall MSVCRT_improper_lock_dtor(improper_lock * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +typedef exception invalid_scheduler_policy_key; +extern const vtable_ptr MSVCRT_invalid_scheduler_policy_key_vtable; + +/* ??0invalid_scheduler_policy_key@Concurrency@@QAE@PBD@Z */ +/* ??0invalid_scheduler_policy_key@Concurrency@@QEAA@PEBD@Z */ +DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_key_ctor_str, 8) +invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor_str( + invalid_scheduler_policy_key *this, const char *str) +{ + TRACE("(%p %p)\n", this, str); + MSVCRT_exception_ctor(this, &str); + this->vtable = &MSVCRT_invalid_scheduler_policy_key_vtable; + return this; +} + +/* ??0invalid_scheduler_policy_key@Concurrency@@QAE@XZ */ +/* ??0invalid_scheduler_policy_key@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_key_ctor, 4) +invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor( + invalid_scheduler_policy_key *this) +{ + return invalid_scheduler_policy_key_ctor_str(this, NULL); +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_key_copy_ctor,8) +invalid_scheduler_policy_key * __thiscall MSVCRT_invalid_scheduler_policy_key_copy_ctor( + invalid_scheduler_policy_key * _this, const invalid_scheduler_policy_key * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_invalid_scheduler_policy_key_vtable; + return _this; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_key_dtor,4) +void __thiscall MSVCRT_invalid_scheduler_policy_key_dtor( + invalid_scheduler_policy_key * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +typedef exception invalid_scheduler_policy_value; +extern const vtable_ptr MSVCRT_invalid_scheduler_policy_value_vtable; + +/* ??0invalid_scheduler_policy_value@Concurrency@@QAE@PBD@Z */ +/* ??0invalid_scheduler_policy_value@Concurrency@@QEAA@PEBD@Z */ +DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_value_ctor_str, 8) +invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor_str( + invalid_scheduler_policy_value *this, const char *str) +{ + TRACE("(%p %p)\n", this, str); + MSVCRT_exception_ctor(this, &str); + this->vtable = &MSVCRT_invalid_scheduler_policy_value_vtable; + return this; +} + +/* ??0invalid_scheduler_policy_value@Concurrency@@QAE@XZ */ +/* ??0invalid_scheduler_policy_value@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_value_ctor, 4) +invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor( + invalid_scheduler_policy_value *this) +{ + return invalid_scheduler_policy_value_ctor_str(this, NULL); +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_value_copy_ctor,8) +invalid_scheduler_policy_value * __thiscall MSVCRT_invalid_scheduler_policy_value_copy_ctor( + invalid_scheduler_policy_value * _this, const invalid_scheduler_policy_value * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_invalid_scheduler_policy_value_vtable; + return _this; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_value_dtor,4) +void __thiscall MSVCRT_invalid_scheduler_policy_value_dtor( + invalid_scheduler_policy_value * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +typedef exception invalid_scheduler_policy_thread_specification; +extern const vtable_ptr MSVCRT_invalid_scheduler_policy_thread_specification_vtable; + +/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QAE@PBD@Z */ +/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QEAA@PEBD@Z */ +DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_thread_specification_ctor_str, 8) +invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor_str( + invalid_scheduler_policy_thread_specification *this, const char *str) +{ + TRACE("(%p %p)\n", this, str); + MSVCRT_exception_ctor(this, &str); + this->vtable = &MSVCRT_invalid_scheduler_policy_thread_specification_vtable; + return this; +} + +/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QAE@XZ */ +/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_thread_specification_ctor, 4) +invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor( + invalid_scheduler_policy_thread_specification *this) +{ + return invalid_scheduler_policy_thread_specification_ctor_str(this, NULL); +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_thread_specification_copy_ctor,8) +invalid_scheduler_policy_thread_specification * __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_copy_ctor( + invalid_scheduler_policy_thread_specification * _this, const invalid_scheduler_policy_thread_specification * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_invalid_scheduler_policy_thread_specification_vtable; + return _this; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_thread_specification_dtor,4) +void __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_dtor( + invalid_scheduler_policy_thread_specification * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +typedef exception improper_scheduler_attach; +extern const vtable_ptr MSVCRT_improper_scheduler_attach_vtable; + +/* ??0improper_scheduler_attach@Concurrency@@QAE@PBD@Z */ +/* ??0improper_scheduler_attach@Concurrency@@QEAA@PEBD@Z */ +DEFINE_THISCALL_WRAPPER(improper_scheduler_attach_ctor_str, 8) +improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor_str( + improper_scheduler_attach *this, const char *str) +{ + TRACE("(%p %p)\n", this, str); + MSVCRT_exception_ctor(this, &str); + this->vtable = &MSVCRT_improper_scheduler_attach_vtable; + return this; +} + +/* ??0improper_scheduler_attach@Concurrency@@QAE@XZ */ +/* ??0improper_scheduler_attach@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(improper_scheduler_attach_ctor, 4) +improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor( + improper_scheduler_attach *this) +{ + return improper_scheduler_attach_ctor_str(this, NULL); +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_attach_copy_ctor,8) +improper_scheduler_attach * __thiscall MSVCRT_improper_scheduler_attach_copy_ctor( + improper_scheduler_attach * _this, const improper_scheduler_attach * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_improper_scheduler_attach_vtable; + return _this; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_attach_dtor,4) +void __thiscall MSVCRT_improper_scheduler_attach_dtor( + improper_scheduler_attach * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +typedef exception improper_scheduler_detach; +extern const vtable_ptr MSVCRT_improper_scheduler_detach_vtable; + +/* ??0improper_scheduler_detach@Concurrency@@QAE@PBD@Z */ +/* ??0improper_scheduler_detach@Concurrency@@QEAA@PEBD@Z */ +DEFINE_THISCALL_WRAPPER(improper_scheduler_detach_ctor_str, 8) +improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor_str( + improper_scheduler_detach *this, const char *str) +{ + TRACE("(%p %p)\n", this, str); + MSVCRT_exception_ctor(this, &str); + this->vtable = &MSVCRT_improper_scheduler_detach_vtable; + return this; +} + +/* ??0improper_scheduler_detach@Concurrency@@QAE@XZ */ +/* ??0improper_scheduler_detach@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(improper_scheduler_detach_ctor, 4) +improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor( + improper_scheduler_detach *this) +{ + return improper_scheduler_detach_ctor_str(this, NULL); +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_detach_copy_ctor,8) +improper_scheduler_detach * __thiscall MSVCRT_improper_scheduler_detach_copy_ctor( + improper_scheduler_detach * _this, const improper_scheduler_detach * rhs) +{ + TRACE("(%p %p)\n", _this, rhs); + MSVCRT_exception_copy_ctor(_this, rhs); + _this->vtable = &MSVCRT_improper_scheduler_detach_vtable; + return _this; +} + +DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_detach_dtor,4) +void __thiscall MSVCRT_improper_scheduler_detach_dtor( + improper_scheduler_detach * _this) +{ + TRACE("(%p)\n", _this); + MSVCRT_exception_dtor(_this); +} + +#endif /* _MSVCR_VER >= 100 */ + +#ifndef _MSC_VER +#ifndef __GNUC__ +void __asm_dummy_vtables(void) { +#endif + +__ASM_VTABLE(type_info, + VTABLE_ADD_FUNC(MSVCRT_type_info_vector_dtor)); +__ASM_VTABLE(exception, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +#if _MSVCR_VER >= 80 +__ASM_VTABLE(exception_old, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(bad_alloc, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +#endif +__ASM_VTABLE(bad_typeid, + VTABLE_ADD_FUNC(MSVCRT_bad_typeid_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(bad_cast, + VTABLE_ADD_FUNC(MSVCRT_bad_cast_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(__non_rtti_object, + VTABLE_ADD_FUNC(MSVCRT___non_rtti_object_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +#if _MSVCR_VER >= 100 +__ASM_VTABLE(scheduler_resource_allocation_error, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(improper_lock, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(invalid_scheduler_policy_key, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(invalid_scheduler_policy_value, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(invalid_scheduler_policy_thread_specification, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(improper_scheduler_attach, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +__ASM_VTABLE(improper_scheduler_detach, + VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor) + VTABLE_ADD_FUNC(MSVCRT_what_exception)); +#endif + +#ifndef __GNUC__ +} +#endif +#endif /* !_MSC_VER */ + +DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" ) +#if _MSVCR_VER >= 80 +DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@std@@" ) +DEFINE_RTTI_DATA0( exception_old, 0, ".?AVexception@@" ) +DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@std@@" ) +DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@std@@" ) +DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@std@@" ) +DEFINE_RTTI_DATA1( bad_alloc, 0, &exception_rtti_base_descriptor, ".?AVbad_alloc@std@@" ) +#else +DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@@" ) +DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@@" ) +DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@@" ) +DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@@" ) +#endif +#if _MSVCR_VER >= 100 +DEFINE_RTTI_DATA1(scheduler_resource_allocation_error, 0, &exception_rtti_base_descriptor, + ".?AVscheduler_resource_allocation_error@Concurrency@@") +DEFINE_RTTI_DATA1(improper_lock, 0, &exception_rtti_base_descriptor, ".?AVimproper_lock@Concurrency@@" ) +DEFINE_RTTI_DATA1(invalid_scheduler_policy_key, 0, &exception_rtti_base_descriptor, + ".?AVinvalid_scheduler_policy_key@Concurrency@@" ) +DEFINE_RTTI_DATA1(invalid_scheduler_policy_value, 0, &exception_rtti_base_descriptor, + ".?AVinvalid_scheduler_policy_value@Concurrency@@" ) +DEFINE_RTTI_DATA1(invalid_scheduler_policy_thread_specification, 0, &exception_rtti_base_descriptor, + ".?AVinvalid_scheduler_policy_thread_specification@Concurrency@@" ) +DEFINE_RTTI_DATA1(improper_scheduler_attach, 0, &exception_rtti_base_descriptor, + ".?AVimproper_scheduler_attach@Concurrency@@" ) +DEFINE_RTTI_DATA1(improper_scheduler_detach, 0, &exception_rtti_base_descriptor, + ".?AVimproper_scheduler_detach@Concurrency@@" ) +#endif + +DEFINE_EXCEPTION_TYPE_INFO( exception, 0, NULL, NULL ) +DEFINE_EXCEPTION_TYPE_INFO( bad_typeid, 1, &exception_cxx_type_info, NULL ) +DEFINE_EXCEPTION_TYPE_INFO( bad_cast, 1, &exception_cxx_type_info, NULL ) +DEFINE_EXCEPTION_TYPE_INFO( __non_rtti_object, 2, &bad_typeid_cxx_type_info, &exception_cxx_type_info ) +#if _MSVCR_VER >= 80 +DEFINE_EXCEPTION_TYPE_INFO( bad_alloc, 1, &exception_cxx_type_info, NULL ) +#endif +#if _MSVCR_VER >= 100 +DEFINE_EXCEPTION_TYPE_INFO(scheduler_resource_allocation_error, 1, &exception_cxx_type_info, NULL) +DEFINE_EXCEPTION_TYPE_INFO(improper_lock, 1, &exception_cxx_type_info, NULL) +DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_key, 1, &exception_cxx_type_info, NULL) +DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_value, 1, &exception_cxx_type_info, NULL) +DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_thread_specification, 1, &exception_cxx_type_info, NULL) +DEFINE_EXCEPTION_TYPE_INFO(improper_scheduler_attach, 1, &exception_cxx_type_info, NULL) +DEFINE_EXCEPTION_TYPE_INFO(improper_scheduler_detach, 1, &exception_cxx_type_info, NULL) +#endif + +void msvcrt_init_exception(void *base) +{ +#ifdef __x86_64__ + init_type_info_rtti(base); + init_exception_rtti(base); +#if _MSVCR_VER >= 80 + init_exception_old_rtti(base); + init_bad_alloc_rtti(base); +#endif + init_bad_typeid_rtti(base); + init_bad_cast_rtti(base); + init___non_rtti_object_rtti(base); +#if _MSVCR_VER >= 100 + init_scheduler_resource_allocation_error_rtti(base); + init_improper_lock_rtti(base); + init_invalid_scheduler_policy_key_rtti(base); + init_invalid_scheduler_policy_value_rtti(base); + init_invalid_scheduler_policy_thread_specification_rtti(base); + init_improper_scheduler_attach_rtti(base); + init_improper_scheduler_detach_rtti(base); +#endif + + init_exception_cxx(base); + init_bad_typeid_cxx(base); + init_bad_cast_cxx(base); + init___non_rtti_object_cxx(base); +#if _MSVCR_VER >= 80 + init_bad_alloc_cxx(base); +#endif +#if _MSVCR_VER >= 100 + init_scheduler_resource_allocation_error_cxx(base); + init_improper_lock_cxx(base); + init_invalid_scheduler_policy_key_cxx(base); + init_invalid_scheduler_policy_value_cxx(base); + init_invalid_scheduler_policy_thread_specification_cxx(base); + init_improper_scheduler_attach_cxx(base); + init_improper_scheduler_detach_cxx(base); +#endif +#endif +} + +#if _MSVCR_VER >= 80 +void throw_exception(exception_type et, HRESULT hr, const char *str) +{ + switch(et) { + case EXCEPTION_BAD_ALLOC: { + bad_alloc e; + bad_alloc_ctor(&e, &str); + _CxxThrowException(&e, &bad_alloc_exception_type); + } +#if _MSVCR_VER >= 100 + case EXCEPTION_SCHEDULER_RESOURCE_ALLOCATION_ERROR: { + scheduler_resource_allocation_error e; + scheduler_resource_allocation_error_ctor_name(&e, str, hr); + _CxxThrowException(&e.e, &scheduler_resource_allocation_error_exception_type); + } + case EXCEPTION_IMPROPER_LOCK: { + improper_lock e; + improper_lock_ctor_str(&e, str); + _CxxThrowException(&e, &improper_lock_exception_type); + } + case EXCEPTION_INVALID_SCHEDULER_POLICY_KEY: { + invalid_scheduler_policy_key e; + invalid_scheduler_policy_key_ctor_str(&e, str); + _CxxThrowException(&e, &invalid_scheduler_policy_key_exception_type); + } + case EXCEPTION_INVALID_SCHEDULER_POLICY_VALUE: { + invalid_scheduler_policy_value e; + invalid_scheduler_policy_value_ctor_str(&e, str); + _CxxThrowException(&e, &invalid_scheduler_policy_value_exception_type); + } + case EXCEPTION_INVALID_SCHEDULER_POLICY_THREAD_SPECIFICATION: { + invalid_scheduler_policy_thread_specification e; + invalid_scheduler_policy_thread_specification_ctor_str(&e, str); + _CxxThrowException(&e, &invalid_scheduler_policy_thread_specification_exception_type); + } + case EXCEPTION_IMPROPER_SCHEDULER_ATTACH: { + improper_scheduler_attach e; + improper_scheduler_attach_ctor_str(&e, str); + _CxxThrowException(&e, &improper_scheduler_attach_exception_type); + } + case EXCEPTION_IMPROPER_SCHEDULER_DETACH: { + improper_scheduler_detach e; + improper_scheduler_detach_ctor_str(&e, str); + _CxxThrowException(&e, &improper_scheduler_detach_exception_type); + } +#endif + } +} +#endif + +/****************************************************************** + * ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@) + * + * Install a handler to be called when terminate() is called. + * + * PARAMS + * func [I] Handler function to install + * + * RETURNS + * The previously installed handler function, if any. + */ +MSVCRT_terminate_function CDECL MSVCRT_set_terminate(MSVCRT_terminate_function func) +{ + thread_data_t *data = msvcrt_get_thread_data(); + MSVCRT_terminate_function previous = data->terminate_handler; + TRACE("(%p) returning %p\n",func,previous); + data->terminate_handler = func; + return previous; +} + +/****************************************************************** + * _get_terminate (MSVCRT.@) + */ +MSVCRT_terminate_function CDECL MSVCRT__get_terminate(void) +{ + thread_data_t *data = msvcrt_get_thread_data(); + TRACE("returning %p\n", data->terminate_handler); + return data->terminate_handler; +} + +/****************************************************************** + * ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@) + * + * Install a handler to be called when unexpected() is called. + * + * PARAMS + * func [I] Handler function to install + * + * RETURNS + * The previously installed handler function, if any. + */ +MSVCRT_unexpected_function CDECL MSVCRT_set_unexpected(MSVCRT_unexpected_function func) +{ + thread_data_t *data = msvcrt_get_thread_data(); + MSVCRT_unexpected_function previous = data->unexpected_handler; + TRACE("(%p) returning %p\n",func,previous); + data->unexpected_handler = func; + return previous; +} + +/****************************************************************** + * _get_unexpected (MSVCRT.@) + */ +MSVCRT_unexpected_function CDECL MSVCRT__get_unexpected(void) +{ + thread_data_t *data = msvcrt_get_thread_data(); + TRACE("returning %p\n", data->unexpected_handler); + return data->unexpected_handler; +} + +/****************************************************************** + * ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z (MSVCRT.@) + */ +MSVCRT__se_translator_function CDECL MSVCRT__set_se_translator(MSVCRT__se_translator_function func) +{ + thread_data_t *data = msvcrt_get_thread_data(); + MSVCRT__se_translator_function previous = data->se_translator; + TRACE("(%p) returning %p\n",func,previous); + data->se_translator = func; + return previous; +} + +/****************************************************************** + * ?terminate@@YAXXZ (MSVCRT.@) + * + * Default handler for an unhandled exception. + * + * PARAMS + * None. + * + * RETURNS + * This function does not return. Either control resumes from any + * handler installed by calling set_terminate(), or (by default) abort() + * is called. + */ +void CDECL MSVCRT_terminate(void) +{ + thread_data_t *data = msvcrt_get_thread_data(); + if (data->terminate_handler) data->terminate_handler(); + MSVCRT_abort(); +} + +/****************************************************************** + * ?unexpected@@YAXXZ (MSVCRT.@) + */ +void CDECL MSVCRT_unexpected(void) +{ + thread_data_t *data = msvcrt_get_thread_data(); + if (data->unexpected_handler) data->unexpected_handler(); + MSVCRT_terminate(); +} + + +/****************************************************************** + * __RTtypeid (MSVCRT.@) + * + * Retrieve the Run Time Type Information (RTTI) for a C++ object. + * + * PARAMS + * cppobj [I] C++ object to get type information for. + * + * RETURNS + * Success: A type_info object describing cppobj. + * Failure: If the object to be cast has no RTTI, a __non_rtti_object + * exception is thrown. If cppobj is NULL, a bad_typeid exception + * is thrown. In either case, this function does not return. + * + * NOTES + * This function is usually called by compiler generated code as a result + * of using one of the C++ dynamic cast statements. + */ +#ifndef __x86_64__ +const type_info* CDECL MSVCRT___RTtypeid(void *cppobj) +{ + const type_info *ret; + + if (!cppobj) + { + bad_typeid e; + MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" ); + _CxxThrowException( &e, &bad_typeid_exception_type ); + return NULL; + } + + __TRY + { + const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); + ret = obj_locator->type_descriptor; + } + __EXCEPT_PAGE_FAULT + { + __non_rtti_object e; + MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" ); + _CxxThrowException( &e, &__non_rtti_object_exception_type ); + return NULL; + } + __ENDTRY + return ret; +} + +#else + +const type_info* CDECL MSVCRT___RTtypeid(void *cppobj) +{ + const type_info *ret; + + if (!cppobj) + { + bad_typeid e; + MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" ); + _CxxThrowException( &e, &bad_typeid_exception_type ); + return NULL; + } + + __TRY + { + const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); + char *base; + + if(obj_locator->signature == 0) + base = RtlPcToFileHeader((void*)obj_locator, (void**)&base); + else + base = (char*)obj_locator - obj_locator->object_locator; + + ret = (type_info*)(base + obj_locator->type_descriptor); + } + __EXCEPT_PAGE_FAULT + { + __non_rtti_object e; + MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" ); + _CxxThrowException( &e, &__non_rtti_object_exception_type ); + return NULL; + } + __ENDTRY + return ret; +} +#endif + +/****************************************************************** + * __RTDynamicCast (MSVCRT.@) + * + * Dynamically cast a C++ object to one of its base classes. + * + * PARAMS + * cppobj [I] Any C++ object to cast + * unknown [I] Reserved, set to 0 + * src [I] type_info object describing cppobj + * dst [I] type_info object describing the base class to cast to + * do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't + * + * RETURNS + * Success: The address of cppobj, cast to the object described by dst. + * Failure: NULL, If the object to be cast has no RTTI, or dst is not a + * valid cast for cppobj. If do_throw is TRUE, a bad_cast exception + * is thrown and this function does not return. + * + * NOTES + * This function is usually called by compiler generated code as a result + * of using one of the C++ dynamic cast statements. + */ +#ifndef __x86_64__ +void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown, + type_info *src, type_info *dst, + int do_throw) +{ + void *ret; + + if (!cppobj) return NULL; + + TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n", + cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw); + + /* To cast an object at runtime: + * 1.Find out the true type of the object from the typeinfo at vtable[-1] + * 2.Search for the destination type in the class hierarchy + * 3.If destination type is found, return base object address + dest offset + * Otherwise, fail the cast + * + * FIXME: the unknown parameter doesn't seem to be used for anything + */ + __TRY + { + int i; + const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); + const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy; + const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases; + + if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator); + + ret = NULL; + for (i = 0; i < obj_bases->array_len; i++) + { + const type_info *typ = base_desc[i]->type_descriptor; + + if (!strcmp(typ->mangled, dst->mangled)) + { + /* compute the correct this pointer for that base class */ + void *this_ptr = (char *)cppobj - obj_locator->base_class_offset; + ret = get_this_pointer( &base_desc[i]->offsets, this_ptr ); + break; + } + } + /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned + * to a reference, since references cannot be NULL. + */ + if (!ret && do_throw) + { + const char *msg = "Bad dynamic_cast!"; + bad_cast e; + MSVCRT_bad_cast_ctor( &e, &msg ); + _CxxThrowException( &e, &bad_cast_exception_type ); + } + } + __EXCEPT_PAGE_FAULT + { + __non_rtti_object e; + MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" ); + _CxxThrowException( &e, &__non_rtti_object_exception_type ); + return NULL; + } + __ENDTRY + return ret; +} + +#else + +void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown, + type_info *src, type_info *dst, + int do_throw) +{ + void *ret; + + if (!cppobj) return NULL; + + TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n", + cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw); + + __TRY + { + int i; + const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); + const rtti_object_hierarchy *obj_bases; + const rtti_base_array *base_array; + char *base; + + if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator); + + if(obj_locator->signature == 0) + base = RtlPcToFileHeader((void*)obj_locator, (void**)&base); + else + base = (char*)obj_locator - obj_locator->object_locator; + + obj_bases = (const rtti_object_hierarchy*)(base + obj_locator->type_hierarchy); + base_array = (const rtti_base_array*)(base + obj_bases->base_classes); + + ret = NULL; + for (i = 0; i < obj_bases->array_len; i++) + { + const rtti_base_descriptor *base_desc = (const rtti_base_descriptor*)(base + base_array->bases[i]); + const type_info *typ = (const type_info*)(base + base_desc->type_descriptor); + + if (!strcmp(typ->mangled, dst->mangled)) + { + void *this_ptr = (char *)cppobj - obj_locator->base_class_offset; + ret = get_this_pointer( &base_desc->offsets, this_ptr ); + break; + } + } + if (!ret && do_throw) + { + const char *msg = "Bad dynamic_cast!"; + bad_cast e; + MSVCRT_bad_cast_ctor( &e, &msg ); + _CxxThrowException( &e, &bad_cast_exception_type ); + } + } + __EXCEPT_PAGE_FAULT + { + __non_rtti_object e; + MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" ); + _CxxThrowException( &e, &__non_rtti_object_exception_type ); + return NULL; + } + __ENDTRY + return ret; +} +#endif + + +/****************************************************************** + * __RTCastToVoid (MSVCRT.@) + * + * Dynamically cast a C++ object to a void*. + * + * PARAMS + * cppobj [I] The C++ object to cast + * + * RETURNS + * Success: The base address of the object as a void*. + * Failure: NULL, if cppobj is NULL or has no RTTI. + * + * NOTES + * This function is usually called by compiler generated code as a result + * of using one of the C++ dynamic cast statements. + */ +void* CDECL MSVCRT___RTCastToVoid(void *cppobj) +{ + void *ret; + + if (!cppobj) return NULL; + + __TRY + { + const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); + ret = (char *)cppobj - obj_locator->base_class_offset; + } + __EXCEPT_PAGE_FAULT + { + __non_rtti_object e; + MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" ); + _CxxThrowException( &e, &__non_rtti_object_exception_type ); + return NULL; + } + __ENDTRY + return ret; +} + + +/********************************************************************* + * _CxxThrowException (MSVCRT.@) + */ +#ifndef __x86_64__ +void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type ) +{ + ULONG_PTR args[3]; + + args[0] = CXX_FRAME_MAGIC_VC6; + args[1] = (ULONG_PTR)object; + args[2] = (ULONG_PTR)type; + RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args ); +} +#else +void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type ) +{ + ULONG_PTR args[4]; + + args[0] = CXX_FRAME_MAGIC_VC6; + args[1] = (ULONG_PTR)object; + args[2] = (ULONG_PTR)type; + RtlPcToFileHeader( (void*)type, (void**)&args[3]); + RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 4, args ); +} +#endif + +#if _MSVCR_VER >= 80 + +/********************************************************************* + * ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z + * ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z + */ +#ifndef __x86_64__ +int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep) +{ + int ret = -1; + + TRACE("(%p %p)\n", ti, ep); + + __TRY + { + EXCEPTION_RECORD *rec = ep->ExceptionRecord; + + if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==3 && + (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 || + rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 || + rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8)) + { + const cxx_type_info_table *tit = ((cxx_exception_type*)rec->ExceptionInformation[2])->type_info_table; + int i; + + for (i=0; icount; i++) { + if (ti==tit->info[i]->type_info || !strcmp(ti->mangled, tit->info[i]->type_info->mangled)) + { + ret = 1; + break; + } + } + + if (i == tit->count) + ret = 0; + } + } + __EXCEPT_PAGE_FAULT + __ENDTRY + + if(ret == -1) + MSVCRT_terminate(); + return ret; +} +#else +int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep) +{ + int ret = -1; + + TRACE("(%p %p)\n", ti, ep); + + __TRY + { + EXCEPTION_RECORD *rec = ep->ExceptionRecord; + + if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==4 && + (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 || + rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 || + rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8)) + { + const cxx_exception_type *et = (cxx_exception_type*)rec->ExceptionInformation[2]; + const cxx_type_info_table *tit = (const cxx_type_info_table*)(rec->ExceptionInformation[3]+et->type_info_table); + int i; + + for (i=0; icount; i++) { + const cxx_type_info *cti = (const cxx_type_info*)(rec->ExceptionInformation[3]+tit->info[i]); + const type_info *except_ti = (const type_info*)(rec->ExceptionInformation[3]+cti->type_info); + if (ti==except_ti || !strcmp(ti->mangled, except_ti->mangled)) + { + ret = 1; + break; + } + } + + if (i == tit->count) + ret = 0; + } + } + __EXCEPT_PAGE_FAULT + __ENDTRY + + if(ret == -1) + MSVCRT_terminate(); + return ret; +} +#endif + +/********************************************************************* + * __clean_type_info_names_internal (MSVCR80.@) + */ +void CDECL __clean_type_info_names_internal(void *p) +{ + FIXME("(%p) stub\n", p); +} + +/********************************************************************* + * ?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR100.@) + */ +DEFINE_THISCALL_WRAPPER(type_info_name_internal_method,8) +const char * __thiscall type_info_name_internal_method(type_info * _this, struct __type_info_node *node) +{ + static int once; + if (node && !once++) FIXME("type_info_node parameter ignored\n"); + + return MSVCRT_type_info_name(_this); +} + +#endif /* _MSVCR_VER >= 80 */ + +/* std::exception_ptr class helpers */ +typedef struct +{ + EXCEPTION_RECORD *rec; + int *ref; /* not binary compatible with native msvcr100 */ +} exception_ptr; + +#if _MSVCR_VER >= 100 + +/********************************************************************* + * ?__ExceptionPtrCreate@@YAXPAX@Z + * ?__ExceptionPtrCreate@@YAXPEAX@Z + */ +void __cdecl __ExceptionPtrCreate(exception_ptr *ep) +{ + TRACE("(%p)\n", ep); + + ep->rec = NULL; + ep->ref = NULL; +} + +#if defined(__i386__) && !defined(__MINGW32__) +extern void call_dtor(const cxx_exception_type *type, void *func, void *object); + +__ASM_GLOBAL_FUNC( call_dtor, + "movl 12(%esp),%ecx\n\t" + "call *8(%esp)\n\t" + "ret" ); +#elif __x86_64__ +static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object) +{ + char *base = RtlPcToFileHeader((void*)type, (void**)&base); + void (__cdecl *func)(void*) = (void*)(base + dtor); + func(object); +} +#else +#define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object) +#endif + +/********************************************************************* + * ?__ExceptionPtrDestroy@@YAXPAX@Z + * ?__ExceptionPtrDestroy@@YAXPEAX@Z + */ +void __cdecl __ExceptionPtrDestroy(exception_ptr *ep) +{ + TRACE("(%p)\n", ep); + + if (!ep->rec) + return; + + if (!InterlockedDecrement(ep->ref)) + { + if (ep->rec->ExceptionCode == CXX_EXCEPTION) + { + const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2]; + void *obj = (void*)ep->rec->ExceptionInformation[1]; + + if (type && type->destructor) call_dtor(type, type->destructor, obj); + HeapFree(GetProcessHeap(), 0, obj); + } + + HeapFree(GetProcessHeap(), 0, ep->rec); + HeapFree(GetProcessHeap(), 0, ep->ref); + } +} + +/********************************************************************* + * ?__ExceptionPtrCopy@@YAXPAXPBX@Z + * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z + */ +void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy) +{ + TRACE("(%p %p)\n", ep, copy); + + /* don't destroy object stored in ep */ + *ep = *copy; + if (ep->ref) + InterlockedIncrement(copy->ref); +} + +/********************************************************************* + * ?__ExceptionPtrAssign@@YAXPAXPBX@Z + * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z + */ +void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign) +{ + TRACE("(%p %p)\n", ep, assign); + + /* don't destroy object stored in ep */ + if (ep->ref) + InterlockedDecrement(ep->ref); + + *ep = *assign; + if (ep->ref) + InterlockedIncrement(ep->ref); +} + +#endif /* _MSVCR_VER >= 100 */ + +/********************************************************************* + * ?__ExceptionPtrRethrow@@YAXPBX@Z + * ?__ExceptionPtrRethrow@@YAXPEBX@Z + */ +void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep) +{ + TRACE("(%p)\n", ep); + + if (!ep->rec) + { + static const char *exception_msg = "bad exception"; + exception e; + + MSVCRT_exception_ctor(&e, &exception_msg); + _CxxThrowException(&e, &exception_exception_type); + return; + } + + RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING), + ep->rec->NumberParameters, ep->rec->ExceptionInformation); +} + +#if _MSVCR_VER >= 100 + +#ifdef __i386__ +extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase ); +#else +static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase ) +{ + TRACE( "calling copy ctor %p object %p src %p\n", func, this, src ); + if (has_vbase) + ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1); + else + ((void (__cdecl*)(void*, void*))func)(this, src); +} +#endif + +/********************************************************************* + * ?__ExceptionPtrCurrentException@@YAXPAX@Z + * ?__ExceptionPtrCurrentException@@YAXPEAX@Z + */ +#ifndef __x86_64__ +void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) +{ + EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; + + TRACE("(%p)\n", ep); + + if (!rec) + { + ep->rec = NULL; + ep->ref = NULL; + return; + } + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + + *ep->rec = *rec; + *ep->ref = 1; + + if (ep->rec->ExceptionCode == CXX_EXCEPTION) + { + const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2]; + const cxx_type_info *ti; + void **data, *obj; + + ti = et->type_info_table->info[0]; + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + + obj = (void*)ep->rec->ExceptionInformation[1]; + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, obj, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; + } + return; +} +#else +void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep) +{ + EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record; + + TRACE("(%p)\n", ep); + + if (!rec) + { + ep->rec = NULL; + ep->ref = NULL; + return; + } + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + + *ep->rec = *rec; + *ep->ref = 1; + + if (ep->rec->ExceptionCode == CXX_EXCEPTION) + { + const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2]; + const cxx_type_info *ti; + void **data, *obj; + char *base = RtlPcToFileHeader((void*)et, (void**)&base); + + ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]); + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + + obj = (void*)ep->rec->ExceptionInformation[1]; + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, obj, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; + } + return; +} +#endif + +#endif /* _MSVCR_VER >= 100 */ + +#if _MSVCR_VER >= 110 +/********************************************************************* + * ?__ExceptionPtrToBool@@YA_NPBX@Z + * ?__ExceptionPtrToBool@@YA_NPEBX@Z + */ +MSVCRT_bool __cdecl __ExceptionPtrToBool(exception_ptr *ep) +{ + return !!ep->rec; +} +#endif + +#if _MSVCR_VER >= 100 + +/********************************************************************* + * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z + * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z + */ +#ifndef __x86_64__ +void __cdecl __ExceptionPtrCopyException(exception_ptr *ep, + exception *object, const cxx_exception_type *type) +{ + const cxx_type_info *ti; + void **data; + + __ExceptionPtrDestroy(ep); + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + *ep->ref = 1; + + memset(ep->rec, 0, sizeof(EXCEPTION_RECORD)); + ep->rec->ExceptionCode = CXX_EXCEPTION; + ep->rec->ExceptionFlags = EH_NONCONTINUABLE; + ep->rec->NumberParameters = 3; + ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6; + ep->rec->ExceptionInformation[2] = (ULONG_PTR)type; + + ti = type->type_info_table->info[0]; + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, object, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, object), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, object), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; +} +#else +void __cdecl __ExceptionPtrCopyException(exception_ptr *ep, + exception *object, const cxx_exception_type *type) +{ + const cxx_type_info *ti; + void **data; + char *base; + + RtlPcToFileHeader((void*)type, (void**)&base); + __ExceptionPtrDestroy(ep); + + ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD)); + ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); + *ep->ref = 1; + + memset(ep->rec, 0, sizeof(EXCEPTION_RECORD)); + ep->rec->ExceptionCode = CXX_EXCEPTION; + ep->rec->ExceptionFlags = EH_NONCONTINUABLE; + ep->rec->NumberParameters = 4; + ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6; + ep->rec->ExceptionInformation[2] = (ULONG_PTR)type; + ep->rec->ExceptionInformation[3] = (ULONG_PTR)base; + + ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + type->type_info_table))->info[0]); + data = HeapAlloc(GetProcessHeap(), 0, ti->size); + if (ti->flags & CLASS_IS_SIMPLE_TYPE) + { + memcpy(data, object, ti->size); + if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data); + } + else if (ti->copy_ctor) + { + call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, object), + ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS); + } + else + memcpy(data, get_this_pointer(&ti->offsets, object), ti->size); + ep->rec->ExceptionInformation[1] = (ULONG_PTR)data; +} +#endif + +MSVCRT_bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2) +{ + return ep1->rec == ep2->rec; +} + +#endif /* _MSVCR_VER >= 100 */ + +#if _MSVCR_VER >= 80 +void* __cdecl __AdjustPointer(void *obj, const this_ptr_offsets *off) +{ + return get_this_pointer(off, obj); +} +#endif + +#if _MSVCR_VER >= 140 + +typedef struct +{ + char *name; + char mangled[1]; +} type_info140; + +typedef struct +{ + SLIST_ENTRY entry; + char name[1]; +} type_info_entry; + +static void* CDECL type_info_entry_malloc(MSVCRT_size_t size) +{ + type_info_entry *ret = MSVCRT_malloc(FIELD_OFFSET(type_info_entry, name) + size); + return ret->name; +} + +static void CDECL type_info_entry_free(void *ptr) +{ + ptr = (char*)ptr - FIELD_OFFSET(type_info_entry, name); + MSVCRT_free(ptr); +} + +/****************************************************************** + * __std_type_info_compare (UCRTBASE.@) + */ +int CDECL MSVCRT_type_info_compare(const type_info140 *l, const type_info140 *r) +{ + int ret; + + if (l == r) ret = 0; + else ret = MSVCRT_strcmp(l->mangled + 1, r->mangled + 1); + TRACE("(%p %p) returning %d\n", l, r, ret); + return ret; +} + +/****************************************************************** + * __std_type_info_name (UCRTBASE.@) + */ +const char* CDECL MSVCRT_type_info_name_list(type_info140 *ti, SLIST_HEADER *header) +{ + if (!ti->name) + { + char* name = __unDName(0, ti->mangled + 1, 0, + type_info_entry_malloc, type_info_entry_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE); + if (name) + { + unsigned int len = strlen(name); + + while (len && name[--len] == ' ') + name[len] = '\0'; + + if (InterlockedCompareExchangePointer((void**)&ti->name, name, NULL)) + { + type_info_entry_free(name); + } + else + { + type_info_entry *entry = (type_info_entry*)(name-FIELD_OFFSET(type_info_entry, name)); + InterlockedPushEntrySList(header, &entry->entry); + } + } + } + TRACE("(%p) returning %s\n", ti, ti->name); + return ti->name; +} + +/****************************************************************** + * __std_type_info_destroy_list (UCRTBASE.@) + */ +void CDECL MSVCRT_type_info_destroy_list(SLIST_HEADER *header) +{ + SLIST_ENTRY *cur, *next; + + TRACE("(%p)\n", header); + + for(cur = InterlockedFlushSList(header); cur; cur = next) + { + next = cur->Next; + MSVCRT_free(cur); + } +} + +/****************************************************************** + * __std_type_info_hash (UCRTBASE.@) + */ +MSVCRT_size_t CDECL MSVCRT_type_info_hash(const type_info140 *ti) +{ + MSVCRT_size_t hash, fnv_prime; + const char *p; + +#ifdef _WIN64 + hash = 0xcbf29ce484222325; + fnv_prime = 0x100000001b3; +#else + hash = 0x811c9dc5; + fnv_prime = 0x1000193; +#endif + + TRACE("(%p)->%s\n", ti, ti->mangled); + + for(p = ti->mangled+1; *p; p++) { + hash ^= *p; + hash *= fnv_prime; + } + +#ifdef _WIN64 + hash ^= hash >> 32; +#endif + + return hash; +} + +#endif /* _MSVCR_VER >= 140 */ + +#if _MSVCR_VER >= 100 + +enum ConcRT_EventType +{ + CONCRT_EVENT_GENERIC, + CONCRT_EVENT_START, + CONCRT_EVENT_END, + CONCRT_EVENT_BLOCK, + CONCRT_EVENT_UNBLOCK, + CONCRT_EVENT_YIELD, + CONCRT_EVENT_ATTACH, + CONCRT_EVENT_DETACH +}; + +/* ?_Trace_ppl_function@Concurrency@@YAXABU_GUID@@EW4ConcRT_EventType@1@@Z */ +/* ?_Trace_ppl_function@Concurrency@@YAXAEBU_GUID@@EW4ConcRT_EventType@1@@Z */ +void __cdecl Concurrency__Trace_ppl_function(const GUID *guid, unsigned char level, enum ConcRT_EventType type) +{ + FIXME("(%s %u %i) stub\n", debugstr_guid(guid), level, type); +} + +#endif /* _MSVCR_VER >= 100 */ diff --git a/sdk/lib/crt/except/cppexcept.h b/sdk/lib/crt/wine/cppexcept.h similarity index 77% rename from sdk/lib/crt/except/cppexcept.h rename to sdk/lib/crt/wine/cppexcept.h index 254d3ddd1be..69fb3c5eed9 100644 --- a/sdk/lib/crt/except/cppexcept.h +++ b/sdk/lib/crt/wine/cppexcept.h @@ -21,6 +21,8 @@ #ifndef __MSVCRT_CPPEXCEPT_H #define __MSVCRT_CPPEXCEPT_H +#include "wine/asm.h" + #define CXX_FRAME_MAGIC_VC6 0x19930520 #define CXX_FRAME_MAGIC_VC7 0x19930521 #define CXX_FRAME_MAGIC_VC8 0x19930522 @@ -33,17 +35,17 @@ typedef void (*vtable_ptr)(void); /* type_info object, see cpp.c for implementation */ typedef struct __type_info { - const vtable_ptr* vtable; - char* name; /* Unmangled name, allocated lazily */ - char mangled[64]; /* Variable length, but we declare it large enough for static RTTI */ + const vtable_ptr *vtable; + char *name; /* Unmangled name, allocated lazily */ + char mangled[64]; /* Variable length, but we declare it large enough for static RTTI */ } type_info; /* exception object */ typedef struct __exception { - const vtable_ptr* vtable; - char* name; /* Name of this exception, always a new copy for each object */ - BOOL do_free; /* Whether to free 'name' in our dtor */ + const vtable_ptr *vtable; + char *name; /* Name of this exception, always a new copy for each object */ + BOOL do_free; /* Whether to free 'name' in our dtor */ } exception; typedef void (*cxx_copy_ctor)(void); @@ -61,7 +63,7 @@ typedef struct typedef struct __cxx_type_info { UINT flags; /* flags (see CLASS_* flags below) */ - const type_info* type_info; /* C++ type info */ + const type_info *type_info; /* C++ type info */ this_ptr_offsets offsets; /* offsets for computing the this pointer */ unsigned int size; /* object size */ cxx_copy_ctor copy_ctor; /* copy constructor */ @@ -85,7 +87,7 @@ typedef struct __cxx_type_info typedef struct __cxx_type_info_table { UINT count; /* number of types */ - const cxx_type_info* info[3]; /* variable length, we declare it large enough for static RTTI */ + const cxx_type_info *info[3]; /* variable length, we declare it large enough for static RTTI */ } cxx_type_info_table; #else typedef struct __cxx_type_info_table @@ -98,10 +100,10 @@ typedef struct __cxx_type_info_table struct __cxx_exception_frame; struct __cxx_function_descr; -typedef DWORD(*cxx_exc_custom_handler)(PEXCEPTION_RECORD, struct __cxx_exception_frame*, - PCONTEXT, EXCEPTION_REGISTRATION_RECORD**, - const struct __cxx_function_descr*, int nested_trylevel, - EXCEPTION_REGISTRATION_RECORD* nested_frame, DWORD unknown3); +typedef DWORD (*cxx_exc_custom_handler)( PEXCEPTION_RECORD, struct __cxx_exception_frame*, + PCONTEXT, EXCEPTION_REGISTRATION_RECORD**, + const struct __cxx_function_descr*, int nested_trylevel, + EXCEPTION_REGISTRATION_RECORD *nested_frame, DWORD unknown3 ); /* type information for an exception object */ #ifndef __x86_64__ @@ -110,7 +112,7 @@ typedef struct __cxx_exception_type UINT flags; /* TYPE_FLAG flags */ void (*destructor)(void);/* exception object destructor */ cxx_exc_custom_handler custom_handler; /* custom handler for this exception */ - const cxx_type_info_table* type_info_table; /* list of types for this exception object */ + const cxx_type_info_table *type_info_table; /* list of types for this exception object */ } cxx_exception_type; #else typedef struct @@ -122,33 +124,33 @@ typedef struct } cxx_exception_type; #endif -void WINAPI _CxxThrowException(exception*, const cxx_exception_type*); +void WINAPI _CxxThrowException(exception*,const cxx_exception_type*); int CDECL _XcptFilter(NTSTATUS, PEXCEPTION_POINTERS); -static inline const char* dbgstr_type_info(const type_info* info) +static inline const char *dbgstr_type_info( const type_info *info ) { if (!info) return "{}"; - return wine_dbg_sprintf("{vtable=%p name=%s (%s)}", - info->vtable, info->mangled, info->name ? info->name : ""); + return wine_dbg_sprintf( "{vtable=%p name=%s (%s)}", + info->vtable, info->mangled, info->name ? info->name : "" ); } /* compute the this pointer for a base class of a given type */ -static inline void* get_this_pointer(const this_ptr_offsets* off, void* object) +static inline void *get_this_pointer( const this_ptr_offsets *off, void *object ) { if (!object) return NULL; if (off->vbase_descr >= 0) { - int* offset_ptr; + int *offset_ptr; /* move this ptr to vbase descriptor */ - object = (char*)object + off->vbase_descr; + object = (char *)object + off->vbase_descr; /* and fetch additional offset from vbase descriptor */ - offset_ptr = (int*)(*(char**)object + off->vbase_offset); - object = (char*)object + *offset_ptr; + offset_ptr = (int *)(*(char **)object + off->vbase_offset); + object = (char *)object + *offset_ptr; } - object = (char*)object + off->this_offset; + object = (char *)object + off->this_offset; return object; } diff --git a/sdk/lib/crt/wine/cxx.h b/sdk/lib/crt/wine/cxx.h new file mode 100644 index 00000000000..b22ff22cc85 --- /dev/null +++ b/sdk/lib/crt/wine/cxx.h @@ -0,0 +1,267 @@ +/* + * Copyright 2012 Piotr Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + */ + +#include "wine/asm.h" + +#ifdef _WIN64 + +#define VTABLE_ADD_FUNC(name) "\t.quad " THISCALL_NAME(name) "\n" + +#define __ASM_VTABLE(name,funcs) \ + __asm__(".data\n" \ + "\t.balign 8\n" \ + "\t.quad " __ASM_NAME(#name "_rtti") "\n" \ + "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \ + __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \ + funcs "\n\t.text") + +#else + +#define VTABLE_ADD_FUNC(name) "\t.long " THISCALL_NAME(name) "\n" + +#define __ASM_VTABLE(name,funcs) \ + __asm__(".data\n" \ + "\t.balign 4\n" \ + "\t.long " __ASM_NAME(#name "_rtti") "\n" \ + "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \ + __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \ + funcs "\n\t.text") + +#endif /* _WIN64 */ + +#ifndef __x86_64__ + +#define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \ + static type_info name ## _type_info = { \ + &MSVCRT_type_info_vtable, \ + NULL, \ + mangled_name \ + }; \ +\ +static const rtti_base_descriptor name ## _rtti_base_descriptor = { \ + &name ##_type_info, \ + base_classes_no, \ + { 0, -1, 0}, \ + 64 \ +}; \ +\ +static const rtti_base_array name ## _rtti_base_array = { \ + { \ + &name ## _rtti_base_descriptor, \ + cl1, \ + cl2, \ + cl3, \ + cl4, \ + cl5, \ + cl6, \ + cl7, \ + cl8, \ + cl9, \ + } \ +}; \ +\ +static const rtti_object_hierarchy name ## _hierarchy = { \ + 0, \ + 0, \ + base_classes_no+1, \ + &name ## _rtti_base_array \ +}; \ +\ +const rtti_object_locator name ## _rtti = { \ + 0, \ + off, \ + 0, \ + &name ## _type_info, \ + &name ## _hierarchy \ +}; + +#else + +#define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \ + static type_info name ## _type_info = { \ + &MSVCRT_type_info_vtable, \ + NULL, \ + mangled_name \ + }; \ +\ +static rtti_base_descriptor name ## _rtti_base_descriptor = { \ + 0xdeadbeef, \ + base_classes_no, \ + { 0, -1, 0}, \ + 64 \ +}; \ +\ +static rtti_base_array name ## _rtti_base_array = { \ + { \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + } \ +}; \ +\ +static rtti_object_hierarchy name ## _hierarchy = { \ + 0, \ + 0, \ + base_classes_no+1, \ + 0xdeadbeef \ +}; \ +\ +rtti_object_locator name ## _rtti = { \ + 1, \ + off, \ + 0, \ + 0xdeadbeef, \ + 0xdeadbeef, \ + 0xdeadbeef \ +};\ +\ +static void init_ ## name ## _rtti(char *base) \ +{ \ + name ## _rtti_base_descriptor.type_descriptor = (char*)&name ## _type_info - base; \ + name ## _rtti_base_array.bases[0] = (char*)&name ## _rtti_base_descriptor - base; \ + name ## _rtti_base_array.bases[1] = (char*)cl1 - base; \ + name ## _rtti_base_array.bases[2] = (char*)cl2 - base; \ + name ## _rtti_base_array.bases[3] = (char*)cl3 - base; \ + name ## _rtti_base_array.bases[4] = (char*)cl4 - base; \ + name ## _rtti_base_array.bases[5] = (char*)cl5 - base; \ + name ## _rtti_base_array.bases[6] = (char*)cl6 - base; \ + name ## _rtti_base_array.bases[7] = (char*)cl7 - base; \ + name ## _rtti_base_array.bases[8] = (char*)cl8 - base; \ + name ## _rtti_base_array.bases[9] = (char*)cl9 - base; \ + name ## _hierarchy.base_classes = (char*)&name ## _rtti_base_array - base; \ + name ## _rtti.type_descriptor = (char*)&name ## _type_info - base; \ + name ## _rtti.type_hierarchy = (char*)&name ## _hierarchy - base; \ + name ## _rtti.object_locator = (char*)&name ## _rtti - base; \ +} + +#endif + +#define DEFINE_RTTI_DATA0(name, off, mangled_name) \ + DEFINE_RTTI_DATA(name, off, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) +#define DEFINE_RTTI_DATA1(name, off, cl1, mangled_name) \ + DEFINE_RTTI_DATA(name, off, 1, cl1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) +#define DEFINE_RTTI_DATA2(name, off, cl1, cl2, mangled_name) \ + DEFINE_RTTI_DATA(name, off, 2, cl1, cl2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) +#define DEFINE_RTTI_DATA3(name, off, cl1, cl2, cl3, mangled_name) \ + DEFINE_RTTI_DATA(name, off, 3, cl1, cl2, cl3, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) +#define DEFINE_RTTI_DATA4(name, off, cl1, cl2, cl3, cl4, mangled_name) \ + DEFINE_RTTI_DATA(name, off, 4, cl1, cl2, cl3, cl4, NULL, NULL, NULL, NULL, NULL, mangled_name) +#define DEFINE_RTTI_DATA8(name, off, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, mangled_name) \ + DEFINE_RTTI_DATA(name, off, 8, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, NULL, mangled_name) +#define DEFINE_RTTI_DATA9(name, off, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \ + DEFINE_RTTI_DATA(name, off, 9, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) + +#ifndef __x86_64__ + +typedef struct _rtti_base_descriptor +{ + const type_info *type_descriptor; + int num_base_classes; + this_ptr_offsets offsets; /* offsets for computing the this pointer */ + unsigned int attributes; +} rtti_base_descriptor; + +typedef struct _rtti_base_array +{ + const rtti_base_descriptor *bases[10]; /* First element is the class itself */ +} rtti_base_array; + +typedef struct _rtti_object_hierarchy +{ + unsigned int signature; + unsigned int attributes; + int array_len; /* Size of the array pointed to by 'base_classes' */ + const rtti_base_array *base_classes; +} rtti_object_hierarchy; + +typedef struct _rtti_object_locator +{ + unsigned int signature; + int base_class_offset; + unsigned int flags; + const type_info *type_descriptor; + const rtti_object_hierarchy *type_hierarchy; +} rtti_object_locator; + +#else + +typedef struct +{ + unsigned int type_descriptor; + int num_base_classes; + this_ptr_offsets offsets; /* offsets for computing the this pointer */ + unsigned int attributes; +} rtti_base_descriptor; + +typedef struct +{ + unsigned int bases[10]; /* First element is the class itself */ +} rtti_base_array; + +typedef struct +{ + unsigned int signature; + unsigned int attributes; + int array_len; /* Size of the array pointed to by 'base_classes' */ + unsigned int base_classes; +} rtti_object_hierarchy; + +typedef struct +{ + unsigned int signature; + int base_class_offset; + unsigned int flags; + unsigned int type_descriptor; + unsigned int type_hierarchy; + unsigned int object_locator; +} rtti_object_locator; + +#endif + +#if defined(__i386__) && !defined(__MINGW32__) + +#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (WINAPI*)type)&vtbl_wrapper_##off)args + +extern void *vtbl_wrapper_0; +extern void *vtbl_wrapper_4; +extern void *vtbl_wrapper_8; +extern void *vtbl_wrapper_12; +extern void *vtbl_wrapper_16; +extern void *vtbl_wrapper_20; +extern void *vtbl_wrapper_24; +extern void *vtbl_wrapper_28; +extern void *vtbl_wrapper_32; +extern void *vtbl_wrapper_36; +extern void *vtbl_wrapper_40; +extern void *vtbl_wrapper_44; +extern void *vtbl_wrapper_48; + +#else + +#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (__thiscall***)type)this)[0][off/4]args + +#endif + +//exception* __thiscall MSVCRT_exception_ctor(exception*, const char**); diff --git a/sdk/lib/crt/wine/except.c b/sdk/lib/crt/wine/except.c new file mode 100644 index 00000000000..147ed5e9ef0 --- /dev/null +++ b/sdk/lib/crt/wine/except.c @@ -0,0 +1,545 @@ +/* + * msvcrt.dll exception handling + * + * Copyright 2000 Jon Griffiths + * Copyright 2005 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + * + * FIXME: Incomplete support for nested exceptions/try block cleanup. + */ + +#include "config.h" +#include "wine/port.h" + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "wine/exception.h" +#include "msvcrt.h" +#include "excpt.h" +#include "wincon.h" +#include "wine/debug.h" + +#include "cppexcept.h" + +WINE_DEFAULT_DEBUG_CHANNEL(seh); + +#if _MSVCR_VER>=70 && _MSVCR_VER<=71 +static MSVCRT_security_error_handler security_error_handler; +#endif + +static MSVCRT___sighandler_t sighandlers[MSVCRT_NSIG] = { MSVCRT_SIG_DFL }; + +static BOOL WINAPI msvcrt_console_handler(DWORD ctrlType) +{ + BOOL ret = FALSE; + + switch (ctrlType) + { + case CTRL_C_EVENT: + if (sighandlers[MSVCRT_SIGINT]) + { + if (sighandlers[MSVCRT_SIGINT] != MSVCRT_SIG_IGN) + sighandlers[MSVCRT_SIGINT](MSVCRT_SIGINT); + ret = TRUE; + } + break; + } + return ret; +} + +/********************************************************************* + * __pxcptinfoptrs (MSVCRT.@) + */ +void** CDECL MSVCRT___pxcptinfoptrs(void) +{ + return (void**)&msvcrt_get_thread_data()->xcptinfo; +} + +typedef void (CDECL *float_handler)(int, int); + +/* The exception codes are actually NTSTATUS values */ +static const struct +{ + NTSTATUS status; + int signal; +} float_exception_map[] = { + { EXCEPTION_FLT_DENORMAL_OPERAND, MSVCRT__FPE_DENORMAL }, + { EXCEPTION_FLT_DIVIDE_BY_ZERO, MSVCRT__FPE_ZERODIVIDE }, + { EXCEPTION_FLT_INEXACT_RESULT, MSVCRT__FPE_INEXACT }, + { EXCEPTION_FLT_INVALID_OPERATION, MSVCRT__FPE_INVALID }, + { EXCEPTION_FLT_OVERFLOW, MSVCRT__FPE_OVERFLOW }, + { EXCEPTION_FLT_STACK_CHECK, MSVCRT__FPE_STACKOVERFLOW }, + { EXCEPTION_FLT_UNDERFLOW, MSVCRT__FPE_UNDERFLOW }, +}; + +static LONG msvcrt_exception_filter(struct _EXCEPTION_POINTERS *except) +{ + LONG ret = EXCEPTION_CONTINUE_SEARCH; + MSVCRT___sighandler_t handler; + + if (!except || !except->ExceptionRecord) + return EXCEPTION_CONTINUE_SEARCH; + + switch (except->ExceptionRecord->ExceptionCode) + { + case EXCEPTION_ACCESS_VIOLATION: + if ((handler = sighandlers[MSVCRT_SIGSEGV]) != MSVCRT_SIG_DFL) + { + if (handler != MSVCRT_SIG_IGN) + { + EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)MSVCRT___pxcptinfoptrs(), *old_ep; + + old_ep = *ep; + *ep = except; + sighandlers[MSVCRT_SIGSEGV] = MSVCRT_SIG_DFL; + handler(MSVCRT_SIGSEGV); + *ep = old_ep; + } + ret = EXCEPTION_CONTINUE_EXECUTION; + } + break; + /* According to msdn, + * the FPE signal handler takes as a second argument the type of + * floating point exception. + */ + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_FLT_UNDERFLOW: + if ((handler = sighandlers[MSVCRT_SIGFPE]) != MSVCRT_SIG_DFL) + { + if (handler != MSVCRT_SIG_IGN) + { + EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)MSVCRT___pxcptinfoptrs(), *old_ep; + unsigned int i; + int float_signal = MSVCRT__FPE_INVALID; + + sighandlers[MSVCRT_SIGFPE] = MSVCRT_SIG_DFL; + for (i = 0; i < ARRAY_SIZE(float_exception_map); i++) + { + if (float_exception_map[i].status == + except->ExceptionRecord->ExceptionCode) + { + float_signal = float_exception_map[i].signal; + break; + } + } + + old_ep = *ep; + *ep = except; + ((float_handler)handler)(MSVCRT_SIGFPE, float_signal); + *ep = old_ep; + } + ret = EXCEPTION_CONTINUE_EXECUTION; + } + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + case EXCEPTION_PRIV_INSTRUCTION: + if ((handler = sighandlers[MSVCRT_SIGILL]) != MSVCRT_SIG_DFL) + { + if (handler != MSVCRT_SIG_IGN) + { + EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)MSVCRT___pxcptinfoptrs(), *old_ep; + + old_ep = *ep; + *ep = except; + sighandlers[MSVCRT_SIGILL] = MSVCRT_SIG_DFL; + handler(MSVCRT_SIGILL); + *ep = old_ep; + } + ret = EXCEPTION_CONTINUE_EXECUTION; + } + break; + } + return ret; +} + +void msvcrt_init_signals(void) +{ + SetConsoleCtrlHandler(msvcrt_console_handler, TRUE); +} + +void msvcrt_free_signals(void) +{ + SetConsoleCtrlHandler(msvcrt_console_handler, FALSE); +} + +/********************************************************************* + * signal (MSVCRT.@) + * Some signals may never be generated except through an explicit call to + * raise. + */ +MSVCRT___sighandler_t CDECL MSVCRT_signal(int sig, MSVCRT___sighandler_t func) +{ + MSVCRT___sighandler_t ret = MSVCRT_SIG_ERR; + + TRACE("(%d, %p)\n", sig, func); + + if (func == MSVCRT_SIG_ERR) return MSVCRT_SIG_ERR; + + switch (sig) + { + /* Cases handled internally. Note SIGTERM is never generated by Windows, + * so we effectively mask it. + */ + case MSVCRT_SIGABRT: + case MSVCRT_SIGFPE: + case MSVCRT_SIGILL: + case MSVCRT_SIGSEGV: + case MSVCRT_SIGINT: + case MSVCRT_SIGTERM: + case MSVCRT_SIGBREAK: + ret = sighandlers[sig]; + sighandlers[sig] = func; + break; + default: + ret = MSVCRT_SIG_ERR; + } + return ret; +} + +/********************************************************************* + * raise (MSVCRT.@) + */ +int CDECL MSVCRT_raise(int sig) +{ + MSVCRT___sighandler_t handler; + + TRACE("(%d)\n", sig); + + switch (sig) + { + case MSVCRT_SIGFPE: + case MSVCRT_SIGILL: + case MSVCRT_SIGSEGV: + handler = sighandlers[sig]; + if (handler == MSVCRT_SIG_DFL) MSVCRT__exit(3); + if (handler != MSVCRT_SIG_IGN) + { + EXCEPTION_POINTERS **ep = (EXCEPTION_POINTERS**)MSVCRT___pxcptinfoptrs(), *old_ep; + + sighandlers[sig] = MSVCRT_SIG_DFL; + + old_ep = *ep; + *ep = NULL; + if (sig == MSVCRT_SIGFPE) + ((float_handler)handler)(sig, MSVCRT__FPE_EXPLICITGEN); + else + handler(sig); + *ep = old_ep; + } + break; + case MSVCRT_SIGABRT: + case MSVCRT_SIGINT: + case MSVCRT_SIGTERM: + case MSVCRT_SIGBREAK: + handler = sighandlers[sig]; + if (handler == MSVCRT_SIG_DFL) MSVCRT__exit(3); + if (handler != MSVCRT_SIG_IGN) + { + sighandlers[sig] = MSVCRT_SIG_DFL; + handler(sig); + } + break; + default: + return -1; + } + return 0; +} + +/********************************************************************* + * _XcptFilter (MSVCRT.@) + */ +int CDECL _XcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr) +{ + TRACE("(%08x,%p)\n", ex, ptr); + /* I assume ptr->ExceptionRecord->ExceptionCode is the same as ex */ + return msvcrt_exception_filter(ptr); +} + +#ifndef __REACTOS__ +/********************************************************************* + * _abnormal_termination (MSVCRT.@) + */ +int CDECL _abnormal_termination(void) +{ + FIXME("(void)stub\n"); + return 0; +} +#endif /* __REACTOS__ */ + +/****************************************************************** + * __uncaught_exception (MSVCRT.@) + */ +BOOL CDECL MSVCRT___uncaught_exception(void) +{ + return msvcrt_get_thread_data()->processing_throw != 0; +} + +#if _MSVCR_VER>=70 && _MSVCR_VER<=71 + +/********************************************************************* + * _set_security_error_handler (MSVCR70.@) + */ +MSVCRT_security_error_handler CDECL _set_security_error_handler( + MSVCRT_security_error_handler handler ) +{ + MSVCRT_security_error_handler old = security_error_handler; + + TRACE("(%p)\n", handler); + + security_error_handler = handler; + return old; +} + +/********************************************************************* + * __security_error_handler (MSVCR70.@) + */ +void CDECL __security_error_handler(int code, void *data) +{ + if(security_error_handler) + security_error_handler(code, data); + else + FIXME("(%d, %p) stub\n", code, data); + + MSVCRT__exit(3); +} + +#endif /* _MSVCR_VER>=70 && _MSVCR_VER<=71 */ + +#if _MSVCR_VER>=110 +/********************************************************************* + * __crtSetUnhandledExceptionFilter (MSVCR110.@) + */ +LPTOP_LEVEL_EXCEPTION_FILTER CDECL MSVCR110__crtSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER filter) +{ + return SetUnhandledExceptionFilter(filter); +} +#endif + +/********************************************************************* + * _CreateFrameInfo (MSVCR80.@) + */ +frame_info* CDECL _CreateFrameInfo(frame_info *fi, void *obj) +{ + thread_data_t *data = msvcrt_get_thread_data(); + + TRACE("(%p, %p)\n", fi, obj); + + fi->next = data->frame_info_head; + data->frame_info_head = fi; + fi->object = obj; + return fi; +} + +/********************************************************************* + * _FindAndUnlinkFrame (MSVCR80.@) + */ +void CDECL _FindAndUnlinkFrame(frame_info *fi) +{ + thread_data_t *data = msvcrt_get_thread_data(); + frame_info *cur = data->frame_info_head; + + TRACE("(%p)\n", fi); + + if (cur == fi) + { + data->frame_info_head = cur->next; + return; + } + + for (; cur->next; cur = cur->next) + { + if (cur->next == fi) + { + cur->next = fi->next; + return; + } + } + + ERR("frame not found, native crashes in this case\n"); +} + +/********************************************************************* + * _IsExceptionObjectToBeDestroyed (MSVCR80.@) + */ +BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void *obj) +{ + frame_info *cur; + + TRACE( "%p\n", obj ); + + for (cur = msvcrt_get_thread_data()->frame_info_head; cur; cur = cur->next) + { + if (cur->object == obj) + return FALSE; + } + + return TRUE; +} + +/********************************************************************* + * __DestructExceptionObject (MSVCRT.@) + */ +void CDECL __DestructExceptionObject(EXCEPTION_RECORD *rec) +{ + cxx_exception_type *info = (cxx_exception_type*) rec->ExceptionInformation[2]; + void *object = (void*)rec->ExceptionInformation[1]; + + TRACE("(%p)\n", rec); + + if (rec->ExceptionCode != CXX_EXCEPTION) return; +#ifndef __x86_64__ + if (rec->NumberParameters != 3) return; +#else + if (rec->NumberParameters != 4) return; +#endif + if (rec->ExceptionInformation[0] < CXX_FRAME_MAGIC_VC6 || + rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8) return; + + if (!info || !info->destructor) + return; + +#if defined(__i386__) +#ifdef _MSC_VER + ((void(__fastcall*)(void*))info->destructor)(object); +#else + __asm__ __volatile__("call *%0" : : "r" (info->destructor), "c" (object) : "eax", "edx", "memory"); +#endif +#elif defined(__x86_64__) + ((void (__cdecl*)(void*))(info->destructor+rec->ExceptionInformation[3]))(object); +#else + ((void (__cdecl*)(void*))info->destructor)(object); +#endif +} + +/********************************************************************* + * __CxxRegisterExceptionObject (MSVCRT.@) + */ +BOOL CDECL __CxxRegisterExceptionObject(EXCEPTION_POINTERS *ep, cxx_frame_info *frame_info) +{ + thread_data_t *data = msvcrt_get_thread_data(); + + TRACE("(%p, %p)\n", ep, frame_info); + + if (!ep || !ep->ExceptionRecord) + { + frame_info->rec = (void*)-1; + frame_info->context = (void*)-1; + return TRUE; + } + + frame_info->rec = data->exc_record; + frame_info->context = data->ctx_record; + data->exc_record = ep->ExceptionRecord; + data->ctx_record = ep->ContextRecord; + _CreateFrameInfo(&frame_info->frame_info, (void*)ep->ExceptionRecord->ExceptionInformation[1]); + return TRUE; +} + +/********************************************************************* + * __CxxUnregisterExceptionObject (MSVCRT.@) + */ +void CDECL __CxxUnregisterExceptionObject(cxx_frame_info *frame_info, BOOL in_use) +{ + thread_data_t *data = msvcrt_get_thread_data(); + + TRACE("(%p)\n", frame_info); + + if(frame_info->rec == (void*)-1) + return; + + _FindAndUnlinkFrame(&frame_info->frame_info); + if(data->exc_record->ExceptionCode == CXX_EXCEPTION && !in_use + && _IsExceptionObjectToBeDestroyed((void*)data->exc_record->ExceptionInformation[1])) + __DestructExceptionObject(data->exc_record); + data->exc_record = frame_info->rec; + data->ctx_record = frame_info->context; +} + +struct __std_exception_data { + char *what; + MSVCRT_bool dofree; +}; + +#if _MSVCR_VER>=140 + +/********************************************************************* + * __std_exception_copy (UCRTBASE.@) + */ +void CDECL MSVCRT___std_exception_copy(const struct __std_exception_data *src, + struct __std_exception_data *dst) +{ + TRACE("(%p %p)\n", src, dst); + + if(src->dofree && src->what) { + dst->what = MSVCRT__strdup(src->what); + dst->dofree = 1; + } else { + dst->what = src->what; + dst->dofree = 0; + } +} + +/********************************************************************* + * __std_exception_destroy (UCRTBASE.@) + */ +void CDECL MSVCRT___std_exception_destroy(struct __std_exception_data *data) +{ + TRACE("(%p)\n", data); + + if(data->dofree) + MSVCRT_free(data->what); + data->what = NULL; + data->dofree = 0; +} + +/********************************************************************* + * __current_exception (UCRTBASE.@) + */ +void** CDECL __current_exception(void) +{ + TRACE("()\n"); + return (void**)&msvcrt_get_thread_data()->exc_record; +} + +/********************************************************************* + * __current_exception_context (UCRTBASE.@) + */ +void** CDECL __current_exception_context(void) +{ + TRACE("()\n"); + return (void**)&msvcrt_get_thread_data()->ctx_record; +} + +/********************************************************************* + * __processing_throw (UCRTBASE.@) + */ +int* CDECL __processing_throw(void) +{ + TRACE("()\n"); + return &msvcrt_get_thread_data()->processing_throw; +} + +#endif /* _MSVCR_VER>=140 */ diff --git a/sdk/lib/crt/wine/except_arm.c b/sdk/lib/crt/wine/except_arm.c new file mode 100644 index 00000000000..41b0c1c7d3e --- /dev/null +++ b/sdk/lib/crt/wine/except_arm.c @@ -0,0 +1,147 @@ +/* + * msvcrt C++ exception handling + * + * Copyright 2011 Alexandre Julliard + * Copyright 2013 André Hentschel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + */ + +#include "config.h" +#include "wine/port.h" + +#ifdef __arm__ + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "msvcrt.h" +#include "wine/exception.h" +#include "excpt.h" +#include "wine/debug.h" + +#include "cppexcept.h" + +WINE_DEFAULT_DEBUG_CHANNEL(seh); + + +/********************************************************************* + * __CxxExceptionFilter (MSVCRT.@) + */ +int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs, + const type_info *ti, int flags, void **copy ) +{ + FIXME( "%p %p %x %p: not implemented\n", ptrs, ti, flags, copy ); + return EXCEPTION_CONTINUE_SEARCH; +} + +/********************************************************************* + * __CxxFrameHandler (MSVCRT.@) + */ +EXCEPTION_DISPOSITION CDECL __CxxFrameHandler(EXCEPTION_RECORD *rec, DWORD frame, CONTEXT *context, + DISPATCHER_CONTEXT *dispatch) +{ + FIXME("%p %x %p %p: not implemented\n", rec, frame, context, dispatch); + return ExceptionContinueSearch; +} + + +/********************************************************************* + * __CppXcptFilter (MSVCRT.@) + */ +int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr) +{ + /* only filter c++ exceptions */ + if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH; + return _XcptFilter(ex, ptr); +} + + +/********************************************************************* + * __CxxDetectRethrow (MSVCRT.@) + */ +BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs) +{ + PEXCEPTION_RECORD rec; + + if (!ptrs) + return FALSE; + + rec = ptrs->ExceptionRecord; + + if (rec->ExceptionCode == CXX_EXCEPTION && + rec->NumberParameters == 3 && + rec->ExceptionInformation[0] == CXX_FRAME_MAGIC_VC6 && + rec->ExceptionInformation[2]) + { + ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record; + return TRUE; + } + return (msvcrt_get_thread_data()->exc_record == rec); +} + + +/********************************************************************* + * __CxxQueryExceptionSize (MSVCRT.@) + */ +unsigned int CDECL __CxxQueryExceptionSize(void) +{ + return sizeof(cxx_exception_type); +} + + +/******************************************************************* + * _setjmp (MSVCRT.@) + */ +__ASM_GLOBAL_FUNC(MSVCRT__setjmp, + "mov r1, #0\n\t" /* frame */ + "b " __ASM_NAME("__wine_setjmpex")); + +/******************************************************************* + * longjmp (MSVCRT.@) + */ +void __cdecl MSVCRT_longjmp(struct MSVCRT___JUMP_BUFFER *jmp, int retval) +{ + EXCEPTION_RECORD rec; + + if (!retval) retval = 1; + if (jmp->Frame) + { + rec.ExceptionCode = STATUS_LONGJUMP; + rec.ExceptionFlags = 0; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = NULL; + rec.NumberParameters = 1; + rec.ExceptionInformation[0] = (DWORD_PTR)jmp; + RtlUnwind((void *)jmp->Frame, (void *)jmp->Pc, &rec, IntToPtr(retval)); + } + __wine_longjmp( (__wine_jmp_buf *)jmp, retval ); +} + +/********************************************************************* + * _fpieee_flt (MSVCRT.@) + */ +int __cdecl _fpieee_flt(ULONG exception_code, EXCEPTION_POINTERS *ep, + int (__cdecl *handler)(_FPIEEE_RECORD*)) +{ + FIXME("(%x %p %p)\n", exception_code, ep, handler); + return EXCEPTION_CONTINUE_SEARCH; +} + +#endif /* __arm__ */ diff --git a/sdk/lib/crt/wine/except_arm64.c b/sdk/lib/crt/wine/except_arm64.c new file mode 100644 index 00000000000..97059d13972 --- /dev/null +++ b/sdk/lib/crt/wine/except_arm64.c @@ -0,0 +1,148 @@ +/* + * msvcrt C++ exception handling + * + * Copyright 2011 Alexandre Julliard + * Copyright 2013 André Hentschel + * Copyright 2017 Martin Storsjo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + */ + +#include "config.h" +#include "wine/port.h" + +#ifdef __aarch64__ + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "msvcrt.h" +#include "wine/exception.h" +#include "excpt.h" +#include "wine/debug.h" + +#include "cppexcept.h" + +WINE_DEFAULT_DEBUG_CHANNEL(seh); + + +/********************************************************************* + * __CxxExceptionFilter (MSVCRT.@) + */ +int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs, + const type_info *ti, int flags, void **copy ) +{ + FIXME( "%p %p %x %p: not implemented\n", ptrs, ti, flags, copy ); + return EXCEPTION_CONTINUE_SEARCH; +} + +/********************************************************************* + * __CxxFrameHandler (MSVCRT.@) + */ +EXCEPTION_DISPOSITION CDECL __CxxFrameHandler(EXCEPTION_RECORD *rec, DWORD frame, CONTEXT *context, + DISPATCHER_CONTEXT *dispatch) +{ + FIXME("%p %x %p %p: not implemented\n", rec, frame, context, dispatch); + return ExceptionContinueSearch; +} + + +/********************************************************************* + * __CppXcptFilter (MSVCRT.@) + */ +int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr) +{ + /* only filter c++ exceptions */ + if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH; + return _XcptFilter(ex, ptr); +} + + +/********************************************************************* + * __CxxDetectRethrow (MSVCRT.@) + */ +BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs) +{ + PEXCEPTION_RECORD rec; + + if (!ptrs) + return FALSE; + + rec = ptrs->ExceptionRecord; + + if (rec->ExceptionCode == CXX_EXCEPTION && + rec->NumberParameters == 3 && + rec->ExceptionInformation[0] == CXX_FRAME_MAGIC_VC6 && + rec->ExceptionInformation[2]) + { + ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record; + return TRUE; + } + return (msvcrt_get_thread_data()->exc_record == rec); +} + + +/********************************************************************* + * __CxxQueryExceptionSize (MSVCRT.@) + */ +unsigned int CDECL __CxxQueryExceptionSize(void) +{ + return sizeof(cxx_exception_type); +} + + +/******************************************************************* + * _setjmp (MSVCRT.@) + */ +__ASM_GLOBAL_FUNC(MSVCRT__setjmp, + "mov x1, #0\n\t" /* frame */ + "b " __ASM_NAME("__wine_setjmpex")); + +/******************************************************************* + * longjmp (MSVCRT.@) + */ +void __cdecl MSVCRT_longjmp(struct MSVCRT___JUMP_BUFFER *jmp, int retval) +{ + EXCEPTION_RECORD rec; + + if (!retval) retval = 1; + if (jmp->Frame) + { + rec.ExceptionCode = STATUS_LONGJUMP; + rec.ExceptionFlags = 0; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = NULL; + rec.NumberParameters = 1; + rec.ExceptionInformation[0] = (DWORD_PTR)jmp; + RtlUnwind((void *)jmp->Frame, (void *)jmp->Lr, &rec, IntToPtr(retval)); + } + __wine_longjmp( (__wine_jmp_buf *)jmp, retval ); +} + +/********************************************************************* + * _fpieee_flt (MSVCRT.@) + */ +int __cdecl _fpieee_flt(ULONG exception_code, EXCEPTION_POINTERS *ep, + int (__cdecl *handler)(_FPIEEE_RECORD*)) +{ + FIXME("(%x %p %p)\n", exception_code, ep, handler); + return EXCEPTION_CONTINUE_SEARCH; +} + +#endif /* __aarch64__ */ diff --git a/sdk/lib/crt/wine/except_i386.c b/sdk/lib/crt/wine/except_i386.c new file mode 100644 index 00000000000..acb8223075c --- /dev/null +++ b/sdk/lib/crt/wine/except_i386.c @@ -0,0 +1,1235 @@ +/* + * msvcrt C++ exception handling + * + * Copyright 2000 Jon Griffiths + * Copyright 2002 Alexandre Julliard + * Copyright 2005 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + * A good reference is the article "How a C++ compiler implements + * exception handling" by Vishal Kochhar, available on + * www.thecodeproject.com. + */ + +#include "config.h" +#include "wine/port.h" + +#ifdef __i386__ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "msvcrt.h" +#include "wine/exception.h" +#include "excpt.h" +#include "wine/debug.h" + +#include "cppexcept.h" + +WINE_DEFAULT_DEBUG_CHANNEL(seh); + + +/* the exception frame used by CxxFrameHandler */ +typedef struct __cxx_exception_frame +{ + EXCEPTION_REGISTRATION_RECORD frame; /* the standard exception frame */ + int trylevel; + DWORD ebp; +} cxx_exception_frame; + +/* info about a single catch {} block */ +typedef struct __catchblock_info +{ + UINT flags; /* flags (see below) */ + const type_info *type_info; /* C++ type caught by this block */ + int offset; /* stack offset to copy exception object to */ + void * (*handler)(void);/* catch block handler code */ +} catchblock_info; +#define TYPE_FLAG_CONST 1 +#define TYPE_FLAG_VOLATILE 2 +#define TYPE_FLAG_REFERENCE 8 + +/* info about a single try {} block */ +typedef struct __tryblock_info +{ + int start_level; /* start trylevel of that block */ + int end_level; /* end trylevel of that block */ + int catch_level; /* initial trylevel of the catch block */ + int catchblock_count; /* count of catch blocks in array */ + const catchblock_info *catchblock; /* array of catch blocks */ +} tryblock_info; + +/* info about the unwind handler for a given trylevel */ +typedef struct __unwind_info +{ + int prev; /* prev trylevel unwind handler, to run after this one */ + void * (*handler)(void);/* unwind handler */ +} unwind_info; + +/* descriptor of all try blocks of a given function */ +typedef struct __cxx_function_descr +{ + UINT magic; /* must be CXX_FRAME_MAGIC */ + UINT unwind_count; /* number of unwind handlers */ + const unwind_info *unwind_table; /* array of unwind handlers */ + UINT tryblock_count; /* number of try blocks */ + const tryblock_info *tryblock; /* array of try blocks */ + UINT ipmap_count; + const void *ipmap; + const void *expect_list; /* expected exceptions list when magic >= VC7 */ + UINT flags; /* flags when magic >= VC8 */ +} cxx_function_descr; + +typedef struct +{ + cxx_exception_frame *frame; + const cxx_function_descr *descr; + EXCEPTION_REGISTRATION_RECORD *nested_frame; +} se_translator_ctx; + +typedef struct _SCOPETABLE +{ + int previousTryLevel; + int (*lpfnFilter)(PEXCEPTION_POINTERS); + void * (*lpfnHandler)(void); +} SCOPETABLE, *PSCOPETABLE; + +typedef struct _MSVCRT_EXCEPTION_FRAME +{ + EXCEPTION_REGISTRATION_RECORD *prev; + void (*handler)(PEXCEPTION_RECORD, EXCEPTION_REGISTRATION_RECORD*, + PCONTEXT, PEXCEPTION_RECORD); + PSCOPETABLE scopetable; + int trylevel; + int _ebp; + PEXCEPTION_POINTERS xpointers; +} MSVCRT_EXCEPTION_FRAME; + +typedef struct +{ + int gs_cookie_offset; + ULONG gs_cookie_xor; + int eh_cookie_offset; + ULONG eh_cookie_xor; + SCOPETABLE entries[1]; +} SCOPETABLE_V4; + +#define TRYLEVEL_END (-1) /* End of trylevel list */ + +DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame, + PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch, + const cxx_function_descr *descr, + EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel ) DECLSPEC_HIDDEN; + +/* call a copy constructor */ +extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase ); + +__ASM_GLOBAL_FUNC( call_copy_ctor, + "pushl %ebp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") + "movl %esp, %ebp\n\t" + __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") + "pushl $1\n\t" + "movl 12(%ebp), %ecx\n\t" + "pushl 16(%ebp)\n\t" + "call *8(%ebp)\n\t" + "leave\n" + __ASM_CFI(".cfi_def_cfa %esp,4\n\t") + __ASM_CFI(".cfi_same_value %ebp\n\t") + "ret" ); + +/* continue execution to the specified address after exception is caught */ +extern void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr ); + +__ASM_GLOBAL_FUNC( continue_after_catch, + "movl 4(%esp), %edx\n\t" + "movl 8(%esp), %eax\n\t" + "movl -4(%edx), %esp\n\t" + "leal 12(%edx), %ebp\n\t" + "jmp *%eax" ); + +extern void DECLSPEC_NORETURN call_finally_block( void *code_block, void *base_ptr ); + +__ASM_GLOBAL_FUNC( call_finally_block, + "movl 8(%esp), %ebp\n\t" + "jmp *4(%esp)" ); + +extern int call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *ebp ); + +__ASM_GLOBAL_FUNC( call_filter, + "pushl %ebp\n\t" + "pushl 12(%esp)\n\t" + "movl 20(%esp), %ebp\n\t" + "call *12(%esp)\n\t" + "popl %ebp\n\t" + "popl %ebp\n\t" + "ret" ); + +extern void *call_handler( void * (*func)(void), void *ebp ); + +__ASM_GLOBAL_FUNC( call_handler, + "pushl %ebp\n\t" + "pushl %ebx\n\t" + "pushl %esi\n\t" + "pushl %edi\n\t" + "movl 24(%esp), %ebp\n\t" + "call *20(%esp)\n\t" + "popl %edi\n\t" + "popl %esi\n\t" + "popl %ebx\n\t" + "popl %ebp\n\t" + "ret" ); + +static inline void dump_type( const cxx_type_info *type ) +{ + TRACE( "flags %x type %p %s offsets %d,%d,%d size %d copy ctor %p\n", + type->flags, type->type_info, dbgstr_type_info(type->type_info), + type->offsets.this_offset, type->offsets.vbase_descr, type->offsets.vbase_offset, + type->size, type->copy_ctor ); +} + +static void dump_exception_type( const cxx_exception_type *type ) +{ + UINT i; + + TRACE( "flags %x destr %p handler %p type info %p\n", + type->flags, type->destructor, type->custom_handler, type->type_info_table ); + for (i = 0; i < type->type_info_table->count; i++) + { + TRACE( " %d: ", i ); + dump_type( type->type_info_table->info[i] ); + } +} + +static void dump_function_descr( const cxx_function_descr *descr ) +{ + UINT i; + int j; + + TRACE( "magic %x\n", descr->magic ); + TRACE( "unwind table: %p %d\n", descr->unwind_table, descr->unwind_count ); + for (i = 0; i < descr->unwind_count; i++) + { + TRACE( " %d: prev %d func %p\n", i, + descr->unwind_table[i].prev, descr->unwind_table[i].handler ); + } + TRACE( "try table: %p %d\n", descr->tryblock, descr->tryblock_count ); + for (i = 0; i < descr->tryblock_count; i++) + { + TRACE( " %d: start %d end %d catchlevel %d catch %p %d\n", i, + descr->tryblock[i].start_level, descr->tryblock[i].end_level, + descr->tryblock[i].catch_level, descr->tryblock[i].catchblock, + descr->tryblock[i].catchblock_count ); + for (j = 0; j < descr->tryblock[i].catchblock_count; j++) + { + const catchblock_info *ptr = &descr->tryblock[i].catchblock[j]; + TRACE( " %d: flags %x offset %d handler %p type %p %s\n", + j, ptr->flags, ptr->offset, ptr->handler, + ptr->type_info, dbgstr_type_info( ptr->type_info ) ); + } + } + if (descr->magic <= CXX_FRAME_MAGIC_VC6) return; + TRACE( "expect list: %p\n", descr->expect_list ); + if (descr->magic <= CXX_FRAME_MAGIC_VC7) return; + TRACE( "flags: %08x\n", descr->flags ); +} + +/* check if the exception type is caught by a given catch block, and return the type that matched */ +static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type, + const type_info *catch_ti, UINT catch_flags ) +{ + UINT i; + + for (i = 0; i < exc_type->type_info_table->count; i++) + { + const cxx_type_info *type = exc_type->type_info_table->info[i]; + + if (!catch_ti) return type; /* catch(...) matches any type */ + if (catch_ti != type->type_info) + { + if (strcmp( catch_ti->mangled, type->type_info->mangled )) continue; + } + /* type is the same, now check the flags */ + if ((exc_type->flags & TYPE_FLAG_CONST) && + !(catch_flags & TYPE_FLAG_CONST)) continue; + if ((exc_type->flags & TYPE_FLAG_VOLATILE) && + !(catch_flags & TYPE_FLAG_VOLATILE)) continue; + return type; /* it matched */ + } + return NULL; +} + + +/* copy the exception object where the catch block wants it */ +static void copy_exception( void *object, cxx_exception_frame *frame, + const catchblock_info *catchblock, const cxx_type_info *type ) +{ + void **dest_ptr; + + if (!catchblock->type_info || !catchblock->type_info->mangled[0]) return; + if (!catchblock->offset) return; + dest_ptr = (void **)((char *)&frame->ebp + catchblock->offset); + + if (catchblock->flags & TYPE_FLAG_REFERENCE) + { + *dest_ptr = get_this_pointer( &type->offsets, object ); + } + else if (type->flags & CLASS_IS_SIMPLE_TYPE) + { + memmove( dest_ptr, object, type->size ); + /* if it is a pointer, adjust it */ + if (type->size == sizeof(void *)) *dest_ptr = get_this_pointer( &type->offsets, *dest_ptr ); + } + else /* copy the object */ + { + if (type->copy_ctor) + call_copy_ctor( type->copy_ctor, dest_ptr, get_this_pointer(&type->offsets,object), + (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) ); + else + memmove( dest_ptr, get_this_pointer(&type->offsets,object), type->size ); + } +} + +/* unwind the local function up to a given trylevel */ +static void cxx_local_unwind( cxx_exception_frame* frame, const cxx_function_descr *descr, int last_level) +{ + void * (*handler)(void); + int trylevel = frame->trylevel; + + while (trylevel != last_level) + { + if (trylevel < 0 || trylevel >= descr->unwind_count) + { + ERR( "invalid trylevel %d\n", trylevel ); + MSVCRT_terminate(); + } + handler = descr->unwind_table[trylevel].handler; + if (handler) + { + TRACE( "calling unwind handler %p trylevel %d last %d ebp %p\n", + handler, trylevel, last_level, &frame->ebp ); + call_handler( handler, &frame->ebp ); + } + trylevel = descr->unwind_table[trylevel].prev; + } + frame->trylevel = last_level; +} + +/* exception frame for nested exceptions in catch block */ +struct catch_func_nested_frame +{ + EXCEPTION_REGISTRATION_RECORD frame; /* standard exception frame */ + cxx_exception_frame *cxx_frame; /* frame of parent exception */ + const cxx_function_descr *descr; /* descriptor of parent exception */ + int trylevel; /* current try level */ + cxx_frame_info frame_info; +}; + +/* handler for exceptions happening while calling a catch function */ +static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, + CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) +{ + struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame; + + if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) + { + __CxxUnregisterExceptionObject(&nested_frame->frame_info, FALSE); + return ExceptionContinueSearch; + } + + TRACE( "got nested exception in catch function\n" ); + + if(rec->ExceptionCode == CXX_EXCEPTION) + { + PEXCEPTION_RECORD prev_rec = msvcrt_get_thread_data()->exc_record; + + if((rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) || + (prev_rec->ExceptionCode == CXX_EXCEPTION && + rec->ExceptionInformation[1] == prev_rec->ExceptionInformation[1] && + rec->ExceptionInformation[2] == prev_rec->ExceptionInformation[2])) + { + /* exception was rethrown */ + *rec = *prev_rec; + rec->ExceptionFlags &= ~EH_UNWINDING; + if(TRACE_ON(seh)) { + TRACE("detect rethrow: exception code: %x\n", rec->ExceptionCode); + if(rec->ExceptionCode == CXX_EXCEPTION) + TRACE("re-propagate: obj: %lx, type: %lx\n", + rec->ExceptionInformation[1], rec->ExceptionInformation[2]); + } + } + else + { + TRACE("detect threw new exception in catch block\n"); + } + } + + return cxx_frame_handler( rec, nested_frame->cxx_frame, context, + NULL, nested_frame->descr, &nested_frame->frame, + nested_frame->trylevel ); +} + +/* find and call the appropriate catch block for an exception */ +/* returns the address to continue execution to after the catch block was called */ +static inline void call_catch_block( PEXCEPTION_RECORD rec, CONTEXT *context, + cxx_exception_frame *frame, + const cxx_function_descr *descr, int nested_trylevel, + EXCEPTION_REGISTRATION_RECORD *catch_frame, + cxx_exception_type *info ) +{ + UINT i; + int j; + void *addr, *object = (void *)rec->ExceptionInformation[1]; + struct catch_func_nested_frame nested_frame; + int trylevel = frame->trylevel; + DWORD save_esp = ((DWORD*)frame)[-1]; + thread_data_t *data = msvcrt_get_thread_data(); + + data->processing_throw++; + for (i = 0; i < descr->tryblock_count; i++) + { + const tryblock_info *tryblock = &descr->tryblock[i]; + + /* only handle try blocks inside current catch block */ + if (catch_frame && nested_trylevel > tryblock->start_level) continue; + + if (trylevel < tryblock->start_level) continue; + if (trylevel > tryblock->end_level) continue; + + /* got a try block */ + for (j = 0; j < tryblock->catchblock_count; j++) + { + const catchblock_info *catchblock = &tryblock->catchblock[j]; + if(info) + { + const cxx_type_info *type = find_caught_type( info, + catchblock->type_info, catchblock->flags ); + if (!type) continue; + + TRACE( "matched type %p in tryblock %d catchblock %d\n", type, i, j ); + + /* copy the exception to its destination on the stack */ + copy_exception( object, frame, catchblock, type ); + } + else + { + /* no CXX_EXCEPTION only proceed with a catch(...) block*/ + if(catchblock->type_info) + continue; + TRACE("found catch(...) block\n"); + } + + /* Add frame info here so exception is not freed inside RtlUnwind call */ + _CreateFrameInfo(&nested_frame.frame_info.frame_info, + (void*)rec->ExceptionInformation[1]); + + /* unwind the stack */ + RtlUnwind( catch_frame ? catch_frame : &frame->frame, 0, rec, 0 ); + cxx_local_unwind( frame, descr, tryblock->start_level ); + frame->trylevel = tryblock->end_level + 1; + + nested_frame.frame_info.rec = data->exc_record; + nested_frame.frame_info.context = data->ctx_record; + data->exc_record = rec; + data->ctx_record = context; + data->processing_throw--; + + /* call the catch block */ + TRACE( "calling catch block %p addr %p ebp %p\n", + catchblock, catchblock->handler, &frame->ebp ); + + /* setup an exception block for nested exceptions */ + nested_frame.frame.Handler = catch_function_nested_handler; + nested_frame.cxx_frame = frame; + nested_frame.descr = descr; + nested_frame.trylevel = nested_trylevel + 1; + + __wine_push_frame( &nested_frame.frame ); + addr = call_handler( catchblock->handler, &frame->ebp ); + __wine_pop_frame( &nested_frame.frame ); + + ((DWORD*)frame)[-1] = save_esp; + __CxxUnregisterExceptionObject(&nested_frame.frame_info, FALSE); + TRACE( "done, continuing at %p\n", addr ); + + continue_after_catch( frame, addr ); + } + } + data->processing_throw--; +} + +/********************************************************************* + * __CxxExceptionFilter (MSVCRT.@) + */ +int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs, + const type_info *ti, int flags, void **copy) +{ + const cxx_type_info *type; + PEXCEPTION_RECORD rec; + + TRACE( "%p %p %x %p\n", ptrs, ti, flags, copy ); + + if (!ptrs) return EXCEPTION_CONTINUE_SEARCH; + + /* handle catch(...) */ + if (!ti) return EXCEPTION_EXECUTE_HANDLER; + + rec = ptrs->ExceptionRecord; + if (rec->ExceptionCode != CXX_EXCEPTION || rec->NumberParameters != 3 || + rec->ExceptionInformation[0] < CXX_FRAME_MAGIC_VC6 || + rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8) + return EXCEPTION_CONTINUE_SEARCH; + + if (rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) + { + rec = msvcrt_get_thread_data()->exc_record; + if (!rec) return EXCEPTION_CONTINUE_SEARCH; + } + + type = find_caught_type( (cxx_exception_type*)rec->ExceptionInformation[2], ti, flags ); + if (!type) return EXCEPTION_CONTINUE_SEARCH; + + if (copy) + { + void *object = (void *)rec->ExceptionInformation[1]; + + if (flags & TYPE_FLAG_REFERENCE) + { + *copy = get_this_pointer( &type->offsets, object ); + } + else if (type->flags & CLASS_IS_SIMPLE_TYPE) + { + memmove( copy, object, type->size ); + /* if it is a pointer, adjust it */ + if (type->size == sizeof(void*)) *copy = get_this_pointer( &type->offsets, *copy ); + } + else /* copy the object */ + { + if (type->copy_ctor) + call_copy_ctor( type->copy_ctor, copy, get_this_pointer(&type->offsets,object), + (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) ); + else + memmove( copy, get_this_pointer(&type->offsets,object), type->size ); + } + } + return EXCEPTION_EXECUTE_HANDLER; +} + +static LONG CALLBACK se_translation_filter( EXCEPTION_POINTERS *ep, void *c ) +{ + se_translator_ctx *ctx = (se_translator_ctx *)c; + EXCEPTION_RECORD *rec = ep->ExceptionRecord; + cxx_exception_type *exc_type; + + if (rec->ExceptionCode != CXX_EXCEPTION) + { + TRACE( "non-c++ exception thrown in SEH handler: %x\n", rec->ExceptionCode ); + MSVCRT_terminate(); + } + + exc_type = (cxx_exception_type *)rec->ExceptionInformation[2]; + call_catch_block( rec, ep->ContextRecord, ctx->frame, ctx->descr, + ctx->frame->trylevel, ctx->nested_frame, exc_type ); + + __DestructExceptionObject( rec ); + return ExceptionContinueSearch; +} + +/********************************************************************* + * cxx_frame_handler + * + * Implementation of __CxxFrameHandler. + */ +DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame, + PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch, + const cxx_function_descr *descr, + EXCEPTION_REGISTRATION_RECORD* nested_frame, + int nested_trylevel ) +{ + cxx_exception_type *exc_type; + + if (descr->magic < CXX_FRAME_MAGIC_VC6 || descr->magic > CXX_FRAME_MAGIC_VC8) + { + ERR( "invalid frame magic %x\n", descr->magic ); + return ExceptionContinueSearch; + } + if (descr->magic >= CXX_FRAME_MAGIC_VC8 && + (descr->flags & FUNC_DESCR_SYNCHRONOUS) && + (rec->ExceptionCode != CXX_EXCEPTION)) + return ExceptionContinueSearch; /* handle only c++ exceptions */ + + if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND)) + { + if (descr->unwind_count && !nested_trylevel) cxx_local_unwind( frame, descr, -1 ); + return ExceptionContinueSearch; + } + if (!descr->tryblock_count) return ExceptionContinueSearch; + + if(rec->ExceptionCode == CXX_EXCEPTION && + rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) + { + *rec = *msvcrt_get_thread_data()->exc_record; + rec->ExceptionFlags &= ~EH_UNWINDING; + if(TRACE_ON(seh)) { + TRACE("detect rethrow: exception code: %x\n", rec->ExceptionCode); + if(rec->ExceptionCode == CXX_EXCEPTION) + TRACE("re-propagate: obj: %lx, type: %lx\n", + rec->ExceptionInformation[1], rec->ExceptionInformation[2]); + } + } + + if(rec->ExceptionCode == CXX_EXCEPTION) + { + exc_type = (cxx_exception_type *)rec->ExceptionInformation[2]; + + if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8 && + exc_type->custom_handler) + { + return exc_type->custom_handler( rec, frame, context, dispatch, + descr, nested_trylevel, nested_frame, 0 ); + } + + if (TRACE_ON(seh)) + { + TRACE("handling C++ exception rec %p frame %p trylevel %d descr %p nested_frame %p\n", + rec, frame, frame->trylevel, descr, nested_frame ); + dump_exception_type( exc_type ); + dump_function_descr( descr ); + } + } + else + { + thread_data_t *data = msvcrt_get_thread_data(); + + exc_type = NULL; + TRACE("handling C exception code %x rec %p frame %p trylevel %d descr %p nested_frame %p\n", + rec->ExceptionCode, rec, frame, frame->trylevel, descr, nested_frame ); + + if (data->se_translator) { + EXCEPTION_POINTERS except_ptrs; + se_translator_ctx ctx; + + ctx.frame = frame; + ctx.descr = descr; + ctx.nested_frame = nested_frame; + __TRY + { + except_ptrs.ExceptionRecord = rec; + except_ptrs.ContextRecord = context; + data->se_translator( rec->ExceptionCode, &except_ptrs ); + } + __EXCEPT_CTX(se_translation_filter, &ctx) + { + } + __ENDTRY + } + } + + call_catch_block( rec, context, frame, descr, + frame->trylevel, nested_frame, exc_type ); + return ExceptionContinueSearch; +} + + +/********************************************************************* + * __CxxFrameHandler (MSVCRT.@) + */ +extern DWORD CDECL __CxxFrameHandler(PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame, + PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch); +#ifdef _MSC_VER +DWORD _declspec(naked) __CxxFrameHandler(PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame, + PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch) +{ + __asm + { + push 0 + push 0 + push eax + push[esp + 28] + push[esp + 28] + push[esp + 28] + push[esp + 28] + call cxx_frame_handler + add esp, 28 + ret + } +} +#else +__ASM_GLOBAL_FUNC(__CxxFrameHandler, + "pushl $0\n\t" /* nested_trylevel */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl $0\n\t" /* nested_frame */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl %eax\n\t" /* descr */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl 28(%esp)\n\t" /* dispatch */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl 28(%esp)\n\t" /* context */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl 28(%esp)\n\t" /* frame */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl 28(%esp)\n\t" /* rec */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "call " __ASM_NAME("cxx_frame_handler") "\n\t" + "add $28,%esp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset -28\n\t") + "ret") +#endif + + +/********************************************************************* + * __CxxLongjmpUnwind (MSVCRT.@) + * + * Callback meant to be used as UnwindFunc for setjmp/longjmp. + */ +void __stdcall __CxxLongjmpUnwind( const struct MSVCRT___JUMP_BUFFER *buf ) +{ + cxx_exception_frame *frame = (cxx_exception_frame *)buf->Registration; + const cxx_function_descr *descr = (const cxx_function_descr *)buf->UnwindData[0]; + + TRACE( "unwinding frame %p descr %p trylevel %ld\n", frame, descr, buf->TryLevel ); + cxx_local_unwind( frame, descr, buf->TryLevel ); +} + +/********************************************************************* + * __CppXcptFilter (MSVCRT.@) + */ +int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr) +{ + /* only filter c++ exceptions */ + if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH; + return _XcptFilter( ex, ptr ); +} + +/********************************************************************* + * __CxxDetectRethrow (MSVCRT.@) + */ +BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs) +{ + PEXCEPTION_RECORD rec; + + if (!ptrs) + return FALSE; + + rec = ptrs->ExceptionRecord; + + if (rec->ExceptionCode == CXX_EXCEPTION && + rec->NumberParameters == 3 && + rec->ExceptionInformation[0] == CXX_FRAME_MAGIC_VC6 && + rec->ExceptionInformation[2]) + { + ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record; + return TRUE; + } + return (msvcrt_get_thread_data()->exc_record == rec); +} + +/********************************************************************* + * __CxxQueryExceptionSize (MSVCRT.@) + */ +unsigned int CDECL __CxxQueryExceptionSize(void) +{ + return sizeof(cxx_exception_type); +} + + +/********************************************************************* + * _EH_prolog (MSVCRT.@) + */ + +/* Provided for VC++ binary compatibility only */ +__ASM_GLOBAL_FUNC(_EH_prolog, + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") /* skip ret addr */ + "pushl $-1\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl %eax\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl %fs:0\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "movl %esp, %fs:0\n\t" + "movl 12(%esp), %eax\n\t" + "movl %ebp, 12(%esp)\n\t" + "leal 12(%esp), %ebp\n\t" + "pushl %eax\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "ret") + +static const SCOPETABLE_V4 *get_scopetable_v4( MSVCRT_EXCEPTION_FRAME *frame, ULONG_PTR cookie ) +{ + return (const SCOPETABLE_V4 *)((ULONG_PTR)frame->scopetable ^ cookie); +} + +static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec, + EXCEPTION_REGISTRATION_RECORD* frame, + PCONTEXT context, + EXCEPTION_REGISTRATION_RECORD** dispatch) +{ + if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))) + return ExceptionContinueSearch; + *dispatch = frame; + return ExceptionCollidedUnwind; +} + +static void msvcrt_local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp) +{ + EXCEPTION_REGISTRATION_RECORD reg; + + TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel); + + /* Register a handler in case of a nested exception */ + reg.Handler = MSVCRT_nested_handler; + reg.Prev = NtCurrentTeb()->Tib.ExceptionList; + __wine_push_frame(®); + + while (frame->trylevel != TRYLEVEL_END && frame->trylevel != trylevel) + { + int level = frame->trylevel; + frame->trylevel = frame->scopetable[level].previousTryLevel; + if (!frame->scopetable[level].lpfnFilter) + { + TRACE( "__try block cleanup level %d handler %p ebp %p\n", + level, frame->scopetable[level].lpfnHandler, ebp ); + call_handler( frame->scopetable[level].lpfnHandler, ebp ); + } + } + __wine_pop_frame(®); + TRACE("unwound OK\n"); +} + +static void msvcrt_local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp ) +{ + EXCEPTION_REGISTRATION_RECORD reg; + const SCOPETABLE_V4 *scopetable = get_scopetable_v4( frame, *cookie ); + + TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel); + + /* Register a handler in case of a nested exception */ + reg.Handler = MSVCRT_nested_handler; + reg.Prev = NtCurrentTeb()->Tib.ExceptionList; + __wine_push_frame(®); + + while (frame->trylevel != -2 && frame->trylevel != trylevel) + { + int level = frame->trylevel; + frame->trylevel = scopetable->entries[level].previousTryLevel; + if (!scopetable->entries[level].lpfnFilter) + { + TRACE( "__try block cleanup level %d handler %p ebp %p\n", + level, scopetable->entries[level].lpfnHandler, ebp ); + call_handler( scopetable->entries[level].lpfnHandler, ebp ); + } + } + __wine_pop_frame(®); + TRACE("unwound OK\n"); +} +#ifndef __REACTOS__ +/******************************************************************* + * _local_unwind2 (MSVCRT.@) + */ +void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel) +{ + msvcrt_local_unwind2( frame, trylevel, &frame->_ebp ); +} +#endif +/******************************************************************* + * _local_unwind4 (MSVCRT.@) + */ +void CDECL _local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel ) +{ + msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp ); +} + +#ifndef __REACTOS__ +/******************************************************************* + * _global_unwind2 (MSVCRT.@) + */ +void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame) +{ + TRACE("(%p)\n",frame); + RtlUnwind( frame, 0, 0, 0 ); +} +#else +void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame); +#endif + +#ifndef __REACTOS__ +/********************************************************************* + * _except_handler2 (MSVCRT.@) + */ +int CDECL _except_handler2(PEXCEPTION_RECORD rec, + EXCEPTION_REGISTRATION_RECORD* frame, + PCONTEXT context, + EXCEPTION_REGISTRATION_RECORD** dispatcher) +{ + FIXME("exception %x flags=%x at %p handler=%p %p %p stub\n", + rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, + frame->Handler, context, dispatcher); + return ExceptionContinueSearch; +} + +/********************************************************************* + * _except_handler3 (MSVCRT.@) + */ +int CDECL _except_handler3(PEXCEPTION_RECORD rec, + MSVCRT_EXCEPTION_FRAME* frame, + PCONTEXT context, void* dispatcher) +{ + int retval, trylevel; + EXCEPTION_POINTERS exceptPtrs; + PSCOPETABLE pScopeTable; + + TRACE("exception %x flags=%x at %p handler=%p %p %p semi-stub\n", + rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, + frame->handler, context, dispatcher); + +#ifdef _MSC_VER + __asm{ cld } +#else + __asm__ __volatile__("cld"); +#endif + if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) + { + /* Unwinding the current frame */ + msvcrt_local_unwind2(frame, TRYLEVEL_END, &frame->_ebp); + TRACE("unwound current frame, returning ExceptionContinueSearch\n"); + return ExceptionContinueSearch; + } + else + { + /* Hunting for handler */ + exceptPtrs.ExceptionRecord = rec; + exceptPtrs.ContextRecord = context; + *((DWORD *)frame-1) = (DWORD)&exceptPtrs; + trylevel = frame->trylevel; + pScopeTable = frame->scopetable; + + while (trylevel != TRYLEVEL_END) + { + TRACE( "level %d prev %d filter %p\n", trylevel, pScopeTable[trylevel].previousTryLevel, + pScopeTable[trylevel].lpfnFilter ); + if (pScopeTable[trylevel].lpfnFilter) + { + retval = call_filter( pScopeTable[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp ); + + TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ? + "CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ? + "EXECUTE_HANDLER" : "CONTINUE_SEARCH"); + + if (retval == EXCEPTION_CONTINUE_EXECUTION) + return ExceptionContinueExecution; + + if (retval == EXCEPTION_EXECUTE_HANDLER) + { + /* Unwind all higher frames, this one will handle the exception */ + _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame); + msvcrt_local_unwind2(frame, trylevel, &frame->_ebp); + + /* Set our trylevel to the enclosing block, and call the __finally + * code, which won't return + */ + frame->trylevel = pScopeTable[trylevel].previousTryLevel; + TRACE("__finally block %p\n",pScopeTable[trylevel].lpfnHandler); + call_finally_block(pScopeTable[trylevel].lpfnHandler, &frame->_ebp); + } + } + trylevel = pScopeTable[trylevel].previousTryLevel; + } + } + TRACE("reached TRYLEVEL_END, returning ExceptionContinueSearch\n"); + return ExceptionContinueSearch; +} +#endif /* __REACTOS__ */ +/********************************************************************* + * _except_handler4_common (MSVCRT.@) + */ +int CDECL _except_handler4_common( ULONG *cookie, void (*check_cookie)(void), + EXCEPTION_RECORD *rec, MSVCRT_EXCEPTION_FRAME *frame, + CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) +{ + int retval, trylevel; + EXCEPTION_POINTERS exceptPtrs; + const SCOPETABLE_V4 *scope_table = get_scopetable_v4( frame, *cookie ); + + TRACE( "exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x\n", + rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, + frame->handler, context, dispatcher, *cookie, scope_table, + scope_table->gs_cookie_offset, scope_table->gs_cookie_xor, + scope_table->eh_cookie_offset, scope_table->eh_cookie_xor ); + + /* FIXME: no cookie validation yet */ + + if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) + { + /* Unwinding the current frame */ + msvcrt_local_unwind4( cookie, frame, -2, &frame->_ebp ); + TRACE("unwound current frame, returning ExceptionContinueSearch\n"); + return ExceptionContinueSearch; + } + else + { + /* Hunting for handler */ + exceptPtrs.ExceptionRecord = rec; + exceptPtrs.ContextRecord = context; + *((DWORD *)frame-1) = (DWORD)&exceptPtrs; + trylevel = frame->trylevel; + + while (trylevel != -2) + { + TRACE( "level %d prev %d filter %p\n", trylevel, + scope_table->entries[trylevel].previousTryLevel, + scope_table->entries[trylevel].lpfnFilter ); + if (scope_table->entries[trylevel].lpfnFilter) + { + retval = call_filter( scope_table->entries[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp ); + + TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ? + "CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ? + "EXECUTE_HANDLER" : "CONTINUE_SEARCH"); + + if (retval == EXCEPTION_CONTINUE_EXECUTION) + return ExceptionContinueExecution; + + if (retval == EXCEPTION_EXECUTE_HANDLER) + { + __DestructExceptionObject(rec); + + /* Unwind all higher frames, this one will handle the exception */ + _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame); + msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp ); + + /* Set our trylevel to the enclosing block, and call the __finally + * code, which won't return + */ + frame->trylevel = scope_table->entries[trylevel].previousTryLevel; + TRACE("__finally block %p\n",scope_table->entries[trylevel].lpfnHandler); + call_finally_block(scope_table->entries[trylevel].lpfnHandler, &frame->_ebp); + } + } + trylevel = scope_table->entries[trylevel].previousTryLevel; + } + } + TRACE("reached -2, returning ExceptionContinueSearch\n"); + return ExceptionContinueSearch; +} + + +/* + * setjmp/longjmp implementation + */ + +#define MSVCRT_JMP_MAGIC 0x56433230 /* ID value for new jump structure */ +typedef void (__stdcall *MSVCRT_unwind_function)(const struct MSVCRT___JUMP_BUFFER *); + +/* define an entrypoint for setjmp/setjmp3 that stores the registers in the jmp buf */ +/* and then jumps to the C backend function */ +#define DEFINE_SETJMP_ENTRYPOINT(name) \ + __ASM_GLOBAL_FUNC( name, \ + "movl 4(%esp),%ecx\n\t" /* jmp_buf */ \ + "movl %ebp,0(%ecx)\n\t" /* jmp_buf.Ebp */ \ + "movl %ebx,4(%ecx)\n\t" /* jmp_buf.Ebx */ \ + "movl %edi,8(%ecx)\n\t" /* jmp_buf.Edi */ \ + "movl %esi,12(%ecx)\n\t" /* jmp_buf.Esi */ \ + "movl %esp,16(%ecx)\n\t" /* jmp_buf.Esp */ \ + "movl 0(%esp),%eax\n\t" \ + "movl %eax,20(%ecx)\n\t" /* jmp_buf.Eip */ \ + "jmp " __ASM_NAME("__regs_") # name ) + +/******************************************************************* + * _setjmp (MSVCRT.@) + */ +DEFINE_SETJMP_ENTRYPOINT(MSVCRT__setjmp) +int CDECL DECLSPEC_HIDDEN __regs_MSVCRT__setjmp(struct MSVCRT___JUMP_BUFFER *jmp) +{ + jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList; + if (jmp->Registration == ~0UL) + jmp->TryLevel = TRYLEVEL_END; + else + jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel; + + TRACE("buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx\n", + jmp, jmp->Ebx, jmp->Esi, jmp->Edi, jmp->Ebp, jmp->Esp, jmp->Eip, jmp->Registration ); + return 0; +} + +/******************************************************************* + * _setjmp3 (MSVCRT.@) + */ +DEFINE_SETJMP_ENTRYPOINT( MSVCRT__setjmp3 ) +int WINAPIV DECLSPEC_HIDDEN __regs_MSVCRT__setjmp3(struct MSVCRT___JUMP_BUFFER *jmp, int nb_args, ...) +{ + jmp->Cookie = MSVCRT_JMP_MAGIC; + jmp->UnwindFunc = 0; + jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList; + if (jmp->Registration == ~0UL) + { + jmp->TryLevel = TRYLEVEL_END; + } + else + { + int i; + va_list args; + + va_start( args, nb_args ); + if (nb_args > 0) jmp->UnwindFunc = va_arg( args, unsigned long ); + if (nb_args > 1) jmp->TryLevel = va_arg( args, unsigned long ); + else jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel; + for (i = 0; i < 6 && i < nb_args - 2; i++) + jmp->UnwindData[i] = va_arg( args, unsigned long ); + va_end( args ); + } + + TRACE("buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx\n", + jmp, jmp->Ebx, jmp->Esi, jmp->Edi, jmp->Ebp, jmp->Esp, jmp->Eip, jmp->Registration ); + return 0; +} + +/********************************************************************* + * longjmp (MSVCRT.@) + */ +void CDECL MSVCRT_longjmp(struct MSVCRT___JUMP_BUFFER *jmp, int retval) +{ + unsigned long cur_frame = 0; + + TRACE("buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx retval=%08x\n", + jmp, jmp->Ebx, jmp->Esi, jmp->Edi, jmp->Ebp, jmp->Esp, jmp->Eip, jmp->Registration, retval ); + + cur_frame=(unsigned long)NtCurrentTeb()->Tib.ExceptionList; + TRACE("cur_frame=%lx\n",cur_frame); + + if (cur_frame != jmp->Registration) + _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)jmp->Registration); + + if (jmp->Registration) + { + if (IsBadReadPtr(&jmp->Cookie, sizeof(long)) || jmp->Cookie != MSVCRT_JMP_MAGIC) + { + msvcrt_local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration, + jmp->TryLevel, (void *)jmp->Ebp); + } + else if(jmp->UnwindFunc) + { + MSVCRT_unwind_function unwind_func; + + unwind_func=(MSVCRT_unwind_function)jmp->UnwindFunc; + unwind_func(jmp); + } + } + + if (!retval) + retval = 1; + + __wine_longjmp( (__wine_jmp_buf *)jmp, retval ); +} + +/********************************************************************* + * _seh_longjmp_unwind (MSVCRT.@) + */ +void __stdcall _seh_longjmp_unwind(struct MSVCRT___JUMP_BUFFER *jmp) +{ + msvcrt_local_unwind2( (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, jmp->TryLevel, (void *)jmp->Ebp ); +} + +/********************************************************************* + * _seh_longjmp_unwind4 (MSVCRT.@) + */ +void __stdcall _seh_longjmp_unwind4(struct MSVCRT___JUMP_BUFFER *jmp) +{ + msvcrt_local_unwind4( (ULONG *)&jmp->Cookie, (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, + jmp->TryLevel, (void *)jmp->Ebp ); +} + +/********************************************************************* + * _fpieee_flt (MSVCRT.@) + */ +int __cdecl _fpieee_flt(ULONG exception_code, EXCEPTION_POINTERS *ep, + int (__cdecl *handler)(_FPIEEE_RECORD*)) +{ + FLOATING_SAVE_AREA *ctx = &ep->ContextRecord->FloatSave; + _FPIEEE_RECORD rec; + int ret; + + TRACE("(%x %p %p)\n", exception_code, ep, handler); + + switch(exception_code) { + case STATUS_FLOAT_DIVIDE_BY_ZERO: + case STATUS_FLOAT_INEXACT_RESULT: + case STATUS_FLOAT_INVALID_OPERATION: + case STATUS_FLOAT_OVERFLOW: + case STATUS_FLOAT_UNDERFLOW: + break; + default: + return EXCEPTION_CONTINUE_SEARCH; + } + + memset(&rec, 0, sizeof(rec)); + rec.RoundingMode = ctx->ControlWord >> 10; + switch((ctx->ControlWord >> 8) & 0x3) { + case 0: rec.Precision = 2; break; + case 1: rec.Precision = 3; break; + case 2: rec.Precision = 1; break; + case 3: rec.Precision = 0; break; + } + rec.Status.InvalidOperation = ctx->StatusWord & 0x1; + rec.Status.ZeroDivide = ((ctx->StatusWord & 0x4) != 0); + rec.Status.Overflow = ((ctx->StatusWord & 0x8) != 0); + rec.Status.Underflow = ((ctx->StatusWord & 0x10) != 0); + rec.Status.Inexact = ((ctx->StatusWord & 0x20) != 0); + rec.Enable.InvalidOperation = ((ctx->ControlWord & 0x1) == 0); + rec.Enable.ZeroDivide = ((ctx->ControlWord & 0x4) == 0); + rec.Enable.Overflow = ((ctx->ControlWord & 0x8) == 0); + rec.Enable.Underflow = ((ctx->ControlWord & 0x10) == 0); + rec.Enable.Inexact = ((ctx->ControlWord & 0x20) == 0); + rec.Cause.InvalidOperation = rec.Enable.InvalidOperation & rec.Status.InvalidOperation; + rec.Cause.ZeroDivide = rec.Enable.ZeroDivide & rec.Status.ZeroDivide; + rec.Cause.Overflow = rec.Enable.Overflow & rec.Status.Overflow; + rec.Cause.Underflow = rec.Enable.Underflow & rec.Status.Underflow; + rec.Cause.Inexact = rec.Enable.Inexact & rec.Status.Inexact; + + TRACE("opcode: %x\n", *(ULONG*)ep->ContextRecord->FloatSave.ErrorOffset); + + if(*(WORD*)ctx->ErrorOffset == 0x35dc) { /* fdiv m64fp */ + if(exception_code==STATUS_FLOAT_DIVIDE_BY_ZERO || exception_code==STATUS_FLOAT_INVALID_OPERATION) { + rec.Operand1.OperandValid = 1; + rec.Result.OperandValid = 0; + } else { + rec.Operand1.OperandValid = 0; + rec.Result.OperandValid = 1; + } + rec.Operand2.OperandValid = 1; + rec.Operation = _FpCodeDivide; + rec.Operand1.Format = _FpFormatFp80; + memcpy(&rec.Operand1.Value.Fp80Value, ctx->RegisterArea, sizeof(rec.Operand1.Value.Fp80Value)); + rec.Operand2.Format = _FpFormatFp64; + rec.Operand2.Value.Fp64Value = *(double*)ctx->DataOffset; + rec.Result.Format = _FpFormatFp80; + memcpy(&rec.Result.Value.Fp80Value, ctx->RegisterArea, sizeof(rec.Operand1.Value.Fp80Value)); + + ret = handler(&rec); + + if(ret == EXCEPTION_CONTINUE_EXECUTION) + memcpy(ctx->RegisterArea, &rec.Result.Value.Fp80Value, sizeof(rec.Operand1.Value.Fp80Value)); + return ret; + } + + FIXME("unsupported opcode: %x\n", *(ULONG*)ep->ContextRecord->FloatSave.ErrorOffset); + return EXCEPTION_CONTINUE_SEARCH; +} + +#endif /* __i386__ */ diff --git a/sdk/lib/crt/wine/except_x86_64.c b/sdk/lib/crt/wine/except_x86_64.c new file mode 100644 index 00000000000..e91b8628297 --- /dev/null +++ b/sdk/lib/crt/wine/except_x86_64.c @@ -0,0 +1,758 @@ +/* + * msvcrt C++ exception handling + * + * Copyright 2011 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + */ + +#include "config.h" +#include "wine/port.h" + +#ifdef __x86_64__ + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "msvcrt.h" +#include "wine/exception.h" +#include "excpt.h" +#include "wine/debug.h" + +#include "cppexcept.h" + +WINE_DEFAULT_DEBUG_CHANNEL(seh); + +typedef struct +{ + int prev; + UINT handler; +} unwind_info; + +typedef struct +{ + UINT flags; + UINT type_info; + int offset; + UINT handler; + UINT frame; +} catchblock_info; +#define TYPE_FLAG_CONST 1 +#define TYPE_FLAG_VOLATILE 2 +#define TYPE_FLAG_REFERENCE 8 + +typedef struct +{ + int start_level; + int end_level; + int catch_level; + int catchblock_count; + UINT catchblock; +} tryblock_info; + +typedef struct +{ + int ip; + int state; +} ipmap_info; + +typedef struct __cxx_function_descr +{ + UINT magic; + UINT unwind_count; + UINT unwind_table; + UINT tryblock_count; + UINT tryblock; + UINT ipmap_count; + UINT ipmap; + UINT unwind_help; + UINT expect_list; + UINT flags; +} cxx_function_descr; + +typedef struct +{ + cxx_frame_info frame_info; + BOOL rethrow; +} cxx_catch_ctx; + +typedef struct +{ + ULONG64 dest_frame; + ULONG64 orig_frame; + EXCEPTION_RECORD *seh_rec; + DISPATCHER_CONTEXT *dispatch; + const cxx_function_descr *descr; +} se_translator_ctx; + +static inline void* rva_to_ptr(UINT rva, ULONG64 base) +{ + return rva ? (void*)(base+rva) : NULL; +} + +static inline void dump_type(UINT type_rva, ULONG64 base) +{ + const cxx_type_info *type = rva_to_ptr(type_rva, base); + + TRACE("flags %x type %x %s offsets %d,%d,%d size %d copy ctor %x(%p)\n", + type->flags, type->type_info, dbgstr_type_info(rva_to_ptr(type->type_info, base)), + type->offsets.this_offset, type->offsets.vbase_descr, type->offsets.vbase_offset, + type->size, type->copy_ctor, rva_to_ptr(type->copy_ctor, base)); +} + +static void dump_exception_type(const cxx_exception_type *type, ULONG64 base) +{ + const cxx_type_info_table *type_info_table = rva_to_ptr(type->type_info_table, base); + UINT i; + + TRACE("flags %x destr %x(%p) handler %x(%p) type info %x(%p)\n", + type->flags, type->destructor, rva_to_ptr(type->destructor, base), + type->custom_handler, rva_to_ptr(type->custom_handler, base), + type->type_info_table, type_info_table); + for (i = 0; i < type_info_table->count; i++) + { + TRACE(" %d: ", i); + dump_type(type_info_table->info[i], base); + } +} + +static void dump_function_descr(const cxx_function_descr *descr, ULONG64 image_base) +{ + unwind_info *unwind_table = rva_to_ptr(descr->unwind_table, image_base); + tryblock_info *tryblock = rva_to_ptr(descr->tryblock, image_base); + ipmap_info *ipmap = rva_to_ptr(descr->ipmap, image_base); + UINT i, j; + + TRACE("magic %x\n", descr->magic); + TRACE("unwind table: %x(%p) %d\n", descr->unwind_table, unwind_table, descr->unwind_count); + for (i=0; iunwind_count; i++) + { + TRACE(" %d: prev %d func %x(%p)\n", i, unwind_table[i].prev, + unwind_table[i].handler, rva_to_ptr(unwind_table[i].handler, image_base)); + } + TRACE("try table: %x(%p) %d\n", descr->tryblock, tryblock, descr->tryblock_count); + for (i=0; itryblock_count; i++) + { + catchblock_info *catchblock = rva_to_ptr(tryblock[i].catchblock, image_base); + + TRACE(" %d: start %d end %d catchlevel %d catch %x(%p) %d\n", i, + tryblock[i].start_level, tryblock[i].end_level, + tryblock[i].catch_level, tryblock[i].catchblock, + catchblock, tryblock[i].catchblock_count); + for (j=0; jipmap, ipmap, descr->ipmap_count); + for (i=0; iipmap_count; i++) + { + TRACE(" %d: ip %x state %d\n", i, ipmap[i].ip, ipmap[i].state); + } + TRACE("unwind_help %d\n", descr->unwind_help); + if (descr->magic <= CXX_FRAME_MAGIC_VC6) return; + TRACE("expect list: %x\n", descr->expect_list); + if (descr->magic <= CXX_FRAME_MAGIC_VC7) return; + TRACE("flags: %08x\n", descr->flags); +} + +static inline int ip_to_state(ipmap_info *ipmap, UINT count, int ip) +{ + UINT low = 0, high = count-1, med; + + while (low < high) { + med = low + (high-low)/2; + + if (ipmap[med].ip <= ip && ipmap[med+1].ip > ip) + { + low = med; + break; + } + if (ipmap[med].ip < ip) low = med+1; + else high = med-1; + } + + TRACE("%x -> %d\n", ip, ipmap[low].state); + return ipmap[low].state; +} + +/* check if the exception type is caught by a given catch block, and return the type that matched */ +static const cxx_type_info *find_caught_type(cxx_exception_type *exc_type, ULONG64 exc_base, + const type_info *catch_ti, UINT catch_flags) +{ + const cxx_type_info_table *type_info_table = rva_to_ptr(exc_type->type_info_table, exc_base); + UINT i; + + for (i = 0; i < type_info_table->count; i++) + { + const cxx_type_info *type = rva_to_ptr(type_info_table->info[i], exc_base); + const type_info *ti = rva_to_ptr(type->type_info, exc_base); + + if (!catch_ti) return type; /* catch(...) matches any type */ + if (catch_ti != ti) + { + if (strcmp( catch_ti->mangled, ti->mangled )) continue; + } + /* type is the same, now check the flags */ + if ((exc_type->flags & TYPE_FLAG_CONST) && + !(catch_flags & TYPE_FLAG_CONST)) continue; + if ((exc_type->flags & TYPE_FLAG_VOLATILE) && + !(catch_flags & TYPE_FLAG_VOLATILE)) continue; + return type; /* it matched */ + } + return NULL; +} + +static inline void copy_exception(void *object, ULONG64 frame, + DISPATCHER_CONTEXT *dispatch, + const catchblock_info *catchblock, + const cxx_type_info *type, ULONG64 exc_base) +{ + const type_info *catch_ti = rva_to_ptr(catchblock->type_info, dispatch->ImageBase); + void **dest = rva_to_ptr(catchblock->offset, frame); + + if (!catch_ti || !catch_ti->mangled[0]) return; + if (!catchblock->offset) return; + + if (catchblock->flags & TYPE_FLAG_REFERENCE) + { + *dest = get_this_pointer(&type->offsets, object); + } + else if (type->flags & CLASS_IS_SIMPLE_TYPE) + { + memmove(dest, object, type->size); + /* if it is a pointer, adjust it */ + if (type->size == sizeof(void*)) *dest = get_this_pointer(&type->offsets, *dest); + } + else /* copy the object */ + { + if (type->copy_ctor) + { + if (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) + { + void (__cdecl *copy_ctor)(void*, void*, int) = + rva_to_ptr(type->copy_ctor, exc_base); + copy_ctor(dest, get_this_pointer(&type->offsets, object), 1); + } + else + { + void (__cdecl *copy_ctor)(void*, void*) = + rva_to_ptr(type->copy_ctor, exc_base); + copy_ctor(dest, get_this_pointer(&type->offsets, object)); + } + } + else + memmove(dest, get_this_pointer(&type->offsets,object), type->size); + } +} + +static void cxx_local_unwind(ULONG64 frame, DISPATCHER_CONTEXT *dispatch, + const cxx_function_descr *descr, int last_level) +{ + const unwind_info *unwind_table = rva_to_ptr(descr->unwind_table, dispatch->ImageBase); + void (__cdecl *handler)(ULONG64 unk, ULONG64 rbp); + int *unwind_help = rva_to_ptr(descr->unwind_help, frame); + int trylevel; + + if (unwind_help[0] == -2) + { + trylevel = ip_to_state(rva_to_ptr(descr->ipmap, dispatch->ImageBase), + descr->ipmap_count, dispatch->ControlPc-dispatch->ImageBase); + } + else + { + trylevel = unwind_help[0]; + } + + TRACE("current level: %d, last level: %d\n", trylevel, last_level); + while (trylevel > last_level) + { + if (trylevel<0 || trylevel>=descr->unwind_count) + { + ERR("invalid trylevel %d\n", trylevel); + MSVCRT_terminate(); + } + handler = rva_to_ptr(unwind_table[trylevel].handler, dispatch->ImageBase); + if (handler) + { + TRACE("handler: %p\n", handler); + handler(0, frame); + } + trylevel = unwind_table[trylevel].prev; + } + unwind_help[0] = trylevel; +} + +static LONG CALLBACK cxx_rethrow_filter(PEXCEPTION_POINTERS eptrs, void *c) +{ + EXCEPTION_RECORD *rec = eptrs->ExceptionRecord; + thread_data_t *data = msvcrt_get_thread_data(); + cxx_catch_ctx *ctx = c; + + if (rec->ExceptionCode != CXX_EXCEPTION) + return EXCEPTION_CONTINUE_SEARCH; + if (!rec->ExceptionInformation[1] && !rec->ExceptionInformation[2]) + return EXCEPTION_EXECUTE_HANDLER; + if (rec->ExceptionInformation[1] == data->exc_record->ExceptionInformation[1]) + ctx->rethrow = TRUE; + return EXCEPTION_CONTINUE_SEARCH; +} + +static void CALLBACK cxx_catch_cleanup(BOOL normal, void *c) +{ + cxx_catch_ctx *ctx = c; + __CxxUnregisterExceptionObject(&ctx->frame_info, ctx->rethrow); +} + +static void* WINAPI call_catch_block(EXCEPTION_RECORD *rec) +{ + ULONG64 frame = rec->ExceptionInformation[1]; + const cxx_function_descr *descr = (void*)rec->ExceptionInformation[2]; + EXCEPTION_RECORD *prev_rec = (void*)rec->ExceptionInformation[4]; + EXCEPTION_RECORD *untrans_rec = (void*)rec->ExceptionInformation[6]; + CONTEXT *context = (void*)rec->ExceptionInformation[7]; + void* (__cdecl *handler)(ULONG64 unk, ULONG64 rbp) = (void*)rec->ExceptionInformation[5]; + int *unwind_help = rva_to_ptr(descr->unwind_help, frame); + EXCEPTION_POINTERS ep = { prev_rec, context }; + cxx_catch_ctx ctx; + void *ret_addr = NULL; + + TRACE("calling handler %p\n", handler); + + ctx.rethrow = FALSE; + __CxxRegisterExceptionObject(&ep, &ctx.frame_info); + msvcrt_get_thread_data()->processing_throw--; + __TRY + { + __TRY + { + ret_addr = handler(0, frame); + } + __EXCEPT_CTX(cxx_rethrow_filter, &ctx) + { + TRACE("detect rethrow: exception code: %x\n", prev_rec->ExceptionCode); + ctx.rethrow = TRUE; + + if (untrans_rec) + { + __DestructExceptionObject(prev_rec); + RaiseException(untrans_rec->ExceptionCode, untrans_rec->ExceptionFlags, + untrans_rec->NumberParameters, untrans_rec->ExceptionInformation); + } + else + { + RaiseException(prev_rec->ExceptionCode, prev_rec->ExceptionFlags, + prev_rec->NumberParameters, prev_rec->ExceptionInformation); + } + } + __ENDTRY + } + __FINALLY_CTX(cxx_catch_cleanup, &ctx) + + unwind_help[0] = -2; + unwind_help[1] = -1; + return ret_addr; +} + +static inline BOOL cxx_is_consolidate(const EXCEPTION_RECORD *rec) +{ + return rec->ExceptionCode==STATUS_UNWIND_CONSOLIDATE && rec->NumberParameters==8 && + rec->ExceptionInformation[0]==(ULONG_PTR)call_catch_block; +} + +static inline void find_catch_block(EXCEPTION_RECORD *rec, CONTEXT *context, + EXCEPTION_RECORD *untrans_rec, + ULONG64 frame, DISPATCHER_CONTEXT *dispatch, + const cxx_function_descr *descr, + cxx_exception_type *info, ULONG64 orig_frame) +{ + ULONG64 exc_base = (rec->NumberParameters == 4 ? rec->ExceptionInformation[3] : 0); + int trylevel = ip_to_state(rva_to_ptr(descr->ipmap, dispatch->ImageBase), + descr->ipmap_count, dispatch->ControlPc-dispatch->ImageBase); + thread_data_t *data = msvcrt_get_thread_data(); + const tryblock_info *in_catch; + EXCEPTION_RECORD catch_record; + CONTEXT ctx; + UINT i, j; + INT *unwind_help; + + data->processing_throw++; + for (i=descr->tryblock_count; i>0; i--) + { + in_catch = rva_to_ptr(descr->tryblock, dispatch->ImageBase); + in_catch = &in_catch[i-1]; + + if (trylevel>in_catch->end_level && trylevel<=in_catch->catch_level) + break; + } + if (!i) + in_catch = NULL; + + unwind_help = rva_to_ptr(descr->unwind_help, orig_frame); + if (trylevel > unwind_help[1]) + unwind_help[0] = unwind_help[1] = trylevel; + else + trylevel = unwind_help[1]; + TRACE("current trylevel: %d\n", trylevel); + + for (i=0; itryblock_count; i++) + { + const tryblock_info *tryblock = rva_to_ptr(descr->tryblock, dispatch->ImageBase); + tryblock = &tryblock[i]; + + if (trylevel < tryblock->start_level) continue; + if (trylevel > tryblock->end_level) continue; + + if (in_catch) + { + if(tryblock->start_level <= in_catch->end_level) continue; + if(tryblock->end_level > in_catch->catch_level) continue; + } + + /* got a try block */ + for (j=0; jcatchblock_count; j++) + { + const catchblock_info *catchblock = rva_to_ptr(tryblock->catchblock, dispatch->ImageBase); + catchblock = &catchblock[j]; + + if (info) + { + const cxx_type_info *type = find_caught_type(info, exc_base, + rva_to_ptr(catchblock->type_info, dispatch->ImageBase), + catchblock->flags); + if (!type) continue; + + TRACE("matched type %p in tryblock %d catchblock %d\n", type, i, j); + + /* copy the exception to its destination on the stack */ + copy_exception((void*)rec->ExceptionInformation[1], + orig_frame, dispatch, catchblock, type, exc_base); + } + else + { + /* no CXX_EXCEPTION only proceed with a catch(...) block*/ + if (catchblock->type_info) + continue; + TRACE("found catch(...) block\n"); + } + + /* unwind stack and call catch */ + memset(&catch_record, 0, sizeof(catch_record)); + catch_record.ExceptionCode = STATUS_UNWIND_CONSOLIDATE; + catch_record.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + catch_record.NumberParameters = 8; + catch_record.ExceptionInformation[0] = (ULONG_PTR)call_catch_block; + catch_record.ExceptionInformation[1] = orig_frame; + catch_record.ExceptionInformation[2] = (ULONG_PTR)descr; + catch_record.ExceptionInformation[3] = tryblock->start_level; + catch_record.ExceptionInformation[4] = (ULONG_PTR)rec; + catch_record.ExceptionInformation[5] = + (ULONG_PTR)rva_to_ptr(catchblock->handler, dispatch->ImageBase); + catch_record.ExceptionInformation[6] = (ULONG_PTR)untrans_rec; + catch_record.ExceptionInformation[7] = (ULONG_PTR)context; + RtlUnwindEx((void*)frame, (void*)dispatch->ControlPc, &catch_record, NULL, &ctx, NULL); + } + } + + TRACE("no matching catch block found\n"); + data->processing_throw--; +} + +static LONG CALLBACK se_translation_filter(EXCEPTION_POINTERS *ep, void *c) +{ + se_translator_ctx *ctx = (se_translator_ctx *)c; + EXCEPTION_RECORD *rec = ep->ExceptionRecord; + cxx_exception_type *exc_type; + + if (rec->ExceptionCode != CXX_EXCEPTION) + { + TRACE("non-c++ exception thrown in SEH handler: %x\n", rec->ExceptionCode); + MSVCRT_terminate(); + } + + exc_type = (cxx_exception_type *)rec->ExceptionInformation[2]; + find_catch_block(rec, ep->ContextRecord, ctx->seh_rec, ctx->dest_frame, ctx->dispatch, + ctx->descr, exc_type, ctx->orig_frame); + + __DestructExceptionObject(rec); + return ExceptionContinueSearch; +} + +static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame, + CONTEXT *context, DISPATCHER_CONTEXT *dispatch, + const cxx_function_descr *descr) +{ + int trylevel = ip_to_state(rva_to_ptr(descr->ipmap, dispatch->ImageBase), + descr->ipmap_count, dispatch->ControlPc-dispatch->ImageBase); + cxx_exception_type *exc_type; + ULONG64 orig_frame = frame; + ULONG64 throw_base; + DWORD throw_func_off; + void *throw_func; + UINT i, j; + int unwindlevel = -1; + + if (descr->magicmagic>CXX_FRAME_MAGIC_VC8) + { + FIXME("unhandled frame magic %x\n", descr->magic); + return ExceptionContinueSearch; + } + + if (descr->magic >= CXX_FRAME_MAGIC_VC8 && + (descr->flags & FUNC_DESCR_SYNCHRONOUS) && + (rec->ExceptionCode != CXX_EXCEPTION && + !cxx_is_consolidate(rec) && + rec->ExceptionCode != STATUS_LONGJUMP)) + return ExceptionContinueSearch; /* handle only c++ exceptions */ + + /* update orig_frame if it's a nested exception */ + throw_func_off = RtlLookupFunctionEntry(dispatch->ControlPc, &throw_base, NULL)->BeginAddress; + throw_func = rva_to_ptr(throw_func_off, throw_base); + TRACE("reconstructed handler pointer: %p\n", throw_func); + for (i=descr->tryblock_count; i>0; i--) + { + const tryblock_info *tryblock = rva_to_ptr(descr->tryblock, dispatch->ImageBase); + tryblock = &tryblock[i-1]; + + if (trylevel>tryblock->end_level && trylevel<=tryblock->catch_level) + { + for (j=0; jcatchblock_count; j++) + { + const catchblock_info *catchblock = rva_to_ptr(tryblock->catchblock, dispatch->ImageBase); + catchblock = &catchblock[j]; + + if (rva_to_ptr(catchblock->handler, dispatch->ImageBase) == throw_func) + { + TRACE("nested exception detected\n"); + unwindlevel = tryblock->end_level; + orig_frame = *(ULONG64*)rva_to_ptr(catchblock->frame, frame); + TRACE("setting orig_frame to %lx\n", orig_frame); + } + } + } + } + + if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND)) + { + if (rec->ExceptionFlags & EH_TARGET_UNWIND) + cxx_local_unwind(orig_frame, dispatch, descr, + cxx_is_consolidate(rec) ? rec->ExceptionInformation[3] : trylevel); + else + cxx_local_unwind(orig_frame, dispatch, descr, unwindlevel); + return ExceptionContinueSearch; + } + if (!descr->tryblock_count) return ExceptionContinueSearch; + + if (rec->ExceptionCode == CXX_EXCEPTION) + { + exc_type = (cxx_exception_type *)rec->ExceptionInformation[2]; + + if (TRACE_ON(seh)) + { + TRACE("handling C++ exception rec %p frame %lx descr %p\n", rec, frame, descr); + dump_exception_type(exc_type, rec->ExceptionInformation[3]); + dump_function_descr(descr, dispatch->ImageBase); + } + } + else + { + thread_data_t *data = msvcrt_get_thread_data(); + + exc_type = NULL; + TRACE("handling C exception code %x rec %p frame %lx descr %p\n", + rec->ExceptionCode, rec, frame, descr); + + if (data->se_translator) { + EXCEPTION_POINTERS except_ptrs; + se_translator_ctx ctx; + + ctx.dest_frame = frame; + ctx.orig_frame = orig_frame; + ctx.seh_rec = rec; + ctx.dispatch = dispatch; + ctx.descr = descr; + __TRY + { + except_ptrs.ExceptionRecord = rec; + except_ptrs.ContextRecord = context; + data->se_translator(rec->ExceptionCode, &except_ptrs); + } + __EXCEPT_CTX(se_translation_filter, &ctx) + { + } + __ENDTRY + } + } + + find_catch_block(rec, context, NULL, frame, dispatch, descr, exc_type, orig_frame); + return ExceptionContinueSearch; +} + +/********************************************************************* + * __CxxExceptionFilter (MSVCRT.@) + */ +int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs, + const type_info *ti, int flags, void **copy ) +{ + FIXME( "%p %p %x %p: not implemented\n", ptrs, ti, flags, copy ); + return EXCEPTION_CONTINUE_SEARCH; +} + +/********************************************************************* + * __CxxFrameHandler (MSVCRT.@) + */ +EXCEPTION_DISPOSITION CDECL __CxxFrameHandler( EXCEPTION_RECORD *rec, ULONG64 frame, + CONTEXT *context, DISPATCHER_CONTEXT *dispatch ) +{ + TRACE( "%p %lx %p %p\n", rec, frame, context, dispatch ); + return cxx_frame_handler( rec, frame, context, dispatch, + rva_to_ptr(*(UINT*)dispatch->HandlerData, dispatch->ImageBase) ); +} + + +/********************************************************************* + * __CppXcptFilter (MSVCRT.@) + */ +int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr) +{ + /* only filter c++ exceptions */ + if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH; + return _XcptFilter( ex, ptr ); +} + + +/********************************************************************* + * __CxxDetectRethrow (MSVCRT.@) + */ +BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs) +{ + PEXCEPTION_RECORD rec; + + if (!ptrs) + return FALSE; + + rec = ptrs->ExceptionRecord; + + if (rec->ExceptionCode == CXX_EXCEPTION && + rec->NumberParameters == 4 && + rec->ExceptionInformation[0] == CXX_FRAME_MAGIC_VC6 && + rec->ExceptionInformation[2]) + { + ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record; + return TRUE; + } + return (msvcrt_get_thread_data()->exc_record == rec); +} + + +/********************************************************************* + * __CxxQueryExceptionSize (MSVCRT.@) + */ +unsigned int CDECL __CxxQueryExceptionSize(void) +{ + return sizeof(cxx_exception_type); +} + + +/******************************************************************* + * _setjmp (MSVCRT.@) + */ +__ASM_GLOBAL_FUNC( MSVCRT__setjmp, + "jmp " __ASM_NAME("__wine_setjmpex") ); + +/******************************************************************* + * longjmp (MSVCRT.@) + */ +void __cdecl MSVCRT_longjmp( struct MSVCRT___JUMP_BUFFER *jmp, int retval ) +{ + EXCEPTION_RECORD rec; + + if (!retval) retval = 1; + if (jmp->Frame) + { + rec.ExceptionCode = STATUS_LONGJUMP; + rec.ExceptionFlags = 0; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = NULL; + rec.NumberParameters = 1; + rec.ExceptionInformation[0] = (DWORD_PTR)jmp; + RtlUnwind( (void *)jmp->Frame, (void *)jmp->Rip, &rec, IntToPtr(retval) ); + } + __wine_longjmp( (__wine_jmp_buf *)jmp, retval ); +} + +#ifndef __REACTOS__ // different file for ntdll +/******************************************************************* + * _local_unwind (MSVCRT.@) + */ +void __cdecl _local_unwind( void *frame, void *target ) +{ + RtlUnwind( frame, target, NULL, 0 ); +} +#endif /* __REACTOS__ */ + +/********************************************************************* + * _fpieee_flt (MSVCRT.@) + */ +int __cdecl _fpieee_flt(ULONG exception_code, EXCEPTION_POINTERS *ep, + int (__cdecl *handler)(_FPIEEE_RECORD*)) +{ + FIXME("(%x %p %p) opcode: %s\n", exception_code, ep, handler, + wine_dbgstr_longlong(*(ULONG64*)ep->ContextRecord->Rip)); + return EXCEPTION_CONTINUE_SEARCH; +} + +#if _MSVCR_VER>=110 && _MSVCR_VER<=120 +/********************************************************************* + * __crtCapturePreviousContext (MSVCR110.@) + */ +void __cdecl get_prev_context(CONTEXT *ctx, DWORD64 rip) +{ + ULONG64 frame, image_base; + RUNTIME_FUNCTION *rf; + void *data; + + TRACE("(%p)\n", ctx); + + rf = RtlLookupFunctionEntry(ctx->Rip, &image_base, NULL); + if(!rf) { + FIXME("RtlLookupFunctionEntry failed\n"); + return; + } + + RtlVirtualUnwind(UNW_FLAG_NHANDLER, image_base, ctx->Rip, + rf, ctx, &data, &frame, NULL); +} + +__ASM_GLOBAL_FUNC( __crtCapturePreviousContext, + "movq %rcx,8(%rsp)\n\t" + "call " __ASM_NAME("RtlCaptureContext") "\n\t" + "movq 8(%rsp),%rcx\n\t" /* context */ + "leaq 8(%rsp),%rax\n\t" + "movq %rax,0x98(%rcx)\n\t" /* context->Rsp */ + "movq (%rsp),%rax\n\t" + "movq %rax,0xf8(%rcx)\n\t" /* context->Rip */ + "jmp " __ASM_NAME("get_prev_context") ) +#endif + +#endif /* __x86_64__ */ diff --git a/sdk/lib/crt/wine/msvcrt.h b/sdk/lib/crt/wine/msvcrt.h new file mode 100644 index 00000000000..d5dc4cd5366 --- /dev/null +++ b/sdk/lib/crt/wine/msvcrt.h @@ -0,0 +1,1494 @@ +/* + * Copyright 2001 Jon Griffiths + * Copyright 2004 Dimitrie O. Paun + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + * Naming conventions + * - Symbols are prefixed with MSVCRT_ if they conflict + * with libc symbols + * - Internal symbols are usually prefixed by msvcrt_. + * - Exported symbols that are not present in the public + * headers are usually kept the same as the original. + * Other conventions + * - To avoid conflicts with the standard C library, + * no msvcrt headers are included in the implementation. + * - Instead, symbols are duplicated here, prefixed with + * MSVCRT_, as explained above. + * - To avoid inconsistencies, a test for each symbol is + * added into tests/headers.c. Please always add a + * corresponding test when you add a new symbol! + */ + +#ifndef __WINE_MSVCRT_H +#define __WINE_MSVCRT_H + +#include + +#include "windef.h" +#include "winbase.h" + +#define MSVCRT_INT_MAX 0x7fffffff +#define MSVCRT_LONG_MAX 0x7fffffff +#define MSVCRT_LONG_MIN (-MSVCRT_LONG_MAX-1) +#define MSVCRT_ULONG_MAX 0xffffffff +#define MSVCRT_I64_MAX (((__int64)0x7fffffff << 32) | 0xffffffff) +#define MSVCRT_I64_MIN (-MSVCRT_I64_MAX-1) +#define MSVCRT_UI64_MAX (((unsigned __int64)0xffffffff << 32) | 0xffffffff) +#define MSVCRT_MB_LEN_MAX 5 +#define MSVCRT_FLT_MAX_10_EXP 38 +#define MSVCRT_FLT_MIN_10_EXP (-37) +#define MSVCRT_DBL_MAX_10_EXP 308 +#define MSVCRT_DBL_MIN_10_EXP (-307) +#define MSVCRT_DBL_DIG 15 +#ifdef _WIN64 +#define MSVCRT_SIZE_MAX MSVCRT_UI64_MAX +#else +#define MSVCRT_SIZE_MAX MSVCRT_ULONG_MAX +#endif + +#define MSVCRT__MAX_DRIVE 3 +#define MSVCRT__MAX_DIR 256 +#define MSVCRT__MAX_FNAME 256 +#define MSVCRT__MAX_EXT 256 + +typedef unsigned char MSVCRT_bool; +typedef unsigned short MSVCRT_wchar_t; +typedef unsigned short MSVCRT_wint_t; +typedef unsigned short MSVCRT_wctrans_t; +typedef unsigned short MSVCRT_wctype_t; +typedef unsigned short MSVCRT__ino_t; +typedef unsigned int MSVCRT__fsize_t; +typedef int MSVCRT_long; +typedef unsigned int MSVCRT_ulong; +typedef __int64 MSVCRT_longlong; +#ifdef _WIN64 +typedef unsigned __int64 MSVCRT_size_t; +typedef __int64 MSVCRT_intptr_t; +typedef unsigned __int64 MSVCRT_uintptr_t; +#else +typedef unsigned long MSVCRT_size_t; +typedef long MSVCRT_intptr_t; +typedef unsigned long MSVCRT_uintptr_t; +#endif +#ifdef _CRTDLL +typedef short MSVCRT__dev_t; +#else +typedef unsigned int MSVCRT__dev_t; +#endif +typedef int MSVCRT__off_t; +typedef int MSVCRT_clock_t; +typedef int MSVCRT___time32_t; +typedef __int64 DECLSPEC_ALIGN(8) MSVCRT___time64_t; +typedef __int64 DECLSPEC_ALIGN(8) MSVCRT_fpos_t; +typedef int MSVCRT_mbstate_t; + +typedef void (__cdecl *MSVCRT_terminate_handler)(void); +typedef void (__cdecl *MSVCRT_terminate_function)(void); +typedef void (__cdecl *MSVCRT_unexpected_handler)(void); +typedef void (__cdecl *MSVCRT_unexpected_function)(void); +typedef void (__cdecl *MSVCRT__se_translator_function)(unsigned int code, struct _EXCEPTION_POINTERS *info); +typedef void (__cdecl *MSVCRT__beginthread_start_routine_t)(void *); +typedef unsigned int (__stdcall *MSVCRT__beginthreadex_start_routine_t)(void *); +typedef int (__cdecl *MSVCRT__onexit_t)(void); +typedef void (__cdecl *MSVCRT_invalid_parameter_handler)(const MSVCRT_wchar_t*, const MSVCRT_wchar_t*, const MSVCRT_wchar_t*, unsigned, MSVCRT_uintptr_t); +typedef void (__cdecl *MSVCRT_purecall_handler)(void); +typedef void (__cdecl *MSVCRT_security_error_handler)(int, void *); + +typedef struct {ULONG x80[3];} MSVCRT__LDOUBLE; /* Intel 80 bit FP format has sizeof() 12 */ + +struct MSVCRT_tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +typedef struct MSVCRT_tagLC_ID { + unsigned short wLanguage; + unsigned short wCountry; + unsigned short wCodePage; +} MSVCRT_LC_ID, *MSVCRT_LPLC_ID; + +typedef struct { + union { + const char *str[43]; + struct { + const char *short_wday[7]; + const char *wday[7]; + const char *short_mon[12]; + const char *mon[12]; + const char *am; + const char *pm; + const char *short_date; + const char *date; + const char *time; + } names; + } str; +#if _MSVCR_VER < 110 + LCID lcid; +#endif + int unk[2]; + union { + const MSVCRT_wchar_t *wstr[43]; + struct { + const MSVCRT_wchar_t *short_wday[7]; + const MSVCRT_wchar_t *wday[7]; + const MSVCRT_wchar_t *short_mon[12]; + const MSVCRT_wchar_t *mon[12]; + const MSVCRT_wchar_t *am; + const MSVCRT_wchar_t *pm; + const MSVCRT_wchar_t *short_date; + const MSVCRT_wchar_t *date; + const MSVCRT_wchar_t *time; + } names; + } wstr; +#if _MSVCR_VER >= 110 + const MSVCRT_wchar_t *locname; +#endif + char data[1]; +} MSVCRT___lc_time_data; + +typedef struct MSVCRT_threadlocaleinfostruct { +#if _MSVCR_VER >= 140 + unsigned short *pctype; + int mb_cur_max; + unsigned int lc_codepage; +#endif + + int refcount; +#if _MSVCR_VER < 140 + unsigned int lc_codepage; +#endif + unsigned int lc_collate_cp; + MSVCRT_ulong lc_handle[6]; + MSVCRT_LC_ID lc_id[6]; + struct { + char *locale; + MSVCRT_wchar_t *wlocale; + int *refcount; + int *wrefcount; + } lc_category[6]; + int lc_clike; +#if _MSVCR_VER < 140 + int mb_cur_max; +#endif + int *lconv_intl_refcount; + int *lconv_num_refcount; + int *lconv_mon_refcount; + struct MSVCRT_lconv *lconv; + int *ctype1_refcount; + unsigned short *ctype1; +#if _MSVCR_VER < 140 + unsigned short *pctype; +#endif + unsigned char *pclmap; + unsigned char *pcumap; + MSVCRT___lc_time_data *lc_time_curr; +#if _MSVCR_VER >= 110 + MSVCRT_wchar_t *lc_name[6]; +#endif +} MSVCRT_threadlocinfo; + +typedef struct MSVCRT_threadmbcinfostruct { + int refcount; + int mbcodepage; + int ismbcodepage; + int mblcid; + unsigned short mbulinfo[6]; + unsigned char mbctype[257]; + unsigned char mbcasemap[256]; +} MSVCRT_threadmbcinfo; + +typedef struct MSVCRT_threadlocaleinfostruct *MSVCRT_pthreadlocinfo; +typedef struct MSVCRT_threadmbcinfostruct *MSVCRT_pthreadmbcinfo; + +typedef struct MSVCRT_localeinfo_struct +{ + MSVCRT_pthreadlocinfo locinfo; + MSVCRT_pthreadmbcinfo mbcinfo; +} MSVCRT__locale_tstruct, *MSVCRT__locale_t; + +typedef struct MSVCRT__onexit_table_t +{ + MSVCRT__onexit_t *_first; + MSVCRT__onexit_t *_last; + MSVCRT__onexit_t *_end; +} MSVCRT__onexit_table_t; + +typedef struct _frame_info +{ + void *object; + struct _frame_info *next; +} frame_info; + +typedef struct +{ + frame_info frame_info; + EXCEPTION_RECORD *rec; + CONTEXT *context; +} cxx_frame_info; + +frame_info* __cdecl _CreateFrameInfo(frame_info *fi, void *obj); +BOOL __cdecl __CxxRegisterExceptionObject(EXCEPTION_POINTERS*, cxx_frame_info*); +void __cdecl __CxxUnregisterExceptionObject(cxx_frame_info*, BOOL); +void CDECL __DestructExceptionObject(EXCEPTION_RECORD*); + +/* TLS data */ +extern DWORD msvcrt_tls_index DECLSPEC_HIDDEN; + +/* Keep in sync with msvcr90/tests/msvcr90.c */ +struct __thread_data { + DWORD tid; + HANDLE handle; + int thread_errno; + MSVCRT_ulong thread_doserrno; + int unk1; + unsigned int random_seed; /* seed for rand() */ + char *strtok_next; /* next ptr for strtok() */ + MSVCRT_wchar_t *wcstok_next; /* next ptr for wcstok() */ + unsigned char *mbstok_next; /* next ptr for mbstok() */ + char *strerror_buffer; /* buffer for strerror */ + MSVCRT_wchar_t *wcserror_buffer; /* buffer for wcserror */ + char *tmpnam_buffer; /* buffer for tmpname() */ + MSVCRT_wchar_t *wtmpnam_buffer; /* buffer for wtmpname() */ + void *unk2[2]; + char *asctime_buffer; /* buffer for asctime */ + MSVCRT_wchar_t *wasctime_buffer; /* buffer for wasctime */ + struct MSVCRT_tm *time_buffer; /* buffer for localtime/gmtime */ + char *efcvt_buffer; /* buffer for ecvt/fcvt */ + int unk3[2]; + void *unk4[3]; + EXCEPTION_POINTERS *xcptinfo; + int fpecode; + MSVCRT_pthreadmbcinfo mbcinfo; + MSVCRT_pthreadlocinfo locinfo; + BOOL have_locale; + int unk5[1]; + MSVCRT_terminate_function terminate_handler; + MSVCRT_unexpected_function unexpected_handler; + MSVCRT__se_translator_function se_translator; + void *unk6[3]; + int unk7; + EXCEPTION_RECORD *exc_record; + CONTEXT *ctx_record; + int processing_throw; + frame_info *frame_info_head; + void *unk8[6]; + LCID cached_lcid; + BOOL cached_sname; + int unk9[2]; + DWORD cached_cp; + char cached_locale[131]; + void *unk10[100]; +#if _MSVCR_VER >= 140 + MSVCRT_invalid_parameter_handler invalid_parameter_handler; +#endif +}; + +typedef struct __thread_data thread_data_t; + +extern thread_data_t *msvcrt_get_thread_data(void) DECLSPEC_HIDDEN; + +LCID MSVCRT_locale_to_LCID(const char*, unsigned short*, BOOL*) DECLSPEC_HIDDEN; +extern MSVCRT__locale_t MSVCRT_locale DECLSPEC_HIDDEN; +extern MSVCRT___lc_time_data cloc_time_data DECLSPEC_HIDDEN; +extern unsigned int MSVCRT___lc_codepage; +extern int MSVCRT___lc_collate_cp; +extern WORD MSVCRT__ctype [257]; +extern BOOL initial_locale DECLSPEC_HIDDEN; + +void msvcrt_set_errno(int) DECLSPEC_HIDDEN; +#if _MSVCR_VER >= 80 +typedef enum { + EXCEPTION_BAD_ALLOC, +#if _MSVCR_VER >= 100 + EXCEPTION_SCHEDULER_RESOURCE_ALLOCATION_ERROR, + EXCEPTION_IMPROPER_LOCK, + EXCEPTION_INVALID_SCHEDULER_POLICY_KEY, + EXCEPTION_INVALID_SCHEDULER_POLICY_VALUE, + EXCEPTION_INVALID_SCHEDULER_POLICY_THREAD_SPECIFICATION, + EXCEPTION_IMPROPER_SCHEDULER_ATTACH, + EXCEPTION_IMPROPER_SCHEDULER_DETACH, +#endif +} exception_type; +void throw_exception(exception_type, HRESULT, const char*) DECLSPEC_HIDDEN; +#endif + +void __cdecl _purecall(void); +void __cdecl _amsg_exit(int errnum); + +extern char **MSVCRT__environ; +extern MSVCRT_wchar_t **MSVCRT__wenviron; + +extern char ** msvcrt_SnapshotOfEnvironmentA(char **) DECLSPEC_HIDDEN; +extern MSVCRT_wchar_t ** msvcrt_SnapshotOfEnvironmentW(MSVCRT_wchar_t **) DECLSPEC_HIDDEN; + +MSVCRT_wchar_t *msvcrt_wstrdupa(const char *) DECLSPEC_HIDDEN; + +extern unsigned int MSVCRT__commode; + +/* FIXME: This should be declared in new.h but it's not an extern "C" so + * it would not be much use anyway. Even for Winelib applications. + */ +int __cdecl MSVCRT__set_new_mode(int mode); + +void* __cdecl MSVCRT_operator_new(MSVCRT_size_t); +void __cdecl MSVCRT_operator_delete(void*); + +typedef void* (__cdecl *malloc_func_t)(MSVCRT_size_t); +typedef void (__cdecl *free_func_t)(void*); + +/* Setup and teardown multi threaded locks */ +extern void msvcrt_init_mt_locks(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_locks(void) DECLSPEC_HIDDEN; + +extern void msvcrt_init_exception(void*) DECLSPEC_HIDDEN; +extern BOOL msvcrt_init_locale(void) DECLSPEC_HIDDEN; +extern void msvcrt_init_math(void) DECLSPEC_HIDDEN; +extern void msvcrt_init_io(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_io(void) DECLSPEC_HIDDEN; +extern void msvcrt_init_console(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_console(void) DECLSPEC_HIDDEN; +extern void msvcrt_init_args(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_args(void) DECLSPEC_HIDDEN; +extern void msvcrt_init_signals(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_signals(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_popen_data(void) DECLSPEC_HIDDEN; +extern BOOL msvcrt_init_heap(void) DECLSPEC_HIDDEN; +extern void msvcrt_destroy_heap(void) DECLSPEC_HIDDEN; +extern void msvcrt_init_clock(void) DECLSPEC_HIDDEN; + +#if _MSVCR_VER >= 100 +extern void msvcrt_init_scheduler(void*) DECLSPEC_HIDDEN; +extern void msvcrt_free_scheduler(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_scheduler_thread(void) DECLSPEC_HIDDEN; +#endif + +extern unsigned msvcrt_create_io_inherit_block(WORD*, BYTE**) DECLSPEC_HIDDEN; + +extern unsigned int __cdecl _control87(unsigned int, unsigned int); + +/* run-time error codes */ +#define _RT_STACK 0 +#define _RT_NULLPTR 1 +#define _RT_FLOAT 2 +#define _RT_INTDIV 3 +#define _RT_EXECMEM 5 +#define _RT_EXECFORM 6 +#define _RT_EXECENV 7 +#define _RT_SPACEARG 8 +#define _RT_SPACEENV 9 +#define _RT_ABORT 10 +#define _RT_NPTR 12 +#define _RT_FPTR 13 +#define _RT_BREAK 14 +#define _RT_INT 15 +#define _RT_THREAD 16 +#define _RT_LOCK 17 +#define _RT_HEAP 18 +#define _RT_OPENCON 19 +#define _RT_QWIN 20 +#define _RT_NOMAIN 21 +#define _RT_NONCONT 22 +#define _RT_INVALDISP 23 +#define _RT_ONEXIT 24 +#define _RT_PUREVIRT 25 +#define _RT_STDIOINIT 26 +#define _RT_LOWIOINIT 27 +#define _RT_HEAPINIT 28 +#define _RT_DOMAIN 120 +#define _RT_SING 121 +#define _RT_TLOSS 122 +#define _RT_CRNL 252 +#define _RT_BANNER 255 + +struct MSVCRT___timeb32 { + MSVCRT___time32_t time; + unsigned short millitm; + short timezone; + short dstflag; +}; + +struct MSVCRT___timeb64 { + MSVCRT___time64_t time; + unsigned short millitm; + short timezone; + short dstflag; +}; + +struct MSVCRT__iobuf { + char* _ptr; + int _cnt; + char* _base; + int _flag; + int _file; + int _charbuf; + int _bufsiz; + char* _tmpfname; +}; + +typedef struct MSVCRT__iobuf MSVCRT_FILE; + +struct MSVCRT_lconv { + char* decimal_point; + char* thousands_sep; + char* grouping; + char* int_curr_symbol; + char* currency_symbol; + char* mon_decimal_point; + char* mon_thousands_sep; + char* mon_grouping; + char* positive_sign; + char* negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; +#if _MSVCR_VER >= 100 + MSVCRT_wchar_t* _W_decimal_point; + MSVCRT_wchar_t* _W_thousands_sep; + MSVCRT_wchar_t* _W_int_curr_symbol; + MSVCRT_wchar_t* _W_currency_symbol; + MSVCRT_wchar_t* _W_mon_decimal_point; + MSVCRT_wchar_t* _W_mon_thousands_sep; + MSVCRT_wchar_t* _W_positive_sign; + MSVCRT_wchar_t* _W_negative_sign; +#endif +}; + +struct MSVCRT__exception { + int type; + char* name; + double arg1; + double arg2; + double retval; +}; + +struct MSVCRT__complex { + double x; /* Real part */ + double y; /* Imaginary part */ +}; +typedef struct MSVCRT__complex _Dcomplex; + +typedef struct MSVCRT__div_t { + int quot; /* quotient */ + int rem; /* remainder */ +} MSVCRT_div_t; + +typedef struct MSVCRT__ldiv_t { + MSVCRT_long quot; /* quotient */ + MSVCRT_long rem; /* remainder */ +} MSVCRT_ldiv_t; + +typedef struct MSVCRT__lldiv_t { + MSVCRT_longlong quot; /* quotient */ + MSVCRT_longlong rem; /* remainder */ +} MSVCRT_lldiv_t; + +struct MSVCRT__heapinfo { + int* _pentry; + MSVCRT_size_t _size; + int _useflag; +}; + +#ifdef __i386__ +struct MSVCRT___JUMP_BUFFER { + unsigned long Ebp; + unsigned long Ebx; + unsigned long Edi; + unsigned long Esi; + unsigned long Esp; + unsigned long Eip; + unsigned long Registration; + unsigned long TryLevel; + /* Start of new struct members */ + unsigned long Cookie; + unsigned long UnwindFunc; + unsigned long UnwindData[6]; +}; +#elif defined(__x86_64__) +struct MSVCRT__SETJMP_FLOAT128 +{ + unsigned __int64 DECLSPEC_ALIGN(16) Part[2]; +}; +struct MSVCRT___JUMP_BUFFER +{ + unsigned __int64 Frame; + unsigned __int64 Rbx; + unsigned __int64 Rsp; + unsigned __int64 Rbp; + unsigned __int64 Rsi; + unsigned __int64 Rdi; + unsigned __int64 R12; + unsigned __int64 R13; + unsigned __int64 R14; + unsigned __int64 R15; + unsigned __int64 Rip; + unsigned __int64 Spare; + struct MSVCRT__SETJMP_FLOAT128 Xmm6; + struct MSVCRT__SETJMP_FLOAT128 Xmm7; + struct MSVCRT__SETJMP_FLOAT128 Xmm8; + struct MSVCRT__SETJMP_FLOAT128 Xmm9; + struct MSVCRT__SETJMP_FLOAT128 Xmm10; + struct MSVCRT__SETJMP_FLOAT128 Xmm11; + struct MSVCRT__SETJMP_FLOAT128 Xmm12; + struct MSVCRT__SETJMP_FLOAT128 Xmm13; + struct MSVCRT__SETJMP_FLOAT128 Xmm14; + struct MSVCRT__SETJMP_FLOAT128 Xmm15; +}; +#elif defined(__arm__) +struct MSVCRT___JUMP_BUFFER +{ + unsigned long Frame; + unsigned long R4; + unsigned long R5; + unsigned long R6; + unsigned long R7; + unsigned long R8; + unsigned long R9; + unsigned long R10; + unsigned long R11; + unsigned long Sp; + unsigned long Pc; + unsigned long Fpscr; + unsigned long long D[8]; +}; +#elif defined(__aarch64__) +struct MSVCRT___JUMP_BUFFER +{ + unsigned __int64 Frame; + unsigned __int64 Reserved; + unsigned __int64 X19; + unsigned __int64 X20; + unsigned __int64 X21; + unsigned __int64 X22; + unsigned __int64 X23; + unsigned __int64 X24; + unsigned __int64 X25; + unsigned __int64 X26; + unsigned __int64 X27; + unsigned __int64 X28; + unsigned __int64 Fp; + unsigned __int64 Lr; + unsigned __int64 Sp; + unsigned long Fpcr; + unsigned long Fpsr; + double D[8]; +}; +#endif /* __i386__ */ + +struct MSVCRT__diskfree_t { + unsigned int total_clusters; + unsigned int avail_clusters; + unsigned int sectors_per_cluster; + unsigned int bytes_per_sector; +}; + +struct MSVCRT__finddata32_t { + unsigned int attrib; + MSVCRT___time32_t time_create; + MSVCRT___time32_t time_access; + MSVCRT___time32_t time_write; + MSVCRT__fsize_t size; + char name[260]; +}; + +struct MSVCRT__finddata32i64_t { + unsigned int attrib; + MSVCRT___time32_t time_create; + MSVCRT___time32_t time_access; + MSVCRT___time32_t time_write; + __int64 DECLSPEC_ALIGN(8) size; + char name[260]; +}; + +struct MSVCRT__finddata64i32_t { + unsigned int attrib; + MSVCRT___time64_t time_create; + MSVCRT___time64_t time_access; + MSVCRT___time64_t time_write; + MSVCRT__fsize_t size; + char name[260]; +}; + +struct MSVCRT__finddata64_t { + unsigned int attrib; + MSVCRT___time64_t time_create; + MSVCRT___time64_t time_access; + MSVCRT___time64_t time_write; + __int64 DECLSPEC_ALIGN(8) size; + char name[260]; +}; + +struct MSVCRT__wfinddata32_t { + unsigned int attrib; + MSVCRT___time32_t time_create; + MSVCRT___time32_t time_access; + MSVCRT___time32_t time_write; + MSVCRT__fsize_t size; + MSVCRT_wchar_t name[260]; +}; + +struct MSVCRT__wfinddata32i64_t { + unsigned int attrib; + MSVCRT___time32_t time_create; + MSVCRT___time32_t time_access; + MSVCRT___time32_t time_write; + __int64 DECLSPEC_ALIGN(8) size; + MSVCRT_wchar_t name[260]; +}; + +struct MSVCRT__wfinddata64i32_t { + unsigned int attrib; + MSVCRT___time64_t time_create; + MSVCRT___time64_t time_access; + MSVCRT___time64_t time_write; + MSVCRT__fsize_t size; + MSVCRT_wchar_t name[260]; +}; + +struct MSVCRT__wfinddata64_t { + unsigned int attrib; + MSVCRT___time64_t time_create; + MSVCRT___time64_t time_access; + MSVCRT___time64_t time_write; + __int64 DECLSPEC_ALIGN(8) size; + MSVCRT_wchar_t name[260]; +}; + +struct MSVCRT___utimbuf32 +{ + MSVCRT___time32_t actime; + MSVCRT___time32_t modtime; +}; + +struct MSVCRT___utimbuf64 +{ + MSVCRT___time64_t actime; + MSVCRT___time64_t modtime; +}; + +/* for FreeBSD */ +#undef st_atime +#undef st_ctime +#undef st_mtime + +struct MSVCRT__stat32 { + MSVCRT__dev_t st_dev; + MSVCRT__ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + MSVCRT__dev_t st_rdev; + MSVCRT__off_t st_size; + MSVCRT___time32_t st_atime; + MSVCRT___time32_t st_mtime; + MSVCRT___time32_t st_ctime; +}; + +struct MSVCRT__stat32i64 { + MSVCRT__dev_t st_dev; + MSVCRT__ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + MSVCRT__dev_t st_rdev; + __int64 DECLSPEC_ALIGN(8) st_size; + MSVCRT___time32_t st_atime; + MSVCRT___time32_t st_mtime; + MSVCRT___time32_t st_ctime; +}; + +struct MSVCRT__stat64i32 { + MSVCRT__dev_t st_dev; + MSVCRT__ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + MSVCRT__dev_t st_rdev; + MSVCRT__off_t st_size; + MSVCRT___time64_t st_atime; + MSVCRT___time64_t st_mtime; + MSVCRT___time64_t st_ctime; +}; + +struct MSVCRT__stat64 { + MSVCRT__dev_t st_dev; + MSVCRT__ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + MSVCRT__dev_t st_rdev; + __int64 DECLSPEC_ALIGN(8) st_size; + MSVCRT___time64_t st_atime; + MSVCRT___time64_t st_mtime; + MSVCRT___time64_t st_ctime; +}; + +#ifdef _WIN64 +#define MSVCRT__finddata_t MSVCRT__finddata64i32_t +#define MSVCRT__finddatai64_t MSVCRT__finddata64_t +#define MSVCRT__wfinddata_t MSVCRT__wfinddata64i32_t +#define MSVCRT__wfinddatai64_t MSVCRT__wfinddata64_t +#define MSVCRT__stat MSVCRT__stat64i32 +#define MSVCRT__stati64 MSVCRT__stat64 +#else +#define MSVCRT__finddata_t MSVCRT__finddata32_t +#define MSVCRT__finddatai64_t MSVCRT__finddata32i64_t +#define MSVCRT__wfinddata_t MSVCRT__wfinddata32_t +#define MSVCRT__wfinddatai64_t MSVCRT__wfinddata32i64_t +#define MSVCRT__stat MSVCRT__stat32 +#define MSVCRT__stati64 MSVCRT__stat32i64 +#endif + +#define MSVCRT_WEOF (MSVCRT_wint_t)(0xFFFF) +#define MSVCRT_EOF (-1) +#define MSVCRT_TMP_MAX 0x7fff +#define MSVCRT_TMP_MAX_S 0x7fffffff +#define MSVCRT_RAND_MAX 0x7fff +#define MSVCRT_BUFSIZ 512 + +#define MSVCRT_SEEK_SET 0 +#define MSVCRT_SEEK_CUR 1 +#define MSVCRT_SEEK_END 2 + +#define MSVCRT_NO_CONSOLE_FD (-2) +#define MSVCRT_NO_CONSOLE ((HANDLE)MSVCRT_NO_CONSOLE_FD) + +#define MSVCRT_STDIN_FILENO 0 +#define MSVCRT_STDOUT_FILENO 1 +#define MSVCRT_STDERR_FILENO 2 + +/* more file._flag flags, but these conflict with Unix */ +#define MSVCRT__IOFBF 0x0000 +#define MSVCRT__IONBF 0x0004 +#define MSVCRT__IOLBF 0x0040 + +#define MSVCRT_FILENAME_MAX 260 +#define MSVCRT_DRIVE_MAX 3 +#define MSVCRT_FNAME_MAX 256 +#define MSVCRT_DIR_MAX 256 +#define MSVCRT_EXT_MAX 256 +#define MSVCRT_PATH_MAX 260 +#define MSVCRT_stdin (MSVCRT__iob+MSVCRT_STDIN_FILENO) +#define MSVCRT_stdout (MSVCRT__iob+MSVCRT_STDOUT_FILENO) +#define MSVCRT_stderr (MSVCRT__iob+MSVCRT_STDERR_FILENO) + +#define MSVCRT__P_WAIT 0 +#define MSVCRT__P_NOWAIT 1 +#define MSVCRT__P_OVERLAY 2 +#define MSVCRT__P_NOWAITO 3 +#define MSVCRT__P_DETACH 4 + +#define MSVCRT_EPERM 1 +#define MSVCRT_ENOENT 2 +#define MSVCRT_ESRCH 3 +#define MSVCRT_EINTR 4 +#define MSVCRT_EIO 5 +#define MSVCRT_ENXIO 6 +#define MSVCRT_E2BIG 7 +#define MSVCRT_ENOEXEC 8 +#define MSVCRT_EBADF 9 +#define MSVCRT_ECHILD 10 +#define MSVCRT_EAGAIN 11 +#define MSVCRT_ENOMEM 12 +#define MSVCRT_EACCES 13 +#define MSVCRT_EFAULT 14 +#define MSVCRT_EBUSY 16 +#define MSVCRT_EEXIST 17 +#define MSVCRT_EXDEV 18 +#define MSVCRT_ENODEV 19 +#define MSVCRT_ENOTDIR 20 +#define MSVCRT_EISDIR 21 +#define MSVCRT_EINVAL 22 +#define MSVCRT_ENFILE 23 +#define MSVCRT_EMFILE 24 +#define MSVCRT_ENOTTY 25 +#define MSVCRT_EFBIG 27 +#define MSVCRT_ENOSPC 28 +#define MSVCRT_ESPIPE 29 +#define MSVCRT_EROFS 30 +#define MSVCRT_EMLINK 31 +#define MSVCRT_EPIPE 32 +#define MSVCRT_EDOM 33 +#define MSVCRT_ERANGE 34 +#define MSVCRT_EDEADLK 36 +#define MSVCRT_EDEADLOCK MSVCRT_EDEADLK +#define MSVCRT_ENAMETOOLONG 38 +#define MSVCRT_ENOLCK 39 +#define MSVCRT_ENOSYS 40 +#define MSVCRT_ENOTEMPTY 41 +#define MSVCRT_EILSEQ 42 +#define MSVCRT_STRUNCATE 80 + +#define MSVCRT_LC_ALL 0 +#define MSVCRT_LC_COLLATE 1 +#define MSVCRT_LC_CTYPE 2 +#define MSVCRT_LC_MONETARY 3 +#define MSVCRT_LC_NUMERIC 4 +#define MSVCRT_LC_TIME 5 +#define MSVCRT_LC_MIN MSVCRT_LC_ALL +#define MSVCRT_LC_MAX MSVCRT_LC_TIME + +#define MSVCRT__HEAPEMPTY -1 +#define MSVCRT__HEAPOK -2 +#define MSVCRT__HEAPBADBEGIN -3 +#define MSVCRT__HEAPBADNODE -4 +#define MSVCRT__HEAPEND -5 +#define MSVCRT__HEAPBADPTR -6 + +#define MSVCRT__FREEENTRY 0 +#define MSVCRT__USEDENTRY 1 + +#define MSVCRT__OUT_TO_DEFAULT 0 +#define MSVCRT__OUT_TO_STDERR 1 +#define MSVCRT__OUT_TO_MSGBOX 2 +#define MSVCRT__REPORT_ERRMODE 3 + +/* ASCII char classification table - binary compatible */ +#define MSVCRT__UPPER 0x0001 /* C1_UPPER */ +#define MSVCRT__LOWER 0x0002 /* C1_LOWER */ +#define MSVCRT__DIGIT 0x0004 /* C1_DIGIT */ +#define MSVCRT__SPACE 0x0008 /* C1_SPACE */ +#define MSVCRT__PUNCT 0x0010 /* C1_PUNCT */ +#define MSVCRT__CONTROL 0x0020 /* C1_CNTRL */ +#define MSVCRT__BLANK 0x0040 /* C1_BLANK */ +#define MSVCRT__HEX 0x0080 /* C1_XDIGIT */ +#define MSVCRT__LEADBYTE 0x8000 +#define MSVCRT__ALPHA (0x0100|MSVCRT__UPPER|MSVCRT__LOWER) /* (C1_ALPHA|_UPPER|_LOWER) */ + +#define MSVCRT__IOREAD 0x0001 +#define MSVCRT__IOWRT 0x0002 +#define MSVCRT__IOMYBUF 0x0008 +#define MSVCRT__IOEOF 0x0010 +#define MSVCRT__IOERR 0x0020 +#define MSVCRT__IOSTRG 0x0040 +#define MSVCRT__IORW 0x0080 +#define MSVCRT__USERBUF 0x0100 +#define MSVCRT__IOCOMMIT 0x4000 + +#define MSVCRT__S_IEXEC 0x0040 +#define MSVCRT__S_IWRITE 0x0080 +#define MSVCRT__S_IREAD 0x0100 +#define MSVCRT__S_IFIFO 0x1000 +#define MSVCRT__S_IFCHR 0x2000 +#define MSVCRT__S_IFDIR 0x4000 +#define MSVCRT__S_IFREG 0x8000 +#define MSVCRT__S_IFMT 0xF000 + +#define MSVCRT__LK_UNLCK 0 +#define MSVCRT__LK_LOCK 1 +#define MSVCRT__LK_NBLCK 2 +#define MSVCRT__LK_RLCK 3 +#define MSVCRT__LK_NBRLCK 4 + +#define MSVCRT__SH_COMPAT 0x00 /* Compatibility */ +#define MSVCRT__SH_DENYRW 0x10 /* Deny read/write */ +#define MSVCRT__SH_DENYWR 0x20 /* Deny write */ +#define MSVCRT__SH_DENYRD 0x30 /* Deny read */ +#define MSVCRT__SH_DENYNO 0x40 /* Deny nothing */ + +#define MSVCRT__O_RDONLY 0 +#define MSVCRT__O_WRONLY 1 +#define MSVCRT__O_RDWR 2 +#define MSVCRT__O_ACCMODE (MSVCRT__O_RDONLY|MSVCRT__O_WRONLY|MSVCRT__O_RDWR) +#define MSVCRT__O_APPEND 0x0008 +#define MSVCRT__O_RANDOM 0x0010 +#define MSVCRT__O_SEQUENTIAL 0x0020 +#define MSVCRT__O_TEMPORARY 0x0040 +#define MSVCRT__O_NOINHERIT 0x0080 +#define MSVCRT__O_CREAT 0x0100 +#define MSVCRT__O_TRUNC 0x0200 +#define MSVCRT__O_EXCL 0x0400 +#define MSVCRT__O_SHORT_LIVED 0x1000 +#define MSVCRT__O_TEXT 0x4000 +#define MSVCRT__O_BINARY 0x8000 +#define MSVCRT__O_RAW MSVCRT__O_BINARY +#define MSVCRT__O_WTEXT 0x10000 +#define MSVCRT__O_U16TEXT 0x20000 +#define MSVCRT__O_U8TEXT 0x40000 + +/* _statusfp bit flags */ +#define MSVCRT__SW_INEXACT 0x00000001 /* inexact (precision) */ +#define MSVCRT__SW_UNDERFLOW 0x00000002 /* underflow */ +#define MSVCRT__SW_OVERFLOW 0x00000004 /* overflow */ +#define MSVCRT__SW_ZERODIVIDE 0x00000008 /* zero divide */ +#define MSVCRT__SW_INVALID 0x00000010 /* invalid */ + +#define MSVCRT__SW_UNEMULATED 0x00000040 /* unemulated instruction */ +#define MSVCRT__SW_SQRTNEG 0x00000080 /* square root of a neg number */ +#define MSVCRT__SW_STACKOVERFLOW 0x00000200 /* FP stack overflow */ +#define MSVCRT__SW_STACKUNDERFLOW 0x00000400 /* FP stack underflow */ + +#define MSVCRT__SW_DENORMAL 0x00080000 /* denormal status bit */ + +/* fpclass constants */ +#define MSVCRT__FPCLASS_SNAN 0x0001 /* Signaling "Not a Number" */ +#define MSVCRT__FPCLASS_QNAN 0x0002 /* Quiet "Not a Number" */ +#define MSVCRT__FPCLASS_NINF 0x0004 /* Negative Infinity */ +#define MSVCRT__FPCLASS_NN 0x0008 /* Negative Normal */ +#define MSVCRT__FPCLASS_ND 0x0010 /* Negative Denormal */ +#define MSVCRT__FPCLASS_NZ 0x0020 /* Negative Zero */ +#define MSVCRT__FPCLASS_PZ 0x0040 /* Positive Zero */ +#define MSVCRT__FPCLASS_PD 0x0080 /* Positive Denormal */ +#define MSVCRT__FPCLASS_PN 0x0100 /* Positive Normal */ +#define MSVCRT__FPCLASS_PINF 0x0200 /* Positive Infinity */ + +/* fpclassify constants */ +#define MSVCRT_FP_INFINITE 1 +#define MSVCRT_FP_NAN 2 +#define MSVCRT_FP_NORMAL -1 +#define MSVCRT_FP_SUBNORMAL -2 +#define MSVCRT_FP_ZERO 0 + +#define MSVCRT__MCW_EM 0x0008001f +#define MSVCRT__MCW_IC 0x00040000 +#define MSVCRT__MCW_RC 0x00000300 +#define MSVCRT__MCW_PC 0x00030000 +#define MSVCRT__MCW_DN 0x03000000 + +#define MSVCRT__EM_INVALID 0x00000010 +#define MSVCRT__EM_DENORMAL 0x00080000 +#define MSVCRT__EM_ZERODIVIDE 0x00000008 +#define MSVCRT__EM_OVERFLOW 0x00000004 +#define MSVCRT__EM_UNDERFLOW 0x00000002 +#define MSVCRT__EM_INEXACT 0x00000001 +#define MSVCRT__IC_AFFINE 0x00040000 +#define MSVCRT__IC_PROJECTIVE 0x00000000 +#define MSVCRT__RC_CHOP 0x00000300 +#define MSVCRT__RC_UP 0x00000200 +#define MSVCRT__RC_DOWN 0x00000100 +#define MSVCRT__RC_NEAR 0x00000000 +#define MSVCRT__PC_24 0x00020000 +#define MSVCRT__PC_53 0x00010000 +#define MSVCRT__PC_64 0x00000000 +#define MSVCRT__DN_SAVE 0x00000000 +#define MSVCRT__DN_FLUSH 0x01000000 +#define MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS 0x02000000 +#define MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS 0x03000000 +#define MSVCRT__EM_AMBIGUOUS 0x80000000 + +typedef struct +{ + unsigned int control; + unsigned int status; +} MSVCRT_fenv_t; + +#define MSVCRT_CLOCKS_PER_SEC 1000 + +/* signals */ +#define MSVCRT_SIGINT 2 +#define MSVCRT_SIGILL 4 +#define MSVCRT_SIGFPE 8 +#define MSVCRT_SIGSEGV 11 +#define MSVCRT_SIGTERM 15 +#define MSVCRT_SIGBREAK 21 +#define MSVCRT_SIGABRT 22 +#define MSVCRT_NSIG (MSVCRT_SIGABRT + 1) + +typedef void (__cdecl *MSVCRT___sighandler_t)(int); + +#define MSVCRT_SIG_DFL ((MSVCRT___sighandler_t)0) +#define MSVCRT_SIG_IGN ((MSVCRT___sighandler_t)1) +#define MSVCRT_SIG_ERR ((MSVCRT___sighandler_t)-1) + +#define MSVCRT__FPE_INVALID 0x81 +#define MSVCRT__FPE_DENORMAL 0x82 +#define MSVCRT__FPE_ZERODIVIDE 0x83 +#define MSVCRT__FPE_OVERFLOW 0x84 +#define MSVCRT__FPE_UNDERFLOW 0x85 +#define MSVCRT__FPE_INEXACT 0x86 +#define MSVCRT__FPE_UNEMULATED 0x87 +#define MSVCRT__FPE_SQRTNEG 0x88 +#define MSVCRT__FPE_STACKOVERFLOW 0x8a +#define MSVCRT__FPE_STACKUNDERFLOW 0x8b +#define MSVCRT__FPE_EXPLICITGEN 0x8c + +#define _MS 0x01 +#define _MP 0x02 +#define _M1 0x04 +#define _M2 0x08 + +#define _SBUP 0x10 +#define _SBLOW 0x20 + +#define _MBC_SINGLE 0 +#define _MBC_LEAD 1 +#define _MBC_TRAIL 2 +#define _MBC_ILLEGAL -1 + +#define _MB_CP_SBCS 0 +#define _MB_CP_OEM -2 +#define _MB_CP_ANSI -3 +#define _MB_CP_LOCALE -4 + +#define MSVCRT__TRUNCATE ((MSVCRT_size_t)-1) + +#define _MAX__TIME64_T (((MSVCRT___time64_t)0x00000007 << 32) | 0x93406FFF) + +/* _set_abort_behavior codes */ +#define MSVCRT__WRITE_ABORT_MSG 1 +#define MSVCRT__CALL_REPORTFAULT 2 + +/* _get_output_format return code */ +#define MSVCRT__TWO_DIGIT_EXPONENT 0x1 + +#define MSVCRT__NLSCMPERROR ((unsigned int)0x7fffffff) + +void __cdecl MSVCRT_free(void*); +void* __cdecl MSVCRT_malloc(MSVCRT_size_t); +void* __cdecl MSVCRT_calloc(MSVCRT_size_t,MSVCRT_size_t); +void* __cdecl MSVCRT_realloc(void*,MSVCRT_size_t); + +int __cdecl MSVCRT_iswalpha(MSVCRT_wint_t); +int __cdecl MSVCRT_iswspace(MSVCRT_wint_t); +int __cdecl MSVCRT_iswdigit(MSVCRT_wint_t); +int __cdecl MSVCRT_isleadbyte(int); +int __cdecl MSVCRT__isleadbyte_l(int, MSVCRT__locale_t); +int __cdecl MSVCRT__isspace_l(int, MSVCRT__locale_t); +int __cdecl MSVCRT__iswspace_l(MSVCRT_wchar_t, MSVCRT__locale_t); + +void __cdecl MSVCRT__lock_file(MSVCRT_FILE*); +void __cdecl MSVCRT__unlock_file(MSVCRT_FILE*); +int __cdecl MSVCRT_fgetc(MSVCRT_FILE*); +int __cdecl MSVCRT__fgetc_nolock(MSVCRT_FILE*); +int __cdecl MSVCRT__fputc_nolock(int,MSVCRT_FILE*); +int __cdecl MSVCRT_ungetc(int,MSVCRT_FILE*); +int __cdecl MSVCRT__ungetc_nolock(int,MSVCRT_FILE*); +MSVCRT_wint_t __cdecl MSVCRT_fgetwc(MSVCRT_FILE*); +MSVCRT_wint_t __cdecl MSVCRT__fgetwc_nolock(MSVCRT_FILE*); +MSVCRT_wint_t __cdecl MSVCRT__fputwc_nolock(MSVCRT_wint_t,MSVCRT_FILE*); +MSVCRT_wint_t __cdecl MSVCRT_ungetwc(MSVCRT_wint_t,MSVCRT_FILE*); +MSVCRT_wint_t __cdecl MSVCRT__ungetwc_nolock(MSVCRT_wint_t, MSVCRT_FILE*); +int __cdecl MSVCRT__fseeki64_nolock(MSVCRT_FILE*,__int64,int); +__int64 __cdecl MSVCRT__ftelli64(MSVCRT_FILE* file); +__int64 __cdecl MSVCRT__ftelli64_nolock(MSVCRT_FILE*); +void __cdecl MSVCRT__exit(int); +void __cdecl MSVCRT_abort(void); +MSVCRT_ulong* __cdecl MSVCRT___doserrno(void); +int* __cdecl MSVCRT__errno(void); +char* __cdecl MSVCRT_getenv(const char*); +MSVCRT_size_t __cdecl MSVCRT__fread_nolock(void*,MSVCRT_size_t,MSVCRT_size_t,MSVCRT_FILE*); +MSVCRT_size_t __cdecl MSVCRT__fread_nolock_s(void*,MSVCRT_size_t,MSVCRT_size_t,MSVCRT_size_t,MSVCRT_FILE*); +MSVCRT_size_t __cdecl MSVCRT__fwrite_nolock(const void*,MSVCRT_size_t,MSVCRT_size_t,MSVCRT_FILE*); +int __cdecl MSVCRT_fclose(MSVCRT_FILE*); +int __cdecl MSVCRT__fclose_nolock(MSVCRT_FILE*); +int __cdecl MSVCRT__fflush_nolock(MSVCRT_FILE*); +void __cdecl MSVCRT_terminate(void); +MSVCRT_FILE* __cdecl MSVCRT__iob_func(void); +MSVCRT_clock_t __cdecl MSVCRT_clock(void); +MSVCRT___time32_t __cdecl MSVCRT__time32(MSVCRT___time32_t*); +MSVCRT___time64_t __cdecl MSVCRT__time64(MSVCRT___time64_t*); +MSVCRT_FILE* __cdecl MSVCRT__fdopen(int, const char *); +MSVCRT_FILE* __cdecl MSVCRT__wfdopen(int, const MSVCRT_wchar_t *); +int __cdecl MSVCRT_vsnprintf(char *str, MSVCRT_size_t len, const char *format, __ms_va_list valist); +int __cdecl MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, MSVCRT_size_t len, + const MSVCRT_wchar_t *format, __ms_va_list valist ); +int WINAPIV MSVCRT__snwprintf(MSVCRT_wchar_t*, unsigned int, const MSVCRT_wchar_t*, ...); +int WINAPIV MSVCRT_sprintf(char*,const char*,...); +int WINAPIV MSVCRT__snprintf(char*,unsigned int,const char*,...); +int WINAPIV MSVCRT__scprintf(const char*,...); +int __cdecl MSVCRT_raise(int sig); +int __cdecl MSVCRT__set_printf_count_output(int); + +#define MSVCRT__ENABLE_PER_THREAD_LOCALE 1 +#define MSVCRT__DISABLE_PER_THREAD_LOCALE 2 + +extern MSVCRT__locale_t MSVCRT_locale; +MSVCRT_pthreadlocinfo get_locinfo(void) DECLSPEC_HIDDEN; +MSVCRT_pthreadmbcinfo get_mbcinfo(void) DECLSPEC_HIDDEN; +void __cdecl MSVCRT__free_locale(MSVCRT__locale_t); +void free_locinfo(MSVCRT_pthreadlocinfo) DECLSPEC_HIDDEN; +void free_mbcinfo(MSVCRT_pthreadmbcinfo) DECLSPEC_HIDDEN; +int _setmbcp_l(int, LCID, MSVCRT_pthreadmbcinfo) DECLSPEC_HIDDEN; + +#ifndef __WINE_MSVCRT_TEST +int __cdecl MSVCRT__write(int,const void*,unsigned int); +int __cdecl _getch(void); +int __cdecl _ismbblead(unsigned int); +int __cdecl _ismbblead_l(unsigned int, MSVCRT__locale_t); +int __cdecl _ismbclegal(unsigned int c); +int __cdecl _ismbstrail(const unsigned char* start, const unsigned char* str); +int __cdecl MSVCRT_mbtowc(MSVCRT_wchar_t*,const char*,MSVCRT_size_t); +int __cdecl MSVCRT_mbtowc_l(MSVCRT_wchar_t*,const char*,MSVCRT_size_t,MSVCRT__locale_t); +MSVCRT_size_t __cdecl MSVCRT_mbstowcs(MSVCRT_wchar_t*,const char*,MSVCRT_size_t); +MSVCRT_size_t __cdecl MSVCRT__mbstowcs_l(MSVCRT_wchar_t*, const char*, MSVCRT_size_t, MSVCRT__locale_t); +int __cdecl MSVCRT__mbstowcs_s_l(MSVCRT_size_t*, MSVCRT_wchar_t*, + MSVCRT_size_t, const char*, MSVCRT_size_t, MSVCRT__locale_t); +MSVCRT_size_t __cdecl MSVCRT_wcstombs(char*,const MSVCRT_wchar_t*,MSVCRT_size_t); +MSVCRT_size_t __cdecl MSVCRT__wcstombs_l(char*, const MSVCRT_wchar_t*, MSVCRT_size_t, MSVCRT__locale_t); +MSVCRT_intptr_t __cdecl MSVCRT__spawnve(int,const char*,const char* const *,const char* const *); +MSVCRT_intptr_t __cdecl MSVRT__spawnvpe(int,const char*,const char* const *,const char* const *); +MSVCRT_intptr_t __cdecl MSVCRT__wspawnve(int,const MSVCRT_wchar_t*,const MSVCRT_wchar_t* const *,const MSVCRT_wchar_t* const *); +MSVCRT_intptr_t __cdecl MSVCRT__wspawnvpe(int,const MSVCRT_wchar_t*,const MSVCRT_wchar_t* const *,const MSVCRT_wchar_t* const *); +void __cdecl MSVCRT__searchenv(const char*,const char*,char*); +int __cdecl MSVCRT__getdrive(void); +char* __cdecl MSVCRT__strdup(const char*); +char* __cdecl MSVCRT__strnset(char*,int,MSVCRT_size_t); +char* __cdecl _strset(char*,int); +int __cdecl _ungetch(int); +int __cdecl _cputs(const char*); +int WINAPIV _cprintf(const char*,...); +int WINAPIV _cwprintf(const MSVCRT_wchar_t*,...); +char*** __cdecl MSVCRT___p__environ(void); +int* __cdecl __p___mb_cur_max(void); +int* __cdecl MSVCRT___p__fmode(void); +MSVCRT_wchar_t* __cdecl MSVCRT__wcsdup(const MSVCRT_wchar_t*); +MSVCRT_size_t __cdecl MSVCRT_strnlen(const char *,MSVCRT_size_t); +MSVCRT_size_t __cdecl MSVCRT_wcsnlen(const MSVCRT_wchar_t*,MSVCRT_size_t); +MSVCRT_wchar_t*** __cdecl MSVCRT___p__wenviron(void); +INT __cdecl MSVCRT_wctomb(char*,MSVCRT_wchar_t); +int __cdecl MSVCRT__wctomb_l(char*, MSVCRT_wchar_t, MSVCRT__locale_t); +char* __cdecl MSVCRT__strdate(char* date); +char* __cdecl MSVCRT__strtime(char* date); +int __cdecl _setmbcp(int); +int __cdecl MSVCRT__close(int); +int __cdecl MSVCRT__dup(int); +int __cdecl MSVCRT__dup2(int, int); +int __cdecl MSVCRT__pipe(int *, unsigned int, int); +MSVCRT_wchar_t* __cdecl MSVCRT__wgetenv(const MSVCRT_wchar_t*); +void __cdecl MSVCRT__wsearchenv(const MSVCRT_wchar_t*, const MSVCRT_wchar_t*, MSVCRT_wchar_t*); +MSVCRT_intptr_t __cdecl MSVCRT__spawnvpe(int, const char*, const char* const*, const char* const*); +void __cdecl MSVCRT__invalid_parameter(const MSVCRT_wchar_t *expr, const MSVCRT_wchar_t *func, + const MSVCRT_wchar_t *file, unsigned int line, MSVCRT_uintptr_t arg); +int __cdecl MSVCRT__toupper_l(int,MSVCRT__locale_t); +int __cdecl MSVCRT__tolower_l(int,MSVCRT__locale_t); +int __cdecl MSVCRT__towupper_l(MSVCRT_wint_t,MSVCRT__locale_t); +int __cdecl MSVCRT__towlower_l(MSVCRT_wint_t,MSVCRT__locale_t); +int __cdecl MSVCRT__toupper(int); /* only use on lower-case ASCII characters */ +int __cdecl MSVCRT__stricmp(const char*, const char*); +int __cdecl MSVCRT__strnicmp(const char*, const char*, MSVCRT_size_t); +int __cdecl MSVCRT__strnicoll_l(const char*, const char*, MSVCRT_size_t, MSVCRT__locale_t); +int __cdecl MSVCRT__strncoll_l(const char*, const char*, MSVCRT_size_t, MSVCRT__locale_t); +int __cdecl MSVCRT_strncmp(const char*, const char*, MSVCRT_size_t); +int __cdecl MSVCRT_strcmp(const char*, const char*); +char* __cdecl MSVCRT_strstr(const char*, const char*); +unsigned int __cdecl MSVCRT__get_output_format(void); +char* __cdecl MSVCRT_strtok_s(char*, const char*, char**); +double parse_double(MSVCRT_wchar_t (*)(void*), void (*)(void*), void*, MSVCRT_pthreadlocinfo, int*); + +/* Maybe one day we'll enable the invalid parameter handlers with the full set of information (msvcrXXd) + * #define MSVCRT_INVALID_PMT(x) MSVCRT_call_invalid_parameter_handler(x, __FUNCTION__, __FILE__, __LINE__, 0) + * #define MSVCRT_CHECK_PMT(x) ((x) ? TRUE : MSVCRT_INVALID_PMT(#x),FALSE) + * Until this is done, just keep the same semantics for CHECK_PMT(), but without generating / sending + * any information + * NB : MSVCRT_call_invalid_parameter_handler is a wrapper around MSVCRT__invalid_parameter in order + * to do the Ansi to Unicode transformation + */ +#define MSVCRT_INVALID_PMT(x,err) (*MSVCRT__errno() = (err), MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0)) +#define MSVCRT_CHECK_PMT_ERR(x,err) ((x) || (MSVCRT_INVALID_PMT( 0, (err) ), FALSE)) +#define MSVCRT_CHECK_PMT(x) MSVCRT_CHECK_PMT_ERR((x), MSVCRT_EINVAL) +#endif + +#define MSVCRT__ARGMAX 100 +typedef int (*puts_clbk_a)(void*, int, const char*); +typedef int (*puts_clbk_w)(void*, int, const MSVCRT_wchar_t*); +typedef union _printf_arg +{ + void *get_ptr; + int get_int; + LONGLONG get_longlong; + double get_double; +} printf_arg; +typedef printf_arg (*args_clbk)(void*, int, int, __ms_va_list*); +int pf_printf_a(puts_clbk_a, void*, const char*, MSVCRT__locale_t, + DWORD, args_clbk, void*, __ms_va_list*) DECLSPEC_HIDDEN; +int pf_printf_w(puts_clbk_w, void*, const MSVCRT_wchar_t*, MSVCRT__locale_t, + DWORD, args_clbk, void*, __ms_va_list*) DECLSPEC_HIDDEN; +int create_positional_ctx_a(void*, const char*, __ms_va_list) DECLSPEC_HIDDEN; +int create_positional_ctx_w(void*, const MSVCRT_wchar_t*, __ms_va_list) DECLSPEC_HIDDEN; +printf_arg arg_clbk_valist(void*, int, int, __ms_va_list*) DECLSPEC_HIDDEN; +printf_arg arg_clbk_positional(void*, int, int, __ms_va_list*) DECLSPEC_HIDDEN; + +#define MSVCRT_FLT_MIN 1.175494351e-38F +#define MSVCRT_DBL_MIN 2.2250738585072014e-308 +#define MSVCRT__OVERFLOW 3 +#define MSVCRT__UNDERFLOW 4 + +#define MSVCRT_FP_ILOGB0 (-MSVCRT_INT_MAX - 1) +#define MSVCRT_FP_ILOGBNAN MSVCRT_INT_MAX + +typedef struct +{ + float f; +} MSVCRT__CRT_FLOAT; + +typedef struct +{ + double x; +} MSVCRT__CRT_DOUBLE; + +extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t,unsigned short int); + +/* __unDName/__unDNameEx flags */ +#define UNDNAME_COMPLETE (0x0000) +#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) /* Don't show __ in calling convention */ +#define UNDNAME_NO_MS_KEYWORDS (0x0002) /* Don't show calling convention at all */ +#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) /* Don't show function/method return value */ +#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) +#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) +#define UNDNAME_NO_MS_THISTYPE (0x0020) +#define UNDNAME_NO_CV_THISTYPE (0x0040) +#define UNDNAME_NO_THISTYPE (0x0060) +#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) /* Don't show access specifier (public/protected/private) */ +#define UNDNAME_NO_THROW_SIGNATURES (0x0100) +#define UNDNAME_NO_MEMBER_TYPE (0x0200) /* Don't show static/virtual specifier */ +#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) +#define UNDNAME_32_BIT_DECODE (0x0800) +#define UNDNAME_NAME_ONLY (0x1000) /* Only report the variable/method name */ +#define UNDNAME_NO_ARGUMENTS (0x2000) /* Don't show method arguments */ +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) +#define UNDNAME_NO_COMPLEX_TYPE (0x8000) + +#define UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION (0x0001) +#define UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR (0x0002) +#define UCRTBASE_PRINTF_LEGACY_WIDE_SPECIFIERS (0x0004) +#define UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY (0x0008) +#define UCRTBASE_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS (0x0010) + +#define UCRTBASE_PRINTF_MASK (0x001F) + +#define MSVCRT_PRINTF_POSITIONAL_PARAMS (0x0100) +#define MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER (0x0200) + +#define UCRTBASE_SCANF_SECURECRT (0x0001) +#define UCRTBASE_SCANF_LEGACY_WIDE_SPECIFIERS (0x0002) +#define UCRTBASE_SCANF_LEGACY_MSVCRT_COMPATIBILITY (0x0004) + +#define UCRTBASE_SCANF_MASK (0x0007) + +#define COOPERATIVE_TIMEOUT_INFINITE ((unsigned int)-1) +#define COOPERATIVE_WAIT_TIMEOUT ~0 + +typedef enum { + _FpCodeUnspecified, + _FpCodeAdd, + _FpCodeSubtract, + _FpCodeMultiply, + _FpCodeDivide, + _FpCodeSquareRoot, + _FpCodeRemainder, + _FpCodeCompare, + _FpCodeConvert, + _FpCodeRound, + _FpCodeTruncate, + _FpCodeFloor, + _FpCodeCeil, + _FpCodeAcos, + _FpCodeAsin, + _FpCodeAtan, + _FpCodeAtan2, + _FpCodeCabs, + _FpCodeCos, + _FpCodeCosh, + _FpCodeExp, + _FpCodeFabs, + _FpCodeFmod, + _FpCodeFrexp, + _FpCodeHypot, + _FpCodeLdexp, + _FpCodeLog, + _FpCodeLog10, + _FpCodeModf, + _FpCodePow, + _FpCodeSin, + _FpCodeSinh, + _FpCodeTan, + _FpCodeTanh, + _FpCodeY0, + _FpCodeY1, + _FpCodeYn, + _FpCodeLogb, + _FpCodeNextafter, + _FpCodeNegate, + _FpCodeFmin, + _FpCodeFmax, + _FpCodeConvertTrunc, + _XMMIAddps, + _XMMIAddss, + _XMMISubps, + _XMMISubss, + _XMMIMulps, + _XMMIMulss, + _XMMIDivps, + _XMMIDivss, + _XMMISqrtps, + _XMMISqrtss, + _XMMIMaxps, + _XMMIMaxss, + _XMMIMinps, + _XMMIMinss, + _XMMICmpps, + _XMMICmpss, + _XMMIComiss, + _XMMIUComiss, + _XMMICvtpi2ps, + _XMMICvtsi2ss, + _XMMICvtps2pi, + _XMMICvtss2si, + _XMMICvttps2pi, + _XMMICvttss2si, + _XMMIAddsubps, + _XMMIHaddps, + _XMMIHsubps, + _XMMI2Addpd, + _XMMI2Addsd, + _XMMI2Subpd, + _XMMI2Subsd, + _XMMI2Mulpd, + _XMMI2Mulsd, + _XMMI2Divpd, + _XMMI2Divsd, + _XMMI2Sqrtpd, + _XMMI2Sqrtsd, + _XMMI2Maxpd, + _XMMI2Maxsd, + _XMMI2Minpd, + _XMMI2Minsd, + _XMMI2Cmppd, + _XMMI2Cmpsd, + _XMMI2Comisd, + _XMMI2UComisd, + _XMMI2Cvtpd2pi, + _XMMI2Cvtsd2si, + _XMMI2Cvttpd2pi, + _XMMI2Cvttsd2si, + _XMMI2Cvtps2pd, + _XMMI2Cvtss2sd, + _XMMI2Cvtpd2ps, + _XMMI2Cvtsd2ss, + _XMMI2Cvtdq2ps, + _XMMI2Cvttps2dq, + _XMMI2Cvtps2dq, + _XMMI2Cvttpd2dq, + _XMMI2Cvtpd2dq, + _XMMI2Addsubpd, + _XMMI2Haddpd, + _XMMI2Hsubpd, +} _FP_OPERATION_CODE; + +typedef enum { + _FpFormatFp32, + _FpFormatFp64, + _FpFormatFp80, + _FpFormatFp128, + _FpFormatI16, + _FpFormatI32, + _FpFormatI64, + _FpFormatU16, + _FpFormatU32, + _FpFormatU64, + _FpFormatBcd80, + _FpFormatCompare, + _FpFormatString, +} _FPIEEE_FORMAT; + +typedef float _FP32; +typedef double _FP64; +typedef short _I16; +typedef int _I32; +typedef unsigned short _U16; +typedef unsigned int _U32; +typedef __int64 _Q64; + +typedef struct { + unsigned short W[5]; +} _FP80; + +typedef struct DECLSPEC_ALIGN(16) { + MSVCRT_ulong W[4]; +} _FP128; + +typedef struct DECLSPEC_ALIGN(8) { + MSVCRT_ulong W[2]; +} _I64; + +typedef struct DECLSPEC_ALIGN(8) { + MSVCRT_ulong W[2]; +} _U64; + +typedef struct { + unsigned short W[5]; +} _BCD80; + +typedef struct DECLSPEC_ALIGN(16) { + _Q64 W[2]; +} _FPQ64; + +typedef struct { + union { + _FP32 Fp32Value; + _FP64 Fp64Value; + _FP80 Fp80Value; + _FP128 Fp128Value; + _I16 I16Value; + _I32 I32Value; + _I64 I64Value; + _U16 U16Value; + _U32 U32Value; + _U64 U64Value; + _BCD80 Bcd80Value; + char *StringValue; + int CompareValue; + _Q64 Q64Value; + _FPQ64 Fpq64Value; + } Value; + unsigned int OperandValid : 1; + unsigned int Format : 4; +} _FPIEEE_VALUE; + +typedef struct { + unsigned int Inexact : 1; + unsigned int Underflow : 1; + unsigned int Overflow : 1; + unsigned int ZeroDivide : 1; + unsigned int InvalidOperation : 1; +} _FPIEEE_EXCEPTION_FLAGS; + +typedef struct { + unsigned int RoundingMode : 2; + unsigned int Precision : 3; + unsigned int Operation :12; + _FPIEEE_EXCEPTION_FLAGS Cause; + _FPIEEE_EXCEPTION_FLAGS Enable; + _FPIEEE_EXCEPTION_FLAGS Status; + _FPIEEE_VALUE Operand1; + _FPIEEE_VALUE Operand2; + _FPIEEE_VALUE Result; +} _FPIEEE_RECORD, *_PFPIEEE_RECORD; + +#define INHERIT_THREAD_PRIORITY 0xF000 + +#ifdef __REACTOS__ +#define __wine_longjmp longjmp +#define __wine_jmp_buf _JBTYPE +#endif + +#endif /* __WINE_MSVCRT_H */ diff --git a/sdk/lib/crt/wine/mtdll.h b/sdk/lib/crt/wine/mtdll.h new file mode 100644 index 00000000000..c01beaff93c --- /dev/null +++ b/sdk/lib/crt/wine/mtdll.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002, TransGaming Technologies Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + */ + +#ifndef WINE_MTDLL_H +#define WINE_MTDLL_H + +#if defined(_MT) + +#define _mlock(locknum) _lock(locknum) +#define _munlock(locknum) _unlock(locknum) + +void __cdecl _unlock( int locknum ); +void __cdecl _lock( int locknum ); + +#else + +#define _mlock(locknum) do {} while(0) +#define _munlock(locknum) do {} while(0) + +#endif + + +#define _SIGNAL_LOCK 1 +#define _IOB_SCAN_LOCK 2 +#define _TMPNAM_LOCK 3 +#define _INPUT_LOCK 4 +#define _OUTPUT_LOCK 5 +#define _CSCANF_LOCK 6 +#define _CPRINTF_LOCK 7 +#define _CONIO_LOCK 8 +#define _HEAP_LOCK 9 +#define _BHEAP_LOCK 10 /* No longer used? */ +#define _TIME_LOCK 11 +#define _ENV_LOCK 12 +#define _EXIT_LOCK1 13 +#define _EXIT_LOCK2 14 +#define _THREADDATA_LOCK 15 /* No longer used? */ +#define _POPEN_LOCK 16 +#define _LOCKTAB_LOCK 17 +#define _OSFHND_LOCK 18 +#define _SETLOCALE_LOCK 19 +#define _LC_COLLATE_LOCK 20 /* No longer used? */ +#define _LC_CTYPE_LOCK 21 /* No longer used? */ +#define _LC_MONETARY_LOCK 22 /* No longer used? */ +#define _LC_NUMERIC_LOCK 23 /* No longer used? */ +#define _LC_TIME_LOCK 24 /* No longer used? */ +#define _MB_CP_LOCK 25 +#define _NLG_LOCK 26 +#define _TYPEINFO_LOCK 27 +#define _STREAM_LOCKS 28 + +/* Must match definition in msvcrt/stdio.h */ +#define _IOB_ENTRIES 20 + +#define _LAST_STREAM_LOCK (_STREAM_LOCKS+_IOB_ENTRIES-1) + +#define _TOTAL_LOCKS (_LAST_STREAM_LOCK+1) + +#endif /* WINE_MTDLL_H */ diff --git a/sdk/lib/crt/wine/winternl.h b/sdk/lib/crt/wine/winternl.h new file mode 100644 index 00000000000..498c4367108 --- /dev/null +++ b/sdk/lib/crt/wine/winternl.h @@ -0,0 +1,313 @@ +/* + * Internal NT APIs and data structures + * + * Copyright (C) the Wine project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * 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 + */ + +#ifndef __WINE_WINTERNL_H +#define __WINE_WINTERNL_H + +#ifndef __REACTOS__ +#include +#endif /* __REACTOS__ */ +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +#ifndef WINE_NTSTATUS_DECLARED +#define WINE_NTSTATUS_DECLARED + typedef LONG NTSTATUS; +#endif + +#ifndef __UNICODE_STRING_DEFINED__ +#define __UNICODE_STRING_DEFINED__ + typedef struct _UNICODE_STRING { + USHORT Length; /* bytes */ + USHORT MaximumLength; /* bytes */ + PWSTR Buffer; + } UNICODE_STRING, * PUNICODE_STRING; +#endif + + typedef struct _CLIENT_ID + { + HANDLE UniqueProcess; + HANDLE UniqueThread; + } CLIENT_ID, * PCLIENT_ID; + + typedef struct _CURDIR + { + UNICODE_STRING DosPath; + PVOID Handle; + } CURDIR, * PCURDIR; + + typedef struct RTL_DRIVE_LETTER_CURDIR + { + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + UNICODE_STRING DosPath; + } RTL_DRIVE_LETTER_CURDIR, * PRTL_DRIVE_LETTER_CURDIR; + + typedef struct tagRTL_BITMAP { + ULONG SizeOfBitMap; /* Number of bits in the bitmap */ + PULONG Buffer; /* Bitmap data, assumed sized to a DWORD boundary */ + } RTL_BITMAP, * PRTL_BITMAP; + + typedef const RTL_BITMAP* PCRTL_BITMAP; + + typedef struct _RTL_USER_PROCESS_PARAMETERS + { + ULONG AllocationSize; + ULONG Size; + ULONG Flags; + ULONG DebugFlags; + HANDLE ConsoleHandle; + ULONG ConsoleFlags; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; + CURDIR CurrentDirectory; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PWSTR Environment; + ULONG dwX; + ULONG dwY; + ULONG dwXSize; + ULONG dwYSize; + ULONG dwXCountChars; + ULONG dwYCountChars; + ULONG dwFillAttribute; + ULONG dwFlags; + ULONG wShowWindow; + UNICODE_STRING WindowTitle; + UNICODE_STRING Desktop; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeInfo; + RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; + } RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; + + typedef struct _PEB_LDR_DATA + { + ULONG Length; + BOOLEAN Initialized; + PVOID SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; + } PEB_LDR_DATA, * PPEB_LDR_DATA; + + typedef struct _GDI_TEB_BATCH + { + ULONG Offset; + HANDLE HDC; + ULONG Buffer[0x136]; + } GDI_TEB_BATCH; + + typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME + { + struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous; + struct _ACTIVATION_CONTEXT* ActivationContext; + ULONG Flags; + } RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME; + + typedef struct _ACTIVATION_CONTEXT_STACK + { + ULONG Flags; + ULONG NextCookieSequenceNumber; + RTL_ACTIVATION_CONTEXT_STACK_FRAME* ActiveFrame; + LIST_ENTRY FrameListCache; + } ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK; + + typedef struct _TEB_ACTIVE_FRAME_CONTEXT + { + ULONG Flags; + const char* FrameName; + } TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT; + + typedef struct _TEB_ACTIVE_FRAME + { + ULONG Flags; + struct _TEB_ACTIVE_FRAME* Previous; + TEB_ACTIVE_FRAME_CONTEXT* Context; + } TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME; + + typedef struct _PEB + { /* win32/win64 */ + BOOLEAN InheritedAddressSpace; /* 000/000 */ + BOOLEAN ReadImageFileExecOptions; /* 001/001 */ + BOOLEAN BeingDebugged; /* 002/002 */ + BOOLEAN SpareBool; /* 003/003 */ + HANDLE Mutant; /* 004/008 */ + HMODULE ImageBaseAddress; /* 008/010 */ + PPEB_LDR_DATA LdrData; /* 00c/018 */ + RTL_USER_PROCESS_PARAMETERS* ProcessParameters; /* 010/020 */ + PVOID SubSystemData; /* 014/028 */ + HANDLE ProcessHeap; /* 018/030 */ + PRTL_CRITICAL_SECTION FastPebLock; /* 01c/038 */ + PVOID /*PPEBLOCKROUTINE*/ FastPebLockRoutine; /* 020/040 */ + PVOID /*PPEBLOCKROUTINE*/ FastPebUnlockRoutine; /* 024/048 */ + ULONG EnvironmentUpdateCount; /* 028/050 */ + PVOID KernelCallbackTable; /* 02c/058 */ + ULONG Reserved[2]; /* 030/060 */ + PVOID /*PPEB_FREE_BLOCK*/ FreeList; /* 038/068 */ + ULONG TlsExpansionCounter; /* 03c/070 */ + PRTL_BITMAP TlsBitmap; /* 040/078 */ + ULONG TlsBitmapBits[2]; /* 044/080 */ + PVOID ReadOnlySharedMemoryBase; /* 04c/088 */ + PVOID ReadOnlySharedMemoryHeap; /* 050/090 */ + PVOID* ReadOnlyStaticServerData; /* 054/098 */ + PVOID AnsiCodePageData; /* 058/0a0 */ + PVOID OemCodePageData; /* 05c/0a8 */ + PVOID UnicodeCaseTableData; /* 060/0b0 */ + ULONG NumberOfProcessors; /* 064/0b8 */ + ULONG NtGlobalFlag; /* 068/0bc */ + LARGE_INTEGER CriticalSectionTimeout; /* 070/0c0 */ + SIZE_T HeapSegmentReserve; /* 078/0c8 */ + SIZE_T HeapSegmentCommit; /* 07c/0d0 */ + SIZE_T HeapDeCommitTotalFreeThreshold; /* 080/0d8 */ + SIZE_T HeapDeCommitFreeBlockThreshold; /* 084/0e0 */ + ULONG NumberOfHeaps; /* 088/0e8 */ + ULONG MaximumNumberOfHeaps; /* 08c/0ec */ + PVOID* ProcessHeaps; /* 090/0f0 */ + PVOID GdiSharedHandleTable; /* 094/0f8 */ + PVOID ProcessStarterHelper; /* 098/100 */ + PVOID GdiDCAttributeList; /* 09c/108 */ + PVOID LoaderLock; /* 0a0/110 */ + ULONG OSMajorVersion; /* 0a4/118 */ + ULONG OSMinorVersion; /* 0a8/11c */ + ULONG OSBuildNumber; /* 0ac/120 */ + ULONG OSPlatformId; /* 0b0/124 */ + ULONG ImageSubSystem; /* 0b4/128 */ + ULONG ImageSubSystemMajorVersion; /* 0b8/12c */ + ULONG ImageSubSystemMinorVersion; /* 0bc/130 */ + ULONG ImageProcessAffinityMask; /* 0c0/134 */ + HANDLE GdiHandleBuffer[28]; /* 0c4/138 */ + ULONG unknown[6]; /* 134/218 */ + PVOID PostProcessInitRoutine; /* 14c/230 */ + PRTL_BITMAP TlsExpansionBitmap; /* 150/238 */ + ULONG TlsExpansionBitmapBits[32]; /* 154/240 */ + ULONG SessionId; /* 1d4/2c0 */ + ULARGE_INTEGER AppCompatFlags; /* 1d8/2c8 */ + ULARGE_INTEGER AppCompatFlagsUser; /* 1e0/2d0 */ + PVOID ShimData; /* 1e8/2d8 */ + PVOID AppCompatInfo; /* 1ec/2e0 */ + UNICODE_STRING CSDVersion; /* 1f0/2e8 */ + PVOID ActivationContextData; /* 1f8/2f8 */ + PVOID ProcessAssemblyStorageMap; /* 1fc/300 */ + PVOID SystemDefaultActivationData; /* 200/308 */ + PVOID SystemAssemblyStorageMap; /* 204/310 */ + SIZE_T MinimumStackCommit; /* 208/318 */ + PVOID* FlsCallback; /* 20c/320 */ + LIST_ENTRY FlsListHead; /* 210/328 */ + PRTL_BITMAP FlsBitmap; /* 218/338 */ + ULONG FlsBitmapBits[4]; /* 21c/340 */ + } PEB, * PPEB; + + typedef struct _TEB + { /* win32/win64 */ + NT_TIB Tib; /* 000/0000 */ + PVOID EnvironmentPointer; /* 01c/0038 */ + CLIENT_ID ClientId; /* 020/0040 */ + PVOID ActiveRpcHandle; /* 028/0050 */ + PVOID ThreadLocalStoragePointer; /* 02c/0058 */ + PPEB Peb; /* 030/0060 */ + ULONG LastErrorValue; /* 034/0068 */ + ULONG CountOfOwnedCriticalSections; /* 038/006c */ + PVOID CsrClientThread; /* 03c/0070 */ + PVOID Win32ThreadInfo; /* 040/0078 */ + ULONG Win32ClientInfo[31]; /* 044/0080 used for user32 private data in Wine */ + PVOID WOW32Reserved; /* 0c0/0100 */ + ULONG CurrentLocale; /* 0c4/0108 */ + ULONG FpSoftwareStatusRegister; /* 0c8/010c */ + PVOID SystemReserved1[54]; /* 0cc/0110 used for kernel32 private data in Wine */ + LONG ExceptionCode; /* 1a4/02c0 */ + ACTIVATION_CONTEXT_STACK ActivationContextStack; /* 1a8/02c8 */ + BYTE SpareBytes1[24]; /* 1bc/02e8 */ + PVOID SystemReserved2[10]; /* 1d4/0300 used for ntdll platform-specific private data in Wine */ + GDI_TEB_BATCH GdiTebBatch; /* 1fc/0350 used for ntdll private data in Wine */ + HANDLE gdiRgn; /* 6dc/0838 */ + HANDLE gdiPen; /* 6e0/0840 */ + HANDLE gdiBrush; /* 6e4/0848 */ + CLIENT_ID RealClientId; /* 6e8/0850 */ + HANDLE GdiCachedProcessHandle; /* 6f0/0860 */ + ULONG GdiClientPID; /* 6f4/0868 */ + ULONG GdiClientTID; /* 6f8/086c */ + PVOID GdiThreadLocaleInfo; /* 6fc/0870 */ + ULONG UserReserved[5]; /* 700/0878 */ + PVOID glDispatchTable[280]; /* 714/0890 */ + PVOID glReserved1[26]; /* b74/1150 */ + PVOID glReserved2; /* bdc/1220 */ + PVOID glSectionInfo; /* be0/1228 */ + PVOID glSection; /* be4/1230 */ + PVOID glTable; /* be8/1238 */ + PVOID glCurrentRC; /* bec/1240 */ + PVOID glContext; /* bf0/1248 */ + ULONG LastStatusValue; /* bf4/1250 */ + UNICODE_STRING StaticUnicodeString; /* bf8/1258 used by advapi32 */ + WCHAR StaticUnicodeBuffer[261]; /* c00/1268 used by advapi32 */ + PVOID DeallocationStack; /* e0c/1478 */ + PVOID TlsSlots[64]; /* e10/1480 */ + LIST_ENTRY TlsLinks; /* f10/1680 */ + PVOID Vdm; /* f18/1690 */ + PVOID ReservedForNtRpc; /* f1c/1698 */ + PVOID DbgSsReserved[2]; /* f20/16a0 */ + ULONG HardErrorDisabled; /* f28/16b0 */ + PVOID Instrumentation[16]; /* f2c/16b8 */ + PVOID WinSockData; /* f6c/1738 */ + ULONG GdiBatchCount; /* f70/1740 */ + ULONG Spare2; /* f74/1744 */ + ULONG GuaranteedStackBytes; /* f78/1748 */ + PVOID ReservedForPerf; /* f7c/1750 */ + PVOID ReservedForOle; /* f80/1758 */ + ULONG WaitingOnLoaderLock; /* f84/1760 */ + PVOID Reserved5[3]; /* f88/1768 */ + PVOID* TlsExpansionSlots; /* f94/1780 */ +#ifdef _WIN64 + PVOID DeallocationBStore; /* /1788 */ + PVOID BStoreLimit; /* /1790 */ +#endif + ULONG ImpersonationLocale; /* f98/1798 */ + ULONG IsImpersonating; /* f9c/179c */ + PVOID NlsCache; /* fa0/17a0 */ + PVOID ShimData; /* fa4/17a8 */ + ULONG HeapVirtualAffinity; /* fa8/17b0 */ + PVOID CurrentTransactionHandle; /* fac/17b8 */ + TEB_ACTIVE_FRAME* ActiveFrame; /* fb0/17c0 */ + PVOID* FlsSlots; /* fb4/17c8 */ + } TEB, * PTEB; + + NTSYSAPI PVOID WINAPI RtlAllocateHeap(HANDLE, ULONG, SIZE_T) __WINE_ALLOC_SIZE(3); + NTSYSAPI BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP, ULONG, ULONG); + NTSYSAPI BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP, ULONG, ULONG); + NTSYSAPI BOOLEAN WINAPI RtlFreeHeap(HANDLE, ULONG, PVOID); + NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG); + NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG); + +#define ARRAY_SIZE ARRAYSIZE +#define MSVCRT_free free +#define MSVCRT_malloc malloc +//#define MSVCRT_terminate terminate +#define MSVCRT__exit exit +#define MSVCRT_abort abort + +#endif /* __WINE_WINTERNL_H */