From ffc404a7f6e5d32fa77e83fa832c664ab43d360b Mon Sep 17 00:00:00 2001 From: Daniel Edwards Date: Mon, 2 Jul 2018 08:34:21 +1200 Subject: [PATCH] Added accountGetUserCount and accountListAllUsers (#103) * Added accountGetUserCount and accountListAllUsers --- nx/include/switch/services/acc.h | 13 ++++ nx/source/services/acc.c | 101 +++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/nx/include/switch/services/acc.h b/nx/include/switch/services/acc.h index 35480055..e9067313 100644 --- a/nx/include/switch/services/acc.h +++ b/nx/include/switch/services/acc.h @@ -8,6 +8,8 @@ #include "../types.h" #include "sm.h" +#define ACC_USER_LIST_SIZE 8 + typedef struct { Service s; } AccountProfile; @@ -33,6 +35,17 @@ Result accountInitialize(void); void accountExit(void); Service* accountGetService(void); +/// Get the total number of user profiles +Result accountGetUserCount(s32* user_count); + +/** + * @brief Get a list of all user IDs. The returned list will never be larger than ACC_USER_LIST_SIZE. + * @param userIDs Pointer to array of user IDs. + * @param max_userIDs Maximum number of user IDs to return. + * @param actual_total The actual total number of user IDs found. + */ +Result accountListAllUsers(u128* userIDs, size_t max_userIDs, size_t *actual_total); + /// Get the userID for the currently active user. The output userID is only valid when the output account_selected==1, otherwise no user is currently selected. /// An user is only selected when the user-account selection applet was used to select an user at least once before. Result accountGetActiveUser(u128 *userID, bool *account_selected); diff --git a/nx/source/services/acc.c b/nx/source/services/acc.c index 8c5d04b8..93b8e2e8 100644 --- a/nx/source/services/acc.c +++ b/nx/source/services/acc.c @@ -33,6 +33,107 @@ Service* accountGetService(void) { return &g_accSrv; } +Result accountGetUserCount(s32* user_count) +{ + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + + Result rc = serviceIpcDispatch(&g_accSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u32 user_count; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *user_count = resp->user_count; + } + } + + return rc; +} + +static Result _accountListAllUsers(u128* userIDs) +{ + IpcCommand c; + ipcInitialize(&c); + + Result rc=0; + + size_t bufsize = ACC_USER_LIST_SIZE * sizeof(u128); + + ipcAddRecvStatic(&c, userIDs, bufsize, 0); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 2; + + rc = serviceIpcDispatch(&g_accSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result accountListAllUsers(u128* userIDs, size_t max_userIDs, size_t *actual_total) +{ + Result rc=0; + u128 temp_userIDs[ACC_USER_LIST_SIZE]; + memset(temp_userIDs, 0, sizeof(temp_userIDs)); + + rc = _accountListAllUsers(temp_userIDs); + + if (R_SUCCEEDED(rc)) { + size_t total_userIDs; + for (total_userIDs = 0; total_userIDs < ACC_USER_LIST_SIZE; total_userIDs++) { + if (!temp_userIDs[total_userIDs]) + break; + } + + if (max_userIDs > total_userIDs) { + max_userIDs = total_userIDs; + } + + memcpy(userIDs, temp_userIDs, sizeof(u128) * max_userIDs); + *actual_total = max_userIDs; + } + + return rc; +} + Result accountGetActiveUser(u128 *userID, bool *account_selected) { IpcCommand c;