Trap Windows application crash and flush file buffers
This question is a bit far-out, but I thought maybe someone knows a clever solution.
I have a particular situation with an RTS game in Windows (Kane's Wrath), which saves replay files. It is possible for an adverse opponent to trigger a crash in the game. In that event, having as complete a replay file as possible would be advantageous.
However, the replay file output seems to be buffered and only occurs in sets of 4096 bytes (which is a lot of game time). I am wondering if it is possible somehow to force the program to flush all its file handles in the event of a crash. Is there a some built-in OS feature that allows disabling of buffering for an application?
Failing that, I might like to write a launcher/wrapper for this problem. I imagine that it should inject some code which a) installs a signal handler for the crash (is it SIGSEGV?), and b) redirects CreateFile
(which I know the program uses from following a trace) to store the handle. The crash handler would then just flush all the handlers with FlushFileBuffer开发者_开发知识库s
.
Or is it perhaps possible to obtain another process's open file handles?
Would this have a chance of working, and could you give me any advice on how to best achieve this with the least amount of intrusion?
Little update: @CatPlusPlus has suggested Detours to hook into the program, intercept file opening calls and modify them to be unbuffered. This may well be the solution!
Well you could start by wrapping winmain in a try/catch block like is described in this article:
XCrashReport : Exception Handling and Crash Reporting - Part 1
which basically does something like this:
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
int Result = -1;
__try
{
Result = HandledWinMain(hInstance, NULL, lpstrCmdLine, nCmdShow);
}
__except(RecordExceptionInfo(hInstance,GetExceptionInformation(), "main thread"))
{
// Do nothing here - RecordExceptionInfo() has already done
// everything that is needed. Actually this code won't even
// get called unless you return EXCEPTION_EXECUTE_HANDLER from
// the __except clause.
}
return Result;
}
Of course I'm not sure what the state of your buffers will be, but this will allow you to hook into the process.
Assuming that the process is not yours,
your only option seems to be hooking WriteFile function, and do instead a WriteFile followed by a Flush.
WriteFile can be hooked by IAT hooking directy or using a library like eashook.
The only thing I can think of is to attach a debugger and tinker in its assembler output.
I remember doing this with some programs when they crashed on me: Jump over the offending machine instructions to the end of the function, and let it run. in about 50% of all cases that would let the program get to a point where I could save my data. Of course, restarting afterwards was mandatory.
精彩评论