diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index 514cac962..690edd6ca 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -123,7 +123,6 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name, lpdword_t license_mask_ptr, dword_t cache_size, qword_t content_size, lpvoid_t overlapped_ptr) { - X_RESULT result = X_ERROR_INVALID_PARAMETER; XCONTENT_AGGREGATE_DATA content_data; if (content_data_size == sizeof(XCONTENT_DATA)) { content_data = *content_data_ptr.as(); @@ -131,91 +130,99 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name, content_data = *content_data_ptr.as(); } else { assert_always(); - return result; + return X_ERROR_INVALID_PARAMETER; } auto content_manager = kernel_state()->content_manager(); - bool create = false; - bool open = false; - switch (flags & 0xF) { - 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; + + if (overlapped_ptr && disposition_ptr) { + *disposition_ptr = 0; } - // creation result - // 0 = ? - // 1 = created - // 2 = opened - uint32_t disposition = create ? 1 : 2; - if (disposition_ptr) { - // In case when overlapped_ptr exist we should clear disposition_ptr first - // however we're executing it immediately, so it's not required - *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! - } - - if (overlapped_ptr) { - X_RESULT extended_error = X_HRESULT_FROM_WIN32(result); - if (int32_t(extended_error) < 0) { - result = X_ERROR_FUNCTION_FAILED; + auto run = [content_manager, root_name, flags, content_data, disposition_ptr, + license_mask_ptr](uint32_t& extended_error, + uint32_t& length) -> X_RESULT { + X_RESULT result = X_ERROR_INVALID_PARAMETER; + bool create = false; + bool open = false; + switch (flags & 0xF) { + 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; } - kernel_state()->CompleteOverlappedImmediateEx(overlapped_ptr, result, - extended_error, disposition); - return X_ERROR_IO_PENDING; - } else { + + // creation result + // 0 = ? + // 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; + }; + + 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; } }