diff --git a/src/common/utils/file_handle.hpp b/src/common/utils/file_handle.hpp index 1c50c78e..29603137 100644 --- a/src/common/utils/file_handle.hpp +++ b/src/common/utils/file_handle.hpp @@ -59,6 +59,27 @@ namespace utils return this->file_; } + [[nodiscard]] int64_t size() const + { + const auto current_position = this->tell(); + + this->seek_to(0, SEEK_END); + const auto size = this->tell(); + this->seek_to(current_position); + + return size; + } + + bool seek_to(const int64_t position, const int origin = SEEK_SET) const + { + return _fseeki64(this->file_, position, origin) == 0; + } + + [[nodiscard]] int64_t tell() const + { + return _ftelli64(this->file_); + } + private: FILE* file_{}; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index b690c561..854cf44b 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -976,17 +976,72 @@ namespace return STATUS_NOT_SUPPORTED; } - NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, uint64_t /*file_handle*/, - const emulator_object io_status_block, + NTSTATUS handle_NtSetInformationFile(const syscall_context& c, const uint64_t file_handle, + const emulator_object io_status_block, + const uint64_t file_information, + const ULONG length, const FILE_INFORMATION_CLASS info_class) + { + const auto* f = c.proc.files.get(file_handle); + if (!f) + { + return STATUS_INVALID_HANDLE; + } + + if (info_class == FilePositionInformation) + { + if (!f->handle) + { + return STATUS_NOT_SUPPORTED; + } + + if (io_status_block) + { + IO_STATUS_BLOCK block{}; + block.Information = sizeof(FILE_POSITION_INFORMATION); + io_status_block.write(block); + } + + if (length != sizeof(FILE_POSITION_INFORMATION)) + { + return STATUS_BUFFER_OVERFLOW; + } + + const emulator_object info{c.emu, file_information}; + const auto i = info.read(); + + if (!f->handle.seek_to(i.CurrentByteOffset.QuadPart)) + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; + } + + printf("Unsupported set file info class: %X\n", info_class); + c.emu.stop(); + + return STATUS_NOT_SUPPORTED; + } + + NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, uint64_t file_handle, + const emulator_object io_status_block, const uint64_t file_information, const uint32_t length, const uint32_t info_class) { + const auto* f = c.proc.files.get(file_handle); + if (!f) + { + return STATUS_INVALID_HANDLE; + } + if (info_class == FileStandardInformation) { if (io_status_block) { - io_status_block.write(sizeof(FILE_STANDARD_INFORMATION)); + IO_STATUS_BLOCK block{}; + block.Information = sizeof(FILE_STANDARD_INFORMATION); + io_status_block.write(block); } if (length != sizeof(FILE_STANDARD_INFORMATION)) @@ -995,15 +1050,49 @@ namespace } const emulator_object info{c.emu, file_information}; - info.access([&](FILE_STANDARD_INFORMATION& i) + FILE_STANDARD_INFORMATION i{}; + i.Directory = f->handle ? FALSE : TRUE; + + if (f->handle) { - memset(&i, 0, sizeof(i)); - }); + i.EndOfFile.QuadPart = f->handle.size(); + } + + info.write(i); return STATUS_SUCCESS; } - printf("Unsupported file info class: %X\n", info_class); + if (info_class == FilePositionInformation) + { + if (!f->handle) + { + return STATUS_NOT_SUPPORTED; + } + + if (io_status_block) + { + IO_STATUS_BLOCK block{}; + block.Information = sizeof(FILE_POSITION_INFORMATION); + io_status_block.write(block); + } + + if (length != sizeof(FILE_POSITION_INFORMATION)) + { + return STATUS_BUFFER_OVERFLOW; + } + + const emulator_object info{c.emu, file_information}; + FILE_POSITION_INFORMATION i{}; + + i.CurrentByteOffset.QuadPart = f->handle.tell(); + + info.write(i); + + return STATUS_SUCCESS; + } + + printf("Unsupported query file info class: %X\n", info_class); c.emu.stop(); return STATUS_NOT_SUPPORTED; @@ -2113,6 +2202,7 @@ void syscall_dispatcher::add_handlers(std::unordered_map