diff --git a/src/xenia/kernel/xam/profile_manager.cc b/src/xenia/kernel/xam/profile_manager.cc index 719743cd8..51c4a4e49 100644 --- a/src/xenia/kernel/xam/profile_manager.cc +++ b/src/xenia/kernel/xam/profile_manager.cc @@ -54,9 +54,6 @@ bool ProfileManager::DecryptAccountFile(const uint8_t* data, if (std::memcmp(data, data_hash, 0x10) == 0) { // Copy account data to output std::memcpy(output, dec_data + 8, sizeof(X_XAMACCOUNTINFO)); - - // Swap gamertag endian - xe::copy_and_swap(output->gamertag, output->gamertag, 0x10); return true; } @@ -74,10 +71,6 @@ void ProfileManager::EncryptAccountFile(const X_XAMACCOUNTINFO* input, reinterpret_cast(output + 0x18); std::memcpy(output_acct, input, sizeof(X_XAMACCOUNTINFO)); - // Swap gamertag endian - xe::copy_and_swap(output_acct->gamertag, output_acct->gamertag, - 0x10); - // Set confounder, should be random but meh std::memset(output + 0x10, 0xFD, 8); @@ -500,10 +493,10 @@ const X_XAMACCOUNTINFO* ProfileManager::GetAccount(const uint64_t xuid) { bool ProfileManager::CreateAccount(const uint64_t xuid, const std::string gamertag) { X_XAMACCOUNTINFO account = {}; - std::u16string gamertag_u16 = xe::to_utf16(gamertag); + const std::u16string gamertag_u16 = xe::to_utf16(gamertag); - string_util::copy_truncating(account.gamertag, gamertag_u16, - sizeof(account.gamertag)); + string_util::copy_and_swap_truncating(account.gamertag, gamertag_u16, + sizeof(account.gamertag)); const bool result = UpdateAccount(xuid, &account); DismountProfile(xuid); diff --git a/src/xenia/kernel/xam/profile_manager.h b/src/xenia/kernel/xam/profile_manager.h index a769912e7..ad9bf5321 100644 --- a/src/xenia/kernel/xam/profile_manager.h +++ b/src/xenia/kernel/xam/profile_manager.h @@ -44,6 +44,13 @@ inline const std::string kDashboardStringID = constexpr std::string_view kDefaultMountFormat = "User_{:016X}"; +const static inline uint64_t GenerateXuid() { + std::random_device rd; + std::mt19937 gen(rd()); + + return ((uint64_t)0xE03 << 52) + (gen() % (1 << 31)); +} + class ProfileManager { public: static bool DecryptAccountFile(const uint8_t* data, X_XAMACCOUNTINFO* output, @@ -116,13 +123,6 @@ class ProfileManager { uint8_t FindFirstFreeProfileSlot() const; std::bitset GetUsedUserSlots() const; - uint64_t GenerateXuid() const { - std::random_device rd; - std::mt19937 gen(rd()); - - return ((uint64_t)0xE03 << 52) + (gen() % (1 << 31)); - } - std::map accounts_; std::map> logged_profiles_; diff --git a/src/xenia/kernel/xam/ui/gamercard_ui.cc b/src/xenia/kernel/xam/ui/gamercard_ui.cc index 2fda1893c..d527aef2c 100644 --- a/src/xenia/kernel/xam/ui/gamercard_ui.cc +++ b/src/xenia/kernel/xam/ui/gamercard_ui.cc @@ -620,10 +620,10 @@ void GamercardUI::SaveAccountData() { account.SetSubscriptionTier(gamercardValues_.account_subscription_tier); account.ToggleLiveFlag(gamercardValues_.is_live_enabled); - std::u16string gamertag = + const std::u16string gamertag = xe::to_utf16(std::string(gamercardValues_.gamertag)); - string_util::copy_truncating(account.gamertag, gamertag, - std::size(account.gamertag)); + string_util::copy_and_swap_truncating(account.gamertag, gamertag, + std::size(account.gamertag)); if (std::memcmp(&account, &account_original, sizeof(X_XAMACCOUNTINFO)) != 0) { if (!is_signed_in_) { diff --git a/src/xenia/kernel/xam/xam.h b/src/xenia/kernel/xam/xam.h index a03ce098e..8991965fc 100644 --- a/src/xenia/kernel/xam/xam.h +++ b/src/xenia/kernel/xam/xam.h @@ -99,7 +99,7 @@ struct X_XAMACCOUNTINFO { } std::string GetGamertagString() const { - return xe::to_utf8(std::u16string(gamertag)); + return xe::to_utf8(xe::string_util::read_u16string_and_swap(gamertag)); } void ToggleLiveFlag(bool is_live) { @@ -293,7 +293,7 @@ struct X_PROFILE_CREATION_INFO { X_PASSPORT_SESSION_TOKEN user_token; X_PASSPORT_SESSION_TOKEN owner_token; uint32_t task_handle_ptr; - uint32_t unk2; + uint32_t profile_creation_ptr; }; static_assert_size(X_PROFILE_CREATION_INFO, 0xAC0); diff --git a/src/xenia/kernel/xam/xam_profile.cc b/src/xenia/kernel/xam/xam_profile.cc index 8cc002f3b..d0d0c57f0 100644 --- a/src/xenia/kernel/xam/xam_profile.cc +++ b/src/xenia/kernel/xam/xam_profile.cc @@ -9,6 +9,7 @@ #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" +#include "xenia/kernel/xam/profile_manager.h" #include "xenia/kernel/xam/xam_private.h" namespace xe { @@ -70,42 +71,41 @@ dword_result_t XamProfileCreate_entry( pointer_t payment_info, pointer_t user_token, pointer_t owner_token, - pointer_t profile_info_ptr) { - if ((flags & 0x80000000) == 0x80000000) { - profile_info_ptr->flags = flags & 0x7fffffff; - profile_info_ptr->unk2 = 1; - } else { - profile_info_ptr->flags = flags; - profile_info_ptr->unk2 = 0; - } + lpdword_t profile_info_ptr) { + *profile_info_ptr = + kernel_memory()->SystemHeapAlloc(sizeof(X_PROFILE_CREATION_INFO)); + kernel_memory()->Fill(*profile_info_ptr, sizeof(X_PROFILE_CREATION_INFO), 0); + + auto profile_info = + kernel_memory()->TranslateVirtual( + *profile_info_ptr); + + profile_info->flags = flags & 0x7fffffff; if (device_id) { *device_id = 0x1; - profile_info_ptr->device_id = *device_id; + profile_info->device_id = *device_id; } - profile_info_ptr->offline_xuid = xuid; - profile_info_ptr->account_info = *account; - - X_XAMACCOUNTINFO account_info_data; - memcpy(&account_info_data, account, sizeof(X_XAMACCOUNTINFO)); - xe::copy_and_swap(account_info_data.gamertag, - account_info_data.gamertag, 16); + const uint64_t proper_xuid = + xuid == 0 ? GenerateXuid() : static_cast(xuid); + profile_info->offline_xuid = proper_xuid; + profile_info->account_info = *account; if (payment_info) { - profile_info_ptr->user_payment_info = *payment_info; + profile_info->user_payment_info = *payment_info; } if (user_token) { - profile_info_ptr->user_token = *user_token; + profile_info->user_token = *user_token; } if (owner_token) { - profile_info_ptr->owner_token = *owner_token; + profile_info->owner_token = *owner_token; } // calls XamTaskSchedule bool result = kernel_state()->xam_state()->profile_manager()->CreateProfile( - &account_info_data, xuid); + &profile_info->account_info, proper_xuid); return result ? X_ERROR_SUCCESS : X_ERROR_INVALID_PARAMETER; } @@ -128,7 +128,16 @@ dword_result_t XamProfileGetCreationStatus_entry( // XamTaskGetStatus(profile_info->task_handle_ptr); // if (result == 0) { // result = XamTaskGetCompletionStatus(profile_info->task_handle_ptr) + + // Custom safeguard + if (!profile_info) { + XELOGE("XamProfileGetCreationStatus: Invalid profile_info provided!"); + return X_ERROR_SUCCESS; + } + *offline_xuid = profile_info->offline_xuid; + + kernel_state()->memory()->SystemHeapFree(profile_info.guest_address()); // XamTaskCloseHandle(profile_info->task_handle_ptr); //} return X_ERROR_SUCCESS; // result diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 3dbe9fe0c..45e0192cf 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -518,13 +518,6 @@ dword_result_t XamShowDeviceSelectorUI_entry( return X_ERROR_INVALID_PARAMETER; } - if (user_index != XUserIndexAny && - !kernel_state()->xam_state()->IsUserSignedIn(user_index)) { - kernel_state()->CompleteOverlappedImmediate(overlapped, - X_ERROR_NO_SUCH_USER); - return X_ERROR_IO_PENDING; - } - std::vector devices = ListStorageDevices(); if (cvars::headless || !cvars::storage_selection_dialog) {