mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-18 19:23:56 +00:00
Cleanup exception handling and prepare UI support
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user