[XAM] Deferred xeXamContentCreate.

This commit is contained in:
gibbed 2021-06-30 03:05:16 -05:00 committed by Rick Gibbed
parent e8fda5878c
commit 4498a28568
1 changed files with 86 additions and 79 deletions

View File

@ -123,7 +123,6 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
lpdword_t license_mask_ptr, lpdword_t license_mask_ptr,
dword_t cache_size, qword_t content_size, dword_t cache_size, qword_t content_size,
lpvoid_t overlapped_ptr) { lpvoid_t overlapped_ptr) {
X_RESULT result = X_ERROR_INVALID_PARAMETER;
XCONTENT_AGGREGATE_DATA content_data; XCONTENT_AGGREGATE_DATA content_data;
if (content_data_size == sizeof(XCONTENT_DATA)) { if (content_data_size == sizeof(XCONTENT_DATA)) {
content_data = *content_data_ptr.as<XCONTENT_DATA*>(); content_data = *content_data_ptr.as<XCONTENT_DATA*>();
@ -131,91 +130,99 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
content_data = *content_data_ptr.as<XCONTENT_AGGREGATE_DATA*>(); content_data = *content_data_ptr.as<XCONTENT_AGGREGATE_DATA*>();
} else { } else {
assert_always(); assert_always();
return result; return X_ERROR_INVALID_PARAMETER;
} }
auto content_manager = kernel_state()->content_manager(); auto content_manager = kernel_state()->content_manager();
bool create = false;
bool open = false; if (overlapped_ptr && disposition_ptr) {
switch (flags & 0xF) { *disposition_ptr = 0;
case 1: // CREATE_NEW
// Fail if exists.
if (content_manager->ContentExists(content_data)) {
result = X_ERROR_ALREADY_EXISTS;
} else {
create = true;
}
break;
case 2: // CREATE_ALWAYS
// Overwrite existing, if any.
if (content_manager->ContentExists(content_data)) {
content_manager->DeleteContent(content_data);
create = true;
} else {
create = true;
}
break;
case 3: // OPEN_EXISTING
// Open only if exists.
if (!content_manager->ContentExists(content_data)) {
result = X_ERROR_PATH_NOT_FOUND;
} else {
open = true;
}
break;
case 4: // OPEN_ALWAYS
// Create if needed.
if (!content_manager->ContentExists(content_data)) {
create = true;
} else {
open = true;
}
break;
case 5: // TRUNCATE_EXISTING
// Fail if doesn't exist, if does exist delete and recreate.
if (!content_manager->ContentExists(content_data)) {
result = X_ERROR_PATH_NOT_FOUND;
} else {
content_manager->DeleteContent(content_data);
create = true;
}
break;
default:
assert_unhandled_case(flags & 0xF);
break;
} }
// creation result auto run = [content_manager, root_name, flags, content_data, disposition_ptr,
// 0 = ? license_mask_ptr](uint32_t& extended_error,
// 1 = created uint32_t& length) -> X_RESULT {
// 2 = opened X_RESULT result = X_ERROR_INVALID_PARAMETER;
uint32_t disposition = create ? 1 : 2; bool create = false;
if (disposition_ptr) { bool open = false;
// In case when overlapped_ptr exist we should clear disposition_ptr first switch (flags & 0xF) {
// however we're executing it immediately, so it's not required case 1: // CREATE_NEW
*disposition_ptr = disposition; // Fail if exists.
} if (content_manager->ContentExists(content_data)) {
result = X_ERROR_ALREADY_EXISTS;
if (create) { } else {
result = content_manager->CreateContent(root_name.value(), content_data); create = true;
} else if (open) { }
result = content_manager->OpenContent(root_name.value(), content_data); break;
} case 2: // CREATE_ALWAYS
// Overwrite existing, if any.
if (license_mask_ptr && XSUCCEEDED(result)) { if (content_manager->ContentExists(content_data)) {
*license_mask_ptr = 0; // Stub! content_manager->DeleteContent(content_data);
} create = true;
} else {
if (overlapped_ptr) { create = true;
X_RESULT extended_error = X_HRESULT_FROM_WIN32(result); }
if (int32_t(extended_error) < 0) { break;
result = X_ERROR_FUNCTION_FAILED; case 3: // OPEN_EXISTING
// Open only if exists.
if (!content_manager->ContentExists(content_data)) {
result = X_ERROR_PATH_NOT_FOUND;
} else {
open = true;
}
break;
case 4: // OPEN_ALWAYS
// Create if needed.
if (!content_manager->ContentExists(content_data)) {
create = true;
} else {
open = true;
}
break;
case 5: // TRUNCATE_EXISTING
// Fail if doesn't exist, if does exist delete and recreate.
if (!content_manager->ContentExists(content_data)) {
result = X_ERROR_PATH_NOT_FOUND;
} else {
content_manager->DeleteContent(content_data);
create = true;
}
break;
default:
assert_unhandled_case(flags & 0xF);
break;
} }
kernel_state()->CompleteOverlappedImmediateEx(overlapped_ptr, result,
extended_error, disposition); // creation result
return X_ERROR_IO_PENDING; // 0 = ?
} else { // 1 = created
// 2 = opened
uint32_t disposition = create ? 1 : 2;
if (disposition_ptr) {
*disposition_ptr = disposition;
}
if (create) {
result = content_manager->CreateContent(root_name.value(), content_data);
} else if (open) {
result = content_manager->OpenContent(root_name.value(), content_data);
}
if (license_mask_ptr && XSUCCEEDED(result)) {
*license_mask_ptr = 0; // Stub!
}
extended_error = X_HRESULT_FROM_WIN32(result);
length = disposition;
return result; return result;
};
if (!overlapped_ptr) {
uint32_t extended_error, length;
return run(extended_error, length);
} else {
kernel_state()->CompleteOverlappedDeferredEx(run, overlapped_ptr);
return X_ERROR_IO_PENDING;
} }
} }