Make results, account, service compile

This commit is contained in:
Joey Yakimowich-Payne 2022-12-09 20:58:14 -07:00
commit f11006b4dd
No known key found for this signature in database
GPG key ID: 6BFE655FA5ABD1E1
6 changed files with 132 additions and 155 deletions

4
.gitignore vendored
View file

@ -1,3 +1,7 @@
*
!*/
!*.*
nimcache/
# Swap
[._]*.s[a-v][a-z]

View file

@ -1,7 +1,7 @@
import strutils
import libnx/wrapper/acc
import libnx/wrapper/switch/services/acc
import libnx/results
import libnx/wrapper/types
import libnx/wrapper/switch/types
import libnx/ext/integer128
import libnx/service
import libnx/utils
@ -19,7 +19,7 @@ type
AccountImageLoadError* = object of AccountError
User* = ref object
id*: u128
id*: AccountUid
selected*: bool
username*: string
lastEdited*: uint64
@ -32,24 +32,28 @@ type
AccountImage* = ref object
data: seq[uint8]
imageSize: int
imageSize: U32
export AccountUid
export AccountServiceType
var enabled = false
proc getService*(): Service =
let serv = accountGetService()[]
let serv = accountGetServiceSession()[]
result = newService(serv)
proc init() =
proc init(ty: AccountServiceType) =
## Initializes the account service. Should not
## be used in client code
let service = getService()
if service.isActive:
return
let code = accountInitialize().newResult
let code = accountInitialize(ty).newResult
if code.failed:
raiseEx(
AccountInitError,
@ -84,7 +88,7 @@ proc ensureEnabled() =
proc getImageSize*(profile: AccountProfile): int =
ensureEnabled()
var res = 0.csize
var res = 0.U32
result = 0
let code = accountProfileGetImageSize(profile.unsafeAddr, res.addr).newResult
if code.failed:
@ -92,19 +96,19 @@ proc getImageSize*(profile: AccountProfile): int =
result = res.int
proc imageSize*(user: User): int =
proc imageSize*(user: User): csize_t =
ensureEnabled()
var prof: AccountProfile
var size: csize
var size: U32
let res = accountProfileGetImageSize(prof.addr, size.addr).newResult
if res.failed:
raiseEx(AccountImageSizeError, "Error, could not get image size", res)
result = size.int
result = size.csize_t
proc getProfileHelper(userID: u128): AccountProfile =
proc getProfileHelper(userID: AccountUid): AccountProfile =
let res = accountGetProfile(result.addr, userID).newResult
if res.failed:
@ -115,7 +119,6 @@ proc loadImage*(user: User): AccountImage =
ensureEnabled()
result = new(AccountImage)
let imSize = user.imageSize()
var size: csize
var prof = getProfileHelper(user.id)
@ -137,7 +140,7 @@ proc userID*(user: User): string =
$user.id
proc getUser*(userID: u128): User =
proc getUser*(userID: AccountUid): User =
ensureEnabled()
result = new(User)
@ -154,7 +157,7 @@ proc getUser*(userID: u128): User =
if res.failed:
raiseEx(AccountUserDataError, "Error, could not get user data", res)
result.username = profBase.username.join("")
result.username = profBase.nickname.join("")
result.lastEdited = profBase.lastEditTimestamp
result.iconID = userData.iconID
result.iconBgColorID = userData.iconBackgroundColorID
@ -167,19 +170,15 @@ proc getActiveUser*(): User =
ensureEnabled()
result = new(User)
var
userID: u128 = newUInt128(0,0)
selected: bool
userID: AccountUid
var res = accountGetActiveUser(userID.addr, selected.addr).newResult
var res = accountGetPreselectedUser(userID.addr).newResult
if res.failed:
raiseEx(AccountActiveUserError, "Error, could not get active user ID", res)
if not selected:
raiseEx(AccountUserNotSelectedError, "No user currently selected!")
result.id = userID
result.selected = selected
result.selected = true
var
prof: AccountProfile = getProfileHelper(userID)
@ -191,7 +190,7 @@ proc getActiveUser*(): User =
if res.failed:
raiseEx(AccountUserDataError, "Error, could not get user data", res)
result.username = profBase.username.join("")
result.username = profBase.nickname.join("")
result.lastEdited = profBase.lastEditTimestamp
result.iconID = userData.iconID
result.iconBgColorID = userData.iconBackgroundColorID
@ -235,8 +234,8 @@ proc listAllUsers*(): seq[User] =
result = @[]
var
userIDs: array[ACC_USER_LIST_SIZE, u128]
usersReturned: csize
userIDs: array[ACC_USER_LIST_SIZE, AccountUid]
usersReturned: S32
let res = accountListAllUsers(
userIDs[0].addr,

View file

@ -1,7 +1,6 @@
import strutils
import
libnx/wrapper/result,
libnx/wrapper/types
libnx/wrapper/switch/result
type
@ -83,8 +82,8 @@ type
IoctlFailed #///< Maps to Nvidia: 0x3000F
proc succeeded*(res: Result): bool = res.code.R_SUCCEEDED
proc failed*(res: Result): bool = res.code.R_FAILED
proc succeeded*(res: Result): bool {.inline.} = res.code.r_SUCCEEDED
proc failed*(res: Result): bool {.inline.} = res.code.r_FAILED
proc newResult*(code: uint32): Result =
## Create a result from a libnx error code for friendlier syntax.
@ -92,12 +91,12 @@ proc newResult*(code: uint32): Result =
result.code = code
let moduleCode = code.R_MODULE
let moduleCode = code.r_MODULE
let module = Module(moduleCode)
result.kind = module
let descCode = code.R_DESCRIPTION
let descCode = code.r_DESCRIPTION
var error = "Unknown error: module: $# description: $#" %
[$moduleCode, $descCode]

View file

@ -1,17 +1,18 @@
import
libnx/results,
libnx/wrapper/sm
libnx/wrapper/switch/services/sm,
libnx/wrapper/switch/sf/service,
libnx/wrapper/switch/types
from libnx/wrapper/types import Handle
type
Service* = ref object
serv: sm.Service
serv: service.Service
proc getSmService*(serv: Service): sm.Service =
proc getSmService*(serv: Service): service.Service =
serv.serv
proc newService*(serv: sm.Service): Service =
proc newService*(serv: service.Service): Service =
result = Service(serv: serv)
proc isOverride*(service: Service): bool =
@ -54,24 +55,6 @@ proc objectId*(service: Service): uint32 =
##
serviceGetObjectId(service.serv.addr)
proc close*(service: Service; objectId: uint32): Result =
## *
## @brief Closes a domain object by ID.
## @param[in] s Service object, necessarily a domain or domain subservice.
## @param object_id ID of the object to close.
## @return Result code.
##
serviceCloseObjectById(service.serv.addr, objectId).newResult
proc ipcDispatch*(service: Service): Result =
## *
## @brief Dispatches an IPC request to a service.
## @param[in] s Service object.
## @return Result code.
##
serviceIpcDispatch(service.serv.addr).newResult
proc createService*(handle: Handle): Service =
## *
## @brief Creates a service object from an IPC session handle.
@ -91,7 +74,7 @@ proc createDomainSubservice*(parent: Service; objectId: uint32): Service =
result = new(Service)
serviceCreateDomainSubservice(result.serv.addr, parent.serv.addr, objectId)
proc convertToDomain*(service: Service): Result =
proc convertToDomain*(service: Service): results.Result =
## *
## @brief Converts a regular service to a domain.
## @param[in] s Service object.

View file

@ -59,22 +59,23 @@ type
AccountNetworkServiceAccountId* {.bycopy.} = object
id*: U64 ## /< Id.
## / Initialize account.
proc accountInitialize*(serviceType: AccountServiceType): Result {.cdecl,
importc: "accountInitialize".}
## / Exit account.
## / Initialize account.
proc accountExit*() {.cdecl, importc: "accountExit".}
## / Gets the Service object for the actual account service session.
## / Exit account.
proc accountGetServiceSession*(): ptr Service {.cdecl,
importc: "accountGetServiceSession".}
## / Get the total number of user profiles.
## / Gets the Service object for the actual account service session.
proc accountGetUserCount*(userCount: ptr S32): Result {.cdecl,
importc: "accountGetUserCount".}
## / Get the total number of user profiles.
proc accountListAllUsers*(uids: ptr AccountUid; maxUids: S32; actualTotal: ptr S32): Result {.
cdecl, importc: "accountListAllUsers".}
## *
## @brief Get a list of all userIds. The returned list will never be larger than ACC_USER_LIST_SIZE.
## @param uids Pointer to array of userIds.
@ -82,52 +83,50 @@ proc accountGetUserCount*(userCount: ptr S32): Result {.cdecl,
## @param actual_total The actual total number of userIds found.
##
proc accountListAllUsers*(uids: ptr AccountUid; maxUids: S32; actualTotal: ptr S32): Result {.
cdecl, importc: "accountListAllUsers".}
## / Get the userId for the last opened user.
proc accountGetLastOpenedUser*(uid: ptr AccountUid): Result {.cdecl,
importc: "accountGetLastOpenedUser".}
## / Get an AccountProfile for the specified userId.
## / Get the userId for the last opened user.
proc accountGetProfile*(`out`: ptr AccountProfile; uid: AccountUid): Result {.cdecl,
importc: "accountGetProfile".}
## / IsUserRegistrationRequestPermitted
## / Get an AccountProfile for the specified userId.
proc accountIsUserRegistrationRequestPermitted*(`out`: ptr bool): Result {.cdecl,
importc: "accountIsUserRegistrationRequestPermitted".}
## / TrySelectUserWithoutInteraction
## / IsUserRegistrationRequestPermitted
proc accountTrySelectUserWithoutInteraction*(uid: ptr AccountUid;
isNetworkServiceAccountRequired: bool): Result {.cdecl,
importc: "accountTrySelectUserWithoutInteraction".}
## / Close the AccountProfile.
## / TrySelectUserWithoutInteraction
proc accountProfileClose*(profile: ptr AccountProfile) {.cdecl,
importc: "accountProfileClose".}
## / Get \ref AccountUserData and \ref AccountProfileBase for the specified profile, userdata is optional (can be NULL).
## / Close the AccountProfile.
proc accountProfileGet*(profile: ptr AccountProfile; userdata: ptr AccountUserData;
profilebase: ptr AccountProfileBase): Result {.cdecl,
importc: "accountProfileGet".}
## / Get the icon image size.
## / Get \ref AccountUserData and \ref AccountProfileBase for the specified profile, userdata is optional (can be NULL).
proc accountProfileGetImageSize*(profile: ptr AccountProfile; imageSize: ptr U32): Result {.
cdecl, importc: "accountProfileGetImageSize".}
## / Load the JPEG profile icon, valid for both Miis and character icons. The output image_size is the same as the one from \ref accountProfileGetImageSize.
## / Get the icon image size.
proc accountProfileLoadImage*(profile: ptr AccountProfile; buf: pointer; len: csize_t;
imageSize: ptr U32): Result {.cdecl,
importc: "accountProfileLoadImage".}
## / Gets the userId which was selected by the profile-selector applet (if any), prior to launching the currently running Application.
## / This gets the cached PreselectedUser loaded during accountInitialize, when PreselectedUser is available.
## / Load the JPEG profile icon, valid for both Miis and character icons. The output image_size is the same as the one from \ref accountProfileGetImageSize.
proc accountGetPreselectedUser*(uid: ptr AccountUid): Result {.cdecl,
importc: "accountGetPreselectedUser".}
## *
## @brief Checks whether the specified \ref AccountUid is valid/set (non-zero).
## @param[in] Uid \ref AccountUid
##
## / Gets the userId which was selected by the profile-selector applet (if any), prior to launching the currently running Application.
## / This gets the cached PreselectedUser loaded during accountInitialize, when PreselectedUser is available.
proc accountUidIsValid*(uid: ptr AccountUid): bool {.inline, cdecl.} =
## *
## @brief Checks whether the specified \ref AccountUid is valid/set (non-zero).
## @param[in] Uid \ref AccountUid
##
return uid.uid[0] != 0 or uid.uid[1] != 0

View file

@ -72,74 +72,68 @@ type
outHandles*: ptr Handle
## *
## @brief Returns whether a service has been initialized.
## @param[in] s Service object.
## @return true if initialized.
##
proc serviceIsActive*(s: ptr Service): bool {.inline, cdecl.} =
## *
## @brief Returns whether a service has been initialized.
## @param[in] s Service object.
## @return true if initialized.
##
return s.session != Invalid_Handle
## *
## @brief Returns whether a service is overriden in the homebrew environment.
## @param[in] s Service object.
## @return true if overriden.
##
proc serviceIsOverride*(s: ptr Service): bool {.inline, cdecl.} =
## *
## @brief Returns whether a service is overriden in the homebrew environment.
## @param[in] s Service object.
## @return true if overriden.
##
return serviceIsActive(s) and not s.ownHandle.bool and not s.objectId.bool
## *
## @brief Returns whether a service is a domain.
## @param[in] s Service object.
## @return true if a domain.
##
proc serviceIsDomain*(s: ptr Service): bool {.inline, cdecl.} =
## *
## @brief Returns whether a service is a domain.
## @param[in] s Service object.
## @return true if a domain.
##
return serviceIsActive(s) and s.ownHandle.bool and s.objectId.bool
## *
## @brief Returns whether a service is a domain subservice.
## @param[in] s Service object.
## @return true if a domain subservice.
##
proc serviceIsDomainSubservice*(s: ptr Service): bool {.inline, cdecl.} =
## *
## @brief Returns whether a service is a domain subservice.
## @param[in] s Service object.
## @return true if a domain subservice.
##
return serviceIsActive(s) and not s.ownHandle.bool and s.objectId.bool
## *
## @brief For a domain/domain subservice, return the associated object ID.
## @param[in] s Service object, necessarily a domain or domain subservice.
## @return The object ID.
##
proc serviceGetObjectId*(s: ptr Service): U32 {.inline, cdecl.} =
## *
## @brief For a domain/domain subservice, return the associated object ID.
## @param[in] s Service object, necessarily a domain or domain subservice.
## @return The object ID.
##
return s.objectId
## *
## @brief Creates a service object from an IPC session handle.
## @param[out] s Service object.
## @param[in] h IPC session handle.
##
proc serviceCreate*(s: ptr Service; h: Handle) {.inline, cdecl.} =
## *
## @brief Creates a service object from an IPC session handle.
## @param[out] s Service object.
## @param[in] h IPC session handle.
##
s.session = h
s.ownHandle = 1
s.objectId = 0
s.pointerBufferSize = 0
discard cmifQueryPointerBufferSize(h, addr(s.pointerBufferSize))
## *
## @brief Creates a non-domain subservice object from a parent service.
## @param[out] s Service object.
## @param[in] parent Parent service.
## @param[in] h IPC session handle for this subservice.
##
proc serviceCreateNonDomainSubservice*(s: ptr Service; parent: ptr Service; h: Handle) {.
inline, cdecl.} =
## *
## @brief Creates a non-domain subservice object from a parent service.
## @param[out] s Service object.
## @param[in] parent Parent service.
## @param[in] h IPC session handle for this subservice.
##
if h != Invalid_Handle:
s.session = h
s.ownHandle = 1
@ -148,15 +142,15 @@ proc serviceCreateNonDomainSubservice*(s: ptr Service; parent: ptr Service; h: H
else:
s[] = Service()
## *
## @brief Creates a domain subservice object from a parent service.
## @param[out] s Service object.
## @param[in] parent Parent service, necessarily a domain or domain subservice.
## @param[in] object_id Object ID for this subservice.
##
proc serviceCreateDomainSubservice*(s: ptr Service; parent: ptr Service; objectId: U32) {.
inline, cdecl.} =
## *
## @brief Creates a domain subservice object from a parent service.
## @param[out] s Service object.
## @param[in] parent Parent service, necessarily a domain or domain subservice.
## @param[in] object_id Object ID for this subservice.
##
if objectId != 0:
s.session = parent.session
s.ownHandle = 0
@ -165,24 +159,24 @@ proc serviceCreateDomainSubservice*(s: ptr Service; parent: ptr Service; objectI
else:
s[] = Service()
## *
## @brief Hints the compiler that a service will always contain a domain object.
## @param[in] _s Service object.
##
template serviceAssumeDomain*(s: untyped): void =
## *
## @brief Hints the compiler that a service will always contain a domain object.
## @param[in] _s Service object.
##
while true:
if not (s).objectId.bool:
builtinUnreachable()
if not 0:
break
## *
## @brief Closes a service.
## @param[in] s Service object.
##
proc serviceClose*(s: ptr Service) {.inline, cdecl.} =
## *
## @brief Closes a service.
## @param[in] s Service object.
##
{.emit: "#if defined(NX_SERVICE_ASSUME_NON_DOMAIN)".}
{.emit: " if (`s`->object_id)".}
{.emit: " __builtin_unreachable();".}
@ -195,13 +189,12 @@ proc serviceClose*(s: ptr Service) {.inline, cdecl.} =
{.emit: " }".}
{.emit: " *`s` = (Service){};".}
## *
## @brief Clones a service.
## @param[in] s Service object.
## @param[out] out_s Output service object.
##
proc serviceClone*(s: ptr Service; outS: ptr Service): Result {.inline, cdecl.} =
## *
## @brief Clones a service.
## @param[in] s Service object.
## @param[out] out_s Output service object.
##
{.emit: "#if defined(NX_SERVICE_ASSUME_NON_DOMAIN)".}
{.emit: " if (`s`->object_id)".}
{.emit: " __builtin_unreachable();".}
@ -212,14 +205,14 @@ proc serviceClone*(s: ptr Service; outS: ptr Service): Result {.inline, cdecl.}
{.emit: " `outS`->pointer_buffer_size = `s`->pointer_buffer_size;".}
{.emit: " `result` = cmifCloneCurrentObject(`s`->session, &`outS`->session);".}
## *
## @brief Clones a service with a session manager tag.
## @param[in] s Service object.
## @param[in] tag Session manager tag (unused in current official server code)
## @param[out] out_s Output service object.
##
proc serviceCloneEx*(s: ptr Service; tag: U32; outS: ptr Service): Result {.inline, cdecl.} =
## *
## @brief Clones a service with a session manager tag.
## @param[in] s Service object.
## @param[in] tag Session manager tag (unused in current official server code)
## @param[out] out_s Output service object.
##
{.emit: "#if defined(NX_SERVICE_ASSUME_NON_DOMAIN)".}
{.emit: " if (`s`->object_id)".}
{.emit: " __builtin_unreachable();".}
@ -230,13 +223,13 @@ proc serviceCloneEx*(s: ptr Service; tag: U32; outS: ptr Service): Result {.inli
{.emit: " `outS`->pointer_buffer_size = `s`->pointer_buffer_size;".}
{.emit: " `result` = cmifCloneCurrentObjectEx(`s`->session, `tag`, &`outS`->session);".}
## *
## @brief Converts a regular service to a domain.
## @param[in] s Service object.
## @return Result code.
##
proc serviceConvertToDomain*(s: ptr Service): Result {.inline, cdecl.} =
## *
## @brief Converts a regular service to a domain.
## @param[in] s Service object.
## @return Result code.
##
if not s.ownHandle.bool:
## For overridden services, create a clone first.
var rc: Result = cmifCloneCurrentObjectEx(s.session, 0, addr(s.session))