// 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);
}
Exemple #2
0
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);
  }
}