injection and dumper seems to work now!

- lot of cleanup
- needs more testing
- changed folder structure for dumps
- added dialog for injection

seem to crash for some games after dumping.
This commit is contained in:
Maschell 2015-10-25 18:26:25 +01:00
parent 7356f4029c
commit 721c983122
13 changed files with 897 additions and 447 deletions

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 := -O2 -Wall -x c -std=gnu99 \
CFLAGS := -O0 -Wall -x c -std=gnu99 \
-ffreestanding \
-mrvl -mcpu=750 -meabi -mhard-float -fshort-wchar \
-msdata=none -memb -ffunction-sections -fdata-sections \

View File

@ -5,20 +5,8 @@
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".magicptr"))); \
res my_ ## name(__VA_ARGS__)
#define DEBUG_LOG 0
extern FSStatus FSOpenDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, int *dh, FSRetFlag errHandling);
extern FSStatus FSReadDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSDirEntry *dir_entry, FSRetFlag errHandling);
extern FSStatus FSChangeDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling);
extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFlag errHandling);
extern FSStatus FSReadFile(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error);
extern FSStatus FSSetPosFile(FSClient *pClient, FSCmdBlock *pCmd, int fd, int pos, int error);
extern FSStatus FSCloseFile (FSClient *pClient, FSCmdBlock *pCmd, int fd, int error);
extern FSStatus FSMakeDir(FSClient *pClient, FSCmdBlock *pCmd,const char *path, FSRetFlag errHandling);
extern FSStatus FSRemove(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);
void GX2WaitForVsync(void);
static void handle_saves(void *pClient, void *pCmd,int error, int client);
static void hook(void * pClient,void * pCmd, int error, int client);
#define BUFFER_SIZE (1024)*100*2
#define BUFFER_SIZE_STEPS 0x200
DECL(int, FSAInit, void) {
if ((int)bss_ptr == 0x0a000000) {
@ -56,24 +44,6 @@ static int strlen(char* path) {
return i;
}
static int strcmp(const char *s1, const char *s2)
{
while(*s1 && *s2)
{
if(*s1 != *s2) {
return -1;
}
s1++;
s2++;
}
if(*s1 != *s2) {
return -1;
}
return 0;
}
static int client_num_alloc(void *pClient) {
int i;
@ -153,7 +123,7 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) {
// Init command block.
FSInitCmdBlock(pCmd);
hook(pClient, pCmd,-1, client);
hook(pClient, pCmd,-1);
bss.saveFolderChecked = 2;
error: real_FSDelClient(pClient);
@ -168,333 +138,259 @@ DECL(int, FSAddClientEx, void *r3, void *r4, void *r5) {
return res;
}
static int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle){
int ret = 0;
if ((ret = FSOpenDir(pClient, pCmd, path, &handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){
char buffer[strlen(path) + 25];
__os_snprintf(buffer, sizeof(buffer), "remove files in dir %s",path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
FSDirEntry dir_entry;
while (FSReadDir(pClient, pCmd, handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK)
{
char full_path[255];
int i=0;
char *path_ptr = (char *)path;
while(*path_ptr) {
full_path[i++] = *path_ptr++;
}
full_path[i++] = '/';
char *dir_name_ptr = (char *)dir_entry.name;
while(*dir_name_ptr) {
full_path[i++] = *dir_name_ptr++;
}
full_path[i++] = '\0';
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){
__os_snprintf(buffer, sizeof(buffer), "error: %d on %s",ret,full_path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
return -1;
}
}
if((FSCloseDir(pClient, pCmd, handle, FS_RET_NO_ERROR)) < 0 ){
log_string(bss.logsock, "error while closing dir", BYTE_LOG_STR);
}
}
return 0;
}
static void hook(void * pClient,void * pCmd, int error, int client){
void hook(void * pClient,void * pCmd, int error){
log_string(bss.logsock, "hook", BYTE_LOG_STR);
handle_saves(pClient, pCmd,-1, client);
handle_saves(pClient, pCmd,-1);
}
static void init_Save(){
int (*SAVEInit)();
unsigned int save_handle;
OSDynLoad_Acquire("nn_save.rpl", &save_handle);
OSDynLoad_FindExport(save_handle, 0, "SAVEInit", (void **)&SAVEInit);
SAVEInit();
}
static long getPesistentID(){
unsigned int nn_act_handle;
unsigned long (*GetPersistentIdEx)(unsigned char);
int (*GetSlotNo)(void);
void (*nn_Initialize)(void);
void (*nn_Finalize)(void);
OSDynLoad_Acquire("nn_act.rpl", &nn_act_handle);
OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", (void **)&GetPersistentIdEx);
OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", (void **)&GetSlotNo);
OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", (void **)&nn_Initialize);
OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", (void **)&nn_Finalize);
nn_Initialize(); // To be sure that it is really Initialized
unsigned char slotno = GetSlotNo();
long idlong = GetPersistentIdEx(slotno);
nn_Finalize(); //must be called an equal number of times to nn_Initialize
return idlong;
}
#define DUMP_BLOCK_SIZE (0x200 * 100)
#define DUMP_BLOCK_SIZE_SLOW (0x20 * 100)
static int dump_dir(void *pClient,int client, void *pCmd, char *path, int error, int handle){
int dir_handle = handle;
int my_handle = handle +1;
int ret = 0;
if ((ret = FSOpenDir(pClient, pCmd, path, &dir_handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK)
{
char buffer[strlen(path) + 25];
__os_snprintf(buffer, sizeof(buffer), "open dir %s",path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
FSDirEntry dir_entry;
while (FSReadDir(pClient, pCmd, dir_handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK)
{
char full_path[255];
int i=0;
char *path_ptr = (char *)path;
while(*path_ptr) {
full_path[i++] = *path_ptr++;
}
full_path[i++] = '/';
char *dir_name_ptr = (char *)dir_entry.name;
while(*dir_name_ptr) {
full_path[i++] = *dir_name_ptr++;
}
full_path[i++] = '\0';
if((dir_entry.stat.flag&FS_STAT_FLAG_IS_DIRECTORY) == FS_STAT_FLAG_IS_DIRECTORY){
log_string(bss.logsock, "-> dir", BYTE_LOG_STR);
dump_dir(pClient,client, pCmd,full_path,-1,my_handle);
}else{
//DUMP
ret = FSOpenFile(pClient, pCmd, full_path, "r", &my_handle, FS_RET_ALL_ERROR);
if (ret >= 0) {
__os_snprintf(buffer, sizeof(buffer), "dumping %s",dir_entry.name);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
int my_ret = cafiine_send_handle(bss.socket_fsa[client], client, full_path, my_handle);
int size = (my_ret == 1 ? DUMP_BLOCK_SIZE : DUMP_BLOCK_SIZE_SLOW);
void * buffer = memalign(sizeof(char) * size, 0x40);
int ret2;
while ((ret2 = FSReadFile(pClient, pCmd, buffer, 1, size, my_handle, 0, 0)) > 0)
cafiine_send_file(bss.socket_fsa[client], buffer, ret2, my_handle);
cafiine_fclose(bss.socket_fsa[client], &ret2, my_handle,1);
FSSetPosFile(pClient, pCmd, my_handle, 0, FS_RET_ALL_ERROR);
free(buffer);
FSCloseFile(pClient, pCmd, my_handle, -1);
}else{
char type[2];
type[0] = '9' + ret;
type[1] = '\0';
log_string(bss.logsock, type, BYTE_LOG_STR);
}
}
}
FSCloseDir(pClient, pCmd, dir_handle, FS_RET_NO_ERROR);
}
return 0;
}
#define BUFFER_SIZE (1024)*100
static void handle_saves(void *pClient, void *pCmd,int error, int client){
log_string(bss.logsock, "handle_saves", BYTE_LOG_STR);
init_Save();
long id = getPesistentID();
void handle_saves(void *pClient, void *pCmd,int error){
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, "user savedata", BYTE_LOG_STR);
log_string(bss.logsock, "getting mode", BYTE_LOG_STR);
if(getMode(bss.socket_fsa[client],&mode)){
if(id >= 0x80000000 && id <= 0x90000000){
char savepath[20];
__os_snprintf(savepath, sizeof(savepath), "/vol/save/%08x",id);
log_string(bss.logsock, "Getting mode!", BYTE_LOG_STR);
{
if(mode == BYTE_MODE_D){
log_string(bss.logsock, "dump mode!", BYTE_LOG_STR);
dump_dir(pClient,client,pCmd,savepath,-1,50);
}else if(mode == BYTE_MODE_I){
log_string(bss.logsock, "inject mode", BYTE_LOG_STR);
log_string(bss.logsock, "deleting current save", BYTE_LOG_STR);
remove_files_in_dir(pClient,pCmd,savepath,0);
int buf_size = BUFFER_SIZE;
char * pBuffer;
int failed = 0;
do{
buf_size -= 0x200;
if(buf_size < 0){
log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR);
failed = 1;
break;
}
pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40);
}while(!pBuffer);
if(!failed){
int result = injectFiles(pClient,pCmd,savepath,"/",pBuffer,buf_size,-1);
if(result == -1){
log_string(bss.logsock, "injection failed, trying to restore the data", BYTE_LOG_STR);
//TODO FSRollbackQuota
}else{
char logbugger[50];
__os_snprintf(logbugger, sizeof(logbugger), "injected %d files, flushing the data now",result);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
if(FSFlushQuota(pClient,pCmd,savepath,-1) == 0){
log_string(bss.logsock, "success", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "failed", BYTE_LOG_STR);
}
}
}
}
}
}
if(mode == BYTE_MODE_D){
log_string(bss.logsock, "dumping common savedata", BYTE_LOG_STR);
dump_dir(pClient,client,pCmd,"/vol/save/common/",error,60);
log_string(bss.logsock, "done!", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "common injection", BYTE_LOG_STR);
int buf_size = BUFFER_SIZE;
char * pBuffer;
int failed = 0;
do{
buf_size -= 0x200;
if(buf_size < 0){
log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR);
failed = 1;
break;
}
pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40);
}while(!pBuffer);
if(!failed){
int result = injectFiles(pClient,pCmd,"/vol/save/common/","/",pBuffer,buf_size,-1);
if(result == -1){
log_string(bss.logsock, "injection failed, trying to restore the data", BYTE_LOG_STR);
//TODO FSRollbackQuota
}else{
char logbugger[50];
__os_snprintf(logbugger, sizeof(logbugger), "injected %d files, flushing the data now",result);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
if(FSFlushQuota(pClient,pCmd,"/vol/save/common/",-1) == 0){
log_string(bss.logsock, "success", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "failed", BYTE_LOG_STR);
}
}
if(mode == BYTE_MODE_D){
log_string(bss.logsock, "dump mode!", BYTE_LOG_STR);
dumpSavaData(pClient, pCmd,id,error);
}else if(mode == BYTE_MODE_I){
log_string(bss.logsock, "inject mode", BYTE_LOG_STR);
injectSaveData(pClient,pCmd,id,error);
}
}
}
}
void dumpSavaData(void *pClient, void *pCmd,long persistentID,int error){
int client = client_num(pClient);
/*
Allocate buffer for injection
*/
int buf_size = BUFFER_SIZE;
char * pBuffer;
int failed = 0;
do{
buf_size -= BUFFER_SIZE_STEPS;
if(buf_size < 0){
log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR);
failed = 1;
break;
}
pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40);
}while(!pBuffer);
if(!failed){
int mask = 0;
char buffer[60];
__os_snprintf(buffer, sizeof(buffer), "allocated %d bytes",buf_size);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
if(saviine_start_dump(bss.socket_fsa[client], persistentID,&mask)){
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, "error dumping user dir", BYTE_LOG_STR);
failed = 1;
}
}
if((mask & MASK_COMMON) == MASK_COMMON && !failed){
char * commonDir = "/vol/save/common";
log_string(bss.logsock, "dumping common savedata", BYTE_LOG_STR);
if(dump_dir(pClient,pCmd,commonDir,pBuffer,buf_size,error,60) == -1){
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);
}
}
}
int dump_dir(void *pClient, void *pCmd, char *path, void * pBuffer, int size,int error, int handle){
int client = client_num(pClient);
int dir_handle = handle;
int my_handle = handle +1;
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];
__os_snprintf(buffer, sizeof(buffer), "open dir %s",path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
FSDirEntry dir_entry;
while (FSReadDir(pClient, pCmd, dir_handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK && final_result == 0)
{
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, "-> dir", BYTE_LOG_STR);
if(dump_dir(pClient, pCmd,full_path,pBuffer,size,-1,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);
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)
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);
}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);
}else{
log_string(bss.logsock, "error on FSOpenDir()", BYTE_LOG_STR);
final_result = -1;
}
return final_result;
}
/**************************
Injection functions
**************************/
void injectSaveData(void *pClient, void *pCmd,long persistentID,int error){
int client = client_num(pClient);
char logbuffer[255];
/*
Allocate buffer for injection
*/
int buf_size = BUFFER_SIZE;
char * pBuffer;
int failed = 0;
do{
buf_size -= BUFFER_SIZE_STEPS;
if(buf_size < 0){
log_string(bss.logsock, "error on buffer allocation", BYTE_LOG_STR);
failed = 1;
break;
}
pBuffer = (char *)MEMAllocFromDefaultHeapEx(buf_size, 0x40);
}while(!pBuffer);
if(!failed){
int result = 0;
int mask = 0;
if((result = saviine_start_injection(bss.socket_fsa[client], persistentID,&mask))){
if((mask & MASK_USER) == MASK_USER){
char savepath[20];
__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);
if(remove_files_in_dir(pClient,pCmd,savepath,0) == -1){
failed = 1;
}else{
/*
Inject Save
*/
result = injectFiles(pClient,pCmd,savepath,"/",pBuffer,buf_size,-1);
doFlushOrRollback(pClient,pCmd,result,savepath);
}
}
if((mask & MASK_COMMON) == MASK_COMMON && !failed){
char * commonDir = "/vol/save/common";
if((mask & MASK_COMMON_CLEAN) == MASK_COMMON_CLEAN){
log_string(bss.logsock, "deleting common save", BYTE_LOG_STR);
if(remove_files_in_dir(pClient,pCmd,commonDir,0) == -1){
failed = 1;
}
}
if(!failed){
/*
Inject common
*/
result = injectFiles(pClient,pCmd,commonDir,"/",pBuffer,buf_size,-1);
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);
}
}
}
int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char * pBuffer, int buffer_size, int error){
//FSStatus (*FSWriteFileWithPos) (FSClient *pClient, FSCmdBlock *pCmd, const void *source,int size,int count,int fpos,int fileHandle,int flag,FSRetFlag errHandling);
int client = client_num(pClient);
int failed = 0;
int filesinjected = 0;
int type = 0;
log_string(bss.logsock, "injecting files", BYTE_LOG_STR);
char namebuffer[255];
char logbugger[255];
char logbuffer[255];
int filesize = 0;
if(!failed){
__os_snprintf(logbugger, sizeof(logbugger), "buffer size: %d bytes",buffer_size);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
while(getFiles(bss.socket_fsa[client],path,namebuffer, &type,&filesize) && !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)];
__os_snprintf(newpath, sizeof(newpath), "%s/%s",path,namebuffer);
if(type == BYTE_FILE){
__os_snprintf(logbugger, sizeof(logbugger), "file: %s%s size: %d",relativepath,namebuffer,filesize);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
__os_snprintf(logbuffer, sizeof(logbuffer), "file: %s%s size: %d",relativepath,namebuffer,filesize);
log_string(bss.logsock, logbuffer, BYTE_LOG_STR);
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(DEBUG_LOG) log_string(bss.logsock, "file opened and created", BYTE_LOG_STR);
if(filesize > 0){
int myhandle;
int ret = 0;
if((cafiine_fopen(bss.socket_fsa[client], &ret, newpath, "r", &myhandle)) == 0 && ret == 0){
if(DEBUG_LOG)__os_snprintf(logbugger, sizeof(logbugger), "cafiine_fopen with handle %d",myhandle);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
int size = sizeof(char);
int count = buffer_size;
int retsize = 0;
int pos = 0;
while(pos < filesize){
if(DEBUG_LOG) log_string(bss.logsock, "reading", BYTE_LOG_STR);
if(DEBUG_LOG)__os_snprintf(logbugger, sizeof(logbugger), "count %d",count);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
if(cafiine_fread(bss.socket_fsa[client], &retsize, pBuffer, count, myhandle) == 0){
__os_snprintf(logbugger, sizeof(logbugger), "got %d",retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
int fwrite = 0;
if((fwrite = my_FSWriteFile(pClient, pCmd, pBuffer,size,retsize,handle,0,0x0200)) >= 0){
__os_snprintf(logbugger, sizeof(logbugger), "wrote %d",retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
}else{
__os_snprintf(logbugger, sizeof(logbugger), "my_FSWriteFile failed with error: %d",fwrite);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
log_string(bss.logsock, "error while FSWriteFile", BYTE_LOG_STR);
failed = 1;
}
__os_snprintf(logbugger, sizeof(logbugger), "old p %d new p %d",pos,pos+retsize);
if(DEBUG_LOG) log_string(bss.logsock, logbugger, BYTE_LOG_STR);
pos += retsize;
}else{
log_string(bss.logsock, "error while recieving file", BYTE_LOG_STR);
failed = 1;
break;
}
}
int result = 0;
if((cafiine_fclose(bss.socket_fsa[client], &result, myhandle,0)) == 0 && result == 0){
if(DEBUG_LOG) log_string(bss.logsock, "cafiine_fclose success", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "cafiine_fclose failed", BYTE_LOG_STR);
failed = 1;
}
}else{
log_string(bss.logsock, "cafiine_fopen failed", BYTE_LOG_STR);
failed = 1;
}
failed = doInjectForFile(pClient,pCmd,handle,newpath,filesize,pBuffer,buffer_size);
}else{
if(DEBUG_LOG) log_string(bss.logsock, "filesize is 0", BYTE_LOG_STR);
}
if((FSCloseFile (pClient, pCmd, handle, -1)) < 0){
log_string(bss.logsock, "FSCloseFile failed", BYTE_LOG_STR);
failed = 1;
}
}else{
log_string(bss.logsock, "opening the file failed", BYTE_LOG_STR);
failed = 1;
}
if(!failed) filesinjected++;
}else if( type == BYTE_FOLDER){
__os_snprintf(logbugger, sizeof(logbugger), "dir: %s",namebuffer);
log_string(bss.logsock, logbugger, BYTE_LOG_STR);
__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){
char op_offset[strlen(relativepath) + strlen(namebuffer)+ 1 + 1];
@ -511,13 +407,162 @@ int injectFiles(void *pClient, void *pCmd, char * path,char * relativepath,char
}
}
}
free(pBuffer);
if(failed) return -1;
else return filesinjected;
}else{
return -1;
}
}
int doInjectForFile(void * pClient, void * pCmd,int handle,char * filepath,int filesize,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(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(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(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);
failed = 1;
}
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);
pos += retsize;
}else{
log_string(bss.logsock, "error while recieving file", BYTE_LOG_STR);
failed = 1;
break;
}
}
int result = 0;
if((cafiine_fclose(bss.socket_fsa[client], &result, myhandle,0)) == 0 && result == 0){
if(DEBUG_LOG) log_string(bss.logsock, "cafiine_fclose success", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "cafiine_fclose failed", BYTE_LOG_STR);
failed = 1;
}
}else{
log_string(bss.logsock, "cafiine_fopen failed", BYTE_LOG_STR);
failed = 1;
}
return failed;
}
/*************************
Util functions
**************************/
/*flush if result != -1*/
void doFlushOrRollback(void *pClient, void *pCmd,int result,char *savepath){
char logbuffer[50 + strlen(savepath)];
if(result != -1){
__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){
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){
log_string(bss.logsock, "rollback done", BYTE_LOG_STR);
}else{
log_string(bss.logsock, "rollback failed", BYTE_LOG_STR);
}
}
}
void init_Save(unsigned char slotNo){
int (*SAVEInit)();
int (*SAVEInitSaveDir)(unsigned char accountSlotNo);
unsigned int save_handle;
OSDynLoad_Acquire("nn_save.rpl", &save_handle);
OSDynLoad_FindExport(save_handle, 0, "SAVEInit", (void **)&SAVEInit);
OSDynLoad_FindExport(save_handle, 0, "SAVEInitSaveDir", (void **)&SAVEInitSaveDir);
SAVEInit();
SAVEInitSaveDir(slotNo);
SAVEInitSaveDir(255U);
}
long getPesistentID(unsigned char * slotno){
unsigned int nn_act_handle;
unsigned long (*GetPersistentIdEx)(unsigned char);
int (*GetSlotNo)(void);
void (*nn_Initialize)(void);
void (*nn_Finalize)(void);
OSDynLoad_Acquire("nn_act.rpl", &nn_act_handle);
OSDynLoad_FindExport(nn_act_handle, 0, "GetPersistentIdEx__Q2_2nn3actFUc", (void **)&GetPersistentIdEx);
OSDynLoad_FindExport(nn_act_handle, 0, "GetSlotNo__Q2_2nn3actFv", (void **)&GetSlotNo);
OSDynLoad_FindExport(nn_act_handle, 0, "Initialize__Q2_2nn3actFv", (void **)&nn_Initialize);
OSDynLoad_FindExport(nn_act_handle, 0, "Finalize__Q2_2nn3actFv", (void **)&nn_Finalize);
nn_Initialize(); // To be sure that it is really Initialized
*slotno = GetSlotNo();
long idlong = GetPersistentIdEx(*slotno);
nn_Finalize(); //must be called an equal number of times to nn_Initialize
return idlong;
}
int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle){
int ret = 0;
int my_handle = handle +1;
char buffer[strlen(path) + 50];
if ((ret = FSOpenDir(pClient, pCmd, path, &handle, FS_RET_ALL_ERROR)) == FS_STATUS_OK){
__os_snprintf(buffer, sizeof(buffer), "remove files in dir %s",path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
FSDirEntry dir_entry;
while (FSReadDir(pClient, pCmd, handle, &dir_entry, FS_RET_ALL_ERROR) == FS_STATUS_OK)
{
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(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){
__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 ){
log_string(bss.logsock, "error while closing dir", BYTE_LOG_STR);
return -1;
}
}else{
__os_snprintf(buffer, sizeof(buffer), "error: %d on opening %s",ret,path);
log_string(bss.logsock, buffer, BYTE_LOG_STR);
return -1;
}
return 0;
}
#define MAKE_MAGIC(x) { x, my_ ## x, &real_ ## x }
@ -537,6 +582,4 @@ struct magic_t {
MAKE_MAGIC(FSDelClient),
MAKE_MAGIC(FSWriteFile),
MAKE_MAGIC(FSFlushQuota),
};

View File

@ -24,9 +24,18 @@
#define BYTE_LOG_STR 0xfb
#define BYTE_FILE 0xC0
#define BYTE_FOLDER 0xC1
#define BYTE_GET_FILES 0xCC
#define BYTE_READ_DIR 0xCC
#define BYTE_INJECTSTART 0x40
#define BYTE_INJECTEND 0x41
#define BYTE_DUMPSTART 0x42
#define BYTE_DUMPEND 0x43
#define BYTE_END 0xfd
#define MASK_NORMAL 0x8000
#define MASK_USER 0x0100
#define MASK_COMMON 0x0200
#define MASK_COMMON_CLEAN 0x0400
void *memcpy(void *dst, const void *src, int bytes);
void *memset(void *dst, int val, int bytes);
@ -47,6 +56,18 @@ extern FSStatus FSAddClient(FSClient *pClient, FSRetFlag errHandling);
extern void FSInitCmdBlock(FSCmdBlock *pCmd);
extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFlag errHandling);
extern FSStatus FSOpenFile(FSClient *pClient, FSCmdBlock *pCmd, char *path,char *mode,int *dh,FSRetFlag errHandling);
extern FSStatus FSOpenDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, int *dh, FSRetFlag errHandling);
extern FSStatus FSReadDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSDirEntry *dir_entry, FSRetFlag errHandling);
extern FSStatus FSChangeDir(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling);
extern FSStatus FSCloseDir(FSClient *pClient, FSCmdBlock *pCmd, int dh, FSRetFlag errHandling);
extern FSStatus FSReadFile(FSClient *pClient, FSCmdBlock *pCmd, void *buffer, int size, int count, int fd, int flag, int error);
extern FSStatus FSSetPosFile(FSClient *pClient, FSCmdBlock *pCmd, int fd, int pos, int error);
extern FSStatus FSCloseFile (FSClient *pClient, FSCmdBlock *pCmd, int fd, int error);
extern FSStatus FSMakeDir(FSClient *pClient, FSCmdBlock *pCmd,const char *path, FSRetFlag errHandling);
extern FSStatus FSRemove(FSClient *pClient, FSCmdBlock *pCmd, const char *path, FSRetFlag errHandling);
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 socket_lib_init();
extern int socket(int domain, int type, int protocol);
@ -54,9 +75,21 @@ extern int socketclose(int socket);
extern int connect(int socket, void *addr, int addrlen);
extern int send(int socket, const void *buffer, int size, int flags);
extern int recv(int socket, void *buffer, int size, int flags);
extern int __os_snprintf(char* s, int n, const char * format, ...);
int getFiles(int sock, char * path,char * resultname, int * resulttype,int *filesize);
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);
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);
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);
int remove_files_in_dir(void * pClient,void * pCmd, char * path, int handle);
struct in_addr {
unsigned int s_addr;
@ -102,3 +135,8 @@ int cafiine_fstat(int sock, int *result, int fd, void *ptr);
int cafiine_feof(int sock, int *result, int fd);
void cafiine_send_ping(int sock, int val1, int val2);
void log_string(int sock, const char* str, char flag_byte);
int saviine_end_injection(int sock);
int saviine_start_injection(int sock, long persistentID,int * mask);
int saviine_start_dump(int sock, long persistentID,int * mask);
int saviine_end_dump(int sock);

View File

@ -72,9 +72,8 @@ int getMode(int sock,int * result)
{
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
CHECK_ERROR(sock == -1);
int ret = 0;
CHECK_ERROR(sock == -1);
// create and send buffer with : [cmd id][fd][size][buffer data ...]
{
@ -145,6 +144,8 @@ int cafiine_send_handle(int sock, int client, const char *path, int handle)
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_SPECIAL);
if(ret == BYTE_REQUEST){
ret = 1;
}else{
@ -152,6 +153,7 @@ int cafiine_send_handle(int sock, int client, const char *path, int handle)
}
// wait reply
int special_ret = recvbyte(sock);
CHECK_ERROR(special_ret < 0);
CHECK_ERROR(special_ret != BYTE_SPECIAL);
bss.lock = 0;
return ret;
@ -164,10 +166,9 @@ error:
int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int *handle) {
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
int final_result = -1;
CHECK_ERROR(sock == -1);
int final_ret = 0;
int ret;
int len_path = 0;
while (path[len_path++]);
@ -186,23 +187,23 @@ int cafiine_fopen(int sock, int *result, const char *path, const char *mode, int
buffer[9 + len_path + ret] = mode[ret];
ret = sendwait(sock, buffer, 1 + 8 + len_path + len_mode);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_NORMAL);
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
ret = recvwait(sock, handle, 4);
CHECK_ERROR(ret < 0);
}
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret == BYTE_NORMAL);
final_result = 0;
ret = recvwait(sock, result, 4);
CHECK_ERROR(ret < 0);
ret = recvwait(sock, handle, 4);
CHECK_ERROR(ret < 0);
quit:
bss.lock = 0;
return final_ret;
error:
bss.lock = 0;
return -1;
return final_result;
}
void cafiine_send_file(int sock, char *file, int size, int fd) {
@ -225,7 +226,7 @@ void cafiine_send_file(int sock, char *file, int size, int fd) {
// send buffer, wait for reply
ret = sendwait(sock, buffer, 1 + 4 + 4 + size);
CHECK_ERROR(ret < 0);
// wait reply
ret = recvbyte(sock);
CHECK_ERROR(ret != BYTE_SPECIAL);
@ -247,14 +248,16 @@ int cafiine_fread(int sock, int *result, void *ptr, int size, int fd) {
*(int *)(buffer + 1) = size;
*(int *)(buffer + 5) = fd;
ret = sendwait(sock, buffer, 1 + 8);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret == BYTE_NORMAL);
int sz;
ret = recvwait(sock, &sz, 4);
CHECK_ERROR(ret < 0);
ret = recvwaitlen(sock, ptr, sz);
*result = sz - ret;
ret = sendbyte(sock, BYTE_OK);
CHECK_ERROR(ret < 0);
bss.lock = 0;
return 0;
@ -289,11 +292,115 @@ error:
return -1;
}
int getFiles(int sock, char * path,char * resultname, int * resulttype, int * filesize){
int saviine_start_injection(int sock, long persistentID,int * mask){
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
CHECK_ERROR(sock == -1);
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
char buffer[1+4];
buffer[0] = BYTE_INJECTSTART;
*(long *)(buffer + 1) = persistentID;
ret = sendwait(sock, buffer, 1 + 4);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
ret = recvwait(sock, mask, 4);
CHECK_ERROR(ret < 0);
CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
result = 1;
}
error:
bss.lock = 0;
return result;
}
int saviine_end_injection(int sock){
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
ret = sendbyte(sock, BYTE_INJECTEND);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_OK);
result = 1;
}
error:
bss.lock = 0;
return result;
}
int saviine_start_dump(int sock, long persistentID,int * mask){
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
char buffer[1+4];
buffer[0] = BYTE_DUMPSTART;
*(long *)(buffer + 1) = persistentID;
ret = sendwait(sock, buffer, 1 + 4);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
ret = recvwait(sock, mask, 4);
CHECK_ERROR(ret < 0);
CHECK_ERROR((*mask & MASK_NORMAL) != MASK_NORMAL);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_SPECIAL);
result = 1;
}
error:
bss.lock = 0;
return result;
}
int saviine_end_dump(int sock){
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
{
ret = sendbyte(sock, BYTE_DUMPEND);
CHECK_ERROR(ret < 0);
ret = recvbyte(sock);
CHECK_ERROR(ret < 0);
CHECK_ERROR(ret != BYTE_OK);
result = 1;
}
error:
bss.lock = 0;
return result;
}
int saviine_readdir(int sock, char * path,char * resultname, int * resulttype, int * filesize){
while (bss.lock) GX2WaitForVsync();
bss.lock = 1;
int result = 0;
CHECK_ERROR(sock == -1);
int ret;
// create and send buffer with : [cmd id][len_path][path][filesize]
{
@ -301,13 +408,14 @@ int getFiles(int sock, char * path,char * resultname, int * resulttype, int * fi
while (path[size++]);
char buffer[1+4+size];
buffer[0] = BYTE_GET_FILES;
buffer[0] = BYTE_READ_DIR;
*(int *)(buffer + 1) = size;
for (ret = 0; ret < size; ret++)
buffer[5 + ret] = path[ret];
// send buffer, wait for reply
ret = sendwait(sock, buffer, 1+4+size);
CHECK_ERROR(ret < 0);
// wait reply
ret = recvbyte(sock);

View File

@ -26,6 +26,7 @@ PROVIDE(FSAAddClient = 0x106546c);
PROVIDE(FSADelClient = 0x1060aa4);
PROVIDE(FSAOpenFile = 0x10621f8);
/*FE3C00*/
/* FS methods */
PROVIDE(FSInit = 0x10683c8);
PROVIDE(FSShutdown = 0x1068538);
@ -45,7 +46,7 @@ PROVIDE(FSGetStatFile = 0x106f5a0);
PROVIDE(FSIsEof = 0x106f610);
PROVIDE(FSWriteFile = 0x106F228);
PROVIDE(FSFlushQuota = 0x106FAC8);
PROVIDE(FSRollbackQuota = 0x106FC48);
/* */
PROVIDE(FSGetStat = 0x0106fdc8);

View File

@ -34,9 +34,24 @@ namespace saviine_server
public const byte BYTE_LOG_STR = 0xFB;
public const byte BYTE_FILE = 0xC0;
public const byte BYTE_FOLDER = 0xC1;
public const byte BYTE_GET_FILES = 0xCC;
public const byte BYTE_READ_DIR = 0xCC;
public const byte BYTE_INJECTSTART = 0x40;
public const byte BYTE_INJECTEND = 0x41;
public const byte BYTE_DUMPSTART = 0x42;
public const byte BYTE_DUMPEND = 0x43;
public const byte BYTE_END = 0xfd;
public const int MASK_NORMAL = 0x8000;
public const int MASK_USER = 0x0100;
public const int MASK_COMMON = 0x0200;
public const int MASK_COMMON_CLEAN = 0x0400;
private static long currentPersistentID = 0x0;
private static long COMMON_PERSISTENTID = 0x1;
[Flags]
public enum FSStatFlag : uint
{
@ -80,6 +95,9 @@ namespace saviine_server
public static string root = "saviine_root";
public static string logs_root = "logs";
public static string injectfolder = "inject";
public static string dumpfolder = "dump";
public static string common = "common";
const uint BUFFER_SIZE = 64 * 1024;
static Boolean fastmode = false;
@ -118,6 +136,7 @@ namespace saviine_server
if (op_mode == BYTE_MODE_D)
{
currentPersistentID = 0x01;
Console.WriteLine("Dump mode");
if(fastmode)Console.WriteLine("Now using fastmode");
}
@ -201,29 +220,6 @@ namespace saviine_server
}
static string getRealPath(string path,string title_id){
SaveSelectorDialog ofd = new SaveSelectorDialog(path, title_id);
try
{
DialogResult result = ofd.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
Console.WriteLine("selected: " + ofd.NewPath);
return ofd.NewPath;
}
else
{
Console.WriteLine("nothing selected");
}
}
catch(Exception e)
{
Console.WriteLine("No saves found to inject");
}
return "";
}
static void Handle(object client_obj)
{
string name = Thread.CurrentThread.Name;
@ -295,11 +291,18 @@ namespace saviine_server
string mode = reader.ReadString(Encoding.ASCII, len_mode - 1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
path = getRealPathCurrent(path, title_id);
//Log(log, "old path" + path);
//Log(log, "currentID: " + currentPersistentID);
if (op_mode == BYTE_MODE_I)
path = getRealPathCurrentInject(path, title_id);
//Log(log, "new path" + path);
if (path.Length == 0) failed = true;
if (File.Exists(path) && !failed)
{
//Log(log, "path exits");
int handle = -1;
for (int i = 1; i < files.Length; i++)
{
@ -326,6 +329,7 @@ namespace saviine_server
writer.Write(handle);
break;
}
//Log(log, "error fopen");
//else on error:
writer.Write(BYTE_NORMAL);
@ -357,16 +361,156 @@ namespace saviine_server
}
break;
}
case BYTE_GET_FILES:
case BYTE_INJECTSTART:
{
long wiiUpersistentID = (long)reader.ReadUInt32();
int dumpCommon = 0;
Boolean injectioncanceled = false;
SaveSelectorDialog ofd = new SaveSelectorDialog(title_id, wiiUpersistentID);
try
{
DialogResult result = ofd.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
currentPersistentID = ofd.NewPersistentID;
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;
}
else
{
Console.WriteLine("Injection canceled");
injectioncanceled = true;
}
}
catch (Exception e)
{
Console.WriteLine("Injection canceled");
injectioncanceled = true;
}
if (injectioncanceled)
{
writer.Write(BYTE_NORMAL);
}
else
{
writer.Write(BYTE_SPECIAL);
}
int dumpmask = MASK_NORMAL;
if (currentPersistentID != 0 && currentPersistentID != COMMON_PERSISTENTID)
dumpmask |= MASK_USER;
if (dumpCommon >= 1) {
dumpmask |= MASK_COMMON;
if(dumpCommon == 2)
dumpmask |= MASK_COMMON_CLEAN;
}
writer.Write(dumpmask);
writer.Write(BYTE_SPECIAL);
break;
}
case BYTE_INJECTEND:
{
currentPersistentID = 0;
//close all opened files
for (int i = 1; i < files.Length; i++)
{
if (files[i] != null)
{
files[i].Close();
files[i] = null;
}
}
writer.Write(BYTE_OK);
Console.WriteLine("InjectionEND");
break;
}
case BYTE_DUMPSTART:
{
long wiiUpersistentID = (long)reader.ReadUInt32();
int dumpCommon = 0;
currentPersistentID = wiiUpersistentID;
dumpCommon = 1;
/*
Boolean injectioncanceled = false;
SaveSelectorDialog ofd = new SaveSelectorDialog(title_id, wiiUpersistentID);
try
{
DialogResult result = ofd.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
currentPersistentID = ofd.NewPersistentID;
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;
}
else
{
Console.WriteLine("dump canceled");
injectioncanceled = true;
}
}
catch (Exception e)
{
Console.WriteLine("dump canceled");
injectioncanceled = true;
}
if (injectioncanceled)
{
writer.Write(BYTE_NORMAL);
}
else
{
writer.Write(BYTE_SPECIAL);
}*/
writer.Write(BYTE_SPECIAL);
int dumpmask = MASK_NORMAL;
if (currentPersistentID != 0 && currentPersistentID != COMMON_PERSISTENTID)
dumpmask |= MASK_USER;
if (dumpCommon == 1)
{
dumpmask |= MASK_COMMON;
}
writer.Write(dumpmask);
writer.Write(BYTE_SPECIAL);
break;
}
case BYTE_DUMPEND:
{
currentPersistentID = 0;
//close all opened files
for (int i = 1; i < files.Length; i++)
{
if (files[i] != null)
{
files[i].Close();
files[i] = null;
}
}
writer.Write(BYTE_OK);
Console.WriteLine("dumpEND");
break;
}
case BYTE_READ_DIR:
{
Boolean failed = false;
int len_path = reader.ReadInt32();
string path = reader.ReadString(Encoding.ASCII, len_path-1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
int x = 0;
currentPersistentID = getPersistentIDFromPath(path);
path = getRealPath(path, title_id);
//Console.WriteLine("old" + path);
if(op_mode == BYTE_MODE_I)
path = getRealPathCurrentInject(path, title_id);
//Console.WriteLine("new" + path);
if(path.Length == 0)failed = true;
if (Directory.Exists(path) && !failed)
@ -464,9 +608,13 @@ namespace saviine_server
string strSize = (sz / 1024).ToString();
string strCurrent = (offset / 1024).ToString().PadLeft(strSize.Length, ' ');
Console.Write("\r\t--> {0}% ({1} kB / {2} kB)", strProgress, strCurrent, strSize);
log.Write("\r\t--> {0}% ({1} kB / {2} kB)", strProgress, strCurrent, strSize);
//Console.Write("send " + rd );
if(offset == sz) Console.Write("\n");
if (offset == sz)
{
Console.Write("\n");
log.Write("\r\t--> {0}% ({1} kB / {2} kB)\n", strProgress, strCurrent, strSize);
}
int ret = -5;
if ((ret =reader.ReadByte()) != BYTE_OK)
{
@ -486,13 +634,24 @@ namespace saviine_server
int len_path = reader.ReadInt32();
string path = reader.ReadString(Encoding.ASCII, len_path - 1);
if (reader.ReadByte() != 0) throw new InvalidDataException();
if (!Directory.Exists(LocalRootDump + path))
//Console.WriteLine("old " + path);
if (op_mode == BYTE_MODE_D)
path = getRealPathCurrentDump(path, title_id);
//Console.WriteLine("new " + path);
if (path.Length == 0)
{
Directory.CreateDirectory(Path.GetDirectoryName(LocalRootDump + path));
writer.Write(BYTE_SPECIAL);
break;
}
if (!Directory.Exists(path))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
}
// Add new file for incoming data
files_request.Add(fd, new FileStream(LocalRootDump + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write));
files_request.Add(fd, new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write));
// Send response
if (fastmode) {
writer.Write(BYTE_REQUEST);
@ -652,40 +811,43 @@ namespace saviine_server
Console.WriteLine(name + " Exit");
}
private static string getPersistentIDFromPath(string path)
private static string getRealPathCurrentInject(string path, string title_id)
{
string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" };
string[] result;
string resultstr = "";
result = path.Split(stringSeparators, StringSplitOptions.None);
if (result.Length < 2) return "";
resultstr = result[result.Length-1];
stringSeparators = new string[] { "/", "\\" };
result = resultstr.Split(stringSeparators, StringSplitOptions.None);
if (result.Length < 1) return "";
return result[0];
return getRealPathCurrent(injectfolder, path, title_id);
}
private static string currentPersistentID = "80000009";
private static string getRealPathCurrent(string path, string title_id)
private static string getRealPathCurrentDump(string path, string title_id)
{
if (currentPersistentID.Length == 0) return "";
return getRealPathCurrent(dumpfolder, path, title_id);
}
private static string getRealPathCurrent(string prefix, string path, string title_id)
{
string savePath = Program.root + "/" + prefix + "/" + title_id;
if (currentPersistentID == 0) return "";
string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" };
string[] result;
string resultstr = "";
result = path.Split(stringSeparators, StringSplitOptions.None);
if (result.Length < 2) return "";
resultstr = result[result.Length-1];
stringSeparators = new string[] { "/", "\\" };
result = resultstr.Split(stringSeparators, StringSplitOptions.None);
if (result.Length < 2) return "";
if (result.Length < 2)
{
if (result[0] != "common") return savePath + "/" + String.Format("{0:X}", currentPersistentID);
return savePath + "/" + "common";
}
resultstr = "";
if (result[0] != "common")
savePath += "/" + String.Format("{0:X}", currentPersistentID);
else
savePath += "/" + "common";
for (int i = 1; i < result.Length; i++)
{
resultstr += "/" + result[i];
}
string savePath = Program.root + "/" + "inject" + "/" + title_id + "/" + currentPersistentID + resultstr;
savePath += resultstr;
return savePath;
}

View File

@ -30,15 +30,19 @@
{
this.btn_ok = new System.Windows.Forms.Button();
this.btn_cancel = new System.Windows.Forms.Button();
this.listBox_saves = new System.Windows.Forms.ListBox();
this.lbl_message = new System.Windows.Forms.Label();
this.comBoxIDList = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.Inj = new System.Windows.Forms.Label();
this.comBoxCommon = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// btn_ok
//
this.btn_ok.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btn_ok.Location = new System.Drawing.Point(167, 266);
this.btn_ok.Location = new System.Drawing.Point(62, 133);
this.btn_ok.Name = "btn_ok";
this.btn_ok.Size = new System.Drawing.Size(105, 33);
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;
@ -47,33 +51,80 @@
// btn_cancel
//
this.btn_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btn_cancel.Location = new System.Drawing.Point(332, 269);
this.btn_cancel.Location = new System.Drawing.Point(198, 133);
this.btn_cancel.Name = "btn_cancel";
this.btn_cancel.Size = new System.Drawing.Size(130, 29);
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;
//
// listBox_saves
// lbl_message
//
this.listBox_saves.FormattingEnabled = true;
this.listBox_saves.Location = new System.Drawing.Point(54, 48);
this.listBox_saves.Name = "listBox_saves";
this.listBox_saves.Size = new System.Drawing.Size(408, 160);
this.listBox_saves.TabIndex = 2;
this.lbl_message.AutoSize = true;
this.lbl_message.Location = new System.Drawing.Point(12, 10);
this.lbl_message.Name = "lbl_message";
this.lbl_message.Size = new System.Drawing.Size(236, 13);
this.lbl_message.TabIndex = 3;
this.lbl_message.Text = "Got an injection request for 00050000-10157F00";
//
// Form1
// comBoxIDList
//
this.comBoxIDList.FormattingEnabled = true;
this.comBoxIDList.Location = new System.Drawing.Point(186, 48);
this.comBoxIDList.Name = "comBoxIDList";
this.comBoxIDList.Size = new System.Drawing.Size(93, 21);
this.comBoxIDList.TabIndex = 4;
//
// 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(81, 13);
this.label1.TabIndex = 5;
this.label1.Text = "Select userdata";
this.label1.Click += new System.EventHandler(this.label1_Click);
//
// 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(108, 13);
this.Inj.TabIndex = 7;
this.Inj.Text = "Inject common save?";
this.Inj.Click += new System.EventHandler(this.Inj_Click);
//
// comBoxCommon
//
this.comBoxCommon.FormattingEnabled = true;
this.comBoxCommon.Items.AddRange(new object[] {
"no",
"inject",
"clean and inject (deleting existing common)"});
this.comBoxCommon.Location = new System.Drawing.Point(126, 83);
this.comBoxCommon.Name = "comBoxCommon";
this.comBoxCommon.Size = new System.Drawing.Size(153, 21);
this.comBoxCommon.TabIndex = 8;
//
// SaveSelectorDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(499, 314);
this.Controls.Add(this.listBox_saves);
this.ClientSize = new System.Drawing.Size(310, 166);
this.Controls.Add(this.comBoxCommon);
this.Controls.Add(this.Inj);
this.Controls.Add(this.label1);
this.Controls.Add(this.comBoxIDList);
this.Controls.Add(this.lbl_message);
this.Controls.Add(this.btn_cancel);
this.Controls.Add(this.btn_ok);
this.Name = "Form1";
this.Text = "Form1";
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "SaveSelectorDialog";
this.Text = "Injection request";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
@ -81,6 +132,10 @@
private System.Windows.Forms.Button btn_ok;
private System.Windows.Forms.Button btn_cancel;
private System.Windows.Forms.ListBox listBox_saves;
private System.Windows.Forms.Label lbl_message;
private System.Windows.Forms.ComboBox comBoxIDList;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label Inj;
private System.Windows.Forms.ComboBox comBoxCommon;
}
}

View File

@ -12,39 +12,60 @@ namespace saviine_server
{
public partial class SaveSelectorDialog : Form
{
private string newPath = "";
private long newPersistentID = 0;
private int dumpCommon = 0;
public string NewPath
public long NewPersistentID
{
get { return newPath; }
get { return newPersistentID; }
}
private static string savePath = Program.root + "/" + "inject";
public SaveSelectorDialog(string path,string title_id)
public int DumpCommon
{
get { return dumpCommon; }
}
private static string savePath;
public SaveSelectorDialog(string title_id,long persistentID)
{
InitializeComponent();
string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" };
string[] result;
result = path.Split(stringSeparators, StringSplitOptions.None);
if (result.Length < 2) this.Close();
string resultPath = result[result.Length-2];
Console.WriteLine(title_id);
comBoxCommon.SelectedIndex = 0;
savePath = Program.root + "/" + Program.injectfolder;;
this.lbl_message.Text = "Got an injection request for " + title_id;
savePath += "/" + title_id;
string[] subdirectoryEntries;
if (Directory.Exists(savePath))
{
// Recurse into subdirectories of this directory.
string[] subdirectoryEntries = Directory.GetDirectories(savePath);
subdirectoryEntries = Directory.GetDirectories(savePath);
this.comBoxIDList.Items.Add("---none---");
comBoxIDList.SelectedIndex = 0;
foreach (string subdirectory in subdirectoryEntries)
{
this.listBox_saves.Items.Add(Path.GetFileName(subdirectory));
string filename = Path.GetFileName(subdirectory);
long id;
try{
id = Convert.ToUInt32(filename, 16);
}catch (Exception){
id = 0;
}
if (id >= 0x80000000 && id <= 0x81000000)
{
this.comBoxIDList.Items.Add(filename);
}
}
if (comBoxIDList.Items.Count == 1)
{
this.comBoxIDList.Enabled = false;
}
if (!Directory.Exists(savePath + "/" + Program.common))
{
comBoxCommon.Enabled = false;
}
}
else
{
Console.WriteLine("dir not found! " + savePath);
this.Close();
}
}
@ -55,13 +76,35 @@ namespace saviine_server
private void btn_ok_Click(object sender, EventArgs e)
{
newPath = savePath + "/" + this.listBox_saves.SelectedItem.ToString();
long id;
try
{
id = Convert.ToUInt32(this.comBoxIDList.SelectedItem.ToString(), 16);
}
catch (Exception)
{
id = 0;
}
newPersistentID = id;
dumpCommon = comBoxCommon.SelectedIndex;
Console.WriteLine(dumpCommon);
}
private void btn_cancel_Click(object sender, EventArgs e)
{
}
private void Inj_Click(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}

View File

@ -1,8 +1,8 @@
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\bin\saviine_server.exe.config
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\bin\saviine_server.exe
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\bin\saviine_server.pdb
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.exe
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.pdb
G:\Programmieren\libwiiu-master\saviinet\saviine\saviine\server\src\obj\x86\Debug\saviine_server.Form1.resources
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