// The primary exception filter LONG WINAPI BWAPIExceptionFilter(EXCEPTION_POINTERS *ep) { DDrawDestroy(); ShowCursor(TRUE); SYSTEMTIME st; char szFilename[MAX_PATH]; // Create the file GetSystemTime(&st); sprintf_s(szFilename, MAX_PATH, "%sbwapi-data\\logs\\Exceptions\\%u_%02u_%02u.txt", szInstallPath, st.wYear, st.wMonth, st.wDay); FILE *hFile = fopen( szFilename, "a+"); if ( hFile ) { fprintf(hFile, "\n//////////////////////////////////////////////////\n"); // Print the time time_t _t = time(NULL); fprintf(hFile, "TIME: %s\n", ctime(&_t)); // Print version data WORD w1,w2,w3,w4; GetCurrentProductVersion(w1, w2, w3, w4); fprintf(hFile, "VERSION: %hu.%hu.%hu.%hu\n", w1, w2, w3, w4); // BWAPI/Broodwar specific fprintf(hFile, "BWAPI:\n"); fprintf(hFile, " REVISION: %u\n", BWAPI::BroodwarImpl.getRevision()); fprintf(hFile, " BUILD: %s\n", BWAPI::BroodwarImpl.isDebug() ? "DEBUG" : "RELEASE"); fprintf(hFile, " ERROR: %s\n", BWAPI::BroodwarImpl.getLastError().c_str()); fprintf(hFile, " LOCATION: %s %s\n", BWAPI::BroodwarImpl.isMultiplayer() ? (BWAPI::BroodwarImpl.isBattleNet() ? "Battle.net" : "Multiplayer") : "Single Player", BWAPI::BroodwarImpl.isReplay() ? "Replay" : ""); if ( BWAPI::BroodwarImpl.isInGame() ) { fprintf(hFile, "MAP: %s\n %s\n", BWAPI::BroodwarImpl.mapName().c_str(), BWAPI::BroodwarImpl.mapFileName().c_str()); NULLCHECK(BWAPI::BroodwarImpl.self()); NULLCHECK(BWAPI::BroodwarImpl.enemy()); NULLCHECK(BWAPI::BroodwarImpl.neutral()); if ( BWAPI::BroodwarImpl.hAIModule && !BWAPI::BroodwarImpl.client ) fprintf(hFile, "\"Broodwar\" pointer was not initialized for AI module.\n"); if ( BWAPI::BroodwarImpl.hTournamentModule && !BWAPI::BroodwarImpl.tournamentAI ) fprintf(hFile, "\"Broodwar\" pointer was not initialized for Tournament module.\n"); } // Print the exception info DWORD dwExceptionCode = ep->ExceptionRecord->ExceptionCode; fprintf(hFile, "\nEXCEPTION: 0x%p %s\n", dwExceptionCode, GetExceptionName(dwExceptionCode)); // Store exception address PVOID pExceptionAddr = ep->ExceptionRecord->ExceptionAddress; // Print offending module info fprintf(hFile, "FAULT: 0x%p %s\n", pExceptionAddr, getModuleNameFrom(pExceptionAddr).c_str()); // Print register information fprintf(hFile, "REGISTERS:\n"); DWORD dwCntxtFlags = ep->ContextRecord->ContextFlags; if ( dwCntxtFlags & CONTEXT_INTEGER ) fprintf(hFile, " EDI: %08X\n" " ESI: %08X\n" " EBX: %08X\n" " EDX: %08X\n" " ECX: %08X\n" " EAX: %08X\n", ep->ContextRecord->Edi, ep->ContextRecord->Esi, ep->ContextRecord->Ebx, ep->ContextRecord->Edx, ep->ContextRecord->Ecx, ep->ContextRecord->Eax); if ( dwCntxtFlags & CONTEXT_CONTROL ) fprintf(hFile, " EBP: %08X\n" " EIP: %08X\n" " ESP: %08X\n", ep->ContextRecord->Ebp, ep->ContextRecord->Eip, ep->ContextRecord->Esp); // Get the stack frame STACKFRAME sf = { 0 }; sf.AddrPC.Mode = AddrModeFlat; sf.AddrPC.Offset = ep->ContextRecord->Eip; sf.AddrFrame.Mode = AddrModeFlat; sf.AddrFrame.Offset = ep->ContextRecord->Ebp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrStack.Offset = ep->ContextRecord->Esp; // Create a context record copy CONTEXT c = *ep->ContextRecord; // Do the stack trace fprintf(hFile, "STACK:\n"); // Get frequently used handles HANDLE hProcess = GetCurrentProcess(); HANDLE hThread = GetCurrentThread(); // Initialize symbols and stuff if ( _SymInitialize ) { _SymInitialize(hProcess, NULL, FALSE); if ( _SymSetOptions ) _SymSetOptions(SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_AUTO_PUBLICS | SYMOPT_DEFERRED_LOADS | SYMOPT_FAVOR_COMPRESSED | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_LOAD_ANYTHING | SYMOPT_LOAD_LINES); // Load all module symbols if ( _SymLoadModule ) { MODULEENTRY32 me32; me32.dwSize = sizeof(MODULEENTRY32); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); if ( Module32First(hSnapshot, &me32) ) { do { _SymLoadModule(hProcess, NULL, me32.szExePath, me32.szModule, (DWORD)me32.modBaseAddr, me32.modBaseSize); } while( Module32Next(hSnapshot, &me32) ); } CloseHandle(hSnapshot); } // if _SymLoadModule is valid } // Load custom symbols for Broodwar, etc std::vector<_customSymbolStore> customSymbols; char szSymbolMap[MAX_PATH]; sprintf_s(szSymbolMap, MAX_PATH, "%sbwapi-data\\data\\Broodwar.map", szInstallPath); FILE *hBWSymbols = fopen(szSymbolMap, "r"); if ( hBWSymbols ) { char szSymbolName[512]; DWORD dwAddress = 0; DWORD dwSize = 0; for (;;) { int iResult = fscanf(hBWSymbols, "%512s %x %x", szSymbolName, &dwAddress, &dwSize); if ( iResult == EOF || iResult == 0 ) break; _customSymbolStore sym = { szSymbolName, dwAddress, dwAddress + dwSize }; customSymbols.push_back(sym); } fclose(hBWSymbols); } // Walk, don't run if ( _StackWalk && _SymFunctionTableAccess && _SymGetModuleBase ) { while ( _StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &sf, &c, NULL, _SymFunctionTableAccess, _SymGetModuleBase, NULL) ) { DWORD dwOffset = sf.AddrPC.Offset; fprintf(hFile, " %-16s 0x%p ", getModuleNameFrom((LPCVOID)dwOffset).c_str(), dwOffset); bool foundSomething = false; if ( dwOffset ) { // Get the symbol name IMAGEHLP_SYMBOL_PACKAGE sip = { 0 }; sip.sym.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); sip.sym.MaxNameLength = MAX_SYM_NAME; DWORD dwJunk = 0; if ( _SymInitialize && _SymGetSymFromAddr && _SymGetSymFromAddr(hProcess, dwOffset, &dwJunk, &sip.sym) ) { fprintf(hFile, "%s", sip.sym.Name); foundSomething = true; } // Get the file name + line IMAGEHLP_LINE il = { 0 }; il.SizeOfStruct = sizeof(IMAGEHLP_LINE); dwJunk = 0; if ( _SymInitialize && _SymGetLineFromAddr && _SymGetLineFromAddr(hProcess, dwOffset, &dwJunk, &il) ) { fprintf(hFile, "\n %s:%u", il.FileName, il.LineNumber); foundSomething = true; } if ( !foundSomething ) { for ( std::vector<_customSymbolStore>::const_iterator i = customSymbols.begin(), iend = customSymbols.end(); i != iend; ++i ) { if ( dwOffset >= i->dwStartAddress && dwOffset < i->dwEndAddress ) { fprintf(hFile, "%s", i->name.c_str()); foundSomething = true; break; } } } } if ( !foundSomething ) fprintf(hFile, " ----"); fprintf(hFile, "\n"); } } // Clean up if ( _SymInitialize && _SymCleanup ) _SymCleanup(hProcess); fclose(hFile); } // ^if hFile ShowCursor(FALSE); // Call the previous exception filter return TopExceptionFilter.DefFilterProc(ep); }
void SetWMode(int width, int height, bool state) { // Compatibility for Xen W-Mode if ( ghMainWnd && !(GetWindowLong(ghMainWnd, GWL_STYLE) & WS_SYSMENU) ) return; if ( !isCorrectVersion ) return; if ( state ) { wmode = true; if ( !ghMainWnd ) return; // Call the DirectDraw destructor DDrawDestroy(); InitializeWModeBitmap(BW::BWDATA_GameScreenBuffer->wid, BW::BWDATA_GameScreenBuffer->ht); // Hack to enable drawing in Broodwar *BW::BWDATA_PrimarySurface = (LPDIRECTDRAWSURFACE)1; POINT pos = { windowRect.left + (gdwProcNum ? 32 : 0), windowRect.top + (gdwProcNum ? 32 : 0) }; // Change the window settings SetWindowLong(ghMainWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); SetWindowPos(ghMainWnd, HWND_NOTOPMOST, pos.x, pos.y, width, height, SWP_SHOWWINDOW); ShowWindow(ghMainWnd, SW_RESTORE); SIZE border; GetBorderSize(ghMainWnd, &border); int w = width + border.cx; int h = height + border.cy; int cx = GetSystemMetrics(SM_CXFULLSCREEN); int cy = GetSystemMetrics(SM_CYFULLSCREEN); while ( pos.x < 0 ) pos.x = 0; while ( pos.y < 0 ) pos.y = 0; if ( pos.y + h >= cy ) { if ( gdwProcNum ) pos.y -= cy - h; else pos.y = cy - h; } if ( pos.x + w >= cx ) { if ( gdwProcNum ) pos.x -= cx - w; else pos.x = cx - w; } MoveWindow(ghMainWnd, pos.x, pos.y, w, h, TRUE); SetCursor(NULL); SetCursorShowState(false); SetDIBColorTable(hdcMem, 0, 256, wmodebmp.bmiColors); WritePrivateProfileString("window", "windowed", "ON", szConfigPath); } else { wmode = false; *BW::BWDATA_PrimarySurface = NULL; if ( hdcMem ) DeleteDC(hdcMem); hdcMem = NULL; SetWindowLong(ghMainWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE | WS_SYSMENU); SetWindowPos(ghMainWnd, HWND_TOPMOST, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW); SetCursor(NULL); SetCursorShowState(false); SetFocus(ghMainWnd); DDrawDestroy(); DDrawInitialize(width, height); WritePrivateProfileString("window", "windowed", "OFF", szConfigPath); } }