From 50029ee077770bc1032075d7318cf1defa9507f2 Mon Sep 17 00:00:00 2001
From: DavidXanatos <3890945+DavidXanatos@users.noreply.github.com>
Date: Wed, 25 Jan 2023 12:54:41 +0100
Subject: [PATCH] 1.7.0
---
CHANGELOG.md | 23 +-
Sandboxie/apps/control/Updater.cpp | 9 +-
Sandboxie/common/my_version.h | 4 +-
Sandboxie/core/dll/SboxDll.vcxproj | 2 +
Sandboxie/core/dll/debug.c | 2 +-
Sandboxie/core/dll/dllmain.c | 8 +
Sandboxie/core/dll/dump.c | 8 +-
Sandboxie/core/dll/file_copy.c | 61 +++-
Sandboxie/core/dll/key.c | 187 ++++++++--
Sandboxie/core/dll/ldr.c | 46 ++-
Sandboxie/core/dll/ldr_init.c | 31 +-
Sandboxie/core/dll/util_64.asm | 17 +-
Sandboxie/core/dll/util_arm.asm | 3 +-
Sandboxie/core/low/init.c | 29 +-
Sandboxie/core/low/inject.c | 59 ++-
.../MiscHelpers/Common/DebugHelpers.cpp | 6 +
SandboxiePlus/QSbieAPI/SbieUtils.cpp | 87 +++++
SandboxiePlus/QSbieAPI/SbieUtils.h | 3 +
SandboxiePlus/SandMan/Forms/OptionsWindow.ui | 339 +++++++++++++-----
SandboxiePlus/SandMan/Forms/SettingsWindow.ui | 270 +++++++-------
SandboxiePlus/SandMan/OnlineUpdater.cpp | 10 +-
SandboxiePlus/SandMan/OnlineUpdater.h | 2 +-
SandboxiePlus/SandMan/SandManRecovery.cpp | 108 +++++-
SandboxiePlus/SandMan/Views/SbieView.cpp | 9 +-
.../SandMan/Windows/OptionsAdvanced.cpp | 2 -
.../SandMan/Windows/OptionsGeneral.cpp | 338 ++++++++++++++++-
.../SandMan/Windows/OptionsNetwork.cpp | 1 +
.../SandMan/Windows/OptionsWindow.cpp | 49 ++-
SandboxiePlus/SandMan/Windows/OptionsWindow.h | 24 ++
.../SandMan/Windows/SettingsWindow.cpp | 6 +-
SandboxiePlus/SandMan/Wizards/SetupWizard.cpp | 1 -
SandboxiePlus/version.h | 4 +-
32 files changed, 1393 insertions(+), 355 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1bd9509d..29f97867 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,30 @@ This project adheres to [Semantic Versioning](http://semver.org/).
+## [1.7.0 / 5.62.0] - 2023-01-25
-## [1.6.7 / 5.61.7] - 2023-01-?
+### Added
+- added OnFileRecovery trigger allowing to check files before recovering them [#2202](https://github.com/sandboxie-plus/Sandboxie/issues/2202)
+
+- added more box structure presets to sandbox options
+-- Note: these can only be changed when the box is empty
+
+- added new File Migration option page with additional settings
+- added SBIE2113/SBIE2114/SBIE2115 message to indicate files not being migrated due to presets
+
+### changed
+- moved SeparateUserFolders checlbox from global settings to per box options
+
+### fixed
+- resolved SbieDll.dll incompatybility with shadow stack and enabled /CETCOMPAT for SbieDll.dll [#2559](https://github.com/sandboxie-plus/Sandboxie/issues/2559)
+- added missing registry hooks to improve compatybility with newer appliations
+- fixed permission isue with registry entries in privacy mode boxes
+
+
+
+
+## [1.6.7 / 5.61.7] - 2023-01-24
### Added
- added option to the classic ui to apply a supporter certificate
diff --git a/Sandboxie/apps/control/Updater.cpp b/Sandboxie/apps/control/Updater.cpp
index e5aaee2d..5c5c8cc3 100644
--- a/Sandboxie/apps/control/Updater.cpp
+++ b/Sandboxie/apps/control/Updater.cpp
@@ -237,13 +237,14 @@ BOOLEAN CUpdater::QueryUpdateData(UPDATER_DATA* Context)
JSONValue* jsonObject = NULL;
JSONObject jsonRoot;
- Path.Format(L"/update.php?software=sandboxie&version=%S&system=windows-%d.%d.%d-%s&language=%d&auto=%s", MY_VERSION_STRING,
+ Path.Format(L"/update.php?software=sandboxie&version=%S&system=windows-%d.%d.%d-%s&language=%d&auto=%s",
+ MY_VERSION_STRING, m_osvi.dwMajorVersion, m_osvi.dwMinorVersion, m_osvi.dwBuildNumber,
#ifdef _M_ARM64
- m_osvi.dwMajorVersion, m_osvi.dwMinorVersion, m_osvi.dwBuildNumber, L"ARM64",
+ L"ARM64",
#elif _WIN64
- m_osvi.dwMajorVersion, m_osvi.dwMinorVersion, m_osvi.dwBuildNumber, L"x86_64",
+ L"x86_64",
#else
- m_osvi.dwMajorVersion, m_osvi.dwMinorVersion, m_osvi.dwBuildNumber, L"i386",
+ L"i386",
#endif
SbieDll_GetLanguage(NULL), Context->Manual ? L"0" : L"1");
diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h
index 55d2bf84..65ef71af 100644
--- a/Sandboxie/common/my_version.h
+++ b/Sandboxie/common/my_version.h
@@ -21,8 +21,8 @@
#ifndef _MY_VERSION_H
#define _MY_VERSION_H
-#define MY_VERSION_BINARY 5,61,7
-#define MY_VERSION_STRING "5.61.7"
+#define MY_VERSION_BINARY 5,62,0
+#define MY_VERSION_STRING "5.62.0"
#define MY_ABI_VERSION 0x56000
// These #defines are used by either Resource Compiler or NSIS installer
diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj
index ccf7d433..cf4092c9 100644
--- a/Sandboxie/core/dll/SboxDll.vcxproj
+++ b/Sandboxie/core/dll/SboxDll.vcxproj
@@ -204,6 +204,7 @@
true
false
false
+ true
/ignore:4281 %(AdditionalOptions)
@@ -294,6 +295,7 @@
true
false
false
+ true
/ignore:4281 %(AdditionalOptions)
diff --git a/Sandboxie/core/dll/debug.c b/Sandboxie/core/dll/debug.c
index 2d37bb13..a27cebdc 100644
--- a/Sandboxie/core/dll/debug.c
+++ b/Sandboxie/core/dll/debug.c
@@ -46,7 +46,7 @@
//#define BREAK_PROC "ExecSecureObjects"
//#define BREAK_PROC "SoftwareDirectorMsiErrorCheck"
//#define BREAK_PROC "InstallDriverPackages"
-#define BREAK_PROC "MSIunzipcore"
+//#define BREAK_PROC "MSIunzipcore"
#undef HIDE_SBIEDLL
diff --git a/Sandboxie/core/dll/dllmain.c b/Sandboxie/core/dll/dllmain.c
index 9925011d..87782c0c 100644
--- a/Sandboxie/core/dll/dllmain.c
+++ b/Sandboxie/core/dll/dllmain.c
@@ -383,6 +383,14 @@ _FX void Dll_InitInjected(void)
// }
// }
+
+#ifdef WITH_DEBUG
+ if (SbieApi_QueryConfBool(NULL, L"DisableSbieDll", FALSE)) {
+ Dll_InitComplete = TRUE;
+ return;
+ }
+#endif
+
//
// check if process SID is LocalSystem
//
diff --git a/Sandboxie/core/dll/dump.c b/Sandboxie/core/dll/dump.c
index 708833c9..d4f59ebd 100644
--- a/Sandboxie/core/dll/dump.c
+++ b/Sandboxie/core/dll/dump.c
@@ -106,7 +106,10 @@ static LONG __stdcall Dump_CrashHandlerExceptionFilter(EXCEPTION_POINTERS* pEx)
}
#endif
- SbieApi_Log(2224, L"%S [%S]", Dll_ImageName, Dll_BoxName);
+ if (pEx->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C || pEx->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ SbieApi_Log(2224, L"%S (0x%08X) [%S]", Dll_ImageName, pEx->ExceptionRecord->ExceptionCode, Dll_BoxName);
BOOLEAN bSuccess = FALSE;
HANDLE hFile;
@@ -242,6 +245,9 @@ _FX int Dump_Init(void)
SBIEDLL_HOOK(Dump_, SetUnhandledExceptionFilter);
+ // Register Vectored Exception Handler
+ //AddVectoredExceptionHandler(0, Dump_CrashHandlerExceptionFilter);
+
//SbieApi_MonitorPutMsg(MONITOR_OTHER | MONITOR_TRACE, L"Minidump enabled", FALSE);
return 1;
}
\ No newline at end of file
diff --git a/Sandboxie/core/dll/file_copy.c b/Sandboxie/core/dll/file_copy.c
index f7b90da1..c726db94 100644
--- a/Sandboxie/core/dll/file_copy.c
+++ b/Sandboxie/core/dll/file_copy.c
@@ -51,6 +51,7 @@ static BOOLEAN File_MigrationDenyWrite = FALSE;
static ULONGLONG File_CopyLimitKb = (80 * 1024); // 80 MB
static BOOLEAN File_CopyLimitSilent = FALSE;
+static BOOLEAN File_NotifyNoCopy = FALSE;
//---------------------------------------------------------------------------
// File_InitFileMigration
@@ -76,10 +77,37 @@ _FX BOOLEAN File_InitFileMigration(void)
File_InitCopyLimit();
+ File_NotifyNoCopy = SbieApi_QueryConfBool(NULL, L"NotifyNoCopy", FALSE);
+
return TRUE;
}
+//---------------------------------------------------------------------------
+// File_MigrateFile_Message
+//---------------------------------------------------------------------------
+
+
+_FX VOID File_MigrateFile_Message(const WCHAR* TruePath, ULONGLONG file_size, int MsgID)
+{
+ const WCHAR* name = wcsrchr(TruePath, L'\\');
+ if (name)
+ ++name;
+ else
+ name = TruePath;
+
+ ULONG TruePathNameLen = wcslen(name);
+ WCHAR* text = Dll_AllocTemp(
+ (TruePathNameLen + 64) * sizeof(WCHAR));
+ Sbie_snwprintf(text, (TruePathNameLen + 64), L"%s [%s / %I64u]",
+ name, Dll_BoxName, file_size);
+
+ SbieApi_Log(MsgID, text);
+
+ Dll_Free(text);
+}
+
+
//---------------------------------------------------------------------------
// File_MigrateFile_GetMode
//---------------------------------------------------------------------------
@@ -121,8 +149,21 @@ found_match:
Dll_Free(path_lwr);
- if (mode != NUM_COPY_MODES)
+ if (mode != NUM_COPY_MODES) {
+
+ if (File_NotifyNoCopy) {
+ if (mode == FILE_DONT_COPY) {
+ if(File_MigrationDenyWrite)
+ File_MigrateFile_Message(TruePath, file_size, 2114);
+ else // else open read only
+ File_MigrateFile_Message(TruePath, file_size, 2115);
+ }
+ else if (mode == FILE_COPY_EMPTY)
+ File_MigrateFile_Message(TruePath, file_size, 2113);
+ }
+
return mode;
+ }
//
// if tere is no configuration for this file type/path decide based on the file size
@@ -162,23 +203,7 @@ found_match:
//
else if (!File_CopyLimitSilent)
- {
- const WCHAR* name = wcsrchr(TruePath, L'\\');
- if (name)
- ++name;
- else
- name = TruePath;
-
- ULONG TruePathNameLen = wcslen(name);
- WCHAR* text = Dll_AllocTemp(
- (TruePathNameLen + 64) * sizeof(WCHAR));
- Sbie_snwprintf(text, (TruePathNameLen + 64), L"%s [%s / %I64u]",
- name, Dll_BoxName, file_size);
-
- SbieApi_Log(2102, text);
-
- Dll_Free(text);
- }
+ File_MigrateFile_Message(TruePath, file_size, 2102);
return FILE_DONT_COPY;
}
diff --git a/Sandboxie/core/dll/key.c b/Sandboxie/core/dll/key.c
index d2a26e1b..c2988a85 100644
--- a/Sandboxie/core/dll/key.c
+++ b/Sandboxie/core/dll/key.c
@@ -81,10 +81,17 @@ static NTSTATUS Key_NtOpenKey(
ACCESS_MASK DesiredAccess,
OBJECT_ATTRIBUTES *ObjectAttributes);
+static NTSTATUS Key_NtOpenKeyTransacted(
+ HANDLE *KeyHandle,
+ ACCESS_MASK DesiredAccess,
+ OBJECT_ATTRIBUTES *ObjectAttributes,
+ HANDLE TransactionHandle);
+
static NTSTATUS Key_NtOpenKeyImpl(
HANDLE *KeyHandle,
ACCESS_MASK DesiredAccess,
- OBJECT_ATTRIBUTES *ObjectAttributes);
+ OBJECT_ATTRIBUTES *ObjectAttributes,
+ HANDLE TransactionHandle);
static NTSTATUS Key_NtOpenKeyEx(
HANDLE *KeyHandle,
@@ -92,6 +99,13 @@ static NTSTATUS Key_NtOpenKeyEx(
OBJECT_ATTRIBUTES *ObjectAttributes,
ULONG OpenOptions);
+static NTSTATUS Key_NtOpenKeyTransactedEx(
+ HANDLE *KeyHandle,
+ ACCESS_MASK DesiredAccess,
+ OBJECT_ATTRIBUTES *ObjectAttributes,
+ ULONG OpenOptions,
+ HANDLE TransactionHandle);
+
static NTSTATUS Key_NtCreateKey(
HANDLE *KeyHandle,
ACCESS_MASK DesiredAccess,
@@ -101,6 +115,16 @@ static NTSTATUS Key_NtCreateKey(
ULONG CreateOptions,
ULONG *Disposition);
+static NTSTATUS Key_NtCreateKeyTransacted(
+ PHANDLE KeyHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ ULONG TitleIndex,
+ PUNICODE_STRING Class,
+ ULONG CreateOptions,
+ HANDLE TransactionHandle,
+ PULONG Disposition);
+
static NTSTATUS Key_NtCreateKeyImpl(
HANDLE *KeyHandle,
ACCESS_MASK DesiredAccess,
@@ -108,7 +132,8 @@ static NTSTATUS Key_NtCreateKeyImpl(
ULONG TitleIndex,
UNICODE_STRING *Class,
ULONG CreateOptions,
- ULONG *Disposition);
+ ULONG *Disposition,
+ HANDLE TransactionHandle);
static NTSTATUS Key_CreatePath(
OBJECT_ATTRIBUTES *objattrs, PSECURITY_DESCRIPTOR *sd);
@@ -280,8 +305,11 @@ NTSTATUS File_NtCloseImpl(HANDLE FileHandle);
P_NtOpenKey __sys_NtOpenKey = NULL;
+static P_NtOpenKeyTransacted __sys_NtOpenKeyTransacted = NULL;
static P_NtOpenKeyEx __sys_NtOpenKeyEx = NULL;
+static P_NtOpenKeyTransactedEx __sys_NtOpenKeyTransactedEx = NULL;
static P_NtCreateKey __sys_NtCreateKey = NULL;
+static P_NtCreateKeyTransacted __sys_NtCreateKeyTransacted = NULL;
static P_NtDeleteKey __sys_NtDeleteKey = NULL;
static P_NtDeleteValueKey __sys_NtDeleteValueKey = NULL;
static P_NtSetValueKey __sys_NtSetValueKey = NULL;
@@ -428,6 +456,20 @@ _FX BOOLEAN Key_Init(void)
SBIEDLL_HOOK(Key_, NtOpenKeyEx);
}
+ void* NtOpenKeyTransacted = GetProcAddress(Dll_Ntdll, "NtOpenKeyTransacted");
+ if (NtOpenKeyTransacted) { // Windows vista
+ SBIEDLL_HOOK(Key_, NtOpenKeyTransacted);
+ }
+
+ void* NtOpenKeyTransactedEx = GetProcAddress(Dll_Ntdll, "NtOpenKeyTransactedEx");
+ if (NtOpenKeyTransactedEx) { // windows server 2008 R2
+ SBIEDLL_HOOK(Key_, NtOpenKeyTransactedEx);
+ }
+
+ void* NtCreateKeyTransacted = GetProcAddress(Dll_Ntdll, "NtCreateKeyTransacted");
+ if (NtCreateKeyTransacted) { // Windows vista
+ SBIEDLL_HOOK(Key_, NtCreateKeyTransacted);
+ }
SBIEDLL_HOOK(Key_, NtSaveKey);
@@ -1086,7 +1128,26 @@ _FX NTSTATUS Key_NtOpenKey(
ACCESS_MASK DesiredAccess,
OBJECT_ATTRIBUTES *ObjectAttributes)
{
- NTSTATUS status = Key_NtOpenKeyImpl(KeyHandle, DesiredAccess, ObjectAttributes);
+ NTSTATUS status = Key_NtOpenKeyImpl(KeyHandle, DesiredAccess, ObjectAttributes, NULL);
+
+ status = StopTailCallOptimization(status);
+
+ return status;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_NtOpenKeyTransacted
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS Key_NtOpenKeyTransacted(
+ HANDLE *KeyHandle,
+ ACCESS_MASK DesiredAccess,
+ OBJECT_ATTRIBUTES *ObjectAttributes,
+ HANDLE TransactionHandle)
+{
+ NTSTATUS status = Key_NtOpenKeyImpl(KeyHandle, DesiredAccess, ObjectAttributes, TransactionHandle);
status = StopTailCallOptimization(status);
@@ -1101,7 +1162,8 @@ _FX NTSTATUS Key_NtOpenKey(
_FX NTSTATUS Key_NtOpenKeyImpl(
HANDLE *KeyHandle,
ACCESS_MASK DesiredAccess,
- OBJECT_ATTRIBUTES *ObjectAttributes)
+ OBJECT_ATTRIBUTES *ObjectAttributes,
+ HANDLE TransactionHandle)
{
//
// use Key_NtCreateKey here so if anybody else intercepts
@@ -1109,7 +1171,7 @@ _FX NTSTATUS Key_NtOpenKeyImpl(
//
NTSTATUS status = Key_NtCreateKeyImpl(
- KeyHandle, DesiredAccess, ObjectAttributes, 0, NULL, tzuk, NULL);
+ KeyHandle, DesiredAccess, ObjectAttributes, 0, NULL, tzuk, NULL, TransactionHandle);
return status;
}
@@ -1134,7 +1196,36 @@ _FX NTSTATUS Key_NtOpenKeyEx(
}*/
status = Key_NtCreateKeyImpl(
- KeyHandle, DesiredAccess, ObjectAttributes, 0, NULL, tzuk, NULL);
+ KeyHandle, DesiredAccess, ObjectAttributes, 0, NULL, tzuk, NULL, NULL);
+
+ status = StopTailCallOptimization(status);
+
+ return status;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_NtOpenKeyTransactedEx
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS Key_NtOpenKeyTransactedEx(
+ HANDLE *KeyHandle,
+ ACCESS_MASK DesiredAccess,
+ OBJECT_ATTRIBUTES *ObjectAttributes,
+ ULONG OpenOptions,
+ HANDLE TransactionHandle)
+{
+ NTSTATUS status;
+
+ OpenOptions &= ~REG_OPTION_BACKUP_RESTORE;
+ /*if (OpenOptions) {
+ // probably REG_OPTION_OPEN_LINK
+ SbieApi_Log(2205, L"NtOpenKeyEx (%08X)", OpenOptions);
+ }*/
+
+ status = Key_NtCreateKeyImpl(
+ KeyHandle, DesiredAccess, ObjectAttributes, 0, NULL, tzuk, NULL, TransactionHandle);
status = StopTailCallOptimization(status);
@@ -1162,7 +1253,38 @@ _FX NTSTATUS Key_NtCreateKey(
TitleIndex,
Class,
CreateOptions,
- Disposition);
+ Disposition,
+ NULL);
+
+ status = StopTailCallOptimization(status);
+
+ return status;
+}
+
+
+//---------------------------------------------------------------------------
+// Key_NtCreateKeyTransacted
+//---------------------------------------------------------------------------
+
+
+NTSTATUS Key_NtCreateKeyTransacted(
+ PHANDLE KeyHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ ULONG TitleIndex,
+ PUNICODE_STRING Class,
+ ULONG CreateOptions,
+ HANDLE TransactionHandle,
+ PULONG Disposition)
+{
+ NTSTATUS status = Key_NtCreateKeyImpl( KeyHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ TitleIndex,
+ Class,
+ CreateOptions,
+ Disposition,
+ TransactionHandle);
status = StopTailCallOptimization(status);
@@ -1217,7 +1339,8 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
ULONG TitleIndex,
UNICODE_STRING *Class,
ULONG CreateOptions,
- ULONG *Disposition)
+ ULONG *Disposition,
+ HANDLE TransactionHandle)
{
ULONG LastError;
THREAD_DATA *TlsData = Dll_GetTlsData(&LastError);
@@ -1246,6 +1369,9 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
}
#endif
+#define __sys_NtCreateKeyX(kh, da, oa, ti, c, co, d) (TransactionHandle ? __sys_NtCreateKeyTransacted(kh, da, oa, ti, c, co, TransactionHandle, d) : __sys_NtCreateKey(kh, da, oa, ti, c, co, d))
+#define __sys_NtOpenKeyX(kh, da, oa) (TransactionHandle ? __sys_NtOpenKeyTransacted(kh, da, oa, TransactionHandle) : __sys_NtOpenKey(kh, da, oa))
+
//
// if this is a recursive invocation of NtCreateKey,
// then pass it as-is down the chain
@@ -1255,12 +1381,12 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
if (CreateOptions == tzuk) {
- return __sys_NtOpenKey(
+ return __sys_NtOpenKeyX(
KeyHandle, DesiredAccess, ObjectAttributes);
} else {
- return __sys_NtCreateKey(
+ return __sys_NtCreateKeyX(
KeyHandle, DesiredAccess, ObjectAttributes,
TitleIndex, Class, CreateOptions, Disposition);
}
@@ -1338,32 +1464,32 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
if (CreateOptions == tzuk) {
if(IsAKey)
- status = __sys_NtOpenKey(KeyHandle, DesiredAccess, ObjectAttributes);
+ status = __sys_NtOpenKeyX(KeyHandle, DesiredAccess, ObjectAttributes);
else
- status = __sys_NtOpenKey(KeyHandle, DesiredAccess, &objattrs);
+ status = __sys_NtOpenKeyX(KeyHandle, DesiredAccess, &objattrs);
if (status == STATUS_ACCESS_DENIED &&
DesiredAccess == MAXIMUM_ALLOWED) {
- status = __sys_NtOpenKey(
+ status = __sys_NtOpenKeyX(
KeyHandle, KEY_READ_WOW64, &objattrs);
}
} else {
if(IsAKey)
- status = __sys_NtCreateKey(
+ status = __sys_NtCreateKeyX(
KeyHandle, DesiredAccess, ObjectAttributes,
TitleIndex, Class, CreateOptions, Disposition);
else
- status = __sys_NtCreateKey(
+ status = __sys_NtCreateKeyX(
KeyHandle, DesiredAccess, &objattrs,
TitleIndex, Class, CreateOptions, Disposition);
if (status == STATUS_ACCESS_DENIED &&
DesiredAccess == MAXIMUM_ALLOWED) {
- status = __sys_NtCreateKey(
+ status = __sys_NtCreateKeyX(
KeyHandle, KEY_READ_WOW64, &objattrs,
TitleIndex, Class, CreateOptions, Disposition);
}
@@ -1434,14 +1560,14 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
if (CreateOptions == tzuk) {
- status = __sys_NtOpenKey(
+ status = __sys_NtOpenKeyX(
KeyHandle, DesiredAccess | KEY_READ, &objattrs);
} else {
CreateOptions &= ~REG_OPTION_BACKUP_RESTORE;
- status = __sys_NtCreateKey(
+ status = __sys_NtCreateKeyX(
KeyHandle, DesiredAccess | KEY_READ, &objattrs,
TitleIndex, Class, CreateOptions, Disposition);
@@ -1466,12 +1592,12 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
if (CreateOptions == tzuk) {
- status2 = __sys_NtOpenKey(
+ status2 = __sys_NtOpenKeyX(
KeyHandle, DesiredAccess | KEY_READ, &objattrs);
} else {
- status2 = __sys_NtCreateKey(
+ status2 = __sys_NtCreateKeyX(
KeyHandle, DesiredAccess | KEY_READ, &objattrs,
TitleIndex, Class, CreateOptions, Disposition);
@@ -1542,7 +1668,7 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
HANDLE handle;
RtlInitUnicodeString(&objname, TruePath);
- status = __sys_NtOpenKey(
+ status = __sys_NtOpenKeyX(
&handle, Wow64KeyReadAccess, &objattrs);
if (NT_SUCCESS(status)) {
@@ -1633,7 +1759,7 @@ _FX NTSTATUS Key_NtCreateKeyImpl(
// otherwise not write-only, so do normal NtOpenKey
//
- status = __sys_NtOpenKey(KeyHandle, Wow64KeyReadAccess, &objattrs);
+ status = __sys_NtOpenKeyX(KeyHandle, Wow64KeyReadAccess, &objattrs);
}
if (NT_SUCCESS(status)) {
@@ -1747,7 +1873,7 @@ SkipReadOnlyCheck:
// as described above in more detail
//
- status = __sys_NtOpenKey(KeyHandle, DesiredAccess, &objattrs);
+ status = __sys_NtOpenKeyX(KeyHandle, DesiredAccess, &objattrs);
if (NT_SUCCESS(status) && Disposition) {
@@ -1782,7 +1908,7 @@ SkipReadOnlyCheck:
status = Key_NtCreateKeyImpl(
KeyHandle, DesiredAccess, ObjectAttributes,
- TitleIndex, Class, CreateOptions, Disposition);
+ TitleIndex, Class, CreateOptions, Disposition, TransactionHandle);
if (status == STATUS_ACCESS_DENIED && CreateOptions != tzuk) {
@@ -1791,7 +1917,7 @@ SkipReadOnlyCheck:
// so try one more time using NtOpenKey
//
- status = __sys_NtOpenKey(
+ status = __sys_NtOpenKeyX(
KeyHandle, DesiredAccess, ObjectAttributes);
if (NT_SUCCESS(status)) TrueOpened = TRUE; // is that right?
@@ -1819,6 +1945,9 @@ SkipReadOnlyCheck:
Handle_SetRelocationPath(*KeyHandle, OriginalPath);
}
+#undef __sys_NtCreateKeyX
+#undef __sys_NtOpenKeyX
+
//
// finish
//
@@ -2268,7 +2397,7 @@ _FX NTSTATUS Key_NtDeleteKeyTreeImpl(HANDLE KeyHandle, BOOLEAN DeleteTree)
// open the key. this will create a copy key, if necessary
//
- status = Key_NtOpenKeyImpl(&handle, GENERIC_WRITE | KEY_READ | DELETE, &objattrs);
+ status = Key_NtOpenKeyImpl(&handle, GENERIC_WRITE | KEY_READ | DELETE, &objattrs, NULL);
if (! NT_SUCCESS(status))
__leave;
@@ -3241,7 +3370,7 @@ _FX NTSTATUS Key_NtEnumerateKey(
status = Key_NtOpenKeyImpl(&SubkeyHandle,
Key_GetWow64Flag(SubkeyPath, KEY_READ),
- &objattrs);
+ &objattrs, NULL);
}
}
@@ -4955,7 +5084,7 @@ _FX void Key_CreateBaseKeys()
//
InitializeObjectAttributes(
- &objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
+ &objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, Secure_NormalSD);
for (WCHAR** base_key = base_keys; *base_key; base_key++) {
@@ -4964,6 +5093,6 @@ _FX void Key_CreateBaseKeys()
RtlInitUnicodeString(&objname, buff);
- Key_CreatePath(&objattrs, NULL);
+ Key_CreatePath(&objattrs, Secure_EveryoWneSD);
}
}
diff --git a/Sandboxie/core/dll/ldr.c b/Sandboxie/core/dll/ldr.c
index fd22a240..2fa46b27 100644
--- a/Sandboxie/core/dll/ldr.c
+++ b/Sandboxie/core/dll/ldr.c
@@ -493,6 +493,16 @@ _FX BOOLEAN Ldr_Init()
LdrCheckImmersive();
}
+
+ //
+ // set PEB.ProcessParameters->LoaderThreads = 0
+ //
+
+ if (SbieApi_QueryConfBool(NULL, L"NoParallelLoading", FALSE)) {
+ RTL_USER_PROCESS_PARAMETERS* ProcessParms = Proc_GetRtlUserProcessParameters();
+ ProcessParms->LoaderThreads = 0;
+ }
+
//
// do some more initializations based on the executable image,
// and inject code at the program entrypoint
@@ -782,6 +792,38 @@ _FX void Ldr_CallDllCallbacks_WithLock(void)
}
+//---------------------------------------------------------------------------
+// Ldr_LdrLoadDllImpl
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS Ldr_LdrLoadDllImpl(
+ WCHAR* PathString,
+ ULONG* DllFlags,
+ UNICODE_STRING* ModuleName,
+ HANDLE* ModuleHandle)
+{
+ NTSTATUS status = 0;
+
+ //WCHAR text[4096];
+ //Sbie_snwprintf(text, ARRAYSIZE(text), L"%s (loading...)", (ModuleName && ModuleName->Buffer) ? ModuleName->Buffer : PathString);
+ //SbieApi_MonitorPutMsg(MONITOR_IMAGE, text);
+
+ status = __sys_LdrLoadDll(PathString, DllFlags, ModuleName, ModuleHandle);
+
+ if (!NT_SUCCESS(status)) {
+ WCHAR text[4096];
+ Sbie_snwprintf(text, ARRAYSIZE(text), L"%s (load failed 0x%08X)", (ModuleName && ModuleName->Buffer) ? ModuleName->Buffer : PathString, status);
+ SbieApi_MonitorPutMsg(MONITOR_IMAGE, text);
+ }
+
+ //Sbie_snwprintf(text, ARRAYSIZE(text), L"%s (... 0x%08X)", (ModuleName && ModuleName->Buffer) ? ModuleName->Buffer : PathString, status);
+ //SbieApi_MonitorPutMsg(MONITOR_IMAGE, text);
+
+ return status;
+}
+
+
//---------------------------------------------------------------------------
// Ldr_LdrLoadDll
//---------------------------------------------------------------------------
@@ -804,7 +846,7 @@ _FX NTSTATUS Ldr_LdrLoadDll(
status = __sys_LdrLockLoaderLock(0, &state, &LdrCookie);
if (NT_SUCCESS(status)) {
- status = __sys_LdrLoadDll(PathString, DllFlags, ModuleName, ModuleHandle);
+ status = Ldr_LdrLoadDllImpl(PathString, DllFlags, ModuleName, ModuleHandle);
if (NT_SUCCESS(status)) {
Ldr_CallDllCallbacks();
@@ -833,7 +875,7 @@ _FX NTSTATUS Ldr_Win10_LdrLoadDll(
//
NTSTATUS status = 0;
- status = __sys_LdrLoadDll(PathString, DllFlags, ModuleName, ModuleHandle);
+ status = Ldr_LdrLoadDllImpl(PathString, DllFlags, ModuleName, ModuleHandle);
Scm_SecHostDll_W8();
return status;
}
diff --git a/Sandboxie/core/dll/ldr_init.c b/Sandboxie/core/dll/ldr_init.c
index 74e91f1d..03350976 100644
--- a/Sandboxie/core/dll/ldr_init.c
+++ b/Sandboxie/core/dll/ldr_init.c
@@ -35,7 +35,8 @@
#define LDR_INJECT_SETTING_NAME L"InjectDllARM64"
#define LDR_HOST_INJECT_SETTING_NAME L"HostInjectDllARM64"
-#define LDR_INJECT_NUM_SAVE_BYTES 16
+//#define LDR_INJECT_NUM_SAVE_BYTES 16
+#define LDR_INJECT_NUM_SAVE_BYTES 20
#elif _WIN64
@@ -43,7 +44,8 @@
#define LDR_INJECT_SETTING_NAME L"InjectDll64"
#define LDR_HOST_INJECT_SETTING_NAME L"HostInjectDll64"
-#define LDR_INJECT_NUM_SAVE_BYTES 12
+//#define LDR_INJECT_NUM_SAVE_BYTES 12
+#define LDR_INJECT_NUM_SAVE_BYTES 19
#else ! _WIN64
@@ -757,8 +759,9 @@ _FX void Ldr_Inject_Init(BOOLEAN bHostInject)
#ifdef _M_ARM64
ULONG* aCode = (ULONG*)entrypoint;
+ *aCode++ = 0x10000000; // adr x0, 0 - copy pc to x0
*aCode++ = 0x58000048; // ldr x8, 8
- *aCode++ = 0xD63F0100; // blr x8
+ *aCode++ = 0xD61F0100; // br x8
*(ULONG_PTR*)aCode = (ULONG_PTR)Ldr_Inject_Entry64;
NtFlushInstructionCache(GetCurrentProcess(), entrypoint, LDR_INJECT_NUM_SAVE_BYTES);
@@ -768,8 +771,14 @@ _FX void Ldr_Inject_Init(BOOLEAN bHostInject)
entrypoint[0] = 0x48; // mov rax, Ldr_Inject_Entry64
entrypoint[1] = 0xB8;
*(ULONG_PTR *)(entrypoint + 2) = (ULONG_PTR)Ldr_Inject_Entry64;
- entrypoint[10] = 0xFF; // call rax
- entrypoint[11] = 0xD0;
+
+ entrypoint[10] = 0x48; // lea rcx, [rip - 0x11]
+ entrypoint[11] = 0x8d;
+ entrypoint[12] = 0x0d;
+ *(ULONG*)(entrypoint + 13) = -0x11;
+
+ entrypoint[17] = 0xFF; // jmp rax
+ entrypoint[18] = 0xE0;
#else ! _WIN64
@@ -788,7 +797,7 @@ _FX void Ldr_Inject_Init(BOOLEAN bHostInject)
//---------------------------------------------------------------------------
-_FX void Ldr_Inject_Entry(ULONG_PTR *pRetAddr)
+_FX void* Ldr_Inject_Entry(ULONG_PTR *pPtr)
{
UCHAR *entrypoint;
ULONG dummy_prot;
@@ -797,12 +806,12 @@ _FX void Ldr_Inject_Entry(ULONG_PTR *pRetAddr)
// restore correct code sequence at the entrypoint
//
-#ifdef _M_ARM64
- entrypoint = ((UCHAR *)*pRetAddr) - (LDR_INJECT_NUM_SAVE_BYTES - sizeof(ULONG_PTR)); // after blr comes the 64bit address
+#ifdef _WIN64
+ entrypoint = (UCHAR*)pPtr;
#else
- entrypoint = ((UCHAR *)*pRetAddr) - LDR_INJECT_NUM_SAVE_BYTES;
+ entrypoint = ((UCHAR *)*pPtr) - LDR_INJECT_NUM_SAVE_BYTES;
+ *pPtr = (ULONG_PTR)entrypoint;
#endif
- *pRetAddr = (ULONG_PTR)entrypoint;
// If entrypoint hook is different, need to adjust offset. Copying the original byets won't have the correct offset.
// MS UEV also hooks exe entry.
@@ -853,4 +862,6 @@ _FX void Ldr_Inject_Entry(ULONG_PTR *pRetAddr)
{
Ldr_LoadInjectDlls(g_bHostInject);
}
+
+ return entrypoint;
}
diff --git a/Sandboxie/core/dll/util_64.asm b/Sandboxie/core/dll/util_64.asm
index 4e801b12..ac85143f 100644
--- a/Sandboxie/core/dll/util_64.asm
+++ b/Sandboxie/core/dll/util_64.asm
@@ -139,15 +139,10 @@ EXTERN Ldr_Inject_Entry : PROC
Ldr_Inject_Entry64 PROC
- ;
- ; Normally we would start with sub rsp,8+(4*8) but in this case
- ; we know the caller has not aligned the stack correctly
- ;
-
- sub rsp,8+8+(4*8)
- lea rcx,[rsp+8+8+(4*8)] ; setup pRetAddr parameter
+ sub rsp,8+(4*8)
call Ldr_Inject_Entry
- add rsp,8+8+(4*8)
+ mov rdx, rax
+ add rsp,8+(4*8)
;
; clear the stack of any leftovers from Ldr_Inject_Entry.
@@ -162,7 +157,7 @@ Ldr_Inject_Entry64 PROC
cld
rep stosq
- ret
+ jmp rdx
Ldr_Inject_Entry64 ENDP
@@ -171,9 +166,7 @@ Ldr_Inject_Entry64 ENDP
; Gui_FixupCallbackPointers
;----------------------------------------------------------------------------
- nop
- nop
- nop
+
Gui_FixupCallbackPointers PROC
;
diff --git a/Sandboxie/core/dll/util_arm.asm b/Sandboxie/core/dll/util_arm.asm
index a83fe853..2860c53d 100644
--- a/Sandboxie/core/dll/util_arm.asm
+++ b/Sandboxie/core/dll/util_arm.asm
@@ -149,11 +149,10 @@ l02
Ldr_Inject_Entry64 PROC
stp fp, lr, [sp, #-0x10]! ; push
- add x0, sp, 0x8 ; pRetAddr parameter
ldr x8, =Ldr_Inject_Entry
blr x8
ldp fp, lr, [sp], #0x10 ; pop
- ret
+ br x0
ENDP
diff --git a/Sandboxie/core/low/init.c b/Sandboxie/core/low/init.c
index 6385d681..09711ec2 100644
--- a/Sandboxie/core/low/init.c
+++ b/Sandboxie/core/low/init.c
@@ -152,7 +152,6 @@ _FX NTSTATUS SbieApi_Ioctl(SBIELOW_DATA *data, void *parms)
//---------------------------------------------------------------------------
-#if 1
_FX NTSTATUS SbieApi_DebugPrint(SBIELOW_DATA *data, const WCHAR *text)
{
NTSTATUS status = 0;
@@ -171,13 +170,34 @@ _FX NTSTATUS SbieApi_DebugPrint(SBIELOW_DATA *data, const WCHAR *text)
memzero(parms, sizeof(parms));
args->func_code = API_LOG_MESSAGE;
args->session_id.val = -1;
- args->msgid.val = 2101;
+ args->msgid.val = 1122;
args->msgtext.val = &msgtext;
status = SbieApi_Ioctl(data, parms);
return status;
}
-#endif
+
+
+//---------------------------------------------------------------------------
+// SbieApi_DebugError
+//---------------------------------------------------------------------------
+
+
+_FX NTSTATUS SbieApi_DebugError(SBIELOW_DATA* data, ULONG error)
+{
+ // Note: A normal string like L"text" would not resultin position independent code !!!
+ // hence we create a string array and fill it byte by byte
+
+ wchar_t text[] = { 'L','o','w','L','e','v','e','l',' ','E','r','r','o','r',':',' ','0','x',0,0,0,0,0,0,0,0,0,0};
+
+ // covert ulong to hex string and copy it into the message array
+ wchar_t* ptr = &text[18]; // point after L"...0x"
+ wchar_t table[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
+ for(int i=28; i >= 0; i-=4)
+ *ptr++ = table[(error >> i) & 0xF];
+
+ return SbieApi_DebugPrint(data, text);
+}
//---------------------------------------------------------------------------
@@ -724,6 +744,9 @@ ULONG_PTR EntrypointC(SBIELOW_DATA *data, void *DetourCode, void *SystemService)
// WaitForDebugger(data);
+ //wchar_t text[] = { 't','e','s','t',0 };
+ //SbieApi_DebugPrint(data, text);
+
PrepSyscalls(data, SystemService);
if (!data->flags.bHostInject && !data->flags.bNoSysHooks)
InitSyscalls(data, SystemService);
diff --git a/Sandboxie/core/low/inject.c b/Sandboxie/core/low/inject.c
index 69ee9ccd..d5d1bb93 100644
--- a/Sandboxie/core/low/inject.c
+++ b/Sandboxie/core/low/inject.c
@@ -34,11 +34,12 @@ typedef long NTSTATUS;
// Functions
//---------------------------------------------------------------------------
+_FX NTSTATUS SbieApi_DebugError(SBIELOW_DATA* data, ULONG error);
-UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName);
+UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName, ULONG *pErr);
static UCHAR *FindDllExport2(
- void *DllBase, IMAGE_DATA_DIRECTORY *dir0, const UCHAR *ProcName);
+ void *DllBase, IMAGE_DATA_DIRECTORY *dir0, const UCHAR *ProcName, ULONG *pErr);
#ifdef _M_ARM64
void* Hook_GetFFSTarget(UCHAR* SourceFunc);
@@ -57,7 +58,7 @@ static void InitInjectWow64(SBIELOW_DATA *data);
//---------------------------------------------------------------------------
-_FX UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName)
+_FX UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName, ULONG* pErr)
{
IMAGE_DOS_HEADER *dos_hdr;
IMAGE_NT_HEADERS *nt_hdrs;
@@ -68,11 +69,15 @@ _FX UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName)
//
dos_hdr = (void *)DllBase;
- if (dos_hdr->e_magic != 'MZ' && dos_hdr->e_magic != 'ZM')
+ if (dos_hdr->e_magic != 'MZ' && dos_hdr->e_magic != 'ZM') {
+ *pErr = 0xa;
return NULL;
+ }
nt_hdrs = (IMAGE_NT_HEADERS *)((UCHAR *)dos_hdr + dos_hdr->e_lfanew);
- if (nt_hdrs->Signature != IMAGE_NT_SIGNATURE) // 'PE\0\0'
+ if (nt_hdrs->Signature != IMAGE_NT_SIGNATURE) { // 'PE\0\0'
+ *pErr = 0xb;
return NULL;
+ }
if (nt_hdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
@@ -83,7 +88,7 @@ _FX UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName)
if (opt_hdr_32->NumberOfRvaAndSizes) {
IMAGE_DATA_DIRECTORY *dir0 = &opt_hdr_32->DataDirectory[0];
- func_ptr = FindDllExport2(DllBase, dir0, ProcName);
+ func_ptr = FindDllExport2(DllBase, dir0, ProcName, pErr);
}
}
@@ -99,7 +104,7 @@ _FX UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName)
if (opt_hdr_64->NumberOfRvaAndSizes) {
IMAGE_DATA_DIRECTORY *dir0 = &opt_hdr_64->DataDirectory[0];
- func_ptr = FindDllExport2(DllBase, dir0, ProcName);
+ func_ptr = FindDllExport2(DllBase, dir0, ProcName, pErr);
}
}
@@ -115,7 +120,7 @@ _FX UCHAR *FindDllExport(void *DllBase, const UCHAR *ProcName)
_FX UCHAR *FindDllExport2(
- void *DllBase, IMAGE_DATA_DIRECTORY *dir0, const UCHAR *ProcName)
+ void *DllBase, IMAGE_DATA_DIRECTORY *dir0, const UCHAR *ProcName, ULONG* pErr)
{
void *proc = NULL;
ULONG i, j, n;
@@ -163,6 +168,7 @@ _FX UCHAR *FindDllExport2(
// might have to scan LDR tables to find the target dll
//
+ *pErr = 0xc;
proc = NULL;
}
}
@@ -214,6 +220,7 @@ _FX void InitInject(SBIELOW_DATA *data, void *DetourCode)
void *RegionBase;
SIZE_T RegionSize;
ULONG OldProtect;
+ ULONG uError = 0;
//
// now that syscalls were intercepted, we can use the top of the syscall
@@ -278,23 +285,35 @@ _FX void InitInject(SBIELOW_DATA *data, void *DetourCode)
//
LdrCode = FindDllExport(ntdll_base,
- (UCHAR *)extra + extra->LdrLoadDll_offset);
+ (UCHAR *)extra + extra->LdrLoadDll_offset, &uError);
+ if (!LdrCode) {
+ SbieApi_DebugError(data, (0x01 << 4) | uError);
+ return;
+ }
#ifdef _M_ARM64
- if (data->flags.is_arm64ec && LdrCode)
+ if (data->flags.is_arm64ec)
LdrCode = Hook_GetFFSTarget(LdrCode);
#endif
- if (! LdrCode)
+ if (!LdrCode) {
+ SbieApi_DebugError(data, 0x01d);
return;
+ }
inject->LdrLoadDll = (ULONG_PTR)LdrCode;
LdrCode = FindDllExport(ntdll_base,
- (UCHAR *)extra + extra->LdrGetProcAddr_offset);
+ (UCHAR *)extra + extra->LdrGetProcAddr_offset, &uError);
+ if (!LdrCode) {
+ SbieApi_DebugError(data, (0x02 << 4) | uError);
+ return;
+ }
#ifdef _M_ARM64
- if (data->flags.is_arm64ec && LdrCode)
+ if (data->flags.is_arm64ec)
LdrCode = Hook_GetFFSTarget(LdrCode);
#endif
- if (! LdrCode)
+ if (!LdrCode) {
+ SbieApi_DebugError(data, 0x02d);
return;
+ }
inject->LdrGetProcAddr = (ULONG_PTR)LdrCode;
#ifdef _M_ARM64
@@ -311,9 +330,11 @@ _FX void InitInject(SBIELOW_DATA *data, void *DetourCode)
#ifdef _WIN64
if (data->flags.is_wow64) {
LdrCode = FindDllExport(ntdll_base,
- (UCHAR*)extra + extra->NtRaiseHardError_offset);
- if (!LdrCode)
+ (UCHAR*)extra + extra->NtRaiseHardError_offset, &uError);
+ if (!LdrCode) {
+ SbieApi_DebugError(data, (0x03 << 4) | uError);
return;
+ }
inject->NtRaiseHardError = (ULONG_PTR)LdrCode;
}
else
@@ -339,9 +360,11 @@ _FX void InitInject(SBIELOW_DATA *data, void *DetourCode)
#endif
{
LdrCode = FindDllExport(ntdll_base,
- (UCHAR *)extra + extra->RtlFindActCtx_offset);
- if (! LdrCode)
+ (UCHAR *)extra + extra->RtlFindActCtx_offset, &uError);
+ if (!LdrCode) {
+ SbieApi_DebugError(data, (0x04 << 4) | uError);
return;
+ }
}
inject->RtlFindActCtx = (ULONG_PTR)LdrCode;
diff --git a/SandboxiePlus/MiscHelpers/Common/DebugHelpers.cpp b/SandboxiePlus/MiscHelpers/Common/DebugHelpers.cpp
index 25b9e441..a2bc207f 100644
--- a/SandboxiePlus/MiscHelpers/Common/DebugHelpers.cpp
+++ b/SandboxiePlus/MiscHelpers/Common/DebugHelpers.cpp
@@ -212,6 +212,9 @@ static LONG __stdcall MyCrashHandlerExceptionFilter(EXCEPTION_POINTERS* pEx)
#endif
bool bSuccess = false;
+ if (pEx->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C || pEx->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
+ return EXCEPTION_CONTINUE_SEARCH;
+
wchar_t szMiniDumpFileName[128];
wsprintf(szMiniDumpFileName, L"%s %s.dmp", s_szMiniDumpName, QDateTime::currentDateTime().toString("dd.MM.yyyy hh-mm-ss,zzz").replace(QRegularExpression("[:*?<>|\"\\/]"), "_").toStdWString().c_str());
@@ -286,6 +289,9 @@ void InitMiniDumpWriter(const wchar_t* Name, const wchar_t* Path)
// Additional call "PreventSetUnhandledExceptionFilter"...
// See also: "SetUnhandledExceptionFilter" and VC8 (and later)
// http://blog.kalmbachnet.de/?postid=75
+
+ // Register Vectored Exception Handler
+ AddVectoredExceptionHandler(0, MyCrashHandlerExceptionFilter);
}
diff --git a/SandboxiePlus/QSbieAPI/SbieUtils.cpp b/SandboxiePlus/QSbieAPI/SbieUtils.cpp
index 935ffff6..1dc41263 100644
--- a/SandboxiePlus/QSbieAPI/SbieUtils.cpp
+++ b/SandboxiePlus/QSbieAPI/SbieUtils.cpp
@@ -242,6 +242,93 @@ CSbieProgressPtr CSbieUtils::RunCommand(const QString& Command, bool noGui)
return pProgress;
}
+int CSbieUtils::ExecCommand(const QString& Command, bool noGui, quint32 Timeout)
+{
+ STARTUPINFOW si = { 0 };
+ si.cb = sizeof(si);
+ if (noGui) {
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.wShowWindow = SW_HIDE;
+ }
+
+ PROCESS_INFORMATION pi = { 0 };
+ if (!CreateProcessW(NULL, (LPWSTR)Command.toStdWString().c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
+ return -1;
+
+ int iRet = -2;
+ if (WaitForSingleObject(pi.hProcess, (DWORD)Timeout) == WAIT_OBJECT_0)
+ {
+ DWORD dwRet;
+ if (GetExitCodeProcess(pi.hProcess, &dwRet))
+ iRet = (int)dwRet;
+ }
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ return iRet;
+}
+
+int CSbieUtils::ExecCommandEx(const QString& Command, QString* pOutput, quint32 Timeout)
+{
+ HANDLE stdoutReadHandle;
+ HANDLE stdoutWriteHandle;
+ SECURITY_ATTRIBUTES saAttr;
+ // Set the bInheritHandle flag so pipe handles are inherited.
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = nullptr;
+ // Create a pipe for the child process's STDOUT.
+ if (!CreatePipe(&stdoutReadHandle, &stdoutWriteHandle, &saAttr, 0))
+ return -4;
+ if (!SetHandleInformation(stdoutReadHandle, HANDLE_FLAG_INHERIT, 0))
+ return -4;
+
+ STARTUPINFOW si = { 0 };
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.hStdOutput = stdoutWriteHandle;
+ si.hStdError = stdoutWriteHandle;
+ si.wShowWindow = SW_HIDE;
+
+ PROCESS_INFORMATION pi = { 0 };
+ if (!CreateProcessW(NULL, (LPWSTR)Command.toStdWString().c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
+ return -1;
+
+ DWORD exitCode, dataSize;
+ do
+ {
+ // Check if the process is alive.
+ GetExitCodeProcess(pi.hProcess, &exitCode);
+
+ // Check if there is anything in the pipe.
+ if (!PeekNamedPipe(stdoutReadHandle, nullptr, 0, nullptr, &dataSize, nullptr))
+ return -3;
+ if (dataSize == 0)
+ Sleep(10);
+ else {
+ // Read the data out of the pipe.
+ CHAR buffer[4096] = { 0 };
+ if (!ReadFile(stdoutReadHandle, buffer, sizeof(buffer) - 1, &dataSize, nullptr))
+ return -3;
+
+ pOutput->append(QString(buffer));
+ }
+ } while (exitCode == STILL_ACTIVE || dataSize != 0);
+
+ CloseHandle(stdoutReadHandle);
+ CloseHandle(stdoutWriteHandle);
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ return (int)exitCode;
+}
+
//////////////////////////////////////////////////////////////////////////////
// Shell integration
diff --git a/SandboxiePlus/QSbieAPI/SbieUtils.h b/SandboxiePlus/QSbieAPI/SbieUtils.h
index b33a18e7..01dfca88 100644
--- a/SandboxiePlus/QSbieAPI/SbieUtils.h
+++ b/SandboxiePlus/QSbieAPI/SbieUtils.h
@@ -39,6 +39,9 @@ public:
static CSbieProgressPtr RunCommand(const QString& Command, bool noGui = false);
+ static int ExecCommand(const QString& Command, bool noGui = false, quint32 Timeout = -1);
+ static int ExecCommandEx(const QString& Command, QString* pOutput, quint32 Timeout = -1);
+
private:
static SB_RESULT(void*) ElevateOps(const QStringList& Ops);
static SB_STATUS ExecOps(const QStringList& Ops);
diff --git a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui
index ec0c8f77..e93ef0d0 100644
--- a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui
+++ b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui
@@ -281,41 +281,48 @@
-
+
-
+
+
+ Warn when an application opens a harddrive handle
+
+
+
-
-
+
- Auto delete content when last sandboxed process terminates
+ Protect this sandbox from deletion or emptying
- -
-
-
-
- 75
- true
- true
-
-
+
-
+
- File Migration
+ Allow elevated sandboxed applications to read the harddrive
- -
-
-
- Qt::Vertical
-
-
+
-
+
+
20
- 40
+ 16777215
-
+
+
+
+
- -
+
-
+
+
+ Use volume serial numbers for drives, like: \drive\C~1234-ABCD
+
+
+
+ -
@@ -342,31 +349,21 @@
- -
-
+
-
+
- kilobytes
+ The box structure can only be changed when the sandbox is empty
- -
-
+
-
+
- Prompt user for large file migration
+ Allow sandboxed processes to open files protected by EFS
- -
-
-
- Separate user folders
-
-
- false
-
-
-
- -
+
-
@@ -376,65 +373,21 @@
- Raw Disk access
+ Disk/File access
- -
-
-
-
- 75
- 16777215
-
-
-
-
- -
-
+
-
+
- Issue message 2102 when a file is too large
+ Virtualization scheme
- -
-
-
-
- 20
- 16777215
-
-
+
-
+
-
-
-
-
- -
-
-
- Allow elevated sandboxed applications to read the harddrive
-
-
-
- -
-
-
- Warn when an application opens a harddrive handle
-
-
-
- -
-
-
- Copy file size limit:
-
-
-
- -
-
-
- Protect this sandbox from deletion or emptying
+ Auto delete content when last sandboxed process terminates
@@ -452,6 +405,212 @@
+ -
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Separate user folders
+
+
+ false
+
+
+
+
+
+
+
+
+
+ File Migration
+
+
+
+ 3
+
+
+ 3
+
+
+ 6
+
+
+ 3
+
+ -
+
+
-
+
+
+ Copy file size limit:
+
+
+
+ -
+
+
+ Prompt user for large file migration
+
+
+
+ -
+
+
+
+ 75
+ true
+ true
+
+
+
+ File Migration
+
+
+
+ -
+
+
+ 2113: Content of migrated file was discarded
+2114: File was not migrated, write access to file was denied
+2115: File was not migrated, file will be opened read only
+
+
+ Issue message 2113/2114/2115 when a file is not fully migrated
+
+
+
+ -
+
+
+
+ 100
+ 16777215
+
+
+
+
+ -
+
+
+ kilobytes
+
+
+
+ -
+
+
+ Add Pattern
+
+
+
+ -
+
+
+ Remove Pattern
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Show Templates
+
+
+
+ -
+
+
+ true
+
+
+
+ Action
+
+
+
+
+ Program
+
+
+
+
+ Pattern
+
+
+
+
+ -
+
+
+ Sandboxie does not allow writing to host files, unless permitted by the user. When a sandboxed application attempts to modify a file, the entire file must be copied into the sandbox, for large files this can take a significate amount of time. Sandboxie offers options for handling these cases, which can be configured on this page.
+
+
+ true
+
+
+
+ -
+
+
+ Using wildcard patterns file specific behavior can be configured in the list below:
+
+
+
+ -
+
+
+ Issue message 2102 when a file is too large
+
+
+
+ -
+
+
+ When a file cannot be migrated, open it in read-only mode instead
+
+
+
@@ -4375,8 +4534,6 @@ Please note that this values are currently user specific and saved globally for
treeRun
btnAddCmd
btnDelCmd
- chkCopyLimit
- chkNoCopyWarn
chkAutoEmpty
chkProtectBox
treeTriggers
diff --git a/SandboxiePlus/SandMan/Forms/SettingsWindow.ui b/SandboxiePlus/SandMan/Forms/SettingsWindow.ui
index 8a5578c4..d9d6f4a7 100644
--- a/SandboxiePlus/SandMan/Forms/SettingsWindow.ui
+++ b/SandboxiePlus/SandMan/Forms/SettingsWindow.ui
@@ -115,6 +115,7 @@
+ 75
true
true
@@ -151,6 +152,7 @@
+ 75
true
true
@@ -213,6 +215,7 @@
+ 75
true
true
@@ -305,6 +308,7 @@
+ 75
true
true
@@ -328,6 +332,7 @@
+ 75
true
true
@@ -354,6 +359,7 @@
+ 75
true
true
@@ -541,6 +547,7 @@
+ 75
true
true
@@ -738,14 +745,20 @@
-
-
-
-
-
- Portable root folder
+
-
+
+
+ Qt::Horizontal
-
+
+
+ 40
+ 20
+
+
+
- -
+
-
Qt::Horizontal
@@ -758,52 +771,13 @@
- -
-
-
-
- true
- true
-
-
-
- Sandboxing features
-
-
-
-
-
+
- Use Windows Filtering Platform to restrict network access
+ Activate Kernel Mode Object Filtering
- -
-
-
- Sandbox <a href="sbie://docs/ipcrootpath">ipc root</a>:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- true
-
-
-
- -
-
-
- -
-
-
- Separate user folders
-
-
-
- -
-
-
-
@@ -817,18 +791,25 @@
- -
-
-
- Qt::Vertical
+
-
+
+
+ Use a Sandboxie login instead of an anonymous token (experimental)
-
-
- 20
- 40
-
+
+
+ -
+
+
+ Use Windows Filtering Platform to restrict network access
-
+
+
+ -
+
+
+ -
+
-
@@ -843,10 +824,24 @@
- -
-
+
-
+
+
+
+ 75
+ true
+ true
+
+
- Sandbox <a href="sbie://docs/keyrootpath">registry root</a>:
+ Sandboxing features
+
+
+
+ -
+
+
+ Sandbox <a href="sbie://docs/ipcrootpath">ipc root</a>:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -856,69 +851,6 @@
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Hook selected Win32k system calls to enable GPU acceleration (experimental)
-
-
-
- -
-
-
- Use a Sandboxie login instead of an anonymous token (experimental)
-
-
-
- -
-
-
-
- true
- true
-
-
-
- Sandbox default
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- -
-
-
- Activate Kernel Mode Object Filtering
-
-
-
-
@@ -929,8 +861,91 @@
- -
-
+
-
+
+
+ Sandbox <a href="sbie://docs/keyrootpath">registry root</a>:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+ -
+
+
+ -
+
+
+ Hook selected Win32k system calls to enable GPU acceleration (experimental)
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 75
+ true
+ true
+
+
+
+ Sandbox default
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Portable root folder
+
+
@@ -974,6 +989,7 @@
+ 75
true
true
@@ -1244,6 +1260,7 @@
+ 75
true
true
@@ -1336,6 +1353,7 @@
+ 75
true
true
@@ -1488,8 +1506,6 @@
chkSandboxUrls
fileRoot
btnBrowse
- chkSeparateUserFolders
- chkAutoRoot
regRoot
ipcRoot
chkStartBlock
diff --git a/SandboxiePlus/SandMan/OnlineUpdater.cpp b/SandboxiePlus/SandMan/OnlineUpdater.cpp
index c07be493..87c9fb80 100644
--- a/SandboxiePlus/SandMan/OnlineUpdater.cpp
+++ b/SandboxiePlus/SandMan/OnlineUpdater.cpp
@@ -937,11 +937,11 @@ bool COnlineUpdater::IsVersionNewer(const QString& VersionStr)
/////////////////////////////////////////////////////////////////////////////////////////////////
// cert stuf
-void COnlineUpdater::UpdateCert()
+void COnlineUpdater::UpdateCert(bool bWait)
{
QString UpdateKey; // for now only patreons can update the cert automatically
TArguments args = GetArguments(g_Certificate, L'\n', L':');
- if(args.value("TYPE").indexOf("PATREON") == 0)
+ if(args.value("TYPE").contains("PATREON"))
UpdateKey = args.value("UPDATEKEY");
if (UpdateKey.isEmpty()) {
theGUI->OpenUrl("https://sandboxie-plus.com/go.php?to=sbie-get-cert");
@@ -971,6 +971,12 @@ void COnlineUpdater::UpdateCert()
//Request.setRawHeader("Accept-Encoding", "gzip");
QNetworkReply* pReply = m_RequestManager->get(Request);
connect(pReply, SIGNAL(finished()), this, SLOT(OnCertCheck()));
+
+ if (bWait) {
+ while (!pReply->isFinished()) {
+ QCoreApplication::processEvents(); // keep UI responsive
+ }
+ }
}
void COnlineUpdater::OnCertCheck()
diff --git a/SandboxiePlus/SandMan/OnlineUpdater.h b/SandboxiePlus/SandMan/OnlineUpdater.h
index cd87183a..6161833a 100644
--- a/SandboxiePlus/SandMan/OnlineUpdater.h
+++ b/SandboxiePlus/SandMan/OnlineUpdater.h
@@ -32,7 +32,7 @@ public:
void GetUpdates(QObject* receiver, const char* member, const QVariantMap& Params = QVariantMap());
- void UpdateCert();
+ void UpdateCert(bool bWait = false);
void CheckForUpdates(bool bManual = false);
diff --git a/SandboxiePlus/SandMan/SandManRecovery.cpp b/SandboxiePlus/SandMan/SandManRecovery.cpp
index 5f22ef2a..783d46f3 100644
--- a/SandboxiePlus/SandMan/SandManRecovery.cpp
+++ b/SandboxiePlus/SandMan/SandManRecovery.cpp
@@ -70,27 +70,129 @@ CRecoveryWindow* CSandMan::ShowRecovery(const CSandBoxPtr& pBox, bool bFind)
return pBoxEx->m_pRecoveryWnd;
}
-SB_PROGRESS CSandMan::RecoverFiles(const QString& BoxName, const QList>& FileList, int Action)
+SB_PROGRESS CSandMan::CheckFiles(const QString& BoxName, const QStringList& Files)
{
CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
- QtConcurrent::run(CSandMan::RecoverFilesAsync, pProgress, BoxName, FileList, Action);
+ CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
+ QStringList Checkers;
+ if (!pBox.isNull()) {
+ foreach(const QString & Value, pBox->GetTextList("OnFileRecovery", true, false, true)) {
+ Checkers.append(pBox->Expand(Value));
+ }
+ }
+ QtConcurrent::run(CSandMan::CheckFilesAsync, pProgress, BoxName, Files, Checkers);
return SB_PROGRESS(OP_ASYNC, pProgress);
}
-void CSandMan::RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QString& BoxName, const QList>& FileList, int Action)
+void CSandMan::CheckFilesAsync(const CSbieProgressPtr& pProgress, const QString& BoxName, const QStringList& Files, const QStringList& Checkers)
+{
+ int FailCount = 0;
+ for (QStringList::const_iterator I = Files.begin(); I != Files.end(); ++I)
+ {
+ if (pProgress->IsCanceled()) break;
+
+ QString BoxPath = *I;
+ QString FileName = BoxPath.mid(BoxPath.lastIndexOf("\\") + 1);
+
+ pProgress->ShowMessage(tr("Checking file %1").arg(FileName));
+
+ foreach(const QString & Value, Checkers) {
+ QString Output;
+ int ret = CSbieUtils::ExecCommandEx(Value + " \"" + BoxPath + "\"", &Output, 15000); // 15 sec timeout
+ if (ret != 0) {
+ FailCount++;
+ QMetaObject::invokeMethod(theGUI, "ShowMessage", Qt::BlockingQueuedConnection, // show this message using the GUI thread
+ Q_ARG(QString, tr("The file %1 failed a security check!\r\n\r\n%2").arg(BoxPath).arg(Output)),
+ Q_ARG(int, QMessageBox::Warning)
+ );
+ }
+ }
+ }
+ if (FailCount == 0) {
+ QMetaObject::invokeMethod(theGUI, "ShowMessage", Qt::BlockingQueuedConnection, // show this message using the GUI thread
+ Q_ARG(QString, tr("All files passed the checks")),
+ Q_ARG(int, QMessageBox::Information)
+ );
+ }
+
+ pProgress->Finish(SB_OK);
+}
+
+SB_PROGRESS CSandMan::RecoverFiles(const QString& BoxName, const QList>& FileList, int Action)
+{
+ CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
+ CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName);
+ QStringList Checkers;
+ if (!pBox.isNull()) {
+ foreach(const QString & Value, pBox->GetTextList("OnFileRecovery", true, false, true)) {
+ Checkers.append(pBox->Expand(Value));
+ }
+ }
+ QtConcurrent::run(CSandMan::RecoverFilesAsync, pProgress, BoxName, FileList, Checkers, Action);
+ return SB_PROGRESS(OP_ASYNC, pProgress);
+}
+
+void CSandMan::RecoverFilesAsync(const CSbieProgressPtr& pProgress, const QString& BoxName, const QList>& FileList, const QStringList& Checkers, int Action)
{
SB_STATUS Status = SB_OK;
int OverwriteOnExist = -1;
+ int RecoverCheckFailed = -1;
QStringList Unrecovered;
for (QList>::const_iterator I = FileList.begin(); I != FileList.end(); ++I)
{
+ if (pProgress->IsCanceled()) break;
+
QString BoxPath = I->first;
QString RecoveryPath = I->second;
QString FileName = BoxPath.mid(BoxPath.lastIndexOf("\\") + 1);
QString RecoveryFolder = RecoveryPath.left(RecoveryPath.lastIndexOf("\\") + 1);
+ if (!Checkers.isEmpty()) {
+
+ pProgress->ShowMessage(tr("Checking file %1").arg(FileName));
+
+ //bool bNoGui = true;
+ //if (GetKeyState(VK_CONTROL) & 0x8000)
+ // bNoGui = false;
+
+ int ret = 0;
+ foreach(const QString & Value, Checkers) {
+ QString Output;
+ ret = CSbieUtils::ExecCommandEx(Value + " \"" + BoxPath + "\"", &Output, 15000); // 15 sec timeout
+ if (ret != 0) {
+
+ int Recover = RecoverCheckFailed;
+ if (Recover == -1)
+ {
+ bool forAll = false;
+ int retVal = 0;
+ QMetaObject::invokeMethod(theGUI, "ShowQuestion", Qt::BlockingQueuedConnection, // show this question using the GUI thread
+ Q_RETURN_ARG(int, retVal),
+ Q_ARG(QString, tr("The file %1 failed a security check, do you want to recover it anyways?\r\n\r\n%2").arg(BoxPath).arg(Output)),
+ Q_ARG(QString, tr("Do this for all files!")),
+ Q_ARG(bool*, &forAll),
+ Q_ARG(int, QDialogButtonBox::Yes | QDialogButtonBox::No),
+ Q_ARG(int, QDialogButtonBox::No),
+ Q_ARG(int, QMessageBox::Warning)
+ );
+
+ Recover = retVal == QDialogButtonBox::Yes ? 1 : 0;
+ if (forAll)
+ RecoverCheckFailed = Recover;
+ }
+
+ if (Recover == 1)
+ ret = 0;
+ else
+ break;
+ }
+ }
+ if (ret != 0)
+ continue; // Do not recover this file
+ }
+
pProgress->ShowMessage(tr("Recovering file %1 to %2").arg(FileName).arg(RecoveryFolder));
QDir().mkpath(RecoveryFolder);
diff --git a/SandboxiePlus/SandMan/Views/SbieView.cpp b/SandboxiePlus/SandMan/Views/SbieView.cpp
index fa414955..433fa095 100644
--- a/SandboxiePlus/SandMan/Views/SbieView.cpp
+++ b/SandboxiePlus/SandMan/Views/SbieView.cpp
@@ -161,6 +161,8 @@ void CSbieView::CreateMenu()
}
else
m_pMenuRunStart = NULL;
+ //m_pMenuRunTools->addSeparator();
+ m_pMenuAutoRun = m_pMenuRun->addAction(CSandMan::GetIcon("ReloadIni"), tr("Execute Autorun Entries"), this, SLOT(OnSandBoxAction()));
m_pMenuRunTools = m_pMenuRun->addMenu(CSandMan::GetIcon("Maintenance"), tr("More Tools"));
m_pMenuRunBrowser = m_pMenuRunTools->addAction(CSandMan::GetIcon("Internet"), tr("Default Web Browser"), this, SLOT(OnSandBoxAction()));
m_pMenuRunMailer = m_pMenuRunTools->addAction(CSandMan::GetIcon("Email"), tr("Default eMail Client"), this, SLOT(OnSandBoxAction()));
@@ -172,13 +174,10 @@ void CSbieView::CreateMenu()
m_pMenuRunTools->addSeparator();
m_pMenuRunCmd = m_pMenuRunTools->addAction(CSandMan::GetIcon("Cmd"), tr("Command Prompt"), this, SLOT(OnSandBoxAction()));
m_pMenuRunCmdAdmin = m_pMenuRunTools->addAction(CSandMan::GetIcon("Cmd"), tr("Command Prompt (as Admin)"), this, SLOT(OnSandBoxAction()));
-#ifdef _WIN64
+#ifndef _WIN64
if(CSbieAPI::IsWow64())
- m_pMenuRunCmd32 = m_pMenuRunTools->addAction(CSandMan::GetIcon("Cmd"), tr("Command Prompt (32-bit)"), this, SLOT(OnSandBoxAction()));
#endif
- m_pMenuRunTools->addSeparator();
- m_pMenuAutoRun = m_pMenuRunTools->addAction(CSandMan::GetIcon("ReloadIni"), tr("Execute Autorun Entries"), this, SLOT(OnSandBoxAction()));
-
+ m_pMenuRunCmd32 = m_pMenuRunTools->addAction(CSandMan::GetIcon("Cmd"), tr("Command Prompt (32-bit)"), this, SLOT(OnSandBoxAction()));
m_pMenuRun->addSeparator();
m_iMenuRun = m_pMenuRun->actions().count();
m_pMenuEmptyBox = m_pMenuBox->addAction(CSandMan::GetIcon("EmptyAll"), tr("Terminate All Programs"), this, SLOT(OnSandBoxAction()));
diff --git a/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp b/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp
index e8f9f82a..ee400243 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp
+++ b/SandboxiePlus/SandMan/Windows/OptionsAdvanced.cpp
@@ -49,8 +49,6 @@ void COptionsWindow::CreateAdvanced()
m_AdvOptions.insert("FakeAdminRights", SAdvOption{eOnlySpec, QStringList() << "y" << "n", tr("Make specified processes think they have admin permissions.")});
m_AdvOptions.insert("WaitForDebugger", SAdvOption{eOnlySpec, QStringList() << "y" << "n", tr("Force specified processes to wait for a debugger to attach.")});
m_AdvOptions.insert("BoxNameTitle", SAdvOption{eOnlySpec, QStringList() << "y" << "n" << "-", tr("")});
- m_AdvOptions.insert("UseFileDeleteV2", SAdvOption{eNoSpec, QStringList() << "y" << "n", tr("")});
- m_AdvOptions.insert("UseRegDeleteV2", SAdvOption{eNoSpec, QStringList() << "y" << "n", tr("")});
m_AdvOptions.insert("FileRootPath", SAdvOption{eNoSpec, QStringList(), tr("Sandbox file system root")});
m_AdvOptions.insert("KeyRootPath", SAdvOption{eNoSpec, QStringList(), tr("Sandbox registry root")});
m_AdvOptions.insert("IpcRootPath", SAdvOption{eNoSpec, QStringList(), tr("Sandbox ipc root")});
diff --git a/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp b/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp
index 8a1ef207..cdce9ff7 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp
+++ b/SandboxiePlus/SandMan/Windows/OptionsGeneral.cpp
@@ -156,12 +156,33 @@ void COptionsWindow::CreateGeneral()
//connect(ui.chkOpenSmartCard, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
//connect(ui.chkOpenBluetooth, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
+ ui.cmbVersion->addItem(tr("Version 1"));
+ ui.cmbVersion->addItem(tr("Version 2"));
+
+ bool bEmpty = ((CSandBoxPlus*)m_pBox.data())->IsEmpty();
+ ui.lblWhenEmpty->setVisible(!bEmpty);
+ ui.lblScheme->setEnabled(bEmpty);
+ ui.cmbVersion->setEnabled(bEmpty);
+ ui.chkSeparateUserFolders->setEnabled(bEmpty);
+ ui.chkUseVolumeSerialNumbers->setEnabled(bEmpty);
+
+ connect(ui.cmbVersion, SIGNAL(currentIndexChanged(int)), this, SLOT(OnGeneralChanged()));
connect(ui.chkSeparateUserFolders, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
+ connect(ui.chkUseVolumeSerialNumbers, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
connect(ui.txtCopyLimit, SIGNAL(textChanged(const QString&)), this, SLOT(OnGeneralChanged()));
connect(ui.chkCopyLimit, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
connect(ui.chkCopyPrompt, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
connect(ui.chkNoCopyWarn, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
+ connect(ui.chkDenyWrite, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
+ connect(ui.chkNoCopyMsg, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
+
+ connect(ui.btnAddCopy, SIGNAL(clicked(bool)), this, SLOT(OnAddCopyRule()));
+ connect(ui.btnDelCopy, SIGNAL(clicked(bool)), this, SLOT(OnDelCopyRule()));
+ connect(ui.treeCopy, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnCopyItemDoubleClicked(QTreeWidgetItem*, int)));
+ connect(ui.treeCopy, SIGNAL(itemSelectionChanged()), this, SLOT(OnCopySelectionChanged()));
+ connect(ui.treeCopy, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnCopyChanged(QTreeWidgetItem*, int)));
+ connect(ui.chkShowCopyTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowCopyTmpl()));
connect(ui.chkProtectBox, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
connect(ui.chkAutoEmpty, SIGNAL(clicked(bool)), this, SLOT(OnGeneralChanged()));
@@ -254,14 +275,30 @@ void COptionsWindow::LoadGeneral()
ui.cmbDblClick->setCurrentIndex(pos);
if (pos == -1) ui.cmbDblClick->setCurrentText(Action);
+
+ if (m_pBox->GetBool("UseFileDeleteV2", false) && m_pBox->GetBool("UseRegDeleteV2", false))
+ ui.cmbVersion->setCurrentIndex(1);
+ else if (!m_pBox->GetBool("UseFileDeleteV2", false) && !m_pBox->GetBool("UseRegDeleteV2", false))
+ ui.cmbVersion->setCurrentIndex(0);
+ else {
+ ui.cmbVersion->setEditable(true);
+ ui.cmbVersion->lineEdit()->setReadOnly(true);
+ ui.cmbVersion->setCurrentText(tr("Indeterminate"));
+ }
+
ReadGlobalCheck(ui.chkSeparateUserFolders, "SeparateUserFolders", true);
+ ReadGlobalCheck(ui.chkUseVolumeSerialNumbers, "UseVolumeSerialNumbers", false);
int iLimit = m_pBox->GetNum("CopyLimitKb", 80 * 1024);
ui.chkCopyLimit->setChecked(iLimit != -1);
ui.txtCopyLimit->setText(QString::number(iLimit > 0 ? iLimit : 80 * 1024));
ui.chkCopyPrompt->setChecked(m_pBox->GetBool("PromptForFileMigration", true));
ui.chkNoCopyWarn->setChecked(!m_pBox->GetBool("CopyLimitSilent", false));
+ ui.chkDenyWrite->setChecked(m_pBox->GetBool("CopyBlockDenyWrite", false));
+ ui.chkNoCopyMsg->setChecked(m_pBox->GetBool("NotifyNoCopy", false));
+ LoadCopyRules();
+
ui.chkProtectBox->setChecked(m_pBox->GetBool("NeverDelete", false));
ui.chkAutoEmpty->setChecked(m_pBox->GetBool("AutoDelete", false));
@@ -328,11 +365,29 @@ void COptionsWindow::SaveGeneral()
}
WriteTextList("RunCommand", RunCommands);
- WriteGlobalCheck(ui.chkSeparateUserFolders, "SeparateUserFolders", true);
+ if (ui.cmbVersion->isEnabled())
+ {
+ if (ui.cmbVersion->currentIndex() == 1) { // V2
+ m_pBox->SetBool("UseFileDeleteV2", true);
+ m_pBox->SetBool("UseRegDeleteV2", true);
+ }
+ else if (ui.cmbVersion->currentIndex() == 0) { // V1
+ m_pBox->DelValue("UseFileDeleteV2");
+ m_pBox->DelValue("UseRegDeleteV2");
+ }
+
+ WriteGlobalCheck(ui.chkSeparateUserFolders, "SeparateUserFolders", true);
+ WriteGlobalCheck(ui.chkUseVolumeSerialNumbers, "UseVolumeSerialNumbers", false);
+ }
WriteText("CopyLimitKb", ui.chkCopyLimit->isChecked() ? ui.txtCopyLimit->text() : "-1");
WriteAdvancedCheck(ui.chkCopyPrompt, "PromptForFileMigration", "", "n");
WriteAdvancedCheck(ui.chkNoCopyWarn, "CopyLimitSilent", "", "y");
+ WriteAdvancedCheck(ui.chkDenyWrite, "CopyBlockDenyWrite", "y", "");
+ WriteAdvancedCheck(ui.chkNoCopyMsg, "NotifyNoCopy", "y", "");
+
+ if (m_CopyRulesChanged)
+ SaveCopyRules();
WriteAdvancedCheck(ui.chkProtectBox, "NeverDelete", "y", "");
WriteAdvancedCheck(ui.chkAutoEmpty, "AutoDelete", "y", "");
@@ -343,6 +398,287 @@ void COptionsWindow::SaveGeneral()
m_GeneralChanged = false;
}
+// copy
+void COptionsWindow::LoadCopyRules()
+{
+ ui.treeCopy->clear();
+
+ foreach(const QString & Value, m_pBox->GetTextList("CopyAlways", m_Template))
+ ParseAndAddCopyRule(Value, eCopyAlways);
+ foreach(const QString & Value, m_pBox->GetTextList("DontCopy", m_Template))
+ ParseAndAddCopyRule(Value, eDontCopy);
+ foreach(const QString & Value, m_pBox->GetTextList("CopyEmpty", m_Template))
+ ParseAndAddCopyRule(Value, eCopyEmpty);
+
+ foreach(const QString & Value, m_pBox->GetTextList("CopyAlwaysDisabled", m_Template))
+ ParseAndAddCopyRule(Value, eCopyAlways, true);
+ foreach(const QString & Value, m_pBox->GetTextList("DontCopyDisabled", m_Template))
+ ParseAndAddCopyRule(Value, eDontCopy, true);
+ foreach(const QString & Value, m_pBox->GetTextList("CopyEmptyDisabled", m_Template))
+ ParseAndAddCopyRule(Value, eCopyEmpty, true);
+
+ LoadCopyRulesTmpl();
+
+ m_CopyRulesChanged = false;
+}
+
+void COptionsWindow::LoadCopyRulesTmpl(bool bUpdate)
+{
+ if (ui.chkShowCopyTmpl->isChecked())
+ {
+ foreach(const QString & Template, m_pBox->GetTemplates())
+ {
+ foreach(const QString & Value, m_pBox->GetTextListTmpl("CopyAlways", Template))
+ ParseAndAddCopyRule(Value, eCopyAlways, false, Template);
+ foreach(const QString & Value, m_pBox->GetTextListTmpl("DontCopy", Template))
+ ParseAndAddCopyRule(Value, eDontCopy, false, Template);
+ foreach(const QString & Value, m_pBox->GetTextListTmpl("CopyEmpty", Template))
+ ParseAndAddCopyRule(Value, eCopyEmpty, false, Template);
+ }
+ }
+ else if (bUpdate)
+ {
+ for (int i = 0; i < ui.treeCopy->topLevelItemCount(); )
+ {
+ QTreeWidgetItem* pItem = ui.treeCopy->topLevelItem(i);
+ int Type = pItem->data(0, Qt::UserRole).toInt();
+ if (Type == -1) {
+ delete pItem;
+ continue; // entry from template
+ }
+ i++;
+ }
+ }
+}
+
+QString COptionsWindow::GetCopyActionStr(ECopyAction Action)
+{
+ switch (Action)
+ {
+ case eCopyAlways: return tr("Always copy");
+ case eDontCopy: return tr("Don't copy");
+ case eCopyEmpty: return tr("Copy empty");
+ }
+ return "";
+}
+
+void COptionsWindow::ParseAndAddCopyRule(const QString& Value, ECopyAction Action, bool disabled, const QString& Template)
+{
+ QTreeWidgetItem* pItem = new QTreeWidgetItem();
+
+ pItem->setText(0, GetCopyActionStr(Action));
+ pItem->setData(0, Qt::UserRole, Template.isEmpty() ? (int)Action : -1);
+
+ QString Program;
+ QString Pattern;
+ QStringList Values = Value.split(",");
+ if (Values.size() >= 2) {
+ Program = Values[0];
+ Pattern = Values[1];
+ }
+ else
+ Pattern = Values[0];
+
+ // todo this block is also used by access move this to an own function
+ pItem->setData(1, Qt::UserRole, Program);
+ bool bAll = Program.isEmpty();
+ if (bAll)
+ Program = tr("All Programs");
+ bool Not = Program.left(1) == "!";
+ if (Not)
+ Program.remove(0, 1);
+ if (Program.left(1) == "<")
+ Program = tr("Group: %1").arg(Program.mid(1, Program.length() - 2));
+ else if (!bAll)
+ m_Programs.insert(Program);
+ pItem->setText(1, (Not ? "NOT " : "") + Program);
+
+ pItem->setText(2, Pattern);
+
+ if (Template.isEmpty())
+ pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked);
+ ui.treeCopy->addTopLevelItem(pItem);
+}
+
+void COptionsWindow::SaveCopyRules()
+{
+ QList CopyAlways;
+ QList CopyAlwaysDisabled;
+ QList DontCopy;
+ QList DontCopyDisabled;
+ QList CopyEmpty;
+ QList CopyEmptyDisabled;
+ for (int i = 0; i < ui.treeCopy->topLevelItemCount(); i++)
+ {
+ QTreeWidgetItem* pItem = ui.treeCopy->topLevelItem(i);
+ int Type = pItem->data(0, Qt::UserRole).toInt();
+ if (Type == -1)
+ continue; // entry from template
+ ECopyAction Action = (ECopyAction)pItem->data(0, Qt::UserRole).toInt();
+ QString Program = pItem->data(1, Qt::UserRole).toString();
+ QString Pattern = pItem->text(2);
+
+ if (!Program.isEmpty())
+ Pattern.prepend(Program + ",");
+
+ if (pItem->checkState(0) == Qt::Checked) {
+ switch (Action) {
+ case eCopyAlways: CopyAlways.append(Pattern); break;
+ case eDontCopy: DontCopy.append(Pattern); break;
+ case eCopyEmpty: CopyEmpty.append(Pattern); break;
+ }
+ }
+ else {
+ switch (Action) {
+ case eCopyAlways: CopyAlwaysDisabled.append(Pattern); break;
+ case eDontCopy: DontCopyDisabled.append(Pattern); break;
+ case eCopyEmpty: CopyEmptyDisabled.append(Pattern); break;
+ }
+ }
+ }
+ WriteTextList("CopyAlways", CopyAlways);
+ WriteTextList("CopyAlwaysDisabled", CopyAlwaysDisabled);
+ WriteTextList("DontCopy", DontCopy);
+ WriteTextList("DontCopyDisabled", DontCopyDisabled);
+ WriteTextList("CopyEmpty", CopyEmpty);
+ WriteTextList("CopyEmptyDisabled", CopyEmptyDisabled);
+
+ m_CopyRulesChanged = false;
+}
+
+void COptionsWindow::OnCopyItemDoubleClicked(QTreeWidgetItem* pItem, int Column)
+{
+ int Action = pItem->data(0, Qt::UserRole).toInt();
+ if (Action == -1) {
+ QMessageBox::warning(this, "SandboxiePlus", tr("Template values can not be edited."));
+ return;
+ }
+
+ QComboBox* pMode = new QComboBox();
+ pMode->addItem(tr("Always copy"), (int)eCopyAlways);
+ pMode->addItem(tr("Don't copy"), (int)eDontCopy);
+ pMode->addItem(tr("Copy empty"), (int)eCopyEmpty);
+ pMode->setCurrentIndex(pMode->findData(pItem->data(0, Qt::UserRole)));
+ ui.treeCopy->setItemWidget(pItem, 0, pMode);
+
+ QString Program = pItem->data(1, Qt::UserRole).toString();
+
+ // todo:
+ QWidget* pProgram = new QWidget();
+ pProgram->setAutoFillBackground(true);
+ QHBoxLayout* pLayout = new QHBoxLayout();
+ pLayout->setContentsMargins(0, 0, 0, 0);
+ pLayout->setSpacing(0);
+ pProgram->setLayout(pLayout);
+ QToolButton* pNot = new QToolButton(pProgram);
+ pNot->setText("!");
+ pNot->setCheckable(true);
+ if (Program.left(1) == "!") {
+ pNot->setChecked(true);
+ Program.remove(0, 1);
+ }
+ pLayout->addWidget(pNot);
+ QComboBox* pCombo = new QComboBox(pProgram);
+ pCombo->addItem(tr("All Programs"), "");
+
+ for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) {
+ QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i);
+ pCombo->addItem(tr("Group: %1").arg(pItem->text(0)), pItem->data(0, Qt::UserRole).toString());
+ }
+
+ foreach(const QString & Name, m_Programs)
+ pCombo->addItem(Name, Name);
+
+ pCombo->setEditable(true);
+ int Index = pCombo->findData(Program);
+ pCombo->setCurrentIndex(Index);
+ if (Index == -1)
+ pCombo->setCurrentText(Program);
+ pLayout->addWidget(pCombo);
+
+ ui.treeCopy->setItemWidget(pItem, 1, pProgram);
+
+ QLineEdit* pPattern = new QLineEdit();
+ pPattern->setText(pItem->text(2));
+ ui.treeCopy->setItemWidget(pItem, 2, pPattern);
+}
+
+void COptionsWindow::OnCopyChanged(QTreeWidgetItem* pItem, int Column)
+{
+ if (Column != 0)
+ return;
+
+ m_CopyRulesChanged = true;
+ OnOptChanged();
+}
+
+void COptionsWindow::CloseCopyEdit(bool bSave)
+{
+ for (int i = 0; i < ui.treeCopy->topLevelItemCount(); i++)
+ {
+ QTreeWidgetItem* pItem = ui.treeCopy->topLevelItem(i);
+ CloseCopyEdit(pItem, bSave);
+ }
+}
+
+void COptionsWindow::CloseCopyEdit(QTreeWidgetItem* pItem, bool bSave)
+{
+ QWidget* pProgram = ui.treeCopy->itemWidget(pItem, 1);
+ if (!pProgram)
+ return;
+
+ if (bSave)
+ {
+ QComboBox* pAction = (QComboBox*)ui.treeCopy->itemWidget(pItem, 0);
+
+ QHBoxLayout* pLayout = (QHBoxLayout*)pProgram->layout();
+ QToolButton* pNot = (QToolButton*)pLayout->itemAt(0)->widget();
+ QComboBox* pCombo = (QComboBox*)pLayout->itemAt(1)->widget();
+
+ QLineEdit* pPattern = (QLineEdit*)ui.treeCopy->itemWidget(pItem, 2);
+
+ QString Program = pCombo->currentText();
+ int Index = pCombo->findText(Program);
+ if (Index != -1)
+ Program = pCombo->itemData(Index, Qt::UserRole).toString();
+
+ pItem->setText(0, pAction->currentText());
+ pItem->setData(0, Qt::UserRole, pAction->currentData());
+
+ pItem->setText(1, (pNot->isChecked() ? "NOT " : "") + pCombo->currentText());
+ pItem->setData(1, Qt::UserRole, (pNot->isChecked() ? "!" : "") + Program);
+
+ pItem->setText(2, pPattern->text());
+
+ m_CopyRulesChanged = true;
+ OnOptChanged();
+ }
+
+ for (int i = 0; i < 3; i++)
+ ui.treeCopy->setItemWidget(pItem, i, NULL);
+}
+
+void COptionsWindow::OnAddCopyRule()
+{
+ ParseAndAddCopyRule("", eCopyAlways);
+
+ m_CopyRulesChanged = true;
+ OnOptChanged();
+}
+
+void COptionsWindow::OnDelCopyRule()
+{
+ QTreeWidgetItem* pItem = ui.treeCopy->currentItem();
+ if (!pItem)
+ return;
+
+ delete pItem;
+
+ m_CopyRulesChanged = true;
+ OnOptChanged();
+}
+//
+
void COptionsWindow::OnGeneralChanged()
{
ui.lblCopyLimit->setEnabled(ui.chkCopyLimit->isChecked());
diff --git a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp
index 079198f5..e01b5645 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp
+++ b/SandboxiePlus/SandMan/Windows/OptionsNetwork.cpp
@@ -347,6 +347,7 @@ void COptionsWindow::CheckINetBlock()
void COptionsWindow::LoadNetFwRules()
{
ui.treeNetFw->clear();
+
foreach(const QString & Value, m_pBox->GetTextList("NetworkAccess", m_Template))
ParseAndAddFwRule(Value);
diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp
index 87b53199..ed10c1fe 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp
+++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp
@@ -161,6 +161,7 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri
ui.tabs->tabBar()->setProperty("isSidebar", true);
+ ui.tabs->setCurrentIndex(0);
ui.tabs->setTabIcon(0, CSandMan::GetIcon("Config"));
ui.tabs->setTabIcon(1, CSandMan::GetIcon("Security"));
ui.tabs->setTabIcon(2, CSandMan::GetIcon("Group"));
@@ -175,26 +176,33 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri
ui.tabs->setTabIcon(11, CSandMan::GetIcon("Template"));
ui.tabs->setTabIcon(12, CSandMan::GetIcon("Editor"));
+ ui.tabsGeneral->setCurrentIndex(0);
ui.tabsGeneral->setTabIcon(0, CSandMan::GetIcon("Box"));
- ui.tabsGeneral->setTabIcon(1, CSandMan::GetIcon("File"));
- ui.tabsGeneral->setTabIcon(2, CSandMan::GetIcon("NoAccess"));
- ui.tabsGeneral->setTabIcon(3, CSandMan::GetIcon("Run"));
+ ui.tabsGeneral->setTabIcon(1, CSandMan::GetIcon("Folder"));
+ ui.tabsGeneral->setTabIcon(2, CSandMan::GetIcon("Move"));
+ ui.tabsGeneral->setTabIcon(3, CSandMan::GetIcon("NoAccess"));
+ ui.tabsGeneral->setTabIcon(4, CSandMan::GetIcon("Run"));
+ ui.tabsSecurity->setCurrentIndex(0);
ui.tabsSecurity->setTabIcon(0, CSandMan::GetIcon("Shield7"));
ui.tabsSecurity->setTabIcon(1, CSandMan::GetIcon("Fence"));
ui.tabsSecurity->setTabIcon(2, CSandMan::GetIcon("Shield12"));
+ ui.tabsForce->setCurrentIndex(0);
ui.tabsForce->setTabIcon(0, CSandMan::GetIcon("Force"));
ui.tabsForce->setTabIcon(1, CSandMan::GetIcon("Breakout"));
+ ui.tabsStop->setCurrentIndex(0);
ui.tabsStop->setTabIcon(0, CSandMan::GetIcon("Fail"));
ui.tabsStop->setTabIcon(1, CSandMan::GetIcon("Pass"));
+ ui.tabsInternet->setCurrentIndex(0);
ui.tabsInternet->setTabIcon(0, CSandMan::GetIcon("Program"));
ui.tabsInternet->setTabIcon(1, CSandMan::GetIcon("Wall"));
ui.tabsInternet->setTabIcon(2, CSandMan::GetIcon("DNS"));
ui.tabsInternet->setTabIcon(3, CSandMan::GetIcon("Proxy"));
+ ui.tabsAccess->setCurrentIndex(0);
ui.tabsAccess->setTabIcon(0, CSandMan::GetIcon("Folder"));
ui.tabsAccess->setTabIcon(1, CSandMan::GetIcon("RegEdit"));
ui.tabsAccess->setTabIcon(2, CSandMan::GetIcon("Port"));
@@ -203,9 +211,11 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri
//ui.tabsAccess->setTabIcon(0, CSandMan::GetIcon("Rules"));
ui.tabsAccess->setTabIcon(5, CSandMan::GetIcon("Policy"));
+ ui.tabsRecovery->setCurrentIndex(0);
ui.tabsRecovery->setTabIcon(0, CSandMan::GetIcon("QuickRecovery"));
ui.tabsRecovery->setTabIcon(1, CSandMan::GetIcon("ImmidiateRecovery"));
+ ui.tabsAdvanced->setCurrentIndex(0);
ui.tabsAdvanced->setTabIcon(0, CSandMan::GetIcon("Compatibility"));
ui.tabsAdvanced->setTabIcon(1, CSandMan::GetIcon("Trigger"));
ui.tabsAdvanced->setTabIcon(2, CSandMan::GetIcon("Anon"));
@@ -214,6 +224,7 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri
ui.tabsAdvanced->setTabIcon(5, CSandMan::GetIcon("SetLogging"));
ui.tabsAdvanced->setTabIcon(6, CSandMan::GetIcon("Bug"));
+ ui.tabsTemplates->setCurrentIndex(0);
ui.tabsTemplates->setTabIcon(0, CSandMan::GetIcon("Compatibility"));
ui.tabsTemplates->setTabIcon(1, CSandMan::GetIcon("Explore"));
ui.tabsTemplates->setTabIcon(2, CSandMan::GetIcon("Accessibility"));
@@ -506,7 +517,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri
UpdateCurrentTab();
ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
-
+
+ ui.treeCopy->viewport()->installEventFilter(this);
ui.treeINet->viewport()->installEventFilter(this);
ui.treeNetFw->viewport()->installEventFilter(this);
ui.treeFiles->viewport()->installEventFilter(this);
@@ -601,11 +613,13 @@ bool COptionsWindow::eventFilter(QObject *source, QEvent *event)
{
if (event->type() == QEvent::KeyPress && ((QKeyEvent*)event)->key() == Qt::Key_Escape
&& ((QKeyEvent*)event)->modifiers() == Qt::NoModifier
- && (source == ui.treeINet->viewport() || source == ui.treeNetFw->viewport()
+ && (source == ui.treeCopy->viewport()
+ || source == ui.treeINet->viewport() || source == ui.treeNetFw->viewport()
// || source == ui.treeAccess->viewport()
|| source == ui.treeFiles->viewport() || source == ui.treeKeys->viewport() || source == ui.treeIPC->viewport() || source == ui.treeWnd->viewport() || source == ui.treeCOM->viewport()
|| (ui.treeOptions && source == ui.treeOptions->viewport())))
{
+ CloseCopyEdit(false);
CloseINetEdit(false);
CloseNetFwEdit(false);
CloseAccessEdit(false);
@@ -616,6 +630,7 @@ bool COptionsWindow::eventFilter(QObject *source, QEvent *event)
if (event->type() == QEvent::KeyPress && (((QKeyEvent*)event)->key() == Qt::Key_Enter || ((QKeyEvent*)event)->key() == Qt::Key_Return)
&& (((QKeyEvent*)event)->modifiers() == Qt::NoModifier || ((QKeyEvent*)event)->modifiers() == Qt::KeypadModifier))
{
+ CloseCopyEdit(true);
CloseINetEdit(true);
CloseNetFwEdit(true);
CloseAccessEdit(true);
@@ -623,6 +638,21 @@ bool COptionsWindow::eventFilter(QObject *source, QEvent *event)
return true; // cancel event
}
+ if (source == ui.treeCopy->viewport() && event->type() == QEvent::MouseButtonPress)
+ {
+ CloseCopyEdit();
+ }
+
+ if (source == ui.treeINet->viewport() && event->type() == QEvent::MouseButtonPress)
+ {
+ CloseINetEdit();
+ }
+
+ if (source == ui.treeNetFw->viewport() && event->type() == QEvent::MouseButtonPress)
+ {
+ CloseNetFwEdit();
+ }
+
if (//source == ui.treeAccess->viewport()
(source == ui.treeFiles->viewport() || source == ui.treeKeys->viewport() || source == ui.treeIPC->viewport() || source == ui.treeWnd->viewport() || source == ui.treeCOM->viewport())
&& event->type() == QEvent::MouseButtonPress)
@@ -630,15 +660,6 @@ bool COptionsWindow::eventFilter(QObject *source, QEvent *event)
CloseAccessEdit();
}
- if (source == ui.treeINet->viewport() && event->type() == QEvent::MouseButtonPress)
- {
- CloseINetEdit();
- }
-
- if (source == ui.treeNetFw->viewport() && event->type() == QEvent::MouseButtonPress)
- {
- CloseNetFwEdit();
- }
if ((ui.treeOptions && source == ui.treeOptions->viewport()) && event->type() == QEvent::MouseButtonPress)
{
diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.h b/SandboxiePlus/SandMan/Windows/OptionsWindow.h
index e0ff0bf4..ef226faa 100644
--- a/SandboxiePlus/SandMan/Windows/OptionsWindow.h
+++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.h
@@ -54,6 +54,13 @@ private slots:
void OnBoxTypChanged();
void UpdateBoxType();
+ void OnCopyItemDoubleClicked(QTreeWidgetItem* pItem, int Column);
+ void OnCopySelectionChanged() { CloseCopyEdit(); OnOptChanged(); }
+ void OnCopyChanged(QTreeWidgetItem* pItem, int Column);
+ void OnShowCopyTmpl() { LoadCopyRulesTmpl(true); }
+ void OnAddCopyRule();
+ void OnDelCopyRule();
+
void OnBrowsePath();
void OnAddCommand();
void OnDelCommand();
@@ -224,6 +231,13 @@ protected:
void OnTab(QWidget* pTab);
+ enum ECopyAction
+ {
+ eCopyAlways,
+ eDontCopy,
+ eCopyEmpty,
+ };
+
enum ENetWfAction
{
eAllow,
@@ -306,6 +320,11 @@ protected:
QString GetActionFile();
+ QString GetCopyActionStr(ECopyAction Action);
+ void ParseAndAddCopyRule(const QString& Value, ECopyAction Action, bool disabled = false, const QString& Template = QString());
+ void CloseCopyEdit(bool bSave = true);
+ void CloseCopyEdit(QTreeWidgetItem* pItem, bool bSave = true);
+
void SetProgramItem(QString Program, QTreeWidgetItem* pItem, int Column, const QString& Sufix = QString());
QString SelectProgram(bool bOrGroup = true);
@@ -328,6 +347,10 @@ protected:
void LoadGeneral();
void SaveGeneral();
+ void LoadCopyRules();
+ void LoadCopyRulesTmpl(bool bUpdate = false);
+ void SaveCopyRules();
+
void UpdateBoxSecurity();
void LoadGroups();
@@ -461,6 +484,7 @@ protected:
bool m_HoldBoxType;
bool m_GeneralChanged;
+ bool m_CopyRulesChanged;
bool m_GroupsChanged;
bool m_ForcedChanged;
bool m_StopChanged;
diff --git a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp
index 85d93e95..e77be852 100644
--- a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp
+++ b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp
@@ -649,7 +649,7 @@ void CSettingsWindow::LoadSettings()
QString IpcRootPath_Default = "\\Sandbox\\%USER%\\%SANDBOX%\\Session_%SESSION%";
ui.fileRoot->setText(theAPI->GetGlobalSettings()->GetText("FileRootPath", FileRootPath_Default));
- ui.chkSeparateUserFolders->setChecked(theAPI->GetGlobalSettings()->GetBool("SeparateUserFolders", true));
+ //ui.chkSeparateUserFolders->setChecked(theAPI->GetGlobalSettings()->GetBool("SeparateUserFolders", true));
ui.regRoot->setText(theAPI->GetGlobalSettings()->GetText("KeyRootPath", KeyRootPath_Default));
ui.ipcRoot->setText(theAPI->GetGlobalSettings()->GetText("IpcRootPath", IpcRootPath_Default));
@@ -682,7 +682,7 @@ void CSettingsWindow::LoadSettings()
{
ui.cmbDefault->setEnabled(false);
ui.fileRoot->setEnabled(false);
- ui.chkSeparateUserFolders->setEnabled(false);
+ //ui.chkSeparateUserFolders->setEnabled(false);
ui.chkAutoRoot->setEnabled(false);
ui.chkWFP->setEnabled(false);
ui.chkObjCb->setEnabled(false);
@@ -950,7 +950,7 @@ void CSettingsWindow::SaveSettings()
WriteText("DefaultBox", ui.cmbDefault->currentData().toString());
WriteText("FileRootPath", ui.fileRoot->text()); //ui.fileRoot->setText("\\??\\%SystemDrive%\\Sandbox\\%USER%\\%SANDBOX%");
- WriteAdvancedCheck(ui.chkSeparateUserFolders, "SeparateUserFolders", "", "n");
+ //WriteAdvancedCheck(ui.chkSeparateUserFolders, "SeparateUserFolders", "", "n");
WriteText("KeyRootPath", ui.regRoot->text()); //ui.regRoot->setText("\\REGISTRY\\USER\\Sandbox_%USER%_%SANDBOX%");
WriteText("IpcRootPath", ui.ipcRoot->text()); //ui.ipcRoot->setText("\\Sandbox\\%USER%\\%SANDBOX%\\Session_%SESSION%");
diff --git a/SandboxiePlus/SandMan/Wizards/SetupWizard.cpp b/SandboxiePlus/SandMan/Wizards/SetupWizard.cpp
index 98cd69c2..c3d0474f 100644
--- a/SandboxiePlus/SandMan/Wizards/SetupWizard.cpp
+++ b/SandboxiePlus/SandMan/Wizards/SetupWizard.cpp
@@ -92,7 +92,6 @@ bool CSetupWizard::ShowWizard()
theGUI->UpdateSettings(true);
-
return true;
}
diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h
index 74f8ca38..e4ef851b 100644
--- a/SandboxiePlus/version.h
+++ b/SandboxiePlus/version.h
@@ -1,8 +1,8 @@
#pragma once
#define VERSION_MJR 1
-#define VERSION_MIN 6
-#define VERSION_REV 7
+#define VERSION_MIN 7
+#define VERSION_REV 0
#define VERSION_UPD 0
#ifndef STR