mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-21 12:43:57 +00:00
UI progress (#293)
This commit is contained in:
@@ -24,6 +24,7 @@ typedef struct _LARGE_STRING
|
||||
pointer Buffer;
|
||||
} LARGE_STRING;
|
||||
|
||||
using hdc = pointer;
|
||||
using hwnd = pointer;
|
||||
using hmenu = pointer;
|
||||
using hinstance = pointer;
|
||||
|
||||
@@ -161,6 +161,11 @@ class emulator_object
|
||||
return emulator_object<T>(*this->memory_, this->address_ + offset);
|
||||
}
|
||||
|
||||
memory_interface* get_memory_interface() const
|
||||
{
|
||||
return this->memory_;
|
||||
}
|
||||
|
||||
private:
|
||||
memory_interface* memory_{};
|
||||
uint64_t address_{};
|
||||
@@ -310,16 +315,22 @@ class emulator_allocator
|
||||
};
|
||||
|
||||
template <typename Element>
|
||||
std::basic_string<Element> read_string(memory_manager& mem, const uint64_t address)
|
||||
std::basic_string<Element> read_string(memory_interface& mem, const uint64_t address,
|
||||
const std::optional<size_t> size = {})
|
||||
{
|
||||
std::basic_string<Element> result{};
|
||||
|
||||
for (size_t i = 0;; ++i)
|
||||
{
|
||||
if (size && i >= *size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Element element{};
|
||||
mem.read_memory(address + (i * sizeof(element)), &element, sizeof(element));
|
||||
|
||||
if (!element)
|
||||
if (!size && !element)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ struct handle_types
|
||||
registry,
|
||||
mutant,
|
||||
token,
|
||||
window,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -238,7 +239,7 @@ class handle_store : public generic_handle_store
|
||||
return h;
|
||||
}
|
||||
|
||||
bool erase(const typename value_map::iterator& entry)
|
||||
std::pair<typename value_map::iterator, bool> erase(const typename value_map::iterator& entry)
|
||||
{
|
||||
if (this->block_mutation_)
|
||||
{
|
||||
@@ -247,25 +248,25 @@ class handle_store : public generic_handle_store
|
||||
|
||||
if (entry == this->store_.end())
|
||||
{
|
||||
return false;
|
||||
return {entry, false};
|
||||
}
|
||||
|
||||
if constexpr (handle_detail::has_deleter_function<T>())
|
||||
{
|
||||
if (!T::deleter(entry->second))
|
||||
{
|
||||
return true;
|
||||
return {entry, true};
|
||||
}
|
||||
}
|
||||
|
||||
this->store_.erase(entry);
|
||||
return true;
|
||||
auto new_iter = this->store_.erase(entry);
|
||||
return {new_iter, true};
|
||||
}
|
||||
|
||||
bool erase(const handle_value h)
|
||||
{
|
||||
const auto entry = this->get_iterator(h);
|
||||
return this->erase(entry);
|
||||
return this->erase(entry).second;
|
||||
}
|
||||
|
||||
bool erase(const handle h) override
|
||||
|
||||
@@ -271,6 +271,7 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
|
||||
buffer.write(this->semaphores);
|
||||
buffer.write(this->ports);
|
||||
buffer.write(this->mutants);
|
||||
buffer.write(this->windows);
|
||||
buffer.write(this->registry_keys);
|
||||
buffer.write_map(this->atoms);
|
||||
|
||||
@@ -309,6 +310,7 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
|
||||
buffer.read(this->semaphores);
|
||||
buffer.read(this->ports);
|
||||
buffer.read(this->mutants);
|
||||
buffer.read(this->windows);
|
||||
buffer.read(this->registry_keys);
|
||||
buffer.read_map(this->atoms);
|
||||
|
||||
@@ -361,6 +363,20 @@ handle process_context::create_thread(memory_manager& memory, const uint64_t sta
|
||||
return h;
|
||||
}
|
||||
|
||||
std::optional<uint16_t> process_context::find_atom(const std::u16string_view name)
|
||||
{
|
||||
for (auto& entry : this->atoms)
|
||||
{
|
||||
if (entry.second.name == name)
|
||||
{
|
||||
++entry.second.ref_count;
|
||||
return entry.first;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
uint16_t process_context::add_or_find_atom(std::u16string name)
|
||||
{
|
||||
uint16_t index = 1;
|
||||
|
||||
@@ -42,7 +42,7 @@ struct process_context
|
||||
std::u16string name;
|
||||
uint32_t ref_count = 0;
|
||||
|
||||
atom_entry(std::u16string n, uint32_t count)
|
||||
atom_entry(std::u16string n, const uint32_t count)
|
||||
: name(std::move(n)),
|
||||
ref_count(count)
|
||||
{
|
||||
@@ -67,6 +67,7 @@ struct process_context
|
||||
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size,
|
||||
bool suspended);
|
||||
|
||||
std::optional<uint16_t> find_atom(std::u16string_view name);
|
||||
uint16_t add_or_find_atom(std::u16string name);
|
||||
bool delete_atom(const std::u16string& name);
|
||||
bool delete_atom(uint16_t atom_id);
|
||||
@@ -109,6 +110,7 @@ struct process_context
|
||||
handle_store<handle_types::semaphore, semaphore> semaphores{};
|
||||
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::registry, registry_key, 2> registry_keys{};
|
||||
std::map<uint16_t, atom_entry> atoms{};
|
||||
|
||||
|
||||
@@ -574,6 +574,24 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtFindAtom(const syscall_context& c, const uint64_t atom_name, const ULONG length,
|
||||
const emulator_object<uint16_t> atom)
|
||||
{
|
||||
const auto name = read_string<char16_t>(c.emu, atom_name, length / 2);
|
||||
const auto index = c.proc.find_atom(name);
|
||||
if (!index)
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (atom)
|
||||
{
|
||||
atom.write(*index);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserGetAtomName(const syscall_context& c, const RTL_ATOM atom,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> atom_name)
|
||||
{
|
||||
@@ -611,14 +629,15 @@ namespace syscalls
|
||||
return 96;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserGetDCEx()
|
||||
hdc handle_NtUserGetDCEx(const syscall_context& /*c*/, const hwnd window, const uint64_t /*clip_region*/,
|
||||
const ULONG /*flags*/)
|
||||
{
|
||||
return 1;
|
||||
return window;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserGetDC()
|
||||
hdc handle_NtUserGetDC(const syscall_context& c, const hwnd window)
|
||||
{
|
||||
return handle_NtUserGetDCEx();
|
||||
return handle_NtUserGetDCEx(c, window, 0, 0);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserGetWindowDC()
|
||||
@@ -733,32 +752,76 @@ namespace syscalls
|
||||
return 0;
|
||||
}
|
||||
|
||||
hwnd handle_NtUserCreateWindowEx(const syscall_context& c, const DWORD ex_style,
|
||||
const emulator_object<LARGE_STRING> class_name,
|
||||
const emulator_object<LARGE_STRING> cls_version,
|
||||
const emulator_object<LARGE_STRING> window_name, const DWORD style, const int x,
|
||||
const int y, const int width, const int height, const hwnd parent,
|
||||
const hmenu menu, const hinstance instance, const pointer l_param,
|
||||
const DWORD flags, const pointer acbi_buffer)
|
||||
std::u16string read_large_string(const emulator_object<LARGE_STRING> str_obj)
|
||||
{
|
||||
(void)c;
|
||||
(void)ex_style;
|
||||
(void)class_name;
|
||||
(void)cls_version;
|
||||
(void)window_name;
|
||||
(void)style;
|
||||
(void)x;
|
||||
(void)y;
|
||||
(void)width;
|
||||
(void)height;
|
||||
(void)parent;
|
||||
(void)menu;
|
||||
(void)instance;
|
||||
(void)l_param;
|
||||
(void)flags;
|
||||
(void)acbi_buffer;
|
||||
if (!str_obj)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return 1;
|
||||
const auto str = str_obj.read();
|
||||
if (!str.bAnsi)
|
||||
{
|
||||
return read_string<char16_t>(*str_obj.get_memory_interface(), str.Buffer, str.Length / 2);
|
||||
}
|
||||
|
||||
const auto ansi_string = read_string<char>(*str_obj.get_memory_interface(), str.Buffer, str.Length);
|
||||
return u8_to_u16(ansi_string);
|
||||
}
|
||||
|
||||
hwnd handle_NtUserCreateWindowEx(const syscall_context& c, const DWORD /*ex_style*/,
|
||||
const emulator_object<LARGE_STRING> class_name,
|
||||
const emulator_object<LARGE_STRING> /*cls_version*/,
|
||||
const emulator_object<LARGE_STRING> window_name, const DWORD /*style*/,
|
||||
const int x, const int y, const int width, const int height, const hwnd /*parent*/,
|
||||
const hmenu /*menu*/, const hinstance /*instance*/, const pointer /*l_param*/,
|
||||
const DWORD /*flags*/, const pointer /*acbi_buffer*/)
|
||||
{
|
||||
window win{};
|
||||
win.x = x;
|
||||
win.y = y;
|
||||
win.width = width;
|
||||
win.height = height;
|
||||
win.thread_id = c.win_emu.current_thread().id;
|
||||
win.class_name = read_large_string(class_name);
|
||||
win.name = read_large_string(window_name);
|
||||
|
||||
return c.proc.windows.store(std::move(win)).bits;
|
||||
}
|
||||
|
||||
BOOL handle_NtUserDestroyWindow(const syscall_context& c, const hwnd window)
|
||||
{
|
||||
return c.proc.windows.erase(window);
|
||||
}
|
||||
|
||||
BOOL handle_NtUserSetProp(const syscall_context& c, const hwnd window, const uint16_t atom, const uint64_t data)
|
||||
{
|
||||
auto* win = c.proc.windows.get(window);
|
||||
const auto* prop = c.proc.get_atom_name(atom);
|
||||
|
||||
if (!win || !prop)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
win->props[*prop] = data;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL handle_NtUserSetProp2(const syscall_context& c, const hwnd window,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> str, const uint64_t data)
|
||||
{
|
||||
auto* win = c.proc.windows.get(window);
|
||||
if (!win || !str)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
auto prop = read_unicode_string(c.emu, str);
|
||||
win->props[std::move(prop)] = data;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ULONG handle_NtUserGetRawInputDeviceList()
|
||||
@@ -771,6 +834,11 @@ namespace syscalls
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t handle_NtUserChangeWindowMessageFilterEx()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL handle_NtUserShowWindow(const syscall_context& c, const hwnd hwnd, const LONG cmd_show)
|
||||
{
|
||||
(void)c;
|
||||
@@ -898,6 +966,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtDxgkIsFeatureEnabled);
|
||||
add_handler(NtAddAtomEx);
|
||||
add_handler(NtAddAtom);
|
||||
add_handler(NtFindAtom);
|
||||
add_handler(NtDeleteAtom);
|
||||
add_handler(NtUserGetAtomName);
|
||||
add_handler(NtInitializeNlsFiles);
|
||||
@@ -1003,6 +1072,10 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtUserGetRawInputDeviceList);
|
||||
add_handler(NtUserGetKeyboardType);
|
||||
add_handler(NtUserEnumDisplayDevices);
|
||||
add_handler(NtUserSetProp);
|
||||
add_handler(NtUserSetProp2);
|
||||
add_handler(NtUserChangeWindowMessageFilterEx);
|
||||
add_handler(NtUserDestroyWindow);
|
||||
|
||||
#undef add_handler
|
||||
}
|
||||
|
||||
@@ -279,6 +279,19 @@ namespace syscalls
|
||||
|
||||
thread->exit_status = exit_status;
|
||||
c.win_emu.callbacks.on_thread_terminated(thread_handle, *thread);
|
||||
|
||||
for (auto i = c.proc.windows.begin(); i != c.proc.windows.end();)
|
||||
{
|
||||
if (i->second.thread_id != thread->id)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
i->second.ref_count = 1;
|
||||
i = c.proc.windows.erase(i).first;
|
||||
}
|
||||
|
||||
if (thread == c.proc.active_thread)
|
||||
{
|
||||
c.win_emu.yield_thread();
|
||||
|
||||
@@ -39,6 +39,42 @@ struct event : ref_counted_object
|
||||
}
|
||||
};
|
||||
|
||||
struct window : ref_counted_object
|
||||
{
|
||||
uint32_t thread_id{};
|
||||
std::u16string name{};
|
||||
std::u16string class_name{};
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
std::unordered_map<std::u16string, uint64_t> props;
|
||||
|
||||
void serialize_object(utils::buffer_serializer& buffer) const override
|
||||
{
|
||||
buffer.write(this->thread_id);
|
||||
buffer.write(this->name);
|
||||
buffer.write(this->class_name);
|
||||
buffer.write(this->width);
|
||||
buffer.write(this->height);
|
||||
buffer.write(this->x);
|
||||
buffer.write(this->y);
|
||||
buffer.write_map(this->props);
|
||||
}
|
||||
|
||||
void deserialize_object(utils::buffer_deserializer& buffer) override
|
||||
{
|
||||
buffer.read(this->thread_id);
|
||||
buffer.read(this->name);
|
||||
buffer.read(this->class_name);
|
||||
buffer.read(this->width);
|
||||
buffer.read(this->height);
|
||||
buffer.read(this->x);
|
||||
buffer.read(this->y);
|
||||
buffer.read_map(this->props);
|
||||
}
|
||||
};
|
||||
|
||||
struct mutant : ref_counted_object
|
||||
{
|
||||
uint32_t locked_count{0};
|
||||
|
||||
Reference in New Issue
Block a user