Index: CrashLogger.cpp
===================================================================
--- CrashLogger.cpp	(revision d9b6a1c5928db418f1226ed7e59f18eff16252df)
+++ CrashLogger.cpp	(revision b3734660b44b83ea30bd28f6fbf37ea72889956e)
@@ -4,17 +4,19 @@
 #include <cstdio>
 #include <csignal>
+#include <cstring>
 
 #include <fcntl.h>
 
 #include "Compiler.h"
+#include "Consts.h"
+
+// TODO: Double-check which includes are necessary
 
 #ifdef WINDOWS
-   // most of this can be removed since Windows uses __try __catch instead of signals
-
    #include <windows.h>
-   #include "StackWalker.h"
-
    #include <io.h>
    #include <sys/stat.h>
+
+   #include "FileStackWalker.h"
 
    // The windows analogues to the unix open, close, and write functions
@@ -25,4 +27,6 @@
 
    #define STDERR_FILENO 2
+
+   bool handleException(unsigned int expCode, EXCEPTION_POINTERS* pExp, HANDLE thread);
 #else
    #include <unistd.h>
@@ -31,16 +35,40 @@
    #include <cxxabi.h>
    #include <cstring>
+
+   void abortHandler(int signum);
+   static inline void printStackTrace(int fd_out = STDERR_FILENO);
 #endif
 
-CrashLogger::CrashLogger() {
-   // Apparently, sigaction should be used instead for Linux
-   // It gives more info. Check if I should bother switching
-
-   signal(SIGABRT, abortHandler);
-   signal(SIGSEGV, abortHandler);
-   signal(SIGILL, abortHandler);
-   signal(SIGFPE, abortHandler);
-
-   write(STDERR_FILENO, "Handlers attached\n", 18);
+void printInfo(int fd_out);
+
+CrashLogger::CrashLogger(int(*mainFunc)(int, char*[]), int argc, char* argv[]) {
+   write(STDERR_FILENO, "Calling main\n", 13);
+
+   #ifdef WINDOWS
+      __try {
+         mainFunc(argc, argv);
+         // maybe do this and call a function inside CrashLogger
+         // In that case, also pass GetCurrentThread() as a parameter to then pass to handleException
+         // I could also move almost all of this into CrashLogger by creating a function in CrashLogger that takes a reference
+         // to the effective main function and, for Windows, wraps it in all this error-handling stuff
+      } __except (handleException(
+            GetExceptionCode(),
+            GetExceptionInformation(),
+            GetCurrentThread())
+            ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER) {
+      }
+   #else
+      // Apparently, sigaction should be used instead for Linux
+      // It gives more info. Check if I should bother switching
+
+      signal(SIGABRT, abortHandler);
+      signal(SIGSEGV, abortHandler);
+      signal(SIGILL, abortHandler);
+      signal(SIGFPE, abortHandler);
+
+      write(STDERR_FILENO, "Handlers attached\n", 18);
+
+      mainFunc(argc, argv);
+   #endif
 }
 
@@ -48,5 +76,55 @@
 }
 
-static inline void printStackTrace(int fd_out = STDERR_FILENO) {
+#ifdef WINDOWS
+
+bool handleException(unsigned int expCode, EXCEPTION_POINTERS* pExp, HANDLE thread) {
+   int crash_log = open(CRASH_LOG_FILE, O_RDWR | O_CREAT | O_APPEND, _S_IREAD | _S_IWRITE);
+
+   if (crash_log == -1) {
+      // TODO: Figure out exactly what perror does and if I should use it
+      perror("opening crash.log");  // TODO: Figure out exactly what perror does and if I should use it
+   }
+
+   printInfo(crash_log);
+
+   FileStackWalker sw(crash_log == -1 ? STDERR_FILENO  : crash_log);
+
+   if (pExp != NULL) {
+      sw.ShowCallstack(thread, pExp->ContextRecord);
+   } else {
+      write(crash_log, "Could not get the stack trace\n", 30);
+   }
+
+   close(crash_log);
+
+   if (expCode == EXCEPTION_ACCESS_VIOLATION) {
+      write(STDERR_FILENO, "ACCESS VIOLATION\n", 17);
+   }
+
+   return true;
+}
+
+#else
+
+void abortHandler(int signum) {
+   int crash_log = open(CRASH_LOG_FILE, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+
+   if (crash_log == -1) {
+      // TODO: Figure out exactly what perror does and if I should use it
+      perror("opening crash.log"); 
+   }
+
+   printInfo(crash_log);
+
+   printStackTrace(crash_log);
+
+   close(crash_log);
+
+   write(STDERR_FILENO, "The game has crashed. Check crash.log for more info\n", 52);
+
+   exit(signum);
+}
+
+static inline void printStackTrace(int fd_out) {
    write(fd_out, "stack trace:\n", 13);
 
@@ -74,51 +152,51 @@
       char* begin_name = NULL;
       char* begin_offset = NULL;
-      char* end_offset = NULL; // Iirc, this is used in the Linux code
-
-      #ifdef MAC
-         for (char *p = symbollist[i]; *p; p++) {
-            if ((*p == '_') && (*(p-1) == ' ')) {
-               begin_name = p-1;
-            } else if(*p == '+') {
-               begin_offset = p-1;
-            }
+      char* end_offset = NULL; // Iirc, this is used in the Linux code (Check what it's used for)
+
+#ifdef MAC
+      for (char *p = symbollist[i]; *p; p++) {
+         if ((*p == '_') && (*(p-1) == ' ')) {
+            begin_name = p-1;
+         } else if(*p == '+') {
+            begin_offset = p-1;
          }
-
-         if (begin_name && begin_offset && (begin_name < begin_offset )) {
-            *begin_name++ = '\0';
-            *begin_offset++ = '\0';
-
-            // mangled name is now in [begin_name, begin_offset) and caller
-            // offset in [begin_offset, end_offset). now apply
-            // __cxa_demangle():
-            int status;
-            char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
-
-            if (status == 0)  {
-               funcname = ret; // use possibly realloc()-ed string
-               write(fd_out, symbollist[i], strlen(symbollist[i]));
-               write(fd_out, " ", 1);
-               write(fd_out, funcname, strlen(funcname));
-               write(fd_out, " ", 1);
-               write(fd_out, begin_offset, strlen(begin_offset));
-            } else {
-               // demangling failed. Output function name as a C function with no arguments.
-               write(fd_out, "Error\n", 6);
-               write(fd_out, symbollist[i], strlen(symbollist[i]));
-               write(fd_out, " ", 1);
-               write(fd_out, begin_name, strlen(begin_name));
-               write(fd_out, "() ", 3);
-               write(fd_out, begin_offset, strlen(begin_offset));
-            }
+      }
+
+      if (begin_name && begin_offset && (begin_name < begin_offset )) {
+         *begin_name++ = '\0';
+         *begin_offset++ = '\0';
+
+         // mangled name is now in [begin_name, begin_offset) and caller
+         // offset in [begin_offset, end_offset). now apply
+         // __cxa_demangle():
+         int status;
+         char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
+
+         if (status == 0)  {
+            funcname = ret; // use possibly realloc()-ed string
+            write(fd_out, symbollist[i], strlen(symbollist[i]));
+            write(fd_out, " ", 1);
+            write(fd_out, funcname, strlen(funcname));
+            write(fd_out, " ", 1);
+            write(fd_out, begin_offset, strlen(begin_offset));
          } else {
-            // couldn't parse the line? print the whole line.
+            // demangling failed. Output function name as a C function with no arguments.
+            write(fd_out, "Error\n", 6);
             write(fd_out, symbollist[i], strlen(symbollist[i]));
+            write(fd_out, " ", 1);
+            write(fd_out, begin_name, strlen(begin_name));
+            write(fd_out, "() ", 3);
+            write(fd_out, begin_offset, strlen(begin_offset));
          }
-         write(fd_out, "\n", 1);
-      #else
-         // Check that this works on Linux Mint
+      } else {
+         // couldn't parse the line? print the whole line.
          write(fd_out, symbollist[i], strlen(symbollist[i]));
-         write(fd_out, "\n", 1);
-      #endif
+      }
+      write(fd_out, "\n", 1);
+#else
+      // Check that this works on Linux Mint
+      write(fd_out, symbollist[i], strlen(symbollist[i]));
+      write(fd_out, "\n", 1);
+#endif
    }
 
@@ -129,20 +207,23 @@
 }
 
-// Most of this function could probably be shared between Windows and Linux/Mac
-void abortHandler(int signum) {
-   #ifdef WINDOWS
-      int crash_log = open("crash.log", O_RDWR | O_CREAT | O_APPEND, _S_IREAD | _S_IWRITE);
+#endif
+
+void printInfo(int fd_out) {
+   write(fd_out, "Game Version: ", 14);
+   write(fd_out, GAME_VERSION, strlen(GAME_VERSION));
+   write(fd_out, "\n", 1);
+
+   write(fd_out, "OS: ", 4);
+   #if defined WINDOWS
+      write(fd_out, "Windows", 7);
+   #elif defined LINUX
+      write(fd_out, "Linux", 5);
+   #elif defined MAC
+      write(fd_out, "Mac", 3);
    #else
-      int crash_log = open("crash.log", O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+      write(fd_out, "Unknown", 7);
    #endif
-
-   if (crash_log == -1) {
-      perror("opening crash.log");  // TODO: Figure out exactly what perror does and if I should use it
-   }
-
-   printStackTrace(crash_log);
-
-   close(crash_log);
-
-   exit(signum);
-}
+   write(fd_out, "\n", 1);
+
+   write(fd_out, "\n", 1);
+}
