fixed all known bugs

-fixed the make dir issue
-fixed injection in existing folders

need to find a work arround for too much data.
This commit is contained in:
Maschell 2015-10-25 23:07:28 +01:00
parent 721c983122
commit f215d3b13e
25 changed files with 551 additions and 145 deletions

1
.gitignore vendored
View File

@ -58,3 +58,4 @@ saviine/server/src/obj/x86/Debug/saviine_server.csprojResolveAssemblyReference.c
saviine/server/src/obj/x86/Debug/saviine_server.csproj.FileListAbsolute.txt
saviine/server/src/obj/x86/Debug/saviine_server.csproj.GenerateResource.Cache
saviine/server/src/obj/x86/Debug/saviine_server.Form1.resources
saviine/server/src/bin/saviine_server.exe

58
README
View File

@ -1,8 +1,8 @@
Saviine 0.3
Saviine 1.0 (25.10.2015)
Compatible with 5.3.2 fw
dumps WiiU Saves and is a mod of cafiine. Thanks to everyone who worked on cafiine!
dumps and injects (experimental) WiiU Saves(Thanks to everyone who worked on cafiine! code is based on cafiine)
Compilation :
- in order to compile saviine you need to put the saviine folder in your libwiiu project
@ -13,22 +13,52 @@ Pre-made version :
- in www/saviine, it is already compiled, just put the folder in your server
Note :
- make sure you already have a save of the game on you console before trying to dump/inject them
- you can change the server ip directly in the application.
- start the saviine in folder with a short path, some savedata files have some really long names (170+ chracters)
- backup your savedata before dumping it!!! I'm not responsible for any lost data.
- fastmode doesn't work for all games.
- make sure that your game version and the game version from injecting save are the same
- e.g. injecting PAL saves into NTSC one is untested!
NOTE FOR SUPER SMASH BROS FOR WIIU the common data is too big to inject at one time. injecting the common folder will fail. try to split the files up and use the inject without clean to inject the data without the texture folder. MAKE SURE TO MAKE A BACKUP! This may also applies to other games
The WiiU has mutiple save folder. One folder for infos that are shared with all accounts (common) and a folder for each account (e.g 8000000a)
At the moment it is only possible to dump the common folder your own folder. Not all games use the common folder.
Folder structur:
logs/ <-- logs
saviine_root/dump <-- the save files will be dumped here. A sub folder for each game will be created (name is the game title id)
saviine_root/inject <-- place the saves here if you want to inject them
How to use :
Usage:
Normal mode: saviine_server.exe
Fast mode: saviine_server.exe fastmode
- launch the kernel exploit in the brower
- open saviine server in your computer, check your ip
(you can start the server in fastmode (faster dumper), this doesn't work for all games. Only use it when the savegame is really big (e.g. Super Smash Bros for WiiU) )
- relaunch browser and launch saviine app, set saviine server ip in the application with up/down/left/right, and press A to install saviine
temporary installing saviine:
- launch the "normal" kernel exploit in the brower
- relaunch browser and launch saviine app, set saviine server ip in the application with up/down/left/right, and press A to install saviine. if you see crap on the screen, press up/down to fix it
-> browser should exit
- launch a game or application
- the savedata should be dumped to a folder in /saviine/[title_id]
- profit
- you can close the game and dump an other
dumping:
--- MAKE SURE THAT THE SAVIINE SERVER IN A FOLDER WITH A SHORT PATH! some gamefiles have some really really long names. e.g. D:/saviine/ ---
- open the dump.bat or start the saviine_server.exe with the argument "dump"
- launch a game
- a dialog should appear, select if you want to dump the user and/or the common data
- the data will be dumped to saviine_root/dump/[game_title_id]/80000000x (user data) and/or saviine_root/dump/[game_title_id]/common (common)
- close the game and dump an other
injecting:
--- INJECTING FILES IS STILL IN TESTING! MAKE SURE TO SAVE YOUR SAVES BEFORE TRYING TO INJECT SOMETHING ---
--- EXISTING SAVE DATA ON THAT WILL BE GONE AFTER THE INJECTION ---
- open the inject.bat or start the saviine_server.exe with the argument "inject"
- place the save data you want to inject into the "saviine_root/inject" folder. You need to have a folder for each game, named after the games title id (e.g saviine_root\inject\00050000-1010ED00).
this folder will be scanned for 8000000x or common folders.
- launch a game
- a dialog should appear, select if the profile you want to inject and choose if you want to inject the common files too.
For the commmon folder you have two options:
1. inject.
this adds the data into the existing common folder, existing files will be overwritten. (I think this way you can add replays to your Mario Kart 8)
2. clean and inject
deletes all existing files in the existing common and injects the new one.
- on errors during the injection, the wii tries to restore the old data. but it can't guarantee that it works, make sure to make backups!

View File

@ -24,7 +24,7 @@ SFLAGS := -mgekko -mregnames
# -memb: enable embedded application specific compilation
# -ffunction-sections: split up functions so linker can garbage collect
# -fdata-sections: split up data so linker can garbage collect
CFLAGS := -O0 -Wall -x c -std=gnu99 \
CFLAGS := -O2 -Wall -x c -std=gnu99 \
-ffreestanding \
-mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \
-msdata=none -memb -ffunction-sections -fdata-sections \

View File

@ -5,7 +5,7 @@
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".magicptr"))); \
res my_ ## name(__VA_ARGS__)
#define DEBUG_LOG 0
#define BUFFER_SIZE (1024)*100*2
#define BUFFER_SIZE 0x400 * 101
#define BUFFER_SIZE_STEPS 0x200
DECL(int, FSAInit, void) {
@ -25,7 +25,6 @@ DECL(int, FSAAddClient, void *r3) {
cafiine_connect(&bss.socket_fsa[res]);
}
return res;
}
DECL(int, FSADelClient, int client) {
@ -55,7 +54,7 @@ static int client_num_alloc(void *pClient) {
return -1;
}
static void clietn_num_free(int client) {
static void client_num_free(int client) {
bss.pClient_fs[client] = 0;
}
@ -72,6 +71,7 @@ DECL(int, FSInit, void) {
if ((int)bss_ptr == 0x0a000000) {
bss_ptr = memalign(sizeof(struct bss_t), 0x40);
memset(bss_ptr, 0, sizeof(struct bss_t));
}
return real_FSInit();
}
@ -83,7 +83,7 @@ DECL(int, FSDelClient, void *pClient) {
int client = client_num(pClient);
if (client < MAX_CLIENT && client >= 0) {
cafiine_disconnect(bss.socket_fs[client]);
clietn_num_free(client);
client_num_free(client);
}
}
return real_FSDelClient(pClient);
@ -95,63 +95,91 @@ return real_FSWriteFile(pClient,pCmd,source,size,count,fileHandle,flag,error);
DECL(int, FSFlushQuota,FSClient *pClient,FSCmdBlock *pCmd,const char *path,FSRetFlag error) {
return real_FSFlushQuota(pClient,pCmd,path,error);
}
DECL(void, _Exit,void) {
return real__Exit();
}
DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) {
int res = real_FSAddClientEx(r3, r4, r5);
if(!bss.saveinitfs){ //bypass the check for save_init
if(bss.saveFolderChecked != 2){
if(bss.saveFolderChecked == 1) return res;
if ((int)bss_ptr != 0x0a000000 && res >= 0) {
//int client = client_num_alloc(r3);
//if (client < MAX_CLIENT && client >= 0) {
// create game save path
if(bss.saveFolderChecked < 2){
if(bss.saveFolderChecked == 1){
if(r3 != bss.on_start_hook_client){ // block every other client until the on_start method is done
while(bss.saveFolderChecked != 2 || bss.saveFolderChecked != 3){
GX2WaitForVsync();
}
}
}
if ((int)bss_ptr != 0x0a000000) {
int error = 0;
if(bss.saveFolderChecked == 0){
bss.saveFolderChecked = 1;
// Create client and cmd block
FSClient* pClient = (FSClient*)malloc(sizeof(FSClient));
FSClient* pClient_ = (FSClient*)malloc(sizeof(FSClient));
FSCmdBlock* pCmd = (FSCmdBlock*)malloc(sizeof(FSCmdBlock));
if (pClient && pCmd)
{
if (pClient_ && pCmd){
// need to save the pointer of our client to find it again where adding our client to the FS
bss.on_start_hook_client = pClient_;
// Add client to FS.
FSAddClient(pClient, FS_RET_NO_ERROR);
int client = client_num_alloc(pClient);
if(FSAddClient(pClient_, FS_RET_ALL_ERROR) >= 0){
int client = client_num_alloc(pClient_);
if(client < MAX_CLIENT && client >= 0) {
cafiine_connect(&bss.socket_fs[client]);
bss.logsock = bss.socket_fs[client];
}else{
goto error;
error = 3;
bss.saveFolderChecked = 3;
}
// Init command block.
FSInitCmdBlock(pCmd);
if(DEBUG_LOG) log_string(bss.logsock, "FSInitCmdBlock() done", BYTE_LOG_STR);
hook(pClient_, pCmd,FS_RET_ALL_ERROR);
// Init command block.
if(DEBUG_LOG) log_string(bss.logsock, "hook done", BYTE_LOG_STR);
hook(pClient, pCmd,-1);
bss.saveFolderChecked = 2;
error: real_FSDelClient(pClient);
free(pClient);
real_FSDelClient(pClient_);
}else{
error = 2;
bss.saveFolderChecked = 3;
}
free(pClient_);
free(pCmd);
if(DEBUG_LOG) log_string(bss.logsock, "freed the client and buffer", BYTE_LOG_STR);
if(bss.saveFolderChecked != 3)
bss.saveFolderChecked = 2;
if(DEBUG_LOG) log_string(bss.logsock, "set status to done;", BYTE_LOG_STR);
}else{
error = 1;
bss.saveFolderChecked = 3;
}
}
//cafiine_connect(&bss.socket_fs[client]);
//}
}
}
}else{
bss.saveinitfs = 0;
}
int res = real_FSAddClientEx(r3, r4, r5);
return res;
}
void hook(void * pClient,void * pCmd, int error){
log_string(bss.logsock, "hook", BYTE_LOG_STR);
handle_saves(pClient, pCmd,-1);
if(DEBUG_LOG) log_string(bss.logsock, "hook", BYTE_LOG_STR);
handle_saves(pClient, pCmd,error);
}
void handle_saves(void *pClient, void *pCmd,int error){
log_string(bss.logsock, "init", BYTE_LOG_STR);
if(DEBUG_LOG) log_string(bss.logsock, "init", BYTE_LOG_STR);
int client = client_num(pClient);
unsigned char slotNo;
long id = getPesistentID(&slotNo);
init_Save(slotNo);
int mode;
log_string(bss.logsock, "getting mode", BYTE_LOG_STR);
if(DEBUG_LOG)log_string(bss.logsock, "getting mode", BYTE_LOG_STR);
if(getMode(bss.socket_fsa[client],&mode)){
if(id >= 0x80000000 && id <= 0x90000000){
char savepath[20];
@ -183,6 +211,7 @@ void dumpSavaData(void *pClient, void *pCmd,long persistentID,int error){
break;
}
pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40);
if(pBuffer) memset(pBuffer, 0x00, buf_size);
}while(!pBuffer);
if(!failed){
@ -194,8 +223,8 @@ void dumpSavaData(void *pClient, void *pCmd,long persistentID,int error){
if((mask & MASK_USER) == MASK_USER){
char savepath[20];
__os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",persistentID);
log_string(bss.logsock, "user savedata", BYTE_LOG_STR);
if(dump_dir(pClient,pCmd,savepath,pBuffer,buf_size,-1,50) == -1){
log_string(bss.logsock, "dumping user savedata", BYTE_LOG_STR);
if(dump_dir(pClient,pCmd,savepath,pBuffer,buf_size,error,50) == -1){
log_string(bss.logsock, "error dumping user dir", BYTE_LOG_STR);
failed = 1;
}
@ -207,14 +236,18 @@ void dumpSavaData(void *pClient, void *pCmd,long persistentID,int error){
log_string(bss.logsock, "error dumping common dir (maybe the game has no common folder?)", BYTE_LOG_STR);
}
}
log_string(bss.logsock, "done!", BYTE_LOG_STR);
if(!saviine_end_dump(bss.socket_fsa[client])) if(DEBUG_LOG) log_string(bss.logsock, "saviine_end_injection() failed", BYTE_LOG_STR);
free(pBuffer);
if(DEBUG_LOG) log_string(bss.logsock, "end of dump", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "saviine_start_dump() failed", BYTE_LOG_STR);
}
if(DEBUG_LOG) log_string(bss.logsock, "free(pBuffer) coming next", BYTE_LOG_STR);
free(pBuffer);
if(DEBUG_LOG) log_string(bss.logsock, "free(pBuffer)", BYTE_LOG_STR);
}
}
@ -225,7 +258,7 @@ int dump_dir(void *pClient, void *pCmd, char *path, void * pBuffer, int size,int
int ret = 0;
int final_result = 0;
if ((ret = FSOpenDir(pClient, pCmd, path, &dir_handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){
char buffer[strlen(path) + 25];
char buffer[strlen(path) + 30];
__os_snprintf(buffer, sizeof(buffer), "open dir %s",path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
FSDirEntry dir_entry;
@ -236,41 +269,43 @@ int dump_dir(void *pClient, void *pCmd, char *path, void * pBuffer, int size,int
if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){
log_string(bss.logsock, "-> dir", BYTE_LOG_STR);
if(dump_dir(pClient, pCmd,full_path,pBuffer,size,-1,my_handle) == -1){
if(dump_dir(pClient, pCmd,full_path,pBuffer,size,error,my_handle) == -1){
log_string(bss.logsock, "error", BYTE_LOG_STR);
final_result = -1;
}
}else{
//DUMP
ret = FSOpenFile(pClient, pCmd, full_path, "r", &my_handle, FS_RET_ALL_ERROR);
ret = FSOpenFile(pClient, pCmd, full_path, "r", &my_handle, error);
if (ret >= 0) {
__os_snprintf(buffer, sizeof(buffer), "dumping %s",dir_entry.name);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
int buf_size = BUFFER_SIZE;
int ret2;
int my_ret = cafiine_send_handle(bss.socket_fsa[client], client, full_path, my_handle);
if(my_ret != -1){
while ((ret2 = FSReadFile(pClient, pCmd, pBuffer, 1, buf_size, my_handle, 0, 0)) > 0)
while ((ret2 = FSReadFile(pClient, pCmd, pBuffer, 1, size, my_handle, 0, 0)) > 0)
cafiine_send_file(bss.socket_fsa[client], pBuffer, ret2, my_handle);
cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle,1);
}else{
log_string(bss.logsock, "error on opening file on pc" , BYTE_LOG_STR);
final_result = -1;
}
FSSetPosFile(pClient, pCmd, my_handle, 0, FS_RET_ALL_ERROR);
FSCloseFile(pClient, pCmd, my_handle, -1);
if((ret2 = FSCloseFile(pClient, pCmd, my_handle, error)) < FS_STATUS_OK){
__os_snprintf(buffer, sizeof(buffer), "error on FSOpenFile: %d",ret2);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
}
}else{
char buffer[100];
__os_snprintf(buffer, sizeof(buffer), "error on FSOpenFile: %d",ret);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
final_result = -1;
}
}
}
FSCloseDir(pClient, pCmd, dir_handle, FS_RET_NO_ERROR);
if(FSCloseDir(pClient, pCmd, dir_handle, error) < FS_STATUS_OK){
if(DEBUG_LOG) log_string(bss.logsock, "error on FSCloseDir()", BYTE_LOG_STR);
}
}else{
log_string(bss.logsock, "error on FSOpenDir()", BYTE_LOG_STR);
final_result = -1;
@ -298,9 +333,13 @@ void injectSaveData(void *pClient, void *pCmd,long persistentID,int error){
break;
}
pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40);
if(pBuffer) memset(pBuffer, 0x00, buf_size);
}while(!pBuffer);
if(!failed){
char buffer[60];
__os_snprintf(buffer, sizeof(buffer), "allocated %d bytes",buf_size);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
int result = 0;
int mask = 0;
if((result = saviine_start_injection(bss.socket_fsa[client], persistentID,&mask))){
@ -309,14 +348,14 @@ void injectSaveData(void *pClient, void *pCmd,long persistentID,int error){
__os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",persistentID);
__os_snprintf(logbuffer, sizeof(logbuffer), "injecting new userdata in %08x",persistentID);
log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
log_string(bss.logsock, "deleting userdata save", BYTE_LOG_STR);
log_string(bss.logsock, "deleting user save", BYTE_LOG_STR);
if(remove_files_in_dir(pClient,pCmd,savepath,0) == -1){
failed = 1;
}else{
/*
Inject Save
*/
result = injectFiles(pClient,pCmd,savepath,"/",pBuffer,buf_size,-1);
result = injectFiles(pClient,pCmd,savepath,"/",savepath,pBuffer,buf_size,error);
doFlushOrRollback(pClient,pCmd,result,savepath);
}
}
@ -333,20 +372,20 @@ void injectSaveData(void *pClient, void *pCmd,long persistentID,int error){
/*
Inject common
*/
result = injectFiles(pClient,pCmd,commonDir,"/",pBuffer,buf_size,-1);
result = injectFiles(pClient,pCmd,commonDir,"/",commonDir,pBuffer,buf_size,error);
doFlushOrRollback(pClient,pCmd,result,commonDir);
}
}
if(!saviine_end_injection(bss.socket_fsa[client])) if(DEBUG_LOG) log_string(bss.logsock, "saviine_end_injection() failed", BYTE_LOG_STR);
free(pBuffer);
if(DEBUG_LOG)log_string(bss.logsock, "end of injection", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "saviine_start_injection() failed", BYTE_LOG_STR);
}
free(pBuffer);
}
}
int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char * pBuffer, int buffer_size, int error){
int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath, char * basepath, char * pBuffer, int buffer_size, int error){
int client = client_num(pClient);
int failed = 0;
int filesinjected = 0;
@ -357,9 +396,6 @@ int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char
int filesize = 0;
if(!failed){
__os_snprintf(logbuffer, sizeof(logbuffer), "buffer size: %d bytes",buffer_size);
log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
while(saviine_readdir(bss.socket_fsa[client],path,namebuffer, &type,&filesize) && !failed){
if(DEBUG_LOG)log_string(bss.logsock, "got a file", BYTE_LOG_STR);
char newpath[strlen(path) + 1 + strlen(namebuffer)];
@ -370,16 +406,18 @@ int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char
if(DEBUG_LOG) log_string(bss.logsock, "downloading it", BYTE_LOG_STR);
int handle = 10;
if(FSOpenFile(pClient, pCmd, newpath,"w+",&handle,-1) >= 0){
if(FSOpenFile(pClient, pCmd, newpath,"w+",&handle,error) >= FS_STATUS_OK){
if(DEBUG_LOG) log_string(bss.logsock, "file opened and created", BYTE_LOG_STR);
if(filesize > 0){
failed = doInjectForFile(pClient,pCmd,handle,newpath,filesize,pBuffer,buffer_size);
failed = doInjectForFile(pClient,pCmd,handle,newpath,filesize,basepath,pBuffer,buffer_size);
if(failed == 2) // trying it again if the journal was full
failed = doInjectForFile(pClient,pCmd,handle,newpath,filesize,basepath,pBuffer,buffer_size);
}else{
if(DEBUG_LOG) log_string(bss.logsock, "filesize is 0", BYTE_LOG_STR);
}
if((FSCloseFile (pClient, pCmd, handle, -1)) < 0){
if((FSCloseFile (pClient, pCmd, handle, error)) < FS_STATUS_OK){
log_string(bss.logsock, "FSCloseFile failed", BYTE_LOG_STR);
failed = 1;
}
@ -392,10 +430,11 @@ int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char
__os_snprintf(logbuffer, sizeof(logbuffer), "dir: %s",namebuffer);
log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
if(DEBUG_LOG) log_string(bss.logsock, newpath, BYTE_LOG_STR);
if(FSMakeDir(pClient, pCmd, newpath, -1) == 0){
int ret = 0;
if((ret = FSMakeDir(pClient, pCmd, newpath, -1)) == FS_STATUS_OK || ret == FS_STATUS_EXISTS ){
char op_offset[strlen(relativepath) + strlen(namebuffer)+ 1 + 1];
__os_snprintf(op_offset, sizeof(op_offset), "%s%s/",relativepath,namebuffer);
int injectedsub = injectFiles(pClient, pCmd, newpath,op_offset,pBuffer,buffer_size,error);
int injectedsub = injectFiles(pClient, pCmd, newpath,op_offset,basepath,pBuffer,buffer_size,error);
if(injectedsub == -1){
failed = 1;
}else{
@ -414,31 +453,45 @@ int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char
}
}
int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int filesize,void * pBuffer,int buf_size){
int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int filesize, char * basepath,void * pBuffer,int buf_size){
int client = client_num(pClient);
int failed = 0;
int myhandle;
int ret = 0;
char logbuffer[255];
if((cafiine_fopen(bss.socket_fsa[client], &ret, filepath, "r", &myhandle)) == 0 && ret == 0){
if((cafiine_fopen(bss.socket_fsa[client], &ret, filepath, "r", &myhandle)) == 0 && ret == FS_STATUS_OK){
if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "cafiine_fopen with handle %d",myhandle);
if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
int retsize = 0;
int pos = 0;
while(pos < filesize){
if(DEBUG_LOG) log_string(bss.logsock, "reading", BYTE_LOG_STR);
if(cafiine_fread(bss.socket_fsa[client], &retsize, pBuffer, buf_size , myhandle) == 0){
if(cafiine_fread(bss.socket_fsa[client], &retsize, pBuffer, buf_size , myhandle) == FS_STATUS_OK){
if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "got %d",retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
int fwrite = 0;
if((fwrite = my_FSWriteFile(pClient, pCmd, pBuffer,sizeof(char),retsize,handle,0,0x0200)) >= 0){
if((fwrite = my_FSWriteFile(pClient, pCmd, pBuffer,sizeof(char),retsize,handle,0,0x0200)) >= FS_STATUS_OK){
if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "wrote %d",retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
}else{
if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "my_FSWriteFile failed with error: %d",fwrite);
if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
log_string(bss.logsock, "error while FSWriteFile", BYTE_LOG_STR);
if(fwrite == FS_STATUS_JOURNAL_FULL){
log_string(bss.logsock, "journal is full, flushing it now.", BYTE_LOG_STR);
if(FSFlushQuota(pClient,pCmd,basepath,FS_RET_ALL_ERROR) == FS_STATUS_OK){
log_string(bss.logsock, "success", BYTE_LOG_STR);
failed = 2;
break;
}else{
log_string(bss.logsock, "failed", BYTE_LOG_STR);
failed = 1;
break;
}
}
__os_snprintf(logbuffer, sizeof(logbuffer), "my_FSWriteFile failed with error: %d",fwrite);
log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
//log_string(bss.logsock, "error while FSWriteFile", BYTE_LOG_STR);
failed = 1;
break;
}
if(DEBUG_LOG)__os_snprintf(logbuffer, sizeof(logbuffer), "old p %d new p %d",pos,pos+retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
@ -451,7 +504,7 @@ int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int f
}
int result = 0;
if((cafiine_fclose(bss.socket_fsa[client], &result, myhandle,0)) == 0 && result == 0){
if((cafiine_fclose(bss.socket_fsa[client], &result, myhandle,0)) == 0 && result == FS_STATUS_OK){
if(DEBUG_LOG) log_string(bss.logsock, "cafiine_fclose success", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "cafiine_fclose failed", BYTE_LOG_STR);
@ -477,14 +530,14 @@ void doFlushOrRollback(void *pClient, void *pCmd,int result,char *savepath){
__os_snprintf(logbuffer, sizeof(logbuffer), "injected %d files",result);
log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
log_string(bss.logsock, "Flushing data now", BYTE_LOG_STR);
if(FSFlushQuota(pClient,pCmd,savepath,-1) == 0){
if(FSFlushQuota(pClient,pCmd,savepath,FS_RET_ALL_ERROR) == FS_STATUS_OK){
log_string(bss.logsock, "success", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "failed", BYTE_LOG_STR);
}
}else{
log_string(bss.logsock, "injection failed, trying to restore the data", BYTE_LOG_STR);
if(FSRollbackQuota(pClient,pCmd,savepath,-1) == 0){
if(FSRollbackQuota(pClient,pCmd,savepath,FS_RET_ALL_ERROR) == FS_STATUS_OK){
log_string(bss.logsock, "rollback done", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "rollback failed", BYTE_LOG_STR);
@ -499,10 +552,13 @@ void init_Save(unsigned char slotNo){
OSDynLoad_Acquire("nn_save.rpl", &save_handle);
OSDynLoad_FindExport(save_handle, 0, "SAVEInit", (void **)&SAVEInit);
OSDynLoad_FindExport(save_handle, 0, "SAVEInitSaveDir", (void **)&SAVEInitSaveDir);
bss.saveinitfs = 1;
SAVEInit();
if(DEBUG_LOG) log_string(bss.logsock, "saveinit done", BYTE_LOG_STR);
SAVEInitSaveDir(slotNo);
if(DEBUG_LOG) log_string(bss.logsock, "SAVEInitSaveDir done", BYTE_LOG_STR);
SAVEInitSaveDir(255U);
if(DEBUG_LOG) log_string(bss.logsock, "SAVEInitSaveDir 2 done", BYTE_LOG_STR);
}
long getPesistentID(unsigned char * slotno){
@ -540,20 +596,21 @@ int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle){
char full_path[strlen(path) + 1 + strlen(dir_entry.name) +1];
__os_snprintf(full_path, sizeof(full_path), "%s/%s",path,dir_entry.name);
if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){
log_string(bss.logsock, "recursive deletion", BYTE_LOG_STR);
if(DEBUG_LOG) log_string(bss.logsock, "recursive deletion", BYTE_LOG_STR);
if(remove_files_in_dir(pClient,pCmd,full_path,my_handle) == -1) return -1;
}else{
}
char buffer[strlen(full_path) + 50];
__os_snprintf(buffer, sizeof(buffer), "deleting %s",full_path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
if((ret = FSRemove(pClient,pCmd,full_path,-1)) < 0){
if((ret = FSRemove(pClient,pCmd,full_path,FS_RET_ALL_ERROR)) < FS_STATUS_OK){
__os_snprintf(buffer, sizeof(buffer), "error: %d on removing %s",ret,full_path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
return -1;
}
}
}
if((FSCloseDir(pClient, pCmd, handle, FS_RET_NO_ERROR)) < 0 ){
if((FSCloseDir(pClient, pCmd, handle, FS_RET_NO_ERROR)) < FS_STATUS_OK ){
log_string(bss.logsock, "error while closing dir", BYTE_LOG_STR);
return -1;
}
@ -582,4 +639,5 @@ struct magic_t {
MAKE_MAGIC(FSDelClient),
MAKE_MAGIC(FSWriteFile),
MAKE_MAGIC(FSFlushQuota),
MAKE_MAGIC(_Exit),
};

View File

@ -36,6 +36,8 @@
#define MASK_COMMON 0x0200
#define MASK_COMMON_CLEAN 0x0400
void GX2WaitForVsync(void);
void *memcpy(void *dst, const void *src, int bytes);
void *memset(void *dst, int val, int bytes);
@ -68,6 +70,7 @@ extern FSStatus FSRemove(FSClient *pClient, FSCmdBlock *pCmd, const char *path,
extern FSStatus FSRollbackQuota(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling);
extern void OSDynLoad_Acquire (char* rpl, unsigned int *handle);
extern void OSDynLoad_FindExport (unsigned int handle, int isdata, char *symbol, void *address);
extern void _Exit();
extern void socket_lib_init();
extern int socket(int domain, int type, int protocol);
@ -79,13 +82,13 @@ extern int recv(int socket, void *buffer, int size, int flags);
extern int __os_snprintf(char* s, int n, const char * format, ...);
int saviine_readdir(int sock, char * path,char * resultname, int * resulttype,int *filesize);
int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char * pBuffer, int buffer_size, int error);
int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath, char * basepath, char * pBuffer, int buffer_size, int error);
void doFlushOrRollback(void *pClient,void *pCmd,int result,char *savepath);
void injectSaveData(void *pClient, void *pCmd,long persistentID,int error);
void dumpSavaData(void *pClient, void *pCmd,long persistentID,int error);
long getPesistentID(unsigned char * slotno);
void init_Save(unsigned char slotNo);
int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int filesize,void * pBuffer,int buf_size);
int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int filesize, char * basepath,void * pBuffer,int buf_size);
void handle_saves(void *pClient, void *pCmd,int error);
void hook(void * pClient,void * pCmd, int error);
int dump_dir(void *pClient, void *pCmd, char *path, void * pBuffer, int size,int error, int handle);
@ -114,7 +117,9 @@ struct bss_t {
int socket_fs[MAX_CLIENT];
char save_path[255];
volatile int saveFolderChecked;
volatile void * on_start_hook_client;
volatile int lock;
volatile int saveinitfs;
int logsock;
};

View File

@ -12,11 +12,6 @@ static int cafiine_handshake(int sock);
void GX2WaitForVsync(void);
void cafiine_connect(int *psock) {
extern unsigned int server_ip;
struct sockaddr_in addr;

View File

@ -47,6 +47,7 @@ PROVIDE(FSIsEof = 0x106f610);
PROVIDE(FSWriteFile = 0x106F228);
PROVIDE(FSFlushQuota = 0x106FAC8);
PROVIDE(FSRollbackQuota = 0x106FC48);
PROVIDE(_Exit = 0x101CD70);
/* */
PROVIDE(FSGetStat = 0x0106fdc8);

View File

@ -10,10 +10,16 @@
#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE
#define FS_STATUS_OK 0
#define FS_STATUS_EXISTS -5
#define FS_STATUS_STORAGE_FULL -12
#define FS_STATUS_JOURNAL_FULL -13
#define FS_RET_UNSUPPORTED_CMD 0x0400
#define FS_RET_NO_ERROR 0x0000
#define FS_RET_ALL_ERROR (uint)(-1)
/* directory entry stat flag */
#define FS_STAT_ATTRIBUTES_SIZE (48) /* size of FS-specific attributes field */
#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000 /* entry is directory */

Binary file not shown.

Binary file not shown.

View File

@ -308,7 +308,7 @@ static int show_ip_selection_screen(unsigned int coreinit_handle, unsigned int *
while (1)
{
// Print message
PRINT_TEXT1(14, 1, "-- SAVIINE 0.3 (a cafiine mod) --");
PRINT_TEXT1(14, 1, "-- SAVIINE 1.0 (a cafiine mod) --");
PRINT_TEXT2(0, 5, "%s : %3d.%3d.%3d.%3d", "1. Server IP", ip.digit[0], ip.digit[1], ip.digit[2], ip.digit[3]);
PRINT_TEXT1(0, 6, "2. Press A to install saviine");
PRINT_TEXT1(42, 17, "home button to exit ...");

View File

@ -1 +0,0 @@
saviine_server.exe fastmode

Binary file not shown.

140
saviine/server/src/DumpDialog.Designer.cs generated Normal file
View File

@ -0,0 +1,140 @@
namespace saviine_server
{
partial class DumpDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btn_ok = new System.Windows.Forms.Button();
this.btn_cancel = new System.Windows.Forms.Button();
this.lbl_message = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.Inj = new System.Windows.Forms.Label();
this.checkBoxUser = new System.Windows.Forms.CheckBox();
this.checkBoxCommon = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// btn_ok
//
this.btn_ok.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btn_ok.Location = new System.Drawing.Point(15, 133);
this.btn_ok.Name = "btn_ok";
this.btn_ok.Size = new System.Drawing.Size(81, 21);
this.btn_ok.TabIndex = 0;
this.btn_ok.Text = "OK";
this.btn_ok.UseVisualStyleBackColor = true;
this.btn_ok.Click += new System.EventHandler(this.btn_ok_Click);
//
// btn_cancel
//
this.btn_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btn_cancel.Location = new System.Drawing.Point(148, 133);
this.btn_cancel.Name = "btn_cancel";
this.btn_cancel.Size = new System.Drawing.Size(81, 21);
this.btn_cancel.TabIndex = 1;
this.btn_cancel.Text = "Cancel";
this.btn_cancel.UseVisualStyleBackColor = true;
//
// lbl_message
//
this.lbl_message.AutoSize = true;
this.lbl_message.Location = new System.Drawing.Point(12, 9);
this.lbl_message.Name = "lbl_message";
this.lbl_message.Size = new System.Drawing.Size(217, 13);
this.lbl_message.TabIndex = 3;
this.lbl_message.Text = "Got a dump request for 00050000-10157F00";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 51);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(84, 13);
this.label1.TabIndex = 5;
this.label1.Text = "Dump user save";
//
// Inj
//
this.Inj.AutoSize = true;
this.Inj.Location = new System.Drawing.Point(12, 86);
this.Inj.Name = "Inj";
this.Inj.Size = new System.Drawing.Size(104, 13);
this.Inj.TabIndex = 7;
this.Inj.Text = "Dump common save";
//
// checkBoxUser
//
this.checkBoxUser.AutoSize = true;
this.checkBoxUser.Checked = true;
this.checkBoxUser.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBoxUser.Location = new System.Drawing.Point(202, 50);
this.checkBoxUser.Name = "checkBoxUser";
this.checkBoxUser.Size = new System.Drawing.Size(15, 14);
this.checkBoxUser.TabIndex = 9;
this.checkBoxUser.UseVisualStyleBackColor = true;
//
// checkBoxCommon
//
this.checkBoxCommon.AutoSize = true;
this.checkBoxCommon.Checked = true;
this.checkBoxCommon.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBoxCommon.Location = new System.Drawing.Point(202, 85);
this.checkBoxCommon.Name = "checkBoxCommon";
this.checkBoxCommon.Size = new System.Drawing.Size(15, 14);
this.checkBoxCommon.TabIndex = 10;
this.checkBoxCommon.UseVisualStyleBackColor = true;
//
// DumpDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(257, 166);
this.Controls.Add(this.checkBoxCommon);
this.Controls.Add(this.checkBoxUser);
this.Controls.Add(this.Inj);
this.Controls.Add(this.label1);
this.Controls.Add(this.lbl_message);
this.Controls.Add(this.btn_cancel);
this.Controls.Add(this.btn_ok);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "DumpDialog";
this.Text = "Dump request";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btn_ok;
private System.Windows.Forms.Button btn_cancel;
private System.Windows.Forms.Label lbl_message;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label Inj;
private System.Windows.Forms.CheckBox checkBoxUser;
private System.Windows.Forms.CheckBox checkBoxCommon;
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace saviine_server
{
public partial class DumpDialog : Form
{
private Boolean dumpUser = false;
private Boolean dumpCommon = false;
public Boolean DumpCommon
{
get { return dumpCommon; }
}
public Boolean DumpUser
{
get { return dumpUser; }
}
private static string savePath;
public DumpDialog(string title_id, long persistentID)
{
InitializeComponent();
}
private void btn_ok_Click(object sender, EventArgs e)
{
dumpUser = checkBoxUser.Checked;
dumpCommon = checkBoxCommon.Checked;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -425,56 +425,55 @@ namespace saviine_server
}
}
writer.Write(BYTE_OK);
Console.WriteLine("InjectionEND");
//Console.WriteLine("InjectionEND");
break;
}
case BYTE_DUMPSTART:
{
long wiiUpersistentID = (long)reader.ReadUInt32();
int dumpCommon = 0;
Boolean dumpCommon = false;
Boolean dumpUser = false;
currentPersistentID = wiiUpersistentID;
dumpCommon = 1;
/*
Boolean injectioncanceled = false;
SaveSelectorDialog ofd = new SaveSelectorDialog(title_id, wiiUpersistentID);
Boolean dumpcanceled = false;
DumpDialog ofd = new DumpDialog(title_id, wiiUpersistentID);
try
{
DialogResult result = ofd.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
currentPersistentID = ofd.NewPersistentID;
dumpUser = ofd.DumpUser;
dumpCommon = ofd.DumpCommon;
//Console.WriteLine("Injecting " + currentPersistentID.ToString() + " into " + wiiUpersistentID.ToString() + " for title id " + title_id);
if (dumpCommon == 1) Console.WriteLine("clean and inject common folder");
if (dumpCommon == 2) Console.WriteLine("inject common folder");
if (dumpCommon > 0 && currentPersistentID == 0) currentPersistentID = COMMON_PERSISTENTID;
if (dumpCommon) Console.WriteLine("dumping common data");
if (dumpUser) Console.WriteLine("dumping user data");
}
else
{
Console.WriteLine("dump canceled");
injectioncanceled = true;
dumpcanceled = true;
}
}
catch (Exception e)
{
Console.WriteLine("dump canceled");
injectioncanceled = true;
dumpcanceled = true;
}
if (injectioncanceled)
if (dumpcanceled)
{
writer.Write(BYTE_NORMAL);
}
else
{
writer.Write(BYTE_SPECIAL);
}*/
writer.Write(BYTE_SPECIAL);
}
int dumpmask = MASK_NORMAL;
if (currentPersistentID != 0 && currentPersistentID != COMMON_PERSISTENTID)
if (dumpUser)
dumpmask |= MASK_USER;
if (dumpCommon == 1)
if (dumpCommon)
{
dumpmask |= MASK_COMMON;
}
@ -496,7 +495,7 @@ namespace saviine_server
}
}
writer.Write(BYTE_OK);
Console.WriteLine("dumpEND");
//Console.WriteLine("dumpEND");
break;
}

View File

@ -6,3 +6,4 @@ G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debu
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.csproj.GenerateResource.Cache
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.SaveSelectorDialog.resources
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.csprojResolveAssemblyReference.cache
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.DumpDialog.resources

View File

@ -57,6 +57,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DumpDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="DumpDialog.Designer.cs">
<DependentUpon>DumpDialog.cs</DependentUpon>
</Compile>
<Compile Include="SaveSelectorDialog.cs">
<SubType>Form</SubType>
</Compile>
@ -94,6 +100,9 @@
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="DumpDialog.resx">
<DependentUpon>DumpDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SaveSelectorDialog.resx">
<DependentUpon>SaveSelectorDialog.cs</DependentUpon>
</EmbeddedResource>

View File

@ -161,7 +161,7 @@ function sprayCode(n) {
str += unescape("%u6164%u0000%u4f53%u4973%u5468%u7265%u6164%u5465%u726d%u696e%u6174%u6564%u0000%u0000%u5468%u7265%u6164%u206d%u656d%u6f72%u7920%u616c%u6c6f%u6361%u7469%u6f6e%u2066%u6169%u6c65%u642e%u0000%u0000");
str += unescape("%u4661%u696c%u6564%u2074%u6f20%u6372%u6561%u7465%u2074%u6872%u6561%u6400%u4f53%u5363%u7265%u656e%u496e%u6974%u0000%u0000%u4f53%u5363%u7265%u656e%u4765%u7442%u7566%u6665%u7253%u697a%u6545%u7800");
str += unescape("%u4f53%u5363%u7265%u656e%u5365%u7442%u7566%u6665%u7245%u7800%u4f53%u5363%u7265%u656e%u436c%u6561%u7242%u7566%u6665%u7245%u7800%u0000%u4f53%u5363%u7265%u656e%u466c%u6970%u4275%u6666%u6572%u7345");
str += unescape("%u7800%u0000%u4f53%u5363%u7265%u656e%u5075%u7446%u6f6e%u7445%u7800%u0000%u7670%u6164%u2e72%u706c%u0000%u0000%u5650%u4144%u5265%u6164%u0000%u0000%u2d2d%u2053%u4156%u4949%u4e45%u2030%u2e33%u2028");
str += unescape("%u7800%u0000%u4f53%u5363%u7265%u656e%u5075%u7446%u6f6e%u7445%u7800%u0000%u7670%u6164%u2e72%u706c%u0000%u0000%u5650%u4144%u5265%u6164%u0000%u0000%u2d2d%u2053%u4156%u4949%u4e45%u2031%u2e30%u2028");
str += unescape("%u6120%u6361%u6669%u696e%u6520%u6d6f%u6429%u202d%u2d00%u0000%u2573%u203a%u2025%u3364%u2e25%u3364%u2e25%u3364%u2e25%u3364%u0000%u0000%u312e%u2053%u6572%u7665%u7220%u4950%u0000%u0000%u322e%u2050");
str += unescape("%u7265%u7373%u2041%u2074%u6f20%u696e%u7374%u616c%u6c20%u7361%u7669%u696e%u6500%u0000%u686f%u6d65%u2062%u7574%u746f%u6e20%u746f%u2065%u7869%u7420%u2e2e%u2e00%u7676%u7600%u4d65%u6d6f%u7279%u2061");
str += unescape("%u6c6c%u6f63%u6174%u696f%u6e20%u6661%u696c%u6564%u0000%u0000%u5552%u4c20%u6e6f%u7420%u666f%u756e%u6400%u0000%u6e6c%u6962%u6375%u726c%u0000%u0000%u6375%u726c%u5f65%u6173%u795f%u696e%u6974%u0000");

Binary file not shown.