mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
lr: add support for location resolver disable commands
This commit is contained in:
parent
05de5538d6
commit
e1aff401ba
12 changed files with 110 additions and 10 deletions
|
@ -43,7 +43,8 @@
|
|||
AMS_SF_METHOD_INFO(C, H, 17, Result, RedirectProgramPathForDebug, (const lr::Path &path, ncm::ProgramId id), (path, id), hos::Version_7_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 18, Result, RedirectApplicationProgramPathForDebugDeprecated, (const lr::Path &path, ncm::ProgramId id), (path, id), hos::Version_7_0_0, hos::Version_8_1_1) \
|
||||
AMS_SF_METHOD_INFO(C, H, 18, Result, RedirectApplicationProgramPathForDebug, (const lr::Path &path, ncm::ProgramId id, ncm::ProgramId owner_id), (path, id, owner_id), hos::Version_9_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 19, Result, EraseProgramRedirectionForDebug, (ncm::ProgramId id), (id), hos::Version_7_0_0)
|
||||
AMS_SF_METHOD_INFO(C, H, 19, Result, EraseProgramRedirectionForDebug, (ncm::ProgramId id), (id), hos::Version_7_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 20, Result, Disable, (), (), hos::Version_15_0_0)
|
||||
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(ams::lr, ILocationResolver, AMS_LR_I_LOCATION_RESOLVER_INTERFACE_INFO, 0xB36C8B0E)
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
#include <stratosphere/lr/lr_i_add_on_content_location_resolver.hpp>
|
||||
#include <stratosphere/lr/lr_i_registered_location_resolver.hpp>
|
||||
|
||||
#define AMS_LR_I_LOCATION_RESOLVER_MANAGER_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenLocationResolver, (sf::Out<ams::sf::SharedPointer<lr::ILocationResolver>> out, ncm::StorageId storage_id), (out, storage_id)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenRegisteredLocationResolver, (sf::Out<ams::sf::SharedPointer<lr::IRegisteredLocationResolver>> out), (out)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, RefreshLocationResolver, (ncm::StorageId storage_id), (storage_id)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, OpenAddOnContentLocationResolver, (sf::Out<ams::sf::SharedPointer<lr::IAddOnContentLocationResolver>> out), (out), hos::Version_2_0_0)
|
||||
#define AMS_LR_I_LOCATION_RESOLVER_MANAGER_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, OpenLocationResolver, (sf::Out<ams::sf::SharedPointer<lr::ILocationResolver>> out, ncm::StorageId storage_id), (out, storage_id)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 1, Result, OpenRegisteredLocationResolver, (sf::Out<ams::sf::SharedPointer<lr::IRegisteredLocationResolver>> out), (out)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, RefreshLocationResolver, (ncm::StorageId storage_id), (storage_id)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, OpenAddOnContentLocationResolver, (sf::Out<ams::sf::SharedPointer<lr::IAddOnContentLocationResolver>> out), (out), hos::Version_2_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 4, Result, SetEnabled, (const ams::sf::InMapAliasArray<ncm::StorageId> &storages), (storages), hos::Version_15_0_0)
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(ams::lr, ILocationResolverManager, AMS_LR_I_LOCATION_RESOLVER_MANAGER_INTERFACE_INFO, 0xB2950191)
|
||||
|
|
|
@ -170,6 +170,11 @@ namespace ams::lr {
|
|||
AMS_ASSERT(m_interface != nullptr);
|
||||
R_RETURN(m_interface->EraseProgramRedirectionForDebug(id));
|
||||
}
|
||||
|
||||
Result Disable() {
|
||||
AMS_ASSERT(m_interface != nullptr);
|
||||
R_RETURN(m_interface->Disable());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -22,9 +22,13 @@
|
|||
namespace ams::lr {
|
||||
|
||||
class LocationResolverManagerImpl {
|
||||
private:
|
||||
static constexpr size_t ResolverCountMax = 5;
|
||||
private:
|
||||
/* Resolver storage. */
|
||||
ncm::BoundedMap<ncm::StorageId, sf::SharedPointer<ILocationResolver>, 5> m_location_resolvers{};
|
||||
ncm::BoundedMap<ncm::StorageId, sf::SharedPointer<ILocationResolver>, ResolverCountMax> m_location_resolvers{};
|
||||
ncm::BoundedMap<ncm::StorageId, bool, ResolverCountMax> m_location_resolvers_enabled{};
|
||||
bool m_default_enabled = true;
|
||||
sf::SharedPointer<IRegisteredLocationResolver> m_registered_location_resolver = nullptr;
|
||||
sf::SharedPointer<IAddOnContentLocationResolver> m_add_on_content_location_resolver = nullptr;
|
||||
|
||||
|
@ -35,6 +39,7 @@ namespace ams::lr {
|
|||
Result OpenRegisteredLocationResolver(sf::Out<sf::SharedPointer<IRegisteredLocationResolver>> out);
|
||||
Result RefreshLocationResolver(ncm::StorageId storage_id);
|
||||
Result OpenAddOnContentLocationResolver(sf::Out<sf::SharedPointer<IAddOnContentLocationResolver>> out);
|
||||
Result SetEnabled(const sf::InMapAliasArray<ncm::StorageId> &storages);
|
||||
};
|
||||
static_assert(IsILocationResolverManager<LocationResolverManagerImpl>);
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ namespace ams::lr {
|
|||
/* Use a redirection if present. */
|
||||
R_SUCCEED_IF(m_program_redirector.FindRedirection(out.GetPointer(), id));
|
||||
|
||||
/* If we're not enabled, we can't resolve a program. */
|
||||
R_UNLESS(m_enabled, lr::ResultProgramNotFound())
|
||||
|
||||
/* Find the latest program content for the program id. */
|
||||
ncm::ContentId program_content_id;
|
||||
R_TRY_CATCH(m_content_meta_database.GetLatestProgram(std::addressof(program_content_id), id)) {
|
||||
|
@ -60,6 +63,9 @@ namespace ams::lr {
|
|||
}
|
||||
|
||||
Result ContentLocationResolverImpl::ResolveDataPath(sf::Out<Path> out, ncm::DataId id) {
|
||||
/* If we're not enabled, we can't resolve data. */
|
||||
R_UNLESS(m_enabled, lr::ResultDataNotFound())
|
||||
|
||||
/* Find the latest data content for the program id. */
|
||||
ncm::ContentId data_content_id;
|
||||
R_TRY(m_content_meta_database.GetLatestData(std::addressof(data_content_id), id));
|
||||
|
@ -166,9 +172,12 @@ namespace ams::lr {
|
|||
/* Use a redirection if present. */
|
||||
R_SUCCEED_IF(m_debug_program_redirector.FindRedirection(out.GetPointer(), id));
|
||||
|
||||
/* If we're not enabled, we can't resolve a program. */
|
||||
R_UNLESS(m_enabled, lr::ResultDebugProgramNotFound())
|
||||
|
||||
/* Otherwise find the path for the program id. */
|
||||
R_TRY_CATCH(this->ResolveProgramPath(out.GetPointer(), id)) {
|
||||
R_CONVERT(ResultProgramNotFound, lr::ResultDebugProgramNotFound())
|
||||
R_CONVERT(lr::ResultProgramNotFound, lr::ResultDebugProgramNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
R_SUCCEED();
|
||||
|
@ -194,4 +203,9 @@ namespace ams::lr {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ContentLocationResolverImpl::Disable() {
|
||||
m_enabled = false;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,12 +22,13 @@ namespace ams::lr {
|
|||
class ContentLocationResolverImpl : public LocationResolverImplBase {
|
||||
private:
|
||||
ncm::StorageId m_storage_id;
|
||||
bool m_enabled;
|
||||
|
||||
/* Objects for this storage type. */
|
||||
ncm::ContentMetaDatabase m_content_meta_database;
|
||||
ncm::ContentStorage m_content_storage;
|
||||
public:
|
||||
ContentLocationResolverImpl(ncm::StorageId storage_id) : m_storage_id(storage_id), m_content_meta_database(), m_content_storage() { /* ... */ }
|
||||
ContentLocationResolverImpl(ncm::StorageId storage_id, bool enabled) : m_storage_id(storage_id), m_enabled(enabled), m_content_meta_database(), m_content_storage() { /* ... */ }
|
||||
|
||||
~ContentLocationResolverImpl();
|
||||
private:
|
||||
|
@ -61,6 +62,7 @@ namespace ams::lr {
|
|||
Result RedirectApplicationProgramPathForDebugDeprecated(const Path &path, ncm::ProgramId id);
|
||||
Result RedirectApplicationProgramPathForDebug(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id);
|
||||
Result EraseProgramRedirectionForDebug(ncm::ProgramId id);
|
||||
Result Disable();
|
||||
};
|
||||
static_assert(lr::IsILocationResolver<ContentLocationResolverImpl>);
|
||||
|
||||
|
|
|
@ -27,10 +27,19 @@ namespace ams::lr {
|
|||
using ContentLocationResolverFactory = sf::ObjectFactory<sf::StdAllocationPolicy<std::allocator>>;
|
||||
using RedirectOnlyLocationResolverFactory = sf::ObjectFactory<sf::StdAllocationPolicy<std::allocator>>;
|
||||
|
||||
bool IsAcceptableStorageId(ncm::StorageId storage_id) {
|
||||
if (ncm::IsInstallableStorage(storage_id)) {
|
||||
return storage_id != ncm::StorageId::Any;
|
||||
} else {
|
||||
return storage_id == ncm::StorageId::Host || storage_id == ncm::StorageId::GameCard;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Result LocationResolverManagerImpl::OpenLocationResolver(sf::Out<sf::SharedPointer<ILocationResolver>> out, ncm::StorageId storage_id) {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Find an existing resolver. */
|
||||
auto resolver = m_location_resolvers.Find(storage_id);
|
||||
|
||||
|
@ -39,7 +48,11 @@ namespace ams::lr {
|
|||
if (storage_id == ncm::StorageId::Host) {
|
||||
AMS_ABORT_UNLESS(m_location_resolvers.Insert(storage_id, RedirectOnlyLocationResolverFactory::CreateSharedEmplaced<ILocationResolver, RedirectOnlyLocationResolverImpl>()));
|
||||
} else {
|
||||
auto content_resolver = ContentLocationResolverFactory::CreateSharedEmplaced<ILocationResolver, ContentLocationResolverImpl>(storage_id);
|
||||
/* Get enabled. */
|
||||
auto *enabled = m_location_resolvers_enabled.Find(storage_id);
|
||||
|
||||
/* Create the resolver. */
|
||||
auto content_resolver = ContentLocationResolverFactory::CreateSharedEmplaced<ILocationResolver, ContentLocationResolverImpl>(storage_id, enabled != nullptr ? *enabled : m_default_enabled);
|
||||
R_TRY(content_resolver->Refresh());
|
||||
AMS_ABORT_UNLESS(m_location_resolvers.Insert(storage_id, std::move(content_resolver)));
|
||||
}
|
||||
|
@ -94,4 +107,39 @@ namespace ams::lr {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result LocationResolverManagerImpl::SetEnabled(const sf::InMapAliasArray<ncm::StorageId> &storages) {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* If we're setting enabled, we're no longer enabled by default. */
|
||||
m_default_enabled = false;
|
||||
|
||||
/* Create entries for each storage. */
|
||||
for (size_t i = 0; i < storages.GetSize(); ++i) {
|
||||
/* Get the storage id. */
|
||||
const auto storage_id = storages[i];
|
||||
|
||||
/* Check that the storage id is acceptable. */
|
||||
R_UNLESS(IsAcceptableStorageId(storage_id), lr::ResultUnknownStorageId());
|
||||
|
||||
/* Set the storage id as enabled. */
|
||||
AMS_ABORT_UNLESS(m_location_resolvers_enabled.InsertOrAssign(storage_id, true));
|
||||
}
|
||||
|
||||
/* Disable any open storages which shouldn't be enabled. */
|
||||
m_location_resolvers.ForEach([&](ncm::StorageId storage_id, sf::SharedPointer<ILocationResolver> &resolver) -> void {
|
||||
/* Check if the storage id is contained in the input array. */
|
||||
for (size_t i = 0; i < storages.GetSize(); ++i) {
|
||||
if (storages[i] == storage_id) {
|
||||
/* The storage is enabled, so we can return. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* The storage isn't enabled, so disable it. */
|
||||
R_ABORT_UNLESS(resolver->Disable());
|
||||
});
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -158,4 +158,8 @@ namespace ams::lr {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RedirectOnlyLocationResolverImpl::Disable() {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace ams::lr {
|
|||
Result RedirectApplicationProgramPathForDebugDeprecated(const Path &path, ncm::ProgramId id);
|
||||
Result RedirectApplicationProgramPathForDebug(const Path &path, ncm::ProgramId id, ncm::ProgramId owner_id);
|
||||
Result EraseProgramRedirectionForDebug(ncm::ProgramId id);
|
||||
Result Disable();
|
||||
};
|
||||
static_assert(lr::IsILocationResolver<RedirectOnlyLocationResolverImpl>);
|
||||
|
||||
|
|
|
@ -154,6 +154,11 @@ namespace ams::lr {
|
|||
AMS_UNUSED(id);
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
Result Disable() {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
};
|
||||
static_assert(lr::IsILocationResolver<RemoteLocationResolverImpl>);
|
||||
#endif
|
||||
|
|
|
@ -54,6 +54,11 @@ namespace ams::lr {
|
|||
AMS_UNUSED(out);
|
||||
AMS_ABORT("TODO: libnx binding");
|
||||
}
|
||||
|
||||
Result SetEnabled(const sf::InMapAliasArray<ncm::StorageId> &storages) {
|
||||
AMS_UNUSED(storages);
|
||||
AMS_ABORT("TODO: libnx binding");
|
||||
}
|
||||
};
|
||||
static_assert(lr::IsILocationResolverManager<RemoteLocationResolverManagerImpl>);
|
||||
#endif
|
||||
|
|
|
@ -125,6 +125,15 @@ namespace ams::util {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void ForEach(F f) {
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (m_keys[i]) {
|
||||
f(m_keys[i].value(), GetReference(m_values[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue