From 45f2a2fe29373f261144c097d169dad8b65fe012 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 13 Oct 2018 13:02:33 -0400 Subject: acc: Fix account UUID duplication error --- src/core/hle/service/acc/acc.cpp | 9 +++++++-- src/core/hle/service/acc/profile_manager.cpp | 24 ++++++++++++++++++----- src/core/hle/service/acc/profile_manager.h | 2 ++ src/core/hle/service/am/am.cpp | 29 ++++++++++++++++++---------- 4 files changed, 47 insertions(+), 17 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index cee309cb1..cf065c2e0 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -106,6 +106,8 @@ private: const FileUtil::IOFile image(GetImagePath(user_id), "rb"); if (!image.IsOpen()) { + LOG_WARNING(Service_ACC, + "Failed to load user provided image! Falling back to built-in backup..."); ctx.WriteBuffer(backup_jpeg); rb.Push(backup_jpeg_size); } else { @@ -126,10 +128,13 @@ private: const FileUtil::IOFile image(GetImagePath(user_id), "rb"); - if (!image.IsOpen()) + if (!image.IsOpen()) { + LOG_WARNING(Service_ACC, + "Failed to load user provided image! Falling back to built-in backup..."); rb.Push(backup_jpeg_size); - else + } else { rb.Push(std::min(image.GetSize(), MAX_JPEG_IMAGE_SIZE)); + } } const ProfileManager& profile_manager; diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 43743d39e..e6f1a0ae8 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -30,6 +30,8 @@ constexpr ResultCode ERROR_TOO_MANY_USERS(ErrorModule::Account, -1); constexpr ResultCode ERROR_USER_ALREADY_EXISTS(ErrorModule::Account, -2); constexpr ResultCode ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20); +constexpr const char* ACC_SAVE_AVATORS_BASE_PATH = "/system/save/8000000000000010/su/avators/"; + const UUID& UUID::Generate() { std::random_device device; std::mt19937 gen(device()); @@ -45,11 +47,11 @@ ProfileManager::ProfileManager() { if (user_count == 0) CreateNewUser(UUID{}.Generate(), "yuzu"); - auto current = Settings::values.current_user; - if (!GetAllUsers()[current]) + auto current = std::clamp(Settings::values.current_user, 0, MAX_USERS - 1); + if (UserExistsIndex(current)) current = 0; - OpenUser(GetAllUsers()[current]); + OpenUser(*GetUser(current)); } ProfileManager::~ProfileManager() { @@ -126,6 +128,12 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) return CreateNewUser(uuid, username_output); } +boost::optional ProfileManager::GetUser(std::size_t index) const { + if (index >= MAX_USERS) + return boost::none; + return profiles[index].user_uuid; +} + /// Returns a users profile index based on their user id. boost::optional ProfileManager::GetUserIndex(const UUID& uuid) const { if (!uuid) { @@ -189,6 +197,12 @@ bool ProfileManager::UserExists(UUID uuid) const { return (GetUserIndex(uuid) != boost::none); } +bool ProfileManager::UserExistsIndex(std::size_t index) const { + if (index >= MAX_USERS) + return false; + return profiles[index].user_uuid.uuid != INVALID_UUID; +} + /// Opens a specific user void ProfileManager::OpenUser(UUID uuid) { auto idx = GetUserIndex(uuid); @@ -292,7 +306,7 @@ bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) { void ProfileManager::ParseUserSaveFile() { FileUtil::IOFile save(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + - "/system/save/8000000000000010/su/avators/profiles.dat", + ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat", "rb"); ProfileDataRaw data; @@ -322,7 +336,7 @@ void ProfileManager::WriteUserSaveFile() { } FileUtil::IOFile save(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + - "/system/save/8000000000000010/su/avators/profiles.dat", + ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat", "wb"); save.Resize(sizeof(ProfileDataRaw)); diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h index 1e5c2460e..482c1d8a9 100644 --- a/src/core/hle/service/acc/profile_manager.h +++ b/src/core/hle/service/acc/profile_manager.h @@ -96,6 +96,7 @@ public: ResultCode AddUser(const ProfileInfo& user); ResultCode CreateNewUser(UUID uuid, const ProfileUsername& username); ResultCode CreateNewUser(UUID uuid, const std::string& username); + boost::optional GetUser(std::size_t index) const; boost::optional GetUserIndex(const UUID& uuid) const; boost::optional GetUserIndex(const ProfileInfo& user) const; bool GetProfileBase(boost::optional index, ProfileBase& profile) const; @@ -109,6 +110,7 @@ public: std::size_t GetUserCount() const; std::size_t GetOpenUserCount() const; bool UserExists(UUID uuid) const; + bool UserExistsIndex(std::size_t index) const; void OpenUser(UUID uuid); void CloseUser(UUID uuid); UserIDArray GetOpenUsers() const; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 9dfcec59b..4ed66d817 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -28,7 +28,15 @@ namespace Service::AM { -constexpr std::size_t POP_LAUNCH_PARAMETER_BUFFER_SIZE = 0x88; +constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA; + +struct LaunchParameters { + u32_le magic; + u32_le is_account_selected; + u128 current_user; + INSERT_PADDING_BYTES(0x70); +}; +static_assert(sizeof(LaunchParameters) == 0x88); IWindowController::IWindowController() : ServiceFramework("IWindowController") { // clang-format off @@ -728,22 +736,23 @@ void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx } void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { - constexpr std::array header_data{ - 0xca, 0x97, 0x94, 0xc7, // Magic - 1, 0, 0, 0, // IsAccountSelected (bool) - }; + LaunchParameters params{}; - std::vector buffer(POP_LAUNCH_PARAMETER_BUFFER_SIZE); - - std::memcpy(buffer.data(), header_data.data(), header_data.size()); + params.magic = POP_LAUNCH_PARAMETER_MAGIC; + params.is_account_selected = 1; Account::ProfileManager profile_manager{}; - const auto uuid = profile_manager.GetAllUsers()[Settings::values.current_user].uuid; - std::memcpy(buffer.data() + header_data.size(), uuid.data(), sizeof(u128)); + const auto uuid = profile_manager.GetUser(Settings::values.current_user); + ASSERT(uuid != boost::none); + params.current_user = uuid->uuid; IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); + + std::vector buffer(sizeof(LaunchParameters)); + std::memcpy(buffer.data(), ¶ms, buffer.size()); + rb.PushIpcInterface(buffer); LOG_DEBUG(Service_AM, "called"); -- cgit v1.2.3