mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 19:53:56 +00:00
Prepare support for more socket types
This commit is contained in:
@@ -29,14 +29,7 @@ namespace network
|
||||
|
||||
socket::~socket()
|
||||
{
|
||||
if (this->socket_ != INVALID_SOCKET)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
closesocket(this->socket_);
|
||||
#else
|
||||
close(this->socket_);
|
||||
#endif
|
||||
}
|
||||
this->release();
|
||||
}
|
||||
|
||||
socket::socket(socket&& obj) noexcept
|
||||
@@ -48,7 +41,7 @@ namespace network
|
||||
{
|
||||
if (this != &obj)
|
||||
{
|
||||
this->~socket();
|
||||
this->release();
|
||||
this->socket_ = obj.socket_;
|
||||
this->port_ = obj.port_;
|
||||
this->address_family_ = obj.address_family_;
|
||||
@@ -60,6 +53,15 @@ namespace network
|
||||
return *this;
|
||||
}
|
||||
|
||||
void socket::release()
|
||||
{
|
||||
if (this->socket_ != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(this->socket_);
|
||||
this->socket_ = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
bool socket::bind_port(const address& target)
|
||||
{
|
||||
const auto result = bind(this->socket_, &target.get_addr(), target.get_size()) == 0;
|
||||
@@ -182,7 +184,7 @@ namespace network
|
||||
}
|
||||
|
||||
const auto retval = poll(pfds.data(), static_cast<uint32_t>(pfds.size()),
|
||||
static_cast<int>(timeout.count()));
|
||||
static_cast<int>(timeout.count()));
|
||||
|
||||
if (retval == SOCKET_ERROR)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ using socklen_t = int;
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#define SOCKET_ERROR (-1)
|
||||
#define GET_SOCKET_ERROR() (errno)
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
namespace network
|
||||
@@ -56,5 +57,7 @@ namespace network
|
||||
int address_family_{AF_UNSPEC};
|
||||
uint16_t port_ = 0;
|
||||
SOCKET socket_ = INVALID_SOCKET;
|
||||
|
||||
void release();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,87 +1,125 @@
|
||||
#include "afd_endpoint.hpp"
|
||||
#include "afd_types.hpp"
|
||||
|
||||
#include "../windows_emulator.hpp"
|
||||
|
||||
#include <network/address.hpp>
|
||||
#include <network/socket.hpp>
|
||||
|
||||
|
||||
typedef LONG TDI_STATUS;
|
||||
typedef PVOID CONNECTION_CONTEXT;
|
||||
|
||||
typedef struct _TDI_CONNECTION_INFORMATION
|
||||
{
|
||||
LONG UserDataLength;
|
||||
PVOID UserData;
|
||||
LONG OptionsLength;
|
||||
PVOID Options;
|
||||
LONG RemoteAddressLength;
|
||||
PVOID RemoteAddress;
|
||||
} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION;
|
||||
|
||||
typedef struct _TDI_REQUEST
|
||||
{
|
||||
union
|
||||
{
|
||||
HANDLE AddressHandle;
|
||||
CONNECTION_CONTEXT ConnectionContext;
|
||||
HANDLE ControlChannel;
|
||||
} Handle;
|
||||
|
||||
PVOID RequestNotifyObject;
|
||||
PVOID RequestContext;
|
||||
TDI_STATUS TdiStatus;
|
||||
} TDI_REQUEST, *PTDI_REQUEST;
|
||||
|
||||
typedef struct _TDI_REQUEST_SEND_DATAGRAM
|
||||
{
|
||||
TDI_REQUEST Request;
|
||||
PTDI_CONNECTION_INFORMATION SendDatagramInformation;
|
||||
} TDI_REQUEST_SEND_DATAGRAM, *PTDI_REQUEST_SEND_DATAGRAM;
|
||||
|
||||
typedef struct _AFD_SEND_DATAGRAM_INFO
|
||||
{
|
||||
LPWSABUF BufferArray;
|
||||
ULONG BufferCount;
|
||||
ULONG AfdFlags;
|
||||
TDI_REQUEST_SEND_DATAGRAM TdiRequest;
|
||||
TDI_CONNECTION_INFORMATION TdiConnInfo;
|
||||
} AFD_SEND_DATAGRAM_INFO, *PAFD_SEND_DATAGRAM_INFO;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct afd_endpoint : stateless_device
|
||||
struct afd_creation_data
|
||||
{
|
||||
network::socket s{AF_INET};
|
||||
uint64_t unk1;
|
||||
char afd_open_packet_xx[0x10];
|
||||
uint64_t unk2;
|
||||
int address_family;
|
||||
int type;
|
||||
int protocol;
|
||||
// ...
|
||||
};
|
||||
|
||||
afd_creation_data get_creation_data(const io_device_creation_data& data)
|
||||
{
|
||||
if (!data.buffer || data.length < sizeof(afd_creation_data))
|
||||
{
|
||||
throw std::runtime_error("Bad AFD creation data");
|
||||
}
|
||||
|
||||
return emulator_object<afd_creation_data>{data.emu, data.buffer}.read();
|
||||
}
|
||||
|
||||
struct afd_endpoint : io_device
|
||||
{
|
||||
std::optional<SOCKET> s{};
|
||||
|
||||
afd_endpoint()
|
||||
{
|
||||
network::initialize_wsa();
|
||||
}
|
||||
|
||||
afd_endpoint(afd_endpoint&&) = delete;
|
||||
afd_endpoint& operator=(afd_endpoint&&) = delete;
|
||||
|
||||
~afd_endpoint() override
|
||||
{
|
||||
if (this->s)
|
||||
{
|
||||
closesocket(*this->s);
|
||||
}
|
||||
}
|
||||
|
||||
void create(const io_device_creation_data& data) override
|
||||
{
|
||||
const auto creation_data = get_creation_data(data);
|
||||
const auto sock = socket(creation_data.address_family, creation_data.type, creation_data.protocol);
|
||||
if (sock == INVALID_SOCKET)
|
||||
{
|
||||
throw std::runtime_error("Failed to create socket!");
|
||||
}
|
||||
|
||||
s = sock;
|
||||
}
|
||||
|
||||
void deserialize(utils::buffer_deserializer&) override
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void serialize(utils::buffer_serializer&) const override
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
NTSTATUS io_control(const io_device_context& c) override
|
||||
{
|
||||
c.io_status_block.write({});
|
||||
|
||||
if (_AFD_BASE(c.io_control_code) != FSCTL_AFD_BASE)
|
||||
{
|
||||
c.win_emu.logger.print(color::cyan, "Bad AFD IOCTL: %X\n", c.io_control_code);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
c.win_emu.logger.print(color::cyan, "AFD IOCTL: %X\n", c.io_control_code);
|
||||
|
||||
switch (c.io_control_code)
|
||||
const auto request = _AFD_REQUEST(c.io_control_code);
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case 0x12003:
|
||||
case AFD_BIND:
|
||||
return this->ioctl_bind(c);
|
||||
case 0x12023:
|
||||
case AFD_SEND_DATAGRAM:
|
||||
return this->ioctl_send_datagram(c);
|
||||
case 0x12047: // ?
|
||||
case 0x1207B: // ?
|
||||
case AFD_SET_CONTEXT:
|
||||
return STATUS_SUCCESS;
|
||||
case AFD_GET_INFORMATION:
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
c.win_emu.logger.print(color::gray, "Unsupported AFD IOCTL: %X\n", c.io_control_code);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS ioctl_bind(const io_device_context& c)
|
||||
NTSTATUS ioctl_bind(const io_device_context& c) const
|
||||
{
|
||||
std::vector<std::byte> data{};
|
||||
data.resize(c.input_buffer_length);
|
||||
c.emu.read_memory(c.input_buffer, data.data(), c.input_buffer_length);
|
||||
|
||||
utils::buffer_deserializer deserializer{data, true};
|
||||
deserializer.read<uint32_t>(); // IDK :(
|
||||
const network::address addr = deserializer.read<sockaddr_in>();
|
||||
constexpr auto address_offset = 4;
|
||||
|
||||
if (!this->s.bind_port(addr))
|
||||
if (data.size() < address_offset)
|
||||
{
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
const auto* address = reinterpret_cast<const sockaddr*>(data.data() + address_offset);
|
||||
const auto address_size = static_cast<int>(data.size() - address_offset);
|
||||
|
||||
const network::address addr(address, address_size);
|
||||
|
||||
if (bind(*this->s, &addr.get_addr(), addr.get_size()) == SOCKET_ERROR)
|
||||
{
|
||||
return STATUS_ADDRESS_ALREADY_ASSOCIATED;
|
||||
}
|
||||
@@ -89,7 +127,7 @@ namespace
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS ioctl_send_datagram(const io_device_context& c)
|
||||
NTSTATUS ioctl_send_datagram(const io_device_context& c) const
|
||||
{
|
||||
if (c.input_buffer_length < sizeof(AFD_SEND_DATAGRAM_INFO))
|
||||
{
|
||||
@@ -111,7 +149,11 @@ namespace
|
||||
data.resize(buffer.len);
|
||||
c.emu.read_memory(reinterpret_cast<uint64_t>(buffer.buf), data.data(), data.size());
|
||||
|
||||
if (!s.send(target, data.data(), data.size()))
|
||||
const auto sent_data = sendto(*this->s, reinterpret_cast<const char*>(data.data()),
|
||||
static_cast<int>(data.size()), 0 /* ? */, &target.get_addr(),
|
||||
target.get_size());
|
||||
|
||||
if (sent_data < 0)
|
||||
{
|
||||
return STATUS_CONNECTION_REFUSED;
|
||||
}
|
||||
@@ -119,7 +161,7 @@ namespace
|
||||
if (c.io_status_block)
|
||||
{
|
||||
IO_STATUS_BLOCK block{};
|
||||
block.Information = data.size();
|
||||
block.Information = static_cast<uint32_t>(sent_data);
|
||||
c.io_status_block.write(block);
|
||||
}
|
||||
|
||||
|
||||
102
src/windows-emulator/devices/afd_types.hpp
Normal file
102
src/windows-emulator/devices/afd_types.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include "../std_include.hpp"
|
||||
|
||||
typedef LONG TDI_STATUS;
|
||||
typedef PVOID CONNECTION_CONTEXT;
|
||||
|
||||
typedef struct _TDI_CONNECTION_INFORMATION
|
||||
{
|
||||
LONG UserDataLength;
|
||||
PVOID UserData;
|
||||
LONG OptionsLength;
|
||||
PVOID Options;
|
||||
LONG RemoteAddressLength;
|
||||
PVOID RemoteAddress;
|
||||
} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION;
|
||||
|
||||
typedef struct _TDI_REQUEST
|
||||
{
|
||||
union
|
||||
{
|
||||
HANDLE AddressHandle;
|
||||
CONNECTION_CONTEXT ConnectionContext;
|
||||
HANDLE ControlChannel;
|
||||
} Handle;
|
||||
|
||||
PVOID RequestNotifyObject;
|
||||
PVOID RequestContext;
|
||||
TDI_STATUS TdiStatus;
|
||||
} TDI_REQUEST, *PTDI_REQUEST;
|
||||
|
||||
typedef struct _TDI_REQUEST_SEND_DATAGRAM
|
||||
{
|
||||
TDI_REQUEST Request;
|
||||
PTDI_CONNECTION_INFORMATION SendDatagramInformation;
|
||||
} TDI_REQUEST_SEND_DATAGRAM, *PTDI_REQUEST_SEND_DATAGRAM;
|
||||
|
||||
typedef struct _AFD_SEND_DATAGRAM_INFO
|
||||
{
|
||||
LPWSABUF BufferArray;
|
||||
ULONG BufferCount;
|
||||
ULONG AfdFlags;
|
||||
TDI_REQUEST_SEND_DATAGRAM TdiRequest;
|
||||
TDI_CONNECTION_INFORMATION TdiConnInfo;
|
||||
} AFD_SEND_DATAGRAM_INFO, *PAFD_SEND_DATAGRAM_INFO;
|
||||
|
||||
#define _AFD_REQUEST(ioctl) \
|
||||
((((ULONG)(ioctl)) >> 2) & 0x03FF)
|
||||
#define _AFD_BASE(ioctl) \
|
||||
((((ULONG)(ioctl)) >> 12) & 0xFFFFF)
|
||||
|
||||
#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK
|
||||
|
||||
#define AFD_BIND 0
|
||||
#define AFD_CONNECT 1
|
||||
#define AFD_START_LISTEN 2
|
||||
#define AFD_WAIT_FOR_LISTEN 3
|
||||
#define AFD_ACCEPT 4
|
||||
#define AFD_RECEIVE 5
|
||||
#define AFD_RECEIVE_DATAGRAM 6
|
||||
#define AFD_SEND 7
|
||||
#define AFD_SEND_DATAGRAM 8
|
||||
#define AFD_POLL 9
|
||||
#define AFD_PARTIAL_DISCONNECT 10
|
||||
|
||||
#define AFD_GET_ADDRESS 11
|
||||
#define AFD_QUERY_RECEIVE_INFO 12
|
||||
#define AFD_QUERY_HANDLES 13
|
||||
#define AFD_SET_INFORMATION 14
|
||||
#define AFD_GET_CONTEXT_LENGTH 15
|
||||
#define AFD_GET_CONTEXT 16
|
||||
#define AFD_SET_CONTEXT 17
|
||||
|
||||
#define AFD_SET_CONNECT_DATA 18
|
||||
#define AFD_SET_CONNECT_OPTIONS 19
|
||||
#define AFD_SET_DISCONNECT_DATA 20
|
||||
#define AFD_SET_DISCONNECT_OPTIONS 21
|
||||
|
||||
#define AFD_GET_CONNECT_DATA 22
|
||||
#define AFD_GET_CONNECT_OPTIONS 23
|
||||
#define AFD_GET_DISCONNECT_DATA 24
|
||||
#define AFD_GET_DISCONNECT_OPTIONS 25
|
||||
|
||||
#define AFD_SIZE_CONNECT_DATA 26
|
||||
#define AFD_SIZE_CONNECT_OPTIONS 27
|
||||
#define AFD_SIZE_DISCONNECT_DATA 28
|
||||
#define AFD_SIZE_DISCONNECT_OPTIONS 29
|
||||
|
||||
#define AFD_GET_INFORMATION 30
|
||||
#define AFD_TRANSMIT_FILE 31
|
||||
#define AFD_SUPER_ACCEPT 32
|
||||
|
||||
#define AFD_EVENT_SELECT 33
|
||||
#define AFD_ENUM_NETWORK_EVENTS 34
|
||||
|
||||
#define AFD_DEFER_ACCEPT 35
|
||||
#define AFD_WAIT_FOR_LISTEN_LIFO 36
|
||||
#define AFD_SET_QOS 37
|
||||
#define AFD_GET_QOS 38
|
||||
#define AFD_NO_OPERATION 39
|
||||
#define AFD_VALIDATE_GROUP 40
|
||||
#define AFD_GET_UNACCEPTED_CONNECT_DATA 41
|
||||
@@ -27,6 +27,16 @@ struct io_device_context
|
||||
ULONG output_buffer_length;
|
||||
};
|
||||
|
||||
struct io_device_creation_data
|
||||
{
|
||||
windows_emulator& win_emu;
|
||||
x64_emulator& emu;
|
||||
process_context& proc;
|
||||
|
||||
uint64_t buffer;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
struct io_device
|
||||
{
|
||||
io_device() = default;
|
||||
@@ -40,12 +50,21 @@ struct io_device
|
||||
|
||||
virtual NTSTATUS io_control(const io_device_context& context) = 0;
|
||||
|
||||
virtual void create(const io_device_creation_data& data)
|
||||
{
|
||||
(void)data;
|
||||
}
|
||||
|
||||
virtual void serialize(utils::buffer_serializer& buffer) const = 0;
|
||||
virtual void deserialize(utils::buffer_deserializer& buffer) = 0;
|
||||
};
|
||||
|
||||
struct stateless_device : io_device
|
||||
{
|
||||
void create(const io_device_creation_data&) final
|
||||
{
|
||||
}
|
||||
|
||||
void serialize(utils::buffer_serializer&) const override
|
||||
{
|
||||
}
|
||||
@@ -62,10 +81,11 @@ class io_device_container : public io_device
|
||||
public:
|
||||
io_device_container() = default;
|
||||
|
||||
io_device_container(std::wstring device)
|
||||
io_device_container(std::wstring device, const io_device_creation_data& data)
|
||||
: device_name_(std::move(device))
|
||||
{
|
||||
this->setup();
|
||||
this->device_->create(data);
|
||||
}
|
||||
|
||||
NTSTATUS io_control(const io_device_context& context) override
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
#include <ntgdi.h>
|
||||
#include <ws2def.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(pop)
|
||||
|
||||
@@ -2058,8 +2058,8 @@ namespace
|
||||
const emulator_object<IO_STATUS_BLOCK> /*io_status_block*/,
|
||||
const emulator_object<LARGE_INTEGER> /*allocation_size*/, ULONG /*file_attributes*/,
|
||||
ULONG /*share_access*/, ULONG create_disposition, ULONG create_options,
|
||||
uint64_t /*ea_buffer*/,
|
||||
ULONG /*ea_length*/)
|
||||
uint64_t ea_buffer,
|
||||
ULONG ea_length)
|
||||
{
|
||||
const auto attributes = object_attributes.read();
|
||||
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
@@ -2072,8 +2072,16 @@ namespace
|
||||
constexpr std::wstring_view device_prefix = L"\\Device\\";
|
||||
if (filename.starts_with(device_prefix))
|
||||
{
|
||||
const io_device_creation_data data{
|
||||
.win_emu = c.win_emu,
|
||||
.emu = c.emu,
|
||||
.proc = c.proc,
|
||||
.buffer = ea_buffer,
|
||||
.length = ea_length,
|
||||
};
|
||||
|
||||
auto device_name = filename.substr(device_prefix.size());
|
||||
io_device_container container{std::move(device_name)};
|
||||
io_device_container container{std::move(device_name), data};
|
||||
|
||||
const auto handle = c.proc.devices.store(std::move(container));
|
||||
file_handle.write(handle);
|
||||
|
||||
Reference in New Issue
Block a user