diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_device.cc b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_device.cc index a5d6dd1f3..234e35e4b 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_device.cc +++ b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_device.cc @@ -91,7 +91,7 @@ Entry* DiscImageDevice::ResolvePath(const char* path) { XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), next_slash + 1)); } - Entry::Type type = gdfx_entry->attributes & GDFXEntry::kAttrFolder ? + Entry::Type type = gdfx_entry->attributes & X_FILE_ATTRIBUTE_DIRECTORY ? Entry::kTypeDirectory : Entry::kTypeFile; return new DiscImageEntry( type, this, path, mmap_, gdfx_entry); 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 b848c0ffe..892da3dc9 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 @@ -29,6 +29,19 @@ DiscImageFile::DiscImageFile( DiscImageFile::~DiscImageFile() { } +X_STATUS DiscImageFile::QueryInfo(FileInfo* out_info) { + XEASSERTNOTNULL(out_info); + GDFXEntry* gdfx_entry = entry_->gdfx_entry(); + out_info->creation_time = 0; + 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->attributes = gdfx_entry->attributes; + return X_STATUS_SUCCESS; +} + 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/modules/xboxkrnl/fs/devices/disc_image_file.h b/src/xenia/kernel/modules/xboxkrnl/fs/devices/disc_image_file.h index fd18d78cf..9e1b0a2ce 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 @@ -1,50 +1,51 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_ -#define XENIA_KERNEL_MODULES_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_ - -#include -#include - -#include - - -namespace xe { -namespace kernel { -namespace xboxkrnl { -namespace fs { - -class DiscImageEntry; - - -class DiscImageFile : public XFile { -public: - DiscImageFile(KernelState* kernel_state, uint32_t desired_access, - DiscImageEntry* entry); - virtual ~DiscImageFile(); - - -protected: +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_ +#define XENIA_KERNEL_MODULES_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_ + +#include +#include + +#include + + +namespace xe { +namespace kernel { +namespace xboxkrnl { +namespace fs { + +class DiscImageEntry; + + +class DiscImageFile : public XFile { +public: + DiscImageFile(KernelState* kernel_state, uint32_t desired_access, + DiscImageEntry* entry); + virtual ~DiscImageFile(); + + virtual X_STATUS QueryInfo(FileInfo* out_info); + +protected: virtual X_STATUS ReadSync( void* buffer, size_t buffer_length, size_t byte_offset, - size_t* out_bytes_read); - -private: - DiscImageEntry* entry_; -}; - - -} // namespace fs -} // namespace xboxkrnl -} // namespace kernel -} // namespace xe - - -#endif // XENIA_KERNEL_MODULES_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_ + size_t* out_bytes_read); + +private: + DiscImageEntry* entry_; +}; + + +} // namespace fs +} // namespace xboxkrnl +} // namespace kernel +} // namespace xe + + +#endif // XENIA_KERNEL_MODULES_XBOXKRNL_FS_DEVICES_DISC_IMAGE_FILE_H_ 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 967bbe459..074a55af3 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 @@ -29,6 +29,26 @@ HostPathFile::~HostPathFile() { CloseHandle(file_handle_); } +X_STATUS HostPathFile::QueryInfo(FileInfo* out_info) { + XEASSERTNOTNULL(out_info); + + WIN32_FILE_ATTRIBUTE_DATA data; + if (!GetFileAttributesEx( + entry_->local_path(), GetFileExInfoStandard, &data)) { + return X_STATUS_ACCESS_DENIED; + } + +#define COMBINE_TIME(t) (((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime) + 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->attributes = (X_FILE_ATTRIBUTES)data.dwFileAttributes; + return X_STATUS_SUCCESS; +} + 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/modules/xboxkrnl/fs/devices/host_path_file.h b/src/xenia/kernel/modules/xboxkrnl/fs/devices/host_path_file.h index 6ee18757a..a0a9c0a5b 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 @@ -30,6 +30,8 @@ public: HostPathEntry* entry, HANDLE file_handle); virtual ~HostPathFile(); + virtual X_STATUS QueryInfo(FileInfo* out_info); + protected: virtual X_STATUS ReadSync( void* buffer, size_t buffer_length, size_t byte_offset, diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.cc b/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.cc index 9ff9af68c..1572ef382 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.cc +++ b/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.cc @@ -25,7 +25,7 @@ namespace { GDFXEntry::GDFXEntry() : - attributes(0), offset(0), size(0) { + attributes(X_FILE_ATTRIBUTE_NONE), offset(0), size(0) { } GDFXEntry::~GDFXEntry() { @@ -144,7 +144,7 @@ GDFX::Error GDFX::ReadAllEntries(ParseState& state, root_entry_->offset = 0; root_entry_->size = 0; root_entry_->name = ""; - root_entry_->attributes = GDFXEntry::kAttrFolder; + root_entry_->attributes = X_FILE_ATTRIBUTE_DIRECTORY; if (!ReadEntry(state, root_buffer, 0, root_entry_)) { return kErrorOutOfMemory; @@ -172,12 +172,12 @@ bool GDFX::ReadEntry(ParseState& state, const uint8_t* buffer, GDFXEntry* entry = new GDFXEntry(); entry->name = std::string(name, name_length); entry->name.append(1, '\0'); - entry->attributes = attributes; + entry->attributes = (X_FILE_ATTRIBUTES)attributes; // Add to parent. parent->children.push_back(entry); - if (attributes & GDFXEntry::kAttrFolder) { + if (attributes & X_FILE_ATTRIBUTE_DIRECTORY) { // Folder. entry->offset = 0; entry->size = 0; diff --git a/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.h b/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.h index a77de5b34..beb76ef86 100644 --- a/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.h +++ b/src/xenia/kernel/modules/xboxkrnl/fs/gdfx.h @@ -15,6 +15,7 @@ #include +#include #include @@ -29,16 +30,6 @@ class GDFX; class GDFXEntry { public: - enum Attributes { - kAttrNone = 0x00000000, - kAttrReadOnly = 0x00000001, - kAttrHidden = 0x00000002, - kAttrSystem = 0x00000004, - kAttrFolder = 0x00000010, - kAttrArchived = 0x00000020, - kAttrNormal = 0x00000080, - }; - GDFXEntry(); ~GDFXEntry(); @@ -46,10 +37,10 @@ public: void Dump(int indent); - std::string name; - uint32_t attributes; - size_t offset; - size_t size; + std::string name; + X_FILE_ATTRIBUTES attributes; + size_t offset; + size_t size; std::vector children; }; diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc index ee4484994..89a9a73d2 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.cc @@ -38,6 +38,12 @@ X_STATUS XFile::Wait(uint32_t wait_reason, uint32_t processor_mode, wait_reason, processor_mode, alertable, opt_timeout); } +X_STATUS XFile::QueryInfo(FileInfo* out_info) { + XEASSERTNOTNULL(out_info); + xe_zero_struct(out_info, sizeof(FileInfo)); + return X_STATUS_NOT_IMPLEMENTED; +} + X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset, size_t* out_bytes_read) { if (byte_offset == -1) { diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h index efe99325f..1a10bba2e 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xfile.h @@ -28,9 +28,22 @@ public: XFile(KernelState* kernel_state, uint32_t desired_access); virtual ~XFile(); + size_t position() const { return position_; } + virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode, uint32_t alertable, uint64_t* opt_timeout); + typedef struct { + 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; + } FileInfo; + virtual X_STATUS QueryInfo(FileInfo* out_info); + 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, diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc index 505c4ee7a..362b788fc 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_io.cc @@ -233,7 +233,79 @@ SHIM_CALL NtQueryInformationFile_shim( length, file_info_class); - SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE); + X_STATUS result = X_STATUS_SUCCESS; + uint32_t info = 0; + + // Grab file. + XFile* file = NULL; + result = state->object_table()->GetObject( + file_handle, (XObject**)&file); + + if (XSUCCEEDED(result)) { + result = X_STATUS_SUCCESS; + switch (file_info_class) { + case XFilePositionInformation: + // struct FILE_POSITION_INFORMATION { + // LARGE_INTEGER CurrentByteOffset; + // }; + XEASSERT(length == 8); + info = 8; + SHIM_SET_MEM_64(file_info_ptr, file->position()); + break; + case XFileNetworkOpenInformation: + // struct FILE_NETWORK_OPEN_INFORMATION { + // LARGE_INTEGER CreationTime; + // LARGE_INTEGER LastAccessTime; + // LARGE_INTEGER LastWriteTime; + // LARGE_INTEGER ChangeTime; + // LARGE_INTEGER AllocationSize; + // LARGE_INTEGER EndOfFile; + // ULONG FileAttributes; + // ULONG Unknown; + // }; + XEASSERT(length == 56); + XFile::FileInfo file_info; + result = file->QueryInfo(&file_info); + if (XSUCCEEDED(result)) { + info = 56; + SHIM_SET_MEM_64(file_info_ptr, + file_info.creation_time); + SHIM_SET_MEM_64(file_info_ptr + 8, + file_info.last_access_time); + SHIM_SET_MEM_64(file_info_ptr + 16, + file_info.last_write_time); + SHIM_SET_MEM_64(file_info_ptr + 24, + file_info.change_time); + SHIM_SET_MEM_64(file_info_ptr + 32, + file_info.allocation_size); + SHIM_SET_MEM_64(file_info_ptr + 40, + file_info.file_length); + SHIM_SET_MEM_32(file_info_ptr + 48, + file_info.attributes); + SHIM_SET_MEM_32(file_info_ptr + 52, 0); // Unknown! + } + break; + default: + // Unsupported, for now. + XEASSERTALWAYS(); + info = 0; + break; + } + } + + if (XFAILED(result)) { + info = 0; + } + if (io_status_block_ptr) { + SHIM_SET_MEM_32(io_status_block_ptr, result); // Status + SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information + } + + if (file) { + file->Release(); + } + + SHIM_SET_RETURN(result); } SHIM_CALL NtQueryFullAttributesFile_shim( diff --git a/src/xenia/kernel/xbox.h b/src/xenia/kernel/xbox.h index 05db3e193..3baa5e538 100644 --- a/src/xenia/kernel/xbox.h +++ b/src/xenia/kernel/xbox.h @@ -107,6 +107,82 @@ typedef uint32_t X_STATUS; #define X_LANGUAGE_JAPANESE 2 +typedef 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, +} X_FILE_ATTRIBUTES; + + +typedef enum _X_FILE_INFORMATION_CLASS { + XFileDirectoryInformation = 1, + XFileFullDirectoryInformation, + XFileBothDirectoryInformation, + XFileBasicInformation, + XFileStandardInformation, + XFileInternalInformation, + XFileEaInformation, + XFileAccessInformation, + XFileNameInformation, + XFileRenameInformation, + XFileLinkInformation, + XFileNamesInformation, + XFileDispositionInformation, + XFilePositionInformation, + XFileFullEaInformation, + XFileModeInformation, + XFileAlignmentInformation, + XFileAllInformation, + XFileAllocationInformation, + XFileEndOfFileInformation, + XFileAlternateNameInformation, + XFileStreamInformation, + XFilePipeInformation, + XFilePipeLocalInformation, + XFilePipeRemoteInformation, + XFileMailslotQueryInformation, + XFileMailslotSetInformation, + XFileCompressionInformation, + XFileObjectIdInformation, + XFileCompletionInformation, + XFileMoveClusterInformation, + XFileQuotaInformation, + XFileReparsePointInformation, + XFileNetworkOpenInformation, + XFileAttributeTagInformation, + XFileTrackingInformation, + XFileIdBothDirectoryInformation, + XFileIdFullDirectoryInformation, + XFileValidDataLengthInformation, + XFileShortNameInformation, + XFileIoCompletionNotificationInformation, + XFileIoStatusBlockRangeInformation, + XFileIoPriorityHintInformation, + XFileSfioReserveInformation, + XFileSfioVolumeInformation, + XFileHardLinkInformation, + XFileProcessIdsUsingFileInformation, + XFileNormalizedNameInformation, + XFileNetworkPhysicalNameInformation, + XFileIdGlobalTxDirectoryInformation, + XFileIsRemoteDeviceInformation, + XFileAttributeCacheInformation, + XFileNumaNodeInformation, + XFileStandardLinkInformation, + XFileRemoteProtocolInformation, + XFileReplaceCompletionInformation, + XFileMaximumInformation +} X_FILE_INFORMATION_CLASS; + + class X_ANSI_STRING { public: uint16_t length;