diff --git a/CHANGELOG.md b/CHANGELOG.md
index c404e79b..b2c60fd6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,13 +8,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.5 / 5.55.5] - 2021-12-??
### Added
--
+- sandbox top level exception handler to create crash dumps
+-- can be enabled per process or globally using "EnableMiniDump=process.exe,y" or "EnableMiniDump=y" respectivly
+-- the dump flags can be set as hex with MiniDumpFlags=0xAABBCCDD
+-- a presellected flag set for a verbose dump can be set with MiniDumpFlags=Extended
+-- note: Created dump files are located at: C:\Sandbox\%SANDBOX%
### Changed
- improved sbiedll initialization a bit
### Fixed
- fixed issue with forced process display [#1447](https://github.com/sandboxie-plus/Sandboxie/issues/1447)
+- fixed crash issue with GetClassName [#1448](https://github.com/sandboxie-plus/Sandboxie/issues/1448)
diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj
index a42e660e..7a73dd19 100644
--- a/Sandboxie/core/dll/SboxDll.vcxproj
+++ b/Sandboxie/core/dll/SboxDll.vcxproj
@@ -240,6 +240,7 @@
+
@@ -423,6 +424,7 @@
+
diff --git a/Sandboxie/core/dll/SboxDll.vcxproj.filters b/Sandboxie/core/dll/SboxDll.vcxproj.filters
index 1dd59a1f..0e744e64 100644
--- a/Sandboxie/core/dll/SboxDll.vcxproj.filters
+++ b/Sandboxie/core/dll/SboxDll.vcxproj.filters
@@ -4,7 +4,6 @@
-
@@ -161,7 +160,6 @@
hook
-
common
@@ -211,10 +209,18 @@
common\wow64ext
+
+ debug
+
+
+ debug
+
+
+ debug
+
-
hook
@@ -252,7 +258,6 @@
com
-
common
@@ -298,6 +303,15 @@
common
+
+ debug
+
+
+ debug
+
+
+ debug
+
@@ -356,6 +370,9 @@
{c6a9654a-9f55-43ca-9cd1-7571bb879288}
+
+ {db0f9820-8908-4325-96f9-69c82fa9e268}
+
diff --git a/Sandboxie/core/dll/dllmain.c b/Sandboxie/core/dll/dllmain.c
index b52b6e4f..620b5129 100644
--- a/Sandboxie/core/dll/dllmain.c
+++ b/Sandboxie/core/dll/dllmain.c
@@ -25,6 +25,7 @@
#include "obj.h"
#include "trace.h"
#include "debug.h"
+#include "dump.h"
#include "core/low/lowdata.h"
#include "common/my_version.h"
@@ -529,6 +530,17 @@ _FX void Dll_InitExeEntry(void)
//
SbieDll_StartCOM(TRUE);
+
+ //
+ // setup own top level exception handler
+ //
+
+ if(Config_GetSettingsForImageName_bool(L"EnableMiniDump", FALSE))
+ Dump_Init();
+
+ //
+ // once we return here the process images entrypoint will be called
+ //
}
diff --git a/Sandboxie/core/dll/dump.c b/Sandboxie/core/dll/dump.c
new file mode 100644
index 00000000..738d4389
--- /dev/null
+++ b/Sandboxie/core/dll/dump.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2021 DavidXanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+//---------------------------------------------------------------------------
+// Dump Helper
+//---------------------------------------------------------------------------
+
+#include "dll.h"
+#include "dump.h"
+
+#include
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+
+typedef BOOL (__stdcall *P_MiniDumpWriteDump)(
+ IN HANDLE hProcess,
+ IN DWORD ProcessId,
+ IN HANDLE hFile,
+ IN MINIDUMP_TYPE DumpType,
+ IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
+ IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
+ IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
+ );
+
+typedef LPTOP_LEVEL_EXCEPTION_FILTER(*P_SetUnhandledExceptionFilter)(
+ _In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
+
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+
+static P_MiniDumpWriteDump __sys_MiniDumpWriteDump;
+static HMODULE Dump_DbgHelpMod;
+
+#define DUMP_FLAGS_DEFAULT MiniDumpWithHandleData | \
+ MiniDumpWithUnloadedModules | \
+ MiniDumpFilterModulePaths | \
+ MiniDumpWithProcessThreadData | \
+ MiniDumpWithoutOptionalData | \
+ MiniDumpIgnoreInaccessibleMemory | \
+ MiniDumpFilterTriage //0x001205a4 thats what WerFault.exe uses
+
+#define DUMP_FLAGS_EXTENDED MiniDumpWithFullMemory | \
+ MiniDumpWithHandleData | \
+ MiniDumpWithThreadInfo | \
+ MiniDumpWithProcessThreadData | \
+ MiniDumpWithFullMemoryInfo | \
+ MiniDumpWithUnloadedModules | \
+ MiniDumpWithFullAuxiliaryState | \
+ MiniDumpIgnoreInaccessibleMemory | \
+ MiniDumpWithTokenInformation
+
+static MINIDUMP_TYPE Dump_Flags = DUMP_FLAGS_DEFAULT;
+static P_SetUnhandledExceptionFilter __sys_SetUnhandledExceptionFilter = NULL;
+
+
+//---------------------------------------------------------------------------
+// Functions
+//---------------------------------------------------------------------------
+
+
+//---------------------------------------------------------------------------
+// Dump_CrashHandlerExceptionFilter
+//---------------------------------------------------------------------------
+
+LONGLONG GetCurCycle()
+{
+ LONGLONG freq, now;
+ QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
+ QueryPerformanceCounter((LARGE_INTEGER*)&now);
+ LONGLONG dwNow = ((now * 1000000) / freq);
+ return dwNow; // returns time since system start in us
+}
+
+static LONG __stdcall Dump_CrashHandlerExceptionFilter(EXCEPTION_POINTERS* pEx)
+{
+#ifdef _M_IX86
+ if (pEx->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
+ {
+ // be sure that we have enought space...
+ static char MyStack[1024 * 128];
+ // it assumes that DS and SS are the same!!! (this is the case for Win32)
+ // change the stack only if the selectors are the same (this is the case for Win32)
+ //__asm push offset MyStack[1024*128];
+ //__asm pop esp;
+ __asm mov eax, offset MyStack[1024 * 128];
+ __asm mov esp, eax;
+ }
+#endif
+
+ SbieApi_Log(2224, L"%S [%S]", Dll_ImageName, Dll_BoxName);
+
+ BOOLEAN bSuccess = FALSE;
+ HANDLE hFile;
+
+ wchar_t szMiniDumpFileName[128];
+ Sbie_snwprintf(szMiniDumpFileName, 128, L"%s.%lld.dmp", Dll_ImageName, GetCurCycle);
+
+ wchar_t szMiniDumpFilePath[MAX_PATH] = { 0 };
+ Sbie_snwprintf(szMiniDumpFilePath, MAX_PATH, L"%s\\%s", Dll_BoxFilePath, szMiniDumpFileName);
+ //hFile = CreateFile(szMiniDumpFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ UNICODE_STRING uni;
+ OBJECT_ATTRIBUTES attr;
+ RtlInitUnicodeString(&uni, szMiniDumpFilePath);
+ InitializeObjectAttributes(&attr, &uni, OBJ_CASE_INSENSITIVE, NULL, 0);
+
+ IO_STATUS_BLOCK Iosb;
+ extern P_NtCreateFile __sys_NtCreateFile;
+ NTSTATUS status = __sys_NtCreateFile(&hFile, FILE_GENERIC_WRITE, &attr, &Iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
+
+ //if (hFile != INVALID_HANDLE_VALUE)
+ if (NT_SUCCESS(status))
+ {
+ MINIDUMP_EXCEPTION_INFORMATION stMDEI;
+ stMDEI.ThreadId = GetCurrentThreadId();
+ stMDEI.ExceptionPointers = pEx;
+ stMDEI.ClientPointers = TRUE;
+ // try to create an miniDump:
+ if (__sys_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, Dump_Flags, &stMDEI, NULL, NULL))
+ {
+ bSuccess = TRUE;
+ }
+ //CloseHandle(hFile);
+ extern P_NtClose __sys_NtClose;
+ __sys_NtClose(hFile);
+ }
+
+ wchar_t szMiniDumpMessage[256];
+ if (!bSuccess)
+ Sbie_snwprintf(szMiniDumpMessage, 256, L"%s crashed!\r\nCrashdump creation failed.", Dll_ImageName);
+ else
+ Sbie_snwprintf(szMiniDumpMessage, 256, L"%s crashed!\r\nCrashdump saved to \"%s\".", Dll_ImageName, szMiniDumpFileName);
+ SbieApi_MonitorPut2(MONITOR_OTHER | MONITOR_TRACE, szMiniDumpMessage, FALSE);
+
+ // or return one of the following:
+ // - EXCEPTION_CONTINUE_SEARCH // this will trigger the "normal" OS error-dialog
+ // - EXCEPTION_CONTINUE_EXECUTION
+ // - EXCEPTION_EXECUTE_HANDLER // this will prevent the invocation of WerFault.exe
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+//---------------------------------------------------------------------------
+// Dump_SetUnhandledExceptionFilter
+//---------------------------------------------------------------------------
+
+
+ALIGNED LPTOP_LEVEL_EXCEPTION_FILTER Dump_SetUnhandledExceptionFilter(
+ _In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
+)
+{
+ return NULL;
+}
+
+
+//---------------------------------------------------------------------------
+// Dump_SetUnhandledExceptionFilter
+//---------------------------------------------------------------------------
+
+
+/*ALIGNED BOOLEAN Dump_MiniDumpWriteDump(
+ _In_ HANDLE hProcess,
+ _In_ DWORD ProcessId,
+ _In_ HANDLE hFile,
+ _In_ MINIDUMP_TYPE DumpType,
+ _In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ _In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ _In_opt_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
+)
+{
+ while (! IsDebuggerPresent()) {
+ OutputDebugString(L"BREAK\n");
+ Sleep(500);
+ }
+ __debugbreak();
+
+ return __sys_MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType, ExceptionParam, UserStreamParam, CallbackParam);
+}*/
+
+
+//---------------------------------------------------------------------------
+// Dump_Init
+//---------------------------------------------------------------------------
+
+
+_FX int Dump_Init(void)
+{
+ if (Dump_DbgHelpMod != NULL)
+ return 2;
+
+ // Initialize the member, so we do not load the dll after the exception has occured
+ // which might be not possible anymore...
+ Dump_DbgHelpMod = LoadLibrary(L"dbghelp.dll");
+ if (!Dump_DbgHelpMod )
+ return 0;
+
+ /*if (_wcsicmp(Dll_ImageName, L"WerFault.exe") == 0) // fre experimenting only
+ {
+ P_MiniDumpWriteDump MiniDumpWriteDump = (P_MiniDumpWriteDump)GetProcAddress(Dump_DbgHelpMod, "MiniDumpWriteDump");
+ SBIEDLL_HOOK(Dump_, MiniDumpWriteDump);
+ return 1;
+ }*/
+
+ __sys_MiniDumpWriteDump = (P_MiniDumpWriteDump)GetProcAddress(Dump_DbgHelpMod, "MiniDumpWriteDump");
+
+ // get the default preset
+ WCHAR str[32];
+ if (NT_SUCCESS(SbieApi_QueryConfAsIs(NULL, L"MiniDumpFlags", 0, str, sizeof(str) - sizeof(WCHAR)))) {
+ if (_wcsnicmp(str, L"0x", 2) == 0)
+ Dump_Flags = wcstol(str + 2, NULL, 16);
+ else if (_wcsnicmp(str, L"extended", 3) == 0) // check only first 3 letters
+ Dump_Flags = DUMP_FLAGS_EXTENDED;
+ }
+
+ // Register Unhandled Exception-Filter:
+ SetUnhandledExceptionFilter(Dump_CrashHandlerExceptionFilter);
+
+ // Additional call "PreventSetUnhandledExceptionFilter"...
+ // See also: "SetUnhandledExceptionFilter" and VC8 (and later)
+ // http://blog.kalmbachnet.de/?postid=75
+
+ SBIEDLL_HOOK(Dump_, SetUnhandledExceptionFilter);
+
+ //SbieApi_MonitorPut2(MONITOR_OTHER | MONITOR_TRACE, L"Minidump enabled", FALSE);
+ return 1;
+}
\ No newline at end of file
diff --git a/Sandboxie/core/dll/dump.h b/Sandboxie/core/dll/dump.h
new file mode 100644
index 00000000..7bff07c5
--- /dev/null
+++ b/Sandboxie/core/dll/dump.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 DavidXanatos, xanasoft.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+//---------------------------------------------------------------------------
+// Sandboxie Trace
+//---------------------------------------------------------------------------
+
+
+#ifndef _MY_DUMP_H
+#define _MY_DUMP_H
+
+
+//---------------------------------------------------------------------------
+
+int Dump_Init(void);
+
+//---------------------------------------------------------------------------
+
+
+#endif /* _MY_DUMP_H */
diff --git a/Sandboxie/core/dll/file.c b/Sandboxie/core/dll/file.c
index 7362fad2..11b5072b 100644
--- a/Sandboxie/core/dll/file.c
+++ b/Sandboxie/core/dll/file.c
@@ -293,7 +293,7 @@ static P_NtQueryInformationFile __sys_NtQueryInformationFile = NULL;
static P_NtQueryDirectoryFileEx __sys_NtQueryDirectoryFileEx = NULL;
static P_NtSetInformationFile __sys_NtSetInformationFile = NULL;
static P_NtDeleteFile __sys_NtDeleteFile = NULL;
-static P_NtClose __sys_NtClose = NULL;
+ P_NtClose __sys_NtClose = NULL;
static P_NtCreateNamedPipeFile __sys_NtCreateNamedPipeFile = NULL;
static P_NtCreateMailslotFile __sys_NtCreateMailslotFile = NULL;
static P_NtReadFile __sys_NtReadFile = NULL;
diff --git a/Sandboxie/core/dll/guiclass.c b/Sandboxie/core/dll/guiclass.c
index fea16b71..e86e31fd 100644
--- a/Sandboxie/core/dll/guiclass.c
+++ b/Sandboxie/core/dll/guiclass.c
@@ -742,8 +742,10 @@ _FX int Gui_GetClassNameW(
n -= (ULONG)(clsnm_ptr - clsnm);
if (n > nMaxCount - 1)
n = nMaxCount - 1;
- wmemcpy(lpClassName, clsnm_ptr, n);
- lpClassName[n] = L'\0';
+ if (lpClassName) {
+ wmemcpy(lpClassName, clsnm_ptr, n);
+ lpClassName[n] = L'\0';
+ }
} else
n = 0;
} else
@@ -754,8 +756,10 @@ _FX int Gui_GetClassNameW(
n = nMaxCount - 1;
else
n = n0;
- wmemcpy(lpClassName, clsnm, n);
- lpClassName[n] = L'\0';
+ if (lpClassName) {
+ wmemcpy(lpClassName, clsnm, n);
+ lpClassName[n] = L'\0';
+ }
}
Dll_Free(clsnm);
@@ -796,8 +800,10 @@ _FX int Gui_GetClassNameA(
n -= (ULONG)(clsnm_ptr - clsnm);
if (n > nMaxCount - 1)
n = nMaxCount - 1;
- memcpy(lpClassName, clsnm_ptr, n);
- lpClassName[n] = '\0';
+ if (lpClassName) {
+ memcpy(lpClassName, clsnm_ptr, n);
+ lpClassName[n] = '\0';
+ }
} else
n = 0;
} else
@@ -808,8 +814,10 @@ _FX int Gui_GetClassNameA(
n = nMaxCount - 1;
else
n = n0;
- memcpy(lpClassName, clsnm, n);
- lpClassName[n] = L'\0';
+ if (lpClassName) {
+ memcpy(lpClassName, clsnm, n);
+ lpClassName[n] = L'\0';
+ }
}
Dll_Free(clsnm);
diff --git a/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp b/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp
index 5494b1c9..e6f95286 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp
+++ b/SandboxiePlus/SandMan/Windows/OptionsTemplates.cpp
@@ -120,14 +120,14 @@ void COptionsWindow::ShowTemplates()
if (!CategoryFilter.isEmpty() && I.key().compare(CategoryFilter, Qt::CaseInsensitive) != 0)
continue;
- QString Name = I.value().first.mid(9);
-
- if (!Name.isEmpty() && Name.indexOf(TextFilter, 0, Qt::CaseInsensitive) == -1)
+ if (I.value().second.indexOf(TextFilter, 0, Qt::CaseInsensitive) == -1)
continue;
if (I.key().isEmpty())
continue; // dont show templates without a category (these are usually deprecated templates)
+ QString Name = I.value().first.mid(9);
+
QTreeWidgetItem* pItem = new QTreeWidgetItem();
pItem->setText(0, GetCategoryName(I.key()));
pItem->setData(1, Qt::UserRole, I.value().first);