This commit is contained in:
momo5502
2024-11-09 21:40:14 +01:00
parent df70f29ba3
commit 040fcff19a
2 changed files with 163 additions and 26 deletions

View File

@@ -61,6 +61,135 @@ namespace
return {std::move(poll_info), std::move(handle_info)};
}
std::optional<NTSTATUS> perform_poll(windows_emulator& win_emu, const io_device_context& c,
const std::span<const SOCKET> endpoints,
const std::span<const AFD_POLL_HANDLE_INFO> handles)
{
std::vector<pollfd> poll_data{};
poll_data.resize(endpoints.size());
for (size_t i = 0; i < endpoints.size() && i < handles.size(); ++i)
{
auto& pfd = poll_data.at(i);
auto& handle = handles[i];
if (handle.PollEvents & (AFD_POLL_ACCEPT | AFD_POLL_RECEIVE))
{
pfd.events |= POLLRDNORM;
}
if (handle.PollEvents & AFD_POLL_RECEIVE_EXPEDITED)
{
pfd.events |= POLLRDNORM;
}
if (handle.PollEvents & AFD_POLL_RECEIVE_EXPEDITED)
{
pfd.events |= POLLRDBAND;
}
if (handle.PollEvents & (AFD_POLL_CONNECT_FAIL | AFD_POLL_SEND))
{
pfd.events |= POLLWRNORM;
}
/*if ((pfd.events & POLLRDNORM) != 0)
handle.PollEvents |= (AFD_POLL_ACCEPT | AFD_POLL_RECEIVE);
if ((pfd.events & POLLRDBAND) != 0)
handle.PollEvents |= AFD_POLL_RECEIVE_EXPEDITED;
if ((pfd.events & POLLWRNORM) != 0)
handle.PollEvents |= (AFD_POLL_CONNECT_FAIL | AFD_POLL_SEND);
handle.PollEvents |= (AFD_POLL_DISCONNECT | AFD_POLL_ABORT);*/
// -----------------------------
pfd.fd = endpoints[i];
pfd.events = POLLIN;
pfd.revents = pfd.events;
}
const auto count = poll(poll_data.data(), static_cast<uint32_t>(poll_data.size()), 0);
if (count > 0)
{
constexpr auto info_size = offsetof(AFD_POLL_INFO, Handles);
const emulator_object<AFD_POLL_HANDLE_INFO> handle_info_obj{win_emu.emu(), c.input_buffer + info_size};
size_t current_index = 0;
for (size_t i = 0; i < endpoints.size(); ++i)
{
const auto& pfd = poll_data.at(i);
if (pfd.revents == 0)
{
continue;
}
ULONG events = 0;
if (pfd.revents & POLLRDNORM)
{
events |= (AFD_POLL_ACCEPT | AFD_POLL_RECEIVE);
}
if (pfd.revents & POLLRDBAND)
{
events |= AFD_POLL_RECEIVE_EXPEDITED;
}
if (pfd.revents & POLLWRNORM)
{
events |= (AFD_POLL_CONNECT_FAIL | AFD_POLL_SEND);
}
if ((pfd.revents & (POLLHUP | POLLERR)) == (POLLHUP | POLLERR))
{
events |= (AFD_POLL_CONNECT_FAIL | AFD_POLL_ABORT);
}
else if (pfd.revents & POLLHUP)
{
events |= AFD_POLL_DISCONNECT;
}
if (pfd.revents & POLLNVAL)
{
events |= AFD_POLL_LOCAL_CLOSE;
}
/*if ((handle.PollEvents & (AFD_POLL_ACCEPT | AFD_POLL_RECEIVE)) != 0 && (pfd.events & POLLRDNORM) != 0)
pfd.revents |= POLLRDNORM;
if ((handle.PollEvents & AFD_POLL_RECEIVE_EXPEDITED) != 0 && (pfd.events & POLLRDBAND) != 0)
pfd.revents |= POLLRDBAND;
if ((handle.PollEvents & (AFD_POLL_CONNECT_FAIL | AFD_POLL_SEND)) != 0 && (pfd.events & POLLWRNORM) != 0)
pfd.revents |= POLLWRNORM;
if ((handle.PollEvents & AFD_POLL_DISCONNECT) != 0)
pfd.revents |= POLLHUP;
if ((handle.PollEvents & (AFD_POLL_CONNECT_FAIL | AFD_POLL_ABORT)) != 0)
pfd.revents |= POLLHUP | POLLERR;
if ((handle.PollEvents & AFD_POLL_LOCAL_CLOSE) != 0)
pfd.revents |= POLLNVAL;*/
auto entry = handle_info_obj.read(i);
entry.PollEvents = events;
entry.Status = STATUS_SUCCESS;
handle_info_obj.write(entry, current_index++);
break;
}
assert(current_index == static_cast<size_t>(count));
emulator_object<AFD_POLL_INFO>{win_emu.emu(), c.input_buffer}.access([&](AFD_POLL_INFO& info)
{
info.NumberOfHandles = count;
});
return STATUS_SUCCESS;
}
return {};
}
struct afd_endpoint : io_device
{
bool in_poll{};
@@ -187,12 +316,12 @@ namespace
return STATUS_SUCCESS;
}
static std::vector<afd_endpoint*> resolve_endpoints(windows_emulator& win_emu,
const std::span<const AFD_POLL_HANDLE_INFO> handles)
static std::vector<SOCKET> resolve_endpoints(windows_emulator& win_emu,
const std::span<const AFD_POLL_HANDLE_INFO> handles)
{
auto& proc = win_emu.process();
std::vector<afd_endpoint*> endpoints{};
std::vector<SOCKET> endpoints{};
endpoints.reserve(handles.size());
for (const auto& handle : handles)
@@ -203,13 +332,13 @@ namespace
throw std::runtime_error("Bad device!");
}
auto* endpoint = device->get_internal_device<afd_endpoint>();
const auto* endpoint = device->get_internal_device<afd_endpoint>();
if (!endpoint)
{
throw std::runtime_error("Device is not an AFD endpoint!");
}
endpoints.push_back(endpoint);
endpoints.push_back(*endpoint->s);
}
return endpoints;
@@ -221,28 +350,10 @@ namespace
const auto [info, handles] = get_poll_info(win_emu, c);
const auto endpoints = resolve_endpoints(win_emu, handles);
std::vector<pollfd> poll_data{};
poll_data.resize(endpoints.size());
for (size_t i = 0; i < endpoints.size(); ++i)
const auto status = perform_poll(win_emu, c, endpoints, handles);
if (status)
{
auto& pfd = poll_data.at(i);
//auto& handle = handles.at(i);
pfd.fd = *endpoints.at(i)->s;
pfd.events = POLLIN;
pfd.revents = pfd.events;
}
const auto count = poll(poll_data.data(), static_cast<uint32_t>(poll_data.size()), 0);
if (count > 0)
{
emulator_object<AFD_POLL_INFO>{win_emu.emu(), c.input_buffer}.access([&](AFD_POLL_INFO& info)
{
info.NumberOfHandles = count;
});
t.pending_status = STATUS_SUCCESS;
t.pending_status = *status;
return true;
}

View File

@@ -85,6 +85,32 @@ typedef struct _AFD_POLL_INFO
AFD_POLL_HANDLE_INFO Handles[1];
} AFD_POLL_INFO, *PAFD_POLL_INFO;
#define AFD_POLL_RECEIVE_BIT 0
#define AFD_POLL_RECEIVE (1 << AFD_POLL_RECEIVE_BIT)
#define AFD_POLL_RECEIVE_EXPEDITED_BIT 1
#define AFD_POLL_RECEIVE_EXPEDITED (1 << AFD_POLL_RECEIVE_EXPEDITED_BIT)
#define AFD_POLL_SEND_BIT 2
#define AFD_POLL_SEND (1 << AFD_POLL_SEND_BIT)
#define AFD_POLL_DISCONNECT_BIT 3
#define AFD_POLL_DISCONNECT (1 << AFD_POLL_DISCONNECT_BIT)
#define AFD_POLL_ABORT_BIT 4
#define AFD_POLL_ABORT (1 << AFD_POLL_ABORT_BIT)
#define AFD_POLL_LOCAL_CLOSE_BIT 5
#define AFD_POLL_LOCAL_CLOSE (1 << AFD_POLL_LOCAL_CLOSE_BIT)
#define AFD_POLL_CONNECT_BIT 6
#define AFD_POLL_CONNECT (1 << AFD_POLL_CONNECT_BIT)
#define AFD_POLL_ACCEPT_BIT 7
#define AFD_POLL_ACCEPT (1 << AFD_POLL_ACCEPT_BIT)
#define AFD_POLL_CONNECT_FAIL_BIT 8
#define AFD_POLL_CONNECT_FAIL (1 << AFD_POLL_CONNECT_FAIL_BIT)
#define AFD_POLL_QOS_BIT 9
#define AFD_POLL_QOS (1 << AFD_POLL_QOS_BIT)
#define AFD_POLL_GROUP_QOS_BIT 10
#define AFD_POLL_GROUP_QOS (1 << AFD_POLL_GROUP_QOS_BIT)
#define AFD_NUM_POLL_EVENTS 11
#define AFD_POLL_ALL ((1 << AFD_NUM_POLL_EVENTS) - 1)
#define _AFD_REQUEST(ioctl) \
((((ULONG)(ioctl)) >> 2) & 0x03FF)
#define _AFD_BASE(ioctl) \