std::vector<TitleInfo> getTitleInfos(FS_MediaType mediaType) { char tmpStr[16]; extern u8 sysLang; // We got this in main.c u32 count, bytesRead; Result res; Handle fileHandle; TitleInfo tmpTitleInfo; u32 archiveLowPath[4] = {0, 0, mediaType, 0}; const FS_Archive iconArchive = {0x2345678A, {PATH_BINARY, 0x10, (u8*)archiveLowPath}}; const u32 fileLowPath[5] = {0, 0, 2, 0x6E6F6369, 0}; const FS_Path filePath = {PATH_BINARY, 0x14, (const u8*)fileLowPath}; if((res = AM_GetTitleCount(mediaType, &count))) throw titleException(_FILE_, __LINE__, res, "Failed to get title count!"); std::vector<TitleInfo> titleInfos; titleInfos.reserve(count); Buffer<u64> titleIdList(count, false); Buffer<AM_TitleEntry> titleList(count, false); Buffer<Icon> icon(1, false); if((res = AM_GetTitleIdList(mediaType, count, &titleIdList))) throw titleException(_FILE_, __LINE__, res, "Failed to get title ID list!"); if((res = AM_ListTitles(mediaType, count, &titleIdList, &titleList))) throw titleException(_FILE_, __LINE__, res, "Failed to get title list!"); for(u32 i=0; i<count; i++) { // Copy title ID, size and version directly memcpy(&tmpTitleInfo.titleID, &titleList[i].titleID, 18); if(AM_GetTitleProductCode(mediaType, titleIdList[i], tmpStr)) memset(tmpStr, 0, 16); tmpTitleInfo.productCode = tmpStr; // Copy the title ID into our archive low path memcpy(archiveLowPath, &titleIdList[i], 8); icon.clear(); if(!FSUSER_OpenFileDirectly(&fileHandle, iconArchive, filePath, FS_OPEN_READ, 0)) { // Nintendo decided to release a title with an icon entry but with size 0 so this will fail. // Ignoring errors because of this here. FSFILE_Read(fileHandle, &bytesRead, 0, &icon, sizeof(Icon)); FSFILE_Close(fileHandle); } tmpTitleInfo.title = icon[0].appTitles[sysLang].longDesc; tmpTitleInfo.publisher = icon[0].appTitles[sysLang].publisher; memcpy(tmpTitleInfo.icon, icon[0].icon48, 0x1200); titleInfos.push_back(tmpTitleInfo); } return titleInfos; }
std::vector<App> appList(MediaType mediaType) { std::vector<App> titles; if(!serviceRequire("am")) { return titles; } u32 titleCount; Result titleCountResult = AM_GetTitleCount(appMediatypeToByte(mediaType), &titleCount); if(titleCountResult != 0) { platformSetError(serviceParseError((u32) titleCountResult)); return titles; } u64 titleIds[titleCount]; Result titleIdsResult = AM_GetTitleIdList(appMediatypeToByte(mediaType), titleCount, titleIds); if(titleIdsResult != 0) { platformSetError(serviceParseError((u32) titleIdsResult)); return titles; } TitleList titleList[titleCount]; Result titleListResult = AM_ListTitles(appMediatypeToByte(mediaType), titleCount, titleIds, titleList); if(titleListResult != 0) { platformSetError(serviceParseError((u32) titleListResult)); return titles; } for(u32 i = 0; i < titleCount; i++) { u64 titleId = titleList[i].titleID; App app; app.titleId = titleId; app.uniqueId = ((u32*) &titleId)[0]; AM_GetTitleProductCode(appMediatypeToByte(mediaType), titleId, app.productCode); if(strcmp(app.productCode, "") == 0) { strcpy(app.productCode, "<N/A>"); } app.mediaType = mediaType; app.platform = appPlatformFromId(((u16*) &titleId)[3]); app.category = appCategoryFromId(((u16*) &titleId)[2]); app.version = titleList[i].titleVersion; app.size = titleList[i].size; titles.push_back(app); } return titles; }
Result httpwn_setup(char *serverconfig_localpath) { Result ret = 0; u64 http_sysmodule_titleid = 0x0004013000002902ULL; AM_TitleEntry title_entry; u8 *cert = (u8*)builtin_rootca_der; u32 certsize = builtin_rootca_der_size; u8 *filebuffer; u32 filebuffer_size = 0x100000; u32 statuscode = 0; configctx config; targeturlctx *first_targeturlctx = NULL; FILE *f; memset(&config, 0, sizeof(configctx)); config.first_targeturlctx = &first_targeturlctx; ret = amInit(); if(ret!=0) { printf("Failed to initialize AM: 0x%08x.\n", (unsigned int)ret); if(ret==0xd8e06406) { printf("The AM service is inaccessible. With the *hax payloads this should never happen. This is normal with plain ninjhax v1.x: this app isn't usable from ninjhax v1.x without any further hax.\n"); } return ret; } ret = AM_ListTitles(0, 1, &http_sysmodule_titleid, &title_entry); amExit(); if(ret!=0) { printf("Failed to get the HTTP sysmodule title-version: 0x%08x.\n", (unsigned int)ret); return ret; } http_codebin_buf = NULL; http_codebin_buf32 = NULL; http_codebin_size = 0; ret = loadcodebin(http_sysmodule_titleid, MEDIATYPE_NAND, &http_codebin_buf, &http_codebin_size); if(R_FAILED(ret)) { printf("Failed to load the HTTP sysmodule codebin: 0x%08x.\n", (unsigned int)ret); return ret; } http_codebin_buf32 = (u32*)http_codebin_buf; ret = httpcInit(0x1000); if(ret!=0) { printf("Failed to initialize HTTPC: 0x%08x.\n", (unsigned int)ret); if(ret==0xd8e06406) { printf("The HTTPC service is inaccessible. With the *hax payload this may happen if the process this app is running under doesn't have access to that service. Please try rebooting the system, boot *hax payload, then directly launch the app.\n"); } free(http_codebin_buf); return ret; } filebuffer = malloc(filebuffer_size); if(filebuffer==NULL) { printf("Failed to allocate the config filebuffer.\n"); ret = -2; httpcExit(); free(http_codebin_buf); return ret; } memset(filebuffer, 0, filebuffer_size); printf("Downloading config...\n"); ret = download_config("https://yls8.mtheall.com/ctr-httpwn/config.php", cert, certsize, filebuffer, filebuffer_size-1, &statuscode); if(ret!=0) { printf("Config downloading failed: 0x%08x.\n", (unsigned int)ret); if(statuscode==500) { printf("HTTP status-code 500 was returned, server reply:\n%s\n", (char*)filebuffer); } f = fopen(serverconfig_localpath, "rb"); if(f) { printf("Use the cached server_config from SD instead?\nPress the A button to continue, B to abort.\n"); while(1) { gspWaitForVBlank(); hidScanInput(); if(hidKeysDown() & KEY_A)break; if(hidKeysDown() & KEY_B) { fclose(f); httpcExit(); free(http_codebin_buf); return ret; } } memset(filebuffer, 0, filebuffer_size); fread(filebuffer, 1, filebuffer_size-1, f); fclose(f); } else { httpcExit(); free(http_codebin_buf); return ret; } } else { unlink(serverconfig_localpath); f = fopen(serverconfig_localpath, "wb"); if(f) { fwrite(filebuffer, 1, strlen((char*)filebuffer), f); fclose(f); } } ret = config_parse(&config, (char*)filebuffer); if(ret==0) { if(title_entry.version != 13318) { printf("The installed HTTP sysmodule version(v%u) is not supported.", title_entry.version); if(config.incompatsysver_message[0])printf(" %s", config.incompatsysver_message); printf("\n"); httpcExit(); free(http_codebin_buf); free(filebuffer); return -1; } if(display_config_message(&config, "Message from the server:")) { httpcExit(); free(http_codebin_buf); free(filebuffer); return 0; } } if(ret==0) { f = fopen("user_config.xml", "rb"); if(f) { printf("Loading+parsing user_config.xml since it exists on SD...\n"); memset(filebuffer, 0, filebuffer_size); fread(filebuffer, 1, filebuffer_size-1, f); fclose(f); ret = config_parse(&config, (char*)filebuffer); if(ret==0) { if(display_config_message(&config, "Message from the user_config:")) { httpcExit(); free(http_codebin_buf); free(filebuffer); return 0; } } } } if(ret!=0) { printf("Config parsing failed: 0x%08x.\n", (unsigned int)ret); httpcExit(); free(http_codebin_buf); free(filebuffer); return ret; } f = fopen("user_nim_rootcertchain_rootca.der", "rb"); if(f) { printf("Loading user_nim_rootcertchain_rootca.der since it exists on SD, which will be used instead of the built-in ctr-httpwn cert...\n"); memset(filebuffer, 0, filebuffer_size); certsize = fread(filebuffer, 1, filebuffer_size, f); fclose(f); cert = filebuffer; } printf("Preparing the haxx...\n"); ret = http_haxx("http://localhost/", cert, certsize, first_targeturlctx);//URL doesn't matter much since this won't actually be requested over the network. config_freemem(&config); httpcExit(); free(http_codebin_buf); free(filebuffer); if(ret!=0) { printf("Haxx setup failed: 0x%08x.\n", (unsigned int)ret); return ret; } return ret; }