mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Added support for NsProgressAsyncResult and nsRequestVerifyAddOnContentsRights/nsRequestVerifyApplication. Updated docs.
This commit is contained in:
parent
d8a50a46cf
commit
129b3a95b8
@ -64,6 +64,7 @@ Result asyncValueCancel(AsyncValue *a);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the \ref ErrorContext.
|
* @brief Gets the \ref ErrorContext.
|
||||||
|
* @note Only available on [4.0.0+].
|
||||||
* @param a \ref AsyncValue
|
* @param a \ref AsyncValue
|
||||||
* @param[out] context \ref ErrorContext
|
* @param[out] context \ref ErrorContext
|
||||||
*/
|
*/
|
||||||
@ -104,6 +105,7 @@ Result asyncResultCancel(AsyncResult *a);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the \ref ErrorContext.
|
* @brief Gets the \ref ErrorContext.
|
||||||
|
* @note Only available on [4.0.0+].
|
||||||
* @param a \ref AsyncResult
|
* @param a \ref AsyncResult
|
||||||
* @param[out] context \ref ErrorContext
|
* @param[out] context \ref ErrorContext
|
||||||
*/
|
*/
|
||||||
|
@ -51,6 +51,12 @@ typedef struct {
|
|||||||
Service s; ///< IRequestServerStopper
|
Service s; ///< IRequestServerStopper
|
||||||
} NsRequestServerStopper;
|
} NsRequestServerStopper;
|
||||||
|
|
||||||
|
/// ProgressAsyncResult
|
||||||
|
typedef struct {
|
||||||
|
Service s; ///< IProgressAsyncResult
|
||||||
|
Event event; ///< Event with autoclear=false.
|
||||||
|
} NsProgressAsyncResult;
|
||||||
|
|
||||||
/// SystemUpdateControl
|
/// SystemUpdateControl
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Service s; ///< ISystemUpdateControl
|
Service s; ///< ISystemUpdateControl
|
||||||
@ -120,7 +126,7 @@ typedef struct {
|
|||||||
u64 end_timestamp; ///< POSIX timestamp for the promotion end.
|
u64 end_timestamp; ///< POSIX timestamp for the promotion end.
|
||||||
s64 remaining_time; ///< Remaining time until the promotion ends, in nanoseconds ({end_timestamp - current_time} converted to nanoseconds).
|
s64 remaining_time; ///< Remaining time until the promotion ends, in nanoseconds ({end_timestamp - current_time} converted to nanoseconds).
|
||||||
u8 unk_x18[0x4]; ///< Not set, left at zero.
|
u8 unk_x18[0x4]; ///< Not set, left at zero.
|
||||||
u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear: remaining_time is set.
|
u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear: remaining_time is set.
|
||||||
u8 pad[3]; ///< Padding.
|
u8 pad[3]; ///< Padding.
|
||||||
} NsPromotionInfo;
|
} NsPromotionInfo;
|
||||||
|
|
||||||
@ -572,6 +578,25 @@ Result nsIsApplicationUpdateRequested(u64 application_id, bool *flag, u32 *out);
|
|||||||
*/
|
*/
|
||||||
Result nsWithdrawApplicationUpdateRequest(u64 application_id);
|
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
|
* @brief IsAnyApplicationEntityInstalled
|
||||||
* @note Only available on [2.0.0+].
|
* @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
|
///@name ns:vm
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
|
@ -622,6 +622,86 @@ Result nsWithdrawApplicationUpdateRequest(u64 application_id) {
|
|||||||
return _nsCmdInU64(&g_nsAppManSrv, application_id, 907);
|
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) {
|
Result nsIsAnyApplicationEntityInstalled(u64 application_id, bool *out) {
|
||||||
if (hosversionBefore(2,0,0))
|
if (hosversionBefore(2,0,0))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
@ -1058,6 +1138,70 @@ void nsRequestServerStopperClose(NsRequestServerStopper *r) {
|
|||||||
serviceClose(&r->s);
|
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
|
// ns:vm
|
||||||
|
|
||||||
NX_GENERATE_SERVICE_GUARD(nsvm);
|
NX_GENERATE_SERVICE_GUARD(nsvm);
|
||||||
|
Loading…
Reference in New Issue
Block a user