This commit is contained in:
parent
fd171e42a8
commit
04eade2954
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -4,6 +4,24 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
|
||||
|
||||
## [0.9.6 / 5.51.6] - 2021-08-??
|
||||
|
||||
### Added
|
||||
- added ability to rename groups [#1152](https://github.com/sandboxie-plus/Sandboxie/issues/1152)
|
||||
- added ability to define a custom order for the sandboxes, you can move using the move context menu, or holding alt + arow key
|
||||
|
||||
### Fixed
|
||||
- fixed issue with create group menu [#1151](https://github.com/sandboxie-plus/Sandboxie/issues/1151)
|
||||
- fixed issue when renaming a box it lost its group association
|
||||
- fixed issue with thunderbird build 91+ [#1156](https://github.com/sandboxie-plus/Sandboxie/issues/1156)
|
||||
- fixed an issue with file disposition handling [#1161](https://github.com/sandboxie-plus/Sandboxie/issues/1161)
|
||||
|
||||
### Removed
|
||||
- removed "DelayLoadDll=" code from the deriver as the user mode component since opne sourcing never used that information
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.9.5 / 5.51.5] - 2021-08-30
|
||||
|
||||
### Added
|
||||
|
@ -191,7 +209,7 @@ Fixed issue with Windows 7
|
|||
-- the security-enhanced option "MsiInstallerExemptions=n" is now the default behaviour
|
||||
|
||||
### Fixed
|
||||
- fixed issue with the "explore sandboxed" command [#972](https://github.com/sandboxie-plus/Sandboxie/issues/972)
|
||||
- fixed issue with the "Explore Sandboxed" command [#972](https://github.com/sandboxie-plus/Sandboxie/issues/972)
|
||||
- rolled back the switch from using NtQueryKey to NtQueryObject as it seems to break some older Windows 10 versions like 1803 [#984](https://github.com/sandboxie-plus/Sandboxie/issues/984)
|
||||
-- this change was introduced to fix [#951](https://github.com/sandboxie-plus/Sandboxie/issues/951)
|
||||
-- to use NtQueryObject the option "UseObjectNameForKeys=y" can be added to Sandboxie.ini
|
||||
|
@ -320,7 +338,7 @@ Fixed issue with Windows 7
|
|||
## [0.8.0 / 5.50.0] - 2021-06-13
|
||||
|
||||
### Added
|
||||
- Sandboxie now applies by default "Close...=!<program>,..." directives to non-excluded images if they are located in a sandbox
|
||||
- Normally Sandboxie applies "Close...=!<program>,..." directives to non-excluded images if they are located in a sandbox
|
||||
-- added 'AlwaysCloseForBoxed=n' to disable this behaviour as it may not be always desired, and it doesn't provide extra security
|
||||
- added process image information to SandMan UI
|
||||
- localized template categories in the Plus UI [#727](https://github.com/sandboxie-plus/Sandboxie/issues/727)
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#ifndef _MY_VERSION_H
|
||||
#define _MY_VERSION_H
|
||||
|
||||
#define MY_VERSION_BINARY 5,51,5
|
||||
#define MY_VERSION_STRING "5.51.5"
|
||||
#define MY_VERSION_BINARY 5,51,6
|
||||
#define MY_VERSION_STRING "5.51.6"
|
||||
#define MY_VERSION_COMPAT "5.51.0" // this refers to the driver ABI compatibility
|
||||
|
||||
// These #defines are used by either Resource Compiler, or by NSIC installer
|
||||
|
|
|
@ -112,6 +112,7 @@ enum {
|
|||
DLL_IMAGE_PLUGIN_CONTAINER,
|
||||
DLL_IMAGE_OTHER_WEB_BROWSER,
|
||||
DLL_IMAGE_OTHER_MAIL_CLIENT,
|
||||
DLL_IMAGE_MOZILLA_THUNDERBIRD,
|
||||
DLL_IMAGE_LAST
|
||||
};
|
||||
|
||||
|
|
|
@ -534,6 +534,8 @@ _FX ULONG Dll_GetImageType(const WCHAR *ImageName)
|
|||
ImageType = DLL_IMAGE_GOOGLE_CHROME;
|
||||
else if (_wcsicmp(L"firefox", buf) == 0)
|
||||
ImageType = DLL_IMAGE_MOZILLA_FIREFOX;
|
||||
else if (_wcsicmp(L"thunderbird", buf) == 0)
|
||||
ImageType = DLL_IMAGE_MOZILLA_THUNDERBIRD;
|
||||
else if (_wcsicmp(L"browser", buf) == 0)
|
||||
ImageType = DLL_IMAGE_OTHER_WEB_BROWSER;
|
||||
else if (_wcsicmp(L"mail", buf) == 0)
|
||||
|
@ -576,6 +578,8 @@ _FX ULONG Dll_GetImageType(const WCHAR *ImageName)
|
|||
L"k-meleon.exe", (WCHAR *)DLL_IMAGE_MOZILLA_FIREFOX,
|
||||
L"librewolf.exe", (WCHAR *)DLL_IMAGE_MOZILLA_FIREFOX,
|
||||
|
||||
L"thunderbird.exe", (WCHAR *)DLL_IMAGE_MOZILLA_THUNDERBIRD,
|
||||
|
||||
L"wmplayer.exe", (WCHAR *)DLL_IMAGE_WINDOWS_MEDIA_PLAYER,
|
||||
L"winamp.exe", (WCHAR *)DLL_IMAGE_NULLSOFT_WINAMP,
|
||||
L"kmplayer.exe", (WCHAR *)DLL_IMAGE_PANDORA_KMPLAYER,
|
||||
|
@ -603,7 +607,6 @@ _FX ULONG Dll_GetImageType(const WCHAR *ImageName)
|
|||
L"Outlook.exe", (WCHAR *)DLL_IMAGE_OFFICE_OUTLOOK,
|
||||
L"Excel.exe", (WCHAR *)DLL_IMAGE_OFFICE_EXCEL,
|
||||
|
||||
L"thunderbird.exe", (WCHAR *)DLL_IMAGE_OTHER_MAIL_CLIENT,
|
||||
L"winmail.exe", (WCHAR *)DLL_IMAGE_OTHER_MAIL_CLIENT,
|
||||
L"IncMail.exe", (WCHAR *)DLL_IMAGE_OTHER_MAIL_CLIENT,
|
||||
L"eudora.exe", (WCHAR *)DLL_IMAGE_OTHER_MAIL_CLIENT,
|
||||
|
|
|
@ -5924,7 +5924,7 @@ _FX NTSTATUS File_SetDisposition(
|
|||
// handle the request appropriately
|
||||
//
|
||||
|
||||
if (PATH_IS_OPEN(mp_flags) || (FileFlags & FGN_IS_BOXED_PATH) != 0) {
|
||||
if (PATH_IS_OPEN(mp_flags) /*|| (FileFlags & FGN_IS_BOXED_PATH) != 0*/) {
|
||||
|
||||
status = __sys_NtSetInformationFile(
|
||||
FileHandle, IoStatusBlock,
|
||||
|
@ -5938,7 +5938,7 @@ _FX NTSTATUS File_SetDisposition(
|
|||
|
||||
if (NT_SUCCESS(status) && !PATH_IS_OPEN(mp_flags)) {
|
||||
|
||||
BOOLEAN DeleteOnClose;
|
||||
BOOLEAN DeleteOnClose = FALSE;
|
||||
|
||||
if (FileInformationClass == FileDispositionInformation) {
|
||||
|
||||
|
|
|
@ -2132,7 +2132,7 @@ _FX NTSTATUS File_NtCloseImpl(HANDLE FileHandle)
|
|||
InitializeObjectAttributes(
|
||||
&objattrs, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
status = File_NtDeleteFileImpl(&objattrs);
|
||||
File_NtDeleteFileImpl(&objattrs);
|
||||
|
||||
Dll_Free(DeletePath);
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ _FX BOOLEAN File_Init(void)
|
|||
}
|
||||
|
||||
|
||||
if (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX)
|
||||
if (Dll_ImageType == DLL_IMAGE_MOZILLA_FIREFOX || Dll_ImageType == DLL_IMAGE_MOZILLA_THUNDERBIRD)
|
||||
{
|
||||
void *WriteProcessMemory =
|
||||
GetProcAddress(Dll_KernelBase ? Dll_KernelBase : Dll_Kernel32,
|
||||
|
|
|
@ -1944,9 +1944,10 @@ _FX BOOLEAN Proc_CheckMailer(const WCHAR *ImagePath, BOOLEAN IsBoxedPath)
|
|||
// check if image name matches a well-known email program
|
||||
//
|
||||
|
||||
if (imgType == DLL_IMAGE_OFFICE_OUTLOOK ||
|
||||
imgType == DLL_IMAGE_WINDOWS_LIVE_MAIL ||
|
||||
imgType == DLL_IMAGE_OTHER_MAIL_CLIENT ||
|
||||
if (imgType == DLL_IMAGE_OFFICE_OUTLOOK ||
|
||||
imgType == DLL_IMAGE_WINDOWS_LIVE_MAIL ||
|
||||
imgType == DLL_IMAGE_OTHER_MAIL_CLIENT ||
|
||||
imgType == DLL_IMAGE_MOZILLA_THUNDERBIRD ||
|
||||
0)
|
||||
{
|
||||
should_check_openfilepath = TRUE;
|
||||
|
|
|
@ -73,8 +73,9 @@ static LIST Dll_List;
|
|||
static BOOLEAN Dll_List_Initialized = FALSE;
|
||||
|
||||
const WCHAR *Dll_NTDLL = L"NTDLL";
|
||||
#ifdef XP_SUPPORT
|
||||
const WCHAR *Dll_USER = L"USER32";
|
||||
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Dll_Init
|
||||
|
@ -86,10 +87,12 @@ _FX BOOLEAN Dll_Init(void)
|
|||
List_Init(&Dll_List);
|
||||
Dll_List_Initialized = TRUE;
|
||||
|
||||
if (! Dll_Load(Dll_NTDLL)) // ntoskrnl.exe - ntdll.dll
|
||||
if (! Dll_Load(Dll_NTDLL))
|
||||
return FALSE;
|
||||
if (! Dll_Load(Dll_USER)) // win32k.sys - w10: win32u.dll - w7: user32.dll & gdi32.dll
|
||||
#ifdef XP_SUPPORT
|
||||
if (! Dll_Load(Dll_USER))
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -66,8 +66,9 @@ ULONG Dll_GetNextProc(
|
|||
|
||||
|
||||
extern const WCHAR *Dll_NTDLL;
|
||||
#ifdef XP_SUPPORT
|
||||
extern const WCHAR *Dll_USER;
|
||||
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -64,13 +64,14 @@ typedef struct _MY_CONTEXT {
|
|||
} MY_CONTEXT;
|
||||
|
||||
|
||||
typedef struct _BLOCKED_DLL {
|
||||
//typedef struct _BLOCKED_DLL {
|
||||
//
|
||||
// LIST_ELEM list_elem;
|
||||
// ULONG path_len;
|
||||
// WCHAR path[4]; // padding bytes
|
||||
//
|
||||
//} BLOCKED_DLL;
|
||||
|
||||
LIST_ELEM list_elem;
|
||||
ULONG path_len;
|
||||
WCHAR path[4]; // padding bytes
|
||||
|
||||
} BLOCKED_DLL;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -226,7 +227,7 @@ _FX BOOLEAN File_Init(void)
|
|||
Api_SetFunction(API_REFRESH_FILE_PATH_LIST, File_Api_RefreshPathList);
|
||||
Api_SetFunction(API_OPEN_FILE, File_Api_Open);
|
||||
Api_SetFunction(API_CHECK_INTERNET_ACCESS, File_Api_CheckInternetAccess);
|
||||
Api_SetFunction(API_GET_BLOCKED_DLL, File_Api_GetBlockedDll);
|
||||
//Api_SetFunction(API_GET_BLOCKED_DLL, File_Api_GetBlockedDll);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -930,29 +931,29 @@ _FX BOOLEAN File_InitProcess(PROCESS *proc)
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX BOOLEAN File_IsDelayLoadDll(PROCESS *proc, const WCHAR *DllName)
|
||||
{
|
||||
BOOLEAN retval = FALSE;
|
||||
ULONG idx = 0;
|
||||
|
||||
Conf_AdjustUseCount(TRUE);
|
||||
|
||||
while (1) {
|
||||
const WCHAR *value = Conf_Get(proc->box->name, L"DelayLoadDll", idx);
|
||||
if (! value)
|
||||
break;
|
||||
//DbgPrint("Comparing <%S> vs <%S>\n", DllName, value);
|
||||
if (_wcsicmp(value, DllName) == 0) {
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
Conf_AdjustUseCount(FALSE);
|
||||
|
||||
return retval;
|
||||
}
|
||||
//_FX BOOLEAN File_IsDelayLoadDll(PROCESS *proc, const WCHAR *DllName)
|
||||
//{
|
||||
// BOOLEAN retval = FALSE;
|
||||
// ULONG idx = 0;
|
||||
//
|
||||
// Conf_AdjustUseCount(TRUE);
|
||||
//
|
||||
// while (1) {
|
||||
// const WCHAR *value = Conf_Get(proc->box->name, L"DelayLoadDll", idx);
|
||||
// if (! value)
|
||||
// break;
|
||||
// //DbgPrint("Comparing <%S> vs <%S>\n", DllName, value);
|
||||
// if (_wcsicmp(value, DllName) == 0) {
|
||||
// retval = TRUE;
|
||||
// break;
|
||||
// }
|
||||
// ++idx;
|
||||
// }
|
||||
//
|
||||
// Conf_AdjustUseCount(FALSE);
|
||||
//
|
||||
// return retval;
|
||||
//}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -1419,32 +1420,33 @@ _FX NTSTATUS File_Generic_MyParseProc(
|
|||
// has been initialized, then pretend the file does not exist,
|
||||
// and add the DLL path so it can be loaded by SbieDll
|
||||
//
|
||||
|
||||
if ((! proc->sbiedll_loaded) && status == STATUS_SUCCESS
|
||||
&& (CreateOptions & FILE_DIRECTORY_FILE) == 0) {
|
||||
|
||||
WCHAR *backslash = wcsrchr(path, L'\\');
|
||||
if (backslash && File_IsDelayLoadDll(proc, backslash + 1)) {
|
||||
|
||||
ULONG len = sizeof(BLOCKED_DLL) + path_len * sizeof(WCHAR);
|
||||
BLOCKED_DLL *blk = Mem_Alloc(proc->pool, len);
|
||||
if (blk) {
|
||||
|
||||
blk->path_len = path_len;
|
||||
wmemcpy(blk->path, path, path_len + 1);
|
||||
|
||||
KeRaiseIrql(APC_LEVEL, &irql);
|
||||
ExAcquireResourceExclusiveLite(proc->file_lock, TRUE);
|
||||
|
||||
List_Insert_After(&proc->blocked_dlls, NULL, blk);
|
||||
|
||||
ExReleaseResourceLite(proc->file_lock);
|
||||
KeLowerIrql(irql);
|
||||
}
|
||||
|
||||
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
// DX: this info does not seam to be so no point in saving this data
|
||||
//
|
||||
//if ((! proc->sbiedll_loaded) && status == STATUS_SUCCESS
|
||||
// && (CreateOptions & FILE_DIRECTORY_FILE) == 0) {
|
||||
//
|
||||
// WCHAR *backslash = wcsrchr(path, L'\\');
|
||||
// if (backslash && File_IsDelayLoadDll(proc, backslash + 1)) {
|
||||
//
|
||||
// ULONG len = sizeof(BLOCKED_DLL) + path_len * sizeof(WCHAR);
|
||||
// BLOCKED_DLL *blk = Mem_Alloc(proc->pool, len);
|
||||
// if (blk) {
|
||||
//
|
||||
// blk->path_len = path_len;
|
||||
// wmemcpy(blk->path, path, path_len + 1);
|
||||
//
|
||||
// KeRaiseIrql(APC_LEVEL, &irql);
|
||||
// ExAcquireResourceExclusiveLite(proc->file_lock, TRUE);
|
||||
//
|
||||
// List_Insert_After(&proc->blocked_dlls, NULL, blk);
|
||||
//
|
||||
// ExReleaseResourceLite(proc->file_lock);
|
||||
// KeLowerIrql(irql);
|
||||
// }
|
||||
//
|
||||
// status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
// }
|
||||
//}
|
||||
|
||||
//
|
||||
// release temporary path
|
||||
|
@ -2513,69 +2515,69 @@ get_program:
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX NTSTATUS File_Api_GetBlockedDll(PROCESS *proc, ULONG64 *parms)
|
||||
{
|
||||
API_GET_BLOCKED_DLL_ARGS *args = (API_GET_BLOCKED_DLL_ARGS *)parms;
|
||||
WCHAR *user_buf;
|
||||
ULONG user_len;
|
||||
ULONG len;
|
||||
NTSTATUS status;
|
||||
BLOCKED_DLL *blk;
|
||||
KIRQL irql;
|
||||
|
||||
//
|
||||
// this API must be invoked by a sandboxed process
|
||||
//
|
||||
|
||||
if (! proc)
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
//
|
||||
// check input buffers
|
||||
//
|
||||
|
||||
user_buf = args->dll_name_buf.val;
|
||||
user_len = args->dll_name_len.val / sizeof(WCHAR);
|
||||
if ((! user_buf) || (! user_len))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
//
|
||||
// return first blocked dll in the list
|
||||
//
|
||||
|
||||
KeRaiseIrql(APC_LEVEL, &irql);
|
||||
ExAcquireResourceExclusiveLite(proc->file_lock, TRUE);
|
||||
|
||||
blk = List_Head(&proc->blocked_dlls);
|
||||
if (! blk)
|
||||
status = STATUS_END_OF_FILE;
|
||||
else {
|
||||
|
||||
__try {
|
||||
|
||||
len = blk->path_len;
|
||||
if (len >= user_len)
|
||||
len = user_len - 1;
|
||||
|
||||
ProbeForWrite(
|
||||
user_buf, sizeof(WCHAR) * (len + 1), sizeof(WCHAR));
|
||||
wmemcpy(user_buf, blk->path, len);
|
||||
user_buf[len] = L'\0';
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
status = GetExceptionCode();
|
||||
}
|
||||
|
||||
List_Remove(&proc->blocked_dlls, blk);
|
||||
|
||||
len = sizeof(BLOCKED_DLL) + blk->path_len * sizeof(WCHAR);
|
||||
Mem_Free(blk, len);
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(proc->file_lock);
|
||||
KeLowerIrql(irql);
|
||||
|
||||
return status;
|
||||
}
|
||||
//_FX NTSTATUS File_Api_GetBlockedDll(PROCESS *proc, ULONG64 *parms)
|
||||
//{
|
||||
// API_GET_BLOCKED_DLL_ARGS *args = (API_GET_BLOCKED_DLL_ARGS *)parms;
|
||||
// WCHAR *user_buf;
|
||||
// ULONG user_len;
|
||||
// ULONG len;
|
||||
// NTSTATUS status;
|
||||
// BLOCKED_DLL *blk;
|
||||
// KIRQL irql;
|
||||
//
|
||||
// //
|
||||
// // this API must be invoked by a sandboxed process
|
||||
// //
|
||||
//
|
||||
// if (! proc)
|
||||
// return STATUS_NOT_IMPLEMENTED;
|
||||
//
|
||||
// //
|
||||
// // check input buffers
|
||||
// //
|
||||
//
|
||||
// user_buf = args->dll_name_buf.val;
|
||||
// user_len = args->dll_name_len.val / sizeof(WCHAR);
|
||||
// if ((! user_buf) || (! user_len))
|
||||
// return STATUS_INVALID_PARAMETER;
|
||||
//
|
||||
// //
|
||||
// // return first blocked dll in the list
|
||||
// //
|
||||
//
|
||||
// KeRaiseIrql(APC_LEVEL, &irql);
|
||||
// ExAcquireResourceExclusiveLite(proc->file_lock, TRUE);
|
||||
//
|
||||
// blk = List_Head(&proc->blocked_dlls);
|
||||
// if (! blk)
|
||||
// status = STATUS_END_OF_FILE;
|
||||
// else {
|
||||
//
|
||||
// __try {
|
||||
//
|
||||
// len = blk->path_len;
|
||||
// if (len >= user_len)
|
||||
// len = user_len - 1;
|
||||
//
|
||||
// ProbeForWrite(
|
||||
// user_buf, sizeof(WCHAR) * (len + 1), sizeof(WCHAR));
|
||||
// wmemcpy(user_buf, blk->path, len);
|
||||
// user_buf[len] = L'\0';
|
||||
//
|
||||
// status = STATUS_SUCCESS;
|
||||
//
|
||||
// } __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
// status = GetExceptionCode();
|
||||
// }
|
||||
//
|
||||
// List_Remove(&proc->blocked_dlls, blk);
|
||||
//
|
||||
// len = sizeof(BLOCKED_DLL) + blk->path_len * sizeof(WCHAR);
|
||||
// Mem_Free(blk, len);
|
||||
// }
|
||||
//
|
||||
// ExReleaseResourceLite(proc->file_lock);
|
||||
// KeLowerIrql(irql);
|
||||
//
|
||||
// return status;
|
||||
//}
|
||||
|
|
|
@ -59,7 +59,7 @@ NTSTATUS File_Api_Open(PROCESS *proc, ULONG64 *parms);
|
|||
|
||||
NTSTATUS File_Api_CheckInternetAccess(PROCESS *proc, ULONG64 *parms);
|
||||
|
||||
NTSTATUS File_Api_GetBlockedDll(PROCESS *proc, ULONG64 *parms);
|
||||
//NTSTATUS File_Api_GetBlockedDll(PROCESS *proc, ULONG64 *parms);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -142,7 +142,7 @@ struct _PROCESS {
|
|||
LIST read_file_paths; // PATTERN elements
|
||||
LIST write_file_paths; // PATTERN elements
|
||||
BOOLEAN always_close_for_boxed;
|
||||
LIST blocked_dlls;
|
||||
//LIST blocked_dlls;
|
||||
ULONG file_trace;
|
||||
ULONG pipe_trace;
|
||||
BOOLEAN disable_file_flt;
|
||||
|
|
|
@ -113,7 +113,9 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
|||
if (Group.isEmpty())
|
||||
continue;
|
||||
QVariant ID = CSbieModel__AddGroupMark(Group);
|
||||
|
||||
|
||||
QModelIndex Index;
|
||||
|
||||
QHash<QVariant, STreeNode*>::iterator I = Old.find(ID);
|
||||
SSandBoxNode* pNode = I != Old.end() ? static_cast<SSandBoxNode*>(I.value()) : NULL;
|
||||
if (!pNode)
|
||||
|
@ -135,7 +137,20 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
|||
else
|
||||
{
|
||||
I.value() = NULL;
|
||||
Index = Find(m_Root, pNode);
|
||||
}
|
||||
|
||||
int Changed = 0;
|
||||
|
||||
QString ParentGroup = pNode->Path.isEmpty() ? "" : CSbieModel__RemoveGroupMark(pNode->Path.last().toString());
|
||||
int OrderNumber = Groups[ParentGroup].indexOf(Group);
|
||||
if (pNode->OrderNumber != OrderNumber) {
|
||||
pNode->OrderNumber = OrderNumber;
|
||||
Changed = 1;
|
||||
}
|
||||
|
||||
if (Changed && Index.isValid())
|
||||
emit dataChanged(createIndex(Index.row(), 0, pNode), createIndex(Index.row(), columnCount()-1, pNode));
|
||||
}
|
||||
|
||||
foreach (const CSandBoxPtr& pBox, BoxList)
|
||||
|
@ -171,6 +186,13 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, cons
|
|||
bool State = false;
|
||||
int Changed = 0;
|
||||
|
||||
QString Group = pNode->Path.isEmpty() ? "" : CSbieModel__RemoveGroupMark(pNode->Path.last().toString());
|
||||
int OrderNumber = Groups[Group].indexOf(pBox->GetName());
|
||||
if (pNode->OrderNumber != OrderNumber) {
|
||||
pNode->OrderNumber = OrderNumber;
|
||||
Changed = 1;
|
||||
}
|
||||
|
||||
QMap<quint32, CBoxedProcessPtr> ProcessList = pBox->GetProcessList();
|
||||
|
||||
bool inUse = Sync(pBox, pNode->Path, ProcessList, New, Old, Added);
|
||||
|
@ -355,6 +377,14 @@ bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QList<QVariant>& Path, cons
|
|||
return ActiveCount != 0;
|
||||
}
|
||||
|
||||
QVariant CSbieModel::NodeData(STreeNode* pNode, int role, int section) const
|
||||
{
|
||||
if (section == 0 && role == Qt::InitialSortOrderRole) {
|
||||
return ((SSandBoxNode*)pNode)->OrderNumber;
|
||||
}
|
||||
return CTreeItemModel::NodeData(pNode, role, section);
|
||||
}
|
||||
|
||||
CSandBoxPtr CSbieModel::GetSandBox(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
|
|
|
@ -46,15 +46,18 @@ protected:
|
|||
|
||||
struct SSandBoxNode: STreeNode
|
||||
{
|
||||
SSandBoxNode(const QVariant& Id) : STreeNode(Id) { inUse = false; boxType = -1; }
|
||||
SSandBoxNode(const QVariant& Id) : STreeNode(Id) { inUse = false; boxType = -1; OrderNumber = 0; }
|
||||
|
||||
CSandBoxPtr pBox;
|
||||
bool inUse;
|
||||
int boxType;
|
||||
int OrderNumber;
|
||||
|
||||
CBoxedProcessPtr pProcess;
|
||||
};
|
||||
|
||||
virtual QVariant NodeData(STreeNode* pNode, int role, int section) const;
|
||||
|
||||
virtual STreeNode* MkNode(const QVariant& Id) { return new SSandBoxNode(Id); }
|
||||
|
||||
QList<QVariant> MakeProcPath(const QString& BoxName, const CBoxedProcessPtr& pProcess, const QMap<quint32, CBoxedProcessPtr>& ProcessList);
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 810 B |
Binary file not shown.
After Width: | Height: | Size: 726 B |
Binary file not shown.
After Width: | Height: | Size: 780 B |
|
@ -60,6 +60,9 @@
|
|||
<file>IconOffC.png</file>
|
||||
<file>IconFullC.png</file>
|
||||
<file>IconEmptyC.png</file>
|
||||
<file>Actions/Duplicate.png</file>
|
||||
<file>Actions/Up.png</file>
|
||||
<file>Actions/Down.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/Boxes">
|
||||
<file alias="Empty3">Boxes/sandbox-b-empty.png</file>
|
||||
|
|
|
@ -45,6 +45,11 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
|||
|
||||
m_pSbieTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_pSbieTree->setSortingEnabled(true);
|
||||
//m_pSbieTree->setSortingEnabled(false);
|
||||
m_pSbieTree->setUniformRowHeights(true);
|
||||
//m_pSbieTree->header()->setSortIndicatorShown(true);
|
||||
//m_pSbieTree->header()->setSectionsClickable(true);
|
||||
connect(m_pSbieTree->header(), SIGNAL(sectionClicked(int)), this, SLOT(OnCustomSortByColumn(int)));
|
||||
|
||||
m_pSbieTree->setStyle(pStyle);
|
||||
|
||||
|
@ -64,7 +69,8 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
|||
connect(m_pSbieModel, SIGNAL(ToolTipCallback(const QVariant&, QString&)), this, SLOT(OnToolTipCallback(const QVariant&, QString&)), Qt::DirectConnection);
|
||||
|
||||
m_pNewBox = m_pMenu->addAction(CSandMan::GetIcon("NewBox"), tr("Create New Box"), this, SLOT(OnGroupAction()));
|
||||
m_pAddGroupe = m_pMenu->addAction(CSandMan::GetIcon("Group"), tr("Add Group"), this, SLOT(OnGroupAction()));
|
||||
m_pAddGroupe = m_pMenu->addAction(CSandMan::GetIcon("Group"), tr("Create Box Group"), this, SLOT(OnGroupAction()));
|
||||
m_pRenGroupe = m_pMenu->addAction(CSandMan::GetIcon("Rename"), tr("Rename Group"), this, SLOT(OnGroupAction()));
|
||||
m_pDelGroupe = m_pMenu->addAction(CSandMan::GetIcon("Remove"), tr("Remove Group"), this, SLOT(OnGroupAction()));
|
||||
m_iMenuTop = m_pMenu->actions().count();
|
||||
//m_pMenu->addSeparator();
|
||||
|
@ -119,7 +125,17 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
|||
|
||||
m_pMenuRename = m_pMenu->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction()));
|
||||
m_iMoveTo = m_pMenu->actions().count();
|
||||
m_pMenuMoveTo = m_pMenu->addMenu(CSandMan::GetIcon("Group"), tr("Move to Group"));
|
||||
m_pMenuMoveTo = m_pMenu->addMenu(CSandMan::GetIcon("Group"), tr("Move Box/Group"));
|
||||
m_pMenuMoveUp = m_pMenuMoveTo->addAction(CSandMan::GetIcon("Up"), tr("Move Up"), this, SLOT(OnGroupAction()));
|
||||
m_pMenuMoveUp->setShortcut(QKeySequence("Alt+Up"));
|
||||
m_pMenuMoveUp->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
this->addAction(m_pMenuMoveUp);
|
||||
//m_pMenuMoveBy = m_pMenuMoveTo->addAction(tr("Move to Position"), this, SLOT(OnGroupAction())); // does not seam that intuitive for users
|
||||
m_pMenuMoveDown = m_pMenuMoveTo->addAction(CSandMan::GetIcon("Down"), tr("Move Down"), this, SLOT(OnGroupAction()));
|
||||
m_pMenuMoveDown->setShortcut(QKeySequence("Alt+Down"));
|
||||
m_pMenuMoveDown->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
this->addAction(m_pMenuMoveDown);
|
||||
m_pMenuMoveTo->addSeparator();
|
||||
m_pMenuRemove = m_pMenu->addAction(CSandMan::GetIcon("Remove"), tr("Remove Sandbox"), this, SLOT(OnSandBoxAction()));
|
||||
m_iMenuBox = m_pMenu->actions().count();
|
||||
|
||||
|
@ -175,6 +191,11 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
|||
}
|
||||
else
|
||||
m_pSbieTree->restoreState(Columns);
|
||||
if (theConf->GetBool("MainWindow/BoxTree_UseOrder", false)) {
|
||||
m_pSortProxy->sort(0, Qt::AscendingOrder);
|
||||
m_pSortProxy->setSortRole(Qt::InitialSortOrderRole);
|
||||
m_pSbieTree->header()->setSortIndicatorShown(false);
|
||||
}
|
||||
|
||||
//m_pMenu = new QMenu();
|
||||
AddPanelItemsToMenu();
|
||||
|
@ -183,6 +204,7 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
|||
CSbieView::~CSbieView()
|
||||
{
|
||||
theConf->SetBlob("MainWindow/BoxTree_Columns", m_pSbieTree->saveState());
|
||||
theConf->SetValue("MainWindow/BoxTree_UseOrder", m_pSortProxy->sortRole() == Qt::InitialSortOrderRole);
|
||||
}
|
||||
|
||||
void CSbieView::Clear()
|
||||
|
@ -231,6 +253,28 @@ void CSbieView::OnToolTipCallback(const QVariant& ID, QString& ToolTip)
|
|||
}
|
||||
}
|
||||
|
||||
void CSbieView::OnCustomSortByColumn(int column)
|
||||
{
|
||||
Qt::SortOrder order = m_pSbieTree->header()->sortIndicatorOrder();
|
||||
//m_pSbieTree->sortByColumn(column, order);
|
||||
//m_pSbieTree->header()->setSortIndicatorShown(true);
|
||||
if (column == 0) {
|
||||
if (m_pSortProxy->sortRole() == Qt::InitialSortOrderRole) {
|
||||
m_pSortProxy->sort(0, Qt::AscendingOrder);
|
||||
m_pSortProxy->setSortRole(Qt::EditRole);
|
||||
m_pSbieTree->header()->setSortIndicatorShown(true);
|
||||
} else if (order == Qt::DescendingOrder) {
|
||||
m_pSortProxy->sort(0, Qt::AscendingOrder);
|
||||
m_pSortProxy->setSortRole(Qt::InitialSortOrderRole);
|
||||
m_pSbieTree->header()->setSortIndicatorShown(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_pSortProxy->setSortRole(Qt::EditRole);
|
||||
m_pSbieTree->header()->setSortIndicatorShown(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CSbieView::UpdateMenu()
|
||||
{
|
||||
QList<QAction*> MenuActions = m_pMenu->actions();
|
||||
|
@ -245,6 +289,7 @@ void CSbieView::UpdateMenu()
|
|||
CBoxedProcessPtr pProcess;
|
||||
int iProcessCount = 0;
|
||||
int iSandBoxeCount = 0;
|
||||
int iGroupe = 0;
|
||||
//int iSuspendedCount = 0;
|
||||
QModelIndexList Rows = m_pSbieTree->selectedRows();
|
||||
foreach(const QModelIndex& Index, Rows)
|
||||
|
@ -268,12 +313,15 @@ void CSbieView::UpdateMenu()
|
|||
else if (iSandBoxeCount != -1)
|
||||
iSandBoxeCount++;
|
||||
}
|
||||
else
|
||||
iGroupe++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < m_iMenuTop; i++)
|
||||
MenuActions[i]->setVisible(iSandBoxeCount == 0 && iProcessCount == 0);
|
||||
m_pRenGroupe->setVisible(iGroupe == 1 && iSandBoxeCount == 0 && iProcessCount == 0);
|
||||
m_pDelGroupe->setVisible(!Rows.isEmpty() && iSandBoxeCount == 0 && iProcessCount == 0);
|
||||
|
||||
for (int i = m_iMenuTop; i < m_iMenuBox; i++)
|
||||
|
@ -400,14 +448,30 @@ void CSbieView::ReloadGroups()
|
|||
void CSbieView::UpdateGroupMenu()
|
||||
{
|
||||
// update move to menu
|
||||
foreach(QAction* pAction, m_pMenuMoveTo->actions())
|
||||
m_pMenuMoveTo->removeAction(pAction);
|
||||
|
||||
foreach(QAction * pAction, m_pMenuMoveTo->actions()) {
|
||||
if (!pAction->data().toString().isNull())
|
||||
m_pMenuMoveTo->removeAction(pAction);
|
||||
}
|
||||
|
||||
foreach(const QString& Group, m_Groups.keys())
|
||||
{
|
||||
QAction* pAction = m_pMenuMoveTo->addAction(Group.isEmpty() ? tr("[None]") : Group, this, SLOT(OnGroupAction()));
|
||||
pAction->setData(Group);
|
||||
}
|
||||
m_pMenuMoveTo->setEnabled(m_Groups.keys().count() > 1);
|
||||
//m_pMenuMoveTo->setEnabled(m_Groups.keys().count() > 1);
|
||||
}
|
||||
|
||||
void CSbieView::RenameGroup(const QString OldName, const QString NewName)
|
||||
{
|
||||
auto Group = m_Groups.take(OldName);
|
||||
m_Groups.insert(NewName, Group);
|
||||
|
||||
for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I)
|
||||
{
|
||||
if (I.value().removeOne(OldName))
|
||||
I.value().append(NewName);
|
||||
}
|
||||
}
|
||||
|
||||
QString CSbieView__SerializeGroup(QMap<QString, QStringList>& m_Groups, const QString& Parent = "")
|
||||
|
@ -443,6 +507,26 @@ bool CSbieView::IsParentOf(const QString& Name, const QString& Group)
|
|||
return IsParentOf(Name, Parent);
|
||||
}
|
||||
|
||||
QStringList CSbieView::GetSelectedGroups(bool bAndBoxes)
|
||||
{
|
||||
QStringList list;
|
||||
foreach(const QModelIndex & Index, m_pSbieTree->selectedRows())
|
||||
{
|
||||
QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index);
|
||||
QString Name;
|
||||
if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eGroup)
|
||||
Name = m_pSbieModel->GetID(ModelIndex).toString();
|
||||
else if (bAndBoxes && m_pSbieModel->GetType(ModelIndex) == CSbieModel::eBox)
|
||||
Name = m_pSbieModel->GetSandBox(ModelIndex)->GetName();
|
||||
|
||||
if (Name.isEmpty())
|
||||
continue;
|
||||
|
||||
list.append(Name);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void CSbieView::OnGroupAction()
|
||||
{
|
||||
QAction* Action = qobject_cast<QAction*>(sender());
|
||||
|
@ -453,18 +537,38 @@ void CSbieView::OnGroupAction()
|
|||
if (Name.isEmpty())
|
||||
return;
|
||||
|
||||
QModelIndex ModelIndex = m_pSortProxy->mapToSource(m_pSbieTree->currentIndex());
|
||||
QString Parent;
|
||||
if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eGroup)
|
||||
Parent = m_pSbieModel->GetID(ModelIndex).toString();
|
||||
|
||||
m_Groups[Parent].append(Name);
|
||||
QStringList List = GetSelectedGroups();
|
||||
if (List.isEmpty())
|
||||
return;
|
||||
|
||||
m_Groups[List.first()].append(Name);
|
||||
|
||||
m_pSbieModel->Clear(); //todo improve that
|
||||
}
|
||||
else if (Action == m_pAddGroupe)
|
||||
{
|
||||
AddNewGroup();
|
||||
return;
|
||||
}
|
||||
else if (Action == m_pRenGroupe)
|
||||
{
|
||||
QStringList List = GetSelectedGroups();
|
||||
if (List.isEmpty())
|
||||
return;
|
||||
|
||||
QString OldValue = List.first();
|
||||
|
||||
QString Value = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a new name for the Group."), QLineEdit::Normal, OldValue);
|
||||
if (Value.isEmpty() || Value == OldValue)
|
||||
return;
|
||||
if (m_Groups.contains(Value)) {
|
||||
QMessageBox("Sandboxie-Plus", tr("This Group name is already in use."), QMessageBox::Information, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton, this).exec();
|
||||
return;
|
||||
}
|
||||
|
||||
RenameGroup(OldValue, Value);
|
||||
|
||||
m_pSbieModel->Clear(); //todo improve that
|
||||
}
|
||||
else if (Action == m_pDelGroupe)
|
||||
{
|
||||
|
@ -493,22 +597,39 @@ void CSbieView::OnGroupAction()
|
|||
|
||||
m_pSbieModel->Clear(); //todo improve that, also move boxes to grant parent?
|
||||
}
|
||||
else if (Action == m_pMenuMoveUp /*|| Action == m_pMenuMoveBy*/ || Action == m_pMenuMoveDown)
|
||||
{
|
||||
int Offset = 0;
|
||||
if (Action == m_pMenuMoveUp)
|
||||
Offset = -1;
|
||||
else if (Action == m_pMenuMoveDown)
|
||||
Offset = 1;
|
||||
else
|
||||
Offset = QInputDialog::getInt(this, "Sandboxie-Plus", tr("Move entries by (negative values move up oositive values move down):"), 0);
|
||||
if (Offset == 0)
|
||||
return;
|
||||
|
||||
// todo: fix behavioure on multiple selelction
|
||||
foreach(const QString& Name, GetSelectedGroups(true)) {
|
||||
for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) {
|
||||
int pos = I->indexOf(Name);
|
||||
if (pos != -1) {
|
||||
if ((Offset < 0 && pos > Offset + 1) ||(Offset > 0 && pos < I->count() - Offset)){
|
||||
QString Temp = I.value()[pos+Offset];
|
||||
I.value()[pos+Offset] = I.value()[pos];
|
||||
I.value()[pos] = Temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // move to groupe
|
||||
{
|
||||
QString Group = Action->data().toString();
|
||||
|
||||
foreach(const QModelIndex& Index, m_pSbieTree->selectedRows())
|
||||
foreach(const QString& Name, GetSelectedGroups(true))
|
||||
{
|
||||
QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index);
|
||||
QString Name;
|
||||
if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eGroup)
|
||||
Name = m_pSbieModel->GetID(ModelIndex).toString();
|
||||
else if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eBox)
|
||||
Name = m_pSbieModel->GetSandBox(ModelIndex)->GetName();
|
||||
|
||||
if (Name.isEmpty())
|
||||
continue;
|
||||
|
||||
if (Name == Group || IsParentOf(Name, Group)) {
|
||||
QMessageBox("Sandboxie-Plus", tr("A group can not be its own parent."), QMessageBox::Critical, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton, this).exec();
|
||||
continue;
|
||||
|
@ -559,6 +680,10 @@ QString CSbieView::AddNewGroup()
|
|||
|
||||
m_Groups[Parent].append(Name);
|
||||
|
||||
QString Grouping = CSbieView__SerializeGroup(m_Groups);
|
||||
theAPI->GetUserSettings()->SetText("BoxDisplayOrder", Grouping);
|
||||
UpdateGroupMenu();
|
||||
|
||||
return Name;
|
||||
}
|
||||
|
||||
|
@ -730,6 +855,8 @@ void CSbieView::OnSandBoxAction(QAction* Action)
|
|||
if (Value.isEmpty() || Value == OldValue)
|
||||
return;
|
||||
Results.append((SandBoxes.first()->RenameBox(Value.replace(" ", "_"))));
|
||||
|
||||
RenameGroup(OldValue, Value);
|
||||
}
|
||||
else if (Action == m_pMenuRecover)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ public:
|
|||
|
||||
virtual QList<CSandBoxPtr> GetSelectedBoxes();
|
||||
virtual QList<CBoxedProcessPtr> GetSelectedProcesses();
|
||||
virtual QStringList GetSelectedGroups(bool bAndBoxes = false);
|
||||
|
||||
//virtual void UpdateRunMenu();
|
||||
|
||||
|
@ -33,6 +34,8 @@ public slots:
|
|||
private slots:
|
||||
void OnToolTipCallback(const QVariant& ID, QString& ToolTip);
|
||||
|
||||
void OnCustomSortByColumn(int column);
|
||||
|
||||
void OnDoubleClicked(const QModelIndex& index);
|
||||
void ProcessSelection(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
|
||||
|
@ -54,6 +57,7 @@ private:
|
|||
|
||||
void UpdateMenu();
|
||||
void UpdateGroupMenu();
|
||||
void RenameGroup(const QString OldName, const QString NewName);
|
||||
|
||||
QString FindParent(const QString& Name);
|
||||
bool IsParentOf(const QString& Name, const QString& Group);
|
||||
|
@ -68,6 +72,7 @@ private:
|
|||
|
||||
QAction* m_pNewBox;
|
||||
QAction* m_pAddGroupe;
|
||||
QAction* m_pRenGroupe;
|
||||
QAction* m_pDelGroupe;
|
||||
int m_iMenuTop;
|
||||
QMenu* m_pMenuRun;
|
||||
|
@ -101,6 +106,9 @@ private:
|
|||
QAction* m_pMenuRecover;
|
||||
QAction* m_pMenuCleanUp;
|
||||
QAction* m_pMenuRemove;
|
||||
QAction* m_pMenuMoveUp;
|
||||
//QAction* m_pMenuMoveBy;
|
||||
QAction* m_pMenuMoveDown;
|
||||
QMenu* m_pMenuMoveTo;
|
||||
int m_iMoveTo;
|
||||
QAction* m_pMenuRename;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#define VERSION_MJR 0
|
||||
#define VERSION_MIN 9
|
||||
#define VERSION_REV 5
|
||||
#define VERSION_REV 6
|
||||
#define VERSION_UPD 0
|
||||
|
||||
#ifndef STR
|
||||
|
|
Loading…
Reference in New Issue