diff --git a/src/xenia/base/byte_order.h b/src/xenia/base/byte_order.h index 9aea97d6e..5aed576f7 100644 --- a/src/xenia/base/byte_order.h +++ b/src/xenia/base/byte_order.h @@ -68,6 +68,14 @@ inline double byte_swap(double value) { uint64_t temp = byte_swap(*reinterpret_cast(&value)); return *reinterpret_cast(&temp); } +template +inline T byte_swap(T value) { + if (sizeof(T) == 4) { + return static_cast(byte_swap(static_cast(value))); + } else { + assert_always("not handled"); + } +} template struct be { diff --git a/src/xenia/kernel/fs/devices/disc_image_entry.cc b/src/xenia/kernel/fs/devices/disc_image_entry.cc index 3ec844048..0bbd314a8 100644 --- a/src/xenia/kernel/fs/devices/disc_image_entry.cc +++ b/src/xenia/kernel/fs/devices/disc_image_entry.cc @@ -11,6 +11,7 @@ #include +#include "xenia/base/math.h" #include "xenia/kernel/fs/devices/disc_image_file.h" namespace xe { @@ -30,7 +31,7 @@ DiscImageEntry::DiscImageEntry(Device* device, const char* path, : Entry(device, path), mmap_(mmap), gdfx_entry_(gdfx_entry), - it_(gdfx_entry->children.end()) {} + it_(gdfx_entry->children.begin()) {} DiscImageEntry::~DiscImageEntry() {} @@ -40,8 +41,8 @@ X_STATUS DiscImageEntry::QueryInfo(X_FILE_NETWORK_OPEN_INFORMATION* out_info) { out_info->last_access_time = 0; out_info->last_write_time = 0; out_info->change_time = 0; - out_info->allocation_size = 2048; - out_info->file_length = gdfx_entry_->size; + out_info->allocation_size = xe::round_up(gdfx_entry_->size, 2048); + out_info->end_of_file = gdfx_entry_->size; out_info->attributes = gdfx_entry_->attributes; return X_STATUS_SUCCESS; } @@ -71,13 +72,13 @@ X_STATUS DiscImageEntry::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info, entry = gdfx_entry_->GetChild(find_engine_, it_); if (!entry) { - return X_STATUS_UNSUCCESSFUL; + return X_STATUS_NO_SUCH_FILE; } auto end = (uint8_t*)out_info + length; auto entry_name = entry->name; if (((uint8_t*)&out_info->file_name[0]) + entry_name.size() > end) { - return X_STATUS_NO_MORE_FILES; + return X_STATUS_NO_SUCH_FILE; } } @@ -88,7 +89,7 @@ X_STATUS DiscImageEntry::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info, out_info->last_write_time = 0; out_info->change_time = 0; out_info->end_of_file = entry->size; - out_info->allocation_size = 2048; + out_info->allocation_size = xe::round_up(entry->size, 2048); out_info->attributes = entry->attributes; out_info->file_name_length = static_cast(entry->name.size()); memcpy(out_info->file_name, entry->name.c_str(), entry->name.size()); diff --git a/src/xenia/kernel/fs/devices/disc_image_file.cc b/src/xenia/kernel/fs/devices/disc_image_file.cc index 004be7569..e80198d46 100644 --- a/src/xenia/kernel/fs/devices/disc_image_file.cc +++ b/src/xenia/kernel/fs/devices/disc_image_file.cc @@ -48,7 +48,7 @@ X_STATUS DiscImageFile::ReadSync(void* buffer, size_t buffer_length, } size_t real_offset = gdfx_entry->offset + byte_offset; size_t real_length = std::min(buffer_length, gdfx_entry->size - byte_offset); - memcpy(buffer, entry_->mmap()->data() + real_offset, real_length); + std::memcpy(buffer, entry_->mmap()->data() + real_offset, real_length); *out_bytes_read = real_length; return X_STATUS_SUCCESS; } diff --git a/src/xenia/kernel/fs/devices/host_path_entry.cc b/src/xenia/kernel/fs/devices/host_path_entry.cc index c3584af34..6bb61e154 100644 --- a/src/xenia/kernel/fs/devices/host_path_entry.cc +++ b/src/xenia/kernel/fs/devices/host_path_entry.cc @@ -10,6 +10,7 @@ #include "xenia/kernel/fs/devices/host_path_entry.h" #include "xenia/base/mapped_memory.h" +#include "xenia/base/math.h" #include "xenia/base/string.h" #include "xenia/kernel/fs/devices/host_path_file.h" @@ -48,13 +49,14 @@ X_STATUS HostPathEntry::QueryInfo(X_FILE_NETWORK_OPEN_INFORMATION* out_info) { return X_STATUS_ACCESS_DENIED; } + uint64_t file_size = ((uint64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow; + out_info->creation_time = COMBINE_TIME(data.ftCreationTime); out_info->last_access_time = COMBINE_TIME(data.ftLastAccessTime); out_info->last_write_time = COMBINE_TIME(data.ftLastWriteTime); out_info->change_time = COMBINE_TIME(data.ftLastWriteTime); - out_info->allocation_size = 4096; - out_info->file_length = - ((uint64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow; + out_info->allocation_size = xe::round_up(file_size, 4096); + out_info->end_of_file = file_size; out_info->attributes = (X_FILE_ATTRIBUTES)data.dwFileAttributes; return X_STATUS_SUCCESS; } @@ -90,7 +92,7 @@ X_STATUS HostPathEntry::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info, s if (FindNextFile(handle, &ffd) == FALSE) { FindClose(handle); find_file_ = INVALID_HANDLE_VALUE; - return X_STATUS_NO_MORE_FILES; + return X_STATUS_NO_SUCH_FILE; } } @@ -102,15 +104,16 @@ X_STATUS HostPathEntry::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info, s return X_STATUS_BUFFER_OVERFLOW; } + uint64_t file_size = ((uint64_t)ffd.nFileSizeHigh << 32) | ffd.nFileSizeLow; + out_info->next_entry_offset = 0; out_info->file_index = 0xCDCDCDCD; out_info->creation_time = COMBINE_TIME(ffd.ftCreationTime); out_info->last_access_time = COMBINE_TIME(ffd.ftLastAccessTime); out_info->last_write_time = COMBINE_TIME(ffd.ftLastWriteTime); out_info->change_time = COMBINE_TIME(ffd.ftLastWriteTime); - out_info->end_of_file = - ((uint64_t)ffd.nFileSizeHigh << 32) | ffd.nFileSizeLow; - out_info->allocation_size = 4096; + out_info->end_of_file = file_size; + out_info->allocation_size = xe::round_up(file_size, 4096); out_info->attributes = (X_FILE_ATTRIBUTES)ffd.dwFileAttributes; out_info->file_name_length = (uint32_t)entry_name_length; diff --git a/src/xenia/kernel/fs/devices/stfs_container_entry.cc b/src/xenia/kernel/fs/devices/stfs_container_entry.cc index b117ef0ab..d666c1c1e 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_entry.cc +++ b/src/xenia/kernel/fs/devices/stfs_container_entry.cc @@ -9,6 +9,7 @@ #include "xenia/kernel/fs/devices/stfs_container_entry.h" +#include "xenia/base/math.h" #include "xenia/kernel/fs/devices/stfs_container_file.h" namespace xe { @@ -21,7 +22,7 @@ STFSContainerEntry::STFSContainerEntry(Device* device, const char* path, : Entry(device, path), mmap_(mmap), stfs_entry_(stfs_entry), - it_(stfs_entry_->children.end()) {} + it_(stfs_entry_->children.begin()) {} STFSContainerEntry::~STFSContainerEntry() = default; @@ -31,8 +32,8 @@ X_STATUS STFSContainerEntry::QueryInfo(X_FILE_NETWORK_OPEN_INFORMATION* out_info out_info->last_access_time = stfs_entry_->access_timestamp; out_info->last_write_time = stfs_entry_->update_timestamp; out_info->change_time = stfs_entry_->update_timestamp; - out_info->allocation_size = 4096; - out_info->file_length = stfs_entry_->size; + out_info->allocation_size = xe::round_up(stfs_entry_->size, 4096); + out_info->end_of_file = stfs_entry_->size; out_info->attributes = stfs_entry_->attributes; return X_STATUS_SUCCESS; } @@ -64,13 +65,13 @@ X_STATUS STFSContainerEntry::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_in entry = stfs_entry_->GetChild(find_engine_, it_); if (!entry) { - return X_STATUS_UNSUCCESSFUL; + return X_STATUS_NO_SUCH_FILE; } auto end = (uint8_t*)out_info + length; auto entry_name = entry->name; if (((uint8_t*)&out_info->file_name[0]) + entry_name.size() > end) { - return X_STATUS_NO_MORE_FILES; + return X_STATUS_NO_SUCH_FILE; } } @@ -80,7 +81,7 @@ X_STATUS STFSContainerEntry::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_in out_info->last_write_time = entry->update_timestamp; out_info->change_time = entry->update_timestamp; out_info->end_of_file = entry->size; - out_info->allocation_size = 4096; + out_info->allocation_size = xe::round_up(entry->size, 4096); out_info->attributes = entry->attributes; out_info->file_name_length = static_cast(entry->name.size()); memcpy(out_info->file_name, entry->name.c_str(), entry->name.size()); diff --git a/src/xenia/kernel/fs/entry.h b/src/xenia/kernel/fs/entry.h index d24401377..8e07a6fba 100644 --- a/src/xenia/kernel/fs/entry.h +++ b/src/xenia/kernel/fs/entry.h @@ -19,7 +19,7 @@ namespace xe { namespace kernel { class KernelState; class XFile; -class X_FILE_NETWORK_OPEN_INFORMATION; +struct X_FILE_NETWORK_OPEN_INFORMATION; class X_FILE_DIRECTORY_INFORMATION; class X_FILE_FS_ATTRIBUTE_INFORMATION; class X_FILE_FS_SIZE_INFORMATION; diff --git a/src/xenia/kernel/objects/xfile.h b/src/xenia/kernel/objects/xfile.h index de3bb56af..d92af7d7e 100644 --- a/src/xenia/kernel/objects/xfile.h +++ b/src/xenia/kernel/objects/xfile.h @@ -22,27 +22,15 @@ class XAsyncRequest; class XEvent; // https://msdn.microsoft.com/en-us/library/windows/hardware/ff545822.aspx -class X_FILE_NETWORK_OPEN_INFORMATION { - public: - // FILE_NETWORK_OPEN_INFORMATION - uint64_t creation_time; - uint64_t last_access_time; - uint64_t last_write_time; - uint64_t change_time; - uint64_t allocation_size; - uint64_t file_length; - X_FILE_ATTRIBUTES attributes; - - void Write(uint8_t* base, uint32_t p) { - xe::store_and_swap(base + p, creation_time); - xe::store_and_swap(base + p + 8, last_access_time); - xe::store_and_swap(base + p + 16, last_write_time); - xe::store_and_swap(base + p + 24, change_time); - xe::store_and_swap(base + p + 32, allocation_size); - xe::store_and_swap(base + p + 40, file_length); - xe::store_and_swap(base + p + 48, attributes); - xe::store_and_swap(base + p + 52, 0); // pad - } +struct X_FILE_NETWORK_OPEN_INFORMATION { + xe::be creation_time; + xe::be last_access_time; + xe::be last_write_time; + xe::be change_time; + xe::be allocation_size; + xe::be end_of_file; // size in bytes + xe::be attributes; + xe::be pad; }; // https://msdn.microsoft.com/en-us/library/windows/hardware/ff540248.aspx @@ -55,7 +43,7 @@ class X_FILE_DIRECTORY_INFORMATION { uint64_t last_access_time; uint64_t last_write_time; uint64_t change_time; - uint64_t end_of_file; + uint64_t end_of_file; // size in bytes uint64_t allocation_size; X_FILE_ATTRIBUTES attributes; uint32_t file_name_length; diff --git a/src/xenia/kernel/objects/xuser_module.cc b/src/xenia/kernel/objects/xuser_module.cc index 5b0b71041..907069b81 100644 --- a/src/xenia/kernel/objects/xuser_module.cc +++ b/src/xenia/kernel/objects/xuser_module.cc @@ -56,13 +56,13 @@ X_STATUS XUserModule::LoadFromFile(std::string path) { // Load the module. result = LoadFromMemory(mmap->address(), mmap->length()); } else { - X_FILE_NETWORK_OPEN_INFORMATION file_info; + X_FILE_NETWORK_OPEN_INFORMATION file_info = {0}; result = fs_entry->QueryInfo(&file_info); if (result) { return result; } - std::vector buffer(file_info.file_length); + std::vector buffer(file_info.end_of_file); // Open file for reading. XFile* file_ptr = nullptr; diff --git a/src/xenia/kernel/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl_io.cc index f3f2fed82..95f0c3e3b 100644 --- a/src/xenia/kernel/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl_io.cc @@ -492,7 +492,7 @@ SHIM_CALL NtQueryInformationFile_shim(PPCContext* ppc_context, info = 8; SHIM_SET_MEM_64(file_info_ptr, file->position()); break; - case XFileNetworkOpenInformation: + case XFileNetworkOpenInformation: { // struct FILE_NETWORK_OPEN_INFORMATION { // LARGE_INTEGER CreationTime; // LARGE_INTEGER LastAccessTime; @@ -504,13 +504,15 @@ SHIM_CALL NtQueryInformationFile_shim(PPCContext* ppc_context, // ULONG Unknown; // }; assert_true(length == 56); - X_FILE_NETWORK_OPEN_INFORMATION file_info; - result = file->QueryInfo(&file_info); + auto file_info = + kernel_memory()->TranslateVirtual( + file_info_ptr); + result = file->QueryInfo(file_info); if (XSUCCEEDED(result)) { info = 56; - file_info.Write(SHIM_MEM_BASE, file_info_ptr); } break; + } case XFileXctdCompressionInformation: assert_true(length == 4); /* @@ -578,11 +580,10 @@ SHIM_CALL NtQueryFullAttributesFile_shim(PPCContext* ppc_context, auto entry = fs->ResolvePath(object_name); if (entry) { // Found. - X_FILE_NETWORK_OPEN_INFORMATION file_info; - result = entry->QueryInfo(&file_info); - if (XSUCCEEDED(result)) { - file_info.Write(SHIM_MEM_BASE, file_info_ptr); - } + auto file_info = + kernel_memory()->TranslateVirtual( + file_info_ptr); + result = entry->QueryInfo(file_info); } free(object_name); diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index c0f5ceda6..07e6c71a1 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -156,19 +156,18 @@ typedef uint32_t X_HRESULT; #define X_LANGUAGE_ENGLISH 1 #define X_LANGUAGE_JAPANESE 2 - -enum X_FILE_ATTRIBUTES { - X_FILE_ATTRIBUTE_NONE = 0x0000, - X_FILE_ATTRIBUTE_READONLY = 0x0001, - X_FILE_ATTRIBUTE_HIDDEN = 0x0002, - X_FILE_ATTRIBUTE_SYSTEM = 0x0004, - X_FILE_ATTRIBUTE_DIRECTORY = 0x0010, - X_FILE_ATTRIBUTE_ARCHIVE = 0x0020, - X_FILE_ATTRIBUTE_DEVICE = 0x0040, - X_FILE_ATTRIBUTE_NORMAL = 0x0080, - X_FILE_ATTRIBUTE_TEMPORARY = 0x0100, - X_FILE_ATTRIBUTE_COMPRESSED = 0x0800, - X_FILE_ATTRIBUTE_ENCRYPTED = 0x4000, +enum X_FILE_ATTRIBUTES : uint32_t { + X_FILE_ATTRIBUTE_NONE = 0x0000, + X_FILE_ATTRIBUTE_READONLY = 0x0001, + X_FILE_ATTRIBUTE_HIDDEN = 0x0002, + X_FILE_ATTRIBUTE_SYSTEM = 0x0004, + X_FILE_ATTRIBUTE_DIRECTORY = 0x0010, + X_FILE_ATTRIBUTE_ARCHIVE = 0x0020, + X_FILE_ATTRIBUTE_DEVICE = 0x0040, + X_FILE_ATTRIBUTE_NORMAL = 0x0080, + X_FILE_ATTRIBUTE_TEMPORARY = 0x0100, + X_FILE_ATTRIBUTE_COMPRESSED = 0x0800, + X_FILE_ATTRIBUTE_ENCRYPTED = 0x4000, }; // http://code.google.com/p/vdash/source/browse/trunk/vdash/include/kernel.h