[XAM] Enumerator improvements.

- [Kernel] XEnumerator::WriteItems no longer cares about provided
  buffer size, since we know the size when the XEnumerator was created.
- [Kernel] Added XStaticEnumerator template. Previous
  XStaticEnumerator renamed to XStaticUntypedEnumerator.
- [XAM] Deferred xeXamEnumerate.
This commit is contained in:
gibbed
2020-12-04 14:52:05 -06:00
committed by Rick Gibbed
parent b18f73b949
commit e8fda5878c
8 changed files with 92 additions and 91 deletions

View File

@@ -57,8 +57,7 @@ X_HRESULT XamApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
std::memset(buffer, 0, data->buffer_size);
}
uint32_t item_count = 0;
auto result = e->WriteItems(data->buffer_ptr, buffer, data->buffer_size,
&item_count);
auto result = e->WriteItems(data->buffer_ptr, buffer, &item_count);
if (result == X_ERROR_SUCCESS && item_count >= 1) {
if (data->length_ptr) {

View File

@@ -86,8 +86,8 @@ dword_result_t XamContentCreateEnumerator(dword_t user_index, dword_t device_id,
*buffer_size_ptr = sizeof(XCONTENT_DATA) * items_per_enumerate;
}
auto e = object_ref<XStaticEnumerator>(new XStaticEnumerator(
kernel_state(), items_per_enumerate, sizeof(XCONTENT_DATA)));
auto e = make_object<XStaticEnumerator<XCONTENT_DATA>>(kernel_state(),
items_per_enumerate);
auto result = e->Initialize(0xFF, 0xFE, 0x20005, 0x20007, 0);
if (XFAILED(result)) {
return result;
@@ -99,8 +99,7 @@ dword_result_t XamContentCreateEnumerator(dword_t user_index, dword_t device_id,
static_cast<uint32_t>(DummyDeviceId::HDD),
XContentType(uint32_t(content_type)));
for (const auto& content_data : content_datas) {
auto item = reinterpret_cast<XCONTENT_DATA*>(e->AppendItem());
assert_not_null(item);
auto item = e->AppendItem();
*item = content_data;
}
}

View File

@@ -23,7 +23,7 @@ namespace xe {
namespace kernel {
namespace xam {
void AddODDContentTest(object_ref<XStaticEnumerator> e,
void AddODDContentTest(object_ref<XStaticEnumerator<XCONTENT_AGGREGATE_DATA>> e,
XContentType content_type) {
auto root_entry = kernel_state()->file_system()->ResolvePath(
"game:\\Content\\0000000000000000");
@@ -62,13 +62,15 @@ void AddODDContentTest(object_ref<XStaticEnumerator> e,
break;
}
auto item = reinterpret_cast<XCONTENT_AGGREGATE_DATA*>(e->AppendItem());
auto item = e->AppendItem();
assert_not_null(item);
item->device_id = static_cast<uint32_t>(DummyDeviceId::ODD);
item->content_type = content_type;
item->set_display_name(to_utf16(content_entry->name()));
item->set_file_name(content_entry->name());
item->title_id = title_id;
if (item) {
item->device_id = static_cast<uint32_t>(DummyDeviceId::ODD);
item->content_type = content_type;
item->set_display_name(to_utf16(content_entry->name()));
item->set_file_name(content_entry->name());
item->title_id = title_id;
}
}
}
}
@@ -86,8 +88,8 @@ dword_result_t XamContentAggregateCreateEnumerator(qword_t xuid,
return X_E_INVALIDARG;
}
auto e = object_ref<XStaticEnumerator>(new XStaticEnumerator(
kernel_state(), 1, sizeof(XCONTENT_AGGREGATE_DATA)));
auto e = make_object<XStaticEnumerator<XCONTENT_AGGREGATE_DATA>>(
kernel_state(), 1);
X_KENUMERATOR_CONTENT_AGGREGATE* extra;
auto result = e->Initialize(0xFF, 0xFE, 0x2000E, 0x20010, 0, &extra);
if (XFAILED(result)) {
@@ -116,9 +118,11 @@ dword_result_t XamContentAggregateCreateEnumerator(qword_t xuid,
static_cast<uint32_t>(DummyDeviceId::HDD), content_type_enum,
title_id);
for (const auto& content_data : content_datas) {
auto item = reinterpret_cast<XCONTENT_AGGREGATE_DATA*>(e->AppendItem());
auto item = e->AppendItem();
assert_not_null(item);
*item = content_data;
if (item) {
*item = content_data;
}
}
}
}

View File

@@ -139,8 +139,8 @@ dword_result_t XamContentCreateDeviceEnumerator(dword_t content_type,
*buffer_size_ptr = sizeof(X_CONTENT_DEVICE_DATA) * max_count;
}
auto e = object_ref<XStaticEnumerator>(new XStaticEnumerator(
kernel_state(), max_count, sizeof(X_CONTENT_DEVICE_DATA)));
auto e = make_object<XStaticEnumerator<X_CONTENT_DEVICE_DATA>>(kernel_state(),
max_count);
auto result = e->Initialize(0xFE, 0xFE, 0x2000A, 0x20009, 0);
if (XFAILED(result)) {
return result;
@@ -148,7 +148,8 @@ dword_result_t XamContentCreateDeviceEnumerator(dword_t content_type,
for (const auto& device_info : dummy_device_infos_) {
// Copy our dummy device into the enumerator
auto device_data = (X_CONTENT_DEVICE_DATA*)e->AppendItem();
auto device_data = e->AppendItem();
assert_not_null(device_data);
if (device_data) {
device_data->device_id = static_cast<uint32_t>(device_info->device_id);
device_data->device_type =

View File

@@ -32,49 +32,37 @@ uint32_t xeXamEnumerate(uint32_t handle, uint32_t flags, lpvoid_t buffer_ptr,
uint32_t overlapped_ptr) {
assert_true(flags == 0);
X_RESULT result;
uint32_t item_count = 0;
auto e = kernel_state()->object_table()->LookupObject<XEnumerator>(handle);
if (!e) {
result = X_ERROR_INVALID_HANDLE;
} else if (!buffer_ptr) {
result = X_ERROR_INVALID_PARAMETER;
} else {
size_t needed_buffer_size = e->item_size() * e->items_per_enumerate();
uint32_t actual_buffer_size = buffer_size;
if (buffer_size == e->items_per_enumerate()) {
actual_buffer_size = static_cast<uint32_t>(needed_buffer_size);
// Known culprits:
// Final Fight: Double Impact (saves)
XELOGW(
"Broken usage of XamEnumerate! buffer size={:X} vs actual "
"size={:X} (item size={:X}, items per enumerate={})",
buffer_size, actual_buffer_size, e->item_size(),
e->items_per_enumerate());
}
result = X_ERROR_INSUFFICIENT_BUFFER;
if (actual_buffer_size >= needed_buffer_size) {
buffer_ptr.Zero(actual_buffer_size);
result =
e->WriteItems(buffer_ptr.guest_address(), buffer_ptr.as<uint8_t*>(),
actual_buffer_size, &item_count);
}
return X_ERROR_INVALID_HANDLE;
}
auto run = [e, buffer_ptr](uint32_t& extended_error,
uint32_t& length) -> X_RESULT {
X_RESULT result;
uint32_t item_count;
if (!buffer_ptr) {
result = X_ERROR_INVALID_PARAMETER;
item_count = 0;
} else {
result = e->WriteItems(buffer_ptr.guest_address(),
buffer_ptr.as<uint8_t*>(), &item_count);
}
extended_error = X_HRESULT_FROM_WIN32(result);
length = item_count;
return result;
};
if (items_returned) {
assert_true(!overlapped_ptr);
uint32_t extended_error;
uint32_t item_count;
X_RESULT result = run(extended_error, item_count);
*items_returned = result == X_ERROR_SUCCESS ? item_count : 0;
return result;
} else if (overlapped_ptr) {
assert_true(!items_returned);
kernel_state()->CompleteOverlappedImmediateEx(
overlapped_ptr,
result == X_ERROR_SUCCESS ? X_ERROR_SUCCESS : X_ERROR_FUNCTION_FAILED,
X_HRESULT_FROM_WIN32(result),
result == X_ERROR_SUCCESS ? item_count : 0);
kernel_state()->CompleteOverlappedDeferredEx(run, overlapped_ptr);
return X_ERROR_IO_PENDING;
} else {
assert_always();

View File

@@ -608,7 +608,7 @@ class XStaticAchievementEnumerator : public XEnumerator {
}
uint32_t WriteItems(uint32_t buffer_ptr, uint8_t* buffer_data,
uint32_t buffer_size, uint32_t* written_count) override {
uint32_t* written_count) override {
size_t count =
std::min(items_.size() - current_item_, items_per_enumerate());
if (!count) {
@@ -616,9 +616,6 @@ class XStaticAchievementEnumerator : public XEnumerator {
}
size_t size = count * item_size();
if (size > buffer_size) {
return X_ERROR_INSUFFICIENT_BUFFER;
}
auto details = reinterpret_cast<X_ACHIEVEMENT_DETAILS*>(buffer_data);
size_t string_offset =