diff options
Diffstat (limited to 'src')
40 files changed, 529 insertions, 609 deletions
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index ae7a3511b..aa4726cfa 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -35,7 +35,7 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw_file) { | |||
| 35 | update_raw = std::move(update_raw_file); | 35 | update_raw = std::move(update_raw_file); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { | 38 | VirtualFile RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { |
| 39 | if (!updatable) { | 39 | if (!updatable) { |
| 40 | return file; | 40 | return file; |
| 41 | } | 41 | } |
| @@ -45,12 +45,11 @@ ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_titl | |||
| 45 | return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw); | 45 | return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const { | 48 | VirtualFile RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const { |
| 49 | auto nca = content_provider.GetEntry(title_id, type); | 49 | auto nca = content_provider.GetEntry(title_id, type); |
| 50 | 50 | ||
| 51 | if (nca == nullptr) { | 51 | if (nca == nullptr) { |
| 52 | // TODO: Find the right error code to use here | 52 | return nullptr; |
| 53 | return ResultUnknown; | ||
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | const PatchManager patch_manager{title_id, filesystem_controller, content_provider}; | 55 | const PatchManager patch_manager{title_id, filesystem_controller, content_provider}; |
| @@ -58,28 +57,20 @@ ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecor | |||
| 58 | return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type); | 57 | return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type); |
| 59 | } | 58 | } |
| 60 | 59 | ||
| 61 | ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFSWithProgramIndex( | 60 | VirtualFile RomFSFactory::OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, |
| 62 | u64 title_id, u8 program_index, ContentRecordType type) const { | 61 | ContentRecordType type) const { |
| 63 | const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index); | 62 | const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index); |
| 64 | 63 | ||
| 65 | return OpenPatchedRomFS(res_title_id, type); | 64 | return OpenPatchedRomFS(res_title_id, type); |
| 66 | } | 65 | } |
| 67 | 66 | ||
| 68 | ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, | 67 | VirtualFile RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) const { |
| 69 | ContentRecordType type) const { | ||
| 70 | const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type); | 68 | const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type); |
| 71 | if (res == nullptr) { | 69 | if (res == nullptr) { |
| 72 | // TODO(DarkLordZach): Find the right error code to use here | 70 | return nullptr; |
| 73 | return ResultUnknown; | ||
| 74 | } | ||
| 75 | |||
| 76 | const auto romfs = res->GetRomFS(); | ||
| 77 | if (romfs == nullptr) { | ||
| 78 | // TODO(DarkLordZach): Find the right error code to use here | ||
| 79 | return ResultUnknown; | ||
| 80 | } | 71 | } |
| 81 | 72 | ||
| 82 | return romfs; | 73 | return res->GetRomFS(); |
| 83 | } | 74 | } |
| 84 | 75 | ||
| 85 | std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage, | 76 | std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage, |
diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h index 14936031f..7ec40d19d 100644 --- a/src/core/file_sys/romfs_factory.h +++ b/src/core/file_sys/romfs_factory.h | |||
| @@ -41,13 +41,11 @@ public: | |||
| 41 | ~RomFSFactory(); | 41 | ~RomFSFactory(); |
| 42 | 42 | ||
| 43 | void SetPackedUpdate(VirtualFile update_raw_file); | 43 | void SetPackedUpdate(VirtualFile update_raw_file); |
| 44 | [[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const; | 44 | [[nodiscard]] VirtualFile OpenCurrentProcess(u64 current_process_title_id) const; |
| 45 | [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id, | 45 | [[nodiscard]] VirtualFile OpenPatchedRomFS(u64 title_id, ContentRecordType type) const; |
| 46 | ContentRecordType type) const; | 46 | [[nodiscard]] VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, |
| 47 | [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFSWithProgramIndex( | 47 | ContentRecordType type) const; |
| 48 | u64 title_id, u8 program_index, ContentRecordType type) const; | 48 | [[nodiscard]] VirtualFile Open(u64 title_id, StorageId storage, ContentRecordType type) const; |
| 49 | [[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage, | ||
| 50 | ContentRecordType type) const; | ||
| 51 | 49 | ||
| 52 | private: | 50 | private: |
| 53 | [[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage, | 51 | [[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage, |
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index 70b36f170..a4d060007 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp | |||
| @@ -108,26 +108,16 @@ SaveDataFactory::SaveDataFactory(Core::System& system_, VirtualDir save_director | |||
| 108 | 108 | ||
| 109 | SaveDataFactory::~SaveDataFactory() = default; | 109 | SaveDataFactory::~SaveDataFactory() = default; |
| 110 | 110 | ||
| 111 | ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space, | 111 | VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const { |
| 112 | const SaveDataAttribute& meta) const { | ||
| 113 | PrintSaveDataAttributeWarnings(meta); | 112 | PrintSaveDataAttributeWarnings(meta); |
| 114 | 113 | ||
| 115 | const auto save_directory = | 114 | const auto save_directory = |
| 116 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); | 115 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); |
| 117 | 116 | ||
| 118 | auto out = dir->CreateDirectoryRelative(save_directory); | 117 | return dir->CreateDirectoryRelative(save_directory); |
| 119 | |||
| 120 | // Return an error if the save data doesn't actually exist. | ||
| 121 | if (out == nullptr) { | ||
| 122 | // TODO(DarkLordZach): Find out correct error code. | ||
| 123 | return ResultUnknown; | ||
| 124 | } | ||
| 125 | |||
| 126 | return out; | ||
| 127 | } | 118 | } |
| 128 | 119 | ||
| 129 | ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, | 120 | VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const { |
| 130 | const SaveDataAttribute& meta) const { | ||
| 131 | 121 | ||
| 132 | const auto save_directory = | 122 | const auto save_directory = |
| 133 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); | 123 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); |
| @@ -138,12 +128,6 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, | |||
| 138 | return Create(space, meta); | 128 | return Create(space, meta); |
| 139 | } | 129 | } |
| 140 | 130 | ||
| 141 | // Return an error if the save data doesn't actually exist. | ||
| 142 | if (out == nullptr) { | ||
| 143 | // TODO(Subv): Find out correct error code. | ||
| 144 | return ResultUnknown; | ||
| 145 | } | ||
| 146 | |||
| 147 | return out; | 131 | return out; |
| 148 | } | 132 | } |
| 149 | 133 | ||
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index d3633ef03..45c7c81fb 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h | |||
| @@ -89,8 +89,8 @@ public: | |||
| 89 | explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_); | 89 | explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_); |
| 90 | ~SaveDataFactory(); | 90 | ~SaveDataFactory(); |
| 91 | 91 | ||
| 92 | ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; | 92 | VirtualDir Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; |
| 93 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const; | 93 | VirtualDir Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const; |
| 94 | 94 | ||
| 95 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; | 95 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; |
| 96 | 96 | ||
diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index 1df022c9e..d5158cd64 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp | |||
| @@ -23,7 +23,7 @@ SDMCFactory::SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_) | |||
| 23 | 23 | ||
| 24 | SDMCFactory::~SDMCFactory() = default; | 24 | SDMCFactory::~SDMCFactory() = default; |
| 25 | 25 | ||
| 26 | ResultVal<VirtualDir> SDMCFactory::Open() const { | 26 | VirtualDir SDMCFactory::Open() const { |
| 27 | return sd_dir; | 27 | return sd_dir; |
| 28 | } | 28 | } |
| 29 | 29 | ||
diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 3aebfb25e..a445fdb16 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h | |||
| @@ -18,7 +18,7 @@ public: | |||
| 18 | explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_); | 18 | explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_); |
| 19 | ~SDMCFactory(); | 19 | ~SDMCFactory(); |
| 20 | 20 | ||
| 21 | ResultVal<VirtualDir> Open() const; | 21 | VirtualDir Open() const; |
| 22 | 22 | ||
| 23 | VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; | 23 | VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; |
| 24 | VirtualDir GetSDMCContentDirectory() const; | 24 | VirtualDir GetSDMCContentDirectory() const; |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 02b5cada4..9bfc85b34 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -768,7 +768,7 @@ Result KPageTable::UnmapProcessMemory(KProcessAddress dst_addr, size_t size, | |||
| 768 | m_memory_block_slab_manager, num_allocator_blocks); | 768 | m_memory_block_slab_manager, num_allocator_blocks); |
| 769 | R_TRY(allocator_result); | 769 | R_TRY(allocator_result); |
| 770 | 770 | ||
| 771 | CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); | 771 | R_TRY(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); |
| 772 | 772 | ||
| 773 | // Apply the memory block update. | 773 | // Apply the memory block update. |
| 774 | m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages, | 774 | m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages, |
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 240f06689..92a1439eb 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -283,159 +283,6 @@ private: | |||
| 283 | u32 description_end; | 283 | u32 description_end; |
| 284 | }; | 284 | }; |
| 285 | 285 | ||
| 286 | /** | ||
| 287 | * This is an optional value type. It holds a `Result` and, if that code is ResultSuccess, it | ||
| 288 | * also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying | ||
| 289 | * to access the inner value with operator* is undefined behavior and will assert with Unwrap(). | ||
| 290 | * Users of this class must be cognizant to check the status of the ResultVal with operator bool(), | ||
| 291 | * Code(), Succeeded() or Failed() prior to accessing the inner value. | ||
| 292 | * | ||
| 293 | * An example of how it could be used: | ||
| 294 | * \code | ||
| 295 | * ResultVal<int> Frobnicate(float strength) { | ||
| 296 | * if (strength < 0.f || strength > 1.0f) { | ||
| 297 | * // Can't frobnicate too weakly or too strongly | ||
| 298 | * return Result{ErrorModule::Common, 1}; | ||
| 299 | * } else { | ||
| 300 | * // Frobnicated! Give caller a cookie | ||
| 301 | * return 42; | ||
| 302 | * } | ||
| 303 | * } | ||
| 304 | * \endcode | ||
| 305 | * | ||
| 306 | * \code | ||
| 307 | * auto frob_result = Frobnicate(0.75f); | ||
| 308 | * if (frob_result) { | ||
| 309 | * // Frobbed ok | ||
| 310 | * printf("My cookie is %d\n", *frob_result); | ||
| 311 | * } else { | ||
| 312 | * printf("Guess I overdid it. :( Error code: %ux\n", frob_result.Code().raw); | ||
| 313 | * } | ||
| 314 | * \endcode | ||
| 315 | */ | ||
| 316 | template <typename T> | ||
| 317 | class ResultVal { | ||
| 318 | public: | ||
| 319 | constexpr ResultVal() : expected{} {} | ||
| 320 | |||
| 321 | constexpr ResultVal(Result code) : expected{Common::Unexpected(code)} {} | ||
| 322 | |||
| 323 | constexpr ResultVal(ResultRange range) : expected{Common::Unexpected(range)} {} | ||
| 324 | |||
| 325 | template <typename U> | ||
| 326 | constexpr ResultVal(U&& val) : expected{std::forward<U>(val)} {} | ||
| 327 | |||
| 328 | template <typename... Args> | ||
| 329 | constexpr ResultVal(Args&&... args) : expected{std::in_place, std::forward<Args>(args)...} {} | ||
| 330 | |||
| 331 | ~ResultVal() = default; | ||
| 332 | |||
| 333 | constexpr ResultVal(const ResultVal&) = default; | ||
| 334 | constexpr ResultVal(ResultVal&&) = default; | ||
| 335 | |||
| 336 | ResultVal& operator=(const ResultVal&) = default; | ||
| 337 | ResultVal& operator=(ResultVal&&) = default; | ||
| 338 | |||
| 339 | [[nodiscard]] constexpr explicit operator bool() const noexcept { | ||
| 340 | return expected.has_value(); | ||
| 341 | } | ||
| 342 | |||
| 343 | [[nodiscard]] constexpr Result Code() const { | ||
| 344 | return expected.has_value() ? ResultSuccess : expected.error(); | ||
| 345 | } | ||
| 346 | |||
| 347 | [[nodiscard]] constexpr bool Succeeded() const { | ||
| 348 | return expected.has_value(); | ||
| 349 | } | ||
| 350 | |||
| 351 | [[nodiscard]] constexpr bool Failed() const { | ||
| 352 | return !expected.has_value(); | ||
| 353 | } | ||
| 354 | |||
| 355 | [[nodiscard]] constexpr T* operator->() { | ||
| 356 | return std::addressof(expected.value()); | ||
| 357 | } | ||
| 358 | |||
| 359 | [[nodiscard]] constexpr const T* operator->() const { | ||
| 360 | return std::addressof(expected.value()); | ||
| 361 | } | ||
| 362 | |||
| 363 | [[nodiscard]] constexpr T& operator*() & { | ||
| 364 | return *expected; | ||
| 365 | } | ||
| 366 | |||
| 367 | [[nodiscard]] constexpr const T& operator*() const& { | ||
| 368 | return *expected; | ||
| 369 | } | ||
| 370 | |||
| 371 | [[nodiscard]] constexpr T&& operator*() && { | ||
| 372 | return *expected; | ||
| 373 | } | ||
| 374 | |||
| 375 | [[nodiscard]] constexpr const T&& operator*() const&& { | ||
| 376 | return *expected; | ||
| 377 | } | ||
| 378 | |||
| 379 | [[nodiscard]] constexpr T& Unwrap() & { | ||
| 380 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 381 | return expected.value(); | ||
| 382 | } | ||
| 383 | |||
| 384 | [[nodiscard]] constexpr const T& Unwrap() const& { | ||
| 385 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 386 | return expected.value(); | ||
| 387 | } | ||
| 388 | |||
| 389 | [[nodiscard]] constexpr T&& Unwrap() && { | ||
| 390 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 391 | return std::move(expected.value()); | ||
| 392 | } | ||
| 393 | |||
| 394 | [[nodiscard]] constexpr const T&& Unwrap() const&& { | ||
| 395 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 396 | return std::move(expected.value()); | ||
| 397 | } | ||
| 398 | |||
| 399 | template <typename U> | ||
| 400 | [[nodiscard]] constexpr T ValueOr(U&& v) const& { | ||
| 401 | return expected.value_or(v); | ||
| 402 | } | ||
| 403 | |||
| 404 | template <typename U> | ||
| 405 | [[nodiscard]] constexpr T ValueOr(U&& v) && { | ||
| 406 | return expected.value_or(v); | ||
| 407 | } | ||
| 408 | |||
| 409 | private: | ||
| 410 | // TODO (Morph): Replace this with C++23 std::expected. | ||
| 411 | Common::Expected<T, Result> expected; | ||
| 412 | }; | ||
| 413 | |||
| 414 | /** | ||
| 415 | * Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps | ||
| 416 | * the contained value and assigns it to `target`, which can be either an l-value expression or a | ||
| 417 | * variable declaration. If it fails the return code is returned from the current function. Thus it | ||
| 418 | * can be used to cascade errors out, achieving something akin to exception handling. | ||
| 419 | */ | ||
| 420 | #define CASCADE_RESULT(target, source) \ | ||
| 421 | auto CONCAT2(check_result_L, __LINE__) = source; \ | ||
| 422 | if (CONCAT2(check_result_L, __LINE__).Failed()) { \ | ||
| 423 | return CONCAT2(check_result_L, __LINE__).Code(); \ | ||
| 424 | } \ | ||
| 425 | target = std::move(*CONCAT2(check_result_L, __LINE__)) | ||
| 426 | |||
| 427 | /** | ||
| 428 | * Analogous to CASCADE_RESULT, but for a bare Result. The code will be propagated if | ||
| 429 | * non-success, or discarded otherwise. | ||
| 430 | */ | ||
| 431 | #define CASCADE_CODE(source) \ | ||
| 432 | do { \ | ||
| 433 | auto CONCAT2(check_result_L, __LINE__) = source; \ | ||
| 434 | if (CONCAT2(check_result_L, __LINE__).IsError()) { \ | ||
| 435 | return CONCAT2(check_result_L, __LINE__); \ | ||
| 436 | } \ | ||
| 437 | } while (false) | ||
| 438 | |||
| 439 | #define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess()) | 286 | #define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess()) |
| 440 | #define R_FAILED(res) (static_cast<Result>(res).IsFailure()) | 287 | #define R_FAILED(res) (static_cast<Result>(res).IsFailure()) |
| 441 | 288 | ||
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 2632cd3ef..b971401e6 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -765,15 +765,16 @@ Result Module::Interface::InitializeApplicationInfoBase() { | |||
| 765 | // TODO(ogniK): This should be changed to reflect the target process for when we have multiple | 765 | // TODO(ogniK): This should be changed to reflect the target process for when we have multiple |
| 766 | // processes emulated. As we don't actually have pid support we should assume we're just using | 766 | // processes emulated. As we don't actually have pid support we should assume we're just using |
| 767 | // our own process | 767 | // our own process |
| 768 | const auto launch_property = | 768 | Glue::ApplicationLaunchProperty launch_property{}; |
| 769 | system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID()); | 769 | const auto result = system.GetARPManager().GetLaunchProperty( |
| 770 | &launch_property, system.GetApplicationProcessProgramID()); | ||
| 770 | 771 | ||
| 771 | if (launch_property.Failed()) { | 772 | if (result != ResultSuccess) { |
| 772 | LOG_ERROR(Service_ACC, "Failed to get launch property"); | 773 | LOG_ERROR(Service_ACC, "Failed to get launch property"); |
| 773 | return Account::ResultInvalidApplication; | 774 | return Account::ResultInvalidApplication; |
| 774 | } | 775 | } |
| 775 | 776 | ||
| 776 | switch (launch_property->base_game_storage_id) { | 777 | switch (launch_property.base_game_storage_id) { |
| 777 | case FileSys::StorageId::GameCard: | 778 | case FileSys::StorageId::GameCard: |
| 778 | application_info.application_type = ApplicationType::GameCard; | 779 | application_info.application_type = ApplicationType::GameCard; |
| 779 | break; | 780 | break; |
| @@ -785,7 +786,7 @@ Result Module::Interface::InitializeApplicationInfoBase() { | |||
| 785 | break; | 786 | break; |
| 786 | default: | 787 | default: |
| 787 | LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}", | 788 | LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}", |
| 788 | launch_property->base_game_storage_id); | 789 | launch_property.base_game_storage_id); |
| 789 | return Account::ResultInvalidApplication; | 790 | return Account::ResultInvalidApplication; |
| 790 | } | 791 | } |
| 791 | 792 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 585675718..8d057b3a8 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1578,11 +1578,13 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { | |||
| 1578 | attribute.title_id = system.GetApplicationProcessProgramID(); | 1578 | attribute.title_id = system.GetApplicationProcessProgramID(); |
| 1579 | attribute.user_id = user_id; | 1579 | attribute.user_id = user_id; |
| 1580 | attribute.type = FileSys::SaveDataType::SaveData; | 1580 | attribute.type = FileSys::SaveDataType::SaveData; |
| 1581 | |||
| 1582 | FileSys::VirtualDir save_data{}; | ||
| 1581 | const auto res = system.GetFileSystemController().CreateSaveData( | 1583 | const auto res = system.GetFileSystemController().CreateSaveData( |
| 1582 | FileSys::SaveDataSpaceId::NandUser, attribute); | 1584 | &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); |
| 1583 | 1585 | ||
| 1584 | IPC::ResponseBuilder rb{ctx, 4}; | 1586 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1585 | rb.Push(res.Code()); | 1587 | rb.Push(res); |
| 1586 | rb.Push<u64>(0); | 1588 | rb.Push<u64>(0); |
| 1587 | } | 1589 | } |
| 1588 | 1590 | ||
| @@ -1667,26 +1669,30 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { | |||
| 1667 | auto app_man = ns_am2->GetApplicationManagerInterface(); | 1669 | auto app_man = ns_am2->GetApplicationManagerInterface(); |
| 1668 | 1670 | ||
| 1669 | // Get desired application language | 1671 | // Get desired application language |
| 1670 | const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages); | 1672 | u8 desired_language{}; |
| 1671 | if (res_lang.Failed()) { | 1673 | const auto res_lang = |
| 1674 | app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); | ||
| 1675 | if (res_lang != ResultSuccess) { | ||
| 1672 | IPC::ResponseBuilder rb{ctx, 2}; | 1676 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1673 | rb.Push(res_lang.Code()); | 1677 | rb.Push(res_lang); |
| 1674 | return; | 1678 | return; |
| 1675 | } | 1679 | } |
| 1676 | 1680 | ||
| 1677 | // Convert to settings language code. | 1681 | // Convert to settings language code. |
| 1678 | const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang); | 1682 | u64 language_code{}; |
| 1679 | if (res_code.Failed()) { | 1683 | const auto res_code = |
| 1684 | app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); | ||
| 1685 | if (res_code != ResultSuccess) { | ||
| 1680 | IPC::ResponseBuilder rb{ctx, 2}; | 1686 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1681 | rb.Push(res_code.Code()); | 1687 | rb.Push(res_code); |
| 1682 | return; | 1688 | return; |
| 1683 | } | 1689 | } |
| 1684 | 1690 | ||
| 1685 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code); | 1691 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); |
| 1686 | 1692 | ||
| 1687 | IPC::ResponseBuilder rb{ctx, 4}; | 1693 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1688 | rb.Push(ResultSuccess); | 1694 | rb.Push(ResultSuccess); |
| 1689 | rb.Push(*res_code); | 1695 | rb.Push(language_code); |
| 1690 | } | 1696 | } |
| 1691 | 1697 | ||
| 1692 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { | 1698 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index dfcdd3ada..ac465d5a9 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -57,8 +57,8 @@ Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size | |||
| 57 | return FileSys::ERROR_PATH_NOT_FOUND; | 57 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | const auto entry_type = GetEntryType(path); | 60 | FileSys::EntryType entry_type{}; |
| 61 | if (entry_type.Code() == ResultSuccess) { | 61 | if (GetEntryType(&entry_type, path) == ResultSuccess) { |
| 62 | return FileSys::ERROR_PATH_ALREADY_EXISTS; | 62 | return FileSys::ERROR_PATH_ALREADY_EXISTS; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| @@ -210,8 +210,8 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, | |||
| 210 | return ResultUnknown; | 210 | return ResultUnknown; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_, | 213 | Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, |
| 214 | FileSys::Mode mode) const { | 214 | const std::string& path_, FileSys::Mode mode) const { |
| 215 | const std::string path(Common::FS::SanitizePath(path_)); | 215 | const std::string path(Common::FS::SanitizePath(path_)); |
| 216 | std::string_view npath = path; | 216 | std::string_view npath = path; |
| 217 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { | 217 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { |
| @@ -224,50 +224,68 @@ ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std:: | |||
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | if (mode == FileSys::Mode::Append) { | 226 | if (mode == FileSys::Mode::Append) { |
| 227 | return std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()); | 227 | *out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()); |
| 228 | } else { | ||
| 229 | *out_file = file; | ||
| 228 | } | 230 | } |
| 229 | 231 | ||
| 230 | return file; | 232 | return ResultSuccess; |
| 231 | } | 233 | } |
| 232 | 234 | ||
| 233 | ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) { | 235 | Result VfsDirectoryServiceWrapper::OpenDirectory(FileSys::VirtualDir* out_directory, |
| 236 | const std::string& path_) { | ||
| 234 | std::string path(Common::FS::SanitizePath(path_)); | 237 | std::string path(Common::FS::SanitizePath(path_)); |
| 235 | auto dir = GetDirectoryRelativeWrapped(backing, path); | 238 | auto dir = GetDirectoryRelativeWrapped(backing, path); |
| 236 | if (dir == nullptr) { | 239 | if (dir == nullptr) { |
| 237 | // TODO(DarkLordZach): Find a better error code for this | 240 | // TODO(DarkLordZach): Find a better error code for this |
| 238 | return FileSys::ERROR_PATH_NOT_FOUND; | 241 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 239 | } | 242 | } |
| 240 | return dir; | 243 | *out_directory = dir; |
| 244 | return ResultSuccess; | ||
| 241 | } | 245 | } |
| 242 | 246 | ||
| 243 | ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( | 247 | Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type, |
| 244 | const std::string& path_) const { | 248 | const std::string& path_) const { |
| 245 | std::string path(Common::FS::SanitizePath(path_)); | 249 | std::string path(Common::FS::SanitizePath(path_)); |
| 246 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 250 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 247 | if (dir == nullptr) | 251 | if (dir == nullptr) { |
| 248 | return FileSys::ERROR_PATH_NOT_FOUND; | 252 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 253 | } | ||
| 254 | |||
| 249 | auto filename = Common::FS::GetFilename(path); | 255 | auto filename = Common::FS::GetFilename(path); |
| 250 | // TODO(Subv): Some games use the '/' path, find out what this means. | 256 | // TODO(Subv): Some games use the '/' path, find out what this means. |
| 251 | if (filename.empty()) | 257 | if (filename.empty()) { |
| 252 | return FileSys::EntryType::Directory; | 258 | *out_entry_type = FileSys::EntryType::Directory; |
| 259 | return ResultSuccess; | ||
| 260 | } | ||
| 261 | |||
| 262 | if (dir->GetFile(filename) != nullptr) { | ||
| 263 | *out_entry_type = FileSys::EntryType::File; | ||
| 264 | return ResultSuccess; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (dir->GetSubdirectory(filename) != nullptr) { | ||
| 268 | *out_entry_type = FileSys::EntryType::Directory; | ||
| 269 | return ResultSuccess; | ||
| 270 | } | ||
| 253 | 271 | ||
| 254 | if (dir->GetFile(filename) != nullptr) | ||
| 255 | return FileSys::EntryType::File; | ||
| 256 | if (dir->GetSubdirectory(filename) != nullptr) | ||
| 257 | return FileSys::EntryType::Directory; | ||
| 258 | return FileSys::ERROR_PATH_NOT_FOUND; | 272 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 259 | } | 273 | } |
| 260 | 274 | ||
| 261 | ResultVal<FileSys::FileTimeStampRaw> VfsDirectoryServiceWrapper::GetFileTimeStampRaw( | 275 | Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw( |
| 262 | const std::string& path) const { | 276 | FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const { |
| 263 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 277 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 264 | if (dir == nullptr) { | 278 | if (dir == nullptr) { |
| 265 | return FileSys::ERROR_PATH_NOT_FOUND; | 279 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 266 | } | 280 | } |
| 267 | if (GetEntryType(path).Failed()) { | 281 | |
| 282 | FileSys::EntryType entry_type; | ||
| 283 | if (GetEntryType(&entry_type, path) != ResultSuccess) { | ||
| 268 | return FileSys::ERROR_PATH_NOT_FOUND; | 284 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 269 | } | 285 | } |
| 270 | return dir->GetFileTimeStamp(Common::FS::GetFilename(path)); | 286 | |
| 287 | *out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path)); | ||
| 288 | return ResultSuccess; | ||
| 271 | } | 289 | } |
| 272 | 290 | ||
| 273 | FileSystemController::FileSystemController(Core::System& system_) : system{system_} {} | 291 | FileSystemController::FileSystemController(Core::System& system_) : system{system_} {} |
| @@ -310,57 +328,54 @@ void FileSystemController::SetPackedUpdate(FileSys::VirtualFile update_raw) { | |||
| 310 | romfs_factory->SetPackedUpdate(std::move(update_raw)); | 328 | romfs_factory->SetPackedUpdate(std::move(update_raw)); |
| 311 | } | 329 | } |
| 312 | 330 | ||
| 313 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess() const { | 331 | FileSys::VirtualFile FileSystemController::OpenRomFSCurrentProcess() const { |
| 314 | LOG_TRACE(Service_FS, "Opening RomFS for current process"); | 332 | LOG_TRACE(Service_FS, "Opening RomFS for current process"); |
| 315 | 333 | ||
| 316 | if (romfs_factory == nullptr) { | 334 | if (romfs_factory == nullptr) { |
| 317 | // TODO(bunnei): Find a better error code for this | 335 | return nullptr; |
| 318 | return ResultUnknown; | ||
| 319 | } | 336 | } |
| 320 | 337 | ||
| 321 | return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID()); | 338 | return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID()); |
| 322 | } | 339 | } |
| 323 | 340 | ||
| 324 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFS( | 341 | FileSys::VirtualFile FileSystemController::OpenPatchedRomFS(u64 title_id, |
| 325 | u64 title_id, FileSys::ContentRecordType type) const { | 342 | FileSys::ContentRecordType type) const { |
| 326 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id); | 343 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id); |
| 327 | 344 | ||
| 328 | if (romfs_factory == nullptr) { | 345 | if (romfs_factory == nullptr) { |
| 329 | // TODO: Find a better error code for this | 346 | return nullptr; |
| 330 | return ResultUnknown; | ||
| 331 | } | 347 | } |
| 332 | 348 | ||
| 333 | return romfs_factory->OpenPatchedRomFS(title_id, type); | 349 | return romfs_factory->OpenPatchedRomFS(title_id, type); |
| 334 | } | 350 | } |
| 335 | 351 | ||
| 336 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFSWithProgramIndex( | 352 | FileSys::VirtualFile FileSystemController::OpenPatchedRomFSWithProgramIndex( |
| 337 | u64 title_id, u8 program_index, FileSys::ContentRecordType type) const { | 353 | u64 title_id, u8 program_index, FileSys::ContentRecordType type) const { |
| 338 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id, | 354 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id, |
| 339 | program_index); | 355 | program_index); |
| 340 | 356 | ||
| 341 | if (romfs_factory == nullptr) { | 357 | if (romfs_factory == nullptr) { |
| 342 | // TODO: Find a better error code for this | 358 | return nullptr; |
| 343 | return ResultUnknown; | ||
| 344 | } | 359 | } |
| 345 | 360 | ||
| 346 | return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type); | 361 | return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type); |
| 347 | } | 362 | } |
| 348 | 363 | ||
| 349 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS( | 364 | FileSys::VirtualFile FileSystemController::OpenRomFS(u64 title_id, FileSys::StorageId storage_id, |
| 350 | u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const { | 365 | FileSys::ContentRecordType type) const { |
| 351 | LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}", | 366 | LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}", |
| 352 | title_id, storage_id, type); | 367 | title_id, storage_id, type); |
| 353 | 368 | ||
| 354 | if (romfs_factory == nullptr) { | 369 | if (romfs_factory == nullptr) { |
| 355 | // TODO(bunnei): Find a better error code for this | 370 | return nullptr; |
| 356 | return ResultUnknown; | ||
| 357 | } | 371 | } |
| 358 | 372 | ||
| 359 | return romfs_factory->Open(title_id, storage_id, type); | 373 | return romfs_factory->Open(title_id, storage_id, type); |
| 360 | } | 374 | } |
| 361 | 375 | ||
| 362 | ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData( | 376 | Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data, |
| 363 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const { | 377 | FileSys::SaveDataSpaceId space, |
| 378 | const FileSys::SaveDataAttribute& save_struct) const { | ||
| 364 | LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space, | 379 | LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space, |
| 365 | save_struct.DebugInfo()); | 380 | save_struct.DebugInfo()); |
| 366 | 381 | ||
| @@ -368,11 +383,18 @@ ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData( | |||
| 368 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 383 | return FileSys::ERROR_ENTITY_NOT_FOUND; |
| 369 | } | 384 | } |
| 370 | 385 | ||
| 371 | return save_data_factory->Create(space, save_struct); | 386 | auto save_data = save_data_factory->Create(space, save_struct); |
| 387 | if (save_data == nullptr) { | ||
| 388 | return FileSys::ERROR_ENTITY_NOT_FOUND; | ||
| 389 | } | ||
| 390 | |||
| 391 | *out_save_data = save_data; | ||
| 392 | return ResultSuccess; | ||
| 372 | } | 393 | } |
| 373 | 394 | ||
| 374 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData( | 395 | Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data, |
| 375 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& attribute) const { | 396 | FileSys::SaveDataSpaceId space, |
| 397 | const FileSys::SaveDataAttribute& attribute) const { | ||
| 376 | LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space, | 398 | LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space, |
| 377 | attribute.DebugInfo()); | 399 | attribute.DebugInfo()); |
| 378 | 400 | ||
| @@ -380,32 +402,50 @@ ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData( | |||
| 380 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 402 | return FileSys::ERROR_ENTITY_NOT_FOUND; |
| 381 | } | 403 | } |
| 382 | 404 | ||
| 383 | return save_data_factory->Open(space, attribute); | 405 | auto save_data = save_data_factory->Open(space, attribute); |
| 406 | if (save_data == nullptr) { | ||
| 407 | return FileSys::ERROR_ENTITY_NOT_FOUND; | ||
| 408 | } | ||
| 409 | |||
| 410 | *out_save_data = save_data; | ||
| 411 | return ResultSuccess; | ||
| 384 | } | 412 | } |
| 385 | 413 | ||
| 386 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace( | 414 | Result FileSystemController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space, |
| 387 | FileSys::SaveDataSpaceId space) const { | 415 | FileSys::SaveDataSpaceId space) const { |
| 388 | LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space); | 416 | LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space); |
| 389 | 417 | ||
| 390 | if (save_data_factory == nullptr) { | 418 | if (save_data_factory == nullptr) { |
| 391 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 419 | return FileSys::ERROR_ENTITY_NOT_FOUND; |
| 392 | } | 420 | } |
| 393 | 421 | ||
| 394 | return save_data_factory->GetSaveDataSpaceDirectory(space); | 422 | auto save_data_space = save_data_factory->GetSaveDataSpaceDirectory(space); |
| 423 | if (save_data_space == nullptr) { | ||
| 424 | return FileSys::ERROR_ENTITY_NOT_FOUND; | ||
| 425 | } | ||
| 426 | |||
| 427 | *out_save_data_space = save_data_space; | ||
| 428 | return ResultSuccess; | ||
| 395 | } | 429 | } |
| 396 | 430 | ||
| 397 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSDMC() const { | 431 | Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const { |
| 398 | LOG_TRACE(Service_FS, "Opening SDMC"); | 432 | LOG_TRACE(Service_FS, "Opening SDMC"); |
| 399 | 433 | ||
| 400 | if (sdmc_factory == nullptr) { | 434 | if (sdmc_factory == nullptr) { |
| 401 | return FileSys::ERROR_SD_CARD_NOT_FOUND; | 435 | return FileSys::ERROR_SD_CARD_NOT_FOUND; |
| 402 | } | 436 | } |
| 403 | 437 | ||
| 404 | return sdmc_factory->Open(); | 438 | auto sdmc = sdmc_factory->Open(); |
| 439 | if (sdmc == nullptr) { | ||
| 440 | return FileSys::ERROR_SD_CARD_NOT_FOUND; | ||
| 441 | } | ||
| 442 | |||
| 443 | *out_sdmc = sdmc; | ||
| 444 | return ResultSuccess; | ||
| 405 | } | 445 | } |
| 406 | 446 | ||
| 407 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition( | 447 | Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_partition, |
| 408 | FileSys::BisPartitionId id) const { | 448 | FileSys::BisPartitionId id) const { |
| 409 | LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id); | 449 | LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id); |
| 410 | 450 | ||
| 411 | if (bis_factory == nullptr) { | 451 | if (bis_factory == nullptr) { |
| @@ -417,11 +457,12 @@ ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition( | |||
| 417 | return FileSys::ERROR_INVALID_ARGUMENT; | 457 | return FileSys::ERROR_INVALID_ARGUMENT; |
| 418 | } | 458 | } |
| 419 | 459 | ||
| 420 | return part; | 460 | *out_bis_partition = part; |
| 461 | return ResultSuccess; | ||
| 421 | } | 462 | } |
| 422 | 463 | ||
| 423 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage( | 464 | Result FileSystemController::OpenBISPartitionStorage( |
| 424 | FileSys::BisPartitionId id) const { | 465 | FileSys::VirtualFile* out_bis_partition_storage, FileSys::BisPartitionId id) const { |
| 425 | LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id); | 466 | LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id); |
| 426 | 467 | ||
| 427 | if (bis_factory == nullptr) { | 468 | if (bis_factory == nullptr) { |
| @@ -433,7 +474,8 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage( | |||
| 433 | return FileSys::ERROR_INVALID_ARGUMENT; | 474 | return FileSys::ERROR_INVALID_ARGUMENT; |
| 434 | } | 475 | } |
| 435 | 476 | ||
| 436 | return part; | 477 | *out_bis_partition_storage = part; |
| 478 | return ResultSuccess; | ||
| 437 | } | 479 | } |
| 438 | 480 | ||
| 439 | u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const { | 481 | u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const { |
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index a5c1c9d3e..fd991f976 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h | |||
| @@ -64,21 +64,24 @@ public: | |||
| 64 | Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); | 64 | Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); |
| 65 | 65 | ||
| 66 | void SetPackedUpdate(FileSys::VirtualFile update_raw); | 66 | void SetPackedUpdate(FileSys::VirtualFile update_raw); |
| 67 | ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const; | 67 | FileSys::VirtualFile OpenRomFSCurrentProcess() const; |
| 68 | ResultVal<FileSys::VirtualFile> OpenPatchedRomFS(u64 title_id, | 68 | FileSys::VirtualFile OpenPatchedRomFS(u64 title_id, FileSys::ContentRecordType type) const; |
| 69 | FileSys::ContentRecordType type) const; | 69 | FileSys::VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, |
| 70 | ResultVal<FileSys::VirtualFile> OpenPatchedRomFSWithProgramIndex( | 70 | FileSys::ContentRecordType type) const; |
| 71 | u64 title_id, u8 program_index, FileSys::ContentRecordType type) const; | 71 | FileSys::VirtualFile OpenRomFS(u64 title_id, FileSys::StorageId storage_id, |
| 72 | ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id, | 72 | FileSys::ContentRecordType type) const; |
| 73 | FileSys::ContentRecordType type) const; | 73 | |
| 74 | ResultVal<FileSys::VirtualDir> CreateSaveData( | 74 | Result CreateSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space, |
| 75 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const; | 75 | const FileSys::SaveDataAttribute& save_struct) const; |
| 76 | ResultVal<FileSys::VirtualDir> OpenSaveData( | 76 | Result OpenSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space, |
| 77 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const; | 77 | const FileSys::SaveDataAttribute& save_struct) const; |
| 78 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const; | 78 | Result OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space, |
| 79 | ResultVal<FileSys::VirtualDir> OpenSDMC() const; | 79 | FileSys::SaveDataSpaceId space) const; |
| 80 | ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const; | 80 | Result OpenSDMC(FileSys::VirtualDir* out_sdmc) const; |
| 81 | ResultVal<FileSys::VirtualFile> OpenBISPartitionStorage(FileSys::BisPartitionId id) const; | 81 | Result OpenBISPartition(FileSys::VirtualDir* out_bis_partition, |
| 82 | FileSys::BisPartitionId id) const; | ||
| 83 | Result OpenBISPartitionStorage(FileSys::VirtualFile* out_bis_partition_storage, | ||
| 84 | FileSys::BisPartitionId id) const; | ||
| 82 | 85 | ||
| 83 | u64 GetFreeSpaceSize(FileSys::StorageId id) const; | 86 | u64 GetFreeSpaceSize(FileSys::StorageId id) const; |
| 84 | u64 GetTotalSpaceSize(FileSys::StorageId id) const; | 87 | u64 GetTotalSpaceSize(FileSys::StorageId id) const; |
| @@ -224,26 +227,28 @@ public: | |||
| 224 | * @param mode Mode to open the file with | 227 | * @param mode Mode to open the file with |
| 225 | * @return Opened file, or error code | 228 | * @return Opened file, or error code |
| 226 | */ | 229 | */ |
| 227 | ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const; | 230 | Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path, |
| 231 | FileSys::Mode mode) const; | ||
| 228 | 232 | ||
| 229 | /** | 233 | /** |
| 230 | * Open a directory specified by its path | 234 | * Open a directory specified by its path |
| 231 | * @param path Path relative to the archive | 235 | * @param path Path relative to the archive |
| 232 | * @return Opened directory, or error code | 236 | * @return Opened directory, or error code |
| 233 | */ | 237 | */ |
| 234 | ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path); | 238 | Result OpenDirectory(FileSys::VirtualDir* out_directory, const std::string& path); |
| 235 | 239 | ||
| 236 | /** | 240 | /** |
| 237 | * Get the type of the specified path | 241 | * Get the type of the specified path |
| 238 | * @return The type of the specified path or error code | 242 | * @return The type of the specified path or error code |
| 239 | */ | 243 | */ |
| 240 | ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const; | 244 | Result GetEntryType(FileSys::EntryType* out_entry_type, const std::string& path) const; |
| 241 | 245 | ||
| 242 | /** | 246 | /** |
| 243 | * Get the timestamp of the specified path | 247 | * Get the timestamp of the specified path |
| 244 | * @return The timestamp of the specified path or error code | 248 | * @return The timestamp of the specified path or error code |
| 245 | */ | 249 | */ |
| 246 | ResultVal<FileSys::FileTimeStampRaw> GetFileTimeStampRaw(const std::string& path) const; | 250 | Result GetFileTimeStampRaw(FileSys::FileTimeStampRaw* out_time_stamp_raw, |
| 251 | const std::string& path) const; | ||
| 247 | 252 | ||
| 248 | private: | 253 | private: |
| 249 | FileSys::VirtualDir backing; | 254 | FileSys::VirtualDir backing; |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 427dbc8b3..423a814cb 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -419,14 +419,15 @@ public: | |||
| 419 | 419 | ||
| 420 | LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); | 420 | LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); |
| 421 | 421 | ||
| 422 | auto result = backend.OpenFile(name, mode); | 422 | FileSys::VirtualFile vfs_file{}; |
| 423 | if (result.Failed()) { | 423 | auto result = backend.OpenFile(&vfs_file, name, mode); |
| 424 | if (result != ResultSuccess) { | ||
| 424 | IPC::ResponseBuilder rb{ctx, 2}; | 425 | IPC::ResponseBuilder rb{ctx, 2}; |
| 425 | rb.Push(result.Code()); | 426 | rb.Push(result); |
| 426 | return; | 427 | return; |
| 427 | } | 428 | } |
| 428 | 429 | ||
| 429 | auto file = std::make_shared<IFile>(system, result.Unwrap()); | 430 | auto file = std::make_shared<IFile>(system, vfs_file); |
| 430 | 431 | ||
| 431 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 432 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 432 | rb.Push(ResultSuccess); | 433 | rb.Push(ResultSuccess); |
| @@ -444,14 +445,15 @@ public: | |||
| 444 | 445 | ||
| 445 | LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags); | 446 | LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags); |
| 446 | 447 | ||
| 447 | auto result = backend.OpenDirectory(name); | 448 | FileSys::VirtualDir vfs_dir{}; |
| 448 | if (result.Failed()) { | 449 | auto result = backend.OpenDirectory(&vfs_dir, name); |
| 450 | if (result != ResultSuccess) { | ||
| 449 | IPC::ResponseBuilder rb{ctx, 2}; | 451 | IPC::ResponseBuilder rb{ctx, 2}; |
| 450 | rb.Push(result.Code()); | 452 | rb.Push(result); |
| 451 | return; | 453 | return; |
| 452 | } | 454 | } |
| 453 | 455 | ||
| 454 | auto directory = std::make_shared<IDirectory>(system, result.Unwrap()); | 456 | auto directory = std::make_shared<IDirectory>(system, vfs_dir); |
| 455 | 457 | ||
| 456 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 458 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 457 | rb.Push(ResultSuccess); | 459 | rb.Push(ResultSuccess); |
| @@ -464,16 +466,17 @@ public: | |||
| 464 | 466 | ||
| 465 | LOG_DEBUG(Service_FS, "called. file={}", name); | 467 | LOG_DEBUG(Service_FS, "called. file={}", name); |
| 466 | 468 | ||
| 467 | auto result = backend.GetEntryType(name); | 469 | FileSys::EntryType vfs_entry_type{}; |
| 468 | if (result.Failed()) { | 470 | auto result = backend.GetEntryType(&vfs_entry_type, name); |
| 471 | if (result != ResultSuccess) { | ||
| 469 | IPC::ResponseBuilder rb{ctx, 2}; | 472 | IPC::ResponseBuilder rb{ctx, 2}; |
| 470 | rb.Push(result.Code()); | 473 | rb.Push(result); |
| 471 | return; | 474 | return; |
| 472 | } | 475 | } |
| 473 | 476 | ||
| 474 | IPC::ResponseBuilder rb{ctx, 3}; | 477 | IPC::ResponseBuilder rb{ctx, 3}; |
| 475 | rb.Push(ResultSuccess); | 478 | rb.Push(ResultSuccess); |
| 476 | rb.Push<u32>(static_cast<u32>(*result)); | 479 | rb.Push<u32>(static_cast<u32>(vfs_entry_type)); |
| 477 | } | 480 | } |
| 478 | 481 | ||
| 479 | void Commit(HLERequestContext& ctx) { | 482 | void Commit(HLERequestContext& ctx) { |
| @@ -505,16 +508,17 @@ public: | |||
| 505 | 508 | ||
| 506 | LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); | 509 | LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); |
| 507 | 510 | ||
| 508 | auto result = backend.GetFileTimeStampRaw(name); | 511 | FileSys::FileTimeStampRaw vfs_timestamp{}; |
| 509 | if (result.Failed()) { | 512 | auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name); |
| 513 | if (result != ResultSuccess) { | ||
| 510 | IPC::ResponseBuilder rb{ctx, 2}; | 514 | IPC::ResponseBuilder rb{ctx, 2}; |
| 511 | rb.Push(result.Code()); | 515 | rb.Push(result); |
| 512 | return; | 516 | return; |
| 513 | } | 517 | } |
| 514 | 518 | ||
| 515 | IPC::ResponseBuilder rb{ctx, 10}; | 519 | IPC::ResponseBuilder rb{ctx, 10}; |
| 516 | rb.Push(ResultSuccess); | 520 | rb.Push(ResultSuccess); |
| 517 | rb.PushRaw(*result); | 521 | rb.PushRaw(vfs_timestamp); |
| 518 | } | 522 | } |
| 519 | 523 | ||
| 520 | private: | 524 | private: |
| @@ -572,14 +576,15 @@ private: | |||
| 572 | } | 576 | } |
| 573 | 577 | ||
| 574 | void FindAllSaves(FileSys::SaveDataSpaceId space) { | 578 | void FindAllSaves(FileSys::SaveDataSpaceId space) { |
| 575 | const auto save_root = fsc.OpenSaveDataSpace(space); | 579 | FileSys::VirtualDir save_root{}; |
| 580 | const auto result = fsc.OpenSaveDataSpace(&save_root, space); | ||
| 576 | 581 | ||
| 577 | if (save_root.Failed() || *save_root == nullptr) { | 582 | if (result != ResultSuccess || save_root == nullptr) { |
| 578 | LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space); | 583 | LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space); |
| 579 | return; | 584 | return; |
| 580 | } | 585 | } |
| 581 | 586 | ||
| 582 | for (const auto& type : (*save_root)->GetSubdirectories()) { | 587 | for (const auto& type : save_root->GetSubdirectories()) { |
| 583 | if (type->GetName() == "save") { | 588 | if (type->GetName() == "save") { |
| 584 | for (const auto& save_id : type->GetSubdirectories()) { | 589 | for (const auto& save_id : type->GetSubdirectories()) { |
| 585 | for (const auto& user_id : save_id->GetSubdirectories()) { | 590 | for (const auto& user_id : save_id->GetSubdirectories()) { |
| @@ -837,9 +842,11 @@ void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { | |||
| 837 | void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { | 842 | void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { |
| 838 | LOG_DEBUG(Service_FS, "called"); | 843 | LOG_DEBUG(Service_FS, "called"); |
| 839 | 844 | ||
| 840 | auto filesystem = | 845 | FileSys::VirtualDir sdmc_dir{}; |
| 841 | std::make_shared<IFileSystem>(system, fsc.OpenSDMC().Unwrap(), | 846 | fsc.OpenSDMC(&sdmc_dir); |
| 842 | SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); | 847 | |
| 848 | auto filesystem = std::make_shared<IFileSystem>( | ||
| 849 | system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); | ||
| 843 | 850 | ||
| 844 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 851 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 845 | rb.Push(ResultSuccess); | 852 | rb.Push(ResultSuccess); |
| @@ -856,7 +863,8 @@ void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) { | |||
| 856 | LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(), | 863 | LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(), |
| 857 | uid[1], uid[0]); | 864 | uid[1], uid[0]); |
| 858 | 865 | ||
| 859 | fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandUser, save_struct); | 866 | FileSys::VirtualDir save_data_dir{}; |
| 867 | fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser, save_struct); | ||
| 860 | 868 | ||
| 861 | IPC::ResponseBuilder rb{ctx, 2}; | 869 | IPC::ResponseBuilder rb{ctx, 2}; |
| 862 | rb.Push(ResultSuccess); | 870 | rb.Push(ResultSuccess); |
| @@ -874,8 +882,9 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) { | |||
| 874 | 882 | ||
| 875 | LOG_INFO(Service_FS, "called."); | 883 | LOG_INFO(Service_FS, "called."); |
| 876 | 884 | ||
| 877 | auto dir = fsc.OpenSaveData(parameters.space_id, parameters.attribute); | 885 | FileSys::VirtualDir dir{}; |
| 878 | if (dir.Failed()) { | 886 | auto result = fsc.OpenSaveData(&dir, parameters.space_id, parameters.attribute); |
| 887 | if (result != ResultSuccess) { | ||
| 879 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; | 888 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; |
| 880 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); | 889 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); |
| 881 | return; | 890 | return; |
| @@ -899,8 +908,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) { | |||
| 899 | ASSERT(false); | 908 | ASSERT(false); |
| 900 | } | 909 | } |
| 901 | 910 | ||
| 902 | auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()), | 911 | auto filesystem = |
| 903 | SizeGetter::FromStorageId(fsc, id)); | 912 | std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id)); |
| 904 | 913 | ||
| 905 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 914 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 906 | rb.Push(ResultSuccess); | 915 | rb.Push(ResultSuccess); |
| @@ -970,7 +979,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) { | |||
| 970 | 979 | ||
| 971 | if (!romfs) { | 980 | if (!romfs) { |
| 972 | auto current_romfs = fsc.OpenRomFSCurrentProcess(); | 981 | auto current_romfs = fsc.OpenRomFSCurrentProcess(); |
| 973 | if (current_romfs.Failed()) { | 982 | if (!current_romfs) { |
| 974 | // TODO (bunnei): Find the right error code to use here | 983 | // TODO (bunnei): Find the right error code to use here |
| 975 | LOG_CRITICAL(Service_FS, "no file system interface available!"); | 984 | LOG_CRITICAL(Service_FS, "no file system interface available!"); |
| 976 | IPC::ResponseBuilder rb{ctx, 2}; | 985 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -978,7 +987,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) { | |||
| 978 | return; | 987 | return; |
| 979 | } | 988 | } |
| 980 | 989 | ||
| 981 | romfs = current_romfs.Unwrap(); | 990 | romfs = current_romfs; |
| 982 | } | 991 | } |
| 983 | 992 | ||
| 984 | auto storage = std::make_shared<IStorage>(system, romfs); | 993 | auto storage = std::make_shared<IStorage>(system, romfs); |
| @@ -999,7 +1008,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) { | |||
| 999 | 1008 | ||
| 1000 | auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); | 1009 | auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); |
| 1001 | 1010 | ||
| 1002 | if (data.Failed()) { | 1011 | if (!data) { |
| 1003 | const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); | 1012 | const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); |
| 1004 | 1013 | ||
| 1005 | if (archive != nullptr) { | 1014 | if (archive != nullptr) { |
| @@ -1021,7 +1030,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) { | |||
| 1021 | const FileSys::PatchManager pm{title_id, fsc, content_provider}; | 1030 | const FileSys::PatchManager pm{title_id, fsc, content_provider}; |
| 1022 | 1031 | ||
| 1023 | auto storage = std::make_shared<IStorage>( | 1032 | auto storage = std::make_shared<IStorage>( |
| 1024 | system, pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); | 1033 | system, pm.PatchRomFS(std::move(data), 0, FileSys::ContentRecordType::Data)); |
| 1025 | 1034 | ||
| 1026 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1035 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1027 | rb.Push(ResultSuccess); | 1036 | rb.Push(ResultSuccess); |
| @@ -1051,7 +1060,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { | |||
| 1051 | fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index, | 1060 | fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index, |
| 1052 | FileSys::ContentRecordType::Program); | 1061 | FileSys::ContentRecordType::Program); |
| 1053 | 1062 | ||
| 1054 | if (patched_romfs.Failed()) { | 1063 | if (!patched_romfs) { |
| 1055 | // TODO: Find the right error code to use here | 1064 | // TODO: Find the right error code to use here |
| 1056 | LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); | 1065 | LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); |
| 1057 | 1066 | ||
| @@ -1060,7 +1069,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { | |||
| 1060 | return; | 1069 | return; |
| 1061 | } | 1070 | } |
| 1062 | 1071 | ||
| 1063 | auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs.Unwrap())); | 1072 | auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs)); |
| 1064 | 1073 | ||
| 1065 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1074 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1066 | rb.Push(ResultSuccess); | 1075 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index ed6fcb5f6..6f1151b03 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp | |||
| @@ -65,18 +65,19 @@ void ARP_R::GetApplicationLaunchProperty(HLERequestContext& ctx) { | |||
| 65 | return; | 65 | return; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | const auto res = manager.GetLaunchProperty(*title_id); | 68 | ApplicationLaunchProperty launch_property{}; |
| 69 | const auto res = manager.GetLaunchProperty(&launch_property, *title_id); | ||
| 69 | 70 | ||
| 70 | if (res.Failed()) { | 71 | if (res != ResultSuccess) { |
| 71 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); | 72 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); |
| 72 | IPC::ResponseBuilder rb{ctx, 2}; | 73 | IPC::ResponseBuilder rb{ctx, 2}; |
| 73 | rb.Push(res.Code()); | 74 | rb.Push(res); |
| 74 | return; | 75 | return; |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | IPC::ResponseBuilder rb{ctx, 6}; | 78 | IPC::ResponseBuilder rb{ctx, 6}; |
| 78 | rb.Push(ResultSuccess); | 79 | rb.Push(ResultSuccess); |
| 79 | rb.PushRaw(*res); | 80 | rb.PushRaw(launch_property); |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) { | 83 | void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) { |
| @@ -85,18 +86,19 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx | |||
| 85 | 86 | ||
| 86 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); | 87 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); |
| 87 | 88 | ||
| 88 | const auto res = manager.GetLaunchProperty(title_id); | 89 | ApplicationLaunchProperty launch_property{}; |
| 90 | const auto res = manager.GetLaunchProperty(&launch_property, title_id); | ||
| 89 | 91 | ||
| 90 | if (res.Failed()) { | 92 | if (res != ResultSuccess) { |
| 91 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); | 93 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); |
| 92 | IPC::ResponseBuilder rb{ctx, 2}; | 94 | IPC::ResponseBuilder rb{ctx, 2}; |
| 93 | rb.Push(res.Code()); | 95 | rb.Push(res); |
| 94 | return; | 96 | return; |
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | IPC::ResponseBuilder rb{ctx, 6}; | 99 | IPC::ResponseBuilder rb{ctx, 6}; |
| 98 | rb.Push(ResultSuccess); | 100 | rb.Push(ResultSuccess); |
| 99 | rb.PushRaw(*res); | 101 | rb.PushRaw(launch_property); |
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { | 104 | void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { |
| @@ -113,16 +115,17 @@ void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { | |||
| 113 | return; | 115 | return; |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | const auto res = manager.GetControlProperty(*title_id); | 118 | std::vector<u8> nacp_data; |
| 119 | const auto res = manager.GetControlProperty(&nacp_data, *title_id); | ||
| 117 | 120 | ||
| 118 | if (res.Failed()) { | 121 | if (res != ResultSuccess) { |
| 119 | LOG_ERROR(Service_ARP, "Failed to get control property!"); | 122 | LOG_ERROR(Service_ARP, "Failed to get control property!"); |
| 120 | IPC::ResponseBuilder rb{ctx, 2}; | 123 | IPC::ResponseBuilder rb{ctx, 2}; |
| 121 | rb.Push(res.Code()); | 124 | rb.Push(res); |
| 122 | return; | 125 | return; |
| 123 | } | 126 | } |
| 124 | 127 | ||
| 125 | ctx.WriteBuffer(*res); | 128 | ctx.WriteBuffer(nacp_data); |
| 126 | 129 | ||
| 127 | IPC::ResponseBuilder rb{ctx, 2}; | 130 | IPC::ResponseBuilder rb{ctx, 2}; |
| 128 | rb.Push(ResultSuccess); | 131 | rb.Push(ResultSuccess); |
| @@ -134,16 +137,17 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(HLERequestContext& ct | |||
| 134 | 137 | ||
| 135 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); | 138 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); |
| 136 | 139 | ||
| 137 | const auto res = manager.GetControlProperty(title_id); | 140 | std::vector<u8> nacp_data; |
| 141 | const auto res = manager.GetControlProperty(&nacp_data, title_id); | ||
| 138 | 142 | ||
| 139 | if (res.Failed()) { | 143 | if (res != ResultSuccess) { |
| 140 | LOG_ERROR(Service_ARP, "Failed to get control property!"); | 144 | LOG_ERROR(Service_ARP, "Failed to get control property!"); |
| 141 | IPC::ResponseBuilder rb{ctx, 2}; | 145 | IPC::ResponseBuilder rb{ctx, 2}; |
| 142 | rb.Push(res.Code()); | 146 | rb.Push(res); |
| 143 | return; | 147 | return; |
| 144 | } | 148 | } |
| 145 | 149 | ||
| 146 | ctx.WriteBuffer(*res); | 150 | ctx.WriteBuffer(nacp_data); |
| 147 | 151 | ||
| 148 | IPC::ResponseBuilder rb{ctx, 2}; | 152 | IPC::ResponseBuilder rb{ctx, 2}; |
| 149 | rb.Push(ResultSuccess); | 153 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/glue/glue_manager.cpp b/src/core/hle/service/glue/glue_manager.cpp index 4bf67921b..22f001704 100644 --- a/src/core/hle/service/glue/glue_manager.cpp +++ b/src/core/hle/service/glue/glue_manager.cpp | |||
| @@ -15,7 +15,8 @@ ARPManager::ARPManager() = default; | |||
| 15 | 15 | ||
| 16 | ARPManager::~ARPManager() = default; | 16 | ARPManager::~ARPManager() = default; |
| 17 | 17 | ||
| 18 | ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const { | 18 | Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_property, |
| 19 | u64 title_id) const { | ||
| 19 | if (title_id == 0) { | 20 | if (title_id == 0) { |
| 20 | return Glue::ResultInvalidProcessId; | 21 | return Glue::ResultInvalidProcessId; |
| 21 | } | 22 | } |
| @@ -25,10 +26,11 @@ ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) | |||
| 25 | return Glue::ResultProcessIdNotRegistered; | 26 | return Glue::ResultProcessIdNotRegistered; |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | return iter->second.launch; | 29 | *out_launch_property = iter->second.launch; |
| 30 | return ResultSuccess; | ||
| 29 | } | 31 | } |
| 30 | 32 | ||
| 31 | ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const { | 33 | Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const { |
| 32 | if (title_id == 0) { | 34 | if (title_id == 0) { |
| 33 | return Glue::ResultInvalidProcessId; | 35 | return Glue::ResultInvalidProcessId; |
| 34 | } | 36 | } |
| @@ -38,7 +40,8 @@ ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const { | |||
| 38 | return Glue::ResultProcessIdNotRegistered; | 40 | return Glue::ResultProcessIdNotRegistered; |
| 39 | } | 41 | } |
| 40 | 42 | ||
| 41 | return iter->second.control; | 43 | *out_control_property = iter->second.control; |
| 44 | return ResultSuccess; | ||
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, | 47 | Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, |
diff --git a/src/core/hle/service/glue/glue_manager.h b/src/core/hle/service/glue/glue_manager.h index 1cf53d9d9..216aa34c1 100644 --- a/src/core/hle/service/glue/glue_manager.h +++ b/src/core/hle/service/glue/glue_manager.h | |||
| @@ -32,12 +32,12 @@ public: | |||
| 32 | // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was | 32 | // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was |
| 33 | // previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or | 33 | // previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or |
| 34 | // ResultInvalidProcessId if the title ID is 0. | 34 | // ResultInvalidProcessId if the title ID is 0. |
| 35 | ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const; | 35 | Result GetLaunchProperty(ApplicationLaunchProperty* out_launch_property, u64 title_id) const; |
| 36 | 36 | ||
| 37 | // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to | 37 | // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to |
| 38 | // the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered | 38 | // the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered |
| 39 | // if it was never registered or ResultInvalidProcessId if the title ID is 0. | 39 | // if it was never registered or ResultInvalidProcessId if the title ID is 0. |
| 40 | ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const; | 40 | Result GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const; |
| 41 | 41 | ||
| 42 | // Adds a new entry to the internal database with the provided parameters, returning | 42 | // Adds a new entry to the internal database with the provided parameters, returning |
| 43 | // ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate | 43 | // ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate |
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 055c0a2db..c73035c77 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -357,7 +357,8 @@ public: | |||
| 357 | return ResultSuccess; | 357 | return ResultSuccess; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) { | 360 | Result MapProcessCodeMemory(VAddr* out_map_location, Kernel::KProcess* process, VAddr base_addr, |
| 361 | u64 size) { | ||
| 361 | auto& page_table{process->GetPageTable()}; | 362 | auto& page_table{process->GetPageTable()}; |
| 362 | VAddr addr{}; | 363 | VAddr addr{}; |
| 363 | 364 | ||
| @@ -372,20 +373,21 @@ public: | |||
| 372 | R_TRY(result); | 373 | R_TRY(result); |
| 373 | 374 | ||
| 374 | if (ValidateRegionForMap(page_table, addr, size)) { | 375 | if (ValidateRegionForMap(page_table, addr, size)) { |
| 375 | return addr; | 376 | *out_map_location = addr; |
| 377 | return ResultSuccess; | ||
| 376 | } | 378 | } |
| 377 | } | 379 | } |
| 378 | 380 | ||
| 379 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; | 381 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; |
| 380 | } | 382 | } |
| 381 | 383 | ||
| 382 | ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size, | 384 | Result MapNro(VAddr* out_map_location, Kernel::KProcess* process, VAddr nro_addr, |
| 383 | VAddr bss_addr, std::size_t bss_size, std::size_t size) { | 385 | std::size_t nro_size, VAddr bss_addr, std::size_t bss_size, std::size_t size) { |
| 384 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { | 386 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { |
| 385 | auto& page_table{process->GetPageTable()}; | 387 | auto& page_table{process->GetPageTable()}; |
| 386 | VAddr addr{}; | 388 | VAddr addr{}; |
| 387 | 389 | ||
| 388 | CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size)); | 390 | R_TRY(MapProcessCodeMemory(&addr, process, nro_addr, nro_size)); |
| 389 | 391 | ||
| 390 | if (bss_size) { | 392 | if (bss_size) { |
| 391 | auto block_guard = detail::ScopeExit([&] { | 393 | auto block_guard = detail::ScopeExit([&] { |
| @@ -411,7 +413,8 @@ public: | |||
| 411 | } | 413 | } |
| 412 | 414 | ||
| 413 | if (ValidateRegionForMap(page_table, addr, size)) { | 415 | if (ValidateRegionForMap(page_table, addr, size)) { |
| 414 | return addr; | 416 | *out_map_location = addr; |
| 417 | return ResultSuccess; | ||
| 415 | } | 418 | } |
| 416 | } | 419 | } |
| 417 | 420 | ||
| @@ -437,9 +440,9 @@ public: | |||
| 437 | CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, | 440 | CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, |
| 438 | nro_header.segment_headers[DATA_INDEX].memory_size); | 441 | nro_header.segment_headers[DATA_INDEX].memory_size); |
| 439 | 442 | ||
| 440 | CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission( | 443 | R_TRY(process->GetPageTable().SetProcessMemoryPermission( |
| 441 | text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute)); | 444 | text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute)); |
| 442 | CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission( | 445 | R_TRY(process->GetPageTable().SetProcessMemoryPermission( |
| 443 | ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read)); | 446 | ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read)); |
| 444 | 447 | ||
| 445 | return process->GetPageTable().SetProcessMemoryPermission( | 448 | return process->GetPageTable().SetProcessMemoryPermission( |
| @@ -542,31 +545,32 @@ public: | |||
| 542 | } | 545 | } |
| 543 | 546 | ||
| 544 | // Map memory for the NRO | 547 | // Map memory for the NRO |
| 545 | const auto map_result{MapNro(system.ApplicationProcess(), nro_address, nro_size, | 548 | VAddr map_location{}; |
| 546 | bss_address, bss_size, nro_size + bss_size)}; | 549 | const auto map_result{MapNro(&map_location, system.ApplicationProcess(), nro_address, |
| 547 | if (map_result.Failed()) { | 550 | nro_size, bss_address, bss_size, nro_size + bss_size)}; |
| 551 | if (map_result != ResultSuccess) { | ||
| 548 | IPC::ResponseBuilder rb{ctx, 2}; | 552 | IPC::ResponseBuilder rb{ctx, 2}; |
| 549 | rb.Push(map_result.Code()); | 553 | rb.Push(map_result); |
| 550 | } | 554 | } |
| 551 | 555 | ||
| 552 | // Load the NRO into the mapped memory | 556 | // Load the NRO into the mapped memory |
| 553 | if (const auto result{ | 557 | if (const auto result{ |
| 554 | LoadNro(system.ApplicationProcess(), header, nro_address, *map_result)}; | 558 | LoadNro(system.ApplicationProcess(), header, nro_address, map_location)}; |
| 555 | result.IsError()) { | 559 | result.IsError()) { |
| 556 | IPC::ResponseBuilder rb{ctx, 2}; | 560 | IPC::ResponseBuilder rb{ctx, 2}; |
| 557 | rb.Push(map_result.Code()); | 561 | rb.Push(result); |
| 558 | } | 562 | } |
| 559 | 563 | ||
| 560 | // Track the loaded NRO | 564 | // Track the loaded NRO |
| 561 | nro.insert_or_assign(*map_result, | 565 | nro.insert_or_assign(map_location, |
| 562 | NROInfo{hash, *map_result, nro_size, bss_address, bss_size, | 566 | NROInfo{hash, map_location, nro_size, bss_address, bss_size, |
| 563 | header.segment_headers[TEXT_INDEX].memory_size, | 567 | header.segment_headers[TEXT_INDEX].memory_size, |
| 564 | header.segment_headers[RO_INDEX].memory_size, | 568 | header.segment_headers[RO_INDEX].memory_size, |
| 565 | header.segment_headers[DATA_INDEX].memory_size, nro_address}); | 569 | header.segment_headers[DATA_INDEX].memory_size, nro_address}); |
| 566 | 570 | ||
| 567 | IPC::ResponseBuilder rb{ctx, 4}; | 571 | IPC::ResponseBuilder rb{ctx, 4}; |
| 568 | rb.Push(ResultSuccess); | 572 | rb.Push(ResultSuccess); |
| 569 | rb.Push(*map_result); | 573 | rb.Push(map_location); |
| 570 | } | 574 | } |
| 571 | 575 | ||
| 572 | Result UnmapNro(const NROInfo& info) { | 576 | Result UnmapNro(const NROInfo& info) { |
| @@ -574,19 +578,19 @@ public: | |||
| 574 | auto& page_table{system.ApplicationProcess()->GetPageTable()}; | 578 | auto& page_table{system.ApplicationProcess()->GetPageTable()}; |
| 575 | 579 | ||
| 576 | if (info.bss_size != 0) { | 580 | if (info.bss_size != 0) { |
| 577 | CASCADE_CODE(page_table.UnmapCodeMemory( | 581 | R_TRY(page_table.UnmapCodeMemory( |
| 578 | info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address, | 582 | info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address, |
| 579 | info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 583 | info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 580 | } | 584 | } |
| 581 | 585 | ||
| 582 | CASCADE_CODE(page_table.UnmapCodeMemory( | 586 | R_TRY(page_table.UnmapCodeMemory( |
| 583 | info.nro_address + info.text_size + info.ro_size, | 587 | info.nro_address + info.text_size + info.ro_size, |
| 584 | info.src_addr + info.text_size + info.ro_size, info.data_size, | 588 | info.src_addr + info.text_size + info.ro_size, info.data_size, |
| 585 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 589 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 586 | CASCADE_CODE(page_table.UnmapCodeMemory( | 590 | R_TRY(page_table.UnmapCodeMemory( |
| 587 | info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size, | 591 | info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size, |
| 588 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 592 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 589 | CASCADE_CODE(page_table.UnmapCodeMemory( | 593 | R_TRY(page_table.UnmapCodeMemory( |
| 590 | info.nro_address, info.src_addr, info.text_size, | 594 | info.nro_address, info.src_addr, info.text_size, |
| 591 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 595 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 592 | return ResultSuccess; | 596 | return ResultSuccess; |
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 5c7adf97d..65c11a2f3 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp | |||
| @@ -101,20 +101,14 @@ private: | |||
| 101 | 101 | ||
| 102 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); | 102 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); |
| 103 | 103 | ||
| 104 | const auto result{manager.GetDefault(source_flag)}; | 104 | const auto default_miis{manager.GetDefault(source_flag)}; |
| 105 | if (result.Failed()) { | 105 | if (default_miis.size() > 0) { |
| 106 | IPC::ResponseBuilder rb{ctx, 2}; | 106 | ctx.WriteBuffer(SerializeArray(default_miis)); |
| 107 | rb.Push(result.Code()); | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (result->size() > 0) { | ||
| 112 | ctx.WriteBuffer(SerializeArray(*result)); | ||
| 113 | } | 107 | } |
| 114 | 108 | ||
| 115 | IPC::ResponseBuilder rb{ctx, 3}; | 109 | IPC::ResponseBuilder rb{ctx, 3}; |
| 116 | rb.Push(ResultSuccess); | 110 | rb.Push(ResultSuccess); |
| 117 | rb.Push<u32>(static_cast<u32>(result->size())); | 111 | rb.Push<u32>(static_cast<u32>(default_miis.size())); |
| 118 | } | 112 | } |
| 119 | 113 | ||
| 120 | void Get1(HLERequestContext& ctx) { | 114 | void Get1(HLERequestContext& ctx) { |
| @@ -123,15 +117,10 @@ private: | |||
| 123 | 117 | ||
| 124 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); | 118 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); |
| 125 | 119 | ||
| 126 | const auto result{manager.GetDefault(source_flag)}; | 120 | const auto default_miis{manager.GetDefault(source_flag)}; |
| 127 | if (result.Failed()) { | ||
| 128 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 129 | rb.Push(result.Code()); | ||
| 130 | return; | ||
| 131 | } | ||
| 132 | 121 | ||
| 133 | std::vector<CharInfo> values; | 122 | std::vector<CharInfo> values; |
| 134 | for (const auto& element : *result) { | 123 | for (const auto& element : default_miis) { |
| 135 | values.emplace_back(element.info); | 124 | values.emplace_back(element.info); |
| 136 | } | 125 | } |
| 137 | 126 | ||
| @@ -139,7 +128,7 @@ private: | |||
| 139 | 128 | ||
| 140 | IPC::ResponseBuilder rb{ctx, 3}; | 129 | IPC::ResponseBuilder rb{ctx, 3}; |
| 141 | rb.Push(ResultSuccess); | 130 | rb.Push(ResultSuccess); |
| 142 | rb.Push<u32>(static_cast<u32>(result->size())); | 131 | rb.Push<u32>(static_cast<u32>(default_miis.size())); |
| 143 | } | 132 | } |
| 144 | 133 | ||
| 145 | void UpdateLatest(HLERequestContext& ctx) { | 134 | void UpdateLatest(HLERequestContext& ctx) { |
| @@ -149,16 +138,17 @@ private: | |||
| 149 | 138 | ||
| 150 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); | 139 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); |
| 151 | 140 | ||
| 152 | const auto result{manager.UpdateLatest(info, source_flag)}; | 141 | CharInfo new_char_info{}; |
| 153 | if (result.Failed()) { | 142 | const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)}; |
| 143 | if (result != ResultSuccess) { | ||
| 154 | IPC::ResponseBuilder rb{ctx, 2}; | 144 | IPC::ResponseBuilder rb{ctx, 2}; |
| 155 | rb.Push(result.Code()); | 145 | rb.Push(result); |
| 156 | return; | 146 | return; |
| 157 | } | 147 | } |
| 158 | 148 | ||
| 159 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; | 149 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; |
| 160 | rb.Push(ResultSuccess); | 150 | rb.Push(ResultSuccess); |
| 161 | rb.PushRaw<CharInfo>(*result); | 151 | rb.PushRaw<CharInfo>(new_char_info); |
| 162 | } | 152 | } |
| 163 | 153 | ||
| 164 | void BuildRandom(HLERequestContext& ctx) { | 154 | void BuildRandom(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index c920650f5..46125d473 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp | |||
| @@ -409,8 +409,7 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const { | |||
| 409 | return static_cast<u32>(count); | 409 | return static_cast<u32>(count); |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | ResultVal<CharInfo> MiiManager::UpdateLatest([[maybe_unused]] const CharInfo& info, | 412 | Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) { |
| 413 | SourceFlag source_flag) { | ||
| 414 | if ((source_flag & SourceFlag::Database) == SourceFlag::None) { | 413 | if ((source_flag & SourceFlag::Database) == SourceFlag::None) { |
| 415 | return ERROR_CANNOT_FIND_ENTRY; | 414 | return ERROR_CANNOT_FIND_ENTRY; |
| 416 | } | 415 | } |
| @@ -672,7 +671,7 @@ bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { | |||
| 672 | return is_valid; | 671 | return is_valid; |
| 673 | } | 672 | } |
| 674 | 673 | ||
| 675 | ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) { | 674 | std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) { |
| 676 | std::vector<MiiInfoElement> result; | 675 | std::vector<MiiInfoElement> result; |
| 677 | 676 | ||
| 678 | if ((source_flag & SourceFlag::Default) == SourceFlag::None) { | 677 | if ((source_flag & SourceFlag::Default) == SourceFlag::None) { |
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index 5525fcd1c..45c2be3c8 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h | |||
| @@ -19,12 +19,12 @@ public: | |||
| 19 | bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter); | 19 | bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter); |
| 20 | bool IsFullDatabase() const; | 20 | bool IsFullDatabase() const; |
| 21 | u32 GetCount(SourceFlag source_flag) const; | 21 | u32 GetCount(SourceFlag source_flag) const; |
| 22 | ResultVal<CharInfo> UpdateLatest(const CharInfo& info, SourceFlag source_flag); | 22 | Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag); |
| 23 | CharInfo BuildRandom(Age age, Gender gender, Race race); | 23 | CharInfo BuildRandom(Age age, Gender gender, Race race); |
| 24 | CharInfo BuildDefault(std::size_t index); | 24 | CharInfo BuildDefault(std::size_t index); |
| 25 | CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; | 25 | CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; |
| 26 | bool ValidateV3Info(const Ver3StoreData& mii_v3) const; | 26 | bool ValidateV3Info(const Ver3StoreData& mii_v3) const; |
| 27 | ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag); | 27 | std::vector<MiiInfoElement> GetDefault(SourceFlag source_flag); |
| 28 | Result GetIndex(const CharInfo& info, u32& index); | 28 | Result GetIndex(const CharInfo& info, u32& index); |
| 29 | 29 | ||
| 30 | // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData | 30 | // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData |
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 91c5a2182..6e0baf0be 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -392,19 +392,20 @@ void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestConte | |||
| 392 | IPC::RequestParser rp{ctx}; | 392 | IPC::RequestParser rp{ctx}; |
| 393 | const auto supported_languages = rp.Pop<u32>(); | 393 | const auto supported_languages = rp.Pop<u32>(); |
| 394 | 394 | ||
| 395 | const auto res = GetApplicationDesiredLanguage(supported_languages); | 395 | u8 desired_language{}; |
| 396 | if (res.Succeeded()) { | 396 | const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages); |
| 397 | if (res == ResultSuccess) { | ||
| 397 | IPC::ResponseBuilder rb{ctx, 3}; | 398 | IPC::ResponseBuilder rb{ctx, 3}; |
| 398 | rb.Push(ResultSuccess); | 399 | rb.Push(ResultSuccess); |
| 399 | rb.Push<u32>(*res); | 400 | rb.Push<u32>(desired_language); |
| 400 | } else { | 401 | } else { |
| 401 | IPC::ResponseBuilder rb{ctx, 2}; | 402 | IPC::ResponseBuilder rb{ctx, 2}; |
| 402 | rb.Push(res.Code()); | 403 | rb.Push(res); |
| 403 | } | 404 | } |
| 404 | } | 405 | } |
| 405 | 406 | ||
| 406 | ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( | 407 | Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language, |
| 407 | const u32 supported_languages) { | 408 | const u32 supported_languages) { |
| 408 | LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); | 409 | LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); |
| 409 | 410 | ||
| 410 | // Get language code from settings | 411 | // Get language code from settings |
| @@ -430,7 +431,8 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( | |||
| 430 | for (const auto lang : *priority_list) { | 431 | for (const auto lang : *priority_list) { |
| 431 | const auto supported_flag = GetSupportedLanguageFlag(lang); | 432 | const auto supported_flag = GetSupportedLanguageFlag(lang); |
| 432 | if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { | 433 | if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { |
| 433 | return static_cast<u8>(lang); | 434 | *out_desired_language = static_cast<u8>(lang); |
| 435 | return ResultSuccess; | ||
| 434 | } | 436 | } |
| 435 | } | 437 | } |
| 436 | 438 | ||
| @@ -444,19 +446,20 @@ void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( | |||
| 444 | IPC::RequestParser rp{ctx}; | 446 | IPC::RequestParser rp{ctx}; |
| 445 | const auto application_language = rp.Pop<u8>(); | 447 | const auto application_language = rp.Pop<u8>(); |
| 446 | 448 | ||
| 447 | const auto res = ConvertApplicationLanguageToLanguageCode(application_language); | 449 | u64 language_code{}; |
| 448 | if (res.Succeeded()) { | 450 | const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language); |
| 451 | if (res == ResultSuccess) { | ||
| 449 | IPC::ResponseBuilder rb{ctx, 4}; | 452 | IPC::ResponseBuilder rb{ctx, 4}; |
| 450 | rb.Push(ResultSuccess); | 453 | rb.Push(ResultSuccess); |
| 451 | rb.Push(*res); | 454 | rb.Push(language_code); |
| 452 | } else { | 455 | } else { |
| 453 | IPC::ResponseBuilder rb{ctx, 2}; | 456 | IPC::ResponseBuilder rb{ctx, 2}; |
| 454 | rb.Push(res.Code()); | 457 | rb.Push(res); |
| 455 | } | 458 | } |
| 456 | } | 459 | } |
| 457 | 460 | ||
| 458 | ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( | 461 | Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( |
| 459 | u8 application_language) { | 462 | u64* out_language_code, u8 application_language) { |
| 460 | const auto language_code = | 463 | const auto language_code = |
| 461 | ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); | 464 | ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); |
| 462 | if (language_code == std::nullopt) { | 465 | if (language_code == std::nullopt) { |
| @@ -464,7 +467,8 @@ ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguag | |||
| 464 | return Service::NS::ResultApplicationLanguageNotFound; | 467 | return Service::NS::ResultApplicationLanguageNotFound; |
| 465 | } | 468 | } |
| 466 | 469 | ||
| 467 | return static_cast<u64>(*language_code); | 470 | *out_language_code = static_cast<u64>(*language_code); |
| 471 | return ResultSuccess; | ||
| 468 | } | 472 | } |
| 469 | 473 | ||
| 470 | IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) | 474 | IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) |
| @@ -618,12 +622,13 @@ void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequ | |||
| 618 | static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); | 622 | static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); |
| 619 | 623 | ||
| 620 | IPC::RequestParser rp{ctx}; | 624 | IPC::RequestParser rp{ctx}; |
| 625 | std::vector<u8> nacp_data{}; | ||
| 621 | const auto parameters{rp.PopRaw<RequestParameters>()}; | 626 | const auto parameters{rp.PopRaw<RequestParameters>()}; |
| 622 | const auto nacp_data{system.GetARPManager().GetControlProperty(parameters.application_id)}; | 627 | const auto result = |
| 623 | const auto result = nacp_data ? ResultSuccess : ResultUnknown; | 628 | system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id); |
| 624 | 629 | ||
| 625 | if (nacp_data) { | 630 | if (result == ResultSuccess) { |
| 626 | ctx.WriteBuffer(nacp_data->data(), nacp_data->size()); | 631 | ctx.WriteBuffer(nacp_data.data(), nacp_data.size()); |
| 627 | } | 632 | } |
| 628 | 633 | ||
| 629 | IPC::ResponseBuilder rb{ctx, 2}; | 634 | IPC::ResponseBuilder rb{ctx, 2}; |
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 203388e1f..175dad780 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h | |||
| @@ -28,8 +28,9 @@ public: | |||
| 28 | explicit IApplicationManagerInterface(Core::System& system_); | 28 | explicit IApplicationManagerInterface(Core::System& system_); |
| 29 | ~IApplicationManagerInterface() override; | 29 | ~IApplicationManagerInterface() override; |
| 30 | 30 | ||
| 31 | ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); | 31 | Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages); |
| 32 | ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language); | 32 | Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code, |
| 33 | u8 application_language); | ||
| 33 | 34 | ||
| 34 | private: | 35 | private: |
| 35 | void GetApplicationControlData(HLERequestContext& ctx); | 36 | void GetApplicationControlData(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 5f55cd31e..21f31f7a0 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -183,7 +183,7 @@ std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) { | |||
| 183 | return layer->GetBinderId(); | 183 | return layer->GetBinderId(); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | ResultVal<Kernel::KReadableEvent*> Nvnflinger::FindVsyncEvent(u64 display_id) { | 186 | Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) { |
| 187 | const auto lock_guard = Lock(); | 187 | const auto lock_guard = Lock(); |
| 188 | auto* const display = FindDisplay(display_id); | 188 | auto* const display = FindDisplay(display_id); |
| 189 | 189 | ||
| @@ -191,7 +191,7 @@ ResultVal<Kernel::KReadableEvent*> Nvnflinger::FindVsyncEvent(u64 display_id) { | |||
| 191 | return VI::ResultNotFound; | 191 | return VI::ResultNotFound; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | return display->GetVSyncEvent(); | 194 | return display->GetVSyncEvent(out_vsync_event); |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | VI::Display* Nvnflinger::FindDisplay(u64 display_id) { | 197 | VI::Display* Nvnflinger::FindDisplay(u64 display_id) { |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index ef236303a..f478c2bc6 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -82,7 +82,7 @@ public: | |||
| 82 | /// | 82 | /// |
| 83 | /// If an invalid display ID is provided, then VI::ResultNotFound is returned. | 83 | /// If an invalid display ID is provided, then VI::ResultNotFound is returned. |
| 84 | /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. | 84 | /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. |
| 85 | [[nodiscard]] ResultVal<Kernel::KReadableEvent*> FindVsyncEvent(u64 display_id); | 85 | [[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id); |
| 86 | 86 | ||
| 87 | /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when | 87 | /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when |
| 88 | /// finished. | 88 | /// finished. |
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp index 7c8a539b8..5db1703d1 100644 --- a/src/core/hle/service/pctl/pctl_module.cpp +++ b/src/core/hle/service/pctl/pctl_module.cpp | |||
| @@ -152,7 +152,7 @@ private: | |||
| 152 | if (pin_code[0] == '\0') { | 152 | if (pin_code[0] == '\0') { |
| 153 | return true; | 153 | return true; |
| 154 | } | 154 | } |
| 155 | if (!restriction_settings.is_free_communication_default_on) { | 155 | if (!settings.is_free_communication_default_on) { |
| 156 | return true; | 156 | return true; |
| 157 | } | 157 | } |
| 158 | // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here | 158 | // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here |
| @@ -168,21 +168,21 @@ private: | |||
| 168 | if (pin_code[0] == '\0') { | 168 | if (pin_code[0] == '\0') { |
| 169 | return true; | 169 | return true; |
| 170 | } | 170 | } |
| 171 | if (!restriction_settings.is_stero_vision_restricted) { | 171 | if (!settings.is_stero_vision_restricted) { |
| 172 | return false; | 172 | return false; |
| 173 | } | 173 | } |
| 174 | return true; | 174 | return true; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | void SetStereoVisionRestrictionImpl(bool is_restricted) { | 177 | void SetStereoVisionRestrictionImpl(bool is_restricted) { |
| 178 | if (restriction_settings.disabled) { | 178 | if (settings.disabled) { |
| 179 | return; | 179 | return; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | if (pin_code[0] == '\0') { | 182 | if (pin_code[0] == '\0') { |
| 183 | return; | 183 | return; |
| 184 | } | 184 | } |
| 185 | restriction_settings.is_stero_vision_restricted = is_restricted; | 185 | settings.is_stero_vision_restricted = is_restricted; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | void Initialize(HLERequestContext& ctx) { | 188 | void Initialize(HLERequestContext& ctx) { |
| @@ -430,7 +430,7 @@ private: | |||
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | rb.Push(ResultSuccess); | 432 | rb.Push(ResultSuccess); |
| 433 | rb.Push(restriction_settings.is_stero_vision_restricted); | 433 | rb.Push(settings.is_stero_vision_restricted); |
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | void ResetConfirmedStereoVisionPermission(HLERequestContext& ctx) { | 436 | void ResetConfirmedStereoVisionPermission(HLERequestContext& ctx) { |
| @@ -460,22 +460,28 @@ private: | |||
| 460 | bool stereo_vision{}; | 460 | bool stereo_vision{}; |
| 461 | }; | 461 | }; |
| 462 | 462 | ||
| 463 | // This is nn::pctl::RestrictionSettings | 463 | struct ParentalControlSettings { |
| 464 | struct RestrictionSettings { | ||
| 465 | bool is_stero_vision_restricted{}; | 464 | bool is_stero_vision_restricted{}; |
| 466 | bool is_free_communication_default_on{}; | 465 | bool is_free_communication_default_on{}; |
| 467 | bool disabled{}; | 466 | bool disabled{}; |
| 468 | }; | 467 | }; |
| 468 | |||
| 469 | // This is nn::pctl::RestrictionSettings | ||
| 470 | struct RestrictionSettings { | ||
| 471 | u8 rating_age; | ||
| 472 | bool sns_post_restriction; | ||
| 473 | bool free_communication_restriction; | ||
| 474 | }; | ||
| 469 | static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size."); | 475 | static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size."); |
| 470 | 476 | ||
| 471 | // This is nn::pctl::PlayTimerSettings | 477 | // This is nn::pctl::PlayTimerSettings |
| 472 | struct PlayTimerSettings { | 478 | struct PlayTimerSettings { |
| 473 | // TODO: RE the actual contents of this struct | 479 | std::array<u32, 13> settings; |
| 474 | std::array<u8, 0x34> settings; | ||
| 475 | }; | 480 | }; |
| 476 | static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size."); | 481 | static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size."); |
| 477 | 482 | ||
| 478 | States states{}; | 483 | States states{}; |
| 484 | ParentalControlSettings settings{}; | ||
| 479 | RestrictionSettings restriction_settings{}; | 485 | RestrictionSettings restriction_settings{}; |
| 480 | std::array<char, 8> pin_code{}; | 486 | std::array<char, 8> pin_code{}; |
| 481 | Capability capability{}; | 487 | Capability capability{}; |
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index d1e99b184..e2e399534 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp | |||
| @@ -102,16 +102,17 @@ Result ServerManager::RegisterNamedService(const std::string& service_name, | |||
| 102 | m_system.ServiceManager().RegisterService(service_name, max_sessions, handler))); | 102 | m_system.ServiceManager().RegisterService(service_name, max_sessions, handler))); |
| 103 | 103 | ||
| 104 | // Get the registered port. | 104 | // Get the registered port. |
| 105 | auto port = m_system.ServiceManager().GetServicePort(service_name); | 105 | Kernel::KPort* port{}; |
| 106 | ASSERT(port.Succeeded()); | 106 | ASSERT( |
| 107 | R_SUCCEEDED(m_system.ServiceManager().GetServicePort(std::addressof(port), service_name))); | ||
| 107 | 108 | ||
| 108 | // Open a new reference to the server port. | 109 | // Open a new reference to the server port. |
| 109 | (*port)->GetServerPort().Open(); | 110 | port->GetServerPort().Open(); |
| 110 | 111 | ||
| 111 | // Begin tracking the server port. | 112 | // Begin tracking the server port. |
| 112 | { | 113 | { |
| 113 | std::scoped_lock ll{m_list_mutex}; | 114 | std::scoped_lock ll{m_list_mutex}; |
| 114 | m_ports.emplace(std::addressof((*port)->GetServerPort()), std::move(handler)); | 115 | m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler)); |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | // Signal the wakeup event. | 118 | // Signal the wakeup event. |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 1608fa24c..9ab718e0a 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -52,8 +52,7 @@ static Result ValidateServiceName(const std::string& name) { | |||
| 52 | 52 | ||
| 53 | Result ServiceManager::RegisterService(std::string name, u32 max_sessions, | 53 | Result ServiceManager::RegisterService(std::string name, u32 max_sessions, |
| 54 | SessionRequestHandlerPtr handler) { | 54 | SessionRequestHandlerPtr handler) { |
| 55 | 55 | R_TRY(ValidateServiceName(name)); | |
| 56 | CASCADE_CODE(ValidateServiceName(name)); | ||
| 57 | 56 | ||
| 58 | std::scoped_lock lk{lock}; | 57 | std::scoped_lock lk{lock}; |
| 59 | if (registered_services.find(name) != registered_services.end()) { | 58 | if (registered_services.find(name) != registered_services.end()) { |
| @@ -77,7 +76,7 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions, | |||
| 77 | } | 76 | } |
| 78 | 77 | ||
| 79 | Result ServiceManager::UnregisterService(const std::string& name) { | 78 | Result ServiceManager::UnregisterService(const std::string& name) { |
| 80 | CASCADE_CODE(ValidateServiceName(name)); | 79 | R_TRY(ValidateServiceName(name)); |
| 81 | 80 | ||
| 82 | std::scoped_lock lk{lock}; | 81 | std::scoped_lock lk{lock}; |
| 83 | const auto iter = registered_services.find(name); | 82 | const auto iter = registered_services.find(name); |
| @@ -92,8 +91,8 @@ Result ServiceManager::UnregisterService(const std::string& name) { | |||
| 92 | return ResultSuccess; | 91 | return ResultSuccess; |
| 93 | } | 92 | } |
| 94 | 93 | ||
| 95 | ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) { | 94 | Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::string& name) { |
| 96 | CASCADE_CODE(ValidateServiceName(name)); | 95 | R_TRY(ValidateServiceName(name)); |
| 97 | 96 | ||
| 98 | std::scoped_lock lk{lock}; | 97 | std::scoped_lock lk{lock}; |
| 99 | auto it = service_ports.find(name); | 98 | auto it = service_ports.find(name); |
| @@ -102,7 +101,8 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name | |||
| 102 | return Service::SM::ResultNotRegistered; | 101 | return Service::SM::ResultNotRegistered; |
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | return it->second; | 104 | *out_port = it->second; |
| 105 | return ResultSuccess; | ||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /** | 108 | /** |
| @@ -122,32 +122,34 @@ void SM::Initialize(HLERequestContext& ctx) { | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | void SM::GetService(HLERequestContext& ctx) { | 124 | void SM::GetService(HLERequestContext& ctx) { |
| 125 | auto result = GetServiceImpl(ctx); | 125 | Kernel::KClientSession* client_session{}; |
| 126 | auto result = GetServiceImpl(&client_session, ctx); | ||
| 126 | if (ctx.GetIsDeferred()) { | 127 | if (ctx.GetIsDeferred()) { |
| 127 | // Don't overwrite the command buffer. | 128 | // Don't overwrite the command buffer. |
| 128 | return; | 129 | return; |
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | if (result.Succeeded()) { | 132 | if (result == ResultSuccess) { |
| 132 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 133 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 133 | rb.Push(result.Code()); | 134 | rb.Push(result); |
| 134 | rb.PushMoveObjects(result.Unwrap()); | 135 | rb.PushMoveObjects(client_session); |
| 135 | } else { | 136 | } else { |
| 136 | IPC::ResponseBuilder rb{ctx, 2}; | 137 | IPC::ResponseBuilder rb{ctx, 2}; |
| 137 | rb.Push(result.Code()); | 138 | rb.Push(result); |
| 138 | } | 139 | } |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | void SM::GetServiceTipc(HLERequestContext& ctx) { | 142 | void SM::GetServiceTipc(HLERequestContext& ctx) { |
| 142 | auto result = GetServiceImpl(ctx); | 143 | Kernel::KClientSession* client_session{}; |
| 144 | auto result = GetServiceImpl(&client_session, ctx); | ||
| 143 | if (ctx.GetIsDeferred()) { | 145 | if (ctx.GetIsDeferred()) { |
| 144 | // Don't overwrite the command buffer. | 146 | // Don't overwrite the command buffer. |
| 145 | return; | 147 | return; |
| 146 | } | 148 | } |
| 147 | 149 | ||
| 148 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 150 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 149 | rb.Push(result.Code()); | 151 | rb.Push(result); |
| 150 | rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); | 152 | rb.PushMoveObjects(result == ResultSuccess ? client_session : nullptr); |
| 151 | } | 153 | } |
| 152 | 154 | ||
| 153 | static std::string PopServiceName(IPC::RequestParser& rp) { | 155 | static std::string PopServiceName(IPC::RequestParser& rp) { |
| @@ -161,7 +163,7 @@ static std::string PopServiceName(IPC::RequestParser& rp) { | |||
| 161 | return result; | 163 | return result; |
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) { | 166 | Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx) { |
| 165 | if (!ctx.GetManager()->GetIsInitializedForSm()) { | 167 | if (!ctx.GetManager()->GetIsInitializedForSm()) { |
| 166 | return Service::SM::ResultInvalidClient; | 168 | return Service::SM::ResultInvalidClient; |
| 167 | } | 169 | } |
| @@ -170,18 +172,18 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) { | |||
| 170 | std::string name(PopServiceName(rp)); | 172 | std::string name(PopServiceName(rp)); |
| 171 | 173 | ||
| 172 | // Find the named port. | 174 | // Find the named port. |
| 173 | auto port_result = service_manager.GetServicePort(name); | 175 | Kernel::KPort* port{}; |
| 174 | if (port_result.Code() == Service::SM::ResultInvalidServiceName) { | 176 | auto port_result = service_manager.GetServicePort(&port, name); |
| 177 | if (port_result == Service::SM::ResultInvalidServiceName) { | ||
| 175 | LOG_ERROR(Service_SM, "Invalid service name '{}'", name); | 178 | LOG_ERROR(Service_SM, "Invalid service name '{}'", name); |
| 176 | return Service::SM::ResultInvalidServiceName; | 179 | return Service::SM::ResultInvalidServiceName; |
| 177 | } | 180 | } |
| 178 | 181 | ||
| 179 | if (port_result.Failed()) { | 182 | if (port_result != ResultSuccess) { |
| 180 | LOG_INFO(Service_SM, "Waiting for service {} to become available", name); | 183 | LOG_INFO(Service_SM, "Waiting for service {} to become available", name); |
| 181 | ctx.SetIsDeferred(); | 184 | ctx.SetIsDeferred(); |
| 182 | return Service::SM::ResultNotRegistered; | 185 | return Service::SM::ResultNotRegistered; |
| 183 | } | 186 | } |
| 184 | auto& port = port_result.Unwrap(); | ||
| 185 | 187 | ||
| 186 | // Create a new session. | 188 | // Create a new session. |
| 187 | Kernel::KClientSession* session{}; | 189 | Kernel::KClientSession* session{}; |
| @@ -192,7 +194,8 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) { | |||
| 192 | 194 | ||
| 193 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); | 195 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); |
| 194 | 196 | ||
| 195 | return session; | 197 | *out_client_session = session; |
| 198 | return ResultSuccess; | ||
| 196 | } | 199 | } |
| 197 | 200 | ||
| 198 | void SM::RegisterService(HLERequestContext& ctx) { | 201 | void SM::RegisterService(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 6697f4007..14bfaf8c2 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -42,7 +42,7 @@ private: | |||
| 42 | void RegisterService(HLERequestContext& ctx); | 42 | void RegisterService(HLERequestContext& ctx); |
| 43 | void UnregisterService(HLERequestContext& ctx); | 43 | void UnregisterService(HLERequestContext& ctx); |
| 44 | 44 | ||
| 45 | ResultVal<Kernel::KClientSession*> GetServiceImpl(HLERequestContext& ctx); | 45 | Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx); |
| 46 | 46 | ||
| 47 | ServiceManager& service_manager; | 47 | ServiceManager& service_manager; |
| 48 | Kernel::KernelCore& kernel; | 48 | Kernel::KernelCore& kernel; |
| @@ -55,7 +55,7 @@ public: | |||
| 55 | 55 | ||
| 56 | Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler); | 56 | Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler); |
| 57 | Result UnregisterService(const std::string& name); | 57 | Result UnregisterService(const std::string& name); |
| 58 | ResultVal<Kernel::KPort*> GetServicePort(const std::string& name); | 58 | Result GetServicePort(Kernel::KPort** out_port, const std::string& name); |
| 59 | 59 | ||
| 60 | template <Common::DerivedFrom<SessionRequestHandler> T> | 60 | template <Common::DerivedFrom<SessionRequestHandler> T> |
| 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { | 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { |
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp index 5dfcaabb1..bac21752a 100644 --- a/src/core/hle/service/sockets/nsd.cpp +++ b/src/core/hle/service/sockets/nsd.cpp | |||
| @@ -54,7 +54,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na | |||
| 54 | RegisterHandlers(functions); | 54 | RegisterHandlers(functions); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static ResultVal<std::string> ResolveImpl(const std::string& fqdn_in) { | 57 | static std::string ResolveImpl(const std::string& fqdn_in) { |
| 58 | // The real implementation makes various substitutions. | 58 | // The real implementation makes various substitutions. |
| 59 | // For now we just return the string as-is, which is good enough when not | 59 | // For now we just return the string as-is, which is good enough when not |
| 60 | // connecting to real Nintendo servers. | 60 | // connecting to real Nintendo servers. |
| @@ -64,13 +64,10 @@ static ResultVal<std::string> ResolveImpl(const std::string& fqdn_in) { | |||
| 64 | 64 | ||
| 65 | static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) { | 65 | static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) { |
| 66 | const auto res = ResolveImpl(fqdn_in); | 66 | const auto res = ResolveImpl(fqdn_in); |
| 67 | if (res.Failed()) { | 67 | if (res.size() >= fqdn_out.size()) { |
| 68 | return res.Code(); | ||
| 69 | } | ||
| 70 | if (res->size() >= fqdn_out.size()) { | ||
| 71 | return ResultOverflow; | 68 | return ResultOverflow; |
| 72 | } | 69 | } |
| 73 | std::memcpy(fqdn_out.data(), res->c_str(), res->size() + 1); | 70 | std::memcpy(fqdn_out.data(), res.c_str(), res.size() + 1); |
| 74 | return ResultSuccess; | 71 | return ResultSuccess; |
| 75 | } | 72 | } |
| 76 | 73 | ||
diff --git a/src/core/hle/service/spl/spl_module.cpp b/src/core/hle/service/spl/spl_module.cpp index cd631b2ea..549e6f4fa 100644 --- a/src/core/hle/service/spl/spl_module.cpp +++ b/src/core/hle/service/spl/spl_module.cpp | |||
| @@ -30,10 +30,10 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) { | |||
| 30 | 30 | ||
| 31 | // This should call svcCallSecureMonitor with the appropriate args. | 31 | // This should call svcCallSecureMonitor with the appropriate args. |
| 32 | // Since we do not have it implemented yet, we will use this for now. | 32 | // Since we do not have it implemented yet, we will use this for now. |
| 33 | const auto smc_result = GetConfigImpl(config_item); | 33 | u64 smc_result{}; |
| 34 | const auto result_code = smc_result.Code(); | 34 | const auto result_code = GetConfigImpl(&smc_result, config_item); |
| 35 | 35 | ||
| 36 | if (smc_result.Failed()) { | 36 | if (result_code != ResultSuccess) { |
| 37 | LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item, | 37 | LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item, |
| 38 | result_code.raw); | 38 | result_code.raw); |
| 39 | 39 | ||
| @@ -42,11 +42,11 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) { | |||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item, | 44 | LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item, |
| 45 | result_code.raw, *smc_result); | 45 | result_code.raw, smc_result); |
| 46 | 46 | ||
| 47 | IPC::ResponseBuilder rb{ctx, 4}; | 47 | IPC::ResponseBuilder rb{ctx, 4}; |
| 48 | rb.Push(result_code); | 48 | rb.Push(result_code); |
| 49 | rb.Push(*smc_result); | 49 | rb.Push(smc_result); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | void Module::Interface::ModularExponentiate(HLERequestContext& ctx) { | 52 | void Module::Interface::ModularExponentiate(HLERequestContext& ctx) { |
| @@ -99,7 +99,7 @@ void Module::Interface::GetBootReason(HLERequestContext& ctx) { | |||
| 99 | rb.Push(ResultSecureMonitorNotImplemented); | 99 | rb.Push(ResultSecureMonitorNotImplemented); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const { | 102 | Result Module::Interface::GetConfigImpl(u64* out_config, ConfigItem config_item) const { |
| 103 | switch (config_item) { | 103 | switch (config_item) { |
| 104 | case ConfigItem::DisableProgramVerification: | 104 | case ConfigItem::DisableProgramVerification: |
| 105 | case ConfigItem::DramId: | 105 | case ConfigItem::DramId: |
| @@ -121,40 +121,50 @@ ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const { | |||
| 121 | return ResultSecureMonitorNotImplemented; | 121 | return ResultSecureMonitorNotImplemented; |
| 122 | case ConfigItem::ExosphereApiVersion: | 122 | case ConfigItem::ExosphereApiVersion: |
| 123 | // Get information about the current exosphere version. | 123 | // Get information about the current exosphere version. |
| 124 | return (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) | | 124 | *out_config = (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) | |
| 125 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) | | 125 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) | |
| 126 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) | | 126 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) | |
| 127 | (static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())); | 127 | (static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())); |
| 128 | return ResultSuccess; | ||
| 128 | case ConfigItem::ExosphereNeedsReboot: | 129 | case ConfigItem::ExosphereNeedsReboot: |
| 129 | // We are executing, so we aren't in the process of rebooting. | 130 | // We are executing, so we aren't in the process of rebooting. |
| 130 | return u64{0}; | 131 | *out_config = u64{0}; |
| 132 | return ResultSuccess; | ||
| 131 | case ConfigItem::ExosphereNeedsShutdown: | 133 | case ConfigItem::ExosphereNeedsShutdown: |
| 132 | // We are executing, so we aren't in the process of shutting down. | 134 | // We are executing, so we aren't in the process of shutting down. |
| 133 | return u64{0}; | 135 | *out_config = u64{0}; |
| 136 | return ResultSuccess; | ||
| 134 | case ConfigItem::ExosphereGitCommitHash: | 137 | case ConfigItem::ExosphereGitCommitHash: |
| 135 | // Get information about the current exosphere git commit hash. | 138 | // Get information about the current exosphere git commit hash. |
| 136 | return u64{0}; | 139 | *out_config = u64{0}; |
| 140 | return ResultSuccess; | ||
| 137 | case ConfigItem::ExosphereHasRcmBugPatch: | 141 | case ConfigItem::ExosphereHasRcmBugPatch: |
| 138 | // Get information about whether this unit has the RCM bug patched. | 142 | // Get information about whether this unit has the RCM bug patched. |
| 139 | return u64{0}; | 143 | *out_config = u64{0}; |
| 144 | return ResultSuccess; | ||
| 140 | case ConfigItem::ExosphereBlankProdInfo: | 145 | case ConfigItem::ExosphereBlankProdInfo: |
| 141 | // Get whether this unit should simulate a "blanked" PRODINFO. | 146 | // Get whether this unit should simulate a "blanked" PRODINFO. |
| 142 | return u64{0}; | 147 | *out_config = u64{0}; |
| 148 | return ResultSuccess; | ||
| 143 | case ConfigItem::ExosphereAllowCalWrites: | 149 | case ConfigItem::ExosphereAllowCalWrites: |
| 144 | // Get whether this unit should allow writing to the calibration partition. | 150 | // Get whether this unit should allow writing to the calibration partition. |
| 145 | return u64{0}; | 151 | *out_config = u64{0}; |
| 152 | return ResultSuccess; | ||
| 146 | case ConfigItem::ExosphereEmummcType: | 153 | case ConfigItem::ExosphereEmummcType: |
| 147 | // Get what kind of emummc this unit has active. | 154 | // Get what kind of emummc this unit has active. |
| 148 | return u64{0}; | 155 | *out_config = u64{0}; |
| 156 | return ResultSuccess; | ||
| 149 | case ConfigItem::ExospherePayloadAddress: | 157 | case ConfigItem::ExospherePayloadAddress: |
| 150 | // Gets the physical address of the reboot payload buffer, if one exists. | 158 | // Gets the physical address of the reboot payload buffer, if one exists. |
| 151 | return ResultSecureMonitorNotInitialized; | 159 | return ResultSecureMonitorNotInitialized; |
| 152 | case ConfigItem::ExosphereLogConfiguration: | 160 | case ConfigItem::ExosphereLogConfiguration: |
| 153 | // Get the log configuration. | 161 | // Get the log configuration. |
| 154 | return u64{0}; | 162 | *out_config = u64{0}; |
| 163 | return ResultSuccess; | ||
| 155 | case ConfigItem::ExosphereForceEnableUsb30: | 164 | case ConfigItem::ExosphereForceEnableUsb30: |
| 156 | // Get whether usb 3.0 should be force-enabled. | 165 | // Get whether usb 3.0 should be force-enabled. |
| 157 | return u64{0}; | 166 | *out_config = u64{0}; |
| 167 | return ResultSuccess; | ||
| 158 | default: | 168 | default: |
| 159 | return ResultSecureMonitorInvalidArgument; | 169 | return ResultSecureMonitorInvalidArgument; |
| 160 | } | 170 | } |
diff --git a/src/core/hle/service/spl/spl_module.h b/src/core/hle/service/spl/spl_module.h index e074e115d..06dcffa6c 100644 --- a/src/core/hle/service/spl/spl_module.h +++ b/src/core/hle/service/spl/spl_module.h | |||
| @@ -35,7 +35,7 @@ public: | |||
| 35 | std::shared_ptr<Module> module; | 35 | std::shared_ptr<Module> module; |
| 36 | 36 | ||
| 37 | private: | 37 | private: |
| 38 | ResultVal<u64> GetConfigImpl(ConfigItem config_item) const; | 38 | Result GetConfigImpl(u64* out_config, ConfigItem config_item) const; |
| 39 | 39 | ||
| 40 | std::mt19937 rng; | 40 | std::mt19937 rng; |
| 41 | }; | 41 | }; |
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 9c96f9763..2cba9e5c9 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include "common/string_util.h" | 4 | #include "common/string_util.h" |
| 5 | 5 | ||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hle/result.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | 8 | #include "core/hle/service/ipc_helpers.h" |
| 8 | #include "core/hle/service/server_manager.h" | 9 | #include "core/hle/service/server_manager.h" |
| 9 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| @@ -141,12 +142,12 @@ private: | |||
| 141 | bool did_set_host_name = false; | 142 | bool did_set_host_name = false; |
| 142 | bool did_handshake = false; | 143 | bool did_handshake = false; |
| 143 | 144 | ||
| 144 | ResultVal<s32> SetSocketDescriptorImpl(s32 fd) { | 145 | Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { |
| 145 | LOG_DEBUG(Service_SSL, "called, fd={}", fd); | 146 | LOG_DEBUG(Service_SSL, "called, fd={}", fd); |
| 146 | ASSERT(!did_handshake); | 147 | ASSERT(!did_handshake); |
| 147 | auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u"); | 148 | auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u"); |
| 148 | ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; }); | 149 | ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; }); |
| 149 | s32 ret_fd; | 150 | |
| 150 | // Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor | 151 | // Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor |
| 151 | if (do_not_close_socket) { | 152 | if (do_not_close_socket) { |
| 152 | auto res = bsd->DuplicateSocketImpl(fd); | 153 | auto res = bsd->DuplicateSocketImpl(fd); |
| @@ -156,9 +157,9 @@ private: | |||
| 156 | } | 157 | } |
| 157 | fd = *res; | 158 | fd = *res; |
| 158 | fd_to_close = fd; | 159 | fd_to_close = fd; |
| 159 | ret_fd = fd; | 160 | *out_fd = fd; |
| 160 | } else { | 161 | } else { |
| 161 | ret_fd = -1; | 162 | *out_fd = -1; |
| 162 | } | 163 | } |
| 163 | std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd); | 164 | std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd); |
| 164 | if (!sock.has_value()) { | 165 | if (!sock.has_value()) { |
| @@ -167,7 +168,7 @@ private: | |||
| 167 | } | 168 | } |
| 168 | socket = std::move(*sock); | 169 | socket = std::move(*sock); |
| 169 | backend->SetSocket(socket); | 170 | backend->SetSocket(socket); |
| 170 | return ret_fd; | 171 | return ResultSuccess; |
| 171 | } | 172 | } |
| 172 | 173 | ||
| 173 | Result SetHostNameImpl(const std::string& hostname) { | 174 | Result SetHostNameImpl(const std::string& hostname) { |
| @@ -247,34 +248,36 @@ private: | |||
| 247 | return ret; | 248 | return ret; |
| 248 | } | 249 | } |
| 249 | 250 | ||
| 250 | ResultVal<std::vector<u8>> ReadImpl(size_t size) { | 251 | Result ReadImpl(std::vector<u8>* out_data, size_t size) { |
| 251 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); | 252 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); |
| 252 | std::vector<u8> res(size); | 253 | size_t actual_size{}; |
| 253 | ResultVal<size_t> actual = backend->Read(res); | 254 | Result res = backend->Read(&actual_size, *out_data); |
| 254 | if (actual.Failed()) { | 255 | if (res != ResultSuccess) { |
| 255 | return actual.Code(); | 256 | return res; |
| 256 | } | 257 | } |
| 257 | res.resize(*actual); | 258 | out_data->resize(actual_size); |
| 258 | return res; | 259 | return res; |
| 259 | } | 260 | } |
| 260 | 261 | ||
| 261 | ResultVal<size_t> WriteImpl(std::span<const u8> data) { | 262 | Result WriteImpl(size_t* out_size, std::span<const u8> data) { |
| 262 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); | 263 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); |
| 263 | return backend->Write(data); | 264 | return backend->Write(out_size, data); |
| 264 | } | 265 | } |
| 265 | 266 | ||
| 266 | ResultVal<s32> PendingImpl() { | 267 | Result PendingImpl(s32* out_pending) { |
| 267 | LOG_WARNING(Service_SSL, "(STUBBED) called."); | 268 | LOG_WARNING(Service_SSL, "(STUBBED) called."); |
| 268 | return 0; | 269 | *out_pending = 0; |
| 270 | return ResultSuccess; | ||
| 269 | } | 271 | } |
| 270 | 272 | ||
| 271 | void SetSocketDescriptor(HLERequestContext& ctx) { | 273 | void SetSocketDescriptor(HLERequestContext& ctx) { |
| 272 | IPC::RequestParser rp{ctx}; | 274 | IPC::RequestParser rp{ctx}; |
| 273 | const s32 fd = rp.Pop<s32>(); | 275 | const s32 in_fd = rp.Pop<s32>(); |
| 274 | const ResultVal<s32> res = SetSocketDescriptorImpl(fd); | 276 | s32 out_fd{-1}; |
| 277 | const Result res = SetSocketDescriptorImpl(&out_fd, in_fd); | ||
| 275 | IPC::ResponseBuilder rb{ctx, 3}; | 278 | IPC::ResponseBuilder rb{ctx, 3}; |
| 276 | rb.Push(res.Code()); | 279 | rb.Push(res); |
| 277 | rb.Push<s32>(res.ValueOr(-1)); | 280 | rb.Push<s32>(out_fd); |
| 278 | } | 281 | } |
| 279 | 282 | ||
| 280 | void SetHostName(HLERequestContext& ctx) { | 283 | void SetHostName(HLERequestContext& ctx) { |
| @@ -313,14 +316,15 @@ private: | |||
| 313 | }; | 316 | }; |
| 314 | static_assert(sizeof(OutputParameters) == 0x8); | 317 | static_assert(sizeof(OutputParameters) == 0x8); |
| 315 | 318 | ||
| 316 | const Result res = DoHandshakeImpl(); | 319 | Result res = DoHandshakeImpl(); |
| 317 | OutputParameters out{}; | 320 | OutputParameters out{}; |
| 318 | if (res == ResultSuccess) { | 321 | if (res == ResultSuccess) { |
| 319 | auto certs = backend->GetServerCerts(); | 322 | std::vector<std::vector<u8>> certs; |
| 320 | if (certs.Succeeded()) { | 323 | res = backend->GetServerCerts(&certs); |
| 321 | const std::vector<u8> certs_buf = SerializeServerCerts(*certs); | 324 | if (res == ResultSuccess) { |
| 325 | const std::vector<u8> certs_buf = SerializeServerCerts(certs); | ||
| 322 | ctx.WriteBuffer(certs_buf); | 326 | ctx.WriteBuffer(certs_buf); |
| 323 | out.certs_count = static_cast<u32>(certs->size()); | 327 | out.certs_count = static_cast<u32>(certs.size()); |
| 324 | out.certs_size = static_cast<u32>(certs_buf.size()); | 328 | out.certs_size = static_cast<u32>(certs_buf.size()); |
| 325 | } | 329 | } |
| 326 | } | 330 | } |
| @@ -330,29 +334,32 @@ private: | |||
| 330 | } | 334 | } |
| 331 | 335 | ||
| 332 | void Read(HLERequestContext& ctx) { | 336 | void Read(HLERequestContext& ctx) { |
| 333 | const ResultVal<std::vector<u8>> res = ReadImpl(ctx.GetWriteBufferSize()); | 337 | std::vector<u8> output_bytes; |
| 338 | const Result res = ReadImpl(&output_bytes, ctx.GetWriteBufferSize()); | ||
| 334 | IPC::ResponseBuilder rb{ctx, 3}; | 339 | IPC::ResponseBuilder rb{ctx, 3}; |
| 335 | rb.Push(res.Code()); | 340 | rb.Push(res); |
| 336 | if (res.Succeeded()) { | 341 | if (res == ResultSuccess) { |
| 337 | rb.Push(static_cast<u32>(res->size())); | 342 | rb.Push(static_cast<u32>(output_bytes.size())); |
| 338 | ctx.WriteBuffer(*res); | 343 | ctx.WriteBuffer(output_bytes); |
| 339 | } else { | 344 | } else { |
| 340 | rb.Push(static_cast<u32>(0)); | 345 | rb.Push(static_cast<u32>(0)); |
| 341 | } | 346 | } |
| 342 | } | 347 | } |
| 343 | 348 | ||
| 344 | void Write(HLERequestContext& ctx) { | 349 | void Write(HLERequestContext& ctx) { |
| 345 | const ResultVal<size_t> res = WriteImpl(ctx.ReadBuffer()); | 350 | size_t write_size{0}; |
| 351 | const Result res = WriteImpl(&write_size, ctx.ReadBuffer()); | ||
| 346 | IPC::ResponseBuilder rb{ctx, 3}; | 352 | IPC::ResponseBuilder rb{ctx, 3}; |
| 347 | rb.Push(res.Code()); | 353 | rb.Push(res); |
| 348 | rb.Push(static_cast<u32>(res.ValueOr(0))); | 354 | rb.Push(static_cast<u32>(write_size)); |
| 349 | } | 355 | } |
| 350 | 356 | ||
| 351 | void Pending(HLERequestContext& ctx) { | 357 | void Pending(HLERequestContext& ctx) { |
| 352 | const ResultVal<s32> res = PendingImpl(); | 358 | s32 pending_size{0}; |
| 359 | const Result res = PendingImpl(&pending_size); | ||
| 353 | IPC::ResponseBuilder rb{ctx, 3}; | 360 | IPC::ResponseBuilder rb{ctx, 3}; |
| 354 | rb.Push(res.Code()); | 361 | rb.Push(res); |
| 355 | rb.Push<s32>(res.ValueOr(0)); | 362 | rb.Push<s32>(pending_size); |
| 356 | } | 363 | } |
| 357 | 364 | ||
| 358 | void SetSessionCacheMode(HLERequestContext& ctx) { | 365 | void SetSessionCacheMode(HLERequestContext& ctx) { |
| @@ -438,13 +445,14 @@ private: | |||
| 438 | void CreateConnection(HLERequestContext& ctx) { | 445 | void CreateConnection(HLERequestContext& ctx) { |
| 439 | LOG_WARNING(Service_SSL, "called"); | 446 | LOG_WARNING(Service_SSL, "called"); |
| 440 | 447 | ||
| 441 | auto backend_res = CreateSSLConnectionBackend(); | 448 | std::unique_ptr<SSLConnectionBackend> backend; |
| 449 | const Result res = CreateSSLConnectionBackend(&backend); | ||
| 442 | 450 | ||
| 443 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 451 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 444 | rb.Push(backend_res.Code()); | 452 | rb.Push(res); |
| 445 | if (backend_res.Succeeded()) { | 453 | if (res == ResultSuccess) { |
| 446 | rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data, | 454 | rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data, |
| 447 | std::move(*backend_res)); | 455 | std::move(backend)); |
| 448 | } | 456 | } |
| 449 | } | 457 | } |
| 450 | 458 | ||
diff --git a/src/core/hle/service/ssl/ssl_backend.h b/src/core/hle/service/ssl/ssl_backend.h index 409f4367c..a2ec8e694 100644 --- a/src/core/hle/service/ssl/ssl_backend.h +++ b/src/core/hle/service/ssl/ssl_backend.h | |||
| @@ -35,11 +35,11 @@ public: | |||
| 35 | virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0; | 35 | virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0; |
| 36 | virtual Result SetHostName(const std::string& hostname) = 0; | 36 | virtual Result SetHostName(const std::string& hostname) = 0; |
| 37 | virtual Result DoHandshake() = 0; | 37 | virtual Result DoHandshake() = 0; |
| 38 | virtual ResultVal<size_t> Read(std::span<u8> data) = 0; | 38 | virtual Result Read(size_t* out_size, std::span<u8> data) = 0; |
| 39 | virtual ResultVal<size_t> Write(std::span<const u8> data) = 0; | 39 | virtual Result Write(size_t* out_size, std::span<const u8> data) = 0; |
| 40 | virtual ResultVal<std::vector<std::vector<u8>>> GetServerCerts() = 0; | 40 | virtual Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) = 0; |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend(); | 43 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend); |
| 44 | 44 | ||
| 45 | } // namespace Service::SSL | 45 | } // namespace Service::SSL |
diff --git a/src/core/hle/service/ssl/ssl_backend_none.cpp b/src/core/hle/service/ssl/ssl_backend_none.cpp index 2f4f23c42..a7fafd0a3 100644 --- a/src/core/hle/service/ssl/ssl_backend_none.cpp +++ b/src/core/hle/service/ssl/ssl_backend_none.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | namespace Service::SSL { | 8 | namespace Service::SSL { |
| 9 | 9 | ||
| 10 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 10 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 11 | LOG_ERROR(Service_SSL, | 11 | LOG_ERROR(Service_SSL, |
| 12 | "Can't create SSL connection because no SSL backend is available on this platform"); | 12 | "Can't create SSL connection because no SSL backend is available on this platform"); |
| 13 | return ResultInternalError; | 13 | return ResultInternalError; |
diff --git a/src/core/hle/service/ssl/ssl_backend_openssl.cpp b/src/core/hle/service/ssl/ssl_backend_openssl.cpp index 6ca869dbf..b2dd37cd4 100644 --- a/src/core/hle/service/ssl/ssl_backend_openssl.cpp +++ b/src/core/hle/service/ssl/ssl_backend_openssl.cpp | |||
| @@ -105,31 +105,30 @@ public: | |||
| 105 | return ResultInternalError; | 105 | return ResultInternalError; |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | return HandleReturn("SSL_do_handshake", 0, ret).Code(); | 108 | return HandleReturn("SSL_do_handshake", 0, ret); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | ResultVal<size_t> Read(std::span<u8> data) override { | 111 | Result Read(size_t* out_size, std::span<u8> data) override { |
| 112 | size_t actual; | 112 | const int ret = SSL_read_ex(ssl, data.data(), data.size(), out_size); |
| 113 | const int ret = SSL_read_ex(ssl, data.data(), data.size(), &actual); | 113 | return HandleReturn("SSL_read_ex", out_size, ret); |
| 114 | return HandleReturn("SSL_read_ex", actual, ret); | ||
| 115 | } | 114 | } |
| 116 | 115 | ||
| 117 | ResultVal<size_t> Write(std::span<const u8> data) override { | 116 | Result Write(size_t* out_size, std::span<const u8> data) override { |
| 118 | size_t actual; | 117 | const int ret = SSL_write_ex(ssl, data.data(), data.size(), out_size); |
| 119 | const int ret = SSL_write_ex(ssl, data.data(), data.size(), &actual); | 118 | return HandleReturn("SSL_write_ex", out_size, ret); |
| 120 | return HandleReturn("SSL_write_ex", actual, ret); | ||
| 121 | } | 119 | } |
| 122 | 120 | ||
| 123 | ResultVal<size_t> HandleReturn(const char* what, size_t actual, int ret) { | 121 | Result HandleReturn(const char* what, size_t* actual, int ret) { |
| 124 | const int ssl_err = SSL_get_error(ssl, ret); | 122 | const int ssl_err = SSL_get_error(ssl, ret); |
| 125 | CheckOpenSSLErrors(); | 123 | CheckOpenSSLErrors(); |
| 126 | switch (ssl_err) { | 124 | switch (ssl_err) { |
| 127 | case SSL_ERROR_NONE: | 125 | case SSL_ERROR_NONE: |
| 128 | return actual; | 126 | return ResultSuccess; |
| 129 | case SSL_ERROR_ZERO_RETURN: | 127 | case SSL_ERROR_ZERO_RETURN: |
| 130 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what); | 128 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what); |
| 131 | // DoHandshake special-cases this, but for Read and Write: | 129 | // DoHandshake special-cases this, but for Read and Write: |
| 132 | return size_t(0); | 130 | *actual = 0; |
| 131 | return ResultSuccess; | ||
| 133 | case SSL_ERROR_WANT_READ: | 132 | case SSL_ERROR_WANT_READ: |
| 134 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what); | 133 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what); |
| 135 | return ResultWouldBlock; | 134 | return ResultWouldBlock; |
| @@ -139,20 +138,20 @@ public: | |||
| 139 | default: | 138 | default: |
| 140 | if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) { | 139 | if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) { |
| 141 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what); | 140 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what); |
| 142 | return size_t(0); | 141 | *actual = 0; |
| 142 | return ResultSuccess; | ||
| 143 | } | 143 | } |
| 144 | LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err); | 144 | LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err); |
| 145 | return ResultInternalError; | 145 | return ResultInternalError; |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override { | 149 | Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { |
| 150 | STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); | 150 | STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); |
| 151 | if (!chain) { | 151 | if (!chain) { |
| 152 | LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr"); | 152 | LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr"); |
| 153 | return ResultInternalError; | 153 | return ResultInternalError; |
| 154 | } | 154 | } |
| 155 | std::vector<std::vector<u8>> ret; | ||
| 156 | int count = sk_X509_num(chain); | 155 | int count = sk_X509_num(chain); |
| 157 | ASSERT(count >= 0); | 156 | ASSERT(count >= 0); |
| 158 | for (int i = 0; i < count; i++) { | 157 | for (int i = 0; i < count; i++) { |
| @@ -161,10 +160,10 @@ public: | |||
| 161 | unsigned char* buf = nullptr; | 160 | unsigned char* buf = nullptr; |
| 162 | int len = i2d_X509(x509, &buf); | 161 | int len = i2d_X509(x509, &buf); |
| 163 | ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; }); | 162 | ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; }); |
| 164 | ret.emplace_back(buf, buf + len); | 163 | out_certs->emplace_back(buf, buf + len); |
| 165 | OPENSSL_free(buf); | 164 | OPENSSL_free(buf); |
| 166 | } | 165 | } |
| 167 | return ret; | 166 | return ResultSuccess; |
| 168 | } | 167 | } |
| 169 | 168 | ||
| 170 | ~SSLConnectionBackendOpenSSL() { | 169 | ~SSLConnectionBackendOpenSSL() { |
| @@ -253,13 +252,13 @@ public: | |||
| 253 | std::shared_ptr<Network::SocketBase> socket; | 252 | std::shared_ptr<Network::SocketBase> socket; |
| 254 | }; | 253 | }; |
| 255 | 254 | ||
| 256 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 255 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 257 | auto conn = std::make_unique<SSLConnectionBackendOpenSSL>(); | 256 | auto conn = std::make_unique<SSLConnectionBackendOpenSSL>(); |
| 258 | const Result res = conn->Init(); | 257 | |
| 259 | if (res.IsFailure()) { | 258 | R_TRY(conn->Init()); |
| 260 | return res; | 259 | |
| 261 | } | 260 | *out_backend = std::move(conn); |
| 262 | return conn; | 261 | return ResultSuccess; |
| 263 | } | 262 | } |
| 264 | 263 | ||
| 265 | namespace { | 264 | namespace { |
diff --git a/src/core/hle/service/ssl/ssl_backend_schannel.cpp b/src/core/hle/service/ssl/ssl_backend_schannel.cpp index d8074339a..bda12b761 100644 --- a/src/core/hle/service/ssl/ssl_backend_schannel.cpp +++ b/src/core/hle/service/ssl/ssl_backend_schannel.cpp | |||
| @@ -299,21 +299,22 @@ public: | |||
| 299 | return ResultSuccess; | 299 | return ResultSuccess; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | ResultVal<size_t> Read(std::span<u8> data) override { | 302 | Result Read(size_t* out_size, std::span<u8> data) override { |
| 303 | *out_size = 0; | ||
| 303 | if (handshake_state != HandshakeState::Connected) { | 304 | if (handshake_state != HandshakeState::Connected) { |
| 304 | LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake"); | 305 | LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake"); |
| 305 | return ResultInternalError; | 306 | return ResultInternalError; |
| 306 | } | 307 | } |
| 307 | if (data.size() == 0 || got_read_eof) { | 308 | if (data.size() == 0 || got_read_eof) { |
| 308 | return size_t(0); | 309 | return ResultSuccess; |
| 309 | } | 310 | } |
| 310 | while (1) { | 311 | while (1) { |
| 311 | if (!cleartext_read_buf.empty()) { | 312 | if (!cleartext_read_buf.empty()) { |
| 312 | const size_t read_size = std::min(cleartext_read_buf.size(), data.size()); | 313 | *out_size = std::min(cleartext_read_buf.size(), data.size()); |
| 313 | std::memcpy(data.data(), cleartext_read_buf.data(), read_size); | 314 | std::memcpy(data.data(), cleartext_read_buf.data(), *out_size); |
| 314 | cleartext_read_buf.erase(cleartext_read_buf.begin(), | 315 | cleartext_read_buf.erase(cleartext_read_buf.begin(), |
| 315 | cleartext_read_buf.begin() + read_size); | 316 | cleartext_read_buf.begin() + *out_size); |
| 316 | return read_size; | 317 | return ResultSuccess; |
| 317 | } | 318 | } |
| 318 | if (!ciphertext_read_buf.empty()) { | 319 | if (!ciphertext_read_buf.empty()) { |
| 319 | SecBuffer empty{ | 320 | SecBuffer empty{ |
| @@ -366,7 +367,8 @@ public: | |||
| 366 | case SEC_I_CONTEXT_EXPIRED: | 367 | case SEC_I_CONTEXT_EXPIRED: |
| 367 | // Server hung up by sending close_notify. | 368 | // Server hung up by sending close_notify. |
| 368 | got_read_eof = true; | 369 | got_read_eof = true; |
| 369 | return size_t(0); | 370 | *out_size = 0; |
| 371 | return ResultSuccess; | ||
| 370 | default: | 372 | default: |
| 371 | LOG_ERROR(Service_SSL, "DecryptMessage failed: {}", | 373 | LOG_ERROR(Service_SSL, "DecryptMessage failed: {}", |
| 372 | Common::NativeErrorToString(ret)); | 374 | Common::NativeErrorToString(ret)); |
| @@ -379,18 +381,21 @@ public: | |||
| 379 | } | 381 | } |
| 380 | if (ciphertext_read_buf.empty()) { | 382 | if (ciphertext_read_buf.empty()) { |
| 381 | got_read_eof = true; | 383 | got_read_eof = true; |
| 382 | return size_t(0); | 384 | *out_size = 0; |
| 385 | return ResultSuccess; | ||
| 383 | } | 386 | } |
| 384 | } | 387 | } |
| 385 | } | 388 | } |
| 386 | 389 | ||
| 387 | ResultVal<size_t> Write(std::span<const u8> data) override { | 390 | Result Write(size_t* out_size, std::span<const u8> data) override { |
| 391 | *out_size = 0; | ||
| 392 | |||
| 388 | if (handshake_state != HandshakeState::Connected) { | 393 | if (handshake_state != HandshakeState::Connected) { |
| 389 | LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake"); | 394 | LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake"); |
| 390 | return ResultInternalError; | 395 | return ResultInternalError; |
| 391 | } | 396 | } |
| 392 | if (data.size() == 0) { | 397 | if (data.size() == 0) { |
| 393 | return size_t(0); | 398 | return ResultSuccess; |
| 394 | } | 399 | } |
| 395 | data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage)); | 400 | data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage)); |
| 396 | if (!cleartext_write_buf.empty()) { | 401 | if (!cleartext_write_buf.empty()) { |
| @@ -402,7 +407,7 @@ public: | |||
| 402 | LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer"); | 407 | LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer"); |
| 403 | return ResultInternalError; | 408 | return ResultInternalError; |
| 404 | } | 409 | } |
| 405 | return WriteAlreadyEncryptedData(); | 410 | return WriteAlreadyEncryptedData(out_size); |
| 406 | } else { | 411 | } else { |
| 407 | cleartext_write_buf.assign(data.begin(), data.end()); | 412 | cleartext_write_buf.assign(data.begin(), data.end()); |
| 408 | } | 413 | } |
| @@ -448,21 +453,21 @@ public: | |||
| 448 | tmp_data_buf.end()); | 453 | tmp_data_buf.end()); |
| 449 | ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(), | 454 | ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(), |
| 450 | trailer_buf.end()); | 455 | trailer_buf.end()); |
| 451 | return WriteAlreadyEncryptedData(); | 456 | return WriteAlreadyEncryptedData(out_size); |
| 452 | } | 457 | } |
| 453 | 458 | ||
| 454 | ResultVal<size_t> WriteAlreadyEncryptedData() { | 459 | Result WriteAlreadyEncryptedData(size_t* out_size) { |
| 455 | const Result r = FlushCiphertextWriteBuf(); | 460 | const Result r = FlushCiphertextWriteBuf(); |
| 456 | if (r != ResultSuccess) { | 461 | if (r != ResultSuccess) { |
| 457 | return r; | 462 | return r; |
| 458 | } | 463 | } |
| 459 | // write buf is empty | 464 | // write buf is empty |
| 460 | const size_t cleartext_bytes_written = cleartext_write_buf.size(); | 465 | *out_size = cleartext_write_buf.size(); |
| 461 | cleartext_write_buf.clear(); | 466 | cleartext_write_buf.clear(); |
| 462 | return cleartext_bytes_written; | 467 | return ResultSuccess; |
| 463 | } | 468 | } |
| 464 | 469 | ||
| 465 | ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override { | 470 | Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { |
| 466 | PCCERT_CONTEXT returned_cert = nullptr; | 471 | PCCERT_CONTEXT returned_cert = nullptr; |
| 467 | const SECURITY_STATUS ret = | 472 | const SECURITY_STATUS ret = |
| 468 | QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert); | 473 | QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert); |
| @@ -473,16 +478,15 @@ public: | |||
| 473 | return ResultInternalError; | 478 | return ResultInternalError; |
| 474 | } | 479 | } |
| 475 | PCCERT_CONTEXT some_cert = nullptr; | 480 | PCCERT_CONTEXT some_cert = nullptr; |
| 476 | std::vector<std::vector<u8>> certs; | ||
| 477 | while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) { | 481 | while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) { |
| 478 | certs.emplace_back(static_cast<u8*>(some_cert->pbCertEncoded), | 482 | out_certs->emplace_back(static_cast<u8*>(some_cert->pbCertEncoded), |
| 479 | static_cast<u8*>(some_cert->pbCertEncoded) + | 483 | static_cast<u8*>(some_cert->pbCertEncoded) + |
| 480 | some_cert->cbCertEncoded); | 484 | some_cert->cbCertEncoded); |
| 481 | } | 485 | } |
| 482 | std::reverse(certs.begin(), | 486 | std::reverse(out_certs->begin(), |
| 483 | certs.end()); // Windows returns certs in reverse order from what we want | 487 | out_certs->end()); // Windows returns certs in reverse order from what we want |
| 484 | CertFreeCertificateContext(returned_cert); | 488 | CertFreeCertificateContext(returned_cert); |
| 485 | return certs; | 489 | return ResultSuccess; |
| 486 | } | 490 | } |
| 487 | 491 | ||
| 488 | ~SSLConnectionBackendSchannel() { | 492 | ~SSLConnectionBackendSchannel() { |
| @@ -532,13 +536,13 @@ public: | |||
| 532 | size_t read_buf_fill_size = 0; | 536 | size_t read_buf_fill_size = 0; |
| 533 | }; | 537 | }; |
| 534 | 538 | ||
| 535 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 539 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 536 | auto conn = std::make_unique<SSLConnectionBackendSchannel>(); | 540 | auto conn = std::make_unique<SSLConnectionBackendSchannel>(); |
| 537 | const Result res = conn->Init(); | 541 | |
| 538 | if (res.IsFailure()) { | 542 | R_TRY(conn->Init()); |
| 539 | return res; | 543 | |
| 540 | } | 544 | *out_backend = std::move(conn); |
| 541 | return conn; | 545 | return ResultSuccess; |
| 542 | } | 546 | } |
| 543 | 547 | ||
| 544 | } // namespace Service::SSL | 548 | } // namespace Service::SSL |
diff --git a/src/core/hle/service/ssl/ssl_backend_securetransport.cpp b/src/core/hle/service/ssl/ssl_backend_securetransport.cpp index b3083cbad..370678f48 100644 --- a/src/core/hle/service/ssl/ssl_backend_securetransport.cpp +++ b/src/core/hle/service/ssl/ssl_backend_securetransport.cpp | |||
| @@ -103,24 +103,20 @@ public: | |||
| 103 | return HandleReturn("SSLHandshake", 0, status).Code(); | 103 | return HandleReturn("SSLHandshake", 0, status).Code(); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | ResultVal<size_t> Read(std::span<u8> data) override { | 106 | Result Read(size_t* out_size, std::span<u8> data) override { |
| 107 | size_t actual; | 107 | OSStatus status = SSLRead(context, data.data(), data.size(), out_size); |
| 108 | OSStatus status = SSLRead(context, data.data(), data.size(), &actual); | 108 | return HandleReturn("SSLRead", out_size, status); |
| 109 | ; | ||
| 110 | return HandleReturn("SSLRead", actual, status); | ||
| 111 | } | 109 | } |
| 112 | 110 | ||
| 113 | ResultVal<size_t> Write(std::span<const u8> data) override { | 111 | Result Write(size_t* out_size, std::span<const u8> data) override { |
| 114 | size_t actual; | 112 | OSStatus status = SSLWrite(context, data.data(), data.size(), out_size); |
| 115 | OSStatus status = SSLWrite(context, data.data(), data.size(), &actual); | 113 | return HandleReturn("SSLWrite", out_size, status); |
| 116 | ; | ||
| 117 | return HandleReturn("SSLWrite", actual, status); | ||
| 118 | } | 114 | } |
| 119 | 115 | ||
| 120 | ResultVal<size_t> HandleReturn(const char* what, size_t actual, OSStatus status) { | 116 | Result HandleReturn(const char* what, size_t* actual, OSStatus status) { |
| 121 | switch (status) { | 117 | switch (status) { |
| 122 | case 0: | 118 | case 0: |
| 123 | return actual; | 119 | return ResultSuccess; |
| 124 | case errSSLWouldBlock: | 120 | case errSSLWouldBlock: |
| 125 | return ResultWouldBlock; | 121 | return ResultWouldBlock; |
| 126 | default: { | 122 | default: { |
| @@ -136,22 +132,21 @@ public: | |||
| 136 | } | 132 | } |
| 137 | } | 133 | } |
| 138 | 134 | ||
| 139 | ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override { | 135 | Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { |
| 140 | CFReleaser<SecTrustRef> trust; | 136 | CFReleaser<SecTrustRef> trust; |
| 141 | OSStatus status = SSLCopyPeerTrust(context, &trust.ptr); | 137 | OSStatus status = SSLCopyPeerTrust(context, &trust.ptr); |
| 142 | if (status) { | 138 | if (status) { |
| 143 | LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status)); | 139 | LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status)); |
| 144 | return ResultInternalError; | 140 | return ResultInternalError; |
| 145 | } | 141 | } |
| 146 | std::vector<std::vector<u8>> ret; | ||
| 147 | for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) { | 142 | for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) { |
| 148 | SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i); | 143 | SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i); |
| 149 | CFReleaser<CFDataRef> data(SecCertificateCopyData(cert)); | 144 | CFReleaser<CFDataRef> data(SecCertificateCopyData(cert)); |
| 150 | ASSERT_OR_EXECUTE(data, { return ResultInternalError; }); | 145 | ASSERT_OR_EXECUTE(data, { return ResultInternalError; }); |
| 151 | const u8* ptr = CFDataGetBytePtr(data); | 146 | const u8* ptr = CFDataGetBytePtr(data); |
| 152 | ret.emplace_back(ptr, ptr + CFDataGetLength(data)); | 147 | out_certs->emplace_back(ptr, ptr + CFDataGetLength(data)); |
| 153 | } | 148 | } |
| 154 | return ret; | 149 | return ResultSuccess; |
| 155 | } | 150 | } |
| 156 | 151 | ||
| 157 | static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) { | 152 | static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) { |
| @@ -210,13 +205,13 @@ private: | |||
| 210 | std::shared_ptr<Network::SocketBase> socket; | 205 | std::shared_ptr<Network::SocketBase> socket; |
| 211 | }; | 206 | }; |
| 212 | 207 | ||
| 213 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 208 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 214 | auto conn = std::make_unique<SSLConnectionBackendSecureTransport>(); | 209 | auto conn = std::make_unique<SSLConnectionBackendSecureTransport>(); |
| 215 | const Result res = conn->Init(); | 210 | |
| 216 | if (res.IsFailure()) { | 211 | R_TRY(conn->Init()); |
| 217 | return res; | 212 | |
| 218 | } | 213 | *out_backend = std::move(conn); |
| 219 | return conn; | 214 | return ResultSuccess; |
| 220 | } | 215 | } |
| 221 | 216 | ||
| 222 | } // namespace Service::SSL | 217 | } // namespace Service::SSL |
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 69af2868a..f0b5eff8a 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -58,14 +58,15 @@ const Layer& Display::GetLayer(std::size_t index) const { | |||
| 58 | return *layers.at(index); | 58 | return *layers.at(index); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | ResultVal<Kernel::KReadableEvent*> Display::GetVSyncEvent() { | 61 | Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) { |
| 62 | if (got_vsync_event) { | 62 | if (got_vsync_event) { |
| 63 | return ResultPermissionDenied; | 63 | return ResultPermissionDenied; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | got_vsync_event = true; | 66 | got_vsync_event = true; |
| 67 | 67 | ||
| 68 | return GetVSyncEventUnchecked(); | 68 | *out_vsync_event = GetVSyncEventUnchecked(); |
| 69 | return ResultSuccess; | ||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { | 72 | Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { |
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 3f31d1f32..101cbce20 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -85,7 +85,7 @@ public: | |||
| 85 | * @returns The internal Vsync event if it has not yet been retrieved, | 85 | * @returns The internal Vsync event if it has not yet been retrieved, |
| 86 | * VI::ResultPermissionDenied otherwise. | 86 | * VI::ResultPermissionDenied otherwise. |
| 87 | */ | 87 | */ |
| 88 | [[nodiscard]] ResultVal<Kernel::KReadableEvent*> GetVSyncEvent(); | 88 | [[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event); |
| 89 | 89 | ||
| 90 | /// Gets the internal vsync event. | 90 | /// Gets the internal vsync event. |
| 91 | Kernel::KReadableEvent* GetVSyncEventUnchecked(); | 91 | Kernel::KReadableEvent* GetVSyncEventUnchecked(); |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 1b193f00c..6bb02393c 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -683,9 +683,9 @@ private: | |||
| 683 | 683 | ||
| 684 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | 684 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); |
| 685 | 685 | ||
| 686 | const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); | 686 | Kernel::KReadableEvent* vsync_event{}; |
| 687 | if (vsync_event.Failed()) { | 687 | const auto result = nv_flinger.FindVsyncEvent(&vsync_event, display_id); |
| 688 | const auto result = vsync_event.Code(); | 688 | if (result != ResultSuccess) { |
| 689 | if (result == ResultNotFound) { | 689 | if (result == ResultNotFound) { |
| 690 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | 690 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); |
| 691 | } | 691 | } |
| @@ -697,7 +697,7 @@ private: | |||
| 697 | 697 | ||
| 698 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 698 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 699 | rb.Push(ResultSuccess); | 699 | rb.Push(ResultSuccess); |
| 700 | rb.PushCopyObjects(*vsync_event); | 700 | rb.PushCopyObjects(vsync_event); |
| 701 | } | 701 | } |
| 702 | 702 | ||
| 703 | void ConvertScalingMode(HLERequestContext& ctx) { | 703 | void ConvertScalingMode(HLERequestContext& ctx) { |
| @@ -705,15 +705,16 @@ private: | |||
| 705 | const auto mode = rp.PopEnum<NintendoScaleMode>(); | 705 | const auto mode = rp.PopEnum<NintendoScaleMode>(); |
| 706 | LOG_DEBUG(Service_VI, "called mode={}", mode); | 706 | LOG_DEBUG(Service_VI, "called mode={}", mode); |
| 707 | 707 | ||
| 708 | const auto converted_mode = ConvertScalingModeImpl(mode); | 708 | ConvertedScaleMode converted_mode{}; |
| 709 | const auto result = ConvertScalingModeImpl(&converted_mode, mode); | ||
| 709 | 710 | ||
| 710 | if (converted_mode.Succeeded()) { | 711 | if (result == ResultSuccess) { |
| 711 | IPC::ResponseBuilder rb{ctx, 4}; | 712 | IPC::ResponseBuilder rb{ctx, 4}; |
| 712 | rb.Push(ResultSuccess); | 713 | rb.Push(ResultSuccess); |
| 713 | rb.PushEnum(*converted_mode); | 714 | rb.PushEnum(converted_mode); |
| 714 | } else { | 715 | } else { |
| 715 | IPC::ResponseBuilder rb{ctx, 2}; | 716 | IPC::ResponseBuilder rb{ctx, 2}; |
| 716 | rb.Push(converted_mode.Code()); | 717 | rb.Push(result); |
| 717 | } | 718 | } |
| 718 | } | 719 | } |
| 719 | 720 | ||
| @@ -760,18 +761,24 @@ private: | |||
| 760 | rb.Push(alignment); | 761 | rb.Push(alignment); |
| 761 | } | 762 | } |
| 762 | 763 | ||
| 763 | static ResultVal<ConvertedScaleMode> ConvertScalingModeImpl(NintendoScaleMode mode) { | 764 | static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, |
| 765 | NintendoScaleMode mode) { | ||
| 764 | switch (mode) { | 766 | switch (mode) { |
| 765 | case NintendoScaleMode::None: | 767 | case NintendoScaleMode::None: |
| 766 | return ConvertedScaleMode::None; | 768 | *out_scaling_mode = ConvertedScaleMode::None; |
| 769 | return ResultSuccess; | ||
| 767 | case NintendoScaleMode::Freeze: | 770 | case NintendoScaleMode::Freeze: |
| 768 | return ConvertedScaleMode::Freeze; | 771 | *out_scaling_mode = ConvertedScaleMode::Freeze; |
| 772 | return ResultSuccess; | ||
| 769 | case NintendoScaleMode::ScaleToWindow: | 773 | case NintendoScaleMode::ScaleToWindow: |
| 770 | return ConvertedScaleMode::ScaleToWindow; | 774 | *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; |
| 775 | return ResultSuccess; | ||
| 771 | case NintendoScaleMode::ScaleAndCrop: | 776 | case NintendoScaleMode::ScaleAndCrop: |
| 772 | return ConvertedScaleMode::ScaleAndCrop; | 777 | *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; |
| 778 | return ResultSuccess; | ||
| 773 | case NintendoScaleMode::PreserveAspectRatio: | 779 | case NintendoScaleMode::PreserveAspectRatio: |
| 774 | return ConvertedScaleMode::PreserveAspectRatio; | 780 | *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; |
| 781 | return ResultSuccess; | ||
| 775 | default: | 782 | default: |
| 776 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | 783 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); |
| 777 | return ResultOperationFailed; | 784 | return ResultOperationFailed; |