mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
309 lines
9.1 KiB
C
309 lines
9.1 KiB
C
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
|
#include "services/news.h"
|
|
#include "service_guard.h"
|
|
#include "runtime/hosversion.h"
|
|
#include <string.h>
|
|
|
|
static NewsServiceType g_newsServiceType;
|
|
static Service g_newsCreatorSrv;
|
|
static Service g_newsSrv;
|
|
|
|
static Result _newsCreateNewsService(Service *srv_out);
|
|
|
|
NX_GENERATE_SERVICE_GUARD_PARAMS(news, (NewsServiceType service_type), (service_type));
|
|
|
|
Result _newsInitialize(NewsServiceType service_type) {
|
|
Result rc;
|
|
|
|
if (service_type >= NewsServiceType_Count)
|
|
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
|
|
|
static const char* const service_names[] = {
|
|
"news:a",
|
|
"news:c",
|
|
"news:m",
|
|
"news:p",
|
|
"news:v",
|
|
};
|
|
|
|
g_newsServiceType = service_type;
|
|
|
|
if (hosversionBefore(2,0,0)) {
|
|
rc = smGetService(&g_newsSrv, service_names[g_newsServiceType]);
|
|
} else {
|
|
rc = smGetService(&g_newsCreatorSrv, service_names[g_newsServiceType]);
|
|
|
|
if (R_SUCCEEDED(rc)) rc = _newsCreateNewsService(&g_newsSrv);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
void _newsCleanup(void) {
|
|
serviceClose(&g_newsSrv);
|
|
serviceClose(&g_newsCreatorSrv);
|
|
}
|
|
|
|
Service *newsGetServiceSession(void) {
|
|
return &g_newsSrv;
|
|
}
|
|
|
|
static Result _newsSrvOut(Service *srv, Service *srv_out, u32 cmd_id) {
|
|
return serviceDispatch(srv, cmd_id,
|
|
.out_num_objects = 1,
|
|
.out_objects = srv_out,
|
|
);
|
|
}
|
|
|
|
static Result _newsCreateNewsService(Service *srv_out) {
|
|
return _newsSrvOut(&g_newsCreatorSrv, srv_out, 0);
|
|
}
|
|
|
|
Result newsCreateNewlyArrivedEventHolder(NewsNewlyArrivedEventHolder *out) {
|
|
Service *srv;
|
|
u32 cmd_id;
|
|
if (hosversionBefore(2,0,0)) {
|
|
srv = &g_newsSrv;
|
|
cmd_id = 30900;
|
|
} else {
|
|
srv = &g_newsCreatorSrv;
|
|
cmd_id = 1;
|
|
}
|
|
return _newsSrvOut(srv, &out->s, cmd_id);
|
|
}
|
|
|
|
Result newsCreateNewsDataService(NewsDataService *out) {
|
|
Service *srv;
|
|
u32 cmd_id;
|
|
if (hosversionBefore(2,0,0)) {
|
|
srv = &g_newsSrv;
|
|
cmd_id = 30901;
|
|
} else {
|
|
srv = &g_newsCreatorSrv;
|
|
cmd_id = 2;
|
|
}
|
|
return _newsSrvOut(srv, &out->s, cmd_id);
|
|
}
|
|
|
|
Result newsCreateNewsDatabaseService(NewsDatabaseService *out) {
|
|
Service *srv;
|
|
u32 cmd_id;
|
|
if (hosversionBefore(2,0,0)) {
|
|
srv = &g_newsSrv;
|
|
cmd_id = 30902;
|
|
} else {
|
|
srv = &g_newsCreatorSrv;
|
|
cmd_id = 3;
|
|
}
|
|
return _newsSrvOut(srv, &out->s, cmd_id);
|
|
}
|
|
|
|
Result newsCreateOverwriteEventHolder(NewsOverwriteEventHolder *out) {
|
|
if (hosversionBefore(2,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return _newsSrvOut(&g_newsCreatorSrv, &out->s, 4);
|
|
}
|
|
|
|
Result newsPostLocalNews(const void *news, size_t size) {
|
|
return serviceDispatch(&g_newsSrv, 10100,
|
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
|
.buffers = { { news, size }, },
|
|
);
|
|
}
|
|
|
|
Result newsSetPassphrase(u64 program_id, const char *passphrase) {
|
|
return serviceDispatchIn(&g_newsSrv, 20100, program_id,
|
|
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
|
.buffers = { { passphrase, strlen(passphrase) + 1 }, },
|
|
);
|
|
}
|
|
|
|
Result newsGetSubscriptionStatus(const char *filter, u32 *status) {
|
|
return serviceDispatchOut(&g_newsSrv, 30100, *status,
|
|
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
|
.buffers = { { filter, strlen(filter) + 1 }, },
|
|
);
|
|
}
|
|
|
|
Result newsGetTopicList(u32 unk, u32 *out_count, NewsTopicName *out, u32 max_count) {
|
|
if (hosversionBefore(3,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return serviceDispatchInOut(&g_newsSrv, 30101, unk, *out_count,
|
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
.buffers = { { out, max_count * sizeof(*out) }, },
|
|
);
|
|
}
|
|
|
|
Result newsGetSavedataUsage(u64 *current, u64 *total) {
|
|
if (hosversionBefore(6,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
struct {
|
|
u64 current;
|
|
u64 total;
|
|
} out;
|
|
|
|
Result rc = serviceDispatchOut(&g_newsSrv, 30110, out);
|
|
|
|
if (R_SUCCEEDED(rc)) {
|
|
if (current) *current = out.current;
|
|
if (total) *total = out.total;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
Result newsIsSystemUpdateRequired(bool *out) {
|
|
u8 tmp=0;
|
|
Result rc = serviceDispatchOut(&g_newsSrv, 30200, tmp);
|
|
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
|
|
return rc;
|
|
}
|
|
|
|
Result newsGetDatabaseVersion(u32 *version) {
|
|
if (hosversionBefore(10,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return serviceDispatchOut(&g_newsSrv, 30210, *version);
|
|
}
|
|
|
|
Result newsRequestImmediateReception(const char *filter) {
|
|
return serviceDispatch(&g_newsSrv, 30300,
|
|
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
|
.buffers = { { filter, strlen(filter) + 1 }, },
|
|
);
|
|
}
|
|
|
|
Result newsSetSubscriptionStatus(const char *filter, u32 status) {
|
|
return serviceDispatchIn(&g_newsSrv, 40100, status,
|
|
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
|
.buffers = { { filter, strlen(filter) + 1 }, },
|
|
);
|
|
}
|
|
|
|
Result newsClearStorage(void) {
|
|
return serviceDispatch(&g_newsSrv, 40200);
|
|
}
|
|
|
|
Result newsClearSubscriptionStatusAll(void) {
|
|
return serviceDispatch(&g_newsSrv, 40201);
|
|
}
|
|
|
|
Result newsGetNewsDatabaseDump(void *buffer, u64 size, u64 *out) {
|
|
return serviceDispatchOut(&g_newsSrv, 90100, *out,
|
|
.buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcMapAlias },
|
|
.buffers = { { buffer, size }, },
|
|
);
|
|
}
|
|
|
|
void newsNewlyArrivedEventHolderClose(NewsNewlyArrivedEventHolder *srv) {
|
|
serviceClose(&srv->s);
|
|
}
|
|
|
|
Result newsNewlyArrivedEventHolderGet(NewsNewlyArrivedEventHolder *srv, Event *out) {
|
|
Handle tmp_handle = INVALID_HANDLE;
|
|
Result rc = 0;
|
|
|
|
rc = serviceDispatch(&srv->s, 0,
|
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
|
.out_handles = &tmp_handle,
|
|
);
|
|
if (R_SUCCEEDED(rc)) eventLoadRemote(out, tmp_handle, true);
|
|
return rc;
|
|
}
|
|
|
|
void newsDataClose(NewsDataService *srv) {
|
|
serviceClose(&srv->s);
|
|
}
|
|
|
|
Result newsDataOpen(NewsDataService *srv, const char *file_name) {
|
|
return serviceDispatch(&srv->s, 0,
|
|
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
|
.buffers = { { file_name, strlen(file_name) + 1 }, },
|
|
);
|
|
}
|
|
|
|
Result newsDataOpenWithNewsRecordV1(NewsDataService *srv, NewsRecordV1 *record) {
|
|
return serviceDispatchIn(&srv->s, 1, *record);
|
|
}
|
|
|
|
Result newsDataRead(NewsDataService *srv, u64 *bytes_read, u64 offset, void *out, size_t out_size) {
|
|
return serviceDispatchInOut(&srv->s, 2, offset, *bytes_read,
|
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
|
.buffers = { { out, out_size }, },
|
|
);
|
|
}
|
|
|
|
Result newsDataGetSize(NewsDataService *srv, u64 *size) {
|
|
return serviceDispatchOut(&srv->s, 3, *size);
|
|
}
|
|
|
|
Result newsDataOpenWithNewsRecord(NewsDataService *srv, NewsRecord *record) {
|
|
if (hosversionBefore(6,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return serviceDispatchIn(&srv->s, 1001, *record);
|
|
}
|
|
|
|
void newsDatabaseClose(NewsDatabaseService *srv) {
|
|
serviceClose(&srv->s);
|
|
}
|
|
|
|
Result newsDatabaseGetListV1(NewsDatabaseService *srv, NewsRecordV1 *out, u32 max_count, const char *where, const char *order, u32 *count, u32 offset) {
|
|
return serviceDispatchInOut(&srv->s, 0, offset, *count,
|
|
.buffer_attrs = {
|
|
SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out,
|
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
|
},
|
|
.buffers = {
|
|
{ out, max_count * sizeof(NewsRecordV1) },
|
|
{ where, strlen(where) + 1 },
|
|
{ order, strlen(order) + 1 },
|
|
},
|
|
);
|
|
}
|
|
|
|
Result newsDatabaseCount(NewsDatabaseService *srv, const char *filter, u32 *count) {
|
|
return serviceDispatchOut(&srv->s, 1, *count,
|
|
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
|
|
.buffers = { { filter, strlen(filter) + 1 }, },
|
|
);
|
|
}
|
|
|
|
Result newsDatabaseGetList(NewsDatabaseService *srv, NewsRecord *out, u32 max_count, const char *where, const char *order, u32 *count, u32 offset) {
|
|
if (hosversionBefore(6,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return serviceDispatchInOut(&srv->s, 1000, offset, *count,
|
|
.buffer_attrs = {
|
|
SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out,
|
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
|
SfBufferAttr_HipcPointer | SfBufferAttr_In,
|
|
},
|
|
.buffers = {
|
|
{ out, max_count * sizeof(NewsRecord) },
|
|
{ where, strlen(where) + 1 },
|
|
{ order, strlen(order) + 1 },
|
|
},
|
|
);
|
|
}
|
|
|
|
void newsOverwriteEventHolderClose(NewsOverwriteEventHolder *srv) {
|
|
serviceClose(&srv->s);
|
|
}
|
|
|
|
Result newsOverwriteEventHolderGet(NewsOverwriteEventHolder *srv, Event *out) {
|
|
Handle tmp_handle = INVALID_HANDLE;
|
|
Result rc = 0;
|
|
|
|
rc = serviceDispatch(&srv->s, 0,
|
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
|
.out_handles = &tmp_handle,
|
|
);
|
|
if (R_SUCCEEDED(rc)) eventLoadRemote(out, tmp_handle, true);
|
|
return rc;
|
|
}
|