From ffd7058bec4b76ee58ef9a86c8f873e458c534e0 Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Sun, 11 Jan 2026 17:07:34 -0300 Subject: [PATCH] Fix NtCreateFile's create_disposition behavior --- src/common/platform/status.hpp | 1 + src/windows-emulator/syscalls/file.cpp | 26 ++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/common/platform/status.hpp b/src/common/platform/status.hpp index 14c9e6c3..1fb015b9 100644 --- a/src/common/platform/status.hpp +++ b/src/common/platform/status.hpp @@ -43,6 +43,7 @@ using NTSTATUS = std::uint32_t; #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L) +#define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS)0xC0000035L) #define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS)0xC0000045L) #define STATUS_MUTANT_NOT_OWNED ((NTSTATUS)0xC0000046L) #define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS)0xC0000047L) diff --git a/src/windows-emulator/syscalls/file.cpp b/src/windows-emulator/syscalls/file.cpp index 77e2e73c..7dee4148 100644 --- a/src/windows-emulator/syscalls/file.cpp +++ b/src/windows-emulator/syscalls/file.cpp @@ -1020,7 +1020,8 @@ namespace syscalls return STATUS_OBJECT_NAME_NOT_FOUND; } - const bool is_directory = std::filesystem::is_directory(c.win_emu.file_sys.translate(path), ec); + const auto host_path = c.win_emu.file_sys.translate(path); + const bool is_directory = std::filesystem::is_directory(host_path, ec); if (is_directory || create_options & FILE_DIRECTORY_FILE) { @@ -1028,7 +1029,7 @@ namespace syscalls if (create_disposition & FILE_CREATE) { - create_directory(c.win_emu.file_sys.translate(path), ec); + create_directory(host_path, ec); if (ec) { @@ -1048,6 +1049,27 @@ namespace syscalls c.win_emu.callbacks.on_generic_access("Opening file", f.name); + const bool file_exists = std::filesystem::exists(host_path, ec); + + if (create_disposition == FILE_CREATE && file_exists) + { + return STATUS_OBJECT_NAME_COLLISION; + } + + if ((create_disposition == FILE_OVERWRITE || create_disposition == FILE_OPEN) && !file_exists) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (create_disposition == FILE_OPEN_IF && !file_exists) + { + std::ofstream touch(host_path, std::ios::binary | std::ios::app); + if (!touch) + { + return STATUS_ACCESS_DENIED; + } + } + std::u16string mode = map_mode(desired_access, create_disposition); if (mode.empty() || path.is_relative())