From b6f46454204f03300c7e5c1b32bd55cbd6028233 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 12:40:52 +0200 Subject: [PATCH] Some more syscalls --- src/common/platform/file_management.hpp | 32 +++++++ src/windows-emulator/syscall_utils.hpp | 9 +- src/windows-emulator/syscalls.cpp | 5 + src/windows-emulator/syscalls/file.cpp | 115 +++++++++++++++++++---- src/windows-emulator/syscalls/object.cpp | 12 ++- 5 files changed, 150 insertions(+), 23 deletions(-) diff --git a/src/common/platform/file_management.hpp b/src/common/platform/file_management.hpp index bf43b9d7..0aa70ccf 100644 --- a/src/common/platform/file_management.hpp +++ b/src/common/platform/file_management.hpp @@ -397,6 +397,11 @@ typedef struct _FILE_BOTH_DIR_INFORMATION } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; #ifndef OS_WINDOWS +typedef struct _FILE_ID_128 +{ + BYTE Identifier[16]; +} FILE_ID_128, *PFILE_ID_128; + typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE, *PSECURITY_CONTEXT_TRACKING_MODE; typedef struct _SECURITY_QUALITY_OF_SERVICE { @@ -408,6 +413,27 @@ typedef struct _SECURITY_QUALITY_OF_SERVICE #endif +#ifndef _MSC_VER +typedef struct _FILE_STAT_BASIC_INFORMATION +{ + LARGE_INTEGER FileId; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; + ULONG ReparseTag; + ULONG NumberOfLinks; + ULONG DeviceType; + ULONG DeviceCharacteristics; + ULONG Reserved; + LARGE_INTEGER VolumeSerialNumber; + FILE_ID_128 FileId128; +} FILE_STAT_BASIC_INFORMATION, *PFILE_STAT_BASIC_INFORMATION; +#endif + typedef struct _PORT_VIEW64 { ULONG Length; @@ -425,4 +451,10 @@ typedef struct _REMOTE_PORT_VIEW64 EmulatorTraits::PVOID ViewBase; } REMOTE_PORT_VIEW64, *PREMOTE_PORT_VIEW64; +typedef struct _OBJECT_HANDLE_FLAG_INFORMATION +{ + BOOLEAN Inherit; + BOOLEAN ProtectFromClose; +} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; + // NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) diff --git a/src/windows-emulator/syscall_utils.hpp b/src/windows-emulator/syscall_utils.hpp index a4585d1c..086a4741 100644 --- a/src/windows-emulator/syscall_utils.hpp +++ b/src/windows-emulator/syscall_utils.hpp @@ -217,14 +217,15 @@ NTSTATUS handle_query_internal(x86_64_emulator& emu, const uint64_t buffer, cons return STATUS_SUCCESS; } -template +template + requires(std::is_integral_v) NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length, - const emulator_object return_length, const Action& action) + const emulator_object return_length, const Action& action) { - const auto length_setter = [&](const uint32_t required_size) { + const auto length_setter = [&](const size_t required_size) { if (return_length) { - return_length.write(required_size); + return_length.write(static_cast(required_size)); } }; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 18924636..e30004d4 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -66,6 +66,10 @@ namespace syscalls NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, handle file_handle, emulator_object>> io_status_block, uint64_t file_information, uint32_t length, uint32_t info_class); + NTSTATUS handle_NtQueryInformationByName( + const syscall_context& c, emulator_object>> object_attributes, + emulator_object>> io_status_block, uint64_t file_information, + uint32_t length, uint32_t info_class); NTSTATUS handle_NtReadFile(const syscall_context& c, handle file_handle, uint64_t /*event*/, uint64_t /*apc_routine*/, uint64_t /*apc_context*/, emulator_object>> io_status_block, uint64_t buffer, @@ -1091,6 +1095,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtUserSetProp2); add_handler(NtUserChangeWindowMessageFilterEx); add_handler(NtUserDestroyWindow); + add_handler(NtQueryInformationByName); #undef add_handler } diff --git a/src/windows-emulator/syscalls/file.cpp b/src/windows-emulator/syscalls/file.cpp index 6462e60b..fc323e1f 100644 --- a/src/windows-emulator/syscalls/file.cpp +++ b/src/windows-emulator/syscalls/file.cpp @@ -464,6 +464,98 @@ namespace syscalls return ret(STATUS_NOT_SUPPORTED); } + static std::pair open_file(const file_system& file_sys, const windows_path& path, + const std::u16string& mode) + { + FILE* file{}; + const auto error = open_unicode(&file, file_sys.translate(path), mode); + + if (file) + { + return {file, STATUS_SUCCESS}; + } + + using fh = utils::file_handle; + + switch (error) + { + case ENOENT: + return {fh{}, STATUS_OBJECT_NAME_NOT_FOUND}; + case EACCES: + return {fh{}, STATUS_ACCESS_DENIED}; + case EISDIR: + return {fh{}, STATUS_FILE_IS_A_DIRECTORY}; + default: + return {fh{}, STATUS_NOT_SUPPORTED}; + } + } + + NTSTATUS handle_NtQueryInformationByName( + const syscall_context& c, const emulator_object>> object_attributes, + const emulator_object>> io_status_block, const uint64_t file_information, + const uint32_t length, const uint32_t info_class) + { + IO_STATUS_BLOCK> block{}; + block.Status = STATUS_SUCCESS; + block.Information = 0; + + const auto _ = utils::finally([&] { + if (io_status_block) + { + io_status_block.write(block); + } + }); + + const auto attributes = object_attributes.read(); + auto filename = read_unicode_string(c.emu, attributes.ObjectName); + + c.win_emu.log.print(color::dark_gray, "--> Query file info: %s\n", u16_to_u8(filename).c_str()); // + + const auto ret = [&](const NTSTATUS status) { + block.Status = status; + return status; + }; + + if (info_class == FileStatBasicInformation) + { + block.Information = sizeof(FILE_STAT_BASIC_INFORMATION); + + if (length < block.Information) + { + return ret(STATUS_BUFFER_OVERFLOW); + } + + auto [native_file_handle, status] = open_file(c.win_emu.file_sys, filename, u"r"); + if (status != STATUS_SUCCESS) + { + return ret(status); + } + + struct _stat64 file_stat{}; + if (fstat64(native_file_handle, &file_stat) != 0) + { + return STATUS_INVALID_HANDLE; + } + + FILE_STAT_BASIC_INFORMATION i{}; + + i.CreationTime = utils::convert_unix_to_windows_time(file_stat.st_atime); + i.LastAccessTime = utils::convert_unix_to_windows_time(file_stat.st_atime); + i.LastWriteTime = utils::convert_unix_to_windows_time(file_stat.st_mtime); + i.ChangeTime = i.LastWriteTime; + i.FileAttributes = (file_stat.st_mode & S_IFDIR) != 0 ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; + + c.emu.write_memory(file_information, i); + + return ret(STATUS_SUCCESS); + } + + c.win_emu.log.error("Unsupported query name info class: %X\n", info_class); + c.emu.stop(); + + return ret(STATUS_NOT_SUPPORTED); + } + void commit_file_data(const std::string_view data, emulator& emu, const emulator_object>> io_status_block, const uint64_t buffer) @@ -739,26 +831,13 @@ namespace syscalls return STATUS_NOT_SUPPORTED; } - FILE* file{}; - - const auto error = open_unicode(&file, c.win_emu.file_sys.translate(path), mode); - - if (!file) + auto [native_file_handle, status] = open_file(c.win_emu.file_sys, path, mode); + if (status != STATUS_SUCCESS) { - switch (error) - { - case ENOENT: - return STATUS_OBJECT_NAME_NOT_FOUND; - case EACCES: - return STATUS_ACCESS_DENIED; - case EISDIR: - return STATUS_FILE_IS_A_DIRECTORY; - default: - return STATUS_NOT_SUPPORTED; - } + return status; } - f.handle = file; + f.handle = std::move(native_file_handle); const auto handle = c.proc.files.store(std::move(f)); file_handle.write(handle); @@ -982,4 +1061,4 @@ namespace syscalls (void)fflush(f->handle); return STATUS_SUCCESS; } -} \ No newline at end of file +} diff --git a/src/windows-emulator/syscalls/object.cpp b/src/windows-emulator/syscalls/object.cpp index 7420e43e..024a04b9 100644 --- a/src/windows-emulator/syscalls/object.cpp +++ b/src/windows-emulator/syscalls/object.cpp @@ -99,6 +99,16 @@ namespace syscalls return STATUS_SUCCESS; } + if (object_information_class == ObjectHandleFlagInformation) + { + return handle_query(c.emu, object_information, object_information_length, + return_length, + [&](OBJECT_HANDLE_FLAG_INFORMATION& info) { + info.Inherit = 0; + info.ProtectFromClose = 0; + }); + } + c.win_emu.log.error("Unsupported object info class: %X\n", object_information_class); c.emu.stop(); return STATUS_NOT_SUPPORTED; @@ -176,4 +186,4 @@ namespace syscalls { return STATUS_NOT_SUPPORTED; } -} \ No newline at end of file +}