Code::Blocks  SVN r11506
crashhandler.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 9410 $
6  * $Id: crashhandler.cpp 9410 2013-10-19 23:45:48Z alpha0010 $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/src/crashhandler.cpp $
8  */
9 
10 #ifdef __WXMSW__
11 #include "sdk.h"
12 #ifndef CB_PRECOMP
13  #include <wx/filefn.h>
14  #include <wx/filename.h>
15  #include <wx/string.h>
16  #include "cbeditor.h"
17  #include "configmanager.h"
18  #include "editormanager.h"
19  #include "globals.h"
20 #endif //CB_PRECOMP
21 #include "cbstyledtextctrl.h"
22 
23 #include "crashhandler.h"
24 #include <shlobj.h>
25 
27 {
28  wxString path;
29  //get the "My Files" folder
30  HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, wxStringBuffer(path, MAX_PATH));
31  if (FAILED(result))
32  { //get at least the profiles folder
34  }
35  path << _T("\\cb-crash-recover");
36  if (!wxDirExists(path)) wxMkdir(path);
37 
38  //make a sub-directory of the current date & time
40  path << now.Format(_T("\\%Y%m%d-%H%M%S"));
41 
43  if (em)
44  {
45  bool AnyFileSaved = false;
46  if (wxMkdir(path) && wxDirExists(path))
47  {
48  for (int i = 0; i < em->GetEditorsCount(); ++i)
49  {
50  cbEditor* ed = em->GetBuiltinEditor(em->GetEditor(i));
51  if (ed)
52  {
53  wxFileName fn(ed->GetFilename());
54  wxString fnpath = path + _T("/") + fn.GetFullName();
55  wxString newfnpath = fnpath;
56  // add number if filename already exists e.g. main.cpp.001, main.cpp.002, ...
57  int j = 1;
58  while (wxFileExists(newfnpath))
59  newfnpath = fnpath + wxString::Format(wxT(".%03d"),j);
60 
61  if (cbSaveToFile(newfnpath,
62  ed->GetControl()->GetText(),
63  ed->GetEncoding(),
64  ed->GetUseBom() ) )
65  {
66  AnyFileSaved = true;
67  }
68  }
69  }
70 
71  if (AnyFileSaved)
72  {
73  buf << _("The currently opened files have been saved to the directory\n");
74  buf << path;
75  buf << _("\nHopefully, this will prevent you from losing recent modifications.\n\n");
76  }
77  else
78  wxRmdir(path);
79  }
80  }
81 }
82 
83 LONG WINAPI CrashHandlerFunc(PEXCEPTION_POINTERS ExceptionInfo)
84 {
85  static bool EditorFilesNotSaved = true;
86  DWORD code = ExceptionInfo->ExceptionRecord->ExceptionCode;
87 
88  if (code != EXCEPTION_ACCESS_VIOLATION && code != EXCEPTION_ILLEGAL_INSTRUCTION)
89  return EXCEPTION_CONTINUE_SEARCH;
90 
91  wxString buf;
92 #if !defined(_WIN64)
93  buf.Printf(_("The application encountered a crash at address %u.\n\n"),
94  (unsigned int) ExceptionInfo->ContextRecord->Eip);
95 #endif
96 
97  if (EditorFilesNotSaved)
98  {
100  EditorFilesNotSaved = false;
101  }
102 
103  buf << _("Now you have three options:\n"
104  "1. Press 'Abort' to pass control back to the system. This will normally display the standard 'application error' message and kill the program.\n"
105  "2. Press 'Ignore' to step over the offending instruction. You may run into another access violation, but if you are lucky enough, you might get to save your work and close the program gracefully.\n"
106  "3. Press 'Retry' to return to the offending instruction (this is almost certain to fail again, but might nevertheless work in rare cases).");
107 
108 
109  switch(MessageBox(0, buf.c_str(), _T("Woah!"), MB_ABORTRETRYIGNORE))
110  {
111  case IDABORT:
112  return EXCEPTION_CONTINUE_SEARCH;
113  break;
114 
115  case IDIGNORE:
116 #if !defined(_WIN64)
117  ExceptionInfo->ContextRecord->Eip += 2;
118 #endif
119  return EXCEPTION_CONTINUE_EXECUTION;
120  break;
121 
122  case IDRETRY:
123  return EXCEPTION_CONTINUE_EXECUTION;
124  break;
125  default:
126  break;
127  }
128  return EXCEPTION_CONTINUE_SEARCH;
129 };
130 
131 
132 CrashHandler::CrashHandler(bool bDisabled) : handler(0)
133 {
134  if (!bDisabled)
135  {
136  AddHandler_t AddHandler = (AddHandler_t) GetProcAddress(GetModuleHandle(_T("kernel32")), "AddVectoredExceptionHandler");
137 
138  if (AddHandler)
139  handler = AddHandler(1, CrashHandlerFunc);
140  }
141 }
142 
144 {
145  if (handler)
146  {
147  RemoveHandler_t RemoveHandler = (RemoveHandler_t) GetProcAddress(GetModuleHandle(_T("kernel32")), "RemoveVectoredExceptionHandler");
148  RemoveHandler(handler);
149  }
150 }
151 
152 #endif //(__WXMSW__)
bool wxRmdir(const wxString &dir, int flags=0)
wxFontEncoding GetEncoding() const
Definition: cbeditor.cpp:1626
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
bool wxFileExists(const wxString &filename)
static wxDateTime Now()
wxCStrData c_str() const
bool wxDirExists(const wxString &dirname)
#define _T(string)
CrashHandler(bool bDisabled)
#define wxT(string)
bool wxMkdir(const wxString &dir, int perm=wxS_DIR_DEFAULT)
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
virtual const wxString & GetFilename() const
Get the editor&#39;s filename (if applicable).
Definition: editorbase.h:45
cbStyledTextCtrl * GetControl() const
Returns a pointer to the underlying cbStyledTextCtrl object (which itself is the wxWindows implementa...
Definition: cbeditor.cpp:842
void CrashHandlerSaveEditorFiles(wxString &buf)
unsigned long(* RemoveHandler_t)(void *)
Definition: crashhandler.h:18
const wxString & _(const wxString &string)
EditorBase * GetEditor(int index)
cbEditor * GetBuiltinEditor(EditorBase *eb)
A file editor.
Definition: cbeditor.h:43
LONG WINAPI CrashHandlerFunc(PEXCEPTION_POINTERS ExceptionInfo)
static wxString GetHomeFolder()
DLLIMPORT bool cbSaveToFile(const wxString &filename, const wxString &contents, wxFontEncoding encoding=wxFONTENCODING_SYSTEM, bool bom=false)
Writes a wxString to a file.
Definition: globals.cpp:721
void *(* AddHandler_t)(unsigned long, PVECTORED_EXCEPTION_HANDLER)
Definition: crashhandler.h:17
wxString GetText() const
Retrieve all the text in the document.
bool GetUseBom() const
Definition: cbeditor.cpp:1654
void * handler
Definition: crashhandler.h:20
int Printf(const wxString &pszFormat,...)
wxString Format(const wxString &format=wxDefaultDateTimeFormat, const TimeZone &tz=Local) const
#define NULL
Definition: prefix.cpp:59
static wxString Format(const wxString &format,...)