Added support for NsProgressAsyncResult and nsRequestVerifyAddOnContentsRights/nsRequestVerifyApplication. Updated docs.

This commit is contained in:
yellows8 2020-02-20 22:17:13 -05:00
parent d8a50a46cf
commit 129b3a95b8
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
3 changed files with 227 additions and 1 deletions

View File

@ -64,6 +64,7 @@ Result asyncValueCancel(AsyncValue *a);
/**
* @brief Gets the \ref ErrorContext.
* @note Only available on [4.0.0+].
* @param a \ref AsyncValue
* @param[out] context \ref ErrorContext
*/
@ -104,6 +105,7 @@ Result asyncResultCancel(AsyncResult *a);
/**
* @brief Gets the \ref ErrorContext.
* @note Only available on [4.0.0+].
* @param a \ref AsyncResult
* @param[out] context \ref ErrorContext
*/

View File

@ -51,6 +51,12 @@ typedef struct {
Service s; ///< IRequestServerStopper
} NsRequestServerStopper;
/// ProgressAsyncResult
typedef struct {
Service s; ///< IProgressAsyncResult
Event event; ///< Event with autoclear=false.
} NsProgressAsyncResult;
/// SystemUpdateControl
typedef struct {
Service s; ///< ISystemUpdateControl
@ -572,6 +578,25 @@ Result nsIsApplicationUpdateRequested(u64 application_id, bool *flag, u32 *out);
*/
Result nsWithdrawApplicationUpdateRequest(u64 application_id);
/**
* @brief RequestVerifyAddOnContentsRights
* @note Only available on [3.0.0+].
* @param[out] a \ref NsProgressAsyncResult
* @param[in] application_id ApplicationId.
*/
Result nsRequestVerifyAddOnContentsRights(NsProgressAsyncResult *a, u64 application_id);
/**
* @brief RequestVerifyApplication
* @note On pre-5.0.0 this uses cmd RequestVerifyApplicationDeprecated, otherwise cmd RequestVerifyApplication is used.
* @param[out] a \ref NsProgressAsyncResult. The data available with \ref nsProgressAsyncResultGetProgress is basically the same as \ref NsSystemUpdateProgress.
* @param[in] application_id ApplicationId.
* @param[in] unk Unknown. A default value of 0x7 can be used (which is what qlaunch uses). Only used on [5.0.0+].
* @param buffer 0x1000-byte aligned buffer for TransferMemory. This buffer must not be accessed until the async operation finishes.
* @param[in] size 0x1000-byte aligned buffer size for TransferMemory. qlaunch uses size 0x100000.
*/
Result nsRequestVerifyApplication(NsProgressAsyncResult *a, u64 application_id, u32 unk, void* buffer, size_t size);
/**
* @brief IsAnyApplicationEntityInstalled
* @note Only available on [2.0.0+].
@ -881,6 +906,61 @@ void nsRequestServerStopperClose(NsRequestServerStopper *r);
///@}
///@name IProgressAsyncResult
///@{
/**
* @brief Close a \ref NsProgressAsyncResult.
* @note When the object is initialized, this uses \ref nsProgressAsyncResultCancel then \ref nsProgressAsyncResultWait with timeout=U64_MAX.
* @param a \ref NsProgressAsyncResult
*/
void nsProgressAsyncResultClose(NsProgressAsyncResult *a);
/**
* @brief Waits for the async operation to finish using the specified timeout.
* @param a \ref NsProgressAsyncResult
* @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout.
*/
Result nsProgressAsyncResultWait(NsProgressAsyncResult *a, u64 timeout);
/**
* @brief Gets the Result.
* @note Prior to using the cmd, this uses \ref nsProgressAsyncResultWait with timeout=U64_MAX.
* @param a \ref NsProgressAsyncResult
*/
Result nsProgressAsyncResultGet(NsProgressAsyncResult *a);
/**
* @brief Cancels the async operation.
* @note Used automatically by \ref nsProgressAsyncResultClose.
* @param a \ref NsProgressAsyncResult
*/
Result nsProgressAsyncResultCancel(NsProgressAsyncResult *a);
/**
* @brief Gets the progress.
* @param a \ref NsProgressAsyncResult
* @param[out] buffer Output buffer.
* @param[in] size Output buffer size.
*/
Result nsProgressAsyncResultGetProgress(NsProgressAsyncResult *a, void* buffer, size_t size);
/**
* @brief GetDetailResult
* @param a \ref NsProgressAsyncResult
*/
Result nsProgressAsyncResultGetDetailResult(NsProgressAsyncResult *a);
/**
* @brief Gets the \ref ErrorContext.
* @note Only available on [4.0.0+].
* @param a \ref NsProgressAsyncResult
* @param[out] context \ref ErrorContext
*/
Result nsProgressAsyncResultGetErrorContext(NsProgressAsyncResult *a, ErrorContext *context);
///@}
///@name ns:vm
///@{

View File

@ -622,6 +622,86 @@ Result nsWithdrawApplicationUpdateRequest(u64 application_id) {
return _nsCmdInU64(&g_nsAppManSrv, application_id, 907);
}
static Result _nsRequestVerifyApplicationDeprecated(NsProgressAsyncResult *a, u64 application_id, TransferMemory *tmem) {
const struct {
u64 application_id;
u64 size;
} in = { application_id, tmem->size };
memset(a, 0, sizeof(*a));
Handle event = INVALID_HANDLE;
Result rc = serviceDispatchIn(&g_nsAppManSrv, 1000, in,
.in_num_handles = 1,
.in_handles = { tmem->handle },
.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 _nsRequestVerifyApplication(NsProgressAsyncResult *a, u64 application_id, u32 unk, TransferMemory *tmem) { // [5.0.0+]
const struct {
u32 unk;
u32 pad;
u64 application_id;
u64 size;
} in = { unk, 0, application_id, tmem->size };
memset(a, 0, sizeof(*a));
Handle event = INVALID_HANDLE;
Result rc = serviceDispatchIn(&g_nsAppManSrv, 1003, in,
.in_num_handles = 1,
.in_handles = { tmem->handle },
.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 nsRequestVerifyAddOnContentsRights(NsProgressAsyncResult *a, u64 application_id) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
memset(a, 0, sizeof(*a));
Handle event = INVALID_HANDLE;
Result rc = serviceDispatchIn(&g_nsAppManSrv, 1002, application_id,
.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 nsRequestVerifyApplication(NsProgressAsyncResult *a, u64 application_id, u32 unk, void* buffer, size_t size) {
Result rc=0;
TransferMemory tmem={0};
rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_None);
if (R_SUCCEEDED(rc)) {
if (hosversionBefore(5,0,0))
rc = _nsRequestVerifyApplicationDeprecated(a, application_id, &tmem);
else
rc = _nsRequestVerifyApplication(a, application_id, unk, &tmem);
}
tmemClose(&tmem);
return rc;
}
Result nsIsAnyApplicationEntityInstalled(u64 application_id, bool *out) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
@ -1058,6 +1138,70 @@ void nsRequestServerStopperClose(NsRequestServerStopper *r) {
serviceClose(&r->s);
}
// IProgressAsyncResult
void nsProgressAsyncResultClose(NsProgressAsyncResult *a) {
if (serviceIsActive(&a->s)) {
nsProgressAsyncResultCancel(a); // Official sw ignores rc from this prior to waiting on the event.
nsProgressAsyncResultWait(a, U64_MAX);
}
serviceClose(&a->s);
eventClose(&a->event);
}
Result nsProgressAsyncResultWait(NsProgressAsyncResult *a, u64 timeout) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return eventWait(&a->event, timeout);
}
Result nsProgressAsyncResultGet(NsProgressAsyncResult *a) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
Result rc = nsProgressAsyncResultWait(a, U64_MAX);
if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(&a->s, 0);
return rc;
}
Result nsProgressAsyncResultCancel(NsProgressAsyncResult *a) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoIO(&a->s, 1);
}
Result nsProgressAsyncResultGetProgress(NsProgressAsyncResult *a, void* buffer, size_t size) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return serviceDispatch(&a->s, 2,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { buffer, size } },
);
}
Result nsProgressAsyncResultGetDetailResult(NsProgressAsyncResult *a) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoIO(&a->s, 3);
}
Result nsProgressAsyncResultGetErrorContext(NsProgressAsyncResult *a, ErrorContext *context) {
if (!serviceIsActive(&a->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatch(&a->s, 4,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { context, sizeof(*context) } },
);
}
// ns:vm
NX_GENERATE_SERVICE_GUARD(nsvm);