/************************************************************************
* database.cpp *
* - functions for loading and saving database files *
************************************************************************/
#include <windows.h>
#include "dasm.h"
#include "debug.h"
#include "disasm.h"
#include "gname.h"
#include "relocs.h"
#include "xref.h"
#include "data.h"
#include "exeload.h"
#include "schedule.h"
//#include "menuids.rh"
#include "resource.h"
#include "decrypt.h"
//#define _CRTDBG_MAP_ALLOC
//#include <crtdbg.h>
/************************************************************************
* savedecryptitems *
* - this saves the list of decryptors to the database *
************************************************************************/
bool savedecryptitems(savefile *sf) {
dword ndecs;
ndecs=decrypter.numlistitems();
decrypter.resetiterator();
sf->Write(&ndecs,sizeof(dword));
for (;ndecs;ndecs--) {
if (!decrypter.write_item(sf)) return false;
}
return true;
}
/************************************************************************
* loaddecryptitems *
* - here we reload the list of decryptors *
************************************************************************/
bool loaddecryptitems(savefile *sf) {
dword ndecs;
if (!sf->Read(&ndecs,sizeof(dword))) return false;
for (;ndecs;ndecs--) {
if (!decrypter.read_item(sf)) return false;
}
return true;
}
/************************************************************************
* retstacksavedb *
* - Borg keeps track of the stack even through saves. It simply saves *
* the full stack *
************************************************************************/
bool retstacksavedb(savefile *sf) {
sf->Write(&cvd->retstack.stacktop,sizeof(int));
sf->Write(cvd->retstack.callstack,sizeof(lptr)*CALLSTACKSIZE);
return sf->okay;
}
/************************************************************************
* retstackloaddb *
* - reloads the stack from the saved database file *
************************************************************************/
bool retstackloaddb(savefile *sf) {
sf->Read(&cvd->retstack.stacktop,sizeof(int));
sf->Read(cvd->retstack.callstack,sizeof(lptr)*CALLSTACKSIZE);
return sf->okay;
}
/************************************************************************
* dissavedb *
* - this routine saves the entire disassembly database to the database *
* save file. It converts instruction pointers into instruction uids *
* and converts data pointers into offsets for saving *
************************************************************************/
bool dissavedb(savefile *sf,byte *filebuff) {
dword ndsms;
dsmitemsave structsave;
dsmitem *currdsm;
ndsms=dsm->numlistitems();
dsm->resetiterator();
sf->Write(&ndsms,sizeof(dword));
for (;ndsms;ndsms--) {
currdsm=dsm->nextiterator();
structsave.addr=currdsm->addr;
structsave.type=currdsm->type;
structsave.length=currdsm->length;
structsave.modrm=currdsm->modrm;
structsave.mode32=currdsm->mode32;
structsave.override=currdsm->override;
structsave.flags=currdsm->flags;
structsave.displayflags=currdsm->displayflags;
if(structsave.type==dsmxref)
{ structsave.fileoffset=0; // NULL ptrs
structsave.tptroffset=0;
}
else if(structsave.type==dsmcode)
{ structsave.fileoffset=currdsm->data-filebuff;
structsave.tptroffset=((asminstdata *)currdsm->tptr)->uniqueid;
}
else
{ structsave.fileoffset=lstrlen((char *)currdsm->data)+1; // strlen
structsave.tptroffset=0; // points to str as well
}
sf->Write(&structsave,sizeof(dsmitemsave));
if ((structsave.type!=dsmxref)&&(structsave.type!=dsmcode))
sf->Write(currdsm->tptr,structsave.fileoffset);
}
// need to save callstack and some other stuff too.
sf->Write(&cvd->curraddr,sizeof(lptr));
sf->Write(&cvd->subitem,sizeof(dsmitemtype));
sf->Write(&dsm->itables,sizeof(int));
sf->Write(&dsm->jtables,sizeof(int));
sf->Write(&dsm->irefs,sizeof(int));
return retstacksavedb(sf);
}
/************************************************************************
* disloaddb *
* - this routine loads the entire disassembly database from the save *
* file It converts instruction uids into the instruction pointers and *
* converts offsets back into pointers. We have to search the assembly *
* instructions for the uids in order to find the correct instruction. *
************************************************************************/
bool disloaddb(savefile *sf,byte *filebuff) {
dword ndsms;
dsmitemsave structsave;
dsmitem *currdsm;
int asminstctr;
asminstdata *findasm;
if (!sf->Read(&ndsms,sizeof(dword))) return false;
for (;ndsms;ndsms--) {
currdsm=new dsmitem;
if (!sf->Read(&structsave,sizeof(dsmitemsave)))
return false;
currdsm->addr=structsave.addr;
currdsm->type=structsave.type;
currdsm->length=structsave.length;
currdsm->modrm=structsave.modrm;
currdsm->mode32=structsave.mode32;
currdsm->override=structsave.override;
currdsm->flags=structsave.flags;
currdsm->displayflags=structsave.displayflags;
switch (structsave.type) {
case dsmxref: {
currdsm->data=NULL;
currdsm->tptr=NULL;
}break;
case dsmcode: {
currdsm->data=structsave.fileoffset+filebuff;
// now reset the tptr = asminstdata ptr (need to find it from the uniqueid)
asminstctr=0;
findasm=reconstruct[asminstctr];
while((dword)(findasm[0].uniqueid/1000)!=(dword)(structsave.tptroffset/1000)) {
asminstctr++;
findasm=reconstruct[asminstctr];
if (findasm==NULL){
#ifdef DEBUG
DebugMessage("File Loader:Failed to find instruction table for %lu",structsave.tptroffset);
#endif
return false;
}
}
asminstctr=0;
while(findasm[asminstctr].uniqueid!=structsave.tptroffset) {
asminstctr++;
if ((!findasm[asminstctr].instbyte)&&(!findasm[asminstctr].processor)) {
#ifdef DEBUG
DebugMessage("File Loader:Failed to find instruction %lu",structsave.tptroffset);
#endif
return false;
}
}
currdsm->tptr=(void *)&findasm[asminstctr];
}break;
default: {
currdsm->data=new byte[structsave.fileoffset];
currdsm->tptr=currdsm->data;
}
}
if (structsave.type!=dsmxref && structsave.type!=dsmcode) {
if (!sf->Read(currdsm->tptr,structsave.fileoffset))
return false;
}
dsm->addto(currdsm);
}
// need to save callstack and some other stuff too.
sf->Read(&cvd->curraddr,sizeof(lptr));
sf->Read(&cvd->subitem,sizeof(dsmitemtype));
sf->Read(&dsm->itables,sizeof(int));
sf->Read(&dsm->jtables,sizeof(int));
sf->Read(&dsm->irefs,sizeof(int));
dsm->dissettable();
cvd->setcuraddr(cvd->curraddr);
return retstackloaddb(sf);
}
/************************************************************************
* saverelocitems *
* - this saves the relocs list to the database file. *
* - we can simply save the number of items followed by each item *
************************************************************************/
bool saverelocitems(savefile *sf) {
dword nrels;
nrels=reloc->numlistitems();
reloc->resetiterator();
// save number of reloc items
sf->Write(&nrels,sizeof(dword));
for(;nrels;nrels--) {
if (!reloc->write_item(sf)) return false;
}
return true;
}
/************************************************************************
* loadrelocitems *
* - this reloads the list of relocs from the database file and *
* constructs the list again *
************************************************************************/
bool loadrelocitems(savefile *sf) {
dword nrels;
// get number of items
if (!sf->Read(&nrels,sizeof(dword))) return false;
for (;nrels;nrels--) {
if (!reloc->read_item(sf)) return false;
}
return true;
}
/************************************************************************
* gnamesavedb *
* - saves all the names in the list to the database file being saved. *
* this is in a one-pass compatible loading format. ie number of items *
* followed by each item, and for strings the length of the string *
* followed by the string. *
************************************************************************/
bool gnamesavedb(gname *gn,savefile *sf) {
dword nexps,nlen;
gnameitem *currexp;
nexps=gn->numlistitems();
gn->resetiterator();
sf->Write(&nexps,sizeof(dword));
for(;nexps;nexps--) {
currexp=gn->nextiterator();
sf->Write(&(currexp->addr),sizeof(lptr));
nlen=lstrlen(currexp->name)+1;
sf->Write(&nlen,sizeof(dword));
sf->Write(currexp->name,nlen);
}
return true;
}
/************************************************************************
* gnameloaddb *
* - loads the names from the database file and reconstructs the names *
* list *
************************************************************************/
bool gnameloaddb(gname *gn,savefile *sf) {
dword nexps,nlen;
gnameitem *currexp;
sf->Read(&nexps,sizeof(dword));
for (;nexps;nexps--) {
currexp=new gnameitem;
sf->Read(&(currexp->addr),sizeof(lptr));
sf->Read(&nlen,sizeof(dword));
currexp->name=new char[nlen];
sf->Read(currexp->name,nlen);
gn->addto(currexp);
}
return true;
}
/************************************************************************
* savedatasegitems *
* - we save the data segment data structures to the database file. *
************************************************************************/
bool savedatasegitems(savefile *sf,byte *filebuff) {
dword nsegs;
nsegs=dta->numlistitems();
dta->resetiterator();
sf->Write(&nsegs,sizeof(dword));
for (;nsegs;nsegs--) {
if (!dta->write_item(sf,filebuff)) return false;
}
return true;
}
/************************************************************************
* loaddatasegitems *
* - loads the data segment data structures in *
************************************************************************/
bool loaddatasegitems(savefile *sf,byte *filebuff) {
dword nsegs;
if (!sf->Read(&nsegs,sizeof(dword))) return false;
#ifdef DEBUG
DebugMessage("Loading %lu datasegs",nsegs);
#endif
for (;nsegs;nsegs--) {
if (!dta->read_item(sf,filebuff)) return false;
}
return true;
}
/************************************************************************
* xrefsavedb *
* save xref list to database file, simply writes the list item out *
* consisting of loc and ref_by, ie two addresses *
************************************************************************/
bool xrefsavedb(savefile *sf) {
dword nxrefs;
xrefitem *currxref;
nxrefs=xrefs->numlistitems();
xrefs->resetiterator();
sf->Write(&nxrefs,sizeof(dword));
for(;nxrefs;nxrefs--) {
currxref=xrefs->nextiterator();
sf->Write(currxref,sizeof(xrefitem));
}
return true;
}
/************************************************************************
* xrefloaddb *
* load xref list to database file, simply reads the list item in *
* consisting of loc and ref_by, ie two addresses *
* and adds it to the new list *
************************************************************************/
bool xrefloaddb(savefile *sf) {
dword nxrefs;
xrefitem *currxref;
if (!sf->Read(&nxrefs,sizeof(dword))) return false;
for (;nxrefs;nxrefs--) {
currxref=new xrefitem;
if (!sf->Read(currxref,sizeof(xrefitem))) return false;
xrefs->addto(currxref);
}
return true;
}
/************************************************************************
* savemessbox *
* - A small dialog box which contains the message 'saving' to be shown *
* as a database file is saved *
************************************************************************/
BOOL CALLBACK savemessbox(HWND,UINT,WPARAM,LPARAM) {
return FALSE;
}
/************************************************************************
* savedbcoord *
* - coordinates saving of the databases when save as database file is *
* chosen in Borg *
************************************************************************/
bool savedbcoord(char *fname,char *exename, UINT FilterIndex) {
savefile sf;
dword flen;
dword bver;
// HWND sbox;
// open file
StatusMessage("Saving...");
// sbox=CreateDialog(hInst,MAKEINTRESOURCE(save_box),MainWnd,savemessbox);
//--- better put that into status line! ---
if (!sf.sopen(fname,GENERIC_WRITE,1,CREATE_ALWAYS,0,FilterIndex==FILTER_RLECOMPRESSED))
return false;
// save header to identify as a database file
sf.Write("BORG",4);
// save BORG_VERSION
bver=BORG_VER;
sf.Write(&bver,sizeof(bver));
// save filename of exe file.
flen=lstrlen(exename)+1;
sf.Write(&flen,sizeof(dword));
sf.Write(exename,flen);
// save options.
sf.Write(&options,sizeof(globaloptions));
sf.Write(&floader.exetype,sizeof(int));
// save segment info
savedatasegitems(&sf,floader.fbuff);
// save import info
gnamesavedb(import,&sf);
// save export info
gnamesavedb(expt,&sf);
// save names
gnamesavedb(name,&sf);
// save relocs
saverelocitems(&sf);
// save xrefs
xrefsavedb(&sf);
// save asm database
dissavedb(&sf,floader.fbuff);
// save decrypter list
savedecryptitems(&sf);
sf.flushfilewrite();
// close file
if (sf.okay) StatusMessage("Saved.");
return sf.okay;
}
/************************************************************************
* loadmessbox *
* - A small dialog box which contains the message 'loading' to be shown *
* as a database file is loaded *
************************************************************************/
BOOL CALLBACK loadmessbox(HWND,UINT,WPARAM,LPARAM) {
return FALSE;
}
/************************************************************************
* loaddbcoord *
* - coordinates loading of the databases when load database file is *
* chosen in Borg *
************************************************************************/
bool loaddbcoord(LPCTSTR fname,char *exename, UINT FilterIndex) {
savefile sf;
dword num;
dword flen,fsize;
dword bver;
// open file
StatusMessage("Loading...");
if (!FilterIndex) { // unknown type? (from dropping or command line)
DWORD id;
HFILE f=_lopen(fname,OF_READ|OF_SHARE_DENY_NONE);
if (f!=HFILE_ERROR) {
_lread(f,&id,sizeof(id));
_lclose(f);
switch (id) {
case MAKEFOURCC('B','O','R','G'): FilterIndex=1; break;
case MAKEFOURCC('B','O',0x05,0x24): FilterIndex=2; break;
}
}
}
// lbox=CreateDialog(hInst,MAKEINTRESOURCE(load_box),MainWnd,loadmessbox);
if (!sf.sopen(fname,GENERIC_READ,1,OPEN_EXISTING,0,FilterIndex==FILTER_RLECOMPRESSED)) {
return false;
}
// load header check its a database file
sf.Read(&bver,4);
if (bver!=MAKEFOURCC('B','O','R','G')) {
MessageBox(MainWnd,"Not A Borg Database File",fname,MB_OK|MB_ICONEXCLAMATION);
return false;
}
// read BORG_VERSION
if (!sf.Read(&bver,sizeof(bver))) return false;
if (bver>BORG_VER) {
MessageBox(MainWnd,"Savefile from a later version [or very early version]!",fname,MB_OK|MB_ICONEXCLAMATION);
return false;
}
if (bver<BORG_VER) {
MessageBox(MainWnd,"Warning:earlier version savefile [will attempt load]",fname,MB_OK|MB_ICONEXCLAMATION);
#ifdef DEBUG
DebugMessage("Detected version: %d.%d Savefile",bver/100,bver%100);
#endif
}
// load filename of exe file.
flen=0;
sf.Read(&flen,sizeof(dword));
sf.Read(exename,flen);
#ifdef DEBUG
DebugMessage("Filename:%s",exename);
#endif
// added 226 to allow load of older databases
if (bver<222) {
MessageBox(MainWnd,"Older databases are incompatible, please reuse the older version of Borg","Prior to 2.22",MB_OK|MB_ICONEXCLAMATION);
return false;
}
// load options.
sf.Read(&options,sizeof(globaloptions));
#ifdef DEBUG
DebugMessage("Global Options Size: %d",sizeof(globaloptions));
#endif
sf.Read(&floader.exetype,sizeof(int));
// load exe file.
// - any errors from here on will now be fatal, and Borg will need to exit
floader.efile=CreateFile(exename,GENERIC_READ|GENERIC_WRITE,1,NULL,OPEN_EXISTING,0,NULL);
if (floader.efile==INVALID_HANDLE_VALUE) {
char *nameptr=strrchr(exename,'\\');
if (nameptr) {
nameptr++; // address the file name portion
floader.efile=CreateFile(nameptr,GENERIC_READ|GENERIC_WRITE,1,NULL,OPEN_EXISTING,0,NULL);
if (floader.efile!=INVALID_HANDLE_VALUE) {
lstrcpy(exename,nameptr); // shuffle name to lower addresses
}
}
}
if(floader.efile==INVALID_HANDLE_VALUE)
{ floader.efile=CreateFile(fname,GENERIC_READ,1,NULL,OPEN_EXISTING,0,NULL);
if(floader.efile==INVALID_HANDLE_VALUE)
{
MessageBox(MainWnd,"File open failed?",exename,MB_OK|MB_ICONEXCLAMATION);
return false;
}
options.readonly=true;
MessageBox(MainWnd,"Couldn't open file to disassemble.\n"
"A copy of that file inside the database will be presented - "
"BORG will not be able to apply any patches.\n"
"BUG: BORG may crash soon or display garbage.",
"Borg Message",MB_OK);
}
if(GetFileType(floader.efile)!=FILE_TYPE_DISK) {
MessageBox(MainWnd,"File open failed?",exename,MB_OK|MB_ICONEXCLAMATION);
CloseHandle(floader.efile);
return false;
}
fsize=GetFileSize(floader.efile,NULL);
floader.fbuff=new byte[fsize];
SetFilePointer(floader.efile,0x00,NULL,FILE_BEGIN);
if(!ReadFile(floader.efile,floader.fbuff,fsize,&num,NULL))
{
MessageBox(MainWnd,"File read failed?",exename,MB_OK|MB_ICONEXCLAMATION);
CloseHandle(floader.efile);
delete floader.fbuff;
return false;
}
// load segment info
if(!loaddatasegitems(&sf,floader.fbuff))
{
MessageBox(MainWnd,"Fatal Error\nSegments: File read failed?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Loading Imports");
#endif
// load import info
if(!gnameloaddb(import,&sf))
{
MessageBox(MainWnd,"Fatal Error\nImports: File read failed?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Loading Exports");
#endif
// load export info
if(!gnameloaddb(expt,&sf))
{
MessageBox(MainWnd,"Fatal Error\nExports: File read failed?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Loading Names");
#endif
// load names
if(!gnameloaddb(name,&sf))
{
MessageBox(MainWnd,"Fatal Error\nNames: File read failed?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Loading Relocs");
#endif
// load relocs
if(!loadrelocitems(&sf))
{
MessageBox(MainWnd,"Fatal Error\nRelocs: File read failed?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Loading Xrefs");
#endif
// load xrefs
if(!xrefloaddb(&sf))
{
MessageBox(MainWnd,"Fatal Error\nXrefs: File read failed?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Loading Asm database");
#endif
// load asm database
if(!disloaddb(&sf,floader.fbuff))
{
MessageBox(MainWnd,"Fatal Error\nDatabase: File read failed?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Relocating File");
#endif
if (!reloc->relocfile()) {
MessageBox(MainWnd,"Fatal Error\nRelocating File",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
#ifdef DEBUG
DebugMessage("Loading Decryptors");
#endif
if(!loaddecryptitems(&sf))
{
MessageBox(MainWnd,"Fatal Error\nDecryptors:File read failed ?",fname,MB_OK|MB_ICONEXCLAMATION);
DestroyWindow(MainWnd);
return false;
}
StatusMessage("Loaded.");
return true;
}
/************************************************************************
* savedb *
* - the first place of call when save as database is selected. *
* - asks the user to select a file before calling the fileloader savedb *
* which is where the save to database is controlled from *
************************************************************************/
bool savedb(void) {
TCHAR szFile[MAX_PATH];
UINT FilterIndex;
if (scheduler.sizelist()) {
MessageBox(MainWnd,"There are still items to process yet","Borg Warning",MB_OK|MB_ICONEXCLAMATION);
return false;
}
if (getfiletosave(szFile,elemof(szFile),IDS_FILTERSAVE,FilterIndex)
&& savedbcoord(szFile,current_exe_name,FilterIndex)) {
dsm->dirty=false;
return true;
}
return false;
}
/************************************************************************
* loaddb *
* - the first place of call when load from database is selected. *
************************************************************************/
bool loaddb(LPCTSTR szFile, UINT FilterIndex) {
changemenus(true);
if (loaddbcoord(szFile,current_exe_name,FilterIndex)) {
TCHAR buf[64];
StatusMessage("Project Opened");
wsprintf(buf,T("%s: %s"),winname,current_exe_name);
SetWindowText(MainWnd,buf);
// InThread=true;
// ThreadHandle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,0,0,&ThreadId);
scheduler.addtask(scrolling,priority_userrequest,nlptr,NULL);
return true;
}
changemenus(false);
MessageBox(MainWnd,"File open failed?",program_name,MB_OK|MB_ICONEXCLAMATION);
return false;
}
Vorgefundene Kodierung: UTF-8 | 0
|