diff --git a/src/xenia/kernel/fs/devices/disc_image_entry.cc b/src/xenia/kernel/fs/devices/disc_image_entry.cc index 2b4b51834..72573d1b3 100644 --- a/src/xenia/kernel/fs/devices/disc_image_entry.cc +++ b/src/xenia/kernel/fs/devices/disc_image_entry.cc @@ -110,6 +110,16 @@ X_STATUS DiscImageEntry::QueryDirectory( return X_STATUS_SUCCESS; } +X_STATUS DiscImageEntry::QueryVolume(XVolumeInfo* out_info, size_t length) { + XEASSERTALWAYS(); + return X_STATUS_NOT_IMPLEMENTED; +} + +X_STATUS DiscImageEntry::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) { + XEASSERTALWAYS(); + return X_STATUS_NOT_IMPLEMENTED; +} + MemoryMapping* DiscImageEntry::CreateMemoryMapping( xe_file_mode file_mode, const size_t offset, const size_t length) { if (file_mode & kXEFileModeWrite) { diff --git a/src/xenia/kernel/fs/devices/disc_image_entry.h b/src/xenia/kernel/fs/devices/disc_image_entry.h index 4ed31b5ef..913ff9df0 100644 --- a/src/xenia/kernel/fs/devices/disc_image_entry.h +++ b/src/xenia/kernel/fs/devices/disc_image_entry.h @@ -35,6 +35,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info); virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart); + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length); + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length); virtual bool can_map() { return true; } virtual MemoryMapping* CreateMemoryMapping( diff --git a/src/xenia/kernel/fs/devices/disc_image_file.cc b/src/xenia/kernel/fs/devices/disc_image_file.cc index 11f1d5bc3..8022606c8 100644 --- a/src/xenia/kernel/fs/devices/disc_image_file.cc +++ b/src/xenia/kernel/fs/devices/disc_image_file.cc @@ -49,6 +49,14 @@ X_STATUS DiscImageFile::QueryDirectory(XDirectoryInfo* out_info, return entry_->QueryDirectory(out_info, length, file_name, restart); } +X_STATUS DiscImageFile::QueryVolume(XVolumeInfo* out_info, size_t length) { + return entry_->QueryVolume(out_info, length); +} + +X_STATUS DiscImageFile::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) { + return entry_->QueryFileSystemAttributes(out_info, length); +} + X_STATUS DiscImageFile::ReadSync( void* buffer, size_t buffer_length, size_t byte_offset, size_t* out_bytes_read) { diff --git a/src/xenia/kernel/fs/devices/disc_image_file.h b/src/xenia/kernel/fs/devices/disc_image_file.h index 2671e0420..b43f89863 100644 --- a/src/xenia/kernel/fs/devices/disc_image_file.h +++ b/src/xenia/kernel/fs/devices/disc_image_file.h @@ -36,6 +36,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info); virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart); + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length); + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length); protected: virtual X_STATUS ReadSync( diff --git a/src/xenia/kernel/fs/devices/host_path_entry.cc b/src/xenia/kernel/fs/devices/host_path_entry.cc index 037563625..b07e81426 100644 --- a/src/xenia/kernel/fs/devices/host_path_entry.cc +++ b/src/xenia/kernel/fs/devices/host_path_entry.cc @@ -140,6 +140,43 @@ X_STATUS HostPathEntry::QueryDirectory( return X_STATUS_SUCCESS; } +// TODO(gibbed): call into HostPathDevice? +X_STATUS HostPathEntry::QueryVolume(XVolumeInfo* out_info, size_t length) { + XEASSERTNOTNULL(out_info); + const char* name = "test"; // TODO(gibbed): actual value + + auto end = (uint8_t*)out_info + length; + size_t name_length = strlen(name); + if (((uint8_t*)&out_info->label[0]) + name_length > end) { + return X_STATUS_BUFFER_OVERFLOW; + } + + out_info->creation_time = 0; + out_info->serial_number = 12345678; + out_info->supports_objects = 0; + out_info->label_length = (uint32_t)name_length; + memcpy(out_info->label, name, name_length); + return X_STATUS_SUCCESS; +} + +// TODO(gibbed): call into HostPathDevice? +X_STATUS HostPathEntry::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) { + XEASSERTNOTNULL(out_info); + const char* name = "test"; // TODO(gibbed): actual value + + auto end = (uint8_t*)out_info + length; + size_t name_length = strlen(name); + if (((uint8_t*)&out_info->fs_name[0]) + name_length > end) { + return X_STATUS_BUFFER_OVERFLOW; + } + + out_info->attributes = 0; + out_info->maximum_component_name_length = 255; // TODO(gibbed): actual value + out_info->fs_name_length = (uint32_t)name_length; + memcpy(out_info->fs_name, name, name_length); + return X_STATUS_SUCCESS; +} + MemoryMapping* HostPathEntry::CreateMemoryMapping( xe_file_mode file_mode, const size_t offset, const size_t length) { xe_mmap_ref mmap = xe_mmap_open(file_mode, local_path_, offset, length); diff --git a/src/xenia/kernel/fs/devices/host_path_entry.h b/src/xenia/kernel/fs/devices/host_path_entry.h index 3406033b0..9af676327 100644 --- a/src/xenia/kernel/fs/devices/host_path_entry.h +++ b/src/xenia/kernel/fs/devices/host_path_entry.h @@ -32,6 +32,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info); virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart); + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length); + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length); virtual bool can_map() { return true; } virtual MemoryMapping* CreateMemoryMapping( diff --git a/src/xenia/kernel/fs/devices/host_path_file.cc b/src/xenia/kernel/fs/devices/host_path_file.cc index 4dda9cb0b..7f304caae 100644 --- a/src/xenia/kernel/fs/devices/host_path_file.cc +++ b/src/xenia/kernel/fs/devices/host_path_file.cc @@ -49,6 +49,14 @@ X_STATUS HostPathFile::QueryDirectory(XDirectoryInfo* out_info, return entry_->QueryDirectory(out_info, length, file_name, restart); } +X_STATUS HostPathFile::QueryVolume(XVolumeInfo* out_info, size_t length) { + return entry_->QueryVolume(out_info, length); +} + +X_STATUS HostPathFile::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) { + return entry_->QueryFileSystemAttributes(out_info, length); +} + X_STATUS HostPathFile::ReadSync( void* buffer, size_t buffer_length, size_t byte_offset, size_t* out_bytes_read) { diff --git a/src/xenia/kernel/fs/devices/host_path_file.h b/src/xenia/kernel/fs/devices/host_path_file.h index 797ee552b..e759ba763 100644 --- a/src/xenia/kernel/fs/devices/host_path_file.h +++ b/src/xenia/kernel/fs/devices/host_path_file.h @@ -36,6 +36,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info); virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart); + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length); + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length); protected: virtual X_STATUS ReadSync( diff --git a/src/xenia/kernel/fs/devices/stfs_container_entry.cc b/src/xenia/kernel/fs/devices/stfs_container_entry.cc index a91d1234b..16da2db05 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_entry.cc +++ b/src/xenia/kernel/fs/devices/stfs_container_entry.cc @@ -88,6 +88,16 @@ X_STATUS STFSContainerEntry::QueryDirectory( return X_STATUS_SUCCESS; } +X_STATUS STFSContainerEntry::QueryVolume(XVolumeInfo* out_info, size_t length) { + XEASSERTALWAYS(); + return X_STATUS_NOT_IMPLEMENTED; +} + +X_STATUS STFSContainerEntry::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) { + XEASSERTALWAYS(); + return X_STATUS_NOT_IMPLEMENTED; +} + X_STATUS STFSContainerEntry::Open( KernelState* kernel_state, uint32_t desired_access, bool async, diff --git a/src/xenia/kernel/fs/devices/stfs_container_entry.h b/src/xenia/kernel/fs/devices/stfs_container_entry.h index 2f9129595..40d77e848 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_entry.h +++ b/src/xenia/kernel/fs/devices/stfs_container_entry.h @@ -35,6 +35,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info); virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart); + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length); + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length); virtual X_STATUS Open( KernelState* kernel_state, diff --git a/src/xenia/kernel/fs/devices/stfs_container_file.cc b/src/xenia/kernel/fs/devices/stfs_container_file.cc index dba66e10c..a2e434fdc 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_file.cc +++ b/src/xenia/kernel/fs/devices/stfs_container_file.cc @@ -44,11 +44,19 @@ X_STATUS STFSContainerFile::QueryInfo(XFileInfo* out_info) { return entry_->QueryInfo(out_info); } +X_STATUS STFSContainerFile::QueryVolume(XVolumeInfo* out_info, size_t length) { + return entry_->QueryVolume(out_info, length); +} + X_STATUS STFSContainerFile::QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart) { return entry_->QueryDirectory(out_info, length, file_name, restart); } +X_STATUS STFSContainerFile::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) { + return entry_->QueryFileSystemAttributes(out_info, length); +} + X_STATUS STFSContainerFile::ReadSync( void* buffer, size_t buffer_length, size_t byte_offset, size_t* out_bytes_read) { diff --git a/src/xenia/kernel/fs/devices/stfs_container_file.h b/src/xenia/kernel/fs/devices/stfs_container_file.h index 3f3bc30b1..778404eaf 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_file.h +++ b/src/xenia/kernel/fs/devices/stfs_container_file.h @@ -36,6 +36,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info); virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart); + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length); + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length); protected: virtual X_STATUS ReadSync( diff --git a/src/xenia/kernel/fs/entry.h b/src/xenia/kernel/fs/entry.h index 29a7ba341..7471bbc19 100644 --- a/src/xenia/kernel/fs/entry.h +++ b/src/xenia/kernel/fs/entry.h @@ -20,6 +20,8 @@ XEDECLARECLASS2(xe, kernel, KernelState); XEDECLARECLASS2(xe, kernel, XFile); XEDECLARECLASS2(xe, kernel, XFileInfo); XEDECLARECLASS2(xe, kernel, XDirectoryInfo); +XEDECLARECLASS2(xe, kernel, XVolumeInfo); +XEDECLARECLASS2(xe, kernel, XFileSystemAttributeInfo); namespace xe { @@ -62,6 +64,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info) = 0; virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart) = 0; + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length) = 0; + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) = 0; virtual bool can_map() { return false; } virtual MemoryMapping* CreateMemoryMapping( diff --git a/src/xenia/kernel/objects/xfile.h b/src/xenia/kernel/objects/xfile.h index 5213e6fdd..9eafe88fe 100644 --- a/src/xenia/kernel/objects/xfile.h +++ b/src/xenia/kernel/objects/xfile.h @@ -83,6 +83,46 @@ public: }; XEASSERTSTRUCTSIZE(XDirectoryInfo, 72); +// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540287(v=vs.85).aspx +class XVolumeInfo { +public: + // FILE_FS_VOLUME_INFORMATION + uint64_t creation_time; + uint32_t serial_number; + uint32_t label_length; + uint32_t supports_objects; + char label[1]; + + void Write(uint8_t* base, uint32_t p) { + uint8_t* dst = base + p; + XESETUINT64BE(dst + 0, this->creation_time); + XESETUINT32BE(dst + 8, this->serial_number); + XESETUINT32BE(dst + 12, this->label_length); + XESETUINT32BE(dst + 16, this->supports_objects); + xe_copy_memory(dst + 20, this->label_length, this->label, this->label_length); + } +}; +XEASSERTSTRUCTSIZE(XVolumeInfo, 24); + +// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540251(v=vs.85).aspx +class XFileSystemAttributeInfo { +public: + // FILE_FS_ATTRIBUTE_INFORMATION + uint32_t attributes; + int32_t maximum_component_name_length; + uint32_t fs_name_length; + char fs_name[1]; + + void Write(uint8_t* base, uint32_t p) { + uint8_t* dst = base + p; + XESETUINT32BE(dst + 0, this->attributes); + XESETUINT32BE(dst + 4, this->maximum_component_name_length); + XESETUINT32BE(dst + 8, this->fs_name_length); + xe_copy_memory(dst + 12, this->fs_name_length, this->fs_name, this->fs_name_length); + } +}; +XEASSERTSTRUCTSIZE(XFileSystemAttributeInfo, 16); + class XFile : public XObject { public: virtual ~XFile(); @@ -97,6 +137,8 @@ public: virtual X_STATUS QueryInfo(XFileInfo* out_info) = 0; virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart) = 0; + virtual X_STATUS QueryVolume(XVolumeInfo* out_info, size_t length) = 0; + virtual X_STATUS QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) = 0; X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset, size_t* out_bytes_read);