From 7822accc226db5302aff649b423bc4b4161df489 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Fri, 28 Feb 2020 20:08:08 -0500 Subject: [PATCH] ns: Added nsGetReadOnlyApplicationControlDataInterface. Use IReadOnlyApplicationControlDataInterface with nsGetApplicationControlData when needed. --- nx/include/switch/services/ns.h | 30 ++++++++++++------ nx/source/services/ns.c | 55 +++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 31fd597e..11ca6784 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -244,6 +244,10 @@ Service* nsGetServiceSession_GetterInterface(void); /// Gets the Service object for IApplicationManagerInterface. Service* nsGetServiceSession_ApplicationManagerInterface(void); +/// Gets the Service object for IReadOnlyApplicationControlDataInterface via the cmd for that. +/// Only available on [5.1.0+]. +Result nsGetReadOnlyApplicationControlDataInterface(Service* srv_out); + /// Gets the Service object for IECommerceInterface via the cmd for that. /// Only available on [4.0.0+]. Result nsGetECommerceInterface(Service* srv_out); @@ -262,6 +266,22 @@ Result nsGetContentManagementInterface(Service* srv_out); ///@} +///@name IReadOnlyApplicationControlDataInterface +///@{ + +/** + * @brief Gets the \ref NsApplicationControlData for the specified application. + * @note Uses \ref nsGetReadOnlyApplicationControlDataInterface on [5.1.0+], otherwise IApplicationManagerInterface is used. + * @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); + +///@} + ///@name IECommerceInterface ///@{ @@ -560,16 +580,6 @@ Result nsUnregisterNetworkServiceAccount(AccountUid uid); */ Result nsUnregisterNetworkServiceAccountWithUserSaveDataDeletion(AccountUid uid); -/** - * @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 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. diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 076e648f..3a665891 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -46,6 +46,13 @@ Service* nsGetServiceSession_ApplicationManagerInterface(void) { return &g_nsAppManSrv; } +Result nsGetReadOnlyApplicationControlDataInterface(Service* srv_out) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsGetSession(&g_nsGetterSrv, srv_out, 7989); +} + Result nsGetECommerceInterface(Service* srv_out) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -278,6 +285,37 @@ static Result _nsCheckNifm(void) { return nifmIsAnyInternetRequestAccepted(nifmGetClientId()) ? 0 : MAKERESULT(16, 340); } +// IReadOnlyApplicationControlDataInterface + +Result nsGetApplicationControlData(NsApplicationControlSource source, u64 application_id, NsApplicationControlData* buffer, size_t size, u64* actual_size) { + Service srv={0}, *srv_ptr = &srv; + Result rc=0; + u32 cmd_id = 400; + if (hosversionAtLeast(5,1,0)) { + rc = nsGetReadOnlyApplicationControlDataInterface(&srv); + cmd_id = 0; + } + else + srv_ptr = &g_nsAppManSrv; + + const struct { + u8 source; + u8 pad[7]; + u64 application_id; + } in = { source, {0}, application_id }; + + u32 tmp=0; + + if (R_SUCCEEDED(rc)) rc = serviceDispatchInOut(srv_ptr, cmd_id, in, tmp, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); + if (R_SUCCEEDED(rc) && actual_size) *actual_size = tmp; + + serviceClose(&srv); + return rc; +} + // IECommerceInterface Result nsRequestLinkDevice(AsyncResult *a, AccountUid uid) { @@ -611,23 +649,6 @@ Result nsUnregisterNetworkServiceAccountWithUserSaveDataDeletion(AccountUid uid) 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, {0}, application_id }; - - u32 tmp=0; - - Result rc = serviceDispatchInOut(&g_nsAppManSrv, 400, in, tmp, - .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { buffer, size } }, - ); - if (R_SUCCEEDED(rc) && actual_size) *actual_size = tmp; - return rc; -} - Result nsRequestDownloadApplicationControlData(AsyncResult *a, u64 application_id) { Result rc = _nsCheckNifm(); if (R_FAILED(rc)) return rc;