diff --git a/src/emulator/memory_manager.hpp b/src/emulator/memory_manager.hpp index 54e33dd..9e16b6c 100644 --- a/src/emulator/memory_manager.hpp +++ b/src/emulator/memory_manager.hpp @@ -40,6 +40,12 @@ class memory_manager return value; } + template + T read_memory(const void* address) + { + return this->read_memory(reinterpret_cast(address)); + } + template void write_memory(const uint64_t address, const T& value) { diff --git a/src/windows-emulator/devices/afd_endpoint.cpp b/src/windows-emulator/devices/afd_endpoint.cpp index 9c25106..97f3b9d 100644 --- a/src/windows-emulator/devices/afd_endpoint.cpp +++ b/src/windows-emulator/devices/afd_endpoint.cpp @@ -52,6 +52,7 @@ namespace void create(const io_device_creation_data& data) override { const auto creation_data = get_creation_data(data); + // TODO: values map to windows values; might not be the case for other platforms const auto sock = socket(creation_data.address_family, creation_data.type, creation_data.protocol); if (sock == INVALID_SOCKET) { @@ -91,6 +92,8 @@ namespace return this->ioctl_bind(c); case AFD_SEND_DATAGRAM: return this->ioctl_send_datagram(c); + case AFD_RECEIVE_DATAGRAM: + return this->ioctl_receive_datagram(c); case AFD_SET_CONTEXT: return STATUS_SUCCESS; case AFD_GET_INFORMATION: @@ -127,6 +130,63 @@ namespace return STATUS_SUCCESS; } + NTSTATUS ioctl_receive_datagram(const io_device_context& c) const + { + if (c.input_buffer_length < sizeof(AFD_RECV_DATAGRAM_INFO)) + { + return STATUS_BUFFER_TOO_SMALL; + } + + const auto receive_info = emulator_object{c.emu, c.input_buffer}.read(); + const auto buffer = emulator_object{c.emu, receive_info.BufferArray}.read(0); + + std::vector address{}; + + ULONG address_length = 0x1000; + if (receive_info.AddressLength) + { + address_length = c.emu.read_memory(receive_info.AddressLength); + } + + address.resize(std::clamp(address_length, 1UL, 0x1000UL)); + + if (!buffer.len || buffer.len > 0x10000 || !buffer.buf) + { + return STATUS_INVALID_PARAMETER; + } + + int fromlength = static_cast(address.size()); + + std::vector data{}; + data.resize(buffer.len); + + const auto recevied_data = recvfrom(*this->s, data.data(), static_cast(data.size()), 0, + reinterpret_cast(address.data()), &fromlength); + + if (recevied_data < 0) + { + return STATUS_UNSUCCESSFUL; + } + + c.emu.write_memory(reinterpret_cast(buffer.buf), data.data(), + std::min(data.size(), static_cast(recevied_data))); + + if (receive_info.Address && address_length) + { + c.emu.write_memory(reinterpret_cast(receive_info.Address), address.data(), + std::min(address.size(), static_cast(address_length))); + } + + if (c.io_status_block) + { + IO_STATUS_BLOCK block{}; + block.Information = static_cast(recevied_data); + c.io_status_block.write(block); + } + + return STATUS_SUCCESS; + } + NTSTATUS ioctl_send_datagram(const io_device_context& c) const { if (c.input_buffer_length < sizeof(AFD_SEND_DATAGRAM_INFO)) diff --git a/src/windows-emulator/devices/afd_types.hpp b/src/windows-emulator/devices/afd_types.hpp index 17a4cf0..a168380 100644 --- a/src/windows-emulator/devices/afd_types.hpp +++ b/src/windows-emulator/devices/afd_types.hpp @@ -35,6 +35,14 @@ typedef struct _TDI_REQUEST_SEND_DATAGRAM PTDI_CONNECTION_INFORMATION SendDatagramInformation; } TDI_REQUEST_SEND_DATAGRAM, *PTDI_REQUEST_SEND_DATAGRAM; +typedef struct _AFD_SEND_INFO +{ + LPWSABUF BufferArray; + ULONG BufferCount; + ULONG AfdFlags; + ULONG TdiFlags; +} AFD_SEND_INFO, *PAFD_SEND_INFO; + typedef struct _AFD_SEND_DATAGRAM_INFO { LPWSABUF BufferArray; @@ -44,6 +52,24 @@ typedef struct _AFD_SEND_DATAGRAM_INFO TDI_CONNECTION_INFORMATION TdiConnInfo; } AFD_SEND_DATAGRAM_INFO, *PAFD_SEND_DATAGRAM_INFO; +typedef struct _AFD_RECV_INFO +{ + LPWSABUF BufferArray; + ULONG BufferCount; + ULONG AfdFlags; + ULONG TdiFlags; +} AFD_RECV_INFO, *PAFD_RECV_INFO; + +typedef struct _AFD_RECV_DATAGRAM_INFO +{ + LPWSABUF BufferArray; + ULONG BufferCount; + ULONG AfdFlags; + ULONG TdiFlags; + PVOID Address; + PULONG AddressLength; +} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO; + #define _AFD_REQUEST(ioctl) \ ((((ULONG)(ioctl)) >> 2) & 0x03FF) #define _AFD_BASE(ioctl) \