Cleanup exception handling and prepare UI support

This commit is contained in:
momo5502
2025-01-11 09:51:22 +01:00
parent ff6fd79dd5
commit b2b2ffd6be
3 changed files with 67 additions and 33 deletions

View File

@@ -5,15 +5,16 @@
using NTSTATUS = std::uint32_t;
#ifndef OS_WINDOWS
#define STATUS_WAIT_0 ((NTSTATUS)0x00000000L)
#define STATUS_TIMEOUT ((NTSTATUS)0x00000102L)
#define STATUS_WAIT_0 ((NTSTATUS)0x00000000L)
#define STATUS_TIMEOUT ((NTSTATUS)0x00000102L)
#define STATUS_ACCESS_VIOLATION ((NTSTATUS)0xC0000005L)
#define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
#define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS)0xC000001DL)
#define STATUS_ACCESS_VIOLATION ((NTSTATUS)0xC0000005L)
#define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
#define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS)0xC000001DL)
#define STATUS_INTEGER_DIVIDE_BY_ZERO ((NTSTATUS)0xC0000094L)
#define STATUS_PENDING ((NTSTATUS)0x00000103L)
#define STATUS_PENDING ((NTSTATUS)0x00000103L)
#endif
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)

View File

@@ -3198,6 +3198,21 @@ namespace
return FALSE;
}
NTSTATUS handle_NtUserGetDpiForCurrentProcess()
{
return 96;
}
NTSTATUS handle_NtUserGetDCEx()
{
return 1;
}
NTSTATUS handle_NtUserModifyUserStartupInfoFlags()
{
return STATUS_SUCCESS;
}
bool is_awaitable_object_type(const handle h)
{
return h.value.type == handle_types::thread //
@@ -3510,6 +3525,9 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtUserSystemParametersInfo);
add_handler(NtGetContextThread);
add_handler(NtYieldExecution);
add_handler(NtUserModifyUserStartupInfoFlags);
add_handler(NtUserGetDCEx);
add_handler(NtUserGetDpiForCurrentProcess);
#undef add_handler
}

View File

@@ -407,8 +407,10 @@ namespace
});
}
void dispatch_access_violation(x64_emulator& emu, const uint64_t dispatcher, const uint64_t address,
const memory_operation operation)
template <typename T>
requires(std::is_integral_v<T>)
void dispatch_exception(x64_emulator& emu, const process_context& proc, const T status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters)
{
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
@@ -416,40 +418,47 @@ namespace
EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>> record{};
memset(&record, 0, sizeof(record));
record.ExceptionCode = static_cast<DWORD>(STATUS_ACCESS_VIOLATION);
record.ExceptionCode = static_cast<DWORD>(status);
record.ExceptionFlags = 0;
record.ExceptionRecord = 0;
record.ExceptionAddress = static_cast<EmulatorTraits<Emu64>::PVOID>(emu.read_instruction_pointer());
record.NumberParameters = 2;
record.ExceptionInformation[0] = map_violation_operation_to_parameter(operation);
record.ExceptionInformation[1] = address;
record.ExceptionAddress = emu.read_instruction_pointer();
record.NumberParameters = static_cast<DWORD>(parameters.size());
if (parameters.size() > 15)
{
throw std::runtime_error("Too many exception parameters");
}
for (size_t i = 0; i < parameters.size(); ++i)
{
record.ExceptionInformation[i] = parameters[i];
}
EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers{};
pointers.ContextRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&ctx);
pointers.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&record);
dispatch_exception_pointers(emu, dispatcher, pointers);
dispatch_exception_pointers(emu, proc.ki_user_exception_dispatcher, pointers);
}
void dispatch_illegal_instruction_violation(x64_emulator& emu, const uint64_t dispatcher)
void dispatch_access_violation(x64_emulator& emu, const process_context& proc, const uint64_t address,
const memory_operation operation)
{
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
context_frame::save(emu, ctx);
dispatch_exception(emu, proc, STATUS_ACCESS_VIOLATION,
{
map_violation_operation_to_parameter(operation),
address,
});
}
EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>> record{};
memset(&record, 0, sizeof(record));
record.ExceptionCode = static_cast<DWORD>(STATUS_ILLEGAL_INSTRUCTION);
record.ExceptionFlags = 0;
record.ExceptionRecord = 0;
record.ExceptionAddress = static_cast<EmulatorTraits<Emu64>::PVOID>(emu.read_instruction_pointer());
record.NumberParameters = 0;
void dispatch_illegal_instruction_violation(x64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_ILLEGAL_INSTRUCTION, {});
}
EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers{};
pointers.ContextRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&ctx);
pointers.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&record);
dispatch_exception_pointers(emu, dispatcher, pointers);
void dispatch_integer_division_by_zero(x64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_INTEGER_DIVIDE_BY_ZERO, {});
}
void perform_context_switch_work(windows_emulator& win_emu)
@@ -891,9 +900,15 @@ void windows_emulator::setup_hooks()
});
this->emu().hook_interrupt([&](const int interrupt) {
if (interrupt == 0)
{
dispatch_integer_division_by_zero(this->emu(), this->process());
return;
}
if (interrupt == 6)
{
dispatch_illegal_instruction_violation(this->emu(), this->process().ki_user_exception_dispatcher);
dispatch_illegal_instruction_violation(this->emu(), this->process());
return;
}
@@ -931,7 +946,7 @@ void windows_emulator::setup_hooks()
return memory_violation_continuation::stop;
}
dispatch_access_violation(this->emu(), this->process().ki_user_exception_dispatcher, address, operation);
dispatch_access_violation(this->emu(), this->process(), address, operation);
return memory_violation_continuation::resume;
});