mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 03:33:56 +00:00
Prepare timer support
This commit is contained in:
@@ -52,3 +52,22 @@ inline memory_permission& operator^=(memory_permission& x, const memory_permissi
|
||||
x = x ^ y;
|
||||
return x;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
inline bool is_executable(const memory_permission permission)
|
||||
{
|
||||
return (permission & memory_permission::exec) != memory_permission::none;
|
||||
}
|
||||
|
||||
inline bool is_readable(const memory_permission permission)
|
||||
{
|
||||
return (permission & memory_permission::read) != memory_permission::none;
|
||||
}
|
||||
|
||||
inline bool is_writable(const memory_permission permission)
|
||||
{
|
||||
return (permission & memory_permission::write) != memory_permission::none;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ struct handle_types
|
||||
mutant,
|
||||
token,
|
||||
window,
|
||||
timer,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -272,6 +272,7 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
buffer.write(this->ports);
|
||||
buffer.write(this->mutants);
|
||||
buffer.write(this->windows);
|
||||
buffer.write(this->timers);
|
||||
buffer.write(this->registry_keys);
|
||||
buffer.write_map(this->atoms);
|
||||
|
||||
@@ -311,6 +312,7 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
|
||||
buffer.read(this->ports);
|
||||
buffer.read(this->mutants);
|
||||
buffer.read(this->windows);
|
||||
buffer.read(this->timers);
|
||||
buffer.read(this->registry_keys);
|
||||
buffer.read_map(this->atoms);
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ struct process_context
|
||||
handle_store<handle_types::port, port> ports{};
|
||||
handle_store<handle_types::mutant, mutant> mutants{};
|
||||
handle_store<handle_types::window, window> windows{};
|
||||
handle_store<handle_types::timer, timer> timers{};
|
||||
handle_store<handle_types::registry, registry_key, 2> registry_keys{};
|
||||
std::map<uint16_t, atom_entry> atoms{};
|
||||
|
||||
|
||||
@@ -358,14 +358,16 @@ namespace syscalls
|
||||
emulator_object<ULONG> minimum_time, emulator_object<ULONG> current_time);
|
||||
NTSTATUS handle_NtSetTimerResolution(const syscall_context&, ULONG /*desired_resolution*/, BOOLEAN set_resolution,
|
||||
emulator_object<ULONG> current_resolution);
|
||||
NTSTATUS handle_NtCreateTimer2(const syscall_context& c, emulator_object<handle> timer_handle, uint64_t reserved,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG attributes, ACCESS_MASK desired_access);
|
||||
|
||||
// syscalls/token.cpp:
|
||||
NTSTATUS handle_NtDuplicateToken(const syscall_context&, handle existing_token_handle,
|
||||
ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>>
|
||||
/*object_attributes*/,
|
||||
BOOLEAN /*effective_only*/, TOKEN_TYPE type,
|
||||
emulator_object<handle> new_token_handle);
|
||||
NTSTATUS
|
||||
handle_NtDuplicateToken(const syscall_context&, handle existing_token_handle, ACCESS_MASK /*desired_access*/,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>>
|
||||
/*object_attributes*/,
|
||||
BOOLEAN /*effective_only*/, TOKEN_TYPE type, emulator_object<handle> new_token_handle);
|
||||
NTSTATUS handle_NtQueryInformationToken(const syscall_context& c, handle token_handle,
|
||||
TOKEN_INFORMATION_CLASS token_information_class, uint64_t token_information,
|
||||
ULONG token_information_length, emulator_object<ULONG> return_length);
|
||||
@@ -758,11 +760,6 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateTimer2()
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserMapVirtualKeyEx()
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace syscalls
|
||||
if (attributes.ObjectName)
|
||||
{
|
||||
name = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
c.win_emu.log.print(color::dark_gray, "--> Event name: %s\n", u16_to_u8(name).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,14 +210,16 @@ namespace syscalls
|
||||
if (commit && !reserve &&
|
||||
c.win_emu.memory.commit_memory(potential_base, static_cast<size_t>(allocation_bytes), protection))
|
||||
{
|
||||
c.win_emu.log.print(color::dark_gray, "--> Committed 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
|
||||
potential_base + allocation_bytes);
|
||||
c.win_emu.log.print(is_executable(protection) ? color::gray : color::dark_gray,
|
||||
"--> Committed 0x%" PRIx64 " - 0x%" PRIx64 " (%s)\n", potential_base,
|
||||
potential_base + allocation_bytes, get_permission_string(protection).c_str());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
c.win_emu.log.print(color::dark_gray, "--> Allocated 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
|
||||
potential_base + allocation_bytes);
|
||||
c.win_emu.log.print(is_executable(protection) ? color::gray : color::dark_gray,
|
||||
"--> Allocated 0x%" PRIx64 " - 0x%" PRIx64 " (%s)\n", potential_base,
|
||||
potential_base + allocation_bytes, get_permission_string(protection).c_str());
|
||||
|
||||
return c.win_emu.memory.allocate_memory(potential_base, static_cast<size_t>(allocation_bytes), protection,
|
||||
!commit)
|
||||
|
||||
@@ -77,8 +77,7 @@ namespace syscalls
|
||||
const auto attributes = object_attributes.read();
|
||||
if (attributes.ObjectName)
|
||||
{
|
||||
name = read_unicode_string(
|
||||
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{c.emu, attributes.ObjectName});
|
||||
name = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
c.win_emu.log.print(color::dark_gray, "--> Mutant name: %s\n", u16_to_u8(name).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,43 @@ namespace syscalls
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateTimer2(const syscall_context& c, const emulator_object<handle> timer_handle,
|
||||
uint64_t /*reserved*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
ULONG /*attributes*/, ACCESS_MASK /*desired_access*/)
|
||||
{
|
||||
std::u16string name{};
|
||||
if (object_attributes)
|
||||
{
|
||||
const auto attributes = object_attributes.read();
|
||||
if (attributes.ObjectName)
|
||||
{
|
||||
name = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
c.win_emu.log.print(color::dark_gray, "--> Timer name: %s\n", u16_to_u8(name).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
for (auto& entry : c.proc.timers)
|
||||
{
|
||||
if (entry.second.name == name)
|
||||
{
|
||||
++entry.second.ref_count;
|
||||
timer_handle.write(c.proc.timers.make_handle(entry.first));
|
||||
return STATUS_OBJECT_NAME_EXISTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timer t{};
|
||||
t.name = std::move(name);
|
||||
|
||||
const auto h = c.proc.timers.store(std::move(t));
|
||||
timer_handle.write(h);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -346,8 +346,10 @@ void windows_emulator::yield_thread(const bool alertable)
|
||||
this->emu().stop();
|
||||
}
|
||||
|
||||
void windows_emulator::perform_thread_switch()
|
||||
bool windows_emulator::perform_thread_switch()
|
||||
{
|
||||
const auto needed_switch = std::exchange(this->switch_thread_, false);
|
||||
|
||||
this->switch_thread_ = false;
|
||||
while (!switch_to_next_thread(*this))
|
||||
{
|
||||
@@ -359,7 +361,15 @@ void windows_emulator::perform_thread_switch()
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
if (this->should_stop)
|
||||
{
|
||||
this->switch_thread_ = needed_switch;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool windows_emulator::activate_thread(const uint32_t id)
|
||||
@@ -597,7 +607,10 @@ void windows_emulator::start(size_t count)
|
||||
{
|
||||
if (this->switch_thread_ || !this->current_thread().is_thread_ready(this->process, this->clock()))
|
||||
{
|
||||
this->perform_thread_switch();
|
||||
if (!this->perform_thread_switch())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->emu().start(count);
|
||||
|
||||
@@ -182,7 +182,7 @@ class windows_emulator
|
||||
bool fuzzing{false};
|
||||
|
||||
void yield_thread(bool alertable = false);
|
||||
void perform_thread_switch();
|
||||
bool perform_thread_switch();
|
||||
bool activate_thread(uint32_t id);
|
||||
|
||||
private:
|
||||
|
||||
@@ -6,6 +6,21 @@
|
||||
#include <utils/file_handle.hpp>
|
||||
#include <platform/synchronisation.hpp>
|
||||
|
||||
struct timer : ref_counted_object
|
||||
{
|
||||
std::u16string name{};
|
||||
|
||||
void serialize_object(utils::buffer_serializer& buffer) const override
|
||||
{
|
||||
buffer.write(this->name);
|
||||
}
|
||||
|
||||
void deserialize_object(utils::buffer_deserializer& buffer) override
|
||||
{
|
||||
buffer.read(this->name);
|
||||
}
|
||||
};
|
||||
|
||||
struct event : ref_counted_object
|
||||
{
|
||||
bool signaled{};
|
||||
|
||||
Reference in New Issue
Block a user