diff --git a/src/common/utils/file_handle.hpp b/src/common/utils/file_handle.hpp index 240cf8ed..f7988e89 100644 --- a/src/common/utils/file_handle.hpp +++ b/src/common/utils/file_handle.hpp @@ -7,6 +7,12 @@ namespace utils { class file_handle { + struct rename_information + { + std::filesystem::path old_filepath; + std::filesystem::path new_filepath; + }; + public: file_handle() = default; @@ -80,8 +86,14 @@ namespace utils return _ftelli64(this->file_); } + void defer_rename(std::filesystem::path oldname, std::filesystem::path newname) + { + deferred_rename_ = {.old_filepath = std::move(oldname), .new_filepath = std::move(newname)}; + } + private: FILE* file_{}; + std::optional deferred_rename_; void release() { @@ -90,6 +102,13 @@ namespace utils (void)fclose(this->file_); this->file_ = {}; } + + if (this->deferred_rename_) + { + std::error_code ec{}; + std::filesystem::rename(this->deferred_rename_->old_filepath, this->deferred_rename_->new_filepath, ec); + this->deferred_rename_ = {}; + } } }; } diff --git a/src/windows-emulator/network/socket_wrapper.cpp b/src/windows-emulator/network/socket_wrapper.cpp index 85d2896b..485a1750 100644 --- a/src/windows-emulator/network/socket_wrapper.cpp +++ b/src/windows-emulator/network/socket_wrapper.cpp @@ -111,7 +111,7 @@ namespace network const auto res = ::recvfrom(this->socket_.get_socket(), reinterpret_cast(data.data()), static_cast(data.size()), 0, &source.get_addr(), &source_length); - assert(source.get_size() == source_length); + assert(res < 0 || source.get_size() == source_length); return res; } diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 714bc7be..cc498e1e 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -132,6 +132,7 @@ namespace syscalls emulator_pointer buffer, ULONG number_of_bytes_to_read, emulator_object number_of_bytes_read); NTSTATUS handle_NtSetInformationVirtualMemory(); + BOOL handle_NtLockVirtualMemory(); // syscalls/mutant.cpp: NTSTATUS handle_NtReleaseMutant(const syscall_context& c, handle mutant_handle, emulator_object previous_count); @@ -961,6 +962,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtQuerySystemInformation); add_handler(NtCreateEvent); add_handler(NtProtectVirtualMemory); + add_handler(NtLockVirtualMemory); add_handler(NtOpenDirectoryObject); add_handler(NtTraceEvent); add_handler(NtAllocateVirtualMemoryEx); diff --git a/src/windows-emulator/syscalls/file.cpp b/src/windows-emulator/syscalls/file.cpp index 12c4df89..4bf4b3fb 100644 --- a/src/windows-emulator/syscalls/file.cpp +++ b/src/windows-emulator/syscalls/file.cpp @@ -51,7 +51,7 @@ namespace syscalls 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); + auto* f = c.proc.files.get(file_handle); if (!f) { if (c.proc.devices.get(file_handle)) @@ -88,7 +88,22 @@ namespace syscalls c.win_emu.log.warn("--> File rename requested: %s --> %s\n", u16_to_u8(f->name).c_str(), u16_to_u8(new_name).c_str()); - return STATUS_ACCESS_DENIED; + std::error_code ec{}; + bool file_exists = std::filesystem::exists(new_name, ec); + + if (ec) + { + return STATUS_ACCESS_DENIED; + } + + if (!info.ReplaceIfExists && file_exists) + { + return STATUS_OBJECT_NAME_EXISTS; + } + + f->handle.defer_rename(c.win_emu.file_sys.translate(f->name), c.win_emu.file_sys.translate(new_name)); + + return STATUS_SUCCESS; } if (info_class == FileBasicInformation) @@ -886,6 +901,12 @@ namespace syscalls return STATUS_SUCCESS; } + if (filename == u"\\??\\CONOUT$") + { + file_handle.write(STDOUT_HANDLE); + return STATUS_SUCCESS; + } + file f{}; f.name = std::move(filename); @@ -1022,8 +1043,19 @@ namespace syscalls return STATUS_INVALID_PARAMETER; } - const auto filename = - read_unicode_string(c.emu, emulator_object>>{c.emu, attributes.ObjectName}); + auto filename = read_unicode_string(c.emu, emulator_object>>{c.emu, attributes.ObjectName}); + + if (attributes.RootDirectory) + { + const auto* root = c.proc.files.get(attributes.RootDirectory); + if (!root) + { + return STATUS_INVALID_HANDLE; + } + + const auto has_separator = root->name.ends_with(u"\\") || root->name.ends_with(u"/"); + filename = root->name + (has_separator ? u"" : u"\\") + filename; + } c.win_emu.callbacks.on_generic_access("Querying file attributes", filename); diff --git a/src/windows-emulator/syscalls/memory.cpp b/src/windows-emulator/syscalls/memory.cpp index cbfd1fb6..a727101c 100644 --- a/src/windows-emulator/syscalls/memory.cpp +++ b/src/windows-emulator/syscalls/memory.cpp @@ -295,4 +295,9 @@ namespace syscalls { return STATUS_NOT_SUPPORTED; } + + BOOL handle_NtLockVirtualMemory() + { + return TRUE; + } } diff --git a/src/windows-emulator/windows_objects.hpp b/src/windows-emulator/windows_objects.hpp index 912bfb46..e2c121b7 100644 --- a/src/windows-emulator/windows_objects.hpp +++ b/src/windows-emulator/windows_objects.hpp @@ -186,6 +186,7 @@ struct file : ref_counted_object utils::file_handle handle{}; std::u16string name{}; std::optional enumeration_state{}; + std::optional deferred_rename; bool is_file() const {