diff --git a/libctru/source/srv.c b/libctru/source/srv.c index da34c35..4365b44 100644 --- a/libctru/source/srv.c +++ b/libctru/source/srv.c @@ -7,8 +7,63 @@ #include <3ds/svc.h> +#ifdef SRV_OVERRIDE_SUPPORT +/* + The homebrew loader can choose to supply a list of service handles that have + been "stolen" from other processes that have been compromised. This allows us + to access services that are normally restricted from the current process. + + For every service requested by the application, we shall first check if the + list given to us contains the requested service and if so use it. If we don't + find the service in that list, we ask the service manager and hope for the + best. + */ + +typedef struct { + u32 num; + + struct { + char name[8]; + Handle handle; + } services[]; +} service_list_t; + +extern service_list_t* _service_ptr; +#endif + static Handle g_srv_handle = 0; + + +#ifdef SRV_OVERRIDE_SUPPORT +static int __name_cmp(const char* a, const char* b) { + u32 i; + + for(i=0; i<8; i++) { + if(a[i] != b[i]) + return 1; + if(a[i] == '\0') + return 0; + } + + return 0; +} + +static Handle __get_handle_from_list(char* name) { + if((u32)_service_ptr == 0) + return 0; + + u32 i, num = _service_ptr->num; + + for(i=0; iservices[i].name, name) == 0) + return _service_ptr->services[i].handle; + } + + return 0; +} +#endif + Result srvInit() { Result rc = 0; @@ -30,6 +85,7 @@ Result srvExit() svcCloseHandle(g_srv_handle); g_srv_handle = 0; + return 0; } Result srvRegisterClient() @@ -47,15 +103,24 @@ Result srvRegisterClient() Result srvGetServiceHandle(Handle* out, char* name) { - u8 len = strlen(name); - Result rc; +#ifdef SRV_OVERRIDE_SUPPORT + /* Look in service-list given to us by loader. If we find find a match, + we return it. */ + Handle h = __get_handle_from_list(name); + if(h != 0) { + *out = h; return 0; + } +#endif + + /* Normal request to service manager. */ u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = 0x50100; strcpy((char*) &cmdbuf[1], name); - cmdbuf[3] = len; + cmdbuf[3] = strlen(name); cmdbuf[4] = 0x0; + Result rc; if(rc = svcSendSyncRequest(g_srv_handle)) return rc;