summaryrefslogblamecommitdiffstats
path: root/src/core/hle/service/ns/ns.cpp
blob: 13121c4f1c6cc7ed3131d24fcc9cb1013b0c6418 (plain) (tree)
1
2
3
4
5
6
7
8
9



                                            


                                           

                                    
                                       
                                         
                                   
                                     
                                     
                          
 
                       
 









                                                                                               

                                                            




























































































































































































































                                                                                                                                  

                                                                        






















                                                                                                 
 






                                                                                               
     
 









                                                                                                 
 




                                                                                               
     
 
                         
 



                                               
 


                                                                                                  
 

                                                                        

                                        



                                        
     
 
 


                                                                                         
 
                                      
                                                                                              
 



                                                                                  
     


                                                                                         
     
 


                                                                   
                                                                                                   
                                                     
         
     
 

                                              
 





















                                                                                      
     
 
                                                        




















                                                            

                                                                        

















                                                                          

                                                                











                                                                                   

                                                    

















                                                                                               

                                                            














                                                                                      

                                                      


                                                                        


                                                                        
                                                                     
          




                                

                                                            
















                                                                                                   


                                                                                          

                                                        








                                                      








                                                                               

































                                                                                  
                                                                              
































                                                                               

                                        


                                                    

















                                                               
                                                                                                    









                                                                      
                                                                   

 
                          
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#include "common/logging/log.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/ns/errors.h"
#include "core/hle/service/ns/language.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/pl_u.h"
#include "core/hle/service/set/set.h"
#include "core/settings.h"

namespace Service::NS {

IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountProxyInterface"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, nullptr, "CreateUserAccount"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IAccountProxyInterface::~IAccountProxyInterface() = default;

IApplicationManagerInterface::IApplicationManagerInterface()
    : ServiceFramework{"IApplicationManagerInterface"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, nullptr, "ListApplicationRecord"},
        {1, nullptr, "GenerateApplicationRecordCount"},
        {2, nullptr, "GetApplicationRecordUpdateSystemEvent"},
        {3, nullptr, "GetApplicationViewDeprecated"},
        {4, nullptr, "DeleteApplicationEntity"},
        {5, nullptr, "DeleteApplicationCompletely"},
        {6, nullptr, "IsAnyApplicationEntityRedundant"},
        {7, nullptr, "DeleteRedundantApplicationEntity"},
        {8, nullptr, "IsApplicationEntityMovable"},
        {9, nullptr, "MoveApplicationEntity"},
        {11, nullptr, "CalculateApplicationOccupiedSize"},
        {16, nullptr, "PushApplicationRecord"},
        {17, nullptr, "ListApplicationRecordContentMeta"},
        {19, nullptr, "LaunchApplicationOld"},
        {21, nullptr, "GetApplicationContentPath"},
        {22, nullptr, "TerminateApplication"},
        {23, nullptr, "ResolveApplicationContentPath"},
        {26, nullptr, "BeginInstallApplication"},
        {27, nullptr, "DeleteApplicationRecord"},
        {30, nullptr, "RequestApplicationUpdateInfo"},
        {32, nullptr, "CancelApplicationDownload"},
        {33, nullptr, "ResumeApplicationDownload"},
        {35, nullptr, "UpdateVersionList"},
        {36, nullptr, "PushLaunchVersion"},
        {37, nullptr, "ListRequiredVersion"},
        {38, nullptr, "CheckApplicationLaunchVersion"},
        {39, nullptr, "CheckApplicationLaunchRights"},
        {40, nullptr, "GetApplicationLogoData"},
        {41, nullptr, "CalculateApplicationDownloadRequiredSize"},
        {42, nullptr, "CleanupSdCard"},
        {43, nullptr, "CheckSdCardMountStatus"},
        {44, nullptr, "GetSdCardMountStatusChangedEvent"},
        {45, nullptr, "GetGameCardAttachmentEvent"},
        {46, nullptr, "GetGameCardAttachmentInfo"},
        {47, nullptr, "GetTotalSpaceSize"},
        {48, nullptr, "GetFreeSpaceSize"},
        {49, nullptr, "GetSdCardRemovedEvent"},
        {52, nullptr, "GetGameCardUpdateDetectionEvent"},
        {53, nullptr, "DisableApplicationAutoDelete"},
        {54, nullptr, "EnableApplicationAutoDelete"},
        {55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"},
        {56, nullptr, "SetApplicationTerminateResult"},
        {57, nullptr, "ClearApplicationTerminateResult"},
        {58, nullptr, "GetLastSdCardMountUnexpectedResult"},
        {59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"},
        {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
        {61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
        {62, nullptr, "GetGameCardStopper"},
        {63, nullptr, "IsSystemProgramInstalled"},
        {64, nullptr, "StartApplyDeltaTask"},
        {65, nullptr, "GetRequestServerStopper"},
        {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
        {67, nullptr, "CancelApplicationApplyDelta"},
        {68, nullptr, "ResumeApplicationApplyDelta"},
        {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
        {70, nullptr, "ResumeAll"},
        {71, nullptr, "GetStorageSize"},
        {80, nullptr, "RequestDownloadApplication"},
        {81, nullptr, "RequestDownloadAddOnContent"},
        {82, nullptr, "DownloadApplication"},
        {83, nullptr, "CheckApplicationResumeRights"},
        {84, nullptr, "GetDynamicCommitEvent"},
        {85, nullptr, "RequestUpdateApplication2"},
        {86, nullptr, "EnableApplicationCrashReport"},
        {87, nullptr, "IsApplicationCrashReportEnabled"},
        {90, nullptr, "BoostSystemMemoryResourceLimit"},
        {91, nullptr, "DeprecatedLaunchApplication"},
        {92, nullptr, "GetRunningApplicationProgramId"},
        {93, nullptr, "GetMainApplicationProgramIndex"},
        {94, nullptr, "LaunchApplication"},
        {95, nullptr, "GetApplicationLaunchInfo"},
        {96, nullptr, "AcquireApplicationLaunchInfo"},
        {97, nullptr, "GetMainApplicationProgramIndex2"},
        {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
        {100, nullptr, "ResetToFactorySettings"},
        {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
        {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
        {200, nullptr, "CalculateUserSaveDataStatistics"},
        {201, nullptr, "DeleteUserSaveDataAll"},
        {210, nullptr, "DeleteUserSystemSaveData"},
        {211, nullptr, "DeleteSaveData"},
        {220, nullptr, "UnregisterNetworkServiceAccount"},
        {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"},
        {300, nullptr, "GetApplicationShellEvent"},
        {301, nullptr, "PopApplicationShellEventInfo"},
        {302, nullptr, "LaunchLibraryApplet"},
        {303, nullptr, "TerminateLibraryApplet"},
        {304, nullptr, "LaunchSystemApplet"},
        {305, nullptr, "TerminateSystemApplet"},
        {306, nullptr, "LaunchOverlayApplet"},
        {307, nullptr, "TerminateOverlayApplet"},
        {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"},
        {401, nullptr, "InvalidateAllApplicationControlCache"},
        {402, nullptr, "RequestDownloadApplicationControlData"},
        {403, nullptr, "GetMaxApplicationControlCacheCount"},
        {404, nullptr, "InvalidateApplicationControlCache"},
        {405, nullptr, "ListApplicationControlCacheEntryInfo"},
        {406, nullptr, "GetApplicationControlProperty"},
        {502, nullptr, "RequestCheckGameCardRegistration"},
        {503, nullptr, "RequestGameCardRegistrationGoldPoint"},
        {504, nullptr, "RequestRegisterGameCard"},
        {505, nullptr, "GetGameCardMountFailureEvent"},
        {506, nullptr, "IsGameCardInserted"},
        {507, nullptr, "EnsureGameCardAccess"},
        {508, nullptr, "GetLastGameCardMountFailureResult"},
        {509, nullptr, "ListApplicationIdOnGameCard"},
        {600, nullptr, "CountApplicationContentMeta"},
        {601, nullptr, "ListApplicationContentMetaStatus"},
        {602, nullptr, "ListAvailableAddOnContent"},
        {603, nullptr, "GetOwnedApplicationContentMetaStatus"},
        {604, nullptr, "RegisterContentsExternalKey"},
        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
        {606, nullptr, "GetContentMetaStorage"},
        {607, nullptr, "ListAvailableAddOnContent"},
        {700, nullptr, "PushDownloadTaskList"},
        {701, nullptr, "ClearTaskStatusList"},
        {702, nullptr, "RequestDownloadTaskList"},
        {703, nullptr, "RequestEnsureDownloadTask"},
        {704, nullptr, "ListDownloadTaskStatus"},
        {705, nullptr, "RequestDownloadTaskListData"},
        {800, nullptr, "RequestVersionList"},
        {801, nullptr, "ListVersionList"},
        {802, nullptr, "RequestVersionListData"},
        {900, nullptr, "GetApplicationRecord"},
        {901, nullptr, "GetApplicationRecordProperty"},
        {902, nullptr, "EnableApplicationAutoUpdate"},
        {903, nullptr, "DisableApplicationAutoUpdate"},
        {904, nullptr, "TouchApplication"},
        {905, nullptr, "RequestApplicationUpdate"},
        {906, nullptr, "IsApplicationUpdateRequested"},
        {907, nullptr, "WithdrawApplicationUpdateRequest"},
        {908, nullptr, "ListApplicationRecordInstalledContentMeta"},
        {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
        {910, nullptr, "HasApplicationRecord"},
        {911, nullptr, "SetPreInstalledApplication"},
        {912, nullptr, "ClearPreInstalledApplicationFlag"},
        {1000, nullptr, "RequestVerifyApplicationDeprecated"},
        {1001, nullptr, "CorruptApplicationForDebug"},
        {1002, nullptr, "RequestVerifyAddOnContentsRights"},
        {1003, nullptr, "RequestVerifyApplication"},
        {1004, nullptr, "CorruptContentForDebug"},
        {1200, nullptr, "NeedsUpdateVulnerability"},
        {1300, nullptr, "IsAnyApplicationEntityInstalled"},
        {1301, nullptr, "DeleteApplicationContentEntities"},
        {1302, nullptr, "CleanupUnrecordedApplicationEntity"},
        {1303, nullptr, "CleanupAddOnContentsWithNoRights"},
        {1304, nullptr, "DeleteApplicationContentEntity"},
        {1305, nullptr, "TryDeleteRunningApplicationEntity"},
        {1306, nullptr, "TryDeleteRunningApplicationCompletely"},
        {1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
        {1308, nullptr, "DeleteApplicationCompletelyForDebug"},
        {1309, nullptr, "CleanupUnavailableAddOnContents"},
        {1400, nullptr, "PrepareShutdown"},
        {1500, nullptr, "FormatSdCard"},
        {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
        {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
        {1504, nullptr, "InsertSdCard"},
        {1505, nullptr, "RemoveSdCard"},
        {1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
        {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
        {1700, nullptr, "ListApplicationDownloadingContentMeta"},
        {1701, nullptr, "GetApplicationView"},
        {1702, nullptr, "GetApplicationDownloadTaskStatus"},
        {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
        {1800, nullptr, "IsNotificationSetupCompleted"},
        {1801, nullptr, "GetLastNotificationInfoCount"},
        {1802, nullptr, "ListLastNotificationInfo"},
        {1803, nullptr, "ListNotificationTask"},
        {1900, nullptr, "IsActiveAccount"},
        {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
        {1902, nullptr, "GetApplicationTicketInfo"},
        {2000, nullptr, "GetSystemDeliveryInfo"},
        {2001, nullptr, "SelectLatestSystemDeliveryInfo"},
        {2002, nullptr, "VerifyDeliveryProtocolVersion"},
        {2003, nullptr, "GetApplicationDeliveryInfo"},
        {2004, nullptr, "HasAllContentsToDeliver"},
        {2005, nullptr, "CompareApplicationDeliveryInfo"},
        {2006, nullptr, "CanDeliverApplication"},
        {2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
        {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
        {2009, nullptr, "EstimateRequiredSize"},
        {2010, nullptr, "RequestReceiveApplication"},
        {2011, nullptr, "CommitReceiveApplication"},
        {2012, nullptr, "GetReceiveApplicationProgress"},
        {2013, nullptr, "RequestSendApplication"},
        {2014, nullptr, "GetSendApplicationProgress"},
        {2015, nullptr, "CompareSystemDeliveryInfo"},
        {2016, nullptr, "ListNotCommittedContentMeta"},
        {2017, nullptr, "CreateDownloadTask"},
        {2018, nullptr, "GetApplicationDeliveryInfoHash"},
        {2050, nullptr, "GetApplicationRightsOnClient"},
        {2100, nullptr, "GetApplicationTerminateResult"},
        {2101, nullptr, "GetRawApplicationTerminateResult"},
        {2150, nullptr, "CreateRightsEnvironment"},
        {2151, nullptr, "DestroyRightsEnvironment"},
        {2152, nullptr, "ActivateRightsEnvironment"},
        {2153, nullptr, "DeactivateRightsEnvironment"},
        {2154, nullptr, "ForceActivateRightsContextForExit"},
        {2160, nullptr, "AddTargetApplicationToRightsEnvironment"},
        {2161, nullptr, "SetUsersToRightsEnvironment"},
        {2170, nullptr, "GetRightsEnvironmentStatus"},
        {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
        {2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
        {2181, nullptr, "GetLastResultOfExtendRightsInRightsEnvironment"},
        {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
        {2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
        {2199, nullptr, "GetRightsEnvironmentCountForDebug"},
        {2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
        {2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
        {2250, nullptr, "RequestReportActiveELicence"},
        {2300, nullptr, "ListEventLog"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IApplicationManagerInterface::~IApplicationManagerInterface() = default;

void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestContext& ctx) {
    IPC::RequestParser rp{ctx};
    const auto flag = rp.PopRaw<u64>();
    LOG_DEBUG(Service_NS, "called with flag={:016X}", flag);

    const auto title_id = rp.PopRaw<u64>();

    const auto size = ctx.GetWriteBufferSize();

    const FileSys::PatchManager pm{title_id};
    const auto control = pm.GetControlMetadata();

    std::vector<u8> out;

    if (control.first != nullptr) {
        if (size < 0x4000) {
            LOG_ERROR(Service_NS,
                      "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size);
            IPC::ResponseBuilder rb{ctx, 2};
            // TODO(DarkLordZach): Find a better error code for this.
            rb.Push(ResultCode(-1));
            return;
        }

        out.resize(0x4000);
        const auto bytes = control.first->GetRawBytes();
        std::memcpy(out.data(), bytes.data(), bytes.size());
    } else {
        LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.",
                    title_id);
        out.resize(std::min<u64>(0x4000, size));
    }

    if (control.second != nullptr) {
        if (size < 0x4000 + control.second->GetSize()) {
            LOG_ERROR(Service_NS,
                      "output buffer is too small! (actual={:016X}, expected_min={:016X})", size,
                      0x4000 + control.second->GetSize());
            IPC::ResponseBuilder rb{ctx, 2};
            // TODO(DarkLordZach): Find a better error code for this.
            rb.Push(ResultCode(-1));
            return;
        }

        out.resize(0x4000 + control.second->GetSize());
        control.second->Read(out.data() + 0x4000, control.second->GetSize());
    } else {
        LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.",
                    title_id);
    }

    ctx.WriteBuffer(out);

    IPC::ResponseBuilder rb{ctx, 3};
    rb.Push(RESULT_SUCCESS);
    rb.Push<u32>(static_cast<u32>(out.size()));
}

void IApplicationManagerInterface::GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx) {
    IPC::RequestParser rp{ctx};
    const auto supported_languages = rp.Pop<u32>();

    const auto res = GetApplicationDesiredLanguage(supported_languages);
    if (res.Succeeded()) {
        IPC::ResponseBuilder rb{ctx, 3};
        rb.Push(RESULT_SUCCESS);
        rb.Push<u32>(*res);
    } else {
        IPC::ResponseBuilder rb{ctx, 2};
        rb.Push(res.Code());
    }
}

ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage(
    const u32 supported_languages) {
    LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);

    // Get language code from settings
    const auto language_code = Set::GetLanguageCodeFromIndex(Settings::values.language_index);

    // Convert to application language, get priority list
    const auto application_language = ConvertToApplicationLanguage(language_code);
    if (application_language == std::nullopt) {
        return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
    }
    const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
    if (!priority_list) {
        return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
    }

    // Try to find a valid language.
    for (const auto lang : *priority_list) {
        const auto supported_flag = GetSupportedLanguageFlag(lang);
        if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
            return MakeResult(static_cast<u8>(lang));
        }
    }

    return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
}

void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
    Kernel::HLERequestContext& ctx) {
    IPC::RequestParser rp{ctx};
    const auto application_language = rp.Pop<u8>();

    const auto res = ConvertApplicationLanguageToLanguageCode(application_language);
    if (res.Succeeded()) {
        IPC::ResponseBuilder rb{ctx, 4};
        rb.Push(RESULT_SUCCESS);
        rb.Push(*res);
    } else {
        IPC::ResponseBuilder rb{ctx, 2};
        rb.Push(res.Code());
    }
}

ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
    u8 application_language) {
    const auto language_code =
        ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
    if (language_code == std::nullopt) {
        return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
    }

    return MakeResult(static_cast<u64>(*language_code));
}

IApplicationVersionInterface::IApplicationVersionInterface()
    : ServiceFramework{"IApplicationVersionInterface"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, nullptr, "GetLaunchRequiredVersion"},
        {1, nullptr, "UpgradeLaunchRequiredVersion"},
        {35, nullptr, "UpdateVersionList"},
        {36, nullptr, "PushLaunchVersion"},
        {37, nullptr, "ListRequiredVersion"},
        {800, nullptr, "RequestVersionList"},
        {801, nullptr, "ListVersionList"},
        {802, nullptr, "RequestVersionListData"},
        {1000, nullptr, "PerformAutoUpdate"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IApplicationVersionInterface::~IApplicationVersionInterface() = default;

IContentManagerInterface::IContentManagerInterface()
    : ServiceFramework{"IContentManagerInterface"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {11, nullptr, "CalculateApplicationOccupiedSize"},
        {43, nullptr, "CheckSdCardMountStatus"},
        {47, nullptr, "GetTotalSpaceSize"},
        {48, nullptr, "GetFreeSpaceSize"},
        {600, nullptr, "CountApplicationContentMeta"},
        {601, nullptr, "ListApplicationContentMetaStatus"},
        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
        {607, nullptr, "IsAnyApplicationRunning"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IContentManagerInterface::~IContentManagerInterface() = default;

IDocumentInterface::IDocumentInterface() : ServiceFramework{"IDocumentInterface"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {21, nullptr, "GetApplicationContentPath"},
        {23, nullptr, "ResolveApplicationContentPath"},
        {93, nullptr, "GetRunningApplicationProgramId"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IDocumentInterface::~IDocumentInterface() = default;

IDownloadTaskInterface::IDownloadTaskInterface() : ServiceFramework{"IDownloadTaskInterface"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {701, nullptr, "ClearTaskStatusList"},
        {702, nullptr, "RequestDownloadTaskList"},
        {703, nullptr, "RequestEnsureDownloadTask"},
        {704, nullptr, "ListDownloadTaskStatus"},
        {705, nullptr, "RequestDownloadTaskListData"},
        {706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
        {707, nullptr, "EnableAutoCommit"},
        {708, nullptr, "DisableAutoCommit"},
        {709, nullptr, "TriggerDynamicCommitEvent"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IDownloadTaskInterface::~IDownloadTaskInterface() = default;

IECommerceInterface::IECommerceInterface() : ServiceFramework{"IECommerceInterface"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, nullptr, "RequestLinkDevice"},
        {1, nullptr, "RequestCleanupAllPreInstalledApplications"},
        {2, nullptr, "RequestCleanupPreInstalledApplication"},
        {3, nullptr, "RequestSyncRights"},
        {4, nullptr, "RequestUnlinkDevice"},
        {5, nullptr, "RequestRevokeAllELicense"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IECommerceInterface::~IECommerceInterface() = default;

IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface()
    : ServiceFramework{"IFactoryResetInterface"} {
    // clang-format off
        static const FunctionInfo functions[] = {
            {100, nullptr, "ResetToFactorySettings"},
            {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
            {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
        };
    // clang-format on

    RegisterHandlers(functions);
}

IFactoryResetInterface::~IFactoryResetInterface() = default;

NS::NS(const char* name) : ServiceFramework{name} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
        {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
        {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
        {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
        {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"},
        {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
        {7998, &NS::PushInterface<IContentManagerInterface>, "GetContentManagementInterface"},
        {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

NS::~NS() = default;

std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const {
    return GetInterface<IApplicationManagerInterface>();
}

class NS_DEV final : public ServiceFramework<NS_DEV> {
public:
    explicit NS_DEV() : ServiceFramework{"ns:dev"} {
        // clang-format off
        static const FunctionInfo functions[] = {
            {0, nullptr, "LaunchProgram"},
            {1, nullptr, "TerminateProcess"},
            {2, nullptr, "TerminateProgram"},
            {4, nullptr, "GetShellEventHandle"},
            {5, nullptr, "GetShellEventInfo"},
            {6, nullptr, "TerminateApplication"},
            {7, nullptr, "PrepareLaunchProgramFromHost"},
            {8, nullptr, "LaunchApplication"},
            {9, nullptr, "LaunchApplicationWithStorageId"},
            {10, nullptr, "TerminateApplication2"},
            {11, nullptr, "GetRunningApplicationProcessId"},
            {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActive"},
        };
        // clang-format on

        RegisterHandlers(functions);
    }
};

class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
public:
    explicit ISystemUpdateControl() : ServiceFramework{"ISystemUpdateControl"} {
        // clang-format off
        static const FunctionInfo functions[] = {
            {0, nullptr, "HasDownloaded"},
            {1, nullptr, "RequestCheckLatestUpdate"},
            {2, nullptr, "RequestDownloadLatestUpdate"},
            {3, nullptr, "GetDownloadProgress"},
            {4, nullptr, "ApplyDownloadedUpdate"},
            {5, nullptr, "RequestPrepareCardUpdate"},
            {6, nullptr, "GetPrepareCardUpdateProgress"},
            {7, nullptr, "HasPreparedCardUpdate"},
            {8, nullptr, "ApplyCardUpdate"},
            {9, nullptr, "GetDownloadedEulaDataSize"},
            {10, nullptr, "GetDownloadedEulaData"},
            {11, nullptr, "SetupCardUpdate"},
            {12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
            {13, nullptr, "GetPreparedCardUpdateEulaData"},
            {14, nullptr, "SetupCardUpdateViaSystemUpdater"},
            {15, nullptr, "HasReceived"},
            {16, nullptr, "RequestReceiveSystemUpdate"},
            {17, nullptr, "GetReceiveProgress"},
            {18, nullptr, "ApplyReceivedUpdate"},
            {19, nullptr, "GetReceivedEulaDataSize"},
            {20, nullptr, "GetReceivedEulaData"},
            {21, nullptr, "SetupToReceiveSystemUpdate"},
            {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"},
        };
        // clang-format on

        RegisterHandlers(functions);
    }
};

class NS_SU final : public ServiceFramework<NS_SU> {
public:
    explicit NS_SU() : ServiceFramework{"ns:su"} {
        // clang-format off
        static const FunctionInfo functions[] = {
            {0, nullptr, "GetBackgroundNetworkUpdateState"},
            {1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"},
            {2, nullptr, "NotifyExFatDriverRequired"},
            {3, nullptr, "ClearExFatDriverStatusForDebug"},
            {4, nullptr, "RequestBackgroundNetworkUpdate"},
            {5, nullptr, "NotifyBackgroundNetworkUpdate"},
            {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
            {9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
            {10, nullptr, "NotifySystemUpdateForContentDelivery"},
            {11, nullptr, "PrepareShutdown"},
            {16, nullptr, "DestroySystemUpdateTask"},
            {17, nullptr, "RequestSendSystemUpdate"},
            {18, nullptr, "GetSendSystemUpdateProgress"},
        };
        // clang-format on

        RegisterHandlers(functions);
    }

private:
    void OpenSystemUpdateControl(Kernel::HLERequestContext& ctx) {
        LOG_DEBUG(Service_NS, "called");

        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
        rb.Push(RESULT_SUCCESS);
        rb.PushIpcInterface<ISystemUpdateControl>();
    }
};

class NS_VM final : public ServiceFramework<NS_VM> {
public:
    explicit NS_VM() : ServiceFramework{"ns:vm"} {
        // clang-format off
        static const FunctionInfo functions[] = {
            {1200, nullptr, "NeedsUpdateVulnerability"},
            {1201, nullptr, "UpdateSafeSystemVersionForDebug"},
            {1202, nullptr, "GetSafeSystemVersion"},
        };
        // clang-format on

        RegisterHandlers(functions);
    }
};

void InstallInterfaces(SM::ServiceManager& service_manager, FileSystem::FileSystemController& fsc) {
    std::make_shared<NS>("ns:am2")->InstallAsService(service_manager);
    std::make_shared<NS>("ns:ec")->InstallAsService(service_manager);
    std::make_shared<NS>("ns:rid")->InstallAsService(service_manager);
    std::make_shared<NS>("ns:rt")->InstallAsService(service_manager);
    std::make_shared<NS>("ns:web")->InstallAsService(service_manager);

    std::make_shared<NS_DEV>()->InstallAsService(service_manager);
    std::make_shared<NS_SU>()->InstallAsService(service_manager);
    std::make_shared<NS_VM>()->InstallAsService(service_manager);

    std::make_shared<PL_U>(fsc)->InstallAsService(service_manager);
}

} // namespace Service::NS