Fixes to some file syscalls and improve handling of NtCreateKey (#311)

This PR aims to:
- [Add a new device to
create_device](75ee63803c).
- [Improve handling of
NtCreateKey](4888142d22),
to be more specific, it now opens keys that already exist.
- [Fix some issues in some file
syscalls](3e1f206bc0).
This commit is contained in:
Maurice Heumann
2025-05-21 07:42:42 +02:00
committed by GitHub
4 changed files with 71 additions and 12 deletions

View File

@@ -18,6 +18,7 @@ std::unique_ptr<io_device> create_device(const std::u16string_view device)
{
if (device == u"CNG" //
|| device == u"Nsi" //
|| device == u"RasAcd" //
|| device == u"KsecDD" //
|| device == u"PcwDrv" //
|| device == u"DeviceApi\\CMApi" //

View File

@@ -236,7 +236,11 @@ namespace syscalls
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> value_name,
KEY_VALUE_INFORMATION_CLASS key_value_information_class,
uint64_t key_value_information, ULONG length, emulator_object<ULONG> result_length);
NTSTATUS handle_NtCreateKey();
NTSTATUS handle_NtCreateKey(const syscall_context& c, emulator_object<handle> key_handle,
ACCESS_MASK desired_access,
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
ULONG /*title_index*/, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/,
ULONG /*create_options*/, emulator_object<ULONG> /*disposition*/);
NTSTATUS handle_NtNotifyChangeKey();
NTSTATUS handle_NtSetInformationKey();
NTSTATUS handle_NtEnumerateKey(const syscall_context& c, handle key_handle, ULONG index,

View File

@@ -9,6 +9,12 @@
#include <sys/stat.h>
#if defined(OS_WINDOWS)
#define fstat64 _fstat64
#elif defined(OS_MAC)
#define fstat64 fstat
#endif
namespace syscalls
{
NTSTATUS handle_NtSetInformationFile(const syscall_context& c, const handle file_handle,
@@ -115,7 +121,8 @@ namespace syscalls
files.emplace_back(file_entry{.file_path = "..", .is_directory = true});
}
for (const auto& file : std::filesystem::directory_iterator(dir))
std::error_code ec{};
for (const auto& file : std::filesystem::directory_iterator(dir, ec))
{
if (!file_mask.empty() && !utils::wildcard::match_filename(file.path().filename().u16string(), file_mask))
{
@@ -363,6 +370,35 @@ namespace syscalls
return ret(STATUS_SUCCESS);
}
if (info_class == FileBasicInformation)
{
block.Information = sizeof(FILE_BASIC_INFORMATION);
if (length < block.Information)
{
return ret(STATUS_BUFFER_OVERFLOW);
}
struct _stat64 file_stat{};
if (fstat64(f->handle, &file_stat) != 0)
{
return STATUS_INVALID_HANDLE;
}
const emulator_object<FILE_BASIC_INFORMATION> info{c.emu, file_information};
FILE_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;
info.write(i);
return ret(STATUS_SUCCESS);
}
if (info_class == FilePositionInformation)
{
if (!f->handle)
@@ -411,6 +447,11 @@ namespace syscalls
return ret(STATUS_SUCCESS);
}
if (info_class == FileAllInformation)
{
return ret(STATUS_NOT_SUPPORTED);
}
c.win_emu.log.error("Unsupported query file info class: %X\n", info_class);
c.emu.stop();
@@ -654,8 +695,10 @@ namespace syscalls
printer.cancel();
std::error_code ec{};
const windows_path path = f.name;
const bool is_directory = std::filesystem::is_directory(c.win_emu.file_sys.translate(path));
const bool is_directory = std::filesystem::is_directory(c.win_emu.file_sys.translate(path), ec);
if (is_directory || create_options & FILE_DIRECTORY_FILE)
{
@@ -663,7 +706,6 @@ namespace syscalls
if (create_disposition & FILE_CREATE)
{
std::error_code ec{};
create_directory(c.win_emu.file_sys.translate(path), ec);
if (ec)
@@ -750,10 +792,10 @@ namespace syscalls
c.win_emu.log.print(color::dark_gray, "--> Querying file attributes: %s\n", u16_to_u8(filename).c_str());
const auto local_filename = c.win_emu.file_sys.translate(filename).string();
const auto local_filename = c.win_emu.file_sys.translate(filename).u8string();
struct _stat64 file_stat{};
if (_stat64(local_filename.c_str(), &file_stat) != 0)
if (_stat64(reinterpret_cast<const char*>(local_filename.c_str()), &file_stat) != 0)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -765,7 +807,7 @@ namespace syscalls
info.AllocationSize.QuadPart = file_stat.st_size;
info.EndOfFile.QuadPart = file_stat.st_size;
info.ChangeTime = info.LastWriteTime;
info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
info.FileAttributes = (file_stat.st_mode & S_IFDIR) != 0 ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
});
return STATUS_SUCCESS;
@@ -791,10 +833,10 @@ namespace syscalls
c.win_emu.log.print(color::dark_gray, "--> Querying file attributes: %s\n", u16_to_u8(filename).c_str());
const auto local_filename = c.win_emu.file_sys.translate(filename).string();
const auto local_filename = c.win_emu.file_sys.translate(filename).u8string();
struct _stat64 file_stat{};
if (_stat64(local_filename.c_str(), &file_stat) != 0)
if (_stat64(reinterpret_cast<const char*>(local_filename.c_str()), &file_stat) != 0)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -804,7 +846,7 @@ namespace syscalls
info.LastAccessTime = utils::convert_unix_to_windows_time(file_stat.st_atime);
info.LastWriteTime = utils::convert_unix_to_windows_time(file_stat.st_mtime);
info.ChangeTime = info.LastWriteTime;
info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
info.FileAttributes = (file_stat.st_mode & S_IFDIR) != 0 ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
});
return STATUS_SUCCESS;

View File

@@ -227,9 +227,21 @@ namespace syscalls
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtCreateKey()
NTSTATUS handle_NtCreateKey(const syscall_context& c, const emulator_object<handle> key_handle,
const ACCESS_MASK desired_access,
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
const ULONG /*title_index*/,
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/,
const ULONG /*create_options*/, const emulator_object<ULONG> /*disposition*/)
{
return STATUS_NOT_SUPPORTED;
const auto result = handle_NtOpenKey(c, key_handle, desired_access, object_attributes);
if (result == STATUS_OBJECT_NAME_NOT_FOUND)
{
return STATUS_NOT_SUPPORTED;
}
return result;
}
NTSTATUS handle_NtNotifyChangeKey()