#define NX_SERVICE_ASSUME_NON_DOMAIN #include #include "service_guard.h" #include "services/lr.h" #include "services/fs.h" #include "runtime/hosversion.h" static Service g_lrSrv; NX_GENERATE_SERVICE_GUARD(lr); Result _lrInitialize(void) { return smGetService(&g_lrSrv, "lr"); } void _lrCleanup(void) { serviceClose(&g_lrSrv); } Service* lrGetServiceSession(void) { return &g_lrSrv; } Result lrOpenLocationResolver(NcmStorageId storage, LrLocationResolver* out) { const u8 in = (u8)storage; return serviceDispatchIn(&g_lrSrv, 0, in, .out_num_objects = 1, .out_objects = &out->s, ); } Result lrOpenRegisteredLocationResolver(LrRegisteredLocationResolver* out) { return serviceDispatch(&g_lrSrv, 1, .out_num_objects = 1, .out_objects = &out->s, ); } /* All the LocationResolver/RegisteredLocationResolver "Resolve" commands have a common API. This is a helper function to perform the work for those funcs, given a command ID. */ static Result _lrResolvePath(Service* s, u64 tid, char *out, u32 cmd_id) { char out_path[FS_MAX_PATH] = {0}; Result rc = serviceDispatchIn(s, cmd_id, tid, .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcPointer | SfBufferAttr_FixedSize }, .buffers = { { out_path, FS_MAX_PATH } }, ); if (R_SUCCEEDED(rc)) { strncpy(out, out_path, FS_MAX_PATH); out[FS_MAX_PATH-1] = 0; } return rc; } /* All the LocationResolver/RegisteredLocationResolver "Redirect" commands have a common API. This is a helper function to perform the work for those funcs, given a command ID. */ static Result _lrRedirectPath(Service* s, u64 tid, const char *path, u32 cmd_id) { char send_path[FS_MAX_PATH] = {0}; strncpy(send_path, path, FS_MAX_PATH-1); send_path[FS_MAX_PATH-1] = 0; return serviceDispatchIn(s, cmd_id, tid, .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcPointer }, .buffers = { { send_path, FS_MAX_PATH } }, ); } /* In 9.0.0, "RedirectApplication" commands began taking in a second tid argument. This is a helper function to perform the work for those funcs, given a command ID. */ static Result _lrRedirectApplicationPath(Service* s, u64 tid, u64 tid2, const char *path, u32 cmd_id) { // On < 9.0.0, call the original redirection helper. if (hosversionBefore(9,0,0)) { return _lrRedirectPath(s, tid, path, cmd_id); } char send_path[FS_MAX_PATH] = {0}; strncpy(send_path, path, FS_MAX_PATH-1); send_path[FS_MAX_PATH-1] = 0; const struct { u64 tid; u64 tid2; } in = { tid, tid2 }; return serviceDispatchIn(s, cmd_id, in, .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcPointer }, .buffers = { { send_path, FS_MAX_PATH } }, ); } Result lrLrResolveProgramPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, tid, out, 0); } Result lrLrRedirectProgramPath(LrLocationResolver* lr, u64 tid, const char *path) { return _lrRedirectPath(&lr->s, tid, path, 1); } Result lrLrResolveApplicationControlPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, tid, out, 2); } Result lrLrResolveApplicationHtmlDocumentPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, tid, out, 3); } Result lrLrResolveDataPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, tid, out, 4); } Result lrLrRedirectApplicationControlPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path) { return _lrRedirectApplicationPath(&lr->s, tid, tid2, path, 5); } Result lrLrRedirectApplicationHtmlDocumentPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path) { return _lrRedirectApplicationPath(&lr->s, tid, tid2, path, 6); } Result lrLrResolveApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, tid, out, 7); } Result lrLrRedirectApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path) { return _lrRedirectApplicationPath(&lr->s, tid, tid2, path, 8); } Result lrLrRefresh(LrLocationResolver* lr) { return serviceDispatch(&lr->s, 9); } Result lrLrEraseProgramRedirection(LrLocationResolver* lr, u64 tid) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return serviceDispatchIn(&lr->s, 12, tid); } Result lrRegLrResolveProgramPath(LrRegisteredLocationResolver* reg, u64 tid, char *out) { return _lrResolvePath(®->s, tid, out, 0); }