Index: mptrack/ModDocTemplate.cpp
===================================================================
--- mptrack/ModDocTemplate.cpp	(revision 13970)
+++ mptrack/ModDocTemplate.cpp	(working copy)
@@ -130,7 +130,7 @@
 	if(const auto fileExt = filename.GetFileExt(); !mpt::PathString::CompareNoCase(fileExt, P_(".dll")) || !mpt::PathString::CompareNoCase(fileExt, P_(".vst3")))
 	{
 		CVstPluginManager *pPluginManager = theApp.GetPluginManager();
-		if(pPluginManager && pPluginManager->AddPlugin(filename) != nullptr)
+		if(pPluginManager && pPluginManager->AddPlugin(filename, TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes) != nullptr)
 		{
 			return nullptr;
 		}
Index: mptrack/Mptrack.cpp
===================================================================
--- mptrack/Mptrack.cpp	(revision 13970)
+++ mptrack/Mptrack.cpp	(working copy)
@@ -1847,6 +1847,8 @@
 	m_pPluginManager = new CVstPluginManager;
 	const size_t numPlugins = GetSettings().Read<int32>(U_("VST Plugins"), U_("NumPlugins"), 0);
 
+	bool maskCrashes = TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes;
+
 	std::vector<VSTPluginLib *> nonFoundPlugs;
 	const mpt::PathString failedPlugin = GetSettings().Read<mpt::PathString>(U_("VST Plugins"), U_("FailedPlugin"), P_(""));
 
@@ -1911,7 +1913,7 @@
 			mpt::ustring plugTags = GetSettings().Read<mpt::ustring>(U_("VST Plugins"), tagFormat(plug), mpt::ustring());
 
 			bool plugFound = true;
-			VSTPluginLib *lib = m_pPluginManager->AddPlugin(plugPath, plugTags, true, &plugFound);
+			VSTPluginLib *lib = m_pPluginManager->AddPlugin(plugPath, maskCrashes, plugTags, true, &plugFound);
 			if(!plugFound && lib != nullptr)
 			{
 				nonFoundPlugs.push_back(lib);
Index: mptrack/SelectPluginDialog.cpp
===================================================================
--- mptrack/SelectPluginDialog.cpp	(revision 13970)
+++ mptrack/SelectPluginDialog.cpp	(working copy)
@@ -658,7 +658,7 @@
 
 	for(const auto &file : dlg.GetFilenames())
 	{
-		VSTPluginLib *lib = plugManager->AddPlugin(file, mpt::ustring(), false);
+		VSTPluginLib *lib = plugManager->AddPlugin(file, TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes, mpt::ustring(), false);
 		if(lib != nullptr)
 		{
 			update = true;
@@ -715,6 +715,7 @@
 	pluginScanDlg.ShowWindow(SW_SHOW);
 
 	FolderScanner scan(path, FolderScanner::kOnlyFiles | FolderScanner::kFindInSubDirectories);
+	bool maskCrashes = TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes;
 	mpt::PathString fileName;
 	int files = 0;
 	while(scan.Next(fileName) && pluginScanDlg.IsWindowVisible())
@@ -731,7 +732,7 @@
 				::DispatchMessage(&msg);
 			}
 
-			VSTPluginLib *lib = pManager->AddPlugin(fileName, mpt::ustring(), false);
+			VSTPluginLib *lib = pManager->AddPlugin(fileName, maskCrashes, mpt::ustring(), false);
 			if(lib)
 			{
 				update = true;
Index: mptrack/TrackerSettings.cpp
===================================================================
--- mptrack/TrackerSettings.cpp	(revision 13970)
+++ mptrack/TrackerSettings.cpp	(working copy)
@@ -314,6 +314,8 @@
 	, vstHostProductString(conf, U_("VST Plugins"), U_("HostProductString"), "OpenMPT")
 	, vstHostVendorString(conf, U_("VST Plugins"), U_("HostVendorString"), "OpenMPT project")
 	, vstHostVendorVersion(conf, U_("VST Plugins"), U_("HostVendorVersion"), Version::Current().GetRawVersion())
+	// Broken Plugins Workarounds
+	, BrokenPluginsWorkaroundVSTMaskAllCrashes(conf, U_("Broken Plugins Workarounds"), U_("VSTMaskAllCrashes"), true)  // TODO: really should be false
 	// Update
 	, UpdateEnabled(conf, U_("Update"), U_("Enabled"), true)
 	, UpdateInstallAutomatically(conf, U_("Update"), U_("InstallAutomatically"), false)
Index: mptrack/TrackerSettings.h
===================================================================
--- mptrack/TrackerSettings.h	(revision 13970)
+++ mptrack/TrackerSettings.h	(working copy)
@@ -850,6 +850,10 @@
 	CachedSetting<mpt::lstring> vstHostVendorString;
 	CachedSetting<int32> vstHostVendorVersion;
 
+	// Broken Plugins Workarounds
+
+	Setting<bool> BrokenPluginsWorkaroundVSTMaskAllCrashes;
+
 	// Update
 
 	Setting<bool> UpdateEnabled;
Index: mptrack/Vstplug.cpp
===================================================================
--- mptrack/Vstplug.cpp	(revision 13970)
+++ mptrack/Vstplug.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include "AbstractVstEditor.h"
 #include "VSTEditor.h"
 #include "DefaultVstEditor.h"
+#include "ExceptionHandler.h"
 #endif // MODPLUG_TRACKER
 #include "../soundlib/Sndfile.h"
 #include "../soundlib/MIDIEvents.h"
@@ -29,6 +30,7 @@
 #include "../pluginBridge/BridgeOpCodes.h"
 #include "../soundlib/plugins/OpCodes.h"
 #include "../soundlib/plugins/PluginManager.h"
+#include "../common/mptOSException.h"
 
 using namespace Vst;
 DECLARE_FLAGSET(Vst::VstTimeInfoFlags)
@@ -41,55 +43,58 @@
 #define VST_LOG
 #endif
 
-// Try loading the VST library.
-static bool LoadLibrarySEH(const mpt::RawPathString &pluginPath, HMODULE &library)
+
+using VstCrash = Windows::SEH::Code;
+
+
+bool CVstPlugin::MaskCrashes() noexcept
 {
-	__try
-	{
-		library = LoadLibrary(pluginPath.c_str());
-		return true;
-	} __except(EXCEPTION_EXECUTE_HANDLER)
-	{
-		return false;
-	}
+	return m_maskCrashes;
 }
 
 
-static AEffect *CallMainProc(Vst::MainProc pMainProc)
+template <typename Tfn>
+DWORD CVstPlugin::SETryOrError(bool maskCrashes, Tfn fn)
 {
-	__try
+	DWORD exception = 0;
+	if(maskCrashes)
 	{
-		return pMainProc(CVstPlugin::MasterCallBack);
-	} __except(EXCEPTION_EXECUTE_HANDLER)
+		exception = Windows::SEH::TryOrError(fn);
+		if(exception)
+		{
+			ExceptionHandler::TaintProcess(ExceptionHandler::TaintReason::Plugin);
+		}
+	} else
 	{
-		return nullptr;
+		fn();
 	}
+	return exception;
 }
 
 
-// Try loading the VST plugin and retrieve the AEffect structure.
-static AEffect *GetAEffectSEH(HMODULE library)
+template <typename Tfn>
+DWORD CVstPlugin::SETryOrError(Tfn fn)
 {
-	auto pMainProc = (Vst::MainProc)GetProcAddress(library, "VSTPluginMain");
-	if(pMainProc == nullptr)
+	DWORD exception = 0;
+	if(MaskCrashes())
 	{
-		pMainProc = (Vst::MainProc)GetProcAddress(library, "main");
-	}
-
-	if(pMainProc != nullptr)
-	{
-		return CallMainProc(pMainProc);
+		exception = Windows::SEH::TryOrError(fn);
+		if(exception)
+		{
+			ExceptionHandler::TaintProcess(ExceptionHandler::TaintReason::Plugin);
+		}
 	} else
 	{
-#ifdef VST_LOG
-		MPT_LOG(LogDebug, "VST", MPT_UFORMAT("Entry point not found! (handle={})")(mpt::ufmt::PTR(library)));
-#endif // VST_LOG
-		return nullptr;
+#ifdef MODPLUG_TRACKER
+		ExceptionHandler::ContextSetter ectxguard{&m_Ectx};
+#endif // MODPLUG_TRACKER
+		fn();
 	}
+	return exception;
 }
 
 
-AEffect *CVstPlugin::LoadPlugin(VSTPluginLib &plugin, HMODULE &library, bool forceBridge)
+AEffect *CVstPlugin::LoadPlugin(bool maskCrashes, VSTPluginLib &plugin, HMODULE &library, bool forceBridge)
 {
 	const mpt::PathString &pluginPath = plugin.dllPath;
 
@@ -137,9 +142,17 @@
 		plugin.useBridge = false;
 	}
 
-	if(!LoadLibrarySEH(pluginPath.AsNative(), library))
 	{
-		CVstPluginManager::ReportPlugException(MPT_UFORMAT("Exception caught while loading {}")(pluginPath));
+#ifdef MODPLUG_TRACKER
+		ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plugin.dllPath.ToUnicode()) };
+		ExceptionHandler::ContextSetter ectxguard{&ectx};
+#endif // MODPLUG_TRACKER
+		DWORD exception = SETryOrError(maskCrashes, [&](){ library = LoadLibrary(pluginPath.AsNative().c_str()); });
+		if(exception)
+		{
+			CVstPluginManager::ReportPlugException(MPT_UFORMAT("Exception caught while loading {}")(pluginPath));
+			return nullptr;
+		}
 	}
 	if(library == nullptr)
 	{
@@ -167,7 +180,30 @@
 
 	if(library != nullptr && library != INVALID_HANDLE_VALUE)
 	{
-		effect = GetAEffectSEH(library);
+		auto pMainProc = (Vst::MainProc)GetProcAddress(library, "VSTPluginMain");
+		if(pMainProc == nullptr)
+		{
+			pMainProc = (Vst::MainProc)GetProcAddress(library, "main");
+		}
+
+		if(pMainProc != nullptr)
+		{
+#ifdef MODPLUG_TRACKER
+			ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plugin.dllPath.ToUnicode()) };
+			ExceptionHandler::ContextSetter ectxguard{&ectx};
+#endif // MODPLUG_TRACKER
+			DWORD exception = SETryOrError(maskCrashes, [&](){ effect = pMainProc(CVstPlugin::MasterCallBack); });
+			if(exception)
+			{
+				return nullptr;
+			}
+		} else
+		{
+#ifdef VST_LOG
+			MPT_LOG(LogDebug, "VST", MPT_UFORMAT("Entry point not found! (handle={})")(mpt::ufmt::PTR(library)));
+#endif // VST_LOG
+			return nullptr;
+		}
 	}
 
 	return effect;
@@ -809,8 +845,9 @@
 // CVstPlugin
 //
 
-CVstPlugin::CVstPlugin(HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixStruct, AEffect &effect, CSoundFile &sndFile)
+CVstPlugin::CVstPlugin(bool maskCrashes, HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixStruct, AEffect &effect, CSoundFile &sndFile)
 	: IMidiPlugin(factory, sndFile, &mixStruct)
+	, m_maskCrashes(maskCrashes)
 	, m_Effect(effect)
 	, timeInfo{}
 	, isBridged(!memcmp(&effect.reservedForHost2, "OMPT", 4))
@@ -829,6 +866,9 @@
 
 void CVstPlugin::Initialize()
 {
+
+	m_Ectx = { MPT_UFORMAT("VST Plugin: {}")(m_Factory.dllPath.ToUnicode()) };
+
 	// If filename matched during load but plugin ID didn't, make sure it's updated.
 	m_pMixStruct->Info.dwPluginId1 = m_Factory.pluginId1 = m_Effect.magic;
 	m_pMixStruct->Info.dwPluginId2 = m_Factory.pluginId2 = m_Effect.uniqueID;
@@ -1020,16 +1060,17 @@
 
 
 // Wrapper for VST dispatch call with structured exception handling.
-intptr_t CVstPlugin::DispatchSEH(AEffect *effect, VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception)
+intptr_t CVstPlugin::DispatchSEH(bool maskCrashes, AEffect *effect, VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception)
 {
-	__try
+	if(effect->dispatcher != nullptr)
 	{
-		if(effect->dispatcher != nullptr)
+		intptr_t result = 0;
+		DWORD e = SETryOrError(maskCrashes, [&](){ result = effect->dispatcher(effect, opCode, index, value, ptr, opt); });
+		if(e)
 		{
-			return effect->dispatcher(effect, opCode, index, value, ptr, opt);
+			exception = e;
 		}
-	} __except((exception = GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER)
-	{
+		return result;
 	}
 	return 0;
 }
@@ -1037,29 +1078,39 @@
 
 intptr_t CVstPlugin::Dispatch(VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt)
 {
-	unsigned long exception = 0;
 #ifdef VST_LOG
 	{
 		mpt::ustring codeStr;
 		if(opCode < std::size(VstOpCodes))
+		{
 			codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]);
-		else
+		} else
+		{
 			codeStr = mpt::ufmt::val(opCode);
+		}
 		MPT_LOG(LogDebug, "VST", MPT_UFORMAT("About to Dispatch({}) (Plugin=\"{}\"), index: {}, value: {}, ptr: {}, opt: {}!\n")(codeStr, m_Factory.libraryName, index, mpt::ufmt::PTR(value), mpt::ufmt::PTR(ptr), mpt::ufmt::flt(opt, 3)));
 	}
 #endif
-	intptr_t result = DispatchSEH(&m_Effect, opCode, index, value, ptr, opt, exception);
-
-	if(exception)
+	if(!m_Effect.dispatcher)
 	{
-		mpt::ustring codeStr;
-		if(opCode < static_cast<int32>(std::size(VstOpCodes)))
-			codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]);
-		else
-			codeStr = mpt::ufmt::val(opCode);
-		ReportPlugException(MPT_UFORMAT("Exception {} in Dispatch({})")(mpt::ufmt::HEX0<8>(exception), codeStr));
+		return 0;
 	}
-
+	intptr_t result = 0;
+	{
+		DWORD exception = SETryOrError([&](){ result = m_Effect.dispatcher(&m_Effect, opCode, index, value, ptr, opt); });
+		if(exception)
+		{
+			mpt::ustring codeStr;
+			if(opCode < std::size(VstOpCodes))
+			{
+				codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]);
+			} else
+			{
+				codeStr = mpt::ufmt::val(opCode);
+			}
+			ReportPlugException(MPT_UFORMAT("Exception {} in Dispatch({})")(mpt::ufmt::HEX0<8>(exception), codeStr));
+		}
+	}
 	return result;
 }
 
@@ -1163,11 +1214,9 @@
 	float fResult = 0;
 	if(nIndex < m_Effect.numParams && m_Effect.getParameter != nullptr)
 	{
-		__try
+		DWORD exception = SETryOrError([&](){ fResult = m_Effect.getParameter(&m_Effect, nIndex); });
+		if(exception)
 		{
-			fResult = m_Effect.getParameter(&m_Effect, nIndex);
-		} __except(EXCEPTION_EXECUTE_HANDLER)
-		{
 			//ReportPlugException(U_("Exception in getParameter (Plugin=\"{}\")!\n"), m_Factory.szLibraryName);
 		}
 	}
@@ -1177,16 +1226,15 @@
 
 void CVstPlugin::SetParameter(PlugParamIndex nIndex, PlugParamValue fValue)
 {
-	__try
+	DWORD exception = 0;
+	if(nIndex < m_Effect.numParams && m_Effect.setParameter)
 	{
-		if(nIndex < m_Effect.numParams && m_Effect.setParameter)
-		{
-			m_Effect.setParameter(&m_Effect, nIndex, fValue);
-		}
-		ResetSilence();
-	} __except(EXCEPTION_EXECUTE_HANDLER)
+		exception = SETryOrError([&](){ m_Effect.setParameter(&m_Effect, nIndex, fValue); });
+	}
+	ResetSilence();
+	if(exception)
 	{
-		//ReportPlugException(MPT_UFORMAT("Exception in SetParameter({}, {})!")(nIndex, fValue));
+		//ReportPlugException(mpt::format(U_("Exception in SetParameter({}, {})!"))(nIndex, fValue));
 	}
 }
 
@@ -1273,8 +1321,7 @@
 	// Process VST events
 	if(m_Effect.dispatcher != nullptr && vstEvents.Finalise() > 0)
 	{
-		unsigned long exception = 0;
-		DispatchSEH(&m_Effect, effProcessEvents, 0, 0, &vstEvents, 0, exception);
+		DWORD exception = SETryOrError([&](){ m_Effect.dispatcher(&m_Effect, effProcessEvents, 0, 0, &vstEvents, 0); });
 		ResetSilence();
 		if(exception)
 		{
@@ -1342,18 +1389,6 @@
 }
 
 
-// Wrapper for VST process call with structured exception handling.
-static void ProcessSEH(Vst::ProcessProc processFP, AEffect* effect, float** inputs, float** outputs, int32 sampleFrames, unsigned long &exception)
-{
-	__try
-	{
-		processFP(effect, inputs, outputs, sampleFrames);
-	} __except((exception = GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER)
-	{
-	}
-}
-
-
 void CVstPlugin::Process(float *pOutL, float *pOutR, uint32 numFrames)
 {
 	ProcessVSTEvents();
@@ -1382,14 +1417,15 @@
 		}
 
 		// Do the VST processing magic
-		ASSERT(numFrames <= MIXBUFFERSIZE);
-		unsigned long exception = 0;
-		ProcessSEH(m_pProcessFP, &m_Effect, m_mixBuffer.GetInputBufferArray(), outputBuffers, numFrames, exception);
-		if(exception)
+		MPT_ASSERT(numFrames <= MIXBUFFERSIZE);
 		{
-			Bypass();
-			mpt::ustring processMethod = (m_Effect.flags & effFlagsCanReplacing) ? U_("processReplacing") : U_("process");
-			ReportPlugException(MPT_UFORMAT("The plugin threw an exception ({}) in {}. It has automatically been set to \"Bypass\".")(mpt::ufmt::HEX0<8>(exception), processMethod));
+			DWORD exception = SETryOrError([&](){ m_pProcessFP(&m_Effect, m_mixBuffer.GetInputBufferArray(), outputBuffers, numFrames); });
+			if(exception)
+			{
+				Bypass();
+				mpt::ustring processMethod = (m_Effect.flags & effFlagsCanReplacing) ? U_("processReplacing") : U_("process");
+				ReportPlugException(MPT_UFORMAT("The plugin threw an exception ({}) in {}. It has automatically been set to \"Bypass\".")(mpt::ufmt::HEX0<8>(exception), processMethod));
+			}
 		}
 
 		// Mix outputs of multi-output VSTs:
Index: mptrack/Vstplug.h
===================================================================
--- mptrack/Vstplug.h	(revision 13970)
+++ mptrack/Vstplug.h	(working copy)
@@ -19,7 +19,11 @@
 #include "../soundlib/Mixer.h"
 #include "plugins/VstDefinitions.h"
 #include "plugins/VstEventQueue.h"
+#if defined(MODPLUG_TRACKER)
+#include "ExceptionHandler.h"
+#endif // MODPLUG_TRACKER
 
+
 OPENMPT_NAMESPACE_BEGIN
 
 
@@ -31,6 +35,8 @@
 class CVstPlugin final : public IMidiPlugin
 {
 protected:
+
+	bool m_maskCrashes;
 	HMODULE m_hLibrary;
 	Vst::AEffect &m_Effect;
 	Vst::ProcessProc m_pProcessFP = nullptr; // Function pointer to AEffect processReplacing if supported, else process.
@@ -49,13 +55,29 @@
 	Vst::VstTimeInfo timeInfo;
 
 public:
+
 	const bool isBridged : 1;		// True if our built-in plugin bridge is being used.
 
+private:
+
+#if defined(MODPLUG_TRACKER)
+	ExceptionHandler::Context m_Ectx;
+#endif // MODPLUG_TRACKER
+
 public:
-	CVstPlugin(HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixPlugin, Vst::AEffect &effect, CSoundFile &sndFile);
+	bool MaskCrashes() noexcept;
+
+public:
+	template <typename Tfn> static DWORD SETryOrError(bool maskCrashes, Tfn fn);
+
+private:
+	template <typename Tfn> DWORD SETryOrError(Tfn fn);
+
+public:
+	CVstPlugin(bool maskCrashes, HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixPlugin, Vst::AEffect &effect, CSoundFile &sndFile);
 	~CVstPlugin();
 
-	static Vst::AEffect *LoadPlugin(VSTPluginLib &plugin, HMODULE &library, bool forceBridge);
+	static Vst::AEffect *LoadPlugin(bool maskCrashes, VSTPluginLib &plugin, HMODULE &library, bool forceBridge);
 
 protected:
 	void Initialize();
@@ -91,7 +113,7 @@
 	CString GetParamLabel(PlugParamIndex param) override { return GetParamPropertyString(param, Vst::effGetParamLabel); };
 	CString GetParamDisplay(PlugParamIndex param) override { return GetParamPropertyString(param, Vst::effGetParamDisplay); };
 
-	static intptr_t DispatchSEH(Vst::AEffect *effect, Vst::VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception);
+	static intptr_t DispatchSEH(bool maskCrashes, Vst::AEffect *effect, Vst::VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception);
 	intptr_t Dispatch(Vst::VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt);
 
 	bool HasEditor() const override { return (m_Effect.flags & Vst::effFlagsHasEditor) != 0; }
Index: soundlib/plugins/PluginManager.cpp
===================================================================
--- soundlib/plugins/PluginManager.cpp	(revision 13970)
+++ soundlib/plugins/PluginManager.cpp	(working copy)
@@ -55,6 +55,7 @@
 #include "../../mptrack/TrackerSettings.h"
 #include "../../mptrack/AbstractVstEditor.h"
 #include "../../soundlib/AudioCriticalSection.h"
+#include "../mptrack/ExceptionHandler.h"
 #include "../common/mptCRC.h"
 #endif // MODPLUG_TRACKER
 
@@ -427,10 +428,10 @@
 
 // Extract instrument and category information from plugin.
 #ifndef NO_VST
-static void GetPluginInformation(Vst::AEffect *effect, VSTPluginLib &library)
+static void GetPluginInformation(bool maskCrashes, Vst::AEffect *effect, VSTPluginLib &library)
 {
 	unsigned long exception = 0;
-	library.category = static_cast<VSTPluginLib::PluginCategory>(CVstPlugin::DispatchSEH(effect, Vst::effGetPlugCategory, 0, 0, nullptr, 0, exception));
+	library.category = static_cast<VSTPluginLib::PluginCategory>(CVstPlugin::DispatchSEH(maskCrashes, effect, Vst::effGetPlugCategory, 0, 0, nullptr, 0, exception));
 	library.isInstrument = ((effect->flags & Vst::effFlagsIsSynth) || !effect->numInputs);
 
 	if(library.isInstrument)
@@ -443,7 +444,7 @@
 
 #ifdef MODPLUG_TRACKER
 	std::vector<char> s(256, 0);
-	CVstPlugin::DispatchSEH(effect, Vst::effGetVendorString, 0, 0, s.data(), 0, exception);
+	CVstPlugin::DispatchSEH(maskCrashes, effect, Vst::effGetVendorString, 0, 0, s.data(), 0, exception);
 	library.vendor = mpt::ToCString(mpt::Charset::Locale, s.data());
 #endif // MODPLUG_TRACKER
 }
@@ -452,7 +453,7 @@
 
 #ifdef MODPLUG_TRACKER
 // Add a plugin to the list of known plugins.
-VSTPluginLib *CVstPluginManager::AddPlugin(const mpt::PathString &dllPath, const mpt::ustring &tags, bool fromCache, bool *fileFound)
+VSTPluginLib *CVstPluginManager::AddPlugin(const mpt::PathString &dllPath, bool maskCrashes, const mpt::ustring &tags, bool fromCache, bool *fileFound)
 {
 	const mpt::PathString fileName = dllPath.GetFileName();
 
@@ -535,32 +536,39 @@
 	unsigned long exception = 0;
 	// Always scan plugins in a separate process
 	HINSTANCE hLib = NULL;
-	Vst::AEffect *pEffect = CVstPlugin::LoadPlugin(*plug, hLib, true);
-
-	if(pEffect != nullptr && pEffect->magic == Vst::kEffectMagic && pEffect->dispatcher != nullptr)
 	{
-		CVstPlugin::DispatchSEH(pEffect, Vst::effOpen, 0, 0, 0, 0, exception);
+#ifdef MODPLUG_TRACKER
+		ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plug->dllPath.ToUnicode()) };
+		ExceptionHandler::ContextSetter ectxguard{&ectx};
+#endif // MODPLUG_TRACKER
 
-		plug->pluginId1 = pEffect->magic;
-		plug->pluginId2 = pEffect->uniqueID;
+		Vst::AEffect *pEffect = CVstPlugin::LoadPlugin(maskCrashes, *plug, hLib, true);
 
-		GetPluginInformation(pEffect, *plug);
+		if(pEffect != nullptr && pEffect->magic == Vst::kEffectMagic && pEffect->dispatcher != nullptr)
+		{
+			CVstPlugin::DispatchSEH(maskCrashes, pEffect, Vst::effOpen, 0, 0, 0, 0, exception);
 
+			plug->pluginId1 = pEffect->magic;
+			plug->pluginId2 = pEffect->uniqueID;
+
+			GetPluginInformation(maskCrashes, pEffect, *plug);
+
 #ifdef VST_LOG
-		intptr_t nver = CVstPlugin::DispatchSEH(pEffect, Vst::effGetVstVersion, 0,0, nullptr, 0, exception);
-		if (!nver) nver = pEffect->version;
-		MPT_LOG(LogDebug, "VST", MPT_UFORMAT("{}: v{}.0, {} in, {} out, {} programs, {} params, flags=0x{} realQ={} offQ={}")(
-			plug->libraryName, nver,
-			pEffect->numInputs, pEffect->numOutputs,
-			mpt::ufmt::dec0<2>(pEffect->numPrograms), mpt::ufmt::dec0<2>(pEffect->numParams),
-			mpt::ufmt::HEX0<4>(static_cast<int32>(pEffect->flags)), pEffect->realQualities, pEffect->offQualities));
+			intptr_t nver = CVstPlugin::DispatchSEH(maskCrashes, pEffect, Vst::effGetVstVersion, 0,0, nullptr, 0, exception);
+			if (!nver) nver = pEffect->version;
+			MPT_LOG(LogDebug, "VST", MPT_UFORMAT("{}: v{}.0, {} in, {} out, {} programs, {} params, flags=0x{} realQ={} offQ={}")(
+				plug->libraryName, nver,
+				pEffect->numInputs, pEffect->numOutputs,
+				mpt::ufmt::dec0<2>(pEffect->numPrograms), mpt::ufmt::dec0<2>(pEffect->numParams),
+				mpt::ufmt::HEX0<4>(static_cast<int32>(pEffect->flags)), pEffect->realQualities, pEffect->offQualities));
 #endif // VST_LOG
 
-		CVstPlugin::DispatchSEH(pEffect, Vst::effClose, 0, 0, 0, 0, exception);
+			CVstPlugin::DispatchSEH(maskCrashes, pEffect, Vst::effClose, 0, 0, 0, 0, exception);
 
-		validPlug = true;
+			validPlug = true;
+		}
+
 	}
-
 	FreeLibrary(hLib);
 	if(exception != 0)
 	{
@@ -672,6 +680,8 @@
 	}
 
 #ifdef MODPLUG_TRACKER
+	bool maskCrashes = TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes;
+
 	if(!pFound && (mixPlugin.GetLibraryName() != U_("")))
 	{
 		// Try finding the plugin DLL in the plugin directory or plugin cache instead.
@@ -682,7 +692,7 @@
 		}
 		fullPath += mpt::PathString::FromUnicode(mixPlugin.GetLibraryName()) + P_(".dll");
 
-		pFound = AddPlugin(fullPath);
+		pFound = AddPlugin(fullPath, maskCrashes);
 		if(!pFound)
 		{
 			// Try plugin cache (search for library name)
@@ -696,7 +706,7 @@
 					fullPath = theApp.PathInstallRelativeToAbsolute(fullPath);
 					if(fullPath.IsFile())
 					{
-						pFound = AddPlugin(fullPath);
+						pFound = AddPlugin(fullPath, maskCrashes);
 					}
 				}
 			}
@@ -710,18 +720,18 @@
 		HINSTANCE hLibrary = nullptr;
 		bool validPlugin = false;
 
-		pEffect = CVstPlugin::LoadPlugin(*pFound, hLibrary, TrackerSettings::Instance().bridgeAllPlugins);
+		pEffect = CVstPlugin::LoadPlugin(maskCrashes, *pFound, hLibrary, TrackerSettings::Instance().bridgeAllPlugins);
 
 		if(pEffect != nullptr && pEffect->dispatcher != nullptr && pEffect->magic == Vst::kEffectMagic)
 		{
 			validPlugin = true;
 
-			GetPluginInformation(pEffect, *pFound);
+			GetPluginInformation(maskCrashes, pEffect, *pFound);
 
 			// Update cached information
 			pFound->WriteToCache();
 
-			CVstPlugin *pVstPlug = new (std::nothrow) CVstPlugin(hLibrary, *pFound, mixPlugin, *pEffect, sndFile);
+			CVstPlugin *pVstPlug = new (std::nothrow) CVstPlugin(maskCrashes, hLibrary, *pFound, mixPlugin, *pEffect, sndFile);
 			if(pVstPlug == nullptr)
 			{
 				validPlugin = false;
Index: soundlib/plugins/PluginManager.h
===================================================================
--- soundlib/plugins/PluginManager.h	(revision 13970)
+++ soundlib/plugins/PluginManager.h	(working copy)
@@ -160,7 +160,7 @@
 	size_t size() const { return pluginList.size(); }
 
 	bool IsValidPlugin(const VSTPluginLib *pLib) const;
-	VSTPluginLib *AddPlugin(const mpt::PathString &dllPath, const mpt::ustring &tags = mpt::ustring(), bool fromCache = true, bool *fileFound = nullptr);
+	VSTPluginLib *AddPlugin(const mpt::PathString &dllPath, bool maskCrashes, const mpt::ustring &tags = mpt::ustring(), bool fromCache = true, bool *fileFound = nullptr);
 	bool RemovePlugin(VSTPluginLib *);
 	bool CreateMixPlugin(SNDMIXPLUGIN &, CSoundFile &);
 	void OnIdle();
