mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 11:43:56 +00:00
Add stub for NtReleaseWorkerFactoryWorker, skeleton implementation for NtCreateNamedPipeFile (#444)
Added a stub implementation for NtReleaseWorkerFactoryWorker. Introduced initial skeleton logic for NtCreateNamedPipeFile with device creation and registration, object attribute parse for pipe naming, basic parameters to named_pipe structure, IOSB and handle writing.
This commit is contained in:
@@ -52,6 +52,16 @@ using NTSTATUS = std::uint32_t;
|
||||
#define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS)0xC0000328L)
|
||||
#define STATUS_PORT_NOT_SET ((NTSTATUS)0xC0000353L)
|
||||
#define STATUS_DEBUGGER_INACTIVE ((NTSTATUS)0xC0000354L)
|
||||
#define STATUS_PIPE_BROKEN ((NTSTATUS)0xC000014BL)
|
||||
#define STATUS_PIPE_EMPTY ((NTSTATUS)0xC00000D9L)
|
||||
#define STATUS_PIPE_BUSY ((NTSTATUS)0xC00000AAL)
|
||||
#define STATUS_PIPE_DISCONNECTED ((NTSTATUS)0xC00000B0L)
|
||||
#define STATUS_PIPE_LISTENING ((NTSTATUS)0x00000105L)
|
||||
#define STATUS_PIPE_CONNECTED ((NTSTATUS)0x00000106L)
|
||||
#define STATUS_PIPE_CLOSING ((NTSTATUS)0xC00000B1L)
|
||||
#define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS)0xC00000ACL)
|
||||
#define STATUS_INVALID_PIPE_STATE ((NTSTATUS)0xC00000ADL)
|
||||
#define STATUS_PIPE_NOT_CONNECTED ((NTSTATUS)0xC00000BEL)
|
||||
|
||||
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
|
||||
|
||||
|
||||
35
src/windows-emulator/devices/named_pipe.hpp
Normal file
35
src/windows-emulator/devices/named_pipe.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "../io_device.hpp"
|
||||
|
||||
class named_pipe : public io_device_container
|
||||
{
|
||||
public:
|
||||
std::u16string name;
|
||||
std::deque<std::string> write_queue;
|
||||
ACCESS_MASK access = 0;
|
||||
ULONG pipe_type;
|
||||
ULONG read_mode;
|
||||
ULONG completion_mode;
|
||||
ULONG max_instances;
|
||||
ULONG inbound_quota;
|
||||
ULONG outbound_quota;
|
||||
LARGE_INTEGER default_timeout;
|
||||
|
||||
void create(windows_emulator&, const io_device_creation_data&) override
|
||||
{
|
||||
}
|
||||
void work(windows_emulator&) override
|
||||
{
|
||||
}
|
||||
NTSTATUS io_control(windows_emulator&, const io_device_context&) override
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void serialize_object(utils::buffer_serializer&) const override
|
||||
{
|
||||
}
|
||||
void deserialize_object(utils::buffer_deserializer&) override
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "devices/afd_endpoint.hpp"
|
||||
#include "devices/mount_point_manager.hpp"
|
||||
#include "devices/security_support_provider.hpp"
|
||||
#include "devices/named_pipe.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -49,6 +51,11 @@ std::unique_ptr<io_device> create_device(const std::u16string_view device)
|
||||
return create_security_support_provider();
|
||||
}
|
||||
|
||||
if (device == u"NamedPipe")
|
||||
{
|
||||
return std::make_unique<named_pipe>();
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unsupported device: " + u16_to_u8(device));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "windows_emulator.hpp"
|
||||
#include <ctime>
|
||||
#include <platform/primitives.hpp>
|
||||
#include "windows-emulator/devices/named_pipe.hpp"
|
||||
|
||||
struct syscall_context
|
||||
{
|
||||
@@ -28,6 +29,11 @@ inline bool is_syscall(const std::string_view name)
|
||||
return name.starts_with("Nt") && name.size() > 3 && is_uppercase(name[2]);
|
||||
}
|
||||
|
||||
inline bool is_named_pipe_path(const std::u16string_view& filename)
|
||||
{
|
||||
return filename == u"\\Device\\NamedPipe\\" || filename.starts_with(u"\\Device\\NamedPipe\\");
|
||||
}
|
||||
|
||||
inline std::optional<uint32_t> extract_syscall_id(const exported_symbol& symbol, std::span<const std::byte> data)
|
||||
{
|
||||
if (!is_syscall(symbol.name))
|
||||
|
||||
@@ -436,6 +436,11 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtReleaseWorkerFactoryWorker()
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateIoCompletion(
|
||||
const syscall_context& c, const emulator_object<handle> event_handle, const ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
@@ -1185,6 +1190,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtQueryEvent);
|
||||
add_handler(NtRemoveIoCompletionEx);
|
||||
add_handler(NtCreateDebugObject);
|
||||
add_handler(NtReleaseWorkerFactoryWorker);
|
||||
|
||||
#undef add_handler
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../devices/named_pipe.hpp"
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#define fstat64 _fstat64
|
||||
#elif defined(OS_MAC)
|
||||
@@ -646,6 +648,34 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const auto* container = c.proc.devices.get(file_handle);
|
||||
if (container)
|
||||
{
|
||||
if (auto* pipe = container->get_internal_device<named_pipe>())
|
||||
{
|
||||
if (!pipe->write_queue.empty())
|
||||
{
|
||||
std::string_view data = pipe->write_queue.front();
|
||||
const size_t to_copy = std::min<size_t>(data.size(), length);
|
||||
|
||||
commit_file_data(data.substr(0, to_copy), c.emu, io_status_block, buffer);
|
||||
|
||||
if (to_copy == data.size())
|
||||
{
|
||||
pipe->write_queue.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
pipe->write_queue.front().erase(0, to_copy);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_PIPE_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
const auto* f = c.proc.files.get(file_handle);
|
||||
if (!f)
|
||||
{
|
||||
@@ -683,6 +713,27 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const auto* container = c.proc.devices.get(file_handle);
|
||||
if (container)
|
||||
{
|
||||
if (auto* pipe = container->get_internal_device<named_pipe>())
|
||||
{
|
||||
(void)pipe; // For future use: suppressing compiler issues
|
||||
// TODO c.win_emu.callbacks.on_named_pipe_write(pipe->name, temp_buffer);
|
||||
|
||||
// TODO pipe->write_queue.push_back(temp_buffer);
|
||||
|
||||
if (io_status_block)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Information = static_cast<ULONG>(temp_buffer.size());
|
||||
io_status_block.write(block);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
const auto* f = c.proc.files.get(file_handle);
|
||||
if (!f)
|
||||
{
|
||||
@@ -777,6 +828,33 @@ namespace syscalls
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
NTSTATUS handle_named_pipe_create(const syscall_context& c, const emulator_object<handle>& out_handle,
|
||||
const std::u16string_view filename,
|
||||
const OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>& attributes,
|
||||
ACCESS_MASK desired_access)
|
||||
{
|
||||
(void)attributes; // This isn't being consumed atm, suppressing errors
|
||||
|
||||
c.win_emu.callbacks.on_generic_access("Creating/opening named pipe", filename);
|
||||
|
||||
io_device_creation_data data{};
|
||||
|
||||
std::u16string device_name = u"NamedPipe";
|
||||
|
||||
io_device_container container{device_name, c.win_emu, data};
|
||||
|
||||
if (auto* pipe_device = container.get_internal_device<named_pipe>())
|
||||
{
|
||||
pipe_device->name = std::u16string(filename);
|
||||
pipe_device->access = desired_access;
|
||||
}
|
||||
|
||||
const auto handle = c.proc.devices.store(std::move(container));
|
||||
out_handle.write(handle);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateFile(const syscall_context& c, const emulator_object<handle> file_handle,
|
||||
ACCESS_MASK desired_access,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
@@ -788,6 +866,11 @@ namespace syscalls
|
||||
const auto attributes = object_attributes.read();
|
||||
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
|
||||
if (is_named_pipe_path(filename))
|
||||
{
|
||||
return handle_named_pipe_create(c, file_handle, filename, attributes, desired_access);
|
||||
}
|
||||
|
||||
auto printer = utils::finally([&] {
|
||||
c.win_emu.callbacks.on_generic_access("Opening file", filename); //
|
||||
});
|
||||
@@ -1067,19 +1150,58 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateNamedPipeFile(
|
||||
const syscall_context& c, const emulator_object<handle> /*file_handle*/, const ULONG /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> /*object_attributes*/,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> /*io_status_block*/, const ULONG /*share_access*/,
|
||||
const ULONG /*create_disposition*/, const ULONG /*create_options*/, const ULONG /*named_pipe_type*/,
|
||||
const ULONG /*read_mode*/, const ULONG /*completion_mode*/, const ULONG /*maximum_instances*/,
|
||||
const ULONG /*inbound_quota*/, const ULONG /*outbound_quota*/,
|
||||
const emulator_object<LARGE_INTEGER> /*default_timeout*/)
|
||||
NTSTATUS handle_NtCreateNamedPipeFile(const syscall_context& c, emulator_object<handle> file_handle,
|
||||
ULONG desired_access,
|
||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
ULONG share_access, ULONG create_disposition, ULONG create_options,
|
||||
ULONG named_pipe_type, ULONG read_mode, ULONG completion_mode,
|
||||
ULONG maximum_instances, ULONG inbound_quota, ULONG outbound_quota,
|
||||
emulator_object<LARGE_INTEGER> default_timeout)
|
||||
{
|
||||
c.win_emu.log.error("Unimplemented syscall NtCreateNamedPipeFile!");
|
||||
c.emu.stop();
|
||||
(void)desired_access;
|
||||
(void)share_access;
|
||||
(void)create_disposition;
|
||||
(void)create_options;
|
||||
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
const auto attributes = object_attributes.read();
|
||||
const auto filename = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
|
||||
if (!filename.starts_with(u"\\Device\\NamedPipe"))
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
c.win_emu.callbacks.on_generic_access("Creating named pipe", filename);
|
||||
|
||||
io_device_creation_data data{};
|
||||
io_device_container container{u"NamedPipe", c.win_emu, data};
|
||||
|
||||
if (auto* pipe_device = container.get_internal_device<named_pipe>())
|
||||
{
|
||||
pipe_device->name = filename;
|
||||
pipe_device->pipe_type = named_pipe_type;
|
||||
pipe_device->read_mode = read_mode;
|
||||
pipe_device->completion_mode = completion_mode;
|
||||
pipe_device->max_instances = maximum_instances;
|
||||
pipe_device->inbound_quota = inbound_quota;
|
||||
pipe_device->outbound_quota = outbound_quota;
|
||||
pipe_device->default_timeout = default_timeout.read();
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
handle pipe_handle = c.proc.devices.store(std::move(container));
|
||||
file_handle.write(pipe_handle);
|
||||
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> iosb{};
|
||||
iosb.Status = STATUS_SUCCESS;
|
||||
iosb.Information = 0;
|
||||
io_status_block.write(iosb);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtFsControlFile(const syscall_context& c, const handle /*event_handle*/,
|
||||
|
||||
Reference in New Issue
Block a user