NtCreateFile - Return error while trying to create directory with non-directory flag

This commit is contained in:
Gliniak 2020-08-02 17:09:32 +02:00
parent 749a59e424
commit 6fe668724e
5 changed files with 34 additions and 20 deletions

View File

@ -27,18 +27,6 @@ namespace xe {
namespace kernel {
namespace xboxkrnl {
struct CreateOptions {
// https://processhacker.sourceforge.io/doc/ntioapi_8h.html
static const uint32_t FILE_DIRECTORY_FILE = 0x00000001;
// Optimization - files access will be sequential, not random.
static const uint32_t FILE_SEQUENTIAL_ONLY = 0x00000004;
static const uint32_t FILE_SYNCHRONOUS_IO_ALERT = 0x00000010;
static const uint32_t FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020;
static const uint32_t FILE_NON_DIRECTORY_FILE = 0x00000040;
// Optimization - file access will be random, not sequential.
static const uint32_t FILE_RANDOM_ACCESS = 0x00000800;
};
static bool IsValidPath(const std::string_view s, bool is_pattern) {
// TODO(gibbed): validate path components individually
for (const auto& c : s) {
@ -126,16 +114,15 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
X_STATUS result = kernel_state()->file_system()->OpenFile(
root_entry, target_path,
vfs::FileDisposition((uint32_t)creation_disposition), desired_access,
(create_options & CreateOptions::FILE_DIRECTORY_FILE) != 0, &vfs_file,
&file_action);
create_options, &vfs_file, &file_action);
object_ref<XFile> file = nullptr;
X_HANDLE handle = X_INVALID_HANDLE_VALUE;
if (XSUCCEEDED(result)) {
// If true, desired_access SYNCHRONIZE flag must be set.
bool synchronous =
(create_options & CreateOptions::FILE_SYNCHRONOUS_IO_ALERT) ||
(create_options & CreateOptions::FILE_SYNCHRONOUS_IO_NONALERT);
(create_options & vfs::CreateOptions::FILE_SYNCHRONOUS_IO_ALERT) ||
(create_options & vfs::CreateOptions::FILE_SYNCHRONOUS_IO_NONALERT);
file = object_ref<XFile>(new XFile(kernel_state(), vfs_file, synchronous));
// Handle ref is incremented, so return that.

View File

@ -258,12 +258,17 @@ object_ref<XFile> XFile::Restore(KernelState* kernel_state,
auto is_directory = stream->Read<bool>();
auto is_synchronous = stream->Read<bool>();
uint32_t create_options = 0;
if (is_directory) {
create_options |= vfs::CreateOptions::FILE_DIRECTORY_FILE;
}
XELOGD("XFile {:08X} ({})", file->handle(), abs_path);
vfs::File* vfs_file = nullptr;
vfs::FileAction action;
auto res = kernel_state->file_system()->OpenFile(
nullptr, abs_path, vfs::FileDisposition::kOpen, access, is_directory,
nullptr, abs_path, vfs::FileDisposition::kOpen, access, create_options,
&vfs_file, &action);
if (XFAILED(res)) {
XELOGE("Failed to open XFile: error {:08X}", res);

View File

@ -17,6 +17,18 @@
namespace xe {
namespace vfs {
struct CreateOptions {
// https://processhacker.sourceforge.io/doc/ntioapi_8h.html
static const uint32_t FILE_DIRECTORY_FILE = 0x00000001;
// Optimization - files access will be sequential, not random.
static const uint32_t FILE_SEQUENTIAL_ONLY = 0x00000004;
static const uint32_t FILE_SYNCHRONOUS_IO_ALERT = 0x00000010;
static const uint32_t FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020;
static const uint32_t FILE_NON_DIRECTORY_FILE = 0x00000040;
// Optimization - file access will be random, not sequential.
static const uint32_t FILE_RANDOM_ACCESS = 0x00000800;
};
class Entry;
class File {

View File

@ -173,7 +173,7 @@ bool VirtualFileSystem::DeletePath(const std::string_view path) {
X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry,
const std::string_view path,
FileDisposition creation_disposition,
uint32_t desired_access, bool is_directory,
uint32_t desired_access, uint32_t create_options,
File** out_file, FileAction* out_action) {
// TODO(gibbed): should 'is_directory' remain as a bool or should it be
// flipped to a generic FileAttributeFlags?
@ -189,11 +189,21 @@ X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry,
desired_access |= FileAccess::kFileReadData | FileAccess::kFileWriteData;
}
bool is_directory = create_options & CreateOptions::FILE_DIRECTORY_FILE;
// Lookup host device/parent path.
// If no device or parent, fail.
Entry* parent_entry = nullptr;
Entry* entry = nullptr;
auto path_entry = ResolvePath(path);
if (path_entry) {
if (path_entry->attributes() & kFileAttributeDirectory &&
create_options & CreateOptions::FILE_NON_DIRECTORY_FILE) {
return X_STATUS_FILE_IS_A_DIRECTORY;
}
}
auto base_path = xe::utf8::find_base_guest_path(path);
if (!base_path.empty()) {
parent_entry = !root_entry ? ResolvePath(base_path)

View File

@ -46,8 +46,8 @@ class VirtualFileSystem {
X_STATUS OpenFile(Entry* root_entry, const std::string_view path,
FileDisposition creation_disposition,
uint32_t desired_access, bool is_directory, File** out_file,
FileAction* out_action);
uint32_t desired_access, uint32_t create_options,
File** out_file, FileAction* out_action);
private:
xe::global_critical_region global_critical_region_;