mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-21 20:53:56 +00:00
188 lines
4.6 KiB
C++
188 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
#include <arch_emulator.hpp>
|
|
#include <serialization.hpp>
|
|
|
|
#include "emulator_utils.hpp"
|
|
#include "handles.hpp"
|
|
|
|
class windows_emulator;
|
|
struct process_context;
|
|
|
|
struct lpc_message_context
|
|
{
|
|
emulator_object<PORT_MESSAGE64> send_message;
|
|
emulator_object<PORT_MESSAGE64> receive_message;
|
|
|
|
lpc_message_context(x86_64_emulator& emu)
|
|
: send_message(emu),
|
|
receive_message(emu)
|
|
{
|
|
}
|
|
|
|
lpc_message_context(utils::buffer_deserializer& buffer)
|
|
: lpc_message_context(buffer.read<x64_emulator_wrapper>().get())
|
|
{
|
|
}
|
|
|
|
void serialize(utils::buffer_serializer& buffer) const
|
|
{
|
|
buffer.write(send_message);
|
|
buffer.write(receive_message);
|
|
}
|
|
|
|
void deserialize(utils::buffer_deserializer& buffer)
|
|
{
|
|
buffer.read(send_message);
|
|
buffer.read(receive_message);
|
|
}
|
|
};
|
|
|
|
struct lpc_request_context
|
|
{
|
|
emulator_pointer send_buffer{};
|
|
ULONG send_buffer_length{};
|
|
emulator_pointer recv_buffer{};
|
|
mutable ULONG recv_buffer_length{};
|
|
|
|
void serialize(utils::buffer_serializer& buffer) const
|
|
{
|
|
buffer.write(send_buffer);
|
|
buffer.write(send_buffer_length);
|
|
buffer.write(recv_buffer);
|
|
buffer.write(recv_buffer_length);
|
|
}
|
|
|
|
void deserialize(utils::buffer_deserializer& buffer)
|
|
{
|
|
buffer.read(send_buffer);
|
|
buffer.read(send_buffer_length);
|
|
buffer.read(recv_buffer);
|
|
buffer.read(recv_buffer_length);
|
|
}
|
|
};
|
|
|
|
struct port_creation_data
|
|
{
|
|
uint64_t view_base;
|
|
int64_t view_size;
|
|
};
|
|
|
|
struct port : ref_counted_object
|
|
{
|
|
uint64_t view_base{};
|
|
int64_t view_size{};
|
|
|
|
port() = default;
|
|
~port() override = default;
|
|
|
|
port(port&&) = default;
|
|
port& operator=(port&&) = default;
|
|
|
|
port(const port&) = delete;
|
|
port& operator=(const port&) = delete;
|
|
|
|
void serialize_object(utils::buffer_serializer& buffer) const override
|
|
{
|
|
buffer.write(this->view_base);
|
|
buffer.write(this->view_size);
|
|
}
|
|
|
|
void deserialize_object(utils::buffer_deserializer& buffer) override
|
|
{
|
|
buffer.read(this->view_base);
|
|
buffer.read(this->view_size);
|
|
}
|
|
|
|
virtual void create(windows_emulator& win_emu, const port_creation_data& data)
|
|
{
|
|
(void)win_emu;
|
|
view_base = data.view_base;
|
|
view_size = data.view_size;
|
|
}
|
|
|
|
NTSTATUS handle_message(windows_emulator& win_emu, const lpc_message_context& c);
|
|
|
|
virtual NTSTATUS handle_request(windows_emulator& win_emu, const lpc_request_context& c) = 0;
|
|
};
|
|
|
|
struct rpc_port : port
|
|
{
|
|
NTSTATUS handle_request(windows_emulator& win_emu, const lpc_request_context& c) override;
|
|
|
|
virtual NTSTATUS handle_rpc(windows_emulator& win_emu, uint32_t procedure_id, const lpc_request_context& c) = 0;
|
|
|
|
private:
|
|
static NTSTATUS handle_handshake(windows_emulator& win_emu, const lpc_request_context& c);
|
|
NTSTATUS handle_rpc_call(windows_emulator& win_emu, const lpc_request_context& c);
|
|
};
|
|
|
|
std::unique_ptr<port> create_port(std::u16string_view port);
|
|
|
|
class port_container : public port
|
|
{
|
|
public:
|
|
port_container() = default;
|
|
|
|
port_container(std::u16string port, windows_emulator& win_emu, const port_creation_data& data)
|
|
: port_name_(std::move(port))
|
|
{
|
|
this->setup();
|
|
this->port_->create(win_emu, data);
|
|
}
|
|
|
|
NTSTATUS handle_request(windows_emulator& win_emu, const lpc_request_context& c) override
|
|
{
|
|
this->assert_validity();
|
|
return this->port_->handle_request(win_emu, c);
|
|
}
|
|
|
|
void serialize_object(utils::buffer_serializer& buffer) const override
|
|
{
|
|
this->assert_validity();
|
|
|
|
buffer.write_string(this->port_name_);
|
|
this->port_->serialize(buffer);
|
|
}
|
|
|
|
void deserialize_object(utils::buffer_deserializer& buffer) override
|
|
{
|
|
buffer.read_string(this->port_name_);
|
|
this->setup();
|
|
this->port_->deserialize(buffer);
|
|
}
|
|
|
|
template <typename T = port>
|
|
requires(std::is_base_of_v<port, T> || std::is_same_v<port, T>)
|
|
T* get_internal_port() const
|
|
{
|
|
this->assert_validity();
|
|
auto* value = this->port_.get();
|
|
return dynamic_cast<T*>(value);
|
|
}
|
|
|
|
std::u16string_view get_port_name() const
|
|
{
|
|
this->assert_validity();
|
|
return this->port_name_;
|
|
}
|
|
|
|
private:
|
|
std::u16string port_name_{};
|
|
std::unique_ptr<port> port_{};
|
|
|
|
void setup()
|
|
{
|
|
this->port_ = create_port(this->port_name_);
|
|
}
|
|
|
|
void assert_validity() const
|
|
{
|
|
if (!this->port_)
|
|
{
|
|
throw std::runtime_error("Port not created!");
|
|
}
|
|
}
|
|
};
|