diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.cc b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.cc index 7d16ed11d..4a7bc7b7f 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.cc +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.cc @@ -70,15 +70,8 @@ MemoryMapping* DiscImageEntry::CreateMemoryMapping( X_STATUS DiscImageEntry::Open( KernelState* kernel_state, - /* mode etc */ + uint32_t desired_access, bool async, XFile** out_file) { - //*out_file = new DiscImageFile... - return X_STATUS_NOT_IMPLEMENTED; + *out_file = new DiscImageFile(kernel_state, desired_access, this); + return X_STATUS_SUCCESS; } -/* size_t real_offset = gdfx_entry_->offset + byte_offset; - size_t real_length = MIN(buffer_length, gdfx_entry_->size - byte_offset); - xe_copy_memory( - buffer, buffer_length, - xe_mmap_get_addr(mmap_) + real_offset, real_length); - *out_bytes_read = real_length; - return X_STATUS_SUCCESS;*/ diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.h b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.h index db8f18f70..abe42efae 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.h +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_entry.h @@ -30,12 +30,15 @@ public: xe_mmap_ref mmap, GDFXEntry* gdfx_entry); virtual ~DiscImageEntry(); + xe_mmap_ref mmap() const { return mmap_; } + GDFXEntry* gdfx_entry() const { return gdfx_entry_; } + virtual MemoryMapping* CreateMemoryMapping( xe_file_mode file_mode, const size_t offset, const size_t length); virtual X_STATUS Open( KernelState* kernel_state, - /* mode etc */ + uint32_t desired_access, bool async, XFile** out_file); private: diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.cc b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.cc index 4aa450d04..b848c0ffe 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.cc +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.cc @@ -9,6 +9,7 @@ #include +#include #include @@ -18,10 +19,26 @@ using namespace xe::kernel::xboxkrnl; using namespace xe::kernel::xboxkrnl::fs; -DiscImageFile::DiscImageFile(KernelState* kernel_state, DiscImageEntry* entry) : +DiscImageFile::DiscImageFile( + KernelState* kernel_state, uint32_t desired_access, + DiscImageEntry* entry) : entry_(entry), - XFile(kernel_state) { + XFile(kernel_state, desired_access) { } DiscImageFile::~DiscImageFile() { } + +X_STATUS DiscImageFile::ReadSync( + void* buffer, size_t buffer_length, size_t byte_offset, + size_t* out_bytes_read) { + GDFXEntry* gdfx_entry = entry_->gdfx_entry(); + xe_mmap_ref mmap = entry_->mmap(); + size_t real_offset = gdfx_entry->offset + byte_offset; + size_t real_length = MIN(buffer_length, gdfx_entry->size - byte_offset); + xe_copy_memory( + buffer, buffer_length, + xe_mmap_get_addr(mmap) + real_offset, real_length); + *out_bytes_read = real_length; + return X_STATUS_SUCCESS; +} diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.h b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.h index c2b02e587..fd18d78cf 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.h +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.h @@ -26,9 +26,16 @@ class DiscImageEntry; class DiscImageFile : public XFile { public: - DiscImageFile(KernelState* kernel_state, DiscImageEntry* entry); + DiscImageFile(KernelState* kernel_state, uint32_t desired_access, + DiscImageEntry* entry); virtual ~DiscImageFile(); + +protected: + virtual X_STATUS ReadSync( + void* buffer, size_t buffer_length, size_t byte_offset, + size_t* out_bytes_read); + private: DiscImageEntry* entry_; }; diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.cc b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.cc index 4d0619db7..c3c21afc7 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.cc +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.cc @@ -65,7 +65,24 @@ MemoryMapping* HostPathEntry::CreateMemoryMapping( X_STATUS HostPathEntry::Open( KernelState* kernel_state, + uint32_t desired_access, bool async, XFile** out_file) { - //*out_file = new DiscImageFile... - return X_STATUS_NOT_IMPLEMENTED; + DWORD share_mode = FILE_SHARE_READ; + DWORD creation_disposition = OPEN_EXISTING; + DWORD flags_and_attributes = async ? FILE_FLAG_OVERLAPPED : 0; + HANDLE file = CreateFile( + local_path_, + desired_access, + share_mode, + NULL, + creation_disposition, + flags_and_attributes, + NULL); + if (!file) { + // TODO(benvanik): pick correct response. + return X_STATUS_ACCESS_DENIED; + } + + *out_file = new HostPathFile(kernel_state, desired_access, this, file); + return X_STATUS_SUCCESS; } diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.h b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.h index 9e1920e09..fe3c88b23 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.h +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_entry.h @@ -35,6 +35,7 @@ public: virtual X_STATUS Open( KernelState* kernel_state, + uint32_t desired_access, bool async, XFile** out_file); private: diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.cc b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.cc index 28f6992cc..967bbe459 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.cc +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.cc @@ -18,10 +18,30 @@ using namespace xe::kernel::xboxkrnl; using namespace xe::kernel::xboxkrnl::fs; -HostPathFile::HostPathFile(KernelState* kernel_state, HostPathEntry* entry) : - entry_(entry), - XFile(kernel_state) { +HostPathFile::HostPathFile( + KernelState* kernel_state, uint32_t desired_access, + HostPathEntry* entry, HANDLE file_handle) : + entry_(entry), file_handle_(file_handle), + XFile(kernel_state, desired_access) { } HostPathFile::~HostPathFile() { + CloseHandle(file_handle_); } + +X_STATUS HostPathFile::ReadSync( + void* buffer, size_t buffer_length, size_t byte_offset, + size_t* out_bytes_read) { + OVERLAPPED overlapped; + overlapped.Pointer = (PVOID)byte_offset; + overlapped.hEvent = NULL; + DWORD bytes_read = 0; + BOOL read = ReadFile( + file_handle_, buffer, (DWORD)buffer_length, &bytes_read, &overlapped); + if (read) { + *out_bytes_read = bytes_read; + return X_STATUS_SUCCESS; + } else { + return X_STATUS_UNSUCCESSFUL; + } +} diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.h b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.h index 46c337fcd..6ee18757a 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.h +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.h @@ -26,11 +26,18 @@ class HostPathEntry; class HostPathFile : public XFile { public: - HostPathFile(KernelState* kernel_state, HostPathEntry* entry); + HostPathFile(KernelState* kernel_state, uint32_t desired_access, + HostPathEntry* entry, HANDLE file_handle); virtual ~HostPathFile(); +protected: + virtual X_STATUS ReadSync( + void* buffer, size_t buffer_length, size_t byte_offset, + size_t* out_bytes_read); + private: HostPathEntry* entry_; + HANDLE file_handle_; }; diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/entry.h b/src/xenia/kernel/modules/xboxkrnl/fs/entry.h index 771129a29..be1ed24af 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/entry.h +++ b/src/xenia/kernel/modules/xboxkrnl/fs/entry.h @@ -59,7 +59,8 @@ public: xe_file_mode file_mode, const size_t offset, const size_t length) = 0; virtual X_STATUS Open( - KernelState* kernel_state, + KernelState* kernel_state, + uint32_t desired_access, bool async, XFile** out_file) = 0; private: diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc index 625719f66..ee4484994 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc @@ -18,8 +18,8 @@ using namespace xe::kernel; using namespace xe::kernel::xboxkrnl; -XFile::XFile(KernelState* kernel_state) : - position_(0), +XFile::XFile(KernelState* kernel_state, uint32_t desired_access) : + desired_access_(desired_access), position_(0), XObject(kernel_state, kTypeFile) { async_event_ = new XEvent(kernel_state); async_event_->Initialize(false, false); @@ -42,12 +42,12 @@ X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset, size_t* out_bytes_read) { if (byte_offset == -1) { // Read from current position. + byte_offset = position_; + } + X_STATUS result = ReadSync(buffer, buffer_length, byte_offset, out_bytes_read); + if (XSUCCEEDED(result)) { + position_ += *out_bytes_read; } - // X_STATUS result = entry_->Read(buffer, buffer_length, byte_offset, out_bytes_read); - // if (XSUCCEEDED(result)) { - // position_ += *out_bytes_read; - // } - X_STATUS result = X_STATUS_NOT_IMPLEMENTED; return result; } @@ -56,7 +56,7 @@ X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset, // Also tack on our event so that any waiters wake. request->AddWaitEvent(async_event_); position_ = byte_offset; - //return entry_->Read(buffer, buffer_length, byte_offset, request); + //return entry_->ReadAsync(buffer, buffer_length, byte_offset, request); X_STATUS result = X_STATUS_NOT_IMPLEMENTED; return result; } diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h index 1e7ef4361..efe99325f 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h @@ -25,23 +25,24 @@ class XEvent; class XFile : public XObject { public: - XFile(KernelState* kernel_state); + XFile(KernelState* kernel_state, uint32_t desired_access); virtual ~XFile(); virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode, uint32_t alertable, uint64_t* opt_timeout); - // TODO(benvanik): Create/Open - X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset, size_t* out_bytes_read); X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset, XAsyncRequest* request); protected: - // open/read/write/etc + virtual X_STATUS ReadSync( + void* buffer, size_t buffer_length, size_t byte_offset, + size_t* out_bytes_read) = 0; private: + uint32_t desired_access_; XEvent* async_event_; // TODO(benvanik): create flags, open state, etc. diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc index 1bdf15b49..310833e58 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc @@ -80,7 +80,11 @@ SHIM_CALL NtCreateFile_shim( XFile* file = NULL; if (entry && entry->type() == Entry::kTypeFile) { // Open the file. - result = entry->Open(state, &file); + result = entry->Open( + state, + desired_access, + false, // TODO(benvanik): pick async mode, if needed. + &file); } else { result = X_STATUS_NO_SUCH_FILE; info = X_FILE_DOES_NOT_EXIST;