diff --git a/src/xenia/kernel/fs/devices/host_path_entry.cc b/src/xenia/kernel/fs/devices/host_path_entry.cc index 85b49f4be..48a5883ca 100644 --- a/src/xenia/kernel/fs/devices/host_path_entry.cc +++ b/src/xenia/kernel/fs/devices/host_path_entry.cc @@ -140,9 +140,25 @@ X_STATUS HostPathEntry::Open(KernelState* kernel_state, Mode mode, bool async, // TODO(benvanik): plumb through proper disposition/access mode. DWORD desired_access = is_read_only() ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE); - // mode == Mode::READ ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE); + if (mode == Mode::READ_APPEND) { + desired_access |= FILE_APPEND_DATA; + } DWORD share_mode = FILE_SHARE_READ; - DWORD creation_disposition = mode == Mode::READ ? OPEN_EXISTING : OPEN_ALWAYS; + DWORD creation_disposition; + switch (mode) { + case Mode::READ: + creation_disposition = OPEN_EXISTING; + break; + case Mode::READ_WRITE: + creation_disposition = OPEN_ALWAYS; + break; + case Mode::READ_APPEND: + creation_disposition = OPEN_EXISTING; + break; + default: + assert_unhandled_case(mode); + break; + } DWORD flags_and_attributes = async ? FILE_FLAG_OVERLAPPED : 0; HANDLE file = CreateFile(local_path_.c_str(), desired_access, share_mode, NULL, diff --git a/src/xenia/kernel/fs/entry.h b/src/xenia/kernel/fs/entry.h index 441dcd981..0cb5bacbf 100644 --- a/src/xenia/kernel/fs/entry.h +++ b/src/xenia/kernel/fs/entry.h @@ -35,6 +35,7 @@ class Device; enum class Mode { READ, READ_WRITE, + READ_APPEND, }; class MemoryMapping { diff --git a/src/xenia/kernel/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl_io.cc index f9a747577..4e6723262 100644 --- a/src/xenia/kernel/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl_io.cc @@ -60,10 +60,13 @@ struct FileDisposition { }; struct FileAccess { - static const uint32_t X_GENERIC_READ = 1 << 0; - static const uint32_t X_GENERIC_WRITE = 1 << 1; - static const uint32_t X_GENERIC_EXECUTE = 1 << 2; - static const uint32_t X_GENERIC_ALL = 1 << 3; + static const uint32_t X_GENERIC_READ = 0x80000000; + static const uint32_t X_GENERIC_WRITE = 0x40000000; + static const uint32_t X_GENERIC_EXECUTE = 0x20000000; + static const uint32_t X_GENERIC_ALL = 0x10000000; + static const uint32_t X_FILE_READ_DATA = 0x00000001; + static const uint32_t X_FILE_WRITE_DATA = 0x00000002; + static const uint32_t X_FILE_APPEND_DATA = 0x00000004; }; X_STATUS NtCreateFile(PPCContext* ppc_state, KernelState* state, @@ -100,9 +103,11 @@ X_STATUS NtCreateFile(PPCContext* ppc_state, KernelState* state, entry = fs->ResolvePath(object_name); } - if (creation_disposition != FileDisposition::X_FILE_OPEN || - desired_access & FileAccess::X_GENERIC_WRITE || - desired_access & FileAccess::X_GENERIC_ALL) { + bool wants_write = desired_access & FileAccess::X_GENERIC_WRITE || + desired_access & FileAccess::X_GENERIC_ALL || + desired_access & FileAccess::X_FILE_WRITE_DATA || + desired_access & FileAccess::X_FILE_APPEND_DATA; + if (wants_write) { if (entry && entry->is_read_only()) { // We don't support any write modes. XELOGW("Attempted to open the file/dir for create/write"); @@ -116,10 +121,15 @@ X_STATUS NtCreateFile(PPCContext* ppc_state, KernelState* state, info = X_FILE_DOES_NOT_EXIST; } else { // Open the file/directory. - result = fs->Open(std::move(entry), state, - desired_access & FileAccess::X_GENERIC_WRITE - ? fs::Mode::READ_WRITE - : fs::Mode::READ, + fs::Mode mode; + if (desired_access & FileAccess::X_FILE_APPEND_DATA) { + mode = fs::Mode::READ_APPEND; + } else if (wants_write) { + mode = fs::Mode::READ_WRITE; + } else { + mode = fs::Mode::READ; + } + result = fs->Open(std::move(entry), state, mode, false, // TODO(benvanik): pick async mode, if needed. &file); }