summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/acc/acc.cpp124
-rw-r--r--src/core/hle/service/acc/acc.h1
-rw-r--r--src/core/hle/service/acc/acc_su.cpp2
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp11
-rw-r--r--src/core/hle/service/acc/profile_manager.h2
5 files changed, 130 insertions, 10 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index c01ee3eda..a7c55e116 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -31,6 +31,9 @@
31 31
32namespace Service::Account { 32namespace Service::Account {
33 33
34constexpr ResultCode ERR_INVALID_BUFFER_SIZE{ErrorModule::Account, 30};
35constexpr ResultCode ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100};
36
34static std::string GetImagePath(Common::UUID uuid) { 37static std::string GetImagePath(Common::UUID uuid) {
35 return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + 38 return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
36 "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; 39 "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg";
@@ -41,20 +44,31 @@ static constexpr u32 SanitizeJPEGSize(std::size_t size) {
41 return static_cast<u32>(std::min(size, max_jpeg_image_size)); 44 return static_cast<u32>(std::min(size, max_jpeg_image_size));
42} 45}
43 46
44class IProfile final : public ServiceFramework<IProfile> { 47class IProfileCommon : public ServiceFramework<IProfileCommon> {
45public: 48public:
46 explicit IProfile(Common::UUID user_id, ProfileManager& profile_manager) 49 explicit IProfileCommon(const char* name, bool editor_commands, Common::UUID user_id,
47 : ServiceFramework("IProfile"), profile_manager(profile_manager), user_id(user_id) { 50 ProfileManager& profile_manager)
51 : ServiceFramework(name), profile_manager(profile_manager), user_id(user_id) {
48 static const FunctionInfo functions[] = { 52 static const FunctionInfo functions[] = {
49 {0, &IProfile::Get, "Get"}, 53 {0, &IProfileCommon::Get, "Get"},
50 {1, &IProfile::GetBase, "GetBase"}, 54 {1, &IProfileCommon::GetBase, "GetBase"},
51 {10, &IProfile::GetImageSize, "GetImageSize"}, 55 {10, &IProfileCommon::GetImageSize, "GetImageSize"},
52 {11, &IProfile::LoadImage, "LoadImage"}, 56 {11, &IProfileCommon::LoadImage, "LoadImage"},
53 }; 57 };
58
54 RegisterHandlers(functions); 59 RegisterHandlers(functions);
60
61 if (editor_commands) {
62 static const FunctionInfo editor_functions[] = {
63 {100, &IProfileCommon::Store, "Store"},
64 {101, &IProfileCommon::StoreWithImage, "StoreWithImage"},
65 };
66
67 RegisterHandlers(editor_functions);
68 }
55 } 69 }
56 70
57private: 71protected:
58 void Get(Kernel::HLERequestContext& ctx) { 72 void Get(Kernel::HLERequestContext& ctx) {
59 LOG_INFO(Service_ACC, "called user_id={}", user_id.Format()); 73 LOG_INFO(Service_ACC, "called user_id={}", user_id.Format());
60 ProfileBase profile_base{}; 74 ProfileBase profile_base{};
@@ -127,10 +141,91 @@ private:
127 } 141 }
128 } 142 }
129 143
130 const ProfileManager& profile_manager; 144 void Store(Kernel::HLERequestContext& ctx) {
145 IPC::RequestParser rp{ctx};
146 const auto base = rp.PopRaw<ProfileBase>();
147
148 const auto user_data = ctx.ReadBuffer();
149
150 LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid={}",
151 Common::StringFromFixedZeroTerminatedBuffer(
152 reinterpret_cast<const char*>(base.username.data()), base.username.size()),
153 base.timestamp, base.user_uuid.Format());
154
155 if (user_data.size() < sizeof(ProfileData)) {
156 LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
157 IPC::ResponseBuilder rb{ctx, 2};
158 rb.Push(ERR_INVALID_BUFFER_SIZE);
159 return;
160 }
161
162 ProfileData data;
163 std::memcpy(&data, user_data.data(), sizeof(ProfileData));
164
165 if (!profile_manager.SetProfileBaseAndData(user_id, base, data)) {
166 LOG_ERROR(Service_ACC, "Failed to update profile data and base!");
167 IPC::ResponseBuilder rb{ctx, 2};
168 rb.Push(ERR_FAILED_SAVE_DATA);
169 return;
170 }
171
172 IPC::ResponseBuilder rb{ctx, 2};
173 rb.Push(RESULT_SUCCESS);
174 }
175
176 void StoreWithImage(Kernel::HLERequestContext& ctx) {
177 IPC::RequestParser rp{ctx};
178 const auto base = rp.PopRaw<ProfileBase>();
179
180 const auto user_data = ctx.ReadBuffer();
181 const auto image_data = ctx.ReadBuffer(1);
182
183 LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid={}",
184 Common::StringFromFixedZeroTerminatedBuffer(
185 reinterpret_cast<const char*>(base.username.data()), base.username.size()),
186 base.timestamp, base.user_uuid.Format());
187
188 if (user_data.size() < sizeof(ProfileData)) {
189 LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
190 IPC::ResponseBuilder rb{ctx, 2};
191 rb.Push(ERR_INVALID_BUFFER_SIZE);
192 return;
193 }
194
195 ProfileData data;
196 std::memcpy(&data, user_data.data(), sizeof(ProfileData));
197
198 FileUtil::IOFile image(GetImagePath(user_id), "wb");
199
200 if (!image.IsOpen() || !image.Resize(image_data.size()) ||
201 image.WriteBytes(image_data.data(), image_data.size()) != image_data.size() ||
202 !profile_manager.SetProfileBaseAndData(user_id, base, data)) {
203 LOG_ERROR(Service_ACC, "Failed to update profile data, base, and image!");
204 IPC::ResponseBuilder rb{ctx, 2};
205 rb.Push(ERR_FAILED_SAVE_DATA);
206 return;
207 }
208
209 IPC::ResponseBuilder rb{ctx, 2};
210 rb.Push(RESULT_SUCCESS);
211 }
212
213 ProfileManager& profile_manager;
131 Common::UUID user_id; ///< The user id this profile refers to. 214 Common::UUID user_id; ///< The user id this profile refers to.
132}; 215};
133 216
217class IProfile final : public IProfileCommon {
218public:
219 IProfile(Common::UUID user_id, ProfileManager& profile_manager)
220 : IProfileCommon("IProfile", false, user_id, profile_manager) {}
221};
222
223class IProfileEditor final : public IProfileCommon {
224public:
225 IProfileEditor(Common::UUID user_id, ProfileManager& profile_manager)
226 : IProfileCommon("IProfileEditor", true, user_id, profile_manager) {}
227};
228
134class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { 229class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
135public: 230public:
136 IManagerForApplication() : ServiceFramework("IManagerForApplication") { 231 IManagerForApplication() : ServiceFramework("IManagerForApplication") {
@@ -322,6 +417,17 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx
322 rb.Push(is_locked); 417 rb.Push(is_locked);
323} 418}
324 419
420void Module::Interface::GetProfileEditor(Kernel::HLERequestContext& ctx) {
421 IPC::RequestParser rp{ctx};
422 Common::UUID user_id = rp.PopRaw<Common::UUID>();
423
424 LOG_DEBUG(Service_ACC, "called, user_id={}", user_id.Format());
425
426 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
427 rb.Push(RESULT_SUCCESS);
428 rb.PushIpcInterface<IProfileEditor>(user_id, *profile_manager);
429}
430
325void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) { 431void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) {
326 LOG_DEBUG(Service_ACC, "called"); 432 LOG_DEBUG(Service_ACC, "called");
327 // A u8 is passed into this function which we can safely ignore. It's to determine if we have 433 // A u8 is passed into this function which we can safely ignore. It's to determine if we have
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index f651773b7..7a7dc9ec6 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -32,6 +32,7 @@ public:
32 void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx); 32 void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx);
33 void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx); 33 void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx);
34 void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx); 34 void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx);
35 void GetProfileEditor(Kernel::HLERequestContext& ctx);
35 36
36 private: 37 private:
37 ResultCode InitializeApplicationInfoBase(u64 process_id); 38 ResultCode InitializeApplicationInfoBase(u64 process_id);
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 1b7ec3ed0..0d1663657 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -41,7 +41,7 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
41 {202, nullptr, "CancelUserRegistration"}, 41 {202, nullptr, "CancelUserRegistration"},
42 {203, nullptr, "DeleteUser"}, 42 {203, nullptr, "DeleteUser"},
43 {204, nullptr, "SetUserPosition"}, 43 {204, nullptr, "SetUserPosition"},
44 {205, nullptr, "GetProfileEditor"}, 44 {205, &ACC_SU::GetProfileEditor, "GetProfileEditor"},
45 {206, nullptr, "CompleteUserRegistrationForcibly"}, 45 {206, nullptr, "CompleteUserRegistrationForcibly"},
46 {210, nullptr, "CreateFloatingRegistrationRequest"}, 46 {210, nullptr, "CreateFloatingRegistrationRequest"},
47 {230, nullptr, "AuthenticateServiceAsync"}, 47 {230, nullptr, "AuthenticateServiceAsync"},
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 49aa5908b..8f9986326 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -305,6 +305,17 @@ bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
305 return true; 305 return true;
306} 306}
307 307
308bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new,
309 const ProfileData& data_new) {
310 const auto index = GetUserIndex(uuid);
311 if (index.has_value() && SetProfileBase(uuid, profile_new)) {
312 profiles[*index].data = data_new;
313 return true;
314 }
315
316 return false;
317}
318
308void ProfileManager::ParseUserSaveFile() { 319void ProfileManager::ParseUserSaveFile() {
309 FileUtil::IOFile save(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + 320 FileUtil::IOFile save(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
310 ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat", 321 ACC_SAVE_AVATORS_BASE_PATH + "profiles.dat",
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index fd7abb541..5a6d28925 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -91,6 +91,8 @@ public:
91 91
92 bool RemoveUser(Common::UUID uuid); 92 bool RemoveUser(Common::UUID uuid);
93 bool SetProfileBase(Common::UUID uuid, const ProfileBase& profile_new); 93 bool SetProfileBase(Common::UUID uuid, const ProfileBase& profile_new);
94 bool SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new,
95 const ProfileData& data_new);
94 96
95private: 97private:
96 void ParseUserSaveFile(); 98 void ParseUserSaveFile();