From 52a892ca3196677f669a90601d3849ea1651c53c Mon Sep 17 00:00:00 2001 From: yellows8 Date: Thu, 6 Feb 2020 20:07:02 -0500 Subject: [PATCH 1/6] ns: Fixed cmd order. --- nx/include/switch/services/ns.h | 40 ++++++++++++++++----------------- nx/source/services/ns.c | 28 +++++++++++------------ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index a850e1aa..4b29546e 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -163,26 +163,6 @@ Service* nsGetServiceSession_ApplicationManagerInterface(void); */ Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount); -/** - * @brief Gets an listing of \ref NsApplicationContentMetaStatus. - * @param[in] application_id ApplicationId. - * @param[in] index Starting entry index. - * @param[out] list Output array of \ref NsApplicationContentMetaStatus. - * @param[in] count Size of the list array in entries. - * @param[out] out_entrycount Total output entries. - */ -Result nsListApplicationContentMetaStatus(u64 application_id, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount); - -/** - * @brief Gets the \ref NsApplicationControlData for the specified application. - * @param[in] source Source, official sw uses ::NsApplicationControlSource_Storage. - * @param[in] application_id ApplicationId. - * @param[out] buffer \ref NsApplicationControlData - * @param[in] size Size of the buffer. - * @param[out] actual_size Actual output size. - */ -Result nsGetApplicationControlData(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u64* actual_size); - /** * @brief Returns the total storage capacity (used + free) from content manager services. * @param[in] storage_id \ref NcmStorageId. Must be ::NcmStorageId_SdCard. @@ -197,6 +177,26 @@ Result nsGetTotalSpaceSize(NcmStorageId storage_id, u64 *size); */ Result nsGetFreeSpaceSize(NcmStorageId storage_id, u64 *size); +/** + * @brief Gets the \ref NsApplicationControlData for the specified application. + * @param[in] source Source, official sw uses ::NsApplicationControlSource_Storage. + * @param[in] application_id ApplicationId. + * @param[out] buffer \ref NsApplicationControlData + * @param[in] size Size of the buffer. + * @param[out] actual_size Actual output size. + */ +Result nsGetApplicationControlData(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u64* actual_size); + +/** + * @brief Gets an listing of \ref NsApplicationContentMetaStatus. + * @param[in] application_id ApplicationId. + * @param[in] index Starting entry index. + * @param[out] list Output array of \ref NsApplicationContentMetaStatus. + * @param[in] count Size of the list array in entries. + * @param[out] out_entrycount Total output entries. + */ +Result nsListApplicationContentMetaStatus(u64 application_id, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount); + /** * @brief Generates a \ref NsSystemDeliveryInfo using the currently installed SystemUpdate meta. * @note Only available on [4.0.0+]. diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index e4ba6f23..8849664f 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -175,16 +175,12 @@ Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entr ); } -Result nsListApplicationContentMetaStatus(u64 application_id, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount) { - const struct { - s32 index; - u64 application_id; - } in = { index, application_id }; +Result nsGetTotalSpaceSize(NcmStorageId storage_id, u64 *size) { + return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 47); +} - return serviceDispatchInOut(&g_nsAppManSrv, 601, in, *out_entrycount, - .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { list, count*sizeof(NsApplicationContentMetaStatus) } }, - ); +Result nsGetFreeSpaceSize(NcmStorageId storage_id, u64 *size) { + return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 48); } Result nsGetApplicationControlData(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u64* actual_size) { @@ -203,12 +199,16 @@ Result nsGetApplicationControlData(NsApplicationControlSource source, u64 applic return rc; } -Result nsGetTotalSpaceSize(NcmStorageId storage_id, u64 *size) { - return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 47); -} +Result nsListApplicationContentMetaStatus(u64 application_id, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount) { + const struct { + s32 index; + u64 application_id; + } in = { index, application_id }; -Result nsGetFreeSpaceSize(NcmStorageId storage_id, u64 *size) { - return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 48); + return serviceDispatchInOut(&g_nsAppManSrv, 601, in, *out_entrycount, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { list, count*sizeof(NsApplicationContentMetaStatus) } }, + ); } Result nsGetSystemDeliveryInfo(NsSystemDeliveryInfo *info) { From 68d6260d72e56e8af16ae7f3f2ce74026abe0f2a Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 10 Feb 2020 12:14:40 -0500 Subject: [PATCH 2/6] ns: Actually check the required sysver for nsListApplicationContentMetaStatus. Updated param types for nsGetTotalSpaceSize/nsGetFreeSpaceSize + minor other improvements. Added support for the following: * NsRequestServerStopper/nsRequestServerStopperClose(). * nsGetApplicationRecordUpdateSystemEvent, nsDeleteApplicationEntity, nsDeleteApplicationCompletely, nsDeleteRedundantApplicationEntity, nsIsApplicationEntityMovable, nsMoveApplicationEntity, nsCancelApplicationDownload, nsResumeApplicationDownload, nsCheckApplicationLaunchVersion, nsCalculateApplicationDownloadRequiredSize, nsCleanupSdCard, nsGetSdCardMountStatusChangedEvent, nsGetGameCardUpdateDetectionEvent, nsDisableApplicationAutoDelete, nsEnableApplicationAutoDelete, nsSetApplicationTerminateResult, nsClearApplicationTerminateResult, nsGetLastSdCardMountUnexpectedResult. * nsGetRequestServerStopper, nsCancelApplicationApplyDelta, nsResumeApplicationApplyDelta, nsCalculateApplicationApplyDeltaRequiredSize, nsResumeAll, nsGetStorageSize, nsDeleteUserSystemSaveData, nsDeleteSaveData, nsUnregisterNetworkServiceAccount, nsUnregisterNetworkServiceAccountWithUserSaveDataDeletion, nsGetGameCardMountFailureEvent, nsIsGameCardInserted, nsEnsureGameCardAccess, nsGetLastGameCardMountFailureResult, nsListApplicationIdOnGameCard, nsTouchApplication, nsIsApplicationUpdateRequested, nsWithdrawApplicationUpdateRequest, nsIsAnyApplicationEntityInstalled, nsCleanupUnavailableAddOnContents, nsFormatSdCard, nsNeedsSystemUpdateToFormatSdCard, nsGetLastSdCardFormatUnexpectedResult, nsGetApplicationTerminateResult. --- nx/include/switch/services/ns.h | 312 ++++++++++++++++++++++++++++- nx/source/services/ns.c | 339 +++++++++++++++++++++++++++++++- 2 files changed, 643 insertions(+), 8 deletions(-) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 4b29546e..fbda2982 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -10,6 +10,8 @@ #include "../sf/service.h" #include "../services/ncm_types.h" #include "../services/async.h" +#include "../services/acc.h" +#include "../services/fs.h" #include "../kernel/event.h" #include "../kernel/tmem.h" @@ -43,6 +45,11 @@ typedef enum { NsLatestSystemUpdate_Unknown2 = 2, ///< Unknown. } NsLatestSystemUpdate; +/// RequestServerStopper +typedef struct { + Service s; ///< IRequestServerStopper +} NsRequestServerStopper; + /// SystemUpdateControl typedef struct { Service s; ///< ISystemUpdateControl @@ -163,19 +170,206 @@ Service* nsGetServiceSession_ApplicationManagerInterface(void); */ Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount); +/** + * @brief GetApplicationRecordUpdateSystemEvent + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result nsGetApplicationRecordUpdateSystemEvent(Event* out_event); + +/** + * @brief DeleteApplicationEntity + * @param[in] application_id ApplicationId. + */ +Result nsDeleteApplicationEntity(u64 application_id); + +/** + * @brief DeleteApplicationCompletely + * @param[in] application_id ApplicationId. + */ +Result nsDeleteApplicationCompletely(u64 application_id); + +/** + * @brief DeleteRedundantApplicationEntity + */ +Result nsDeleteRedundantApplicationEntity(void); + +/** + * @brief IsApplicationEntityMovable + * @param[in] application_id ApplicationId. + * @param[in] storage_id \ref NcmStorageId + * @param[out] out Output flag. + */ +Result nsIsApplicationEntityMovable(u64 application_id, NcmStorageId storage_id, bool *out); + +/** + * @brief MoveApplicationEntity + * @param[in] application_id ApplicationId. + * @param[in] storage_id \ref NcmStorageId + */ +Result nsMoveApplicationEntity(u64 application_id, NcmStorageId storage_id); + +/** + * @brief CancelApplicationDownload + * @param[in] application_id ApplicationId. + */ +Result nsCancelApplicationDownload(u64 application_id); + +/** + * @brief ResumeApplicationDownload + * @param[in] application_id ApplicationId. + */ +Result nsResumeApplicationDownload(u64 application_id); + +/** + * @brief CheckApplicationLaunchVersion + * @param[in] application_id ApplicationId. + */ +Result nsCheckApplicationLaunchVersion(u64 application_id); + +/** + * @brief CalculateApplicationApplyDeltaRequiredSize + * @param[in] application_id ApplicationId. + * @param[out] storage_id Output \ref NcmStorageId. + * @param[out] size Output size. + */ +Result nsCalculateApplicationDownloadRequiredSize(u64 application_id, NcmStorageId *storage_id, s64 *size); + +/** + * @brief CleanupSdCard + */ +Result nsCleanupSdCard(void); + +/** + * @brief GetSdCardMountStatusChangedEvent + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=false. + */ +Result nsGetSdCardMountStatusChangedEvent(Event* out_event); + /** * @brief Returns the total storage capacity (used + free) from content manager services. * @param[in] storage_id \ref NcmStorageId. Must be ::NcmStorageId_SdCard. * @param[out] size Pointer to output the total storage size to. */ -Result nsGetTotalSpaceSize(NcmStorageId storage_id, u64 *size); +Result nsGetTotalSpaceSize(NcmStorageId storage_id, s64 *size); /** * @brief Returns the available storage capacity from content manager services. * @param[in] storage_id \ref NcmStorageId. Must be ::NcmStorageId_SdCard. * @param[out] size Pointer to output the free storage size to. */ -Result nsGetFreeSpaceSize(NcmStorageId storage_id, u64 *size); +Result nsGetFreeSpaceSize(NcmStorageId storage_id, s64 *size); + +/** + * @brief GetGameCardUpdateDetectionEvent + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=false. + */ +Result nsGetGameCardUpdateDetectionEvent(Event* out_event); + +/** + * @brief DisableApplicationAutoDelete + * @param[in] application_id ApplicationId. + */ +Result nsDisableApplicationAutoDelete(u64 application_id); + +/** + * @brief EnableApplicationAutoDelete + * @param[in] application_id ApplicationId. + */ +Result nsEnableApplicationAutoDelete(u64 application_id); + +/** + * @brief SetApplicationTerminateResult + * @param[in] application_id ApplicationId. + * @param[in] res Result. + */ +Result nsSetApplicationTerminateResult(u64 application_id, Result res); + +/** + * @brief ClearApplicationTerminateResult + * @param[in] application_id ApplicationId. + */ +Result nsClearApplicationTerminateResult(u64 application_id); + +/** + * @brief GetLastSdCardMountUnexpectedResult + */ +Result nsGetLastSdCardMountUnexpectedResult(void); + +/** + * @brief Opens a \ref NsRequestServerStopper. + * @note Only available on [2.0.0+]. + * @param[out] r \ref NsRequestServerStopper + */ +Result nsGetRequestServerStopper(NsRequestServerStopper *r); + +/** + * @brief CancelApplicationApplyDelta + * @note Only available on [3.0.0+]. + * @param[in] application_id ApplicationId. + */ +Result nsCancelApplicationApplyDelta(u64 application_id); + +/** + * @brief ResumeApplicationApplyDelta + * @note Only available on [3.0.0+]. + * @param[in] application_id ApplicationId. + */ +Result nsResumeApplicationApplyDelta(u64 application_id); + +/** + * @brief CalculateApplicationApplyDeltaRequiredSize + * @note Only available on [3.0.0+]. + * @param[in] application_id ApplicationId. + * @param[out] storage_id Output \ref NcmStorageId. + * @param[out] size Output size. + */ +Result nsCalculateApplicationApplyDeltaRequiredSize(u64 application_id, NcmStorageId *storage_id, s64 *size); + +/** + * @brief ResumeAll + * @note Only available on [3.0.0+]. + */ +Result nsResumeAll(void); + +/** + * @brief Temporarily mounts the specified fs ContentStorage, then uses fs GetTotalSpaceSize/GetFreeSpaceSize with that mounted ContentStorage. + * @note Only available on [3.0.0+]. + * @param[in] storage_id \ref NcmStorageId, must be ::NcmStorageId_BuiltInUser or ::NcmStorageId_SdCard. + * @param[out] total_space_size Output from GetTotalSpaceSize. + * @param[out] free_space_size Output from GetFreeSpaceSize. + */ +Result nsGetStorageSize(NcmStorageId storage_id, s64 *total_space_size, s64 *free_space_size); + +/** + * @brief DeleteUserSystemSaveData + * @param[in] uid \ref AccountUid + * @param[in] system_save_data_id SystemSaveDataId + */ +Result nsDeleteUserSystemSaveData(AccountUid uid, u64 system_save_data_id); + +/** + * @brief DeleteSaveData + * @note Only available on [6.0.0+]. + * @param[in] save_data_space_id \ref FsSaveDataSpaceId + * @param[in] save_data_id SaveDataId + */ +Result nsDeleteSaveData(FsSaveDataSpaceId save_data_space_id, u64 save_data_id); + +/** + * @brief UnregisterNetworkServiceAccount + * @param[in] uid \ref AccountUid + */ +Result nsUnregisterNetworkServiceAccount(AccountUid uid); + +/** + * @brief UnregisterNetworkServiceAccountWithUserSaveDataDeletion + * @note Only available on [6.0.0+]. + * @param[in] uid \ref AccountUid + */ +Result nsUnregisterNetworkServiceAccountWithUserSaveDataDeletion(AccountUid uid); /** * @brief Gets the \ref NsApplicationControlData for the specified application. @@ -187,8 +381,45 @@ Result nsGetFreeSpaceSize(NcmStorageId storage_id, u64 *size); */ Result nsGetApplicationControlData(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u64* actual_size); +/** + * @brief GetGameCardMountFailureEvent + * @note The Event must be closed by the user once finished with it. + * @note Only available on [3.0.0+]. + * @param[out] out_event Output Event with autoclear=false. + */ +Result nsGetGameCardMountFailureEvent(Event* out_event); + +/** + * @brief IsGameCardInserted + * @note Only available on [3.0.0+]. + * @param[out] out Output flag. + */ +Result nsIsGameCardInserted(bool *out); + +/** + * @brief EnsureGameCardAccess + * @note Only available on [3.0.0+]. + */ +Result nsEnsureGameCardAccess(void); + +/** + * @brief GetLastGameCardMountFailureResult + * @note Only available on [3.0.0+]. + */ +Result nsGetLastGameCardMountFailureResult(void); + +/** + * @brief ListApplicationIdOnGameCard + * @note Only available on [5.0.0+]. + * @param[out] application_ids Output array of ApplicationIds. + * @param[in] count Size of the application_ids array in entries. + * @param[out] total_out Total output entries. + */ +Result nsListApplicationIdOnGameCard(u64 *application_ids, s32 count, s32 *total_out); + /** * @brief Gets an listing of \ref NsApplicationContentMetaStatus. + * @note Only available on [2.0.0+]. * @param[in] application_id ApplicationId. * @param[in] index Starting entry index. * @param[out] list Output array of \ref NsApplicationContentMetaStatus. @@ -197,6 +428,64 @@ Result nsGetApplicationControlData(NsApplicationControlSource source, u64 applic */ Result nsListApplicationContentMetaStatus(u64 application_id, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount); +/** + * @brief TouchApplication + * @note Only available on [2.0.0+]. + * @param[in] application_id ApplicationId. + */ +Result nsTouchApplication(u64 application_id); + +/** + * @brief IsApplicationUpdateRequested + * @note Only available on [2.0.0+]. + * @param[in] application_id ApplicationId. + * @param[out] flag Output flag, indicating whether out is valid. + * @param[out] out Output value. + */ +Result nsIsApplicationUpdateRequested(u64 application_id, bool *flag, u32 *out); + +/** + * @brief WithdrawApplicationUpdateRequest + * @note Only available on [2.0.0+]. + * @param[in] application_id ApplicationId. + */ +Result nsWithdrawApplicationUpdateRequest(u64 application_id); + +/** + * @brief IsAnyApplicationEntityInstalled + * @note Only available on [2.0.0+]. + * @param[in] application_id ApplicationId. + * @param[out] out Output flag. + */ +Result nsIsAnyApplicationEntityInstalled(u64 application_id, bool *out); + +/** + * @brief CleanupUnavailableAddOnContents + * @note Only available on [6.0.0+]. + * @param[in] application_id ApplicationId. + * @param[in] uid \ref AccountUid + */ +Result nsCleanupUnavailableAddOnContents(u64 application_id, AccountUid uid); + +/** + * @brief FormatSdCard + * @note Only available on [2.0.0+]. + */ +Result nsFormatSdCard(void); + +/** + * @brief NeedsSystemUpdateToFormatSdCard + * @note Only available on [2.0.0+]. + * @param[out] out Output flag. + */ +Result nsNeedsSystemUpdateToFormatSdCard(bool *out); + +/** + * @brief GetLastSdCardFormatUnexpectedResult + * @note Only available on [2.0.0+]. + */ +Result nsGetLastSdCardFormatUnexpectedResult(void); + /** * @brief Generates a \ref NsSystemDeliveryInfo using the currently installed SystemUpdate meta. * @note Only available on [4.0.0+]. @@ -376,6 +665,25 @@ Result nsListNotCommittedContentMeta(NcmContentMetaKey *meta, s32 count, u64 app */ Result nsGetApplicationDeliveryInfoHash(const NsApplicationDeliveryInfo *info, s32 count, u8 *out_hash); +/** + * @brief GetApplicationTerminateResult + * @note Only available on [6.0.0+]. + * @param[in] application_id ApplicationId. + * @param[out] res Output Result. + */ +Result nsGetApplicationTerminateResult(u64 application_id, Result *res); + +///@} + +///@name IRequestServerStopper +///@{ + +/** + * @brief Close a \ref NsRequestServerStopper. + * @param r \ref NsRequestServerStopper + */ +void nsRequestServerStopperClose(NsRequestServerStopper *r); + ///@} ///@name ns:vm diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 8849664f..be77ac0b 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -109,6 +109,35 @@ static Result _nsCmdNoInOutU64(Service* srv, u64 *out, u32 cmd_id) { return serviceDispatchOut(srv, cmd_id, *out); } +static Result _nsCmdInU8U64NoOut(Service* srv, u8 in8, u64 in64, u32 cmd_id) { + const struct { + u8 in8; + u8 pad[7]; + u64 in64; + } in = { in8, {0}, in64 }; + + return serviceDispatchIn(srv, cmd_id, in); +} + +static Result _nsCmdInU64OutStorageIdS64(Service* srv, u64 inval, NcmStorageId *storage_id, s64 *outval, u32 cmd_id) { + struct { + u8 storage_id; + u8 pad[7]; + s64 outval; + } out; + + Result rc = serviceDispatchInOut(srv, cmd_id, inval, out); + if (R_SUCCEEDED(rc)) { + if (storage_id) *storage_id = out.storage_id; + if (outval) *outval = out.outval; + } + return rc; +} + +static Result _nsCmdInUidNoOut(Service* srv, AccountUid uid, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, uid); +} + static Result _nsCmdNoInOutSystemUpdateProgress(Service* srv, NsSystemUpdateProgress *out, u32 cmd_id) { return serviceDispatchOut(srv, cmd_id, *out); } @@ -175,19 +204,187 @@ Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entr ); } -Result nsGetTotalSpaceSize(NcmStorageId storage_id, u64 *size) { - return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 47); +Result nsGetApplicationRecordUpdateSystemEvent(Event* out_event) { + return _nsCmdGetEvent(&g_nsAppManSrv, out_event, true, 2); } -Result nsGetFreeSpaceSize(NcmStorageId storage_id, u64 *size) { - return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 48); +Result nsDeleteApplicationEntity(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 4); +} + +Result nsDeleteApplicationCompletely(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 5); +} + +Result nsDeleteRedundantApplicationEntity(void) { + return _nsCmdNoIO(&g_nsAppManSrv, 7); +} + +Result nsIsApplicationEntityMovable(u64 application_id, NcmStorageId storage_id, bool *out) { + const struct { + u8 storage_id; + u8 pad[7]; + u64 application_id; + } in = { storage_id, {0}, application_id }; + + u8 tmp=0; + Result rc = serviceDispatchInOut(&g_nsAppManSrv, 8, in, tmp); + if (R_SUCCEEDED(rc) && out) *out = tmp & 1; + return rc; +} + +Result nsMoveApplicationEntity(u64 application_id, NcmStorageId storage_id) { + return _nsCmdInU8U64NoOut(&g_nsAppManSrv, storage_id, application_id, 9); +} + +Result nsCancelApplicationDownload(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 32); +} + +Result nsResumeApplicationDownload(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 33); +} + +Result nsCheckApplicationLaunchVersion(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 38); +} + +Result nsCalculateApplicationDownloadRequiredSize(u64 application_id, NcmStorageId *storage_id, s64 *size) { + return _nsCmdInU64OutStorageIdS64(&g_nsAppManSrv, application_id, storage_id, size, 41); +} + +Result nsCleanupSdCard(void) { + return _nsCmdNoIO(&g_nsAppManSrv, 42); +} + +Result nsGetSdCardMountStatusChangedEvent(Event* out_event) { + return _nsCmdGetEvent(&g_nsAppManSrv, out_event, false, 44); +} + +Result nsGetTotalSpaceSize(NcmStorageId storage_id, s64 *size) { + return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, (u64*)size, 47); +} + +Result nsGetFreeSpaceSize(NcmStorageId storage_id, s64 *size) { + return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, (u64*)size, 48); +} + +Result nsGetGameCardUpdateDetectionEvent(Event* out_event) { + return _nsCmdGetEvent(&g_nsAppManSrv, out_event, false, 52); +} + +Result nsDisableApplicationAutoDelete(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 53); +} + +Result nsEnableApplicationAutoDelete(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 54); +} + +Result nsSetApplicationTerminateResult(u64 application_id, Result res) { + const struct { + Result res; + u32 pad; + u64 application_id; + } in = { res, 0, application_id }; + + return serviceDispatchIn(&g_nsAppManSrv, 56, in); +} + +Result nsClearApplicationTerminateResult(u64 application_id) { + return _nsCmdInU64(&g_nsAppManSrv, application_id, 57); +} + +Result nsGetLastSdCardMountUnexpectedResult(void) { + return _nsCmdNoIO(&g_nsAppManSrv, 58); +} + +Result nsGetRequestServerStopper(NsRequestServerStopper *r) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsGetSession(&g_nsAppManSrv, &r->s, 65); +} + +Result nsCancelApplicationApplyDelta(u64 application_id) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdInU64(&g_nsAppManSrv, application_id, 67); +} + +Result nsResumeApplicationApplyDelta(u64 application_id) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdInU64(&g_nsAppManSrv, application_id, 68); +} + +Result nsCalculateApplicationApplyDeltaRequiredSize(u64 application_id, NcmStorageId *storage_id, s64 *size) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdInU64OutStorageIdS64(&g_nsAppManSrv, application_id, storage_id, size, 69); +} + +Result nsResumeAll(void) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&g_nsAppManSrv, 70); +} + +Result nsGetStorageSize(NcmStorageId storage_id, s64 *total_space_size, s64 *free_space_size) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + struct { + s64 total_space_size; + s64 free_space_size; + } out; + + u8 tmp = storage_id; + Result rc = serviceDispatchInOut(&g_nsAppManSrv, 71, tmp, out); + if (R_SUCCEEDED(rc)) { + if (total_space_size) *total_space_size = out.total_space_size; + if (free_space_size) *free_space_size = out.free_space_size; + } + return rc; +} + +Result nsDeleteUserSystemSaveData(AccountUid uid, u64 system_save_data_id) { + const struct { + AccountUid uid; + u64 system_save_data_id; + } in = { uid, system_save_data_id }; + + return serviceDispatchIn(&g_nsAppManSrv, 210, in); +} + +Result nsDeleteSaveData(FsSaveDataSpaceId save_data_space_id, u64 save_data_id) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdInU8U64NoOut(&g_nsAppManSrv, save_data_space_id, save_data_id, 211); +} + +Result nsUnregisterNetworkServiceAccount(AccountUid uid) { + return _nsCmdInUidNoOut(&g_nsAppManSrv, uid, 220); +} + +Result nsUnregisterNetworkServiceAccountWithUserSaveDataDeletion(AccountUid uid) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdInUidNoOut(&g_nsAppManSrv, uid, 221); } Result nsGetApplicationControlData(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u64* actual_size) { const struct { u8 source; + u8 pad[7]; u64 application_id; - } in = { source, application_id }; + } in = { source, {0}, application_id }; u32 tmp=0; @@ -199,11 +396,53 @@ Result nsGetApplicationControlData(NsApplicationControlSource source, u64 applic return rc; } +Result nsGetGameCardMountFailureEvent(Event* out_event) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdGetEvent(&g_nsAppManSrv, out_event, false, 505); +} + +Result nsIsGameCardInserted(bool *out) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoInOutBool(&g_nsAppManSrv, out, 506); +} + +Result nsEnsureGameCardAccess(void) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&g_nsAppManSrv, 507); +} + +Result nsGetLastGameCardMountFailureResult(void) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&g_nsAppManSrv, 508); +} + +Result nsListApplicationIdOnGameCard(u64 *application_ids, s32 count, s32 *total_out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchOut(&g_nsAppManSrv, 509, *total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { application_ids, count*sizeof(u64) } }, + ); +} + Result nsListApplicationContentMetaStatus(u64 application_id, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { s32 index; + u32 pad; u64 application_id; - } in = { index, application_id }; + } in = { index, 0, application_id }; return serviceDispatchInOut(&g_nsAppManSrv, 601, in, *out_entrycount, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, @@ -211,6 +450,81 @@ Result nsListApplicationContentMetaStatus(u64 application_id, s32 index, NsAppli ); } +Result nsTouchApplication(u64 application_id) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdInU64(&g_nsAppManSrv, application_id, 904); +} + +Result nsIsApplicationUpdateRequested(u64 application_id, bool *flag, u32 *out) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + struct { + u8 flag; + u8 pad[3]; + u32 out; + } tmpout; + + Result rc = serviceDispatchInOut(&g_nsAppManSrv, 906, application_id, tmpout); + if (R_SUCCEEDED(rc)) { + if (flag) *flag = tmpout.flag & 1; + if (out) *out = tmpout.out; + } + return rc; +} + +Result nsWithdrawApplicationUpdateRequest(u64 application_id) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdInU64(&g_nsAppManSrv, application_id, 907); +} + +Result nsIsAnyApplicationEntityInstalled(u64 application_id, bool *out) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + u8 tmp=0; + Result rc = serviceDispatchInOut(&g_nsAppManSrv, 1300, application_id, tmp); + if (R_SUCCEEDED(rc) && out) *out = tmp & 1; + return rc; +} + +Result nsCleanupUnavailableAddOnContents(u64 application_id, AccountUid uid) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u64 application_id; + AccountUid uid; + } in = { application_id, uid }; + + return serviceDispatchIn(&g_nsAppManSrv, 1309, in); +} + +Result nsFormatSdCard(void) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&g_nsAppManSrv, 1500); +} + +Result nsNeedsSystemUpdateToFormatSdCard(bool *out) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoInOutBool(&g_nsAppManSrv, out, 1501); +} + +Result nsGetLastSdCardFormatUnexpectedResult(void) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&g_nsAppManSrv, 1502); +} + Result nsGetSystemDeliveryInfo(NsSystemDeliveryInfo *info) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -482,6 +796,19 @@ Result nsGetApplicationDeliveryInfoHash(const NsApplicationDeliveryInfo *info, s return rc; } +Result nsGetApplicationTerminateResult(u64 application_id, Result *res) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchInOut(&g_nsAppManSrv, 2100, application_id, *res); +} + +// IRequestServerStopper + +void nsRequestServerStopperClose(NsRequestServerStopper *r) { + serviceClose(&r->s); +} + // ns:vm NX_GENERATE_SERVICE_GUARD(nsvm); From c4ebdb4cd8382d277616f3a463b33cf690efe4ac Mon Sep 17 00:00:00 2001 From: fincs Date: Wed, 12 Feb 2020 00:47:03 +0100 Subject: [PATCH 3/6] Fix #371 --- nx/include/switch/services/pm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nx/include/switch/services/pm.h b/nx/include/switch/services/pm.h index aec8904a..01985498 100644 --- a/nx/include/switch/services/pm.h +++ b/nx/include/switch/services/pm.h @@ -85,10 +85,10 @@ void pmshellExit(void); Service* pmshellGetServiceSession(void); /// Initialize pm:bm. -Result pmbmInitialize(); +Result pmbmInitialize(void); /// Exit pm:bm. -void pmbmExit(); +void pmbmExit(void); /// Gets the Service object for the actual pm:bm service session. Service* pmbmGetServiceSession(void); From 9bf745524d3198e74f8bdc8e9aba389a91b2ff6c Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sat, 15 Feb 2020 12:32:50 -0500 Subject: [PATCH 4/6] nifm: Added NifmClientId and nifmGetClientId/nifmIsAnyInternetRequestAccepted. --- nx/include/switch/services/nifm.h | 17 +++++++++++++++++ nx/source/services/nifm.c | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/nx/include/switch/services/nifm.h b/nx/include/switch/services/nifm.h index 04d0cc7a..04956209 100644 --- a/nx/include/switch/services/nifm.h +++ b/nx/include/switch/services/nifm.h @@ -28,6 +28,11 @@ typedef enum { NifmInternetConnectionStatus_Connected = 4, ///< Internet is connected. } NifmInternetConnectionStatus; +/// ClientId +typedef struct { + u32 id; ///< ClientId +} NifmClientId; + /// Initialize nifm. This is used automatically by gethostid(). Result nifmInitialize(NifmServiceType service_type); @@ -40,6 +45,11 @@ Service* nifmGetServiceSession_StaticService(void); /// Gets the Service object for IGeneralService. Service* nifmGetServiceSession_GeneralService(void); +/** + * @brief GetClientId + */ +NifmClientId nifmGetClientId(void); + Result nifmGetCurrentIpAddress(u32* out); /** @@ -56,6 +66,13 @@ Result nifmIsWirelessCommunicationEnabled(bool* out); Result nifmGetInternetConnectionStatus(NifmInternetConnectionType* connectionType, u32* wifiStrength, NifmInternetConnectionStatus* connectionStatus); Result nifmIsEthernetCommunicationEnabled(bool* out); + +/** + * @brief IsAnyInternetRequestAccepted + * @param[in] id \ref NifmClientId + */ +bool nifmIsAnyInternetRequestAccepted(NifmClientId id); + Result nifmIsAnyForegroundRequestAccepted(bool* out); Result nifmPutToSleep(void); Result nifmWakeUp(void); diff --git a/nx/source/services/nifm.c b/nx/source/services/nifm.c index d03cbbf0..fcb63e20 100644 --- a/nx/source/services/nifm.c +++ b/nx/source/services/nifm.c @@ -105,6 +105,16 @@ static Result _nifmCreateGeneralService(Service* srv_out) { ); } +NifmClientId nifmGetClientId(void) { + NifmClientId id={0}; + Result rc = serviceDispatch(&g_nifmIGS, 1, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { &id, sizeof(id) } }, + ); + if (R_FAILED(rc)) id.id = 0; + return id; +} + Result nifmGetCurrentIpAddress(u32* out) { return _nifmCmdNoInOutU32(&g_nifmIGS, out, 12); } @@ -141,6 +151,15 @@ Result nifmIsEthernetCommunicationEnabled(bool* out) { return _nifmCmdNoInOutBool(&g_nifmIGS, out, 20); } +bool nifmIsAnyInternetRequestAccepted(NifmClientId id) { + u8 tmp=0; + Result rc = serviceDispatchOut(&g_nifmIGS, 21, tmp, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { &id, sizeof(id) } }, + ); + return R_SUCCEEDED(rc) ? tmp & 1 : 0; +} + Result nifmIsAnyForegroundRequestAccepted(bool* out) { return _nifmCmdNoInOutBool(&g_nifmIGS, out, 22); } From d8d931fe2558293a8e31b247a7cde49298dbd51e Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 16 Feb 2020 21:32:56 -0500 Subject: [PATCH 5/6] ns: Added support for the following cmds: nsRequestApplicationUpdateInfo, nsRequestUpdateApplication2, nsRequestDownloadApplicationControlData, nsRequestCheckGameCardRegistration, nsRequestGameCardRegistrationGoldPoint, nsRequestRegisterGameCard, nsRequestDownloadApplicationPrepurchasedRights, nsRequestNoDownloadRightsErrorResolution, nsRequestResolveNoDownloadRightsError. --- nx/include/switch/services/ns.h | 82 +++++++++++++++++ nx/source/services/ns.c | 157 ++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index fbda2982..12559a82 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -209,6 +209,14 @@ Result nsIsApplicationEntityMovable(u64 application_id, NcmStorageId storage_id, */ Result nsMoveApplicationEntity(u64 application_id, NcmStorageId storage_id); +/** + * @brief RequestApplicationUpdateInfo + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @param[out] a \ref AsyncValue. The data that can be read from this is u8 ApplicationUpdateInfo. qlaunch just checks whether this is 0. + * @param application_id ApplicationId. + */ +Result nsRequestApplicationUpdateInfo(AsyncValue *a, u64 application_id); + /** * @brief CancelApplicationDownload * @param[in] application_id ApplicationId. @@ -343,6 +351,15 @@ Result nsResumeAll(void); */ Result nsGetStorageSize(NcmStorageId storage_id, s64 *total_space_size, s64 *free_space_size); +/** + * @brief RequestUpdateApplication2 + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @note Only available on [4.0.0+]. + * @param[out] a \ref AsyncResult + * @param[in] application_id ApplicationId. + */ +Result nsRequestUpdateApplication2(AsyncResult *a, u64 application_id); + /** * @brief DeleteUserSystemSaveData * @param[in] uid \ref AccountUid @@ -381,6 +398,44 @@ Result nsUnregisterNetworkServiceAccountWithUserSaveDataDeletion(AccountUid uid) */ Result nsGetApplicationControlData(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u64* actual_size); +/** + * @brief RequestDownloadApplicationControlData + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @param[out] a \ref AsyncResult + * @param[in] application_id ApplicationId. + */ +Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_id); + +/** + * @brief RequestCheckGameCardRegistration + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @note Only available on [2.0.0+]. + * @param[out] a \ref AsyncResult + * @param[in] application_id ApplicationId. + */ +Result nsRequestCheckGameCardRegistration(AsyncResult *a, u64 application_id); + +/** + * @brief RequestGameCardRegistrationGoldPoint + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @note Only available on [2.0.0+]. + * @param[out] a \ref AsyncValue. The data that can be read from this is 4-bytes. + * @param[in] uid \ref AccountUid + * @param[in] application_id ApplicationId. + */ +Result nsRequestGameCardRegistrationGoldPoint(AsyncValue *a, AccountUid uid, u64 application_id); + +/** + * @brief RequestRegisterGameCard + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @note Only available on [2.0.0+]. + * @param[out] a \ref AsyncResult + * @param[in] uid \ref AccountUid + * @param[in] application_id ApplicationId. + * @param[in] inval Input value. + */ +Result nsRequestRegisterGameCard(AsyncResult *a, AccountUid uid, u64 application_id, s32 inval); + /** * @brief GetGameCardMountFailureEvent * @note The Event must be closed by the user once finished with it. @@ -486,6 +541,15 @@ Result nsNeedsSystemUpdateToFormatSdCard(bool *out); */ Result nsGetLastSdCardFormatUnexpectedResult(void); +/** + * @brief RequestDownloadApplicationPrepurchasedRights + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @note Only available on [4.0.0+]. + * @param[out] a \ref AsyncResult + * @param[in] application_id ApplicationId. + */ +Result nsRequestDownloadApplicationPrepurchasedRights(AsyncResult *a, u64 application_id); + /** * @brief Generates a \ref NsSystemDeliveryInfo using the currently installed SystemUpdate meta. * @note Only available on [4.0.0+]. @@ -673,6 +737,24 @@ Result nsGetApplicationDeliveryInfoHash(const NsApplicationDeliveryInfo *info, s */ Result nsGetApplicationTerminateResult(u64 application_id, Result *res); +/** + * @brief RequestNoDownloadRightsErrorResolution + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @note Only available on [9.0.0+]. + * @param[out] a \ref AsyncValue. The data that can be read from this is u8 NoDownloadRightsErrorResolution. + * @param application_id ApplicationId. + */ +Result nsRequestNoDownloadRightsErrorResolution(AsyncValue *a, u64 application_id); + +/** + * @brief RequestResolveNoDownloadRightsError + * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. + * @note Only available on [9.0.0+]. + * @param[out] a \ref AsyncValue. The data that can be read from this is u8 NoDownloadRightsErrorResolution. + * @param application_id ApplicationId. + */ +Result nsRequestResolveNoDownloadRightsError(AsyncValue *a, u64 application_id); + ///@} ///@name IRequestServerStopper diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index be77ac0b..3fa3b530 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -4,6 +4,7 @@ #include "runtime/hosversion.h" #include "services/ns.h" #include "services/async.h" +#include "services/nifm.h" static Service g_nsAppManSrv, g_nsGetterSrv; static Service g_nsvmSrv; @@ -197,6 +198,42 @@ static Result _nsCmdNoInOutAsyncResult(Service* srv, AsyncResult *a, u32 cmd_id) return rc; } +static Result _nsCmdInU64OutAsyncValue(Service* srv, AsyncValue *a, u64 inval, u32 cmd_id) { + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + Result rc = serviceDispatchIn(srv, cmd_id, inval, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + return rc; +} + +static Result _nsCmdInU64OutAsyncResult(Service* srv, AsyncResult *a, u64 inval, u32 cmd_id) { + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + Result rc = serviceDispatchIn(srv, cmd_id, inval, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + return rc; +} + +static Result _nsCheckNifm(void) { + return nifmIsAnyInternetRequestAccepted(nifmGetClientId()) ? 0 : MAKERESULT(16, 340); +} + Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount) { return serviceDispatchInOut(&g_nsAppManSrv, 0, entry_offset, *out_entrycount, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, @@ -237,6 +274,13 @@ Result nsMoveApplicationEntity(u64 application_id, NcmStorageId storage_id) { return _nsCmdInU8U64NoOut(&g_nsAppManSrv, storage_id, application_id, 9); } +Result nsRequestApplicationUpdateInfo(AsyncValue *a, u64 application_id) { + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + return _nsCmdInU64OutAsyncValue(&g_nsAppManSrv, a, application_id, 30); +} + Result nsCancelApplicationDownload(u64 application_id) { return _nsCmdInU64(&g_nsAppManSrv, application_id, 32); } @@ -352,6 +396,16 @@ Result nsGetStorageSize(NcmStorageId storage_id, s64 *total_space_size, s64 *fre return rc; } +Result nsRequestUpdateApplication2(AsyncResult *a, u64 application_id) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + return _nsCmdInU64OutAsyncResult(&g_nsAppManSrv, a, application_id, 85); +} + Result nsDeleteUserSystemSaveData(AccountUid uid, u64 system_save_data_id) { const struct { AccountUid uid; @@ -396,6 +450,79 @@ Result nsGetApplicationControlData(NsApplicationControlSource source, u64 applic return rc; } +Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_id) { + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + return _nsCmdInU64OutAsyncResult(&g_nsAppManSrv, a, application_id, 402); +} + +Result nsRequestCheckGameCardRegistration(AsyncResult *a, u64 application_id) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + return _nsCmdInU64OutAsyncResult(&g_nsAppManSrv, a, application_id, 502); +} + +Result nsRequestGameCardRegistrationGoldPoint(AsyncValue *a, AccountUid uid, u64 application_id) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + const struct { + AccountUid uid; + u64 application_id; + } in = { uid, application_id }; + + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + rc = serviceDispatchIn(&g_nsAppManSrv, 503, in, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + return rc; +} + +Result nsRequestRegisterGameCard(AsyncResult *a, AccountUid uid, u64 application_id, s32 inval) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + const struct { + s32 inval; + u32 pad; + AccountUid uid; + u64 application_id; + } in = { inval, 0, uid, application_id }; + + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + rc = serviceDispatchIn(&g_nsAppManSrv, 504, in, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + return rc; +} + Result nsGetGameCardMountFailureEvent(Event* out_event) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -525,6 +652,16 @@ Result nsGetLastSdCardFormatUnexpectedResult(void) { return _nsCmdNoIO(&g_nsAppManSrv, 1502); } +Result nsRequestDownloadApplicationPrepurchasedRights(AsyncResult *a, u64 application_id) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + return _nsCmdInU64OutAsyncResult(&g_nsAppManSrv, a, application_id, 1901); +} + Result nsGetSystemDeliveryInfo(NsSystemDeliveryInfo *info) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -803,6 +940,26 @@ Result nsGetApplicationTerminateResult(u64 application_id, Result *res) { return serviceDispatchInOut(&g_nsAppManSrv, 2100, application_id, *res); } +Result nsRequestNoDownloadRightsErrorResolution(AsyncValue *a, u64 application_id) { + if (hosversionBefore(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + return _nsCmdInU64OutAsyncValue(&g_nsAppManSrv, a, application_id, 2351); +} + +Result nsRequestResolveNoDownloadRightsError(AsyncValue *a, u64 application_id) { + if (hosversionBefore(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc = _nsCheckNifm(); + if (R_FAILED(rc)) return rc; + + return _nsCmdInU64OutAsyncValue(&g_nsAppManSrv, a, application_id, 2352); +} + // IRequestServerStopper void nsRequestServerStopperClose(NsRequestServerStopper *r) { From c570cd0a2fdca092eca1796820afffa65b86c92e Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 17 Feb 2020 15:46:02 -0500 Subject: [PATCH 6/6] ns: Added NsApplicationRightsOnClient/nsGetApplicationRightsOnClient(). --- nx/include/switch/services/ns.h | 21 +++++++++++++++++++++ nx/source/services/ns.c | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 12559a82..77c879b8 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -143,6 +143,15 @@ typedef struct { u8 hmac[0x20]; ///< HMAC-SHA256 over the above data. } NsApplicationDeliveryInfo; +/// NsApplicationRightsOnClient +typedef struct { + u64 application_id; ///< ApplicationId. + AccountUid uid; ///< \ref AccountUid + u8 flags_x18; ///< qlaunch uses bit0-bit4 and bit7 from here. + u8 flags_x19; ///< qlaunch uses bit0 from here. + u8 unk_x1a[0x6]; ///< Unknown. +} NsApplicationRightsOnClient; + /// Default size for \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater. This is the size used by qlaunch for SetupCardUpdate. #define NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT 0x100000 @@ -737,6 +746,18 @@ Result nsGetApplicationDeliveryInfoHash(const NsApplicationDeliveryInfo *info, s */ Result nsGetApplicationTerminateResult(u64 application_id, Result *res); +/** + * @brief GetApplicationRightsOnClient + * @note Only available on [6.0.0+]. + * @param[out] rights Output array of \ref NsApplicationRightsOnClient. + * @param[in] count Size of the rights array in entries. qlaunch uses value 3 for this. + * @param[in] application_id ApplicationId + * @param[in] uid \ref AccountUid, can optionally be all-zero. + * @param[in] flags Flags. Official sw hard-codes this to value 0x3. + * @param[out] total_out Total output entries. + */ +Result nsGetApplicationRightsOnClient(NsApplicationRightsOnClient *rights, s32 count, u64 application_id, AccountUid uid, u32 flags, s32 *total_out); + /** * @brief RequestNoDownloadRightsErrorResolution * @note \ref nifmInitialize must be used prior to this. Before using the cmd, this calls \ref nifmIsAnyInternetRequestAccepted with the output from \ref nifmGetClientId, an error is returned when that returns false. diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 3fa3b530..35ac9c4f 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -940,6 +940,23 @@ Result nsGetApplicationTerminateResult(u64 application_id, Result *res) { return serviceDispatchInOut(&g_nsAppManSrv, 2100, application_id, *res); } +Result nsGetApplicationRightsOnClient(NsApplicationRightsOnClient *rights, s32 count, u64 application_id, AccountUid uid, u32 flags, s32 *total_out) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u32 flags; + u32 pad; + u64 application_id; + AccountUid uid; + } in = { flags, 0, application_id, uid }; + + return serviceDispatchInOut(&g_nsAppManSrv, 2050, in, *total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { rights, count*sizeof(NsApplicationRightsOnClient) } }, + ); +} + Result nsRequestNoDownloadRightsErrorResolution(AsyncValue *a, u64 application_id) { if (hosversionBefore(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);