19 #ifdef GAME_ERRORLOG_TXT
34 #define SIXTYFOURK (64*ONEK)
35 #define ONEM (ONEK*ONEK)
36 #define ONEG (ONEK*ONEK*ONEK)
72 const int NumCodeBytes = 16;
73 const int MaxStackDump = 2048;
74 const int StackColumns = 8;
88 static void hprintf(
HANDLE LogFile,
char* Format, ...)
93 va_start( arglist, Format);
94 wvsprintf(buffer, Format, arglist);
98 WriteFile(LogFile, buffer, lstrlen(buffer), &NumBytes, 0);
103 static void PrintTime(
char *output, FILETIME TimeToPrint)
106 if (FileTimeToLocalFileTime(&TimeToPrint, &TimeToPrint) &&
107 FileTimeToDosDateTime(&TimeToPrint, &Date, &Time))
111 wsprintf(output,
"%d/%d/%d %02d:%02d:%02d",
112 (Date / 32) & 15, Date & 31, (Date / 512) + 1980,
113 (Time / 2048), (Time / 32) & 63, (Time & 31) * 2);
127 if (GetModuleFileName(ModuleHandle, ModName,
sizeof(ModName)) > 0) {
131 IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
132 if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic) {
136 IMAGE_NT_HEADERS *NTHeader = (IMAGE_NT_HEADERS*)((
char *)DosHeader + DosHeader->e_lfanew);
137 if (IMAGE_NT_SIGNATURE != NTHeader->Signature) {
143 HANDLE ModuleFile = CreateFile(ModName, GENERIC_READ,
144 FILE_SHARE_READ, 0, OPEN_EXISTING,
145 FILE_ATTRIBUTE_NORMAL, 0);
146 char TimeBuffer[100] =
"";
148 if (ModuleFile != INVALID_HANDLE_VALUE) {
149 FileSize = GetFileSize(ModuleFile, 0);
150 FILETIME LastWriteTime;
151 if (GetFileTime(ModuleFile, 0, 0, &LastWriteTime)) {
152 wsprintf(TimeBuffer,
" - file date is ");
153 PrintTime(TimeBuffer + lstrlen(TimeBuffer), LastWriteTime);
155 CloseHandle(ModuleFile);
157 hprintf(LogFile,
"%s, loaded at 0x%08x - %d bytes - %08x%s\r\n",
158 ModName, ModuleHandle, FileSize,
159 NTHeader->FileHeader.TimeDateStamp, TimeBuffer);
164 __except(EXCEPTION_EXECUTE_HANDLER)
175 static void RecordModuleList(
HANDLE LogFile)
177 hprintf(LogFile,
"\r\n"
178 "\tModule list: names, addresses, sizes, time stamps "
179 "and file times:\r\n");
180 SYSTEM_INFO SystemInfo;
181 GetSystemInfo(&SystemInfo);
182 const size_t PageSize = SystemInfo.dwPageSize;
185 const size_t NumPages = 4 * size_t(ONEG / PageSize);
187 void *LastAllocationBase = 0;
188 while (pageNum < NumPages) {
189 MEMORY_BASIC_INFORMATION MemInfo;
190 if (VirtualQuery((
void *)(pageNum * PageSize), &MemInfo,
sizeof(MemInfo))) {
191 if (MemInfo.RegionSize > 0) {
194 pageNum += MemInfo.RegionSize / PageSize;
195 if (MemInfo.State == MEM_COMMIT && MemInfo.AllocationBase > LastAllocationBase) {
199 LastAllocationBase = MemInfo.AllocationBase;
200 ShowModuleInfo(LogFile, (
HINSTANCE)LastAllocationBase);
203 pageNum += SIXTYFOURK / PageSize;
208 pageNum += SIXTYFOURK / PageSize;
216 static void RecordSystemInformation(
HANDLE LogFile)
218 FILETIME CurrentTime;
219 GetSystemTimeAsFileTime(&CurrentTime);
220 char TimeBuffer[100];
221 PrintTime(TimeBuffer, CurrentTime);
222 hprintf(LogFile,
"Error occurred at %s.\r\n", TimeBuffer);
224 if (GetModuleFileName(0, ModuleName,
sizeof(ModuleName)) <= 0) {
225 lstrcpy(ModuleName,
"Unknown");
228 DWORD UserNameSize =
sizeof(UserName);
229 if (!GetUserName(UserName, &UserNameSize)) {
230 lstrcpy(UserName,
"Unknown");
232 hprintf(LogFile,
"%s, run by %s.\r\n", ModuleName, UserName);
234 SYSTEM_INFO SystemInfo;
235 GetSystemInfo(&SystemInfo);
236 hprintf(LogFile,
"%d processor(s), type %d.\r\n",
237 SystemInfo.dwNumberOfProcessors, SystemInfo.dwProcessorType);
239 MEMORYSTATUS MemInfo;
240 MemInfo.dwLength =
sizeof(MemInfo);
241 GlobalMemoryStatus(&MemInfo);
243 hprintf(LogFile,
"%d MBytes physical memory.\r\n", (MemInfo.dwTotalPhys +
249 static const char *GetExceptionDescription(
DWORD ExceptionCode)
251 struct ExceptionNames
257 ExceptionNames ExceptionMap[] =
259 {0x40010005,
"a Control-C"},
260 {0x40010008,
"a Control-Break"},
261 {0x80000002,
"a Datatype Misalignment"},
262 {0x80000003,
"a Breakpoint"},
263 {0xc0000005,
"an Access Violation"},
264 {0xc0000006,
"an In Page Error"},
265 {0xc0000017,
"a No Memory"},
266 {0xc000001d,
"an Illegal Instruction"},
267 {0xc0000025,
"a Noncontinuable Exception"},
268 {0xc0000026,
"an Invalid Disposition"},
269 {0xc000008c,
"a Array Bounds Exceeded"},
270 {0xc000008d,
"a Float Denormal Operand"},
271 {0xc000008e,
"a Float Divide by Zero"},
272 {0xc000008f,
"a Float Inexact Result"},
273 {0xc0000090,
"a Float Invalid Operation"},
274 {0xc0000091,
"a Float Overflow"},
275 {0xc0000092,
"a Float Stack Check"},
276 {0xc0000093,
"a Float Underflow"},
277 {0xc0000094,
"an Integer Divide by Zero"},
278 {0xc0000095,
"an Integer Overflow"},
279 {0xc0000096,
"a Privileged Instruction"},
280 {0xc00000fD,
"a Stack Overflow"},
281 {0xc0000142,
"a DLL Initialization Failed"},
282 {0xe06d7363,
"a Microsoft C++ Exception"},
285 for (
int i = 0;
i <
sizeof(ExceptionMap) /
sizeof(ExceptionMap[0]);
i++) {
286 if (ExceptionCode == ExceptionMap[
i].ExceptionCode) {
287 return ExceptionMap[
i].ExceptionName;
291 return "Unknown exception type";
294 static char* GetFilePart(
char *
source)
296 char *
result = strrchr(source,
'\\');
322 int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS
data,
const char *Message)
324 static bool BeenHere =
false;
328 return EXCEPTION_CONTINUE_SEARCH;
334 char FileName[
MAX_PATH] =
"Unknown";
337 if (GetModuleFileName(0, ModuleName,
sizeof(ModuleName)) <= 0) {
341 char *FilePart = GetFilePart(ModuleName);
345 lstrcpy(FileName, FilePart);
346 char *lastperiod = strrchr(FileName,
'.');
352 lstrcpy(FilePart,
"errorlog.txt");
353 HANDLE LogFile = CreateFile(ModuleName, GENERIC_WRITE, 0, 0,
354 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0);
355 if (LogFile == INVALID_HANDLE_VALUE) {
356 OutputDebugString(
"Error creating exception report");
357 return EXCEPTION_CONTINUE_SEARCH;
361 SetFilePointer(LogFile, 0, 0, FILE_END);
363 hprintf(LogFile,
"\r\n\r\n\r\n\r\n");
364 PEXCEPTION_RECORD Exception = data->ExceptionRecord;
365 PCONTEXT Context = data->ContextRecord;
368 char *CrashModuleFileName =
"Unknown";
369 MEMORY_BASIC_INFORMATION MemInfo;
373 if (VirtualQuery((
void*)Context->Eip, &MemInfo,
sizeof(MemInfo)) && GetModuleFileName((
HINSTANCE)MemInfo.AllocationBase, CrashModulePathName,
sizeof(CrashModulePathName)) > 0) {
374 CrashModuleFileName = GetFilePart(CrashModulePathName);
379 hprintf(LogFile,
"%s caused %s in module %s at %04x:%08x.\r\n",
380 FileName, GetExceptionDescription(Exception->ExceptionCode),
381 CrashModuleFileName, Context->SegCs, Context->Eip);
382 hprintf(LogFile,
"Exception handler called in %s.\r\n", Message);
383 RecordSystemInformation(LogFile);
386 if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION && Exception->NumberParameters >= 2) {
387 char DebugMessage[1000];
388 const char* readwrite =
"Read from";
389 if (Exception->ExceptionInformation[0]) {
390 readwrite =
"Write to";
393 wsprintf(DebugMessage,
"%s location %08x caused an access violation.\r\n", readwrite, Exception->ExceptionInformation[1]);
399 OutputDebugString(
"Exception handler: ");
400 OutputDebugString(DebugMessage);
403 hprintf(LogFile,
"%s", DebugMessage);
407 hprintf(LogFile,
"\r\n");
408 hprintf(LogFile,
"Registers:\r\n");
409 hprintf(LogFile,
"EAX=%08x CS=%04x EIP=%08x EFLGS=%08x\r\n",
410 Context->Eax, Context->SegCs, Context->Eip, Context->EFlags);
411 hprintf(LogFile,
"EBX=%08x SS=%04x ESP=%08x EBP=%08x\r\n",
412 Context->Ebx, Context->SegSs, Context->Esp, Context->Ebp);
413 hprintf(LogFile,
"ECX=%08x DS=%04x ESI=%08x FS=%04x\r\n",
414 Context->Ecx, Context->SegDs, Context->Esi, Context->SegFs);
415 hprintf(LogFile,
"EDX=%08x ES=%04x EDI=%08x GS=%04x\r\n",
416 Context->Edx, Context->SegEs, Context->Edi, Context->SegGs);
417 hprintf(LogFile,
"Bytes at CS:EIP:\r\n");
424 unsigned char *
code = (
unsigned char*)Context->Eip;
425 for (
int codebyte = 0; codebyte < NumCodeBytes; codebyte++) {
429 hprintf(LogFile,
"%02x ", code[codebyte]);
432 __except(EXCEPTION_EXECUTE_HANDLER) {
433 hprintf(LogFile,
"?? ");
441 hprintf(LogFile,
"\r\n"
456 if (pStackTop > pStack + MaxStackDump) {
457 pStackTop = pStack + MaxStackDump;
465 char buffer[1000] =
"";
466 const int safetyzone = 50;
467 char* nearend = buffer +
sizeof(
buffer) - safetyzone;
469 while (pStack + 1 <= pStackTop) {
470 if ((Count % StackColumns) == 0) {
471 output += wsprintf(output,
"%08x: ", pStack);
475 if ((++Count % StackColumns) == 0 || pStack + 2 > pStackTop) {
479 output += wsprintf(output,
"%08x%s", *pStack, Suffix);
482 if (output > nearend) {
483 hprintf(LogFile,
"%s", buffer);
489 hprintf(LogFile,
"%s", buffer);
491 __except(EXCEPTION_EXECUTE_HANDLER) {
492 hprintf(LogFile,
"Exception encountered during stack dump.\r\n");
497 if (!safe_string.empty())
498 hprintf(LogFile,
"Last safe point: %s\r\n", safe_string.c_str());
501 RecordModuleList(LogFile);
503 CloseHandle(LogFile);
508 return EXCEPTION_CONTINUE_SEARCH;
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
for(int idx=0;idx< i;idx++)
GLenum GLsizei GLenum GLenum const GLvoid * data
GLsizei GLsizei GLchar * source