More init hardening.

develop
Petr Mrázek 2011-11-04 09:08:29 +01:00
parent 0ff7a48848
commit af46b262b5
13 changed files with 148 additions and 35 deletions

@ -25,7 +25,7 @@ set(DF_VERSION_MINOR "31")
set(DF_VERSION_PATCH "25") set(DF_VERSION_PATCH "25")
set(DF_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}") set(DF_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}")
set(DFHACK_RELEASE "7d") set(DFHACK_RELEASE "7e")
## where to install things (after the build is done, classic 'make install' or package structure) ## where to install things (after the build is done, classic 'make install' or package structure)
# the dfhack libraries will be installed here: # the dfhack libraries will be installed here:

@ -640,7 +640,6 @@ bool Console::init(bool sharing)
return false; return false;
} }
freopen("stdout.log", "w", stdout); freopen("stdout.log", "w", stdout);
freopen("stderr.log", "w", stderr);
d = new Private(); d = new Private();
// make our own weird streams so our IO isn't redirected // make our own weird streams so our IO isn't redirected
d->dfout_C = fopen("/dev/tty", "w"); d->dfout_C = fopen("/dev/tty", "w");
@ -690,11 +689,18 @@ int Console::printerr( const char* format, ... )
va_list args; va_list args;
lock_guard <mutex> g(*wlock); lock_guard <mutex> g(*wlock);
int ret; int ret;
if(!inited) ret = -1; // also mirror in error log
if(!inited)
{
va_start( args, format );
ret = vfprintf(stderr, format, args);
va_end(args);
}
else else
{ {
va_start( args, format ); va_start( args, format );
ret = d->vprinterr(format, args); ret = d->vprinterr(format, args);
vfprintf(stderr, format, args);
va_end(args); va_end(args);
} }
return ret; return ret;

@ -378,6 +378,7 @@ namespace DFHack
HANDLE console_in; HANDLE console_in;
HANDLE console_out; HANDLE console_out;
HWND ConsoleWindow; HWND ConsoleWindow;
HWND MainWindow;
WORD default_attributes; WORD default_attributes;
// current state // current state
enum console_state enum console_state
@ -402,7 +403,29 @@ Console::Console():std::ostream(0), std::ios(0)
Console::~Console() Console::~Console()
{ {
} }
/*
// DOESN'T WORK - locks up DF!
void ForceForegroundWindow(HWND window)
{
DWORD nForeThread, nAppThread;
nForeThread = GetWindowThreadProcessId(GetForegroundWindow(), 0);
nAppThread = ::GetWindowThreadProcessId(window,0);
if(nForeThread != nAppThread)
{
AttachThreadInput(nForeThread, nAppThread, true);
BringWindowToTop(window);
ShowWindow(window,3);
AttachThreadInput(nForeThread, nAppThread, false);
}
else
{
BringWindowToTop(window);
ShowWindow(window,3);
}
}
*/
bool Console::init(bool) bool Console::init(bool)
{ {
d = new Private(); d = new Private();
@ -411,6 +434,21 @@ bool Console::init(bool)
CONSOLE_SCREEN_BUFFER_INFO coninfo; CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp; FILE *fp;
DWORD oldMode, newMode; DWORD oldMode, newMode;
DWORD dwTheardId;
HWND h = ::GetTopWindow(0 );
while ( h )
{
DWORD pid;
dwTheardId = ::GetWindowThreadProcessId( h,&pid);
if ( pid == GetCurrentProcessId() )
{
// here h is the handle to the window
break;
}
h = ::GetNextWindow( h , GW_HWNDNEXT);
}
d->MainWindow = h;
// Allocate a console! // Allocate a console!
AllocConsole(); AllocConsole();
@ -450,6 +488,8 @@ bool Console::init(bool)
std::cin.tie(this); std::cin.tie(this);
clear(); clear();
inited = true; inited = true;
// DOESN'T WORK - locks up DF!
// ForceForegroundWindow(d->MainWindow);
return true; return true;
} }
// FIXME: looks awfully empty, doesn't it? // FIXME: looks awfully empty, doesn't it?
@ -480,11 +520,18 @@ int Console::printerr( const char* format, ... )
va_list args; va_list args;
lock_guard <mutex> g(*wlock); lock_guard <mutex> g(*wlock);
int ret; int ret;
if(!inited) ret = -1; // also mirror in error log
if(!inited)
{
va_start( args, format );
ret = vfprintf(stderr, format, args);
va_end(args);
}
else else
{ {
va_start( args, format ); va_start( args, format );
ret = d->vprinterr(format, args); ret = d->vprinterr(format, args);
vfprintf(stderr, format, args);
va_end(args); va_end(args);
} }
return ret; return ret;

@ -174,6 +174,8 @@ void fIOthread(void * iodata)
} }
string first = parts[0]; string first = parts[0];
parts.erase(parts.begin()); parts.erase(parts.begin());
cerr << "Invoking: " << command << endl;
// let's see what we actually got // let's see what we actually got
if(first=="help" || first == "?") if(first=="help" || first == "?")
{ {
@ -351,7 +353,7 @@ void fIOthread(void * iodata)
command_result res = plug_mgr->InvokeCommand(first, parts); command_result res = plug_mgr->InvokeCommand(first, parts);
if(res == CR_NOT_IMPLEMENTED) if(res == CR_NOT_IMPLEMENTED)
{ {
con.printerr("Invalid command.\n"); con.printerr("%s is not a recognized command.\n", first.c_str());
clueless_counter ++; clueless_counter ++;
} }
/* /*
@ -393,6 +395,23 @@ Core::Core()
misc_data_mutex=0; misc_data_mutex=0;
}; };
void Core::fatal (std::string output, bool deactivate)
{
stringstream out;
out << output ;
if(deactivate)
out << "DFHack will now deactivate.\n";
if(con.isInited())
{
con.printerr("%s", out.str().c_str());
}
fprintf(stderr, "%s\n", out.str().c_str());
#ifndef LINUX_BUILD
out << "Check file stderr.log for details\n";
MessageBox(0,out.str().c_str(),"DFHack error!", MB_OK | MB_ICONERROR);
#endif
}
bool Core::Init() bool Core::Init()
{ {
if(started) if(started)
@ -406,30 +425,48 @@ bool Core::Init()
#else #else
const char * path = "hack\\Memory.xml"; const char * path = "hack\\Memory.xml";
#endif #endif
vif = new DFHack::VersionInfoFactory(path); vif = new DFHack::VersionInfoFactory();
cerr << "Identifying DF version.\n";
try
{
vif->loadFile(path);
}
catch(Error::All & err)
{
std::stringstream out;
out << "Error while reading Memory.xml:\n";
out << err.what() << std::endl;
delete vif;
vif = nullptr;
errorstate = true;
fatal(out.str(), true);
return false;
}
p = new DFHack::Process(vif); p = new DFHack::Process(vif);
vinfo = p->getDescriptor(); vinfo = p->getDescriptor();
if(!vinfo || !p->isIdentified()) if(!vinfo || !p->isIdentified())
{ {
cerr << "Not a known DF version. DFHack will now deactivate.\n"; fatal ("Not a known DF version.\n", true);
errorstate = true; errorstate = true;
delete p; delete p;
p = NULL; p = NULL;
return false; return false;
} }
cerr << "Version: " << vinfo->getVersion() << endl;
cerr << "Initializing Console.\n";
// init the console. // init the console.
Gui * g = getGui(); Gui * g = getGui();
if(g->init) bool is_text_mode = false;
{ if(g->init && g->init->graphics.flags.is_set(GRAPHICS_TEXT))
if(g->init->graphics.flags.is_set(GRAPHICS_TEXT))
{ {
con.init(true); is_text_mode = true;
} }
else con.init(false); if(con.init(is_text_mode))
} cerr << "Console is running.\n";
else con.init(false); else
fatal ("Console has failed to initialize!\n", false);
// dump offsets to a file // dump offsets to a file
std::ofstream dump("offsets.log"); std::ofstream dump("offsets.log");
@ -444,18 +481,22 @@ bool Core::Init()
AccessMutex = new mutex(); AccessMutex = new mutex();
misc_data_mutex=new mutex(); misc_data_mutex=new mutex();
core_cond = new Core::Cond(); core_cond = new Core::Cond();
cerr << "Initializing Plugins.\n";
// create plugin manager // create plugin manager
plug_mgr = new PluginManager(this); plug_mgr = new PluginManager(this);
cerr << "Starting IO thread.\n";
// create IO thread // create IO thread
IODATA *temp = new IODATA; IODATA *temp = new IODATA;
temp->core = this; temp->core = this;
temp->plug_mgr = plug_mgr; temp->plug_mgr = plug_mgr;
thread * IO = new thread(fIOthread, (void *) temp); thread * IO = new thread(fIOthread, (void *) temp);
cerr << "Starting DF input capture thread.\n";
// set up hotkey capture // set up hotkey capture
HotkeyMutex = new mutex(); HotkeyMutex = new mutex();
HotkeyCond = new condition_variable(); HotkeyCond = new condition_variable();
thread * HK = new thread(fHKthread, (void *) temp); thread * HK = new thread(fHKthread, (void *) temp);
started = true; started = true;
cerr << "DFHack is running.\n";
return true; return true;
} }
/// sets the current hotkey command /// sets the current hotkey command
@ -565,6 +606,8 @@ int Core::Update()
// FIXME: needs to terminate the IO threads and properly dismantle all the machinery involved. // FIXME: needs to terminate the IO threads and properly dismantle all the machinery involved.
int Core::Shutdown ( void ) int Core::Shutdown ( void )
{ {
if(errorstate)
return true;
errorstate = 1; errorstate = 1;
if(plug_mgr) if(plug_mgr)
{ {

@ -132,6 +132,11 @@ DFhackCExport int wgetch(WINDOW *win)
static int (*_SDL_Init)(uint32_t flags) = 0; static int (*_SDL_Init)(uint32_t flags) = 0;
DFhackCExport int SDL_Init(uint32_t flags) DFhackCExport int SDL_Init(uint32_t flags)
{ {
// reroute stderr
freopen("stderr.log", "w", stderr);
// we don't reroute stdout until we figure out if this should be done at all
// See: Console-linux.cpp
// find real functions // find real functions
_SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init"); _SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init");
_SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit"); _SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit");

@ -694,6 +694,9 @@ DFhackCExport uint32_t SDL_ThreadID(void)
// FIXME: this has to be thread-safe. // FIXME: this has to be thread-safe.
bool FirstCall() bool FirstCall()
{ {
// reroute stdout and stderr
freopen("stdout.log", "w", stdout);
freopen("stderr.log", "w", stderr);
HMODULE realSDLlib = LoadLibrary("SDLreal.dll"); HMODULE realSDLlib = LoadLibrary("SDLreal.dll");
if(!realSDLlib) if(!realSDLlib)
{ {

@ -97,13 +97,16 @@ inline bool operator>=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2,
return !(__x < __y); return !(__x < __y);
} }
VersionInfoFactory::VersionInfoFactory(string path_to_xml) VersionInfoFactory::VersionInfoFactory()
{ {
error = false; error = false;
loadFile(path_to_xml);
} }
VersionInfoFactory::~VersionInfoFactory() VersionInfoFactory::~VersionInfoFactory()
{
clear();
}
void VersionInfoFactory::clear(void)
{ {
// for each stored version, delete // for each stored version, delete
for(uint32_t i = 0; i < versions.size();i++) for(uint32_t i = 0; i < versions.size();i++)
@ -111,6 +114,8 @@ VersionInfoFactory::~VersionInfoFactory()
delete versions[i]; delete versions[i];
} }
versions.clear(); versions.clear();
knownVersions.clear();
error = false;
} }
VersionInfo * VersionInfoFactory::getVersionInfoByMD5(string hash) VersionInfo * VersionInfoFactory::getVersionInfoByMD5(string hash)
@ -768,5 +773,6 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
} }
} }
error = false; error = false;
std::cerr << "Loaded " << versions.size() << " DF versions." << std::endl;
return true; return true;
} }

@ -164,6 +164,7 @@ namespace DFHack
//void beep (void); //void beep (void);
/// A simple line edit (raw mode) /// A simple line edit (raw mode)
int lineedit(const std::string& prompt, std::string& output, CommandHistory & history ); int lineedit(const std::string& prompt, std::string& output, CommandHistory & history );
bool isInited (void) { return inited; };
private: private:
Private * d; Private * d;
tthread::mutex * wlock; tthread::mutex * wlock;

@ -143,6 +143,9 @@ namespace DFHack
bool ncurses_wgetch(int in, int & out); bool ncurses_wgetch(int in, int & out);
Core(Core const&); // Don't Implement Core(Core const&); // Don't Implement
void operator=(Core const&); // Don't implement void operator=(Core const&); // Don't implement
// report error to user while failing
void fatal (std::string output, bool will_deactivate);
// 1 = fatal failure
bool errorstate; bool errorstate;
// regulate access to DF // regulate access to DF
struct Cond; struct Cond;

@ -39,7 +39,7 @@ namespace DFHack
{ {
friend class ProcessEnumerator; friend class ProcessEnumerator;
public: public:
VersionInfoFactory(std::string path_to_xml); VersionInfoFactory();
~VersionInfoFactory(); ~VersionInfoFactory();
// memory info entries loaded from a file // memory info entries loaded from a file
bool loadFile( std::string path_to_xml); bool loadFile( std::string path_to_xml);
@ -47,6 +47,7 @@ namespace DFHack
VersionInfo * getVersionInfoByMD5(std::string md5string); VersionInfo * getVersionInfoByMD5(std::string md5string);
VersionInfo * getVersionInfoByPETimestamp(uint32_t timestamp); VersionInfo * getVersionInfoByPETimestamp(uint32_t timestamp);
std::vector<VersionInfo*> versions; std::vector<VersionInfo*> versions;
void clear( void );
private: private:
void ParseVTable(TiXmlElement* vtable, VersionInfo* mem); void ParseVTable(TiXmlElement* vtable, VersionInfo* mem);
void ParseBase (TiXmlElement* base, VersionInfo* mem); void ParseBase (TiXmlElement* base, VersionInfo* mem);

@ -1 +1 @@
Subproject commit 0f6389f4121d6cf3d447fb72a5b561d8d66b0de8 Subproject commit ea35678fc408dadef196ed82f61c00709a23b914

@ -56,13 +56,13 @@ DFhackCExport command_result rawdump_i (Core * c, vector <string> & parameters)
{ {
if( index < mats->df_inorganic->size()) if( index < mats->df_inorganic->size())
{ {
df_inorganic_material * mat = mats->df_inorganic->at(index); df_inorganic_type * mat = mats->df_inorganic->at(index);
// dump single material // dump single material
con.print("%-3d : [%s] %s\n", con.print("%-3d : [%s] %s\n",
index, index,
mat->Inorganic_ID.c_str(), mat->ID.c_str(),
mat->STATE_NAME_SOLID.c_str()); mat->mat.state_name[DFHack::state_solid].c_str());
con.print("MAX EDGE: %d\n",mat->MAX_EDGE); con.print("MAX EDGE: %d\n",mat->mat.MAX_EDGE);
} }
else else
{ {
@ -74,7 +74,7 @@ DFhackCExport command_result rawdump_i (Core * c, vector <string> & parameters)
// dump all materials // dump all materials
for(int i = 0; i < mats->df_inorganic->size();i++) for(int i = 0; i < mats->df_inorganic->size();i++)
{ {
con.print("%-3d : %s\n",i,mats->df_inorganic->at(i)->Inorganic_ID.c_str()); con.print("%-3d : %s\n",i,mats->df_inorganic->at(i)->ID.c_str());
} }
} }
c->Resume(); c->Resume();

@ -198,7 +198,7 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
DFHack::Maps *maps = c->getMaps(); DFHack::Maps *maps = c->getMaps();
if (!maps->Start()) if (!maps->Start())
{ {
con << "Cannot get map info!" << std::endl; con.printerr("Cannot get map info!\n");
c->Resume(); c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
@ -208,13 +208,13 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
DFHack::Materials *mats = c->getMaterials(); DFHack::Materials *mats = c->getMaterials();
if (!mats->df_inorganic) if (!mats->df_inorganic)
{ {
con << "Unable to read inorganic material definitons!" << std::endl; con.printerr("Unable to read inorganic material definitons!\n");
c->Resume(); c->Resume();
return CR_FAILURE; return CR_FAILURE;
} }
if (showPlants && !mats->df_organic) if (showPlants && !mats->df_organic)
{ {
con << "Unable to read organic material definitons; plants won't be listed!" << std::endl; con.printerr("Unable to read organic material definitons; plants won't be listed!\n");
showPlants = false; showPlants = false;
} }
@ -234,21 +234,19 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
if (!(showSlade && maps->ReadGlobalFeatures(globalFeatures))) if (!(showSlade && maps->ReadGlobalFeatures(globalFeatures)))
{ {
con << "Unable to read global features; slade won't be listed!" << std::endl; con.printerr("Unable to read global features; slade won't be listed!\n");
} }
if (!maps->ReadLocalFeatures(localFeatures)) if (!maps->ReadLocalFeatures(localFeatures))
{ {
con << "Unable to read local features; adamantine " con.printerr("Unable to read local features; adamantine and demon temples won't be listed.\n" );
<< (showTemple ? "and demon temples " : "")
<< "won't be listed!" << std::endl;
} }
uint32_t vegCount = 0; uint32_t vegCount = 0;
DFHack::Vegetation *veg = c->getVegetation(); DFHack::Vegetation *veg = c->getVegetation();
if (showPlants && !veg->Start()) if (showPlants && !veg->Start())
{ {
con << "Unable to read vegetation; plants won't be listed!" << std::endl; con.printerr("Unable to read vegetation; plants won't be listed!\n" );
} }
for(uint32_t z = 0; z < z_max; z++) for(uint32_t z = 0; z < z_max; z++)