diff --git a/src/windows-emulator/io_device.hpp b/src/windows-emulator/io_device.hpp index b76ff6cc..d5a8353a 100644 --- a/src/windows-emulator/io_device.hpp +++ b/src/windows-emulator/io_device.hpp @@ -65,15 +65,19 @@ struct io_device_creation_data uint32_t length; }; -inline void write_io_status(const emulator_object>> io_status_block, - const NTSTATUS status) +inline NTSTATUS write_io_status(const emulator_object>> io_status_block, + const NTSTATUS status, const bool clear_struct = false) { - if (io_status_block) - { - io_status_block.access([&](IO_STATUS_BLOCK>& status_block) { - status_block.Status = status; // - }); - } + io_status_block.access([=](IO_STATUS_BLOCK>& status_block) { + if (clear_struct) + { + status_block = {}; + } + + status_block.Status = status; + }); + + return status; } struct io_device : ref_counted_object diff --git a/src/windows-emulator/syscall_utils.hpp b/src/windows-emulator/syscall_utils.hpp index d440aaec..eb61b630 100644 --- a/src/windows-emulator/syscall_utils.hpp +++ b/src/windows-emulator/syscall_utils.hpp @@ -2,6 +2,7 @@ #include "windows_emulator.hpp" #include +#include struct syscall_context { @@ -194,27 +195,57 @@ void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const } } -template -NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t length, - const emulator_object return_length, const Action& action) +template +NTSTATUS handle_query_internal(x64_emulator& emu, const uint64_t buffer, const uint32_t length, + const ReturnLengthSetter& return_length_setter, const Action& action) { constexpr auto required_size = sizeof(ResponseType); - - if (return_length) - { - return_length.write(required_size); - } + return_length_setter(required_size); if (length < required_size) { - return TooSmallResponse; + return STATUS_BUFFER_TOO_SMALL; } - const emulator_object obj{emu, buffer}; - obj.access([&](ResponseType& resp_obj) { - action(resp_obj); // - }); + ResponseType obj{}; + action(obj); - return SuccessResponse; + emu.write_memory(buffer, obj); + + return STATUS_SUCCESS; +} + +template +NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t length, + const emulator_object return_length, const Action& action) +{ + const auto length_setter = [&](const uint32_t required_size) { + if (return_length) + { + return_length.write(required_size); + } + }; + + return handle_query_internal(emu, buffer, length, length_setter, action); +} + +template +NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t length, + const emulator_object>> io_status_block, + const Action& action) +{ + IO_STATUS_BLOCK> status_block{}; + + const auto length_setter = [&](const EmulatorTraits::ULONG_PTR required_size) { + status_block.Information = required_size; // + }; + + status_block.Status = handle_query_internal(emu, buffer, length, length_setter, action); + + if (io_status_block) + { + io_status_block.write(status_block); + } + + return status_block.Status; } diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 414c7514..5a40a921 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -45,9 +45,10 @@ namespace syscalls NTSTATUS handle_NtSetInformationFile(const syscall_context& c, handle file_handle, emulator_object>> io_status_block, uint64_t file_information, ULONG length, FILE_INFORMATION_CLASS info_class); - NTSTATUS handle_NtQueryVolumeInformationFile(const syscall_context& c, handle file_handle, - uint64_t /*io_status_block*/, uint64_t fs_information, - ULONG /*length*/, FS_INFORMATION_CLASS fs_information_class); + NTSTATUS handle_NtQueryVolumeInformationFile( + const syscall_context& c, handle file_handle, + emulator_object>> io_status_block, uint64_t fs_information, ULONG length, + FS_INFORMATION_CLASS fs_information_class); NTSTATUS handle_NtQueryDirectoryFileEx(const syscall_context& c, handle file_handle, handle /*event_handle*/, emulator_pointer /*PIO_APC_ROUTINE*/ /*apc_routine*/, emulator_pointer /*apc_context*/, diff --git a/src/windows-emulator/syscalls/file.cpp b/src/windows-emulator/syscalls/file.cpp index 471329b7..c2c675ef 100644 --- a/src/windows-emulator/syscalls/file.cpp +++ b/src/windows-emulator/syscalls/file.cpp @@ -56,54 +56,46 @@ namespace syscalls return STATUS_NOT_SUPPORTED; } - NTSTATUS handle_NtQueryVolumeInformationFile(const syscall_context& c, const handle file_handle, - const uint64_t /*io_status_block*/, const uint64_t fs_information, - const ULONG /*length*/, - const FS_INFORMATION_CLASS fs_information_class) + NTSTATUS handle_NtQueryVolumeInformationFile( + const syscall_context& c, const handle file_handle, + const emulator_object>> io_status_block, const uint64_t fs_information, + const ULONG length, const FS_INFORMATION_CLASS fs_information_class) { - if (fs_information_class == FileFsDeviceInformation) + switch (fs_information_class) { - const emulator_object info_obj{c.emu, fs_information}; - info_obj.access([&](FILE_FS_DEVICE_INFORMATION& info) { - if (file_handle == STDOUT_HANDLE && !c.win_emu.buffer_stdout) - { - info.DeviceType = FILE_DEVICE_CONSOLE; - info.Characteristics = 0x20000; - } - else - { - info.DeviceType = FILE_DEVICE_DISK; - info.Characteristics = 0x20020; - } - }); + case FileFsDeviceInformation: + return handle_query( + c.emu, fs_information, length, io_status_block, [&](FILE_FS_DEVICE_INFORMATION& info) { + if (file_handle == STDOUT_HANDLE && !c.win_emu.buffer_stdout) + { + info.DeviceType = FILE_DEVICE_CONSOLE; + info.Characteristics = 0x20000; + } + else + { + info.DeviceType = FILE_DEVICE_DISK; + info.Characteristics = 0x20020; + } + }); - return STATUS_SUCCESS; + case FileFsSizeInformation: + return handle_query(c.emu, fs_information, length, io_status_block, + [&](FILE_FS_SIZE_INFORMATION& info) { + info.BytesPerSector = 0x1000; + info.SectorsPerAllocationUnit = 0x1000; + info.TotalAllocationUnits.QuadPart = 0x10000; + info.AvailableAllocationUnits.QuadPart = 0x1000; + }); + + case FileFsVolumeInformation: + return handle_query(c.emu, fs_information, length, io_status_block, + [&](FILE_FS_VOLUME_INFORMATION&) {}); + + default: + c.win_emu.log.error("Unsupported fs info class: %X\n", fs_information_class); + c.emu.stop(); + return write_io_status(io_status_block, STATUS_NOT_SUPPORTED, true); } - - if (fs_information_class == FileFsSizeInformation) - { - const emulator_object info_obj{c.emu, fs_information}; - info_obj.access([&](FILE_FS_SIZE_INFORMATION& info) { - info.BytesPerSector = 0x1000; - info.SectorsPerAllocationUnit = 0x1000; - info.TotalAllocationUnits.QuadPart = 0x10000; - info.AvailableAllocationUnits.QuadPart = 0x1000; - }); - - return STATUS_SUCCESS; - } - - if (fs_information_class == FileFsVolumeInformation) - { - constexpr FILE_FS_VOLUME_INFORMATION volume_info{}; - c.emu.write_memory(fs_information, volume_info); - - return STATUS_SUCCESS; - } - - c.win_emu.log.error("Unsupported fs info class: %X\n", fs_information_class); - c.emu.stop(); - return STATUS_NOT_SUPPORTED; } std::vector scan_directory(const std::filesystem::path& dir) @@ -173,8 +165,9 @@ namespace syscalls { const auto object_offset = object.value() - file_information; - object.access( - [&](T& dir_info) { dir_info.NextEntryOffset = static_cast(new_offset - object_offset); }); + object.access([&](T& dir_info) { + dir_info.NextEntryOffset = static_cast(new_offset - object_offset); // + }); } T info{}; @@ -619,7 +612,7 @@ namespace syscalls return STATUS_ACCESS_DENIED; } } - else if (!std::filesystem::is_directory(c.win_emu.file_sys.translate(f.name))) + else if (!is_directory(c.win_emu.file_sys.translate(f.name))) { return STATUS_OBJECT_NAME_NOT_FOUND; } diff --git a/src/windows-emulator/syscalls/system.cpp b/src/windows-emulator/syscalls/system.cpp index e7510bdf..2d443891 100644 --- a/src/windows-emulator/syscalls/system.cpp +++ b/src/windows-emulator/syscalls/system.cpp @@ -175,7 +175,6 @@ namespace syscalls return handle_query( c.emu, system_information, system_information_length, return_length, [&](info_type& info) { - info = {}; info.Relationship = RelationProcessorCore; if (processor_group == 0)