#include "service_guard.h" #include "sf/sessionmgr.h" #include "services/friends.h" static FriendsServiceType g_friendsServiceType; static Service g_friendsSrv; static Service g_friendsIFriendService; static SessionMgr g_friendsSessionMgr; NX_GENERATE_SERVICE_GUARD_PARAMS(friends, (FriendsServiceType service_type), (service_type)); NX_INLINE bool _friendsObjectIsChild(Service* s) { return s->session == g_friendsSrv.session; } static void _friendsObjectClose(Service* s) { if (!_friendsObjectIsChild(s)) { serviceClose(s); } else { int slot = sessionmgrAttachClient(&g_friendsSessionMgr); uint32_t object_id = serviceGetObjectId(s); serviceAssumeDomain(s); cmifMakeCloseRequest(armGetTls(), object_id); svcSendSyncRequest(sessionmgrGetClientSession(&g_friendsSessionMgr, slot)); sessionmgrDetachClient(&g_friendsSessionMgr, slot); } } NX_INLINE Result _friendsObjectDispatchImpl(Service* s, u32 request_id, const void * in_data, u32 in_data_size, void * out_data, u32 out_data_size, SfDispatchParams disp) { int slot = -1; if (_friendsObjectIsChild(s)) { slot = sessionmgrAttachClient(&g_friendsSessionMgr); if (slot < 0) __builtin_unreachable(); disp.target_session = sessionmgrGetClientSession(&g_friendsSessionMgr, slot); serviceAssumeDomain(s); } Result rc = serviceDispatchImpl(s, request_id, in_data, in_data_size, out_data, out_data_size, disp); if (slot >= 0) sessionmgrDetachClient(&g_friendsSessionMgr, slot); return rc; } #define _friendsObjectDispatch(_s,_rid,...) \ _friendsObjectDispatchImpl((_s),(_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ }) #define _friendsObjectDispatchIn(_s,_rid,_in,...) \ _friendsObjectDispatchImpl((_s),(_rid),&(_in),sizeof(_in),NULL,0,(SfDispatchParams){ __VA_ARGS__ }) #define _friendsObjectDispatchOut(_s,_rid,_out,...) \ _friendsObjectDispatchImpl((_s),(_rid),NULL,0,&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) #define _friendsObjectDispatchInOut(_s,_rid,_in,_out,...) \ _friendsObjectDispatchImpl((_s),(_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) Result _friendsInitialize(FriendsServiceType service_type) { Result rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); g_friendsServiceType = service_type; switch (g_friendsServiceType) { case FriendsServiceType_User: rc = smGetService(&g_friendsSrv, "friend:u"); break; case FriendsServiceType_Administrator: rc = smGetService(&g_friendsSrv, "friend:a"); break; case FriendsServiceType_Manager: rc = smGetService(&g_friendsSrv, "friend:m"); break; case FriendsServiceType_Viewer: rc = smGetService(&g_friendsSrv, "friend:v"); break; case FriendsServiceType_System: rc = smGetService(&g_friendsSrv, "friend:s"); break; } if (R_SUCCEEDED(rc)) rc = serviceConvertToDomain(&g_friendsSrv); if (R_SUCCEEDED(rc)) rc = sessionmgrCreate(&g_friendsSessionMgr, g_friendsSrv.session, 0x5); if (R_SUCCEEDED(rc)) { rc = _friendsObjectDispatch(&g_friendsSrv, 0, .out_num_objects = 1, .out_objects = &g_friendsIFriendService ); } return rc; } void _friendsCleanup(void) { sessionmgrClose(&g_friendsSessionMgr); _friendsObjectClose(&g_friendsIFriendService); serviceClose(&g_friendsSrv); } Service* friendsGetServiceSession(void) { return &g_friendsSrv; } Service* friendsGetServiceSession_IFriendsService(void) { return &g_friendsIFriendService; } Result friendsGetUserSetting(AccountUid uid, FriendsUserSetting *user_setting) { return _friendsObjectDispatchIn(&g_friendsIFriendService, 20800, uid, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, .buffers = { { user_setting, sizeof(FriendsUserSetting) } } ); } Result friendsTryPopFriendInvitationNotificationInfo(AccountUid *uid, void* buffer, u64 size, u64 *out_size) { Result rc=0; AppletStorage storage; s64 storage_size=0; u64 data_size = size; AccountUid tmpuid={0}; rc = appletTryPopFromFriendInvitationStorageChannel(&storage); if (R_SUCCEEDED(rc)) rc = appletStorageGetSize(&storage, &storage_size); if (R_SUCCEEDED(rc) && storage_size < sizeof(AccountUid)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); if (R_SUCCEEDED(rc)) { storage_size-=sizeof(AccountUid); rc = appletStorageRead(&storage, 0, &tmpuid, sizeof(AccountUid)); if (R_SUCCEEDED(rc)) { if (data_size > storage_size) data_size = storage_size; if (data_size) rc = appletStorageRead(&storage, sizeof(AccountUid), buffer, data_size); if (R_SUCCEEDED(rc)) { if (out_size) *out_size = data_size; if (uid) *uid = tmpuid; } } } appletStorageClose(&storage); return rc; }