[PSEH] Use _setjmp3 with custom unwind function

This commit is contained in:
Timo Kreuzer
2025-07-05 16:27:56 +03:00
parent e8d190a29e
commit 011ce7088c
7 changed files with 61 additions and 6 deletions

View File

@@ -13,8 +13,8 @@ add_executable(ftp ${SOURCE} ftp.rc)
target_compile_definitions(ftp PRIVATE lint)
set_module_type(ftp win32cui)
target_link_libraries(ftp oldnames ${PSEH_LIB})
add_importlibs(ftp ws2_32 iphlpapi msvcrt kernel32)
target_link_libraries(ftp oldnames)
add_pch(ftp precomp.h SOURCE)
if(MSVC)

View File

@@ -31,7 +31,7 @@ list(APPEND SOURCE
add_library(libpng MODULE ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/libpng.def)
set_module_type(libpng win32dll)
target_link_libraries(libpng zlib)
target_link_libraries(libpng zlib ${PSEH_LIB})
add_importlibs(libpng msvcrt kernel32 ntdll)
add_pch(libpng pngpriv.h SOURCE)
add_cd_file(TARGET libpng DESTINATION reactos/system32 FOR all)

View File

@@ -116,7 +116,7 @@ add_library(glu32 MODULE
${PCH_SKIP_SOURCE}
glu32.rc
${CMAKE_CURRENT_BINARY_DIR}/glu32.def)
target_link_libraries(glu32 cpprt)
target_link_libraries(glu32 cpprt ${PSEH_LIB})
set_module_type(glu32 win32dll)

View File

@@ -23,9 +23,9 @@ function(add_hal _halname)
${CMAKE_CURRENT_BINARY_DIR}/hal.def)
if(${_halname} STREQUAL "hal")
target_link_libraries(${_halname} libcntpr arbiter fast486)
target_link_libraries(${_halname} libcntpr arbiter fast486 ${PSEH_LIB})
else()
target_link_libraries(${_halname} libcntpr fast486)
target_link_libraries(${_halname} libcntpr fast486 ${PSEH_LIB})
endif()
add_importlibs(${_halname} ntoskrnl)

View File

@@ -447,3 +447,49 @@ _SEH3$_CPP_except_handler(
{
return _SEH3$_common_except_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext, _SEH3$_CPP_HANDLER);
}
void
__stdcall
_SEH3$_longjmp_unwind(_JUMP_BUFFER* _Buf)
{
PSEH3$_REGISTRATION_FRAME RegisteredFrame = (PSEH3$_REGISTRATION_FRAME)_Buf->Registration;
PSEH3$_REGISTRATION_FRAME CurrentFrame;
/* Native SEH registers the EH frame at the start of the function, so a call to
_setjmp(3) will always save that EH frame. PSEH only registers the frame
when entering a try block, so a call to _setjmp outside of a try block
would save a previously installed EH frame, which can be of a different
type (e.g. native EH3/EH4). We need to check whether the frame is ours
by comparing its address to the saved ebp value, which marks the boundary
of the stack frame for the caller of _setjmp. */
if (_Buf->Registration > _Buf->Ebp)
{
/* The registration frame is not ours, we don't need to do anything */
return;
}
/* Loop all frames for this registration */
for (CurrentFrame = RegisteredFrame->EndOfChain;
CurrentFrame->TryLevel != _Buf->TryLevel;
CurrentFrame = CurrentFrame->Next)
{
/* Check if this is a termination handler */
if (CurrentFrame->ScopeTable->Target == NULL)
{
/* Call the termination handler */
if (RegisteredFrame->Handler == _SEH3$_C_except_handler)
{
#ifdef __clang__
_SEH3$_CallFinally(CurrentFrame, _SEH3$_CLANG_HANDLER);
#else
_SEH3$_CallFinally(CurrentFrame, _SEH3$_NESTED_HANDLER);
#endif
}
else
{
ASSERT(CurrentFrame->Handler == _SEH3$_CPP_except_handler);
_SEH3$_CallFinally(CurrentFrame, _SEH3$_CPP_HANDLER);
}
}
}
}

View File

@@ -11,6 +11,7 @@
#define _PSEH3_H_
#include <excpt.h>
#include <intrin.h>
#ifdef __cplusplus
extern "C" {
@@ -495,6 +496,14 @@ _Pragma("GCC diagnostic pop") \
#define _SEH3_VOLATILE volatile
int _setjmp3(jmp_buf env, int count, ...);
void __stdcall _SEH3$_longjmp_unwind(_JUMP_BUFFER* _Buf);
#undef setjmp
#define setjmp(env) \
_setjmp3(env, 2, (const void*)_SEH3$_longjmp_unwind, _SEH3$_TryLevel)
#define _INC_SETJMPEX
#ifdef __cplusplus
}; // extern "C"

View File

@@ -18,7 +18,7 @@ add_library(ftfd MODULE
${CMAKE_CURRENT_BINARY_DIR}/ftfd.def)
set_module_type(ftfd kerneldll ENTRYPOINT FtfdEnableDriver 12)
target_link_libraries(ftfd freetype libcntpr)
target_link_libraries(ftfd freetype libcntpr ${PSEH_LIB})
add_pch(ftfd ftfd.h "${PCH_SKIP_SOURCE}")
add_importlibs(ftfd win32k)
add_dependencies(ftfd psdk)