Index: adblockplus.gyp
diff --git a/adblockplus.gyp b/adblockplus.gyp
index 4bf7a1a3970165d271aede0e03ad6f2a769e3385..aa5512cefe40a8979f02fff90a7f99fa797e5169 100644
--- a/adblockplus.gyp
+++ b/adblockplus.gyp
@@ -97,6 +97,7 @@
       'src/plugin/BuildVariant.h',
       'src/plugin/Config.h',
       'src/plugin/Console.h',
+      'src/plugin/Exception.h',
       'src/plugin/NotificationMessage.cpp',
       'src/plugin/NotificationMessage.h',
       'src/plugin/Plugin.cpp',
@@ -111,7 +112,6 @@
       'src/plugin/PluginDebug.cpp',
       'src/plugin/PluginDebug.h',
       'src/plugin/PluginDomTraverserBase.h',
-      'src/plugin/PluginErrorCodes.h',
       'src/plugin/PluginFilter.cpp',
       'src/plugin/PluginFilter.h',
       'src/plugin/PluginMimeFilterClient.cpp',
@@ -229,8 +229,10 @@
       'libadblockplus/third_party/googletest.gyp:googletest_main',
     ],
     'sources': [
+      'src/plugin/Exception.h',
       'src/plugin/PluginUserSettings.cpp',
       'src/plugin/PluginUserSettings.h',
+      'test/plugin/ExceptionTest.cpp',
       'test/plugin/UserSettingsTest.cpp',
       #
       # required only for linking
Index: src/plugin/Exception.h
diff --git a/src/plugin/Exception.h b/src/plugin/Exception.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd945c5879ef23058dd23918011456597883ebff
--- /dev/null
+++ b/src/plugin/Exception.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file Exception.h -- Default behavior for catch-all exception handlers.
+ */
+
+template<typename SubHandlers>
+struct CatchAllVoid
+{
+  template<typename UserData>
+  static void Handler(UserData userData)
+  {
+    try
+    {
+      std::rethrow_exception(std::current_exception());
+    }
+    catch (const std::system_error& ex)
+    {
+      SubHandlers::Exception(ex, userData);
+    }
+    catch (const std::runtime_error& ex)
+    {
+      SubHandlers::Exception(ex, userData);
+    }
+    catch (const std::logic_error& ex)
+    {
+      SubHandlers::Exception(ex, userData);
+    }
+    catch (const std::exception& ex)
+    {
+      SubHandlers::Exception(ex, userData);
+    }
+    catch (...)
+    {
+      SubHandlers::Unknown(userData);
+    }
+  }
+};
+
+template<typename SubHandlers, typename ReturnType = typename SubHandlers::ReturnType>
+struct CatchAllReturn
+{
+  template<typename UserData>
+  static ReturnType Handler(UserData userData)
+  {
+    try
+    {
+      std::rethrow_exception(std::current_exception());
+      // Apparently VS 2012 does not realize that this function always throws.
+      // Unless we have an explicit return statement, we get a spurious warning C4715 "not all control paths return a value".
+      return ReturnType();
+    }
+    catch (const std::system_error& ex)
+    {
+      return SubHandlers::Exception(ex, userData);
+    }
+    catch (const std::runtime_error& ex)
+    {
+      return SubHandlers::Exception(ex, userData);
+    }
+    catch (const std::logic_error& ex)
+    {
+      return SubHandlers::Exception(ex, userData);
+    }
+    catch (const std::exception& ex)
+    {
+      return SubHandlers::Exception(ex, userData);
+    }
+    catch (...)
+    {
+      return SubHandlers::Unknown(userData);
+    }
+  }
+};
Index: src/plugin/PluginClass.cpp
diff --git a/src/plugin/PluginClass.cpp b/src/plugin/PluginClass.cpp
index 485630c02677360272a831ae1dcdf9d2c20a8c0f..f48f2e9ee53dbe1113402d2edfcfd90ae9d1b5f5 100644
--- a/src/plugin/PluginClass.cpp
+++ b/src/plugin/PluginClass.cpp
@@ -543,6 +543,7 @@ void STDMETHODCALLTYPE CPluginClass::OnBeforeNavigate2(
   }
   catch (...)
   {
+    EntryPointExceptionDefault("CPluginClass::OnBeforeNavigate2");
   }
 }
 
@@ -560,6 +561,7 @@ void STDMETHODCALLTYPE CPluginClass::OnDownloadComplete()
   }
   catch (...)
   {
+    EntryPointExceptionDefault("CPluginClass::OnDownloadComplete");
   }
 }
 
@@ -581,6 +583,7 @@ void STDMETHODCALLTYPE CPluginClass::OnDocumentComplete(IDispatch* frameBrowserD
   }
   catch (...)
   {
+    EntryPointExceptionDefault("CPluginClass::OnDocumentComplete");
   }
 }
 
@@ -611,6 +614,7 @@ void STDMETHODCALLTYPE CPluginClass::OnWindowStateChanged(unsigned long flags, u
   }
   catch (...)
   {
+    EntryPointExceptionDefault("CPluginClass::OnWindowStateChanged");
   }
 }
 
@@ -639,6 +643,7 @@ void STDMETHODCALLTYPE CPluginClass::OnCommandStateChange(long /*command*/, VARI
   }
   catch (...)
   {
+    EntryPointExceptionDefault("CPluginClass::OnCommandStateChange");
   }
 }
 
@@ -651,6 +656,7 @@ void STDMETHODCALLTYPE CPluginClass::OnOnQuit()
   }
   catch (...)
   {
+    EntryPointExceptionDefault("CPluginClass::OnOnQuit");
   }
 }
 
Index: src/plugin/PluginDebug.cpp
diff --git a/src/plugin/PluginDebug.cpp b/src/plugin/PluginDebug.cpp
index 0b08e87e25f52cf6f2aad23f97e50021c8b6ebef..c2521b046480a2948c4bd2f0307379a8e41158ba 100644
--- a/src/plugin/PluginDebug.cpp
+++ b/src/plugin/PluginDebug.cpp
@@ -1,258 +1,338 @@
-/*
- * This file is part of Adblock Plus <https://adblockplus.org/>,
- * Copyright (C) 2006-2015 Eyeo GmbH
- *
- * Adblock Plus is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * Adblock Plus is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "PluginStdAfx.h"
-
-#include "PluginDebug.h"
-#include "PluginMutex.h"
-#include "PluginSettings.h"
-
-class CPluginDebugLock : public CPluginMutex
-{
-
-private:
-
-  static CComAutoCriticalSection s_criticalSectionDebugLock;
-
-public:
-
-  CPluginDebugLock() : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE)
-  {
-    s_criticalSectionDebugLock.Lock();
-  }
-
-  ~CPluginDebugLock()
-  {
-    s_criticalSectionDebugLock.Unlock();
-  }
-};
-
-CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock;
-
-void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId, int errorSubid, const std::string& description)
-{
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "PluginStdAfx.h"
+
+#include "PluginDebug.h"
+#include "Exception.h"
+#include "PluginMutex.h"
+#include "PluginSettings.h"
+
+#if (defined ENABLE_DEBUG_INFO)
+namespace {
+  // VS 2012 does not have support for variadic templates, which would eliminate the need for an argument class.
+  struct LogHandlersArguments
+  {
+    bool isEntryPoint;
+    std::string name;
+  };
+
+  std::string DefaultLogMessage(const LogHandlersArguments& x, const std::string &exceptionType)
+  {
+    std::string s = x.isEntryPoint ? "ENTRY POINT '" : "'";
+    s += x.name;
+    s += "' caught default ";
+    s += exceptionType;
+    return s;
+  }
+
+  struct LogHandlers
+  {
+    static void Unknown(const LogHandlersArguments& args)
+    {
+      CPluginDebug::Debug(DefaultLogMessage(args, "Unknown exception"));
+    }
+    static void Exception(const std::exception& ex, LogHandlersArguments& args)
+    {
+      CPluginDebug::DebugOrdinaryException(ex,
+        PLUGIN_ERROR_ENTRY_POINT, PLUGIN_ERROR_ENTRY_POINT_CATCHALL_EXCEPTION,
+        DefaultLogMessage(args, "std::exception"));
+    }
+    static void LogicError(const std::logic_error& ex, LogHandlersArguments& args)
+    {
+      CPluginDebug::DebugOrdinaryException(ex,
+        PLUGIN_ERROR_ENTRY_POINT, PLUGIN_ERROR_ENTRY_POINT_CATCHALL_EXCEPTION,
+        DefaultLogMessage(args, "std::logic_error"));
+    }
+    static void RuntimeError(const std::runtime_error& ex, LogHandlersArguments& args)
+    {
+      CPluginDebug::DebugOrdinaryException(ex,
+        PLUGIN_ERROR_ENTRY_POINT, PLUGIN_ERROR_ENTRY_POINT_CATCHALL_EXCEPTION,
+        DefaultLogMessage(args, "std::runtime_error"));
+    }
+    static void SystemError(const std::system_error& ex, LogHandlersArguments& args)
+    {
+      CPluginDebug::DebugSystemException(ex,
+        PLUGIN_ERROR_ENTRY_POINT, PLUGIN_ERROR_ENTRY_POINT_CATCHALL_EXCEPTION,
+        DefaultLogMessage(args, "std::std::system_error"));
+    }
+  };
+}
+#endif
+
+void EntryPointExceptionDefault(const std::string& name)
+{
+#if (defined ENABLE_DEBUG_INFO)
+  // VS 2012 does not have support for brace initializer lists; otherwise this could be a single line
+  LogHandlersArguments x;
+  x.isEntryPoint = true;
+  x.name = name;
+  CatchAllVoid<LogHandlers>::Handler(x);
+#endif
+}
+
+void ExceptionDefault(const std::string& name)
+{
+#if (defined ENABLE_DEBUG_INFO)
+  LogHandlersArguments x;
+  x.isEntryPoint = false;
+  x.name = name;
+  CatchAllVoid<LogHandlers>::Handler(x);
+#endif
+}
+
+class CPluginDebugLock : public CPluginMutex
+{
+
+private:
+
+  static CComAutoCriticalSection s_criticalSectionDebugLock;
+
+public:
+
+  CPluginDebugLock() : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE)
+  {
+    s_criticalSectionDebugLock.Lock();
+  }
+
+  ~CPluginDebugLock()
+  {
+    s_criticalSectionDebugLock.Unlock();
+  }
+};
+
+CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock;
+
+void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId, int errorSubid, const std::string& description)
+{
   std::string message = description + ", " + ex.code().message() + ", " + ex.what();
   DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message);
-}
-
-#ifdef ENABLE_DEBUG_INFO
-
-void DebugLegacy(const CString& text, DWORD dwProcessId, DWORD dwThreadId)
-{
-#ifdef USE_CONSOLE
-  CONSOLE("%s", CT2A(text.GetString(), CP_UTF8));
-#endif
-
-  if (CPluginSettings::HasInstance())
-  {
-#ifdef ENABLE_DEBUG_SPLIT_FILE
-    CPluginSettings* settings = CPluginSettings::GetInstance();
-
-    bool isWorkingThread = settings->IsWorkingThread(dwThreadId);
-
-    std::wstring processor;
-    wchar_t tmp[10];
-    _itow_s(::GetCurrentProcessId(), tmp, 10);
-    if (isWorkingThread)
-      processor = L"tab" + std::wstring(tmp) + L"_thread";
-    else
-      processor = L"tab" + std::wstring(tmp) + L"_ui";
-#else
-    if (dwProcessId == 0)
-    {
-      dwProcessId = ::GetCurrentProcessId();
-    }
-    if (dwThreadId == 0)
-    {
-      dwThreadId = ::GetCurrentThreadId();
-    }
-
-    CStringA processInfo;
-    processInfo.Format("%4.4u.%4.4u - ", dwProcessId, dwThreadId);
-#endif
-    SYSTEMTIME st;
-    ::GetSystemTime(&st);
-
-    CStringA sysTime;
-    sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
-
-    CPluginDebugLock lock;
-    if (lock.IsLocked())
-    {
-      std::ofstream debugFile;
-
-#ifdef ENABLE_DEBUG_SPLIT_FILE
-      debugFile.open(GetDataPath(L"debug_" + processor + L".txt"), std::ios::app);
-#else
-      debugFile.open(GetDataPath(L"debug.txt"), std::ios::app);
-#endif
-      int pos = 0;
-      CStringA line = text.Tokenize(L"\n\r", pos);
-
-      while (pos >= 0)
-      {
-        debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
-#ifndef ENABLE_DEBUG_SPLIT_FILE
-        debugFile.write(processInfo.GetBuffer(), processInfo.GetLength());
-#endif
-        debugFile.write(line.GetBuffer(), line.GetLength());
-        debugFile.write("\n", 1);
-
-        line = text.Tokenize(L"\n\r", pos);
-      }
-
-      debugFile.flush();
-    }
-  }
-}
-
-void CPluginDebug::Debug(const std::string& text, DWORD processId, DWORD threadId)
-{
-  DebugLegacy(CString(text.c_str()), processId, threadId);
-}
-
-void CPluginDebug::Debug(const std::wstring& text, DWORD processId, DWORD threadId)
-{
-  DebugLegacy(ToCString(text), processId, threadId);
-}
-
-#endif
-
-#if (defined ENABLE_DEBUG_INFO)
-
-void CPluginDebug::DebugException(const std::exception& ex)
-{
-  auto error = std::string("!!! Exception:") + ex.what();
-#ifdef ENABLE_DEBUG_ERROR
-  Debug(error);
-#endif
-
-  DEBUG_SELFTEST("********************************************************************************\n" + error + "\n********************************************************************************")
-}
-
-void DebugErrorCodeLegacy(DWORD errorCode, const CString& error, DWORD dwProcessId, DWORD dwThreadId)
-{
-  CString errorCodeText;
-  errorCodeText.Format(L"%u (0x%8.8x)", errorCode, errorCode);
-
-  CString finalError = error + L". error=" + errorCodeText;
-
-#ifdef ENABLE_DEBUG_ERROR
-  DebugLegacy(finalError, dwProcessId, dwThreadId);
-#endif
-
-  DEBUG_SELFTEST(L"********************************************************************************\n" + finalError + "\n********************************************************************************")
-}
-
-void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWORD processId, DWORD threadId)
-{
-  DebugErrorCodeLegacy(errorCode, CString(error.c_str()), processId, threadId);
-}
-
-#endif
-
-// ============================================================================
-// Debug result
-// ============================================================================
-
-#ifdef ENABLE_DEBUG_RESULT
-
-void DebugResultLegacy(const CString& text)
-{
-  SYSTEMTIME st;
-  ::GetSystemTime(&st);
-
-  CStringA sysTime;
-  sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
-
-  CStringA textA = text;
-
-  CPluginDebugLock lock;
-  if (lock.IsLocked())
-  {
-    std::ofstream debugFile;
-
-    debugFile.open(GetDataPath(L"debug_result.txt"), std::ios::app);
-    debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
-    debugFile.write(LPCSTR(textA), textA.GetLength());
-    debugFile.write("\n", 1);
-    debugFile.flush();
-  }
-}
-
-void CPluginDebug::DebugResult(const std::wstring& text)
-{
-  DebugResultLegacy(ToCString(text));
-}
-
-void CPluginDebug::DebugResultDomain(const std::wstring& domain)
-{
-  DebugResult(L"===========================================================================================================================================================================================");
-  DebugResult(domain);
-  DebugResult(L"===========================================================================================================================================================================================");
-}
-
-
-void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstring& src, const std::wstring& domain)
-{
-  CString srcTrunc = ToCString(src);
-  if (src.length() > 100)
-  {
-    srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
-  }
-
-  CString blocking;
-  blocking.Format(L"Blocked  %-12s  %-20s  %s", ToCString(type), domain.empty()? L"-" : ToCString(domain), srcTrunc);
-
-  DebugResultLegacy(blocking);
-}
-
-
-void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring& id, const std::wstring& filter)
-{
-  CString srcTrunc = ToCString(id);
-  if (srcTrunc.GetLength() > 100)
-  {
-    srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
-  }
-
-  CString blocking;
-  blocking.Format(L"Hidden   %-12s  - %s  %s", ToCString(tag), srcTrunc, ToCString(filter));
-
-  DebugResultLegacy(blocking);
-}
-
-#endif // ENABLE_DEBUG_RESULT
-
-
-#ifdef ENABLE_DEBUG_RESULT_IGNORED
-
-void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstring& src, const std::wstring& domain)
-{
-  CString srcTrunc = ToCString(src);
-  if (src.length() > 100)
-  {
-    srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
-  }
-
-  CString blocking;
-  blocking.Format(L"Ignored  %-12s  %s  %s", ToCString(type), domain.empty()? L"-" : ToCString(domain), srcTrunc);
-
-  DebugResultLegacy(blocking);
-}
-
-#endif // ENABLE_DEBUG_RESULT_IGNORED
+}
+
+void CPluginDebug::DebugOrdinaryException(const std::exception& ex, int errorId, int errorSubid, const std::string& description)
+{
+  std::string message = description + ", " + ex.what();
+  DEBUG_ERROR_LOG(0, errorId, errorSubid, message);
+}
+
+#ifdef ENABLE_DEBUG_INFO
+
+void DebugLegacy(const CString& text, DWORD dwProcessId, DWORD dwThreadId)
+{
+#ifdef USE_CONSOLE
+  CONSOLE("%s", CT2A(text.GetString(), CP_UTF8));
+#endif
+
+  if (CPluginSettings::HasInstance())
+  {
+#ifdef ENABLE_DEBUG_SPLIT_FILE
+    CPluginSettings* settings = CPluginSettings::GetInstance();
+
+    bool isWorkingThread = settings->IsWorkingThread(dwThreadId);
+
+    std::wstring processor;
+    wchar_t tmp[10];
+    _itow_s(::GetCurrentProcessId(), tmp, 10);
+    if (isWorkingThread)
+      processor = L"tab" + std::wstring(tmp) + L"_thread";
+    else
+      processor = L"tab" + std::wstring(tmp) + L"_ui";
+#else
+    if (dwProcessId == 0)
+    {
+      dwProcessId = ::GetCurrentProcessId();
+    }
+    if (dwThreadId == 0)
+    {
+      dwThreadId = ::GetCurrentThreadId();
+    }
+
+    CStringA processInfo;
+    processInfo.Format("%4.4u.%4.4u - ", dwProcessId, dwThreadId);
+#endif
+    SYSTEMTIME st;
+    ::GetSystemTime(&st);
+
+    CStringA sysTime;
+    sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+
+    CPluginDebugLock lock;
+    if (lock.IsLocked())
+    {
+      std::ofstream debugFile;
+
+#ifdef ENABLE_DEBUG_SPLIT_FILE
+      debugFile.open(GetDataPath(L"debug_" + processor + L".txt"), std::ios::app);
+#else
+      debugFile.open(GetDataPath(L"debug.txt"), std::ios::app);
+#endif
+      int pos = 0;
+      CStringA line = text.Tokenize(L"\n\r", pos);
+
+      while (pos >= 0)
+      {
+        debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
+#ifndef ENABLE_DEBUG_SPLIT_FILE
+        debugFile.write(processInfo.GetBuffer(), processInfo.GetLength());
+#endif
+        debugFile.write(line.GetBuffer(), line.GetLength());
+        debugFile.write("\n", 1);
+
+        line = text.Tokenize(L"\n\r", pos);
+      }
+
+      debugFile.flush();
+    }
+  }
+}
+
+void CPluginDebug::Debug(const std::string& text, DWORD processId, DWORD threadId)
+{
+  DebugLegacy(CString(text.c_str()), processId, threadId);
+}
+
+void CPluginDebug::Debug(const std::wstring& text, DWORD processId, DWORD threadId)
+{
+  DebugLegacy(ToCString(text), processId, threadId);
+}
+
+#endif
+
+#if (defined ENABLE_DEBUG_INFO)
+
+void CPluginDebug::DebugException(const std::exception& ex)
+{
+  auto error = std::string("!!! Exception:") + ex.what();
+#ifdef ENABLE_DEBUG_ERROR
+  Debug(error);
+#endif
+
+  DEBUG_SELFTEST("********************************************************************************\n" + error + "\n********************************************************************************")
+}
+
+void DebugErrorCodeLegacy(DWORD errorCode, const CString& error, DWORD dwProcessId, DWORD dwThreadId)
+{
+  CString errorCodeText;
+  errorCodeText.Format(L"%u (0x%8.8x)", errorCode, errorCode);
+
+  CString finalError = error + L". error=" + errorCodeText;
+
+#ifdef ENABLE_DEBUG_ERROR
+  DebugLegacy(finalError, dwProcessId, dwThreadId);
+#endif
+
+  DEBUG_SELFTEST(L"********************************************************************************\n" + finalError + "\n********************************************************************************")
+}
+
+void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWORD processId, DWORD threadId)
+{
+  DebugErrorCodeLegacy(errorCode, CString(error.c_str()), processId, threadId);
+}
+
+#endif
+
+// ============================================================================
+// Debug result
+// ============================================================================
+
+#ifdef ENABLE_DEBUG_RESULT
+
+void DebugResultLegacy(const CString& text)
+{
+  SYSTEMTIME st;
+  ::GetSystemTime(&st);
+
+  CStringA sysTime;
+  sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+
+  CStringA textA = text;
+
+  CPluginDebugLock lock;
+  if (lock.IsLocked())
+  {
+    std::ofstream debugFile;
+
+    debugFile.open(GetDataPath(L"debug_result.txt"), std::ios::app);
+    debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
+    debugFile.write(LPCSTR(textA), textA.GetLength());
+    debugFile.write("\n", 1);
+    debugFile.flush();
+  }
+}
+
+void CPluginDebug::DebugResult(const std::wstring& text)
+{
+  DebugResultLegacy(ToCString(text));
+}
+
+void CPluginDebug::DebugResultDomain(const std::wstring& domain)
+{
+  DebugResult(L"===========================================================================================================================================================================================");
+  DebugResult(domain);
+  DebugResult(L"===========================================================================================================================================================================================");
+}
+
+
+void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstring& src, const std::wstring& domain)
+{
+  CString srcTrunc = ToCString(src);
+  if (src.length() > 100)
+  {
+    srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
+  }
+
+  CString blocking;
+  blocking.Format(L"Blocked  %-12s  %-20s  %s", ToCString(type), domain.empty()? L"-" : ToCString(domain), srcTrunc);
+
+  DebugResultLegacy(blocking);
+}
+
+
+void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring& id, const std::wstring& filter)
+{
+  CString srcTrunc = ToCString(id);
+  if (srcTrunc.GetLength() > 100)
+  {
+    srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
+  }
+
+  CString blocking;
+  blocking.Format(L"Hidden   %-12s  - %s  %s", ToCString(tag), srcTrunc, ToCString(filter));
+
+  DebugResultLegacy(blocking);
+}
+
+#endif // ENABLE_DEBUG_RESULT
+
+
+#ifdef ENABLE_DEBUG_RESULT_IGNORED
+
+void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstring& src, const std::wstring& domain)
+{
+  CString srcTrunc = ToCString(src);
+  if (src.length() > 100)
+  {
+    srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
+  }
+
+  CString blocking;
+  blocking.Format(L"Ignored  %-12s  %s  %s", ToCString(type), domain.empty()? L"-" : ToCString(domain), srcTrunc);
+
+  DebugResultLegacy(blocking);
+}
+
+#endif // ENABLE_DEBUG_RESULT_IGNORED
Index: src/plugin/PluginDebug.h
diff --git a/src/plugin/PluginDebug.h b/src/plugin/PluginDebug.h
index 4aea67b6239f78e1224f608d06f318d53b9ab4bd..0fdb9d7e8619e3dc1ad1371bd8dfb8d01afef5e1 100644
--- a/src/plugin/PluginDebug.h
+++ b/src/plugin/PluginDebug.h
@@ -1,47 +1,107 @@
-/*
- * This file is part of Adblock Plus <https://adblockplus.org/>,
- * Copyright (C) 2006-2015 Eyeo GmbH
- *
- * Adblock Plus is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * Adblock Plus is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _PLUGIN_DEBUG_H_
-#define _PLUGIN_DEBUG_H_
-
-class CPluginDebug
-{
-
-public:
-  static void DebugSystemException(const std::system_error& ex, int errorId, int errorSubid, const std::string& description); 
-
-#if (defined ENABLE_DEBUG_INFO)
-  static void Debug(const std::string& text, DWORD processId=0, DWORD threadId=0);
-  static void Debug(const std::wstring& text, DWORD processId=0, DWORD threadId=0);
-  static void DebugException(const std::exception& ex);
-  static void DebugErrorCode(DWORD errorCode, const std::string& error, DWORD processId=0, DWORD threadId=0);
-#endif
-
-#if (defined ENABLE_DEBUG_RESULT)
-  static void DebugResult(const std::wstring& text);
-  static void DebugResultDomain(const std::wstring& domain);
-  static void DebugResultBlocking(const std::wstring& type, const std::wstring& src, const std::wstring& domain);
-  static void DebugResultHiding(const std::wstring& tag, const std::wstring& id, const std::wstring& filter);
-#endif
-
-#if (defined ENABLE_DEBUG_RESULT_IGNORED)
-  static void DebugResultIgnoring(const std::wstring& type, const std::wstring& src, const std::wstring& domain);
-#endif
-};
-
-
-#endif // _PLUGIN_DEBUG_H_
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _PLUGIN_DEBUG_H_
+#define _PLUGIN_DEBUG_H_
+
+// Plugin errors
+
+#define PLUGIN_ERROR_SESSION 3
+#define PLUGIN_ERROR_SESSION_GET_INTERNET_SESSION 1
+#define PLUGIN_ERROR_SESSION_CREATE_HTTP_INSTANCE 2
+#define PLUGIN_ERROR_SESSION_REGISTER_HTTP_NAMESPACE 3
+#define PLUGIN_ERROR_SESSION_CREATE_HTTPS_INSTANCE 4
+#define PLUGIN_ERROR_SESSION_REGISTER_HTTPS_NAMESPACE 5
+
+#define PLUGIN_ERROR_THREAD 5
+#define PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS 1
+#define PLUGIN_ERROR_TAB_THREAD_CREATE_PROCESS 2
+
+#define PLUGIN_ERROR_SYSINFO 7
+#define PLUGIN_ERROR_SYSINFO_BROWSER_LANGUAGE 3
+
+#define PLUGIN_ERROR_NAVIGATION 10
+#define PLUGIN_ERROR_NAVIGATION_WELCOME 1
+#define PLUGIN_ERROR_NAVIGATION_SETTINGS 7
+
+#define PLUGIN_ERROR_MUTEX 13
+#define PLUGIN_ERROR_MUTEX_CREATE 1
+#define PLUGIN_ERROR_MUTEX_RELEASE 2
+#define PLUGIN_ERROR_MUTEX_WAIT 3
+#define PLUGIN_ERROR_MUTEX_WAIT_TIMEOUT 4
+#define PLUGIN_ERROR_MUTEX_DEBUG_FILE 50
+#define PLUGIN_ERROR_MUTEX_SETTINGS_FILE_WHITELIST 90
+
+#define PLUGIN_ERROR_SET_SITE 16
+#define PLUGIN_ERROR_SET_SITE_ADVICE 1
+#define PLUGIN_ERROR_SET_SITE_UNADVISE 2
+#define PLUGIN_ERROR_SET_SITE_QUERY_BROWSER 3
+#define PLUGIN_ERROR_SET_SITE_QUERY_SERVICE_PROVIDER 4
+#define PLUGIN_ERROR_SET_SITE_COINIT 5
+#define PLUGIN_ERROR_SET_SITE_FIND_CONNECTION_POINT 6
+
+#define PLUGIN_ERROR_UI 17
+#define PLUGIN_ERROR_UI_GET_UXTHEME 1
+#define PLUGIN_ERROR_UI_GET_UXTHEME_OPEN 2
+#define PLUGIN_ERROR_UI_GET_UXTHEME_DRAW_BACKGROUND 3
+#define PLUGIN_ERROR_UI_GET_UXTHEME_CLOSE 4
+#define PLUGIN_ERROR_UI_GET_BROWSER_WINDOW 5
+#define PLUGIN_ERROR_UI_CREATE_STATUSBAR_PANE 6
+#define PLUGIN_ERROR_UI_REGISTER_PANE_CLASS 7
+#define PLUGIN_ERROR_UI_NO_STATUSBAR_BROWSER 8
+#define PLUGIN_ERROR_UI_LOAD_ICON 9
+#define PLUGIN_ERROR_UI_NO_STATUSBAR_WIN 10
+#define PLUGIN_ERROR_UI_INVALIDATE_STATUSBAR 11
+#define PLUGIN_ERROR_UI_GET_STATUSBAR 12
+#define PLUGIN_ERROR_UI_PUT_STATUSBAR 13
+
+#define PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT 25
+#define PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE 1
+
+#define PLUGIN_ERROR_ENTRY_POINT 99
+#define PLUGIN_ERROR_ENTRY_POINT_CATCHALL_EXCEPTION 1
+
+class CPluginDebug
+{
+
+public:
+  static void DebugSystemException(const std::system_error& ex, int errorId, int errorSubid, const std::string& description); 
+
+#if (defined ENABLE_DEBUG_INFO)
+  static void Debug(const std::string& text, DWORD processId=0, DWORD threadId=0);
+  static void Debug(const std::wstring& text, DWORD processId=0, DWORD threadId=0);
+  static void DebugException(const std::exception& ex);
+  static void DebugErrorCode(DWORD errorCode, const std::string& error, DWORD processId=0, DWORD threadId=0);
+  static void DebugOrdinaryException(const std::exception& ex, int errorId, int errorSubid, const std::string& description); 
+#endif
+
+#if (defined ENABLE_DEBUG_RESULT)
+  static void DebugResult(const std::wstring& text);
+  static void DebugResultDomain(const std::wstring& domain);
+  static void DebugResultBlocking(const std::wstring& type, const std::wstring& src, const std::wstring& domain);
+  static void DebugResultHiding(const std::wstring& tag, const std::wstring& id, const std::wstring& filter);
+#endif
+
+#if (defined ENABLE_DEBUG_RESULT_IGNORED)
+  static void DebugResultIgnoring(const std::wstring& type, const std::wstring& src, const std::wstring& domain);
+#endif
+};
+
+void ExceptionDefault(const std::string& name);	
+void EntryPointExceptionDefault(const std::string& name);
+
+#endif // _PLUGIN_DEBUG_H_
Index: src/plugin/PluginErrorCodes.h
diff --git a/src/plugin/PluginErrorCodes.h b/src/plugin/PluginErrorCodes.h
deleted file mode 100644
index 36b345b928e0f4ec0112a2f84f41c66121a2bea5..0000000000000000000000000000000000000000
--- a/src/plugin/PluginErrorCodes.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * This file is part of Adblock Plus <https://adblockplus.org/>,
- * Copyright (C) 2006-2015 Eyeo GmbH
- *
- * Adblock Plus is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * Adblock Plus is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _PLUGIN_ERROR_CODES_H_
-#define _PLUGIN_ERROR_CODES_H_
-
-
-// Plugin errors
-#define PLUGIN_ERROR_OS_VERSION 1
-#define PLUGIN_ERROR_OS_VERSION_REG_OPEN_KEY 1
-#define PLUGIN_ERROR_OS_VERSION_REG_QUERY_VALUE 2
-
-#define PLUGIN_ERROR_MAC_ID 2
-#define PLUGIN_ERROR_MAC_ID_RETRIEVAL 1
-#define PLUGIN_ERROR_MAC_ID_RETRIEVAL_EX 2
-
-#define PLUGIN_ERROR_SESSION 3
-#define PLUGIN_ERROR_SESSION_GET_INTERNET_SESSION 1
-#define PLUGIN_ERROR_SESSION_CREATE_HTTP_INSTANCE 2
-#define PLUGIN_ERROR_SESSION_REGISTER_HTTP_NAMESPACE 3
-#define PLUGIN_ERROR_SESSION_CREATE_HTTPS_INSTANCE 4
-#define PLUGIN_ERROR_SESSION_REGISTER_HTTPS_NAMESPACE 5
-
-#define PLUGIN_ERROR_UPDATER 4
-#define PLUGIN_ERROR_UPDATER_CREATE_PROCESS 1
-#define PLUGIN_ERROR_UPDATER_DOWNLOAD_FILE 2
-
-#define PLUGIN_ERROR_THREAD 5
-#define PLUGIN_ERROR_MAIN_THREAD_CREATE_PROCESS 1
-#define PLUGIN_ERROR_TAB_THREAD_CREATE_PROCESS 2
-
-#define PLUGIN_ERROR_GUID 6
-#define PLUGIN_ERROR_GUID_REG_OPEN_KEY 1
-#define PLUGIN_ERROR_GUID_REG_GET_SET 2
-
-#define PLUGIN_ERROR_SYSINFO 7
-#define PLUGIN_ERROR_SYSINFO_USER_NAME 1
-#define PLUGIN_ERROR_SYSINFO_COMPUTER_NAME 2
-#define PLUGIN_ERROR_SYSINFO_BROWSER_LANGUAGE 3
-#define PLUGIN_ERROR_SYSINFO_TEMP_PATH 4
-#define PLUGIN_ERROR_SYSINFO_TEMP_FILE 5
-#define PLUGIN_ERROR_SYSINFO_GET_SPECIAL_FOLDER_LOCAL 6
-#define PLUGIN_ERROR_SYSINFO_GET_SPECIAL_FOLDER 7
-#define PLUGIN_ERROR_SYSINFO_GET_SPECIAL_FOLDER_PROGRAM_FILES 8
-#define PLUGIN_ERROR_SYSINFO_GET_SPECIAL_FOLDER_COMMON_FILES 9
-#define PLUGIN_ERROR_SYSINFO_GET_SPECIAL_FOLDER_TEMP 10
-
-#define PLUGIN_ERROR_SETTINGS 8
-// 1 + 2 reserved
-#define PLUGIN_ERROR_SETTINGS_CREATE_FOLDER 3
-#define PLUGIN_ERROR_SETTINGS_FILE_READ 4
-#define PLUGIN_ERROR_SETTINGS_FILE_WRITE 5
-#define PLUGIN_ERROR_SETTINGS_FILE_READ_CHECKSUM 6
-#define PLUGIN_ERROR_SETTINGS_CREATE_MUTEX 7
-#define PLUGIN_ERROR_SETTINGS_RELEASE_MUTEX 8
-#define PLUGIN_ERROR_SETTINGS_CREATE_MAPFILE 9
-#define PLUGIN_ERROR_SETTINGS_RELEASE_MAPFILE 10
-#define PLUGIN_ERROR_SETTINGS_CREATE_MAPFILE_VIEW 11
-#define PLUGIN_ERROR_SETTINGS_RELEASE_MAPFILE_VIEW 12
-
-#define PLUGIN_ERROR_FILTER 9
-#define PLUGIN_ERROR_FILTER_CREATE_FILE_OPEN 1
-#define PLUGIN_ERROR_FILTER_DOWNLOAD_FILE 2
-#define PLUGIN_ERROR_FILTER_READ_FILE 3
-#define PLUGIN_ERROR_FILTER_MOVE_FILE 4
-#define PLUGIN_ERROR_FILTER_CREATE_FILE_WRITE 5
-#define PLUGIN_ERROR_FILTER_CREATE_FILE_CLOSE 6
-#define PLUGIN_ERROR_FILTER_COPY_FILE 7
-
-#define PLUGIN_ERROR_NAVIGATION 10
-#define PLUGIN_ERROR_NAVIGATION_WELCOME 1
-#define PLUGIN_ERROR_NAVIGATION_INFO 2
-#define PLUGIN_ERROR_NAVIGATION_ACTIVATE 3
-#define PLUGIN_ERROR_NAVIGATION_FAQ 4
-#define PLUGIN_ERROR_NAVIGATION_ABOUT 5
-#define PLUGIN_ERROR_NAVIGATION_FEEDBACK 6
-#define PLUGIN_ERROR_NAVIGATION_SETTINGS 7
-#define PLUGIN_ERROR_NAVIGATION_INVITATION 8
-#define PLUGIN_ERROR_NAVIGATION_ENTERLICENSE 9
-#define PLUGIN_ERROR_NAVIGATION_UPGRADE 10
-#define PLUGIN_ERROR_NAVIGATION_ENABLE_CONVERSSION 801
-
-
-#define PLUGIN_ERROR_DICTIONARY 11
-#define PLUGIN_ERROR_DICTIONARY_DOWNLOAD_FILE 1
-#define PLUGIN_ERROR_DICTIONARY_MOVE_FILE 2
-#define PLUGIN_ERROR_DICTIONARY_CREATE_FILE 3
-#define PLUGIN_ERROR_DICTIONARY_READ_FILE 4
-#define PLUGIN_ERROR_DICTIONARY_LOOKUP 5
-#define PLUGIN_ERROR_DICTIONARY_COPY_FILE 6
-
-#define PLUGIN_ERROR_FTP_SEND 12
-#define PLUGIN_ERROR_FTP_SEND_GET_PROXY 1
-#define PLUGIN_ERROR_FTP_SEND_OPEN 2
-#define PLUGIN_ERROR_FTP_SEND_CONNECT 3
-#define PLUGIN_ERROR_FTP_SEND_PUT 4
-#define PLUGIN_ERROR_FTP_SEND_CLOSE 5
-
-#define PLUGIN_ERROR_MUTEX 13
-#define PLUGIN_ERROR_MUTEX_CREATE 1
-#define PLUGIN_ERROR_MUTEX_RELEASE 2
-#define PLUGIN_ERROR_MUTEX_WAIT 3
-#define PLUGIN_ERROR_MUTEX_WAIT_TIMEOUT 4
-
-#define PLUGIN_ERROR_MUTEX_SELFTEST_FILE 10
-
-#define PLUGIN_ERROR_MUTEX_DICTIONARY_FILE 20
-
-#define PLUGIN_ERROR_MUTEX_FILTER_FILE 30
-
-#define PLUGIN_ERROR_MUTEX_SETTINGS_FILE 40
-
-#define PLUGIN_ERROR_MUTEX_DEBUG_FILE 50
-
-#define PLUGIN_ERROR_MUTEX_SETTINGS 60
-
-#define PLUGIN_ERROR_MUTEX_MAIN_TAB 70
-
-#define PLUGIN_ERROR_MUTEX_SETTINGS_FILE_TAB 80
-
-#define PLUGIN_ERROR_MUTEX_SETTINGS_FILE_WHITELIST 90
-
-#define PLUGIN_ERROR_MUTEX_CONFIG_FILE 95
-
-#define PLUGIN_ERROR_HTTP_REQUEST 14
-#define PLUGIN_ERROR_HTTP_REQUEST_SEND 1
-#define PLUGIN_ERROR_HTTP_REQUEST_OPEN 2
-#define PLUGIN_ERROR_HTTP_REQUEST_CONNECT 3
-#define PLUGIN_ERROR_HTTP_REQUEST_OPEN_REQUEST 4
-#define PLUGIN_ERROR_HTTP_REQUEST_SEND_REQUEST 5
-#define PLUGIN_ERROR_HTTP_REQUEST_RECEIVE_RESPONSE 6
-#define PLUGIN_ERROR_HTTP_REQUEST_QUERY_HEADERS 7
-#define PLUGIN_ERROR_HTTP_REQUEST_INVALID_RESPONSE_SERVER 8
-#define PLUGIN_ERROR_HTTP_REQUEST_QUERY_DATA_AVAILABLE 9
-#define PLUGIN_ERROR_HTTP_REQUEST_READ_DATA 10
-#define PLUGIN_ERROR_HTTP_REQUEST_URL_ESCAPE 11
-#define PLUGIN_ERROR_HTTP_REQUEST_SET_OPTION 12
-#define PLUGIN_ERROR_HTTP_REQUEST_GET_URL_PROXY 13
-
-#define PLUGIN_ERROR_HTTP 15
-#define PLUGIN_ERROR_HTTP_PROXY_SETTINGS 1
-#define PLUGIN_ERROR_HTTP_CLOSE_HANDLE 2
-
-#define PLUGIN_ERROR_SET_SITE 16
-#define PLUGIN_ERROR_SET_SITE_ADVICE 1
-#define PLUGIN_ERROR_SET_SITE_UNADVISE 2
-#define PLUGIN_ERROR_SET_SITE_QUERY_BROWSER 3
-#define PLUGIN_ERROR_SET_SITE_QUERY_SERVICE_PROVIDER 4
-#define PLUGIN_ERROR_SET_SITE_COINIT 5
-#define PLUGIN_ERROR_SET_SITE_FIND_CONNECTION_POINT 6
-
-#define PLUGIN_ERROR_UI 17
-#define PLUGIN_ERROR_UI_GET_UXTHEME 1
-#define PLUGIN_ERROR_UI_GET_UXTHEME_OPEN 2
-#define PLUGIN_ERROR_UI_GET_UXTHEME_DRAW_BACKGROUND 3
-#define PLUGIN_ERROR_UI_GET_UXTHEME_CLOSE 4
-#define PLUGIN_ERROR_UI_GET_BROWSER_WINDOW 5
-#define PLUGIN_ERROR_UI_CREATE_STATUSBAR_PANE 6
-#define PLUGIN_ERROR_UI_REGISTER_PANE_CLASS 7
-#define PLUGIN_ERROR_UI_NO_STATUSBAR_BROWSER 8
-#define PLUGIN_ERROR_UI_LOAD_ICON 9
-#define PLUGIN_ERROR_UI_NO_STATUSBAR_WIN 10
-#define PLUGIN_ERROR_UI_INVALIDATE_STATUSBAR 11
-#define PLUGIN_ERROR_UI_GET_STATUSBAR 12
-#define PLUGIN_ERROR_UI_PUT_STATUSBAR 13
-
-#define PLUGIN_ERROR_SELFTEST 18
-#define PLUGIN_ERROR_SELFTEST_MOVE_FILE 1
-#define PLUGIN_ERROR_SELFTEST_COPY_FILE 2
-
-#define PLUGIN_ERROR_SETTINGS_TAB 19
-// Same error codes as PLUGIN_ERROR_SETTINGS
-
-#define PLUGIN_ERROR_SETTINGS_WHITELIST 20
-// Same error codes as PLUGIN_ERROR_SETTINGS
-
-#define PLUGIN_ERROR_INSTALL 21
-#define PLUGIN_ERROR_INSTALL_GET_WINDOWS_PATH 1
-#define PLUGIN_ERROR_INSTALL_APPEND_PATH 2
-#define PLUGIN_ERROR_INSTALL_CREATE_INI_FILE 3
-
-#define PLUGIN_ERROR_CONFIG 22
-#define PLUGIN_ERROR_CONFIG_DOWNLOAD_FILE 1
-#define PLUGIN_ERROR_CONFIG_MOVE_FILE 2
-#define PLUGIN_ERROR_CONFIG_CREATE_FILE 3
-#define PLUGIN_ERROR_CONFIG_READ_FILE 4
-#define PLUGIN_ERROR_CONFIG_COPY_FILE 6
-
-#define PLUGIN_ERROR_DOWNLOAD 23
-#define PLUGIN_ERROR_DOWNLOAD_OPEN_SAVE_DIALOG 1
-#define PLUGIN_ERROR_DOWNLOAD_CREATE_PROCESS 2
-#define PLUGIN_ERROR_DOWNLOAD_FILE_DOWNLOAD 3
-#define PLUGIN_ERROR_DOWNLOAD_CREATE_CONVERSION_PROCESS 4
-
-#define PLUGIN_ERROR_USER_SETTINGS 24
-#define PLUGIN_ERROR_USER_SETTINGS_PARSE_KEY_VALUE 1
-
-#define PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT 25
-#define PLUGIN_ERROR_CREATE_SETTINGS_JAVASCRIPT_INVOKE 1
-
-#endif // _PLUGIN_ERROR_CODES_H_
Index: src/plugin/PluginStdAfx.h
diff --git a/src/plugin/PluginStdAfx.h b/src/plugin/PluginStdAfx.h
index b4a81cc01aacd55892667f2a4a48176032b2fdfd..ce598e193b3c6cbf69db4cb99b0999bfdca52ec4 100644
--- a/src/plugin/PluginStdAfx.h
+++ b/src/plugin/PluginStdAfx.h
@@ -1,97 +1,96 @@
-/*
- * This file is part of Adblock Plus <https://adblockplus.org/>,
- * Copyright (C) 2006-2015 Eyeo GmbH
- *
- * Adblock Plus is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * Adblock Plus is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _STDAFX_H
-#define _STDAFX_H
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-// Embed manifest as a resource, to enable common controls
-// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb773175(v=vs.85).aspx#using_manifests
-#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
-
-
-//#define STRICT
-#define WINVER 0x0501
-
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-
-#define _ATL_APARTMENT_THREADED
-
-//#define _CRT_SECURE_NO_DEPRECATE 1
-#include "ATL_Deprecate.h"
-
-extern CComModule _Module;
-#include <stdio.h>
-#include <assert.h>
-#include <stdexcept>
-#include <ExDisp.h>
-#include <ExDispID.h>
-#include <Mshtml.h>
-
-#include <map>
-#include <set>
-#include <vector>
-#include <fstream>
-#include <sstream>
-#include <commctrl.h>
-#include <mshtmdid.h>
-#include <Mlang.h>
-#include <initguid.h>
-
-// Win32
-#include <shlguid.h>
-#include <shlobj.h>
-#include <iepmapi.h>
-#include <Windows.h>
-#include <Sddl.h>
-
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#include "PluginErrorCodes.h"
-#include "Config.h"
-#include "Resource.h"
-#include "PluginDebug.h"
-
-#define _CRTDBG_MAP_ALLOC
-#include <stdlib.h>
-#include <crtdbg.h>
-
-
-#ifdef _MSC_VER
-#pragma warning(push)
-// warning C4996: function call with parameters that might be unsafe
-#pragma warning(disable : 4996)
-#endif
-
-#endif // not _STDAFX_H
-
-#ifndef countof
-#define countof(x) (sizeof(x)/sizeof(*x))
-#endif
-
-#ifdef USE_CONSOLE
-#include "Console.h"
-#endif
-
-#include "BuildVariant.h"
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _STDAFX_H
+#define _STDAFX_H
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+// Embed manifest as a resource, to enable common controls
+// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb773175(v=vs.85).aspx#using_manifests
+#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+
+
+//#define STRICT
+#define WINVER 0x0501
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
+#define _ATL_APARTMENT_THREADED
+
+//#define _CRT_SECURE_NO_DEPRECATE 1
+#include "ATL_Deprecate.h"
+
+extern CComModule _Module;
+#include <stdio.h>
+#include <assert.h>
+#include <stdexcept>
+#include <ExDisp.h>
+#include <ExDispID.h>
+#include <Mshtml.h>
+
+#include <map>
+#include <set>
+#include <vector>
+#include <fstream>
+#include <sstream>
+#include <commctrl.h>
+#include <mshtmdid.h>
+#include <Mlang.h>
+#include <initguid.h>
+
+// Win32
+#include <shlguid.h>
+#include <shlobj.h>
+#include <iepmapi.h>
+#include <Windows.h>
+#include <Sddl.h>
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#include "Config.h"
+#include "Resource.h"
+#include "PluginDebug.h"
+
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// warning C4996: function call with parameters that might be unsafe
+#pragma warning(disable : 4996)
+#endif
+
+#endif // not _STDAFX_H
+
+#ifndef countof
+#define countof(x) (sizeof(x)/sizeof(*x))
+#endif
+
+#ifdef USE_CONSOLE
+#include "Console.h"
+#endif
+
+#include "BuildVariant.h"
Index: test/plugin/ExceptionTest.cpp
diff --git a/test/plugin/ExceptionTest.cpp b/test/plugin/ExceptionTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e67e4103ac18f280edb548d1a18f742336031f0a
--- /dev/null
+++ b/test/plugin/ExceptionTest.cpp
@@ -0,0 +1,387 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtest/gtest.h>
+#include "../../src/plugin/Exception.h"
+#include <stdexcept>
+
+void AssignCurrentException(std::exception_ptr& e)
+{
+  e = std::current_exception();
+}
+
+/*
+ * This test verifies that std::current_exception works during exception handling generally,
+ *   not just in the immediate context of a 'catch' clause.
+ */
+TEST(Exception, CurrentExceptionWorksOutsideCatchHandler)
+{
+  std::exception_ptr ep;
+  const auto e = std::runtime_error("BJTCiRhkVAmvMg");
+  try
+  {
+    throw e;
+  }
+  catch (...)
+  {
+    AssignCurrentException(ep);
+    ASSERT_TRUE(ep);
+    /*
+     * You might think that the next set would be EXPECT_EQ betwwen the thrown exception and the original one.
+     * Such a test does not pass, nor is in necessary.
+     * The throw statement above is throwing by value, so it makes a copy.
+     */
+  }
+  try
+  {
+    rethrow_exception(ep);
+    FAIL() << "Statement after 'rethrow_exception' executed.";
+  }
+  catch (const std::runtime_error& ex)
+  {
+    EXPECT_STREQ(e.what(), ex.what());
+    return;
+  }
+  catch (...)
+  {
+    FAIL() << "Rethrown exception isn't the same type as the original";
+  }
+  FAIL() << "Did not return after catching rethrown exception";
+}
+
+/*
+ * A plain exception, not a subclass of std::runtime_error or std::logic_error.
+ */
+class PlainException
+  : public std::exception
+{
+  const char* what() const override
+  {
+    return "Plain";
+  };
+};
+
+struct NullHandlers
+{
+  static void Unknown(int) {}
+  static void Exception(const std::exception&,int) {}
+};
+
+/*
+ * The trivial tests assure that nothing escapes the catch-all function,
+ *   that is, we ensure that nothing is thrown or rethrown.
+ */
+template<class X>
+void TrivialVoid(X x)
+{
+  ASSERT_NO_THROW(
+  {
+    try
+    {
+      throw x;
+    }
+    catch (...)
+    {
+      CatchAllVoid<NullHandlers>::Handler(0);
+    }
+  });
+}
+
+TEST(Exception, TrivialVoidUnknown)
+{
+  TrivialVoid(5);
+}
+
+TEST(Exception, TrivialVoidException)
+{
+  TrivialVoid(PlainException());
+}
+
+TEST(Exception, TrivialVoidLogicError)
+{
+  TrivialVoid(std::logic_error(""));
+}
+
+TEST(Exception, TrivialVoidRuntimeError)
+{
+  TrivialVoid(std::runtime_error(""));
+}
+
+TEST(Exception, TrivialVoidSystemError)
+{
+  TrivialVoid(std::system_error(std::error_code()));
+}
+
+enum class ReturnType
+{
+  InvalidCode = -1,
+  UnknownCode = 1,
+  ExceptionCode,
+  LogicErrorCode,
+  RuntimeErrorCode,
+  SystemErrorCode
+};
+
+struct NullHandlersReturn
+{
+  typedef ReturnType ReturnType;
+  static ReturnType Unknown(int) { return ReturnType::UnknownCode; }
+  static ReturnType Exception(const std::exception&, int) { return ReturnType::ExceptionCode; }
+  static ReturnType Exception(const std::logic_error&, int) { return ReturnType::LogicErrorCode; }
+  static ReturnType Exception(const std::runtime_error&, int) { return ReturnType::RuntimeErrorCode; }
+  static ReturnType Exception(const std::system_error&, int) { return ReturnType::SystemErrorCode; }
+};
+
+template<class X>
+void TrivialReturn(ReturnType n, X x)
+{
+  ASSERT_NO_THROW(
+  {
+    try
+    {
+      throw x;
+    }
+    catch (...)
+    {
+      ASSERT_EQ(n, CatchAllReturn<NullHandlersReturn>::Handler(0));
+    }
+  });
+}
+
+TEST(Exception, TrivialReturnUnknown)
+{
+  TrivialReturn(ReturnType::UnknownCode, 5);
+}
+
+TEST(Exception, TrivialReturnException)
+{
+  TrivialReturn(ReturnType::ExceptionCode, PlainException());
+}
+
+TEST(Exception, TrivialReturnLogicError)
+{
+  TrivialReturn(ReturnType::LogicErrorCode, std::logic_error(""));
+}
+
+TEST(Exception, TrivialReturnRuntimeError)
+{
+  TrivialReturn(ReturnType::RuntimeErrorCode, std::runtime_error(""));
+}
+
+TEST(Exception, TrivialReturnSystemError)
+{
+  TrivialReturn(ReturnType::SystemErrorCode, std::system_error(std::error_code()));
+}
+
+class Touchable
+{
+public:
+  Touchable() : m_isTouched(false){}
+  bool IsTouched() const
+  {
+    return m_isTouched;
+  }
+  void Touch()
+  {
+    m_isTouched = true;
+  }
+private:
+  // In the tests we use `Touchable&` as the type for UserData, so let's make
+  // it uncopyable to be sure that it's not copied somewhere by accident.
+  Touchable(const Touchable&);
+  void operator=(const Touchable&);
+private:
+  bool m_isTouched;
+};
+
+/*
+ * The simple tests ensure that the flow of control arrives in the correct subhandler.
+ */
+template<typename H, class X>
+void SimpleVoid(X x)
+{
+  Touchable userData;
+  ASSERT_NO_THROW(
+  {
+    try
+    {
+      throw x;
+    }
+    catch (...)
+    {
+      CatchAllVoid<H>::Handler<Touchable&>(userData);
+    }
+  });
+  EXPECT_TRUE(userData.IsTouched());
+}
+
+/*
+ * The base handler class for the simple tests fails every execution path.
+ * Each specific test redefines a single one of the handler functions that it uses.
+ */
+class SimpleHandlersBase
+{
+public:
+  typedef Touchable& UserData;
+  SimpleHandlersBase(){}
+  static void Unknown(UserData) { FAIL() << "Unexpected exception of unknown type"; }
+  static void Exception(const std::exception&, UserData) { FAIL() << "Unexpected std::exception"; }
+  static void Exception(const std::logic_error&, UserData) { FAIL() << "Unexpected std::logic_error"; }
+  static void Exception(const std::runtime_error&, UserData) { FAIL() << "Unexpected std::runtime_error"; }
+  static void Exception(const std::system_error&, UserData) { FAIL() << "Unexpected std::system_error"; };
+};
+
+TEST(Exception, SimpleVoidUnknown)
+{
+  struct Handler :
+    public SimpleHandlersBase
+  {
+    static void Unknown(UserData h) { h.Touch(); }
+  };
+  SimpleVoid<Handler>(5);
+}
+
+TEST(Exception, SimpleVoidException)
+{
+  struct Handler :
+    public SimpleHandlersBase
+  {
+    static void Exception(const std::exception&, UserData h) { h.Touch(); }
+  };
+  SimpleVoid<Handler>(PlainException());
+}
+
+TEST(Exception, SimpleVoidLogicError)
+{
+  struct Handler :
+    public SimpleHandlersBase
+  {
+    static void Exception(const std::logic_error&, UserData h) { h.Touch(); }
+    using SimpleHandlersBase::Exception;
+  };
+  SimpleVoid<Handler>(std::logic_error(""));
+}
+
+TEST(Exception, SimpleVoidRuntimeError)
+{
+  struct Handler :
+    public SimpleHandlersBase
+  {
+    static void Exception(const std::runtime_error&, UserData h) { h.Touch(); }
+    using SimpleHandlersBase::Exception;
+  };
+  SimpleVoid<Handler>(std::runtime_error(""));
+}
+
+TEST(Exception, SimpleVoidSystemError)
+{
+  struct Handler :
+    public SimpleHandlersBase
+  {
+    static void Exception(const std::system_error&, UserData h) { h.Touch(); }
+    using SimpleHandlersBase::Exception;
+  };
+  SimpleVoid<Handler>(std::system_error(std::error_code()));
+}
+
+template<class H, class X>
+void SimpleReturn(ReturnType n, X x)
+{
+  Touchable userData;
+  ASSERT_NO_THROW(
+  {
+    try
+    {
+      throw x;
+    }
+    catch (...)
+    {
+      EXPECT_EQ(n, CatchAllReturn<H>::Handler<Touchable&>(userData));
+    }
+  });
+  EXPECT_TRUE(userData.IsTouched());
+}
+
+/*
+ * The base handlers class fails every execution path.
+ */
+class SimpleHandlersReturnBase
+{
+public:
+  typedef ReturnType ReturnType;
+  typedef Touchable& UserData;
+  static ReturnType Unknown(UserData) { ADD_FAILURE() << "Unexpected exception of unknown type"; return ReturnType::InvalidCode; }
+  static ReturnType Exception(const std::exception&, UserData) { ADD_FAILURE() << "Unexpected std::exception"; return ReturnType::InvalidCode; }
+  static ReturnType Exception(const std::logic_error&, UserData) { ADD_FAILURE() << "Unexpected std::logic_error"; return ReturnType::InvalidCode; }
+  static ReturnType Exception(const std::runtime_error&, UserData) { ADD_FAILURE() << "Unexpected std::runtime_error"; return ReturnType::InvalidCode; }
+  static ReturnType Exception(const std::system_error&, UserData) { ADD_FAILURE() << "Unexpected std::system_error"; return ReturnType::InvalidCode; }
+};
+
+TEST(Exception, SimpleReturnUnknown)
+{
+  struct Handler :
+    public SimpleHandlersReturnBase
+  {
+    static ReturnType Unknown(UserData h) { h.Touch(); return ReturnType::UnknownCode; }
+    using SimpleHandlersReturnBase::Exception;
+  };
+  SimpleReturn<Handler>(ReturnType::UnknownCode, 5);
+}
+
+TEST(Exception, SimpleReturnException)
+{
+  struct Handler :
+    public SimpleHandlersReturnBase
+  {
+    static ReturnType Exception(const std::exception&, UserData h) { h.Touch(); return ReturnType::ExceptionCode; }
+    using SimpleHandlersReturnBase::Exception;
+  };
+  SimpleReturn<Handler>(ReturnType::ExceptionCode, PlainException());
+}
+
+TEST(Exception, SimpleReturnLogicError)
+{
+  struct Handler :
+    public SimpleHandlersReturnBase
+  {
+    static ReturnType Exception(const std::logic_error&, UserData h) { h.Touch(); return ReturnType::LogicErrorCode; }
+    using SimpleHandlersReturnBase::Exception;
+  };
+  SimpleReturn<Handler>(ReturnType::LogicErrorCode, std::logic_error(""));
+}
+
+TEST(Exception, SimpleReturnRuntimeError)
+{
+  struct Handler :
+    public SimpleHandlersReturnBase
+  {
+    static ReturnType Exception(const std::runtime_error&, UserData h) { h.Touch(); return ReturnType::RuntimeErrorCode; }
+    using SimpleHandlersReturnBase::Exception;
+  };
+  SimpleReturn<Handler>(ReturnType::RuntimeErrorCode, std::runtime_error(""));
+}
+
+TEST(Exception, SimpleReturnSystemError)
+{
+  struct Handler :
+    public SimpleHandlersReturnBase
+  {
+    static ReturnType Exception(const std::system_error&, UserData h) { h.Touch(); return ReturnType::SystemErrorCode; }
+    using SimpleHandlersReturnBase::Exception;
+  };
+  SimpleReturn<Handler>(ReturnType::SystemErrorCode, std::system_error(std::error_code()));
+}
\ No newline at end of file
