From 1aa2b99a982e83022c9aae23c6a47eae119d21a4 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 27 Dec 2018 20:54:44 -0500 Subject: [PATCH] mii: Implement Delete and Destroy file --- src/common/uuid.h | 11 +-- src/core/hle/service/mii/mii.cpp | 87 +++++++++++++++++++++--- src/core/hle/service/mii/mii_manager.cpp | 27 ++++++++ src/core/hle/service/mii/mii_manager.h | 10 +++ 4 files changed, 122 insertions(+), 13 deletions(-) diff --git a/src/common/uuid.h b/src/common/uuid.h index b8864b34fb..f6ad064fb7 100644 --- a/src/common/uuid.h +++ b/src/common/uuid.h @@ -19,15 +19,16 @@ struct UUID { constexpr explicit UUID(const u128& id) : uuid{id} {} constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} - explicit operator bool() const { - return uuid != INVALID_UUID; + constexpr explicit operator bool() const { + return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1]; } - bool operator==(const UUID& rhs) const { - return uuid == rhs.uuid; + constexpr bool operator==(const UUID& rhs) const { + // TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20 + return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1]; } - bool operator!=(const UUID& rhs) const { + constexpr bool operator!=(const UUID& rhs) const { return !operator==(rhs); } diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 39e4e937a5..ce84e25ed2 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -4,6 +4,8 @@ #include +#include + #include "common/logging/log.h" #include "common/string_util.h" #include "core/hle/ipc_helpers.h" @@ -15,6 +17,10 @@ namespace Service::Mii { +constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1}; +constexpr ResultCode ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4}; +constexpr ResultCode ERROR_NOT_IN_TEST_MODE{ErrorModule::Mii, 99}; + class IDatabaseService final : public ServiceFramework { public: explicit IDatabaseService() : ServiceFramework{"IDatabaseService"} { @@ -35,8 +41,8 @@ public: {12, &IDatabaseService::Move, "Move"}, {13, &IDatabaseService::AddOrReplace, "AddOrReplace"}, {14, &IDatabaseService::Delete, "Delete"}, - {15, nullptr, "DestroyFile"}, - {16, nullptr, "DeleteFile"}, + {15, &IDatabaseService::DestroyFile, "DestroyFile"}, + {16, &IDatabaseService::DeleteFile, "DeleteFile"}, {17, &IDatabaseService::Format, "Format"}, {18, nullptr, "Import"}, {19, nullptr, "Export"}, @@ -135,12 +141,33 @@ private: void BuildRandom(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto random_params{rp.PopRaw()}; + const auto [unknown1, unknown2, unknown3] = rp.PopRaw(); + + if (unknown1 > 3) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_INVALID_ARGUMENT); + LOG_ERROR(Service_Mii, "Invalid unknown1 value: {}", unknown1); + return; + } + + if (unknown2 > 2) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_INVALID_ARGUMENT); + LOG_ERROR(Service_Mii, "Invalid unknown2 value: {}", unknown2); + return; + } + + if (unknown3 > 3) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_INVALID_ARGUMENT); + LOG_ERROR(Service_Mii, "Invalid unknown3 value: {}", unknown3); + return; + } LOG_DEBUG(Service_Mii, "called with param_1={:08X}, param_2={:08X}, param_3={:08X}", - random_params.unknown_1, random_params.unknown_2, random_params.unknown_3); + unknown1, unknown2, unknown3); - const auto info = db.CreateRandom(random_params); + const auto info = db.CreateRandom({unknown1, unknown2, unknown3}); IPC::ResponseBuilder rb{ctx, 2 + sizeof(MiiInfo) / sizeof(u32)}; rb.Push(RESULT_SUCCESS); rb.PushRaw(info); @@ -150,6 +177,14 @@ private: IPC::RequestParser rp{ctx}; const auto index{rp.PopRaw()}; + if (index > 5) { + LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}", + index); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_INVALID_ARGUMENT); + return; + } + LOG_DEBUG(Service_Mii, "called with index={:08X}", index); const auto info = db.CreateDefault(index); @@ -218,7 +253,14 @@ private: void Move(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto uuid{rp.PopRaw()}; - const auto index{rp.PopRaw()}; + const auto index{rp.PopRaw()}; + + if (index < 0) { + LOG_ERROR(Service_Mii, "Index cannot be negative but is {:08X}!", index); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_INVALID_ARGUMENT); + return; + } LOG_DEBUG(Service_Mii, "called with uuid={}, index={:08X}", uuid.FormatSwitch(), index); @@ -252,8 +294,37 @@ private: const auto success = db.Remove(uuid); IPC::ResponseBuilder rb{ctx, 2}; - // TODO(DarkLordZach): Find a better error code - rb.Push(success ? RESULT_SUCCESS : ResultCode(-1)); + rb.Push(success ? RESULT_SUCCESS : ERROR_CANNOT_FIND_ENTRY); + } + + void DestroyFile(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Mii, "called"); + + if (!db.IsTestModeEnabled()) { + LOG_ERROR(Service_Mii, "Database is not in test mode -- cannot destory database file."); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_NOT_IN_TEST_MODE); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(db.DestroyFile()); + } + + void DeleteFile(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Mii, "called"); + + if (!db.IsTestModeEnabled()) { + LOG_ERROR(Service_Mii, "Database is not in test mode -- cannot delete database file."); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_NOT_IN_TEST_MODE); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(db.DeleteFile()); } void Format(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index 7011ea2bd1..04fc2180b9 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -32,6 +32,13 @@ constexpr MiiStoreData DEFAULT_MII = { // Default values taken from multiple real databases const MiiDatabase DEFAULT_MII_DATABASE{Common::MakeMagic('N', 'F', 'D', 'B'), {}, {1}, 0, 0}; +constexpr std::array SOURCE_NAMES{ + "Database", + "Default", + "Account", + "Friend", +}; + template std::array ResizeArray(const std::array& in) { std::array out{}; @@ -167,6 +174,11 @@ MiiStoreData ConvertInfoToStoreData(const MiiInfo& info) { } // namespace +std::ostream& operator<<(std::ostream& os,Source source) { + os << SOURCE_NAMES.at(static_cast(source)); + return os; +} + std::u16string MiiInfo::Name() const { return Common::UTF16StringFromFixedZeroTerminatedBuffer(name.data(), name.size()); } @@ -212,6 +224,10 @@ void MiiManager::ResetUpdatedFlag() { updated_flag = false; } +bool MiiManager::IsTestModeEnabled() const { + return is_test_mode_enabled; +} + bool MiiManager::Empty() const { return Size() == 0; } @@ -318,6 +334,17 @@ bool MiiManager::AddOrReplace(const MiiStoreData& data) { return true; } +bool MiiManager::DestroyFile() { + database = DEFAULT_MII_DATABASE; + updated_flag = false; + return DeleteFile(); +} + +bool MiiManager::DeleteFile() { + const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + MII_SAVE_DATABASE_PATH; + return FileUtil::Exists(path) && FileUtil::Delete(path); +} + void MiiManager::WriteToFile() { const auto raw_path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000030"; diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index bf955930db..38ad78a0d8 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h @@ -27,6 +27,8 @@ enum class Source : u32 { Friend = 3, }; +std::ostream& operator<<(std::ostream& os, Source source); + struct MiiInfo { Common::UUID uuid; std::array name; @@ -183,6 +185,8 @@ struct MiiStoreBitFields { }; }; static_assert(sizeof(MiiStoreBitFields) == 0x1C, "MiiStoreBitFields has incorrect size."); +static_assert(std::is_trivially_copyable_v, + "MiiStoreBitFields is not trivially copyable."); struct MiiStoreData { // This corresponds to the above structure MiiStoreBitFields. I did it like this because the @@ -229,6 +233,8 @@ public: bool CheckUpdatedFlag() const; void ResetUpdatedFlag(); + bool IsTestModeEnabled() const; + bool Empty() const; bool Full() const; @@ -248,6 +254,9 @@ public: bool Move(Common::UUID uuid, u32 new_index); bool AddOrReplace(const MiiStoreData& data); + bool DestroyFile(); + bool DeleteFile(); + private: void WriteToFile(); void ReadFromFile(); @@ -258,6 +267,7 @@ private: MiiDatabase database; bool updated_flag = false; + bool is_test_mode_enabled = false; }; }; // namespace Service::Mii