From d99585aa5374dc9e60be075a3db4241c8bddeba6 Mon Sep 17 00:00:00 2001 From: NarcolepticK Date: Tue, 14 Aug 2018 03:41:14 -0400 Subject: [PATCH] service/cecd: Add MBox directory check to OpenAndRead and OpenAndWrite and added a CreateAndPopulateMBoxDirectory function --- src/core/hle/service/cecd/cecd.cpp | 184 ++++++++++++++++++++++++++--- src/core/hle/service/cecd/cecd.h | 2 + 2 files changed, 171 insertions(+), 15 deletions(-) diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp index 5d4dd8f8b..cf19b6a51 100644 --- a/src/core/hle/service/cecd/cecd.cpp +++ b/src/core/hle/service/cecd/cecd.cpp @@ -400,6 +400,18 @@ void Module::Interface::OpenAndWrite(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } else { LOG_ERROR(Service_CECD, "Failed to open file: {}", path.AsString()); + + /// We need to check if the MBox /CEC/ directory even exists... + /// If it doesn't, we create and populate it. + const FileSys::Path mbox_path( + cecd->GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_MBOX_DIR, + ncch_program_id) + .data()); + auto mbox_result = Service::FS::OpenDirectoryFromArchive( + cecd->cecd_system_save_data_archive, mbox_path); + if (mbox_result.Failed()) + cecd->CreateAndPopulateMBoxDirectory(ncch_program_id); + rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::CEC, ErrorSummary::NotFound, ErrorLevel::Status)); } @@ -453,22 +465,19 @@ void Module::Interface::OpenAndRead(Kernel::HLERequestContext& ctx) { } else { LOG_ERROR(Service_CECD, "Failed to open file: {}", path.AsString()); - if (path_type == CecDataPathType::CEC_PATH_MBOX_INFO) { - const FileSys::Path root_dir_path( - cecd->GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_ROOT_DIR, - ncch_program_id) - .data()); - const FileSys::Path mbox_path( - cecd->GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_MBOX_DIR, - ncch_program_id) - .data()); + /// We need to check if the MBox /CEC/ directory even exists... + /// If it doesn't, we create and populate it. + const FileSys::Path mbox_path( + cecd->GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_MBOX_DIR, + ncch_program_id) + .data()); + auto mbox_result = Service::FS::OpenDirectoryFromArchive( + cecd->cecd_system_save_data_archive, mbox_path); + if (mbox_result.Failed()) + cecd->CreateAndPopulateMBoxDirectory(ncch_program_id); - /// Just in case the root dir /CEC doesn't exist, we try to create it first - Service::FS::CreateDirectoryFromArchive(cecd->cecd_system_save_data_archive, - root_dir_path); - Service::FS::CreateDirectoryFromArchive(cecd->cecd_system_save_data_archive, - mbox_path); - } + /// Since the directories/files didn't exist before, we still push a failure + /// A second attempt will then be called, and now everything exists. rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::CEC, ErrorSummary::NotFound, ErrorLevel::Status)); rb.Push(0); /// No bytes read @@ -544,6 +553,151 @@ std::string Module::GetCecDataPathTypeAsString(const CecDataPathType type, const } } +void Module::CreateAndPopulateMBoxDirectory(const u32 ncch_program_id) { + const FileSys::Path root_dir_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_ROOT_DIR, ncch_program_id).data()); + const FileSys::Path mbox_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_MBOX_DIR, ncch_program_id).data()); + const FileSys::Path inbox_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_INBOX_DIR, ncch_program_id).data()); + const FileSys::Path outbox_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_OUTBOX_DIR, ncch_program_id).data()); + + /// Just in case the root dir /CEC doesn't exist, we try to create it first + Service::FS::CreateDirectoryFromArchive(cecd_system_save_data_archive, root_dir_path); + Service::FS::CreateDirectoryFromArchive(cecd_system_save_data_archive, mbox_path); + Service::FS::CreateDirectoryFromArchive(cecd_system_save_data_archive, inbox_path); + Service::FS::CreateDirectoryFromArchive(cecd_system_save_data_archive, outbox_path); + + /// Now that the directories have been created, we can create the required files + FileSys::Mode mode; + mode.write_flag.Assign(1); + mode.create_flag.Assign(1); + + /// MBoxInfo____ resides in the MBox /CEC/ directory, + /// The Magic number is 0x6363 'cc', and has size 0x60 + FileSys::Path mbox_info_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_MBOX_INFO, ncch_program_id).data()); + + auto mbox_info_result = + Service::FS::OpenFileFromArchive(cecd_system_save_data_archive, mbox_info_path, mode); + + constexpr u32 mbox_info_size = 0x60; + auto mbox_info = mbox_info_result.Unwrap(); + std::vector mbox_info_buffer(mbox_info_size); + + std::memset(&mbox_info_buffer[0], 0, mbox_info_size); + mbox_info_buffer[0] = 0x63; + mbox_info_buffer[1] = 0x63; + + mbox_info->backend->Write(0, mbox_info_size, true, mbox_info_buffer.data()); + mbox_info->backend->Close(); + + /// BoxInfo_____ resides in both the InBox and OutBox directories, + /// The Magic number is 0x6262 'bb', and has size 0x20 + FileSys::Path inbox_info_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_INBOX_INFO, ncch_program_id).data()); + + auto inbox_info_result = + Service::FS::OpenFileFromArchive(cecd_system_save_data_archive, inbox_info_path, mode); + + constexpr u32 inbox_info_size = 0x20; + auto inbox_info = inbox_info_result.Unwrap(); + std::vector inbox_info_buffer(inbox_info_size); + + std::memset(&inbox_info_buffer[0], 0, inbox_info_size); + inbox_info_buffer[0] = 0x62; + inbox_info_buffer[1] = 0x62; + + inbox_info->backend->Write(0, inbox_info_size, true, inbox_info_buffer.data()); + inbox_info->backend->Close(); + + /// BoxInfo_____ resides in both the InBox and OutBox directories, + /// The Magic number is 0x6262 'bb', and has size 0x20-byte header, and an array of 0x70-byte + /// entries. Each entry is a copy of the message header. + FileSys::Path outbox_info_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_OUTBOX_INFO, ncch_program_id).data()); + + auto outbox_info_result = + Service::FS::OpenFileFromArchive(cecd_system_save_data_archive, outbox_info_path, mode); + + constexpr u32 outbox_info_size = 0x20; + auto outbox_info = outbox_info_result.Unwrap(); + std::vector outbox_info_buffer(outbox_info_size); + + std::memset(&outbox_info_buffer[0], 0, outbox_info_size); + outbox_info_buffer[0] = 0x62; + outbox_info_buffer[1] = 0x62; + + outbox_info->backend->Write(0, outbox_info_size, true, outbox_info_buffer.data()); + outbox_info->backend->Close(); + + /// OBIndex_____ resides in the OutBox directory, + /// Unknown... + FileSys::Path outbox_index_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_PATH_OUTBOX_INDEX, ncch_program_id).data()); + + auto outbox_index_result = + Service::FS::OpenFileFromArchive(cecd_system_save_data_archive, outbox_index_path, mode); + + constexpr u32 outbox_index_size = 0x32; + auto outbox_index = outbox_index_result.Unwrap(); + std::vector outbox_index_buffer(outbox_index_size); + + std::memset(&outbox_index_buffer[0], 0, outbox_index_size); + + outbox_index->backend->Write(0, outbox_index_size, true, outbox_index_buffer.data()); + outbox_index->backend->Close(); + + /// MBoxData.001 resides in the MBox /CEC/ directory and contains the icon of the app + FileSys::Path mbox_icon_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_MBOX_ICON, ncch_program_id).data()); + + auto mbox_icon_result = + Service::FS::OpenFileFromArchive(cecd_system_save_data_archive, mbox_icon_path, mode); + + constexpr u32 mbox_icon_size = 0x1200; + auto mbox_icon = mbox_icon_result.Unwrap(); + std::vector mbox_icon_buffer(mbox_icon_size); + + std::memset(&mbox_icon_buffer[0], 0, mbox_icon_size); + + mbox_icon->backend->Write(0, mbox_icon_size, true, mbox_icon_buffer.data()); + mbox_icon->backend->Close(); + + /// MBoxData.010 resides in the MBox /CEC/ directory and contains the title of the app + /// in null-terminated UTF-16 string. + FileSys::Path mbox_title_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_MBOX_TITLE, ncch_program_id).data()); + + auto mbox_title_result = + Service::FS::OpenFileFromArchive(cecd_system_save_data_archive, mbox_title_path, mode); + + constexpr u32 mbox_title_size = 0x32; + auto mbox_title = mbox_title_result.Unwrap(); + std::vector mbox_title_buffer(mbox_title_size); + + std::memset(&mbox_title_buffer[0], 0, mbox_title_size); + + mbox_title->backend->Write(0, mbox_title_size, true, mbox_title_buffer.data()); + mbox_title->backend->Close(); + + /// MBoxData.050 resides in the MBox /CEC/ directory and contains the program id of the app + FileSys::Path mbox_program_id_path( + GetCecDataPathTypeAsString(CecDataPathType::CEC_MBOX_PROGRAM_ID, ncch_program_id).data()); + + auto mbox_program_id_result = + Service::FS::OpenFileFromArchive(cecd_system_save_data_archive, mbox_program_id_path, mode); + auto mbox_program_id = mbox_program_id_result.Unwrap(); + + std::vector program_id_buffer(8); + u64_le le_program_id = Kernel::g_current_process->codeset->program_id; + std::memcpy(program_id_buffer.data(), &le_program_id, sizeof(u64)); + + mbox_program_id->backend->Write(0, sizeof(u64), true, program_id_buffer.data()); + mbox_program_id->backend->Close(); +} + Module::SessionData::SessionData() {} Module::SessionData::~SessionData() { diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h index 37e6df0d1..e3573b24d 100644 --- a/src/core/hle/service/cecd/cecd.h +++ b/src/core/hle/service/cecd/cecd.h @@ -534,6 +534,8 @@ private: std::string GetCecDataPathTypeAsString(const CecDataPathType type, const u32 program_id, const std::vector& msg_id = std::vector()) const; + void CreateAndPopulateMBoxDirectory(const u32 ncch_program_id); + Service::FS::ArchiveHandle cecd_system_save_data_archive; Kernel::SharedPtr cecinfo_event;