[XAM] Implementation of: Profile Manager & Profiles Support
Thanks Emoose for Account Encrypt/Decrypt code!
This commit is contained in:
committed by
Radosław Gliński
parent
9ba0f18c82
commit
9bdd07590c
@@ -33,25 +33,32 @@ X_HRESULT_result_t XamUserGetXUID_entry(dword_t user_index, dword_t type_mask,
|
||||
if (!xuid_ptr) {
|
||||
return X_E_INVALIDARG;
|
||||
}
|
||||
|
||||
*xuid_ptr = 0;
|
||||
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!kernel_state()->xam_state()->IsUserSignedIn(user_index)) {
|
||||
return X_E_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
const auto& user_profile =
|
||||
kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
|
||||
uint32_t result = X_E_NO_SUCH_USER;
|
||||
uint64_t xuid = 0;
|
||||
if (user_index < 4) {
|
||||
if (kernel_state()->xam_state()->IsUserSignedIn(user_index)) {
|
||||
const auto& user_profile =
|
||||
kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
auto type = user_profile->type() & type_mask;
|
||||
if (type & (2 | 4)) {
|
||||
// maybe online profile?
|
||||
xuid = user_profile->xuid();
|
||||
result = X_E_SUCCESS;
|
||||
} else if (type & 1) {
|
||||
// maybe offline profile?
|
||||
xuid = user_profile->xuid();
|
||||
result = X_E_SUCCESS;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = X_E_INVALIDARG;
|
||||
|
||||
auto type = user_profile->type() & type_mask;
|
||||
if (type & (2 | 4)) {
|
||||
// maybe online profile?
|
||||
xuid = user_profile->xuid();
|
||||
result = X_E_SUCCESS;
|
||||
} else if (type & 1) {
|
||||
// maybe offline profile?
|
||||
xuid = user_profile->xuid();
|
||||
result = X_E_SUCCESS;
|
||||
}
|
||||
*xuid_ptr = xuid;
|
||||
return result;
|
||||
@@ -62,12 +69,14 @@ dword_result_t XamUserGetSigninState_entry(dword_t user_index) {
|
||||
// Yield, as some games spam this.
|
||||
xe::threading::MaybeYield();
|
||||
uint32_t signin_state = 0;
|
||||
if (user_index < 4) {
|
||||
if (kernel_state()->xam_state()->IsUserSignedIn(user_index)) {
|
||||
const auto& user_profile =
|
||||
kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
signin_state = user_profile->signin_state();
|
||||
}
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return signin_state;
|
||||
}
|
||||
|
||||
if (kernel_state()->xam_state()->IsUserSignedIn(user_index)) {
|
||||
const auto& user_profile =
|
||||
kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
signin_state = user_profile->signin_state();
|
||||
}
|
||||
return signin_state;
|
||||
}
|
||||
@@ -91,12 +100,10 @@ X_HRESULT_result_t XamUserGetSigninInfo_entry(
|
||||
}
|
||||
|
||||
std::memset(info, 0, sizeof(X_USER_SIGNIN_INFO));
|
||||
if (user_index > 3) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_E_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
kernel_state()->xam_state()->UpdateUsedUserProfiles();
|
||||
|
||||
if (kernel_state()->xam_state()->IsUserSignedIn(user_index)) {
|
||||
const auto& user_profile =
|
||||
kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
@@ -113,7 +120,7 @@ DECLARE_XAM_EXPORT1(XamUserGetSigninInfo, kUserProfiles, kImplemented);
|
||||
|
||||
dword_result_t XamUserGetName_entry(dword_t user_index, lpstring_t buffer,
|
||||
dword_t buffer_len) {
|
||||
if (user_index >= 4) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -134,7 +141,7 @@ DECLARE_XAM_EXPORT1(XamUserGetName, kUserProfiles, kImplemented);
|
||||
dword_result_t XamUserGetGamerTag_entry(dword_t user_index,
|
||||
lpu16string_t buffer,
|
||||
dword_t buffer_len) {
|
||||
if (user_index >= 4) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_E_INVALIDARG;
|
||||
}
|
||||
|
||||
@@ -231,9 +238,9 @@ uint32_t XamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index,
|
||||
return X_ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// Title ID = 0 means us.
|
||||
// 0xfffe07d1 = profile?
|
||||
if (!kernel_state()->xam_state()->IsUserSignedIn(user_index) && !xuids) {
|
||||
auto user_profile = kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
|
||||
if (!user_profile && !xuids) {
|
||||
if (overlapped) {
|
||||
kernel_state()->CompleteOverlappedImmediate(
|
||||
kernel_state()->memory()->HostToGuestVirtual(overlapped),
|
||||
@@ -243,8 +250,6 @@ uint32_t XamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index,
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
auto user_profile = kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
|
||||
if (xuids) {
|
||||
uint64_t user_xuid = static_cast<uint64_t>(xuids[0]);
|
||||
if (!kernel_state()->xam_state()->IsUserSignedIn(user_xuid)) {
|
||||
@@ -259,6 +264,10 @@ uint32_t XamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index,
|
||||
user_profile = kernel_state()->xam_state()->GetUserProfile(user_xuid);
|
||||
}
|
||||
|
||||
if (!user_profile) {
|
||||
return X_ERROR_NO_SUCH_USER;
|
||||
}
|
||||
|
||||
// First call asks for size (fill buffer_size_ptr).
|
||||
// Second call asks for buffer contents with that size.
|
||||
|
||||
@@ -355,9 +364,12 @@ dword_result_t XamUserWriteProfileSettings_entry(
|
||||
if (!setting_count || !settings) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
// Update and save settings.
|
||||
const auto& user_profile =
|
||||
kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
|
||||
// Skip writing data about users with id != 0 they're not supported
|
||||
if (user_index > 0) {
|
||||
if (!user_profile) {
|
||||
if (overlapped) {
|
||||
kernel_state()->CompleteOverlappedImmediate(
|
||||
kernel_state()->memory()->HostToGuestVirtual(overlapped),
|
||||
@@ -366,9 +378,6 @@ dword_result_t XamUserWriteProfileSettings_entry(
|
||||
}
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
// Update and save settings.
|
||||
const auto& user_profile =
|
||||
kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
|
||||
for (uint32_t n = 0; n < setting_count; ++n) {
|
||||
const X_USER_PROFILE_SETTING& setting = settings[n];
|
||||
@@ -431,8 +440,8 @@ DECLARE_XAM_EXPORT1(XamUserWriteProfileSettings, kUserProfiles, kImplemented);
|
||||
dword_result_t XamUserCheckPrivilege_entry(dword_t user_index, dword_t mask,
|
||||
lpdword_t out_value) {
|
||||
// checking all users?
|
||||
if (user_index != 0xFF) {
|
||||
if (user_index >= 4) {
|
||||
if (user_index != XUserIndexAny) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -494,7 +503,7 @@ dword_result_t XamUserIsOnlineEnabled_entry(dword_t user_index) { return 1; }
|
||||
DECLARE_XAM_EXPORT1(XamUserIsOnlineEnabled, kUserProfiles, kStub);
|
||||
|
||||
dword_result_t XamUserGetMembershipTier_entry(dword_t user_index) {
|
||||
if (user_index >= 4) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -511,7 +520,7 @@ dword_result_t XamUserAreUsersFriends_entry(dword_t user_index, dword_t unk1,
|
||||
uint32_t are_friends = 0;
|
||||
X_RESULT result;
|
||||
|
||||
if (user_index >= 4) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
result = X_ERROR_INVALID_PARAMETER;
|
||||
} else {
|
||||
if (kernel_state()->xam_state()->IsUserSignedIn(user_index)) {
|
||||
@@ -550,40 +559,6 @@ dword_result_t XamUserAreUsersFriends_entry(dword_t user_index, dword_t unk1,
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamUserAreUsersFriends, kUserProfiles, kStub);
|
||||
|
||||
dword_result_t XamShowSigninUI_entry(dword_t users_needed, dword_t unk_mask) {
|
||||
// XN_SYS_UI (on)
|
||||
kernel_state()->BroadcastNotification(kXNotificationIDSystemUI, 1);
|
||||
kernel_state()->xam_state()->UpdateUsedUserProfiles();
|
||||
// Mask values vary. Probably matching user types? Local/remote?
|
||||
// Games seem to sit and loop until we trigger this notification:
|
||||
|
||||
auto run = [users_needed]() -> void {
|
||||
uint32_t user_mask = 0;
|
||||
uint32_t active_users = 0;
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
if (kernel_state()->xam_state()->IsUserSignedIn(i)) {
|
||||
user_mask |= (1 << i);
|
||||
active_users++;
|
||||
if (active_users >= users_needed) break;
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||
// XN_SYS_SIGNINCHANGED (players)
|
||||
kernel_state()->BroadcastNotification(kXNotificationIDSystemSignInChanged,
|
||||
user_mask);
|
||||
// XN_SYS_UI (off)
|
||||
kernel_state()->BroadcastNotification(kXNotificationIDSystemUI, 0);
|
||||
};
|
||||
|
||||
std::thread thread(run);
|
||||
thread.detach();
|
||||
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamShowSigninUI, kUserProfiles, kStub);
|
||||
|
||||
dword_result_t XamUserCreateAchievementEnumerator_entry(
|
||||
dword_t title_id, dword_t user_index, dword_t xuid, dword_t flags,
|
||||
dword_t offset, dword_t count, lpdword_t buffer_size_ptr,
|
||||
@@ -592,7 +567,7 @@ dword_result_t XamUserCreateAchievementEnumerator_entry(
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (user_index >= 4) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -724,7 +699,7 @@ dword_result_t XamUserGetSubscriptionType_entry(dword_t user_index,
|
||||
dword_t unk2, dword_t unk3,
|
||||
dword_t unk4, dword_t unk5,
|
||||
dword_t unk6) {
|
||||
if (!unk2 || !unk3 || user_index > 4) {
|
||||
if (!unk2 || !unk3 || user_index >= XUserMaxUserCount) {
|
||||
return X_E_INVALIDARG;
|
||||
}
|
||||
|
||||
@@ -749,7 +724,7 @@ dword_result_t XamUserCreateStatsEnumerator_entry(
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (user_index >= 4) {
|
||||
if (user_index >= XUserMaxUserCount) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user