NtQueryDirectoryFile and necessary backing. Not fully functional yet.
This commit is contained in:
parent
c257ad0122
commit
619b9758a0
|
@ -32,6 +32,11 @@ X_STATUS DiscImageFile::QueryInfo(XFileInfo* out_info) {
|
|||
return entry_->QueryInfo(out_info);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageFile::QueryDirectory(XDirectoryInfo* out_info, size_t length, bool restart) {
|
||||
XEASSERTALWAYS();
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS DiscImageFile::ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
virtual ~DiscImageFile();
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, bool restart);
|
||||
|
||||
protected:
|
||||
virtual X_STATUS ReadSync(
|
||||
|
|
|
@ -39,14 +39,20 @@ private:
|
|||
|
||||
HostPathEntry::HostPathEntry(Type type, Device* device, const char* path,
|
||||
const xechar_t* local_path) :
|
||||
Entry(type, device, path) {
|
||||
Entry(type, device, path),
|
||||
find_file_(INVALID_HANDLE_VALUE) {
|
||||
local_path_ = xestrdup(local_path);
|
||||
}
|
||||
|
||||
HostPathEntry::~HostPathEntry() {
|
||||
if (find_file_ != INVALID_HANDLE_VALUE) {
|
||||
FindClose(find_file_);
|
||||
}
|
||||
xe_free(local_path_);
|
||||
}
|
||||
|
||||
#define COMBINE_TIME(t) (((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime)
|
||||
|
||||
X_STATUS HostPathEntry::QueryInfo(XFileInfo* out_info) {
|
||||
XEASSERTNOTNULL(out_info);
|
||||
|
||||
|
@ -56,7 +62,6 @@ X_STATUS HostPathEntry::QueryInfo(XFileInfo* out_info) {
|
|||
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);
|
||||
|
@ -67,6 +72,86 @@ X_STATUS HostPathEntry::QueryInfo(XFileInfo* out_info) {
|
|||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS HostPathEntry::QueryDirectory(XDirectoryInfo* out_info, size_t length, bool restart) {
|
||||
XEASSERTNOTNULL(out_info);
|
||||
|
||||
if (length < sizeof(XDirectoryInfo)) {
|
||||
return X_STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
memset(out_info, 0, length);
|
||||
|
||||
WIN32_FIND_DATA ffd;
|
||||
|
||||
HANDLE handle = find_file_;
|
||||
|
||||
if (restart == true && handle != INVALID_HANDLE_VALUE) {
|
||||
FindClose(find_file_);
|
||||
handle = find_file_ = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
handle = find_file_ = FindFirstFile(local_path_, &ffd);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (FindNextFile(handle, &ffd) == FALSE) {
|
||||
FindClose(handle);
|
||||
find_file_ = INVALID_HANDLE_VALUE;
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
XDirectoryInfo* current;
|
||||
|
||||
auto current_buf = (uint8_t*)out_info;
|
||||
auto end = current_buf + length;
|
||||
|
||||
current = (XDirectoryInfo*)current_buf;
|
||||
if (((uint8_t*)¤t->file_name[0]) + wcslen(ffd.cFileName) > end) {
|
||||
FindClose(handle);
|
||||
find_file_ = INVALID_HANDLE_VALUE;
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
size_t file_name_length = wcslen(ffd.cFileName);
|
||||
if (((uint8_t*)&((XDirectoryInfo*)current_buf)->file_name[0]) + wcslen(ffd.cFileName) > end) {
|
||||
break;
|
||||
}
|
||||
|
||||
current = (XDirectoryInfo*)current_buf;
|
||||
current->file_index = 0xCDCDCDCD;
|
||||
current->creation_time = COMBINE_TIME(ffd.ftCreationTime);
|
||||
current->last_access_time = COMBINE_TIME(ffd.ftLastAccessTime);
|
||||
current->last_write_time = COMBINE_TIME(ffd.ftLastWriteTime);
|
||||
current->change_time = COMBINE_TIME(ffd.ftLastWriteTime);
|
||||
current->end_of_file = ((uint64_t)ffd.nFileSizeHigh << 32) | ffd.nFileSizeLow;
|
||||
current->allocation_size = 4096;
|
||||
current->attributes = (X_FILE_ATTRIBUTES)ffd.dwFileAttributes;
|
||||
|
||||
// TODO: I am pretty sure you need to prefix the file paths with full path, not just the name.
|
||||
current->file_name_length = (uint32_t)file_name_length;
|
||||
for (size_t i = 0; i < file_name_length; ++i) {
|
||||
current->file_name[i] = ffd.cFileName[i] < 256 ? (char)ffd.cFileName[i] : '?';
|
||||
}
|
||||
|
||||
auto next_buf = (((uint8_t*)¤t->file_name[0]) + file_name_length);
|
||||
next_buf += 8 - ((uint8_t)next_buf % 8);
|
||||
|
||||
current->next_entry_offset = (uint32_t)(next_buf - current_buf);
|
||||
current_buf = next_buf;
|
||||
} while (current_buf < end && FindNextFile(handle, &ffd) == TRUE);
|
||||
current->next_entry_offset = 0;
|
||||
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);
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
const xechar_t* local_path() { return local_path_; }
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, bool restart);
|
||||
|
||||
virtual MemoryMapping* CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length);
|
||||
|
@ -41,6 +42,7 @@ public:
|
|||
|
||||
private:
|
||||
xechar_t* local_path_;
|
||||
HANDLE find_file_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,10 @@ X_STATUS HostPathFile::QueryInfo(XFileInfo* out_info) {
|
|||
return entry_->QueryInfo(out_info);
|
||||
}
|
||||
|
||||
X_STATUS HostPathFile::QueryDirectory(XDirectoryInfo* out_info, size_t length, bool restart) {
|
||||
return entry_->QueryDirectory(out_info, length, restart);
|
||||
}
|
||||
|
||||
X_STATUS HostPathFile::ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
virtual ~HostPathFile();
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, bool restart);
|
||||
|
||||
protected:
|
||||
virtual X_STATUS ReadSync(
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
XEDECLARECLASS2(xe, kernel, KernelState);
|
||||
XEDECLARECLASS2(xe, kernel, XFile);
|
||||
XEDECLARECLASS2(xe, kernel, XFileInfo);
|
||||
XEDECLARECLASS2(xe, kernel, XDirectoryInfo);
|
||||
|
||||
|
||||
namespace xe {
|
||||
|
|
|
@ -44,6 +44,44 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class XDirectoryInfo {
|
||||
public:
|
||||
// FILE_DIRECTORY_INFORMATION
|
||||
uint32_t next_entry_offset;
|
||||
uint32_t file_index;
|
||||
uint64_t creation_time;
|
||||
uint64_t last_access_time;
|
||||
uint64_t last_write_time;
|
||||
uint64_t change_time;
|
||||
uint64_t end_of_file;
|
||||
uint64_t allocation_size;
|
||||
X_FILE_ATTRIBUTES attributes;
|
||||
uint32_t file_name_length;
|
||||
char file_name[1];
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
uint8_t* dst = base + p;
|
||||
uint8_t* src = (uint8_t*)this;
|
||||
XDirectoryInfo* info;
|
||||
do {
|
||||
info = (XDirectoryInfo*)src;
|
||||
XESETUINT32BE(dst, info->next_entry_offset);
|
||||
XESETUINT32BE(dst + 4, info->file_index);
|
||||
XESETUINT64BE(dst + 8, info->creation_time);
|
||||
XESETUINT64BE(dst + 16, info->last_access_time);
|
||||
XESETUINT64BE(dst + 24, info->last_write_time);
|
||||
XESETUINT64BE(dst + 32, info->change_time);
|
||||
XESETUINT64BE(dst + 40, info->end_of_file);
|
||||
XESETUINT64BE(dst + 48, info->allocation_size);
|
||||
XESETUINT32BE(dst + 56, info->attributes);
|
||||
XESETUINT32BE(dst + 60, info->file_name_length);
|
||||
xe_copy_memory(dst + 64, info->file_name_length, info->file_name, info->file_name_length);
|
||||
dst += info->next_entry_offset;
|
||||
src += info->next_entry_offset;
|
||||
} while (info->next_entry_offset != 0);
|
||||
}
|
||||
};
|
||||
XEASSERTSTRUCTSIZE(XDirectoryInfo, 72);
|
||||
|
||||
class XFile : public XObject {
|
||||
public:
|
||||
|
@ -53,6 +91,7 @@ public:
|
|||
void set_position(size_t value) { position_ = value; }
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info) = 0;
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, bool restart) = 0;
|
||||
|
||||
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read);
|
||||
|
|
|
@ -458,6 +458,71 @@ SHIM_CALL NtQueryVolumeInformationFile_shim(
|
|||
SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
|
||||
}
|
||||
|
||||
SHIM_CALL NtQueryDirectoryFile_shim(
|
||||
PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t file_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t event_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t apc_routine = SHIM_GET_ARG_32(2);
|
||||
uint32_t apc_context = SHIM_GET_ARG_32(3);
|
||||
uint32_t io_status_block_ptr = SHIM_GET_ARG_32(4);
|
||||
uint32_t file_info_ptr = SHIM_GET_ARG_32(5);
|
||||
uint32_t length = SHIM_GET_ARG_32(6);
|
||||
uint32_t file_name_ptr = SHIM_GET_ARG_32(7);
|
||||
|
||||
XELOGD(
|
||||
"NtQueryDirectoryFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %.8X)",
|
||||
file_handle,
|
||||
event_handle,
|
||||
apc_routine,
|
||||
apc_context,
|
||||
io_status_block_ptr,
|
||||
file_info_ptr,
|
||||
length,
|
||||
file_name_ptr);
|
||||
|
||||
if (length < 72) {
|
||||
SHIM_SET_RETURN(X_STATUS_INFO_LENGTH_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_name_ptr != 0) {
|
||||
if (SHIM_MEM_16(file_name_ptr + 0) != 0 ||
|
||||
SHIM_MEM_16(file_name_ptr + 2) != 0) {
|
||||
const char* file_name = (const char *)SHIM_MEM_ADDR(SHIM_MEM_32(file_name_ptr + 4));
|
||||
XEASSERT(strcmp(file_name, "*.*") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
X_STATUS result = X_STATUS_UNSUCCESSFUL;
|
||||
uint32_t info = 0;
|
||||
|
||||
XFile* file = NULL;
|
||||
result = state->object_table()->GetObject(
|
||||
file_handle, (XObject**)&file);
|
||||
if (XSUCCEEDED(result)) {
|
||||
XDirectoryInfo* dirInfo = (XDirectoryInfo*)xe_malloc(length);
|
||||
result = file->QueryDirectory(dirInfo, length, false);
|
||||
if (XSUCCEEDED(result)) {
|
||||
dirInfo->Write(SHIM_MEM_BASE, file_info_ptr);
|
||||
info = length;
|
||||
}
|
||||
}
|
||||
|
||||
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 FscSetCacheElementCount_shim(
|
||||
PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t unk_0 = SHIM_GET_ARG_32(0);
|
||||
|
@ -486,6 +551,7 @@ void xe::kernel::xboxkrnl::RegisterIoExports(
|
|||
SHIM_SET_MAPPING("xboxkrnl.exe", NtSetInformationFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryFullAttributesFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryVolumeInformationFile, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtQueryDirectoryFile, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", FscSetCacheElementCount, state);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue