#include "stdafx.h" #include "SbieView.h" #include "..\SandMan.h" #include "../QSbieAPI/SbieAPI.h" #include "../QSbieAPI/SbieUtils.h" #include "../../MiscHelpers/Common/SortFilterProxyModel.h" #include "../../MiscHelpers/Common/Settings.h" #include "../../MiscHelpers/Common/Common.h" #include "../Windows/OptionsWindow.h" #include "../Windows/SnapshotsWindow.h" #include "../../MiscHelpers/Common/CheckableMessageBox.h" #include "../Windows/RecoveryWindow.h" #include "../Views/FileView.h" #include "../Wizards/NewBoxWizard.h" #include "../Helpers/WinHelper.h" #include "../Windows/BoxImageWindow.h" #include "../MiscHelpers/Archive/Archive.h" #include "../Windows/SettingsWindow.h" #include "../Windows/CompressDialog.h" #include "qt_windows.h" #include "qwindowdefs_win.h" #include CSbieView::CSbieView(QWidget* parent) : CPanelView(parent) { m_pMainLayout = new QVBoxLayout(); m_pMainLayout->setContentsMargins(0,0,0,0); this->setLayout(m_pMainLayout); m_HoldExpand = false; m_pSbieModel = new CSbieModel(this); m_pSbieModel->SetTree(true); m_pSbieModel->SetUseIcons(true); m_pSortProxy = new CSortFilterProxyModel(this); m_pSortProxy->setSortRole(Qt::EditRole); m_pSortProxy->setSourceModel(m_pSbieModel); m_pSortProxy->setDynamicSortFilter(true); // SbieTree m_pSbieTree = new QTreeViewEx(); m_pSbieTree->setColumnFixed(0, true); m_pSbieTree->setAlternatingRowColors(theConf->GetBool("Options/AltRowColors", false)); m_pSbieTree->setExpandsOnDoubleClick(false); //m_pSbieTree->setItemDelegate(theGUI->GetItemDelegate()); m_pSbieTree->setModel(m_pSortProxy); int iViewMode = theConf->GetInt("Options/ViewMode", 1); int iLargeIcons = theConf->GetInt("Options/LargeIcons", 2); if (iLargeIcons == 2) iLargeIcons = iViewMode == 2 ? 1 : 0; if (iLargeIcons) { m_pSbieModel->SetLargeIcons(); m_pSbieTree->setIconSize(QSize(32, 32)); } m_pSbieTree->setDragDropMode(QAbstractItemView::InternalMove); m_pSbieTree->setSelectionMode(QAbstractItemView::ExtendedSelection); m_pSbieTree->setSortingEnabled(true); //m_pSbieTree->setSortingEnabled(false); //m_pSbieTree->header()->setSortIndicatorShown(true); //m_pSbieTree->header()->setSectionsClickable(true); if(iViewMode != 2) connect(m_pSbieTree->header(), SIGNAL(sectionClicked(int)), this, SLOT(OnCustomSortByColumn(int))); QStyle* pStyle = QStyleFactory::create("windows"); m_pSbieTree->setStyle(pStyle); m_pSbieTree->setItemDelegate(iLargeIcons ? new CTreeItemDelegate2() : new CTreeItemDelegate()); m_pSbieTree->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_pSbieTree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnMenu(const QPoint &))); connect(m_pSbieTree, SIGNAL(pressed(const QModelIndex&)), this, SLOT(OnClicked(const QModelIndex&))); connect(m_pSbieTree, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(OnDoubleClicked(const QModelIndex&))); connect(m_pSbieTree->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(ProcessSelection(QItemSelection, QItemSelection))); connect(m_pSbieTree, SIGNAL(expanded(const QModelIndex &)), this, SLOT(OnExpanded(const QModelIndex &))); connect(m_pSbieTree, SIGNAL(collapsed(const QModelIndex &)), this, SLOT(OnCollapsed(const QModelIndex &))); //connect(theGUI, SIGNAL(ReloadPanels()), m_pSbieModel, SLOT(Clear())); connect(m_pSbieModel, SIGNAL(MoveBox(const QString&, const QString&, int)), this, SLOT(OnMoveItem(const QString&, const QString&, int))); connect(m_pSbieModel, SIGNAL(MoveGroup(const QString&, const QString&, int)), this, SLOT(OnMoveItem(const QString&, const QString&, int))); m_pMainLayout->addWidget(m_pSbieTree); // CFinder* pFinder = new CFinder(m_pSortProxy, this); m_pMainLayout->addWidget(pFinder); pFinder->SetTree(m_pSbieTree); connect(m_pSbieModel, SIGNAL(ToolTipCallback(const QVariant&, QString&)), this, SLOT(OnToolTipCallback(const QVariant&, QString&)), Qt::DirectConnection); if(iViewMode == 2) CreateOldMenu(); else CreateMenu(); m_pCtxMenu = new QMenu(); m_pCtxPinToRun = m_pCtxMenu->addAction(tr("Pin to Run Menu"), this, SLOT(OnMenuContextAction())); m_pCtxPinToRun->setCheckable(true); m_pCtxMkLink = m_pCtxMenu->addAction(CSandMan::GetIcon("MkLink"), tr("Create Shortcut"), this, SLOT(OnMenuContextAction())); m_pRemove = new QAction(this); m_pRemove->setShortcut(QKeySequence::Delete); m_pRemove->setShortcutContext(Qt::WidgetWithChildrenShortcut); this->addAction(m_pRemove); connect(m_pRemove, SIGNAL(triggered()), this, SLOT(OnRemoveItem())); CreateGroupMenu(); CreateTrayMenu(); QByteArray Columns = theConf->GetBlob("MainWindow/BoxTree_Columns"); if (Columns.isEmpty()) { m_pSbieTree->setColumnWidth(0, 300); m_pSbieTree->setColumnWidth(1, 70); m_pSbieTree->setColumnWidth(2, 70); m_pSbieTree->setColumnWidth(3, 70); } else m_pSbieTree->restoreState(Columns); if (theConf->GetBool("MainWindow/BoxTree_UseOrder", false) || iViewMode == 2) SetCustomOrder(); //m_pMenu = new QMenu(); AddPanelItemsToMenu(); AddCopyMenu(m_pMenuBox); AddCopyMenu(m_pMenuProcess); AddCopyMenu(m_pMenuGroup); } CSbieView::~CSbieView() { SaveState(); } void CSbieView::SaveState() { theConf->SetBlob("MainWindow/BoxTree_Columns", m_pSbieTree->saveState()); //theConf->SetValue("MainWindow/BoxTree_UseOrder", m_pSortProxy->sortRole() == Qt::InitialSortOrderRole); } void CSbieView::Clear() { m_Groups.clear(); m_pSbieModel->Clear(); } void CSbieView::CreateMenu() { m_pNewBox = m_pMenu->addAction(CSandMan::GetIcon("NewBox"), tr("Create New Box"), this, SLOT(OnGroupAction())); m_pAddGroupe = m_pMenu->addAction(CSandMan::GetIcon("Group"), tr("Create Box Group"), this, SLOT(OnGroupAction())); m_pImportBox = m_pMenu->addAction(CSandMan::GetIcon("UnPackBox"), tr("Import Box"), this, SLOT(OnGroupAction())); m_pImportBox->setEnabled(CArchive::IsInit()); m_pMenuBox = new QMenu(); m_pStopAsync = m_pMenuBox->addAction(CSandMan::GetIcon("Stop"), tr("Stop Operations"), this, SLOT(OnSandBoxAction())); //m_pMenuBox->addSeparator(); //m_pMenuRun = m_pMenuBox->addMenu(CSandMan::GetIcon("Start"), tr("Run")); m_pMenuRun = new CMenuEx(tr("Run"), m_pMenuBox); m_pMenuRun->setIcon(CSandMan::GetIcon("Start")); m_pMenuBox->addAction(m_pMenuRun->menuAction()); connect(m_pMenuRun, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnMenuContextMenu(const QPoint&))); m_pMenuRunAny = m_pMenuRun->addAction(CSandMan::GetIcon("Run"), tr("Run Program"), this, SLOT(OnSandBoxAction())); m_pMenuRunMenu = m_pMenuRun->addAction(CSandMan::GetIcon("StartMenu"), tr("Run from Start Menu"), this, SLOT(OnSandBoxAction())); if (theConf->GetBool("Options/ScanStartMenu", true)) { m_pMenuRunStart = new QMenu(); m_pMenuRunStart->addAction(CSandMan::GetIcon("StartMenu"), tr("(Host) Start Menu"), this, SLOT(OnSandBoxAction())); m_pMenuRunStart->addSeparator(); } 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("Standard Applications")); 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())); m_pMenuRunExplorer = m_pMenuRunTools->addAction(CSandMan::GetIcon("Explore"), tr("Windows Explorer"), this, SLOT(OnSandBoxAction())); m_pMenuRunRegEdit = m_pMenuRunTools->addAction(CSandMan::GetIcon("RegEdit"), tr("Registry Editor"), this, SLOT(OnSandBoxAction())); m_pMenuRunAppWiz = m_pMenuRunTools->addAction(CSandMan::GetIcon("Software"), tr("Programs and Features"), this, SLOT(OnSandBoxAction())); 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())); #ifndef _WIN64 if(CSbieAPI::IsWow64()) #endif 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())); m_pMenuBox->addSeparator(); m_pMenuContent = m_pMenuBox->addMenu(CSandMan::GetIcon("Compatibility"), tr("Box Content")); m_pMenuBrowse = m_pMenuContent->addAction(CSandMan::GetIcon("Folder"), tr("Browse Files"), this, SLOT(OnSandBoxAction())); m_pMenuContent->addSeparator(); m_pMenuRefresh = m_pMenuContent->addAction(CSandMan::GetIcon("Refresh"), tr("Refresh Info"), this, SLOT(OnSandBoxAction())); m_pMenuMkLink = m_pMenuContent->addAction(CSandMan::GetIcon("MkLink"), tr("Create Shortcut"), this, SLOT(OnSandBoxAction())); m_pMenuContent->addSeparator(); m_pMenuExplore = m_pMenuContent->addAction(CSandMan::GetIcon("Explore"), tr("Explore Content"), this, SLOT(OnSandBoxAction())); m_pMenuRegEdit = m_pMenuContent->addAction(CSandMan::GetIcon("RegEdit"), tr("Open Registry"), this, SLOT(OnSandBoxAction())); m_pMenuSnapshots = m_pMenuBox->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction())); m_pMenuMount = m_pMenuBox->addAction(CSandMan::GetIcon("LockOpen"), tr("Mount Box Image"), this, SLOT(OnSandBoxAction())); m_pMenuUnmount = m_pMenuBox->addAction(CSandMan::GetIcon("LockClosed"), tr("Unmount Box Image"), this, SLOT(OnSandBoxAction())); m_pMenuRecover = m_pMenuBox->addAction(CSandMan::GetIcon("Recover"), tr("Recover Files"), this, SLOT(OnSandBoxAction())); m_pMenuCleanUp = m_pMenuBox->addAction(CSandMan::GetIcon("Erase"), tr("Delete Content"), this, SLOT(OnSandBoxAction())); m_pMenuBox->addSeparator(); m_pMenuOptions = m_pMenuBox->addAction(CSandMan::GetIcon("Options"), tr("Sandbox Options"), this, SLOT(OnSandBoxAction())); QFont f = m_pMenuOptions->font(); f.setBold(true); m_pMenuOptions->setFont(f); m_pMenuPresets = m_pMenuBox->addMenu(CSandMan::GetIcon("Presets"), tr("Sandbox Presets")); m_pMenuPresetsAdmin = new QActionGroup(m_pMenuPresets); m_pMenuPresetsShowUAC = MakeAction(m_pMenuPresetsAdmin, m_pMenuPresets, tr("Ask for UAC Elevation"), 0); m_pMenuPresetsNoAdmin = MakeAction(m_pMenuPresetsAdmin, m_pMenuPresets, tr("Drop Admin Rights"), 1); m_pMenuPresetsFakeAdmin = MakeAction(m_pMenuPresetsAdmin, m_pMenuPresets, tr("Emulate Admin Rights"), 1 | 2); if (theAPI->IsRunningAsAdmin()) { m_pMenuPresetsNoAdmin->setEnabled(false); m_pMenuPresetsFakeAdmin->setEnabled(false); } connect(m_pMenuPresetsAdmin, SIGNAL(triggered(QAction*)), this, SLOT(OnSandBoxAction(QAction*))); m_pMenuPresets->addSeparator(); m_pMenuPresetsINet = m_pMenuPresets->addAction(tr("Block Internet Access"), this, SLOT(OnSandBoxAction())); m_pMenuPresetsINet->setCheckable(true); m_pMenuPresetsShares = m_pMenuPresets->addAction(tr("Allow Network Shares"), this, SLOT(OnSandBoxAction())); m_pMenuPresetsShares->setCheckable(true); m_pMenuPresets->addSeparator(); m_pMenuPresetsRecovery = m_pMenuPresets->addAction(tr("Immediate Recovery"), this, SLOT(OnSandBoxAction())); m_pMenuPresetsRecovery->setCheckable(true); m_pMenuPresetsForce = m_pMenuPresets->addAction(tr("Disable Force Rules"), this, SLOT(OnSandBoxAction())); m_pMenuPresetsForce->setCheckable(true); m_pMenuTools = m_pMenuBox->addMenu(CSandMan::GetIcon("Maintenance"), tr("Sandbox Tools")); m_pMenuDuplicate = m_pMenuTools->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Box Config"), this, SLOT(OnSandBoxAction())); m_pMenuExport = m_pMenuTools->addAction(CSandMan::GetIcon("PackBox"), tr("Export Box"), this, SLOT(OnSandBoxAction())); m_pMenuExport->setEnabled(CArchive::IsInit()); m_pMenuRename = m_pMenuBox->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction())); m_pMenuMoveTo = m_pMenuBox->addMenu(CSandMan::GetIcon("Group"), tr("Move Sandbox")); 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_pMenuBox->addAction(CSandMan::GetIcon("Remove"), tr("Remove Sandbox"), this, SLOT(OnSandBoxAction())); // Process Menu m_pMenuProcess = new QMenu(); m_pMenuTerminate = m_pMenuProcess->addAction(CSandMan::GetIcon("Remove"), tr("Terminate"), this, SLOT(OnProcessAction())); this->addAction(m_pMenuTerminate); m_pMenuLinkTo = m_pMenuProcess->addAction(CSandMan::GetIcon("MkLink"), tr("Create Shortcut"), this, SLOT(OnProcessAction())); m_pMenuPreset = m_pMenuProcess->addMenu(CSandMan::GetIcon("Presets"), tr("Preset")); m_pMenuPinToRun = m_pMenuPreset->addAction(tr("Pin to Run Menu"), this, SLOT(OnProcessAction())); m_pMenuPinToRun->setCheckable(true); m_pMenuBlackList = m_pMenuPreset->addAction(tr("Block and Terminate"), this, SLOT(OnProcessAction())); //m_pMenuBlackList->setShortcut(QKeySequence("Shift+Del")); //m_pMenuBlackList->setShortcutContext(Qt::WidgetWithChildrenShortcut); this->addAction(m_pMenuBlackList); m_pMenuAllowInternet = m_pMenuPreset->addAction(tr("Allow internet access"), this, SLOT(OnProcessAction())); m_pMenuAllowInternet->setCheckable(true); m_pMenuMarkForced = m_pMenuPreset->addAction(tr("Force into this sandbox"), this, SLOT(OnProcessAction())); m_pMenuMarkForced->setCheckable(true); m_pMenuMarkLinger = m_pMenuPreset->addAction(tr("Set Linger Process"), this, SLOT(OnProcessAction())); m_pMenuMarkLinger->setCheckable(true); m_pMenuMarkLeader = m_pMenuPreset->addAction(tr("Set Leader Process"), this, SLOT(OnProcessAction())); m_pMenuMarkLeader->setCheckable(true); m_pMenuSuspend = m_pMenuProcess->addAction(tr("Suspend"), this, SLOT(OnProcessAction())); m_pMenuResume = m_pMenuProcess->addAction(tr("Resume"), this, SLOT(OnProcessAction())); } void CSbieView::CreateOldMenu() { m_pNewBox = m_pMenu->addAction(CSandMan::GetIcon("NewBox"), tr("Create New Box"), this, SLOT(OnGroupAction())); m_pAddGroupe = m_pMenu->addAction(CSandMan::GetIcon("Group"), tr("Create Box Group"), this, SLOT(OnGroupAction())); m_pImportBox = m_pMenu->addAction(CSandMan::GetIcon("UnPackBox"), tr("Import Box"), this, SLOT(OnGroupAction())); m_pImportBox->setEnabled(CArchive::IsInit()); m_pMenuBox = new QMenu(); m_pStopAsync = m_pMenuBox->addAction(CSandMan::GetIcon("Stop"), tr("Stop Operations"), this, SLOT(OnSandBoxAction())); //m_pMenuBox->addSeparator(); //m_pMenuRun = m_pMenuBox->addMenu(CSandMan::GetIcon("Start"), tr("Run Sandboxed")); m_pMenuRun = new CMenuEx(tr("Run"), m_pMenuBox); m_pMenuRun->setIcon(CSandMan::GetIcon("Start")); m_pMenuBox->addAction(m_pMenuRun->menuAction()); connect(m_pMenuRun, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnMenuContextMenu(const QPoint&))); m_pMenuRunBrowser = m_pMenuRun->addAction(CSandMan::GetIcon("Internet"), tr("Run Web Browser"), this, SLOT(OnSandBoxAction())); m_pMenuRunMailer = m_pMenuRun->addAction(CSandMan::GetIcon("Email"), tr("Run eMail Reader"), this, SLOT(OnSandBoxAction())); m_pMenuRunAny = m_pMenuRun->addAction(CSandMan::GetIcon("Run"), tr("Run Any Program"), this, SLOT(OnSandBoxAction())); m_pMenuRunMenu = m_pMenuRun->addAction(CSandMan::GetIcon("StartMenu"), tr("Run From Start Menu"), this, SLOT(OnSandBoxAction())); if (theConf->GetBool("Options/ScanStartMenu", true)) { m_pMenuRunStart = new QMenu(); m_pMenuRunStart->addAction(CSandMan::GetIcon("StartMenu"), tr("(Host) Start Menu"), this, SLOT(OnSandBoxAction())); m_pMenuRunStart->addSeparator(); } else m_pMenuRunStart = NULL; m_pMenuRunExplorer = m_pMenuRun->addAction(CSandMan::GetIcon("Explore"), tr("Run Windows Explorer"), this, SLOT(OnSandBoxAction())); m_pMenuRunCmd = NULL; m_pMenuRunTools = NULL; m_pMenuRunCmdAdmin = NULL; #ifdef _WIN64 m_pMenuRunCmd32 = NULL; #endif m_pMenuRunRegEdit = NULL; m_pMenuRunAppWiz = NULL; m_pMenuAutoRun = NULL; m_pMenuRun->addSeparator(); m_iMenuRun = m_pMenuRun->actions().count(); m_pMenuBox->addSeparator(); m_pMenuEmptyBox = m_pMenuBox->addAction(CSandMan::GetIcon("EmptyAll"), tr("Terminate Programs"), this, SLOT(OnSandBoxAction())); m_pMenuMount = m_pMenuBox->addAction(CSandMan::GetIcon("LockOpen"), tr("Mount Box Image"), this, SLOT(OnSandBoxAction())); m_pMenuUnmount = m_pMenuBox->addAction(CSandMan::GetIcon("LockClosed"), tr("Unmount Box Image"), this, SLOT(OnSandBoxAction())); m_pMenuRecover = m_pMenuBox->addAction(CSandMan::GetIcon("Recover"), tr("Quick Recover"), this, SLOT(OnSandBoxAction())); m_pMenuCleanUp = m_pMenuBox->addAction(CSandMan::GetIcon("Erase"), tr("Delete Content"), this, SLOT(OnSandBoxAction())); m_pMenuExplore = m_pMenuBox->addAction(CSandMan::GetIcon("Explore"), tr("Explore Content"), this, SLOT(OnSandBoxAction())); m_pMenuBox->addSeparator(); m_pMenuOptions = m_pMenuBox->addAction(CSandMan::GetIcon("Options"), tr("Sandbox Settings"), this, SLOT(OnSandBoxAction())); m_pMenuTools = m_pMenuBox->addMenu(CSandMan::GetIcon("Maintenance"), tr("Sandbox Tools")); m_pMenuBrowse = m_pMenuTools->addAction(CSandMan::GetIcon("Tree"), tr("Browse Content"), this, SLOT(OnSandBoxAction())); m_pMenuSnapshots = m_pMenuTools->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction())); m_pMenuTools->addSeparator(); m_pMenuDuplicate = m_pMenuTools->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Sandbox Config"), this, SLOT(OnSandBoxAction())); m_pMenuExport = m_pMenuTools->addAction(CSandMan::GetIcon("PackBox"), tr("Export Sandbox"), this, SLOT(OnSandBoxAction())); m_pMenuExport->setEnabled(CArchive::IsInit()); m_pMenuTools->addSeparator(); m_pMenuRefresh = m_pMenuTools->addAction(CSandMan::GetIcon("Refresh"), tr("Refresh Info"), this, SLOT(OnSandBoxAction())); m_pMenuMkLink = m_pMenuTools->addAction(CSandMan::GetIcon("MkLink"), tr("Create Shortcut"), this, SLOT(OnSandBoxAction())); m_pMenuBox->addSeparator(); m_pMenuRename = m_pMenuBox->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction())); m_pMenuMoveTo = m_pMenuBox->addMenu(CSandMan::GetIcon("Group"), tr("Move Sandbox")); 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_pMenuBox->addAction(CSandMan::GetIcon("Remove"), tr("Remove Sandbox"), this, SLOT(OnSandBoxAction())); m_pMenuContent = NULL; m_pMenuRegEdit = NULL; m_pMenuPresets = NULL; m_pMenuPresetsAdmin = NULL; m_pMenuPresetsShowUAC = NULL; m_pMenuPresetsNoAdmin = NULL; m_pMenuPresetsFakeAdmin = NULL; m_pMenuPresetsINet = NULL; m_pMenuPresetsShares = NULL; m_pMenuPresetsRecovery = NULL; m_pMenuPresetsForce = NULL; // Process Menu m_pMenuProcess = new QMenu(); m_pMenuTerminate = m_pMenuProcess->addAction(CSandMan::GetIcon("Remove"), tr("Terminate"), this, SLOT(OnProcessAction())); this->addAction(m_pMenuTerminate); m_pMenuLinkTo = m_pMenuProcess->addAction(CSandMan::GetIcon("MkLink"), tr("Create Shortcut"), this, SLOT(OnProcessAction())); m_pMenuPreset = NULL; m_pMenuPinToRun = NULL; m_pMenuBlackList = NULL; m_pMenuAllowInternet = NULL; m_pMenuMarkForced = NULL; m_pMenuMarkLinger = NULL; m_pMenuMarkLeader = NULL; m_pMenuSuspend = NULL; m_pMenuResume = NULL; } void CSbieView::CreateGroupMenu() { m_pMenuGroup = new QMenu(); m_pMenuGroup->addAction(m_pNewBox); m_pMenuGroup->addAction(m_pAddGroupe); m_pMenuGroup->addAction(m_pImportBox); m_pMenuGroup->addSeparator(); m_pRenGroupe = m_pMenuGroup->addAction(CSandMan::GetIcon("Rename"), tr("Rename Group"), this, SLOT(OnGroupAction())); m_pMenuGroup->addAction(CSandMan::GetIcon("Group"), tr("Move Group"))->setMenu(m_pMenuMoveTo); m_pDelGroupe = m_pMenuGroup->addAction(CSandMan::GetIcon("Remove"), tr("Remove Group"), this, SLOT(OnGroupAction())); } void CSbieView::CreateTrayMenu() { m_pMenuTray = new QMenu(); m_pMenuTray->addMenu(m_pMenuRun); m_pMenuTray->addAction(m_pMenuEmptyBox); m_pMenuTray->addSeparator(); m_pMenuTray->addAction(m_pMenuBrowse); m_pMenuTray->addAction(m_pMenuExplore); m_pMenuTray->addAction(m_pMenuRegEdit); m_pMenuTray->addAction(m_pMenuSnapshots); m_pMenuTray->addAction(m_pMenuRecover); m_pMenuTray->addAction(m_pMenuCleanUp); m_pMenuTray->addSeparator(); if (m_pMenuPresets) { m_pMenuTray->addAction(m_pMenuOptions); m_pMenuTray->addMenu(m_pMenuPresets); } } int CSbieView__ParseGroup(const QString& Grouping, QMap& m_Groups, const QString& Parent = "", int Index = 0) { QRegularExpression RegExp("[,()]", QRegularExpression::CaseInsensitiveOption); for (; ; ) { int pos = Grouping.indexOf(RegExp, Index); QString Name; if (pos == -1) { Name = Grouping.mid(Index); Index = Grouping.length(); } else { Name = Grouping.mid(Index, pos - Index); Index = pos + 1; } if (!Name.isEmpty()) m_Groups[Parent].append(Name); if (pos == -1) break; if (Grouping.at(pos) == '(') { m_Groups[Name] = QStringList(); Index = CSbieView__ParseGroup(Grouping, m_Groups, Name, Index); } else if (Grouping.at(pos) == ')') break; } return Index; } QString CSbieView__SerializeGroup(QMap& m_Groups, const QString& Parent = "", QSet Test = QSet()) { QStringList Grouping; foreach(const QString& Name, m_Groups[Parent]) { if (Test.contains(Name)) continue; // recursion, skil Test.insert(Name); if (m_Groups.contains(Name)) Grouping.append(Name + "(" + CSbieView__SerializeGroup(m_Groups, Name, Test) + ")"); else Grouping.append(Name); } return Grouping.join(","); } void CSbieView::Refresh() { QList Added = m_pSbieModel->Sync(theAPI->GetAllBoxes(), m_Groups, theGUI->IsShowHidden()); if (m_pSbieModel->IsTree()) { QTimer::singleShot(10, this, [this, Added]() { foreach(const QVariant ID, Added) { QModelIndex ModelIndex = m_pSbieModel->FindIndex(ID); if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eProcess) { m_HoldExpand = true; m_pSbieTree->expand(m_pSortProxy->mapFromSource(ModelIndex)); m_HoldExpand = false; } else { 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 (!m_Collapsed.contains(Name)) { m_HoldExpand = true; m_pSbieTree->expand(m_pSortProxy->mapFromSource(ModelIndex)); m_HoldExpand = false; } } } }); } // add new boxes to the default group foreach(const QStringList &list, m_Groups) { foreach(const QString &str, list) Added.removeAll(str); } if (!Added.isEmpty()) { bool bChanged = false; foreach(const QVariant& ID, Added) { if (ID.type() == QVariant::String) { QString id = ID.toString(); if (id.left(1) != "!") { bChanged = true; m_Groups[""].append(id); } } } if(bChanged) SaveBoxGrouping(); } } void CSbieView::OnToolTipCallback(const QVariant& ID, QString& ToolTip) { if (ID.type() == QVariant::String) { QString BoxName = ID.toString(); CSandBoxPtr pBox = theAPI->GetBoxByName(BoxName); CSandBoxPlus* pBoxEx = qobject_cast(pBox.data()); if (!pBoxEx) return; // todo more info ToolTip = BoxName + "\n"; ToolTip += tr(" File root: %1\n").arg(pBoxEx->GetFileRoot()); ToolTip += tr(" Registry root: %1\n").arg(pBoxEx->GetRegRoot()); ToolTip += tr(" IPC root: %1\n").arg(pBoxEx->GetIpcRoot()); if(!pBoxEx->GetMountRoot().isEmpty()) ToolTip += tr(" Disk root: %1\n").arg(pBoxEx->GetMountRoot()); ToolTip += tr("Options:\n "); ToolTip += pBoxEx->GetStatusStr().replace(", ", "\n "); } else if (quint32 ProcessId = ID.toUInt()) { // todo proc info } } 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); theConf->SetValue("MainWindow/BoxTree_UseOrder", false); m_pSbieTree->header()->setSortIndicatorShown(true); } else if (order == Qt::DescendingOrder) { SetCustomOrder(); theConf->SetValue("MainWindow/BoxTree_UseOrder", true); } } else { m_pSortProxy->setSortRole(Qt::EditRole); m_pSbieTree->header()->setSortIndicatorShown(true); } } bool CSbieView::UpdateMenu(bool bAdvanced, const CSandBoxPtr &pBox, int iSandBoxeCount, bool bBoxBusy, bool bBoxNotMounted) { QList MenuActions = m_pMenu->actions(); auto pBoxEx = pBox.objectCast(); m_pStopAsync->setVisible(bBoxBusy); m_pMenuMount->setVisible(bBoxNotMounted); m_pMenuMount->setEnabled(iSandBoxeCount == 1); if (bBoxBusy) iSandBoxeCount = 0; m_pMenuRun->setEnabled(iSandBoxeCount == 1); if(iSandBoxeCount == 1) UpdateRunMenu(pBox); m_pMenuRename->setEnabled(iSandBoxeCount == 1 && pBoxEx->GetMountRoot().isEmpty()); m_pMenuOptions->setEnabled(iSandBoxeCount == 1); if (m_pMenuPresets) { m_pMenuPresets->setEnabled(iSandBoxeCount == 1); if (iSandBoxeCount == 1) { m_pMenuPresetsShowUAC->setChecked(pBox && !pBox->GetBool("DropAdminRights", false) && !pBox->GetBool("FakeAdminRights", false)); m_pMenuPresetsNoAdmin->setChecked(pBox && pBox->GetBool("DropAdminRights", false) && !pBox->GetBool("FakeAdminRights", false)); m_pMenuPresetsFakeAdmin->setChecked(pBox && pBox->GetBool("DropAdminRights", false) && pBox->GetBool("FakeAdminRights", false)); m_pMenuPresetsINet->setChecked(pBox && pBox.objectCast()->IsINetBlocked()); m_pMenuPresetsShares->setChecked(pBox && pBox.objectCast()->HasSharesAccess()); m_pMenuPresetsRecovery->setChecked(pBox && pBox->GetBool("AutoRecover", false)); m_pMenuPresetsForce->setChecked(pBox && pBox->GetBool("DisableForceRules", false)); } } if (bBoxNotMounted) iSandBoxeCount = 0; m_pMenuMkLink->setEnabled(iSandBoxeCount == 1); m_pMenuTools->setEnabled(iSandBoxeCount == 1); m_pMenuUnmount->setVisible(pBoxEx && pBoxEx->UseImageFile() && !pBoxEx->GetMountRoot().isEmpty()); m_pMenuRecover->setEnabled(iSandBoxeCount == 1); m_pMenuCleanUp->setEnabled(iSandBoxeCount > 0); if (m_pMenuContent) m_pMenuContent->setEnabled(iSandBoxeCount > 0); m_pMenuEmptyBox->setEnabled(iSandBoxeCount > 0); m_pMenuBrowse->setEnabled(iSandBoxeCount == 1); m_pMenuExplore->setEnabled(iSandBoxeCount == 1); if(m_pMenuRegEdit)m_pMenuRegEdit->setEnabled(iSandBoxeCount == 1); m_pMenuSnapshots->setEnabled(iSandBoxeCount == 1); m_pCopyCell->setVisible(bAdvanced); m_pCopyRow->setVisible(bAdvanced); m_pCopyPanel->setVisible(bAdvanced); return bBoxBusy == false; } void CSbieView::UpdateProcMenu(const CBoxedProcessPtr& pProcess, int iProcessCount, int iSuspendedCount) { m_pMenuLinkTo->setEnabled(iProcessCount == 1); CSandBoxPlus* pBoxPlus = pProcess.objectCast()->GetBox(); QStringList RunOptions = pBoxPlus->GetTextList("RunCommand", true); QString FoundPin; QString FileName = pProcess->GetFileName(); foreach(const QString& RunOption, RunOptions) { QVariantMap Entry = GetRunEntry(RunOption); QString CmdFile = pBoxPlus->GetCommandFile(Entry["Command"].toString()); if(CmdFile.compare(FileName, Qt::CaseInsensitive) == 0) { FoundPin = RunOption; break; } } if (m_pMenuPreset) { m_pMenuPinToRun->setChecked(!FoundPin.isEmpty()); m_pMenuPinToRun->setData(FoundPin); m_pMenuPinToRun->setProperty("WorkingDir", pProcess->GetWorkingDir()); m_pMenuAllowInternet->setChecked(pProcess.objectCast()->HasInternetAccess()); m_pMenuMarkForced->setChecked(pProcess.objectCast()->IsForcedProgram()); int isLingering = pProcess.objectCast()->IsLingeringProgram(); m_pMenuMarkLinger->setChecked(isLingering != 0); m_pMenuMarkLinger->setEnabled(isLingering != 2); m_pMenuMarkLeader->setChecked(pProcess.objectCast()->IsLeaderProgram()); } if (m_pMenuSuspend) m_pMenuSuspend->setEnabled(iProcessCount > iSuspendedCount); if (m_pMenuResume) m_pMenuResume->setEnabled(iSuspendedCount > 0); } bool CSbieView::UpdateMenu() { m_CurSandBoxes.clear(); m_CurProcesses.clear(); CSandBoxPtr pBox; bool bBoxBusy = false; bool bBoxNotMounted = false; CBoxedProcessPtr pProcess; int iProcessCount = 0; int iSandBoxeCount = 0; int iGroupe = 0; int iSuspendedCount = 0; QModelIndexList Rows = m_pSbieTree->selectedRows(); foreach(const QModelIndex& Index, Rows) { QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index); pProcess = m_pSbieModel->GetProcess(ModelIndex); if (pProcess) { m_CurProcesses.append(pProcess); iProcessCount++; if (pProcess->TestSuspended()) iSuspendedCount++; } else { pBox = m_pSbieModel->GetSandBox(ModelIndex); if (pBox) { m_CurSandBoxes.append(pBox); if (!pBox->IsEnabled()) iSandBoxeCount = -1; else if (iSandBoxeCount != -1) iSandBoxeCount++; auto pBoxEx = pBox.objectCast(); if(pBoxEx->IsBoxBusy()) bBoxBusy = true; if (pBoxEx->UseImageFile() && pBoxEx->GetMountRoot().isEmpty()) bBoxNotMounted = true; } else iGroupe++; } } bool bAdvanced = theConf->GetInt("Options/ViewMode", 1) == 1 || (QGuiApplication::queryKeyboardModifiers() & Qt::ControlModifier) != 0; m_pRenGroupe->setVisible(iGroupe == 1 && iSandBoxeCount == 0 && iProcessCount == 0); m_pDelGroupe->setVisible(iGroupe > 0 && iSandBoxeCount == 0 && iProcessCount == 0); if (!pProcess.isNull()) UpdateProcMenu(pProcess, iProcessCount, iSuspendedCount); return UpdateMenu(bAdvanced, pBox, iSandBoxeCount, bBoxBusy, bBoxNotMounted); } void CSbieView::OnMenu(const QPoint& Point) { if (!theAPI->IsConnected()) return; UpdateMenu(); UpdateCopyMenu(); if (!m_CurProcesses.isEmpty()) m_pMenuProcess->popup(QCursor::pos()); else if (!m_CurSandBoxes.isEmpty()) m_pMenuBox->popup(QCursor::pos()); else if (!GetSelectedGroups().isEmpty()) m_pMenuGroup->popup(QCursor::pos()); else m_pMenu->popup(QCursor::pos()); } void CSbieView::UpdateMoveMenu() { // update move to menu foreach(QAction * pAction, m_pMenuMoveTo->actions()) { if (!pAction->data().toString().isNull()) m_pMenuMoveTo->removeAction(pAction); } foreach(const QString Group, m_Groups.keys()) { QString Name = Group, Temp = Group; for (;;) { QString Parent = FindParent(Temp); if (Parent.isEmpty()) break; Temp = Parent; Name.prepend(Parent + " > "); } QAction* pAction = m_pMenuMoveTo->addAction(Name.isEmpty() ? tr("[None]") : Name, this, SLOT(OnGroupAction())); pAction->setData(Group); } //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); RenameItem(OldName, NewName); } void CSbieView::RenameItem(const QString OldName, const QString NewName) { quint64 Size = theConf->GetValue("SizeCache/" + OldName, -1).toLongLong(); theConf->DelValue("SizeCache/" + OldName); if(Size != -1) theConf->SetValue("SizeCache/" + NewName, Size); if (m_Collapsed.remove(OldName)) m_Collapsed.insert(NewName); for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { if (I.value().removeOne(OldName)) I.value().append(NewName); } } QString CSbieView::FindParent(const QString& Name) { for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { if (I.value().contains(Name, Qt::CaseInsensitive)) return I.key(); } return QString(); } bool CSbieView::IsParentOf(const QString& Name, const QString& Group) { QString Parent = FindParent(Group); if (Parent == Name) return true; if (Parent.isEmpty()) return false; 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() { OnGroupAction(qobject_cast(sender())); } void CSbieView::OnGroupAction(QAction* Action) { if (Action == m_pNewBox || Action == m_pAddGroupe || Action == m_pImportBox) { QStringList List = GetSelectedGroups(); QString Name = Action == m_pNewBox ? AddNewBox() : (Action == m_pImportBox ? ImportSandbox() : AddNewGroup()); if (Name.isEmpty()) return; if (List.isEmpty()) return; m_Groups[""].removeAll(Name); m_Groups[List.first()].removeAll(Name); m_Groups[List.first()].append(Name); } 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 (!TestNameAndWarn(Value)) return; RenameGroup(OldValue, Value); } else if (Action == m_pDelGroupe) { if (QMessageBox("Sandboxie-Plus", tr("Do you really want to remove the selected group(s)?"), QMessageBox::Question, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes) return; foreach(const QModelIndex& Index, m_pSbieTree->selectedRows()) { QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index); if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eGroup) { QString Group = m_pSbieModel->GetID(ModelIndex).toString(); QStringList Items = m_Groups.take(Group); // remove group // remove from parents for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { if (I.value().removeOne(Group)) { // move items to grand parent I.value().append(Items); break; } } m_Collapsed.remove(Group); } } } else if (Action == m_pMenuMoveUp /*|| Action == m_pMenuMoveBy*/ || Action == m_pMenuMoveDown) { if (!theConf->GetBool("MainWindow/BoxTree_UseOrder", false)) { SetCustomOrder(); theConf->SetValue("MainWindow/BoxTree_UseOrder", true); } 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, positive values move down):"), 0); if (Offset == 0) return; // todo: fix behaviour on multiple selection QMap> GroupPositions; bool bOutBounded = false; auto FindPosition = [this, Offset, &bOutBounded, &GroupPositions](const QString& Name) -> bool { foreach(const QString& Group, m_Groups.keys()) { int pos = m_Groups[Group].indexOf(Name); if (pos != -1) { if (pos + Offset >= 0 && pos + Offset < m_Groups[Group].count()) GroupPositions[Group].append(pos); else bOutBounded = true; return true; } } return false; }; foreach(const QString& Name, GetSelectedGroups(true)) { if (!FindPosition(Name)) { m_Groups[""].prepend(Name); FindPosition(Name); } if (bOutBounded) break; } if (bOutBounded) QApplication::beep(); else { foreach(const QString& Group, GroupPositions.keys()) { std::sort(GroupPositions[Group].begin(), GroupPositions[Group].end(), [Offset](const int& a, const int& b) { return Offset > 0 && a > b || Offset < 0 && a < b; }); foreach(const int ItemIndex, GroupPositions[Group]) { m_Groups[Group].swapItemsAt(ItemIndex + Offset, ItemIndex); } } } } else // move to group { QString Group = Action->data().toString(); foreach(const QString& Name, GetSelectedGroups(true)) { 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; } MoveItem(Name, Group); } } if (!(Action == m_pMenuMoveUp /*|| Action == m_pMenuMoveBy*/ || Action == m_pMenuMoveDown)) { m_pSbieModel->Clear(); //todo improve that Refresh(); } UpdateMoveMenu(); SaveBoxGrouping(); } void CSbieView::SetCustomOrder() { m_pSortProxy->sort(0, Qt::AscendingOrder); m_pSortProxy->setSortRole(Qt::InitialSortOrderRole); m_pSbieTree->header()->setSortIndicatorShown(false); } bool CSbieView::MoveItem(const QString& Name, const QString& To, int pos) { QString From; // remove from old for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { for (int i = 0; i < I.value().count(); i++) { if (I.value().at(i) == Name) { I.value().removeAt(i); From = I.key(); if(From == To && i < pos) pos--; break; } } } // add to new if (pos < 0/* || pos > m_Groups[To].size()*/) m_Groups[To].append(Name); else m_Groups[To].insert(pos, Name); return From != To; } QString CSbieView::AddNewBox(bool bAlowTemp) { QString BoxName = CNewBoxWizard::CreateNewBox(bAlowTemp, this); if (!BoxName.isEmpty()) { theAPI->ReloadBoxes(); Refresh(); SelectBox(BoxName); } return BoxName; } QString CSbieView::ImportSandbox() { QString Path = QFileDialog::getOpenFileName(this, tr("Select file name"), "", tr("7-zip Archive (*.7z)")); if (Path.isEmpty()) return ""; QString Password; quint64 ImageSize = 0; CArchive Archive(Path); int Ret = Archive.Open(); if (Ret == ERR_7Z_PASSWORD_REQUIRED) { for (;;) { CBoxImageWindow window(CBoxImageWindow::eImport, this); if (!theGUI->SafeExec(&window) == 1) return ""; Archive.SetPassword(window.GetPassword()); Ret = Archive.Open(); if (Ret != ERR_7Z_OK) { QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to open archive, wrong password?")); continue; } Password = window.GetPassword(); ImageSize = window.GetImageSize(); break; } } if (Ret != ERR_7Z_OK) { QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to open archive (%1)!").arg(Ret)); return ""; } Archive.Close(); StrPair PathName = Split2(Path, "/", true); StrPair NameEx = Split2(PathName.second, ".", true); QString Name = NameEx.first; CSandBoxPtr pBox; for (;;) { pBox = theAPI->GetBoxByName(Name); if (pBox.isNull()) break; Name = QInputDialog::getText(this, "Sandboxie-Plus", tr("This name is already in use, please select an alternative box name"), QLineEdit::Normal, Name); if (Name.isEmpty()) return ""; } SB_PROGRESS Status = theAPI->CreateBox(Name); if (!Status.IsError()) { pBox = theAPI->GetBoxByName(Name); if (pBox) { auto pBoxEx = pBox.objectCast(); if (!Password.isEmpty()) { Status = pBoxEx->ImBoxCreate(ImageSize / 1024, Password); if (!Status.IsError()) Status = pBoxEx->ImBoxMount(Password, true, true); } if (!Status.IsError()) Status = pBoxEx->ImportBox(Path, Password); } } if (Status.GetStatus() == OP_ASYNC) { Status = theGUI->AddAsyncOp(Status.GetValue(), true, tr("Importing: %1").arg(Path)); if (Status.IsError()) { theGUI->DeleteBoxContent(pBox, CSandMan::eForDelete); pBox->RemoveBox(); } } else theGUI->CheckResults(QList() << Status, this); return Name; } QString CSbieView::AddNewGroup() { QString Name = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a new group name"), QLineEdit::Normal); if (Name.isEmpty() || m_Groups.contains(Name)) return ""; if (!TestNameAndWarn(Name)) return ""; m_Groups[Name] = QStringList(); 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); UpdateMoveMenu(); SaveBoxGrouping(); return Name; } bool CSbieView::TestNameAndWarn(const QString& Name) { if (Name.contains(QRegularExpression("[,()]"))) { QMessageBox::critical(this, "Sandboxie-Plus", tr("The Sandbox name and Box Group name cannot use the ',()' symbol.")); return false; } if (m_Groups.contains(Name)) { QMessageBox::critical(this, "Sandboxie-Plus", tr("This name is already used for a Box Group.")); return false; } if (!theAPI->GetBoxByName(QString(Name).replace(" ", "_")).isNull()) { QMessageBox::critical(this, "Sandboxie-Plus", tr("This name is already used for a Sandbox.")); return false; } return true; } void CSbieView::OnSandBoxAction() { OnSandBoxAction(qobject_cast(sender()), m_CurSandBoxes); } void CSbieView::OnSandBoxAction(QAction* pAction) { OnSandBoxAction(pAction, m_CurSandBoxes); } void CSbieView::OnSandBoxAction(QAction* Action, const QList& SandBoxes) { QList Results; if (SandBoxes.isEmpty()) return; if (Action == m_pStopAsync) { foreach(const CSandBoxPtr& pBox, SandBoxes) { auto pBoxEx = pBox.objectCast(); pBoxEx->OnCancelAsync(); } } else if (Action == m_pMenuRunAny) { /*QString Command = ShowRunDialog(SandBoxes.first()->GetName()); if(!Command.isEmpty()) SandBoxes.first()->RunCommand(Command);*/ Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "run_dialog")); } else if (Action == m_pMenuRunBrowser) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "default_browser")); else if (Action == m_pMenuRunMailer) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "mail_agent")); else if (Action == m_pMenuRunExplorer) { if (theConf->GetInt("Options/ViewMode", 1) != 1 && theConf->GetBool("Options/BoxedExplorerInfo", true)) { bool State = false; CCheckableMessageBox::question(this, "Sandboxie-Plus", theAPI->GetSbieMsgStr(0x00000DCDL, theGUI->m_LanguageId) // MSG_3533 , tr("Don't show this message again."), &State, QDialogButtonBox::Ok, QDialogButtonBox::Ok, QMessageBox::Information); if (State) theConf->SetValue("Options/BoxedExplorerInfo", false); } Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "explorer.exe /e,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}")); } else if (Action == m_pMenuRunRegEdit) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "regedit.exe")); else if (Action == m_pMenuRunAppWiz) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "\"C:\\WINDOWS\\System32\\control.exe\" \"C:\\Windows\\System32\\appwiz.cpl\"")); else if (Action == m_pMenuAutoRun) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "auto_run")); else if (Action == m_pMenuRunCmd) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "cmd.exe")); else if (Action == m_pMenuRunCmdAdmin) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "cmd.exe", true)); #ifdef _WIN64 else if (Action == m_pMenuRunCmd32) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "C:\\WINDOWS\\SysWOW64\\cmd.exe")); #endif else if (Action == m_pMenuPresetsShowUAC) { SandBoxes.first()->SetBoolSafe("DropAdminRights", false); SandBoxes.first()->SetBoolSafe("FakeAdminRights", false); } else if (Action == m_pMenuPresetsNoAdmin) { SandBoxes.first()->SetBoolSafe("DropAdminRights", true); SandBoxes.first()->SetBoolSafe("FakeAdminRights", false); } else if (Action == m_pMenuPresetsFakeAdmin) { SandBoxes.first()->SetBoolSafe("DropAdminRights", true); SandBoxes.first()->SetBoolSafe("FakeAdminRights", true); } else if (Action == m_pMenuPresetsINet) SandBoxes.first().objectCast()->SetINetBlock(m_pMenuPresetsINet->isChecked()); else if (Action == m_pMenuPresetsShares) SandBoxes.first().objectCast()->SetAllowShares(m_pMenuPresetsShares->isChecked()); else if (Action == m_pMenuPresetsRecovery) m_pMenuPresetsRecovery->setChecked(SandBoxes.first()->SetBoolSafe("AutoRecover", m_pMenuPresetsRecovery->isChecked())); else if (Action == m_pMenuPresetsForce) m_pMenuPresetsForce->setChecked(SandBoxes.first()->SetBoolSafe("DisableForceRules", m_pMenuPresetsForce->isChecked())); else if (Action == m_pMenuOptions) ShowOptions(SandBoxes.first()); else if (Action == m_pMenuBrowse) ShowBrowse(SandBoxes.first()); else if (Action == m_pMenuRefresh) { foreach(const CSandBoxPtr& pBox, SandBoxes) { pBox.objectCast()->UpdateSize(); if (theConf->GetBool("Options/ScanStartMenu", true)) pBox.objectCast()->ScanStartMenu(); } } else if (Action == m_pMenuExplore) { if (SandBoxes.first()->IsEmpty()) { QMessageBox("Sandboxie-Plus", tr("This Sandbox is empty."), QMessageBox::Information, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton, this).exec(); return; } if (theConf->GetInt("Options/ViewMode", 1) != 1 && theConf->GetBool("Options/ExplorerInfo", true)) { bool State = false; CCheckableMessageBox::question(this, "Sandboxie-Plus", theAPI->GetSbieMsgStr(0x00000DCEL, theGUI->m_LanguageId) // MSG_3534 , tr("Don't show this message again."), &State, QDialogButtonBox::Ok, QDialogButtonBox::Ok, QMessageBox::Information); if (State) theConf->SetValue("Options/ExplorerInfo", false); } ::ShellExecute(NULL, NULL, SandBoxes.first()->GetFileRoot().toStdWString().c_str(), NULL, NULL, SW_SHOWNORMAL); } else if (Action == m_pMenuRegEdit) { if (SandBoxes.first()->IsEmpty()) { QMessageBox("Sandboxie-Plus", tr("This Sandbox is empty."), QMessageBox::Information, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton, this).exec(); return; } if (theConf->GetInt("Options/WarnOpenRegistry", -1) == -1) { bool State = false; if (CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("WARNING: The opened registry editor is not sandboxed, please be careful and only do changes to the pre-selected sandbox locations.") , tr("Don't show this warning in future"), &State, QDialogButtonBox::Ok | QDialogButtonBox::Cancel, QDialogButtonBox::Yes, QMessageBox::Information) != QDialogButtonBox::Ok) return; if (State) theConf->SetValue("Options/WarnOpenRegistry", 1); } std::wstring path = QCoreApplication::applicationFilePath().toStdWString(); QStringList RegRoot = SandBoxes.first()->GetRegRoot().split("\\"); while (RegRoot.first().isEmpty()) RegRoot.removeFirst(); RegRoot[0] = QString("Computer"); if(RegRoot[1] == "USER") RegRoot[1] = QString("HKEY_USERS"); else if(RegRoot[1] == "MACHINE") RegRoot[1] = QString("HKEY_LOCAL_MACHINE"); std::wstring params = L"/OpenReg \"" + RegRoot.join("\\").toStdWString() + L"\""; if (SandBoxes.first()->GetActiveProcessCount() == 0) params += L" \"" + theAPI->GetStartPath().toStdWString() + L" /box:" + SandBoxes.first()->GetName().toStdWString() + L" mount_hive\""; SHELLEXECUTEINFO shex; memset(&shex, 0, sizeof(SHELLEXECUTEINFO)); shex.cbSize = sizeof(SHELLEXECUTEINFO); shex.fMask = SEE_MASK_FLAG_NO_UI; shex.hwnd = NULL; shex.lpFile = path.c_str(); shex.lpParameters = params.c_str(); shex.nShow = SW_SHOWNORMAL; shex.lpVerb = L"runas"; ShellExecuteEx(&shex); } else if (Action == m_pMenuSnapshots) { CSandBoxPtr pBox = SandBoxes.first(); static QMap SnapshotWindows; CSnapshotsWindow* pSnapshotsWindow = SnapshotWindows.value(pBox.data()); if (pSnapshotsWindow == NULL) { pSnapshotsWindow = new CSnapshotsWindow(SandBoxes.first(), this); connect(theGUI, SIGNAL(Closed()), pSnapshotsWindow, SLOT(close())); SnapshotWindows.insert(pBox.data(), pSnapshotsWindow); connect(pSnapshotsWindow, &CSnapshotsWindow::Closed, [this, pBox]() { SnapshotWindows.remove(pBox.data()); }); SafeShow(pSnapshotsWindow); } else { pSnapshotsWindow->setWindowState((pSnapshotsWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); SetForegroundWindow((HWND)pSnapshotsWindow->winId()); } } else if (Action == m_pMenuDuplicate) { QString OldValue = SandBoxes.first()->GetName().replace("_", " "); QString Value = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a new name for the duplicated Sandbox."), QLineEdit::Normal, tr("%1 Copy").arg(OldValue)); if (Value.isEmpty() || Value == OldValue) return; QString Name = Value.replace(" ", "_"); SB_STATUS Status = theAPI->CreateBox(Name, false); if (!Status.IsError()) { CSandBoxPtr pBox = theAPI->GetBoxByName(Value); QList> Settings; CSandBoxPtr pSrcBox = theAPI->GetBoxByName(SandBoxes.first()->GetName()); qint32 status = 0; if (!pSrcBox.isNull()) Settings = pSrcBox->GetIniSection(&status); if (Settings.isEmpty()) Status = SB_ERR(SB_FailedCopyConf, QVariantList() << SandBoxes.first()->GetName() << (quint32)status); else { for (QList>::iterator I = Settings.begin(); I != Settings.end(); ++I) { if (I->first == "FileRootPath" && !I->second.toUpper().contains("%SANDBOX%")) continue; // skip the FileRootPath if it does not contain a %SANDBOX% Status = theAPI->SbieIniSet(Name, I->first, I->second, CSbieAPI::eIniInsert, false); if (Status.IsError()) break; } } theAPI->CommitIniChanges(); theAPI->ReloadBoxes(true); } Results.append(Status); } else if (Action == m_pMenuExport) { CSandBoxPtr pBox = SandBoxes.first(); auto pBoxEx = pBox.objectCast(); CCompressDialog optWnd(this); if (pBoxEx->UseImageFile()) optWnd.SetMustEncrypt(); if (!theGUI->SafeExec(&optWnd) == 1) return; QString Password; if (optWnd.UseEncryption()) { CBoxImageWindow pwWnd(CBoxImageWindow::eExport, this); if (!theGUI->SafeExec(&pwWnd) == 1) return; Password = pwWnd.GetPassword(); } QString Path = QFileDialog::getSaveFileName(this, tr("Select file name"), SandBoxes.first()->GetName() + ".7z", tr("7-zip Archive (*.7z)")); if (Path.isEmpty()) return; SB_PROGRESS Status = pBoxEx->ExportBox(Path, Password, optWnd.GetLevel(), optWnd.MakeSolid()); if (Status.GetStatus() == OP_ASYNC) theGUI->AddAsyncOp(Status.GetValue(), false, tr("Exporting: %1").arg(Path)); else Results.append(Status); } else if (Action == m_pMenuRename) { QString OldValue = SandBoxes.first()->GetName().replace("_", " "); QString Value = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a new name for the Sandbox."), QLineEdit::Normal, OldValue); if (Value.isEmpty() || Value == OldValue) return; if (!TestNameAndWarn(Value)) return; SB_STATUS Status = SandBoxes.first()->RenameBox(Value.replace(" ", "_")); if (!Status.IsError()) { RenameItem(OldValue.replace(" ", "_"), Value.replace(" ", "_")); if (theAPI->GetGlobalSettings()->GetText("DefaultBox", "DefaultBox").compare(OldValue.replace(" ", "_"), Qt::CaseInsensitive) == 0) theAPI->GetGlobalSettings()->SetText("DefaultBox", Value.replace(" ", "_")); } Results.append(Status); SaveBoxGrouping(); } else if (Action == m_pMenuMount) { Results.append(theGUI->ImBoxMount(SandBoxes.first())); } else if (Action == m_pMenuUnmount) { foreach(const CSandBoxPtr& pBox, SandBoxes) { auto pBoxEx = pBox.objectCast(); pBoxEx->TerminateAll(); Results.append(pBox->ImBoxUnmount()); } } else if (Action == m_pMenuRecover) { theGUI->ShowRecovery(SandBoxes.first()); } else if (Action == m_pMenuRemove) { if (QMessageBox("Sandboxie-Plus", tr("Do you really want to remove the selected sandbox(es)?

Warning: The box content will also be deleted!"), QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes) return; bool bChanged = false; foreach(const CSandBoxPtr& pBox, SandBoxes) { auto pBoxPlus = pBox.objectCast(); if (pBoxPlus->UseImageFile() && !pBoxPlus->GetMountRoot().isEmpty()) pBoxPlus->ImBoxUnmount(); SB_STATUS Status = SB_OK; if (!pBox->GetBool("IsShadow")) { if (pBox->GetBool("NeverRemove", false)) Status = SB_ERR(SB_DeleteProtect); else { Status = theGUI->DeleteBoxContent(pBox, CSandMan::eForDelete); if (Status.GetMsgCode() == SB_Canceled) break; } } QString Name = pBox->GetName(); if (!Status.IsError()) Status = pBox->RemoveBox(); if (!Status.IsError()) { theConf->DelValue("SizeCache/" + Name); m_Collapsed.remove(Name); for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { if (I.value().removeOne(Name)) { bChanged = true; break; } } } Results.append(Status); } if(bChanged) SaveBoxGrouping(); } else if (Action == m_pMenuCleanUp) { bool DeleteSnapshots = false; if (SandBoxes.count() == 1) { if (SandBoxes.first()->IsEmpty()) { QMessageBox("Sandboxie-Plus", tr("This Sandbox is already empty."), QMessageBox::Information, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton, this).exec(); return; } if (theConf->GetBool("Options/ShowRecovery", false)) { // Use recovery dialog in place of the confirmation messagebox for box clean up if(!theGUI->OpenRecovery(SandBoxes.first(), DeleteSnapshots)) return; } else { if (SandBoxes.first()->HasSnapshots()) { if(CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you want to delete the content of the selected sandbox?") , tr("Also delete all Snapshots"), &DeleteSnapshots, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes) return; } else { if(QMessageBox::question(this, "Sandboxie-Plus", tr("Do you want to delete the content of the selected sandbox?") , QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes) return; } } } else if(CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you really want to delete the content of all selected sandboxes?") , tr("Also delete all Snapshots"), &DeleteSnapshots, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes) return; foreach(const CSandBoxPtr& pBox, SandBoxes) { SB_STATUS Status = theGUI->DeleteBoxContent(pBox, CSandMan::eCleanUp, DeleteSnapshots); if (Status.GetMsgCode() == SB_Canceled) break; Results.append(Status); } } else if (Action == m_pMenuEmptyBox) { if (theConf->GetInt("Options/WarnTerminate", -1) == -1) { bool State = false; if(CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you want to terminate all processes in the selected sandbox(es)?") , tr("Terminate without asking"), &State, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes) return; if (State) theConf->SetValue("Options/WarnTerminate", 1); } foreach(const CSandBoxPtr& pBox, SandBoxes) Results.append(pBox->TerminateAll()); } else if (Action == m_pMenuMkLink) { if (theConf->GetInt("Options/InfoMkLink", -1) == -1) { bool State = false; CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("The Sandboxie Start Menu will now be displayed. Select an application from the menu, and Sandboxie will create a new " "shortcut icon on your real desktop, which you can use to invoke the selected application under the supervision of Sandboxie.") , tr("Don't show this message again."), &State, QDialogButtonBox::Ok, QDialogButtonBox::Ok, QMessageBox::Information); if (State) theConf->SetValue("Options/InfoMkLink", 1); } QString BoxName = SandBoxes.first()->GetName(); QString LinkPath, IconPath, WorkDir; quint32 IconIndex; if (!CSbieUtils::GetStartMenuShortcut(theAPI, BoxName, LinkPath, IconPath, IconIndex, WorkDir)) return; CreateShortcutEx(LinkPath, BoxName, "", IconPath, IconIndex, WorkDir); } else // custom run menu command { QString Command = Action->data().toString(); QString WorkingDir = Action->property("WorkingDir").toString(); if (Command.isEmpty()) Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), "start_menu", false, WorkingDir)); else { auto pBoxEx = SandBoxes.first().objectCast(); Results.append(theGUI->RunStart(SandBoxes.first()->GetName(), pBoxEx->GetFullCommand(Command), false, pBoxEx->GetFullCommand(WorkingDir))); } } theGUI->CheckResults(Results, this); } bool CSbieView::CreateShortcutEx(const QString& LinkPath, const QString& BoxName, QString LinkName, const QString &IconPath, int IconIndex, const QString &WorkDir) { if (LinkName.isEmpty()) { int pos = LinkPath.lastIndexOf(L'\\'); if (pos == -1) return false; if (pos == 2 && LinkPath.length() == 3) LinkName = QObject::tr("Drive %1").arg(LinkPath.left(1)); else { LinkName = LinkPath.mid(pos + 1); pos = LinkName.indexOf(QRegularExpression("[" + QRegularExpression::escape("\":;,*?.") + "]")); if (pos != -1) LinkName = LinkName.left(pos); } } QString Path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).replace("/", "\\"); //Path = QFileDialog::getExistingDirectory(this, tr("Select Directory to create Shortcut in"), Path).replace("/", "\\"); //if (Path.isEmpty()) // return; if (Path.right(1) != "\\") Path.append("\\"); Path += "[" + BoxName + "] " + LinkName; Path = QFileDialog::getSaveFileName(theGUI, tr("Create Shortcut to sandbox %1").arg(BoxName), Path, QString("Shortcut files (*.lnk)")).replace("/", "\\"); if (Path.isEmpty()) return false; QString StartExe = theAPI->GetSbiePath() + "\\SandMan.exe"; return CSbieUtils::CreateShortcut(StartExe, Path, LinkName, BoxName, LinkPath, IconPath, IconIndex, WorkDir); } void CSbieView::OnProcessAction() { OnProcessAction(qobject_cast(sender()), m_CurProcesses); } void CSbieView::OnProcessAction(QAction* Action, const QList& Processes) { QList Results; if (Action == m_pMenuTerminate || Action == m_pMenuBlackList) { if (theConf->GetInt("Options/WarnTerminate", -1) == -1) { if (Processes.isEmpty()) return; bool State = false; if(CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you want to terminate %1?").arg(Processes.count() == 1 ? Processes[0]->GetProcessName() : tr("the selected processes")) , tr("Terminate without asking"), &State, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes) != QDialogButtonBox::Yes) return; if (State) theConf->SetValue("Options/WarnTerminate", 1); } } foreach(const CBoxedProcessPtr& pProcess, Processes) { if (Action == m_pMenuTerminate) Results.append(pProcess->Terminate()); else if (Action == m_pMenuLinkTo) { QString BoxName = pProcess->GetBoxName(); QString LinkName = pProcess->GetProcessName(); QString LinkPath = pProcess->GetFileName(); QString Path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).replace("/", "\\"); //Path = QFileDialog::getExistingDirectory(this, tr("Select Directory to create Shortcut in"), Path).replace("/", "\\"); //if (Path.isEmpty()) // return; if (Path.right(1) != "\\") Path.append("\\"); Path += "[" + BoxName + "] " + LinkName; Path = QFileDialog::getSaveFileName(this, tr("Create Shortcut to sandbox %1").arg(BoxName), Path, QString("Shortcut files (*.lnk)")).replace("/", "\\"); if (Path.isEmpty()) return; QString StartExe = theAPI->GetSbiePath() + "\\SandMan.exe"; CSbieUtils::CreateShortcut(StartExe, Path, LinkName, BoxName, LinkPath, LinkPath); } else if (Action == m_pMenuPinToRun) { CSandBoxPlus* pBoxPlus = pProcess.objectCast()->GetBox(); if (m_pMenuPinToRun->isChecked()) pBoxPlus->InsertText("RunCommand", pProcess->GetProcessName() + "|\"" + pBoxPlus->MakeBoxCommand(pProcess->GetFileName()) + "\""); else if(!m_pMenuPinToRun->data().toString().isEmpty()) pBoxPlus->DelValue("RunCommand", m_pMenuPinToRun->data().toString()); } else if (Action == m_pMenuBlackList) { Results.append(pProcess->Terminate()); pProcess.objectCast()->BlockProgram(); } else if (Action == m_pMenuAllowInternet) { if (!pProcess.objectCast()->GetBox()->IsINetBlocked()) { if (QMessageBox("Sandboxie-Plus", tr("This box does not have Internet restrictions in place, do you want to enable them?"), QMessageBox::Question, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes) return; pProcess.objectCast()->GetBox()->SetINetBlock(true); } pProcess.objectCast()->SetInternetAccess(m_pMenuAllowInternet->isChecked()); } else if (Action == m_pMenuMarkForced) pProcess.objectCast()->SetForcedProgram(m_pMenuMarkForced->isChecked()); else if (Action == m_pMenuMarkLinger) pProcess.objectCast()->SetLingeringProgram(m_pMenuMarkLinger->isChecked()); else if (Action == m_pMenuMarkLeader) pProcess.objectCast()->SetLeaderProgram(m_pMenuMarkLeader->isChecked()); else if (Action == m_pMenuSuspend) Results.append(pProcess->SetSuspended(true)); else if (Action == m_pMenuResume) Results.append(pProcess->SetSuspended(false)); } theGUI->CheckResults(Results, this); } void CSbieView::ShowOptions(const CSandBoxPtr& pBox) { auto pBoxEx = pBox.objectCast(); if (pBoxEx->m_pOptionsWnd == NULL) { pBoxEx->m_pOptionsWnd = new COptionsWindow(pBox, pBox->GetName()); connect(theGUI, SIGNAL(Closed()), pBoxEx->m_pOptionsWnd, SLOT(close())); connect(pBoxEx->m_pOptionsWnd, &COptionsWindow::Closed, [pBoxEx]() { pBoxEx->m_pOptionsWnd = NULL; }); SafeShow(pBoxEx->m_pOptionsWnd); } else { pBoxEx->m_pOptionsWnd->setWindowState((pBoxEx->m_pOptionsWnd->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); SetForegroundWindow((HWND)pBoxEx->m_pOptionsWnd->winId()); } } void CSbieView::ShowBrowse(const CSandBoxPtr& pBox) { if (pBox->IsEmpty()) { QMessageBox("Sandboxie-Plus", tr("This Sandbox is empty."), QMessageBox::Information, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton, this).exec(); return; } static QMap FileBrowserWindows; CFileBrowserWindow* pFileBrowserWindow = FileBrowserWindows.value(pBox.data()); if (pFileBrowserWindow == NULL) { pFileBrowserWindow = new CFileBrowserWindow(pBox); connect(theGUI, SIGNAL(Closed()), pFileBrowserWindow, SLOT(close())); FileBrowserWindows.insert(pBox.data(), pFileBrowserWindow); connect(pFileBrowserWindow, &CFileBrowserWindow::Closed, [this, pBox]() { FileBrowserWindows.remove(pBox.data()); }); SafeShow(pFileBrowserWindow); } else { pFileBrowserWindow->setWindowState((pFileBrowserWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); SetForegroundWindow((HWND)pFileBrowserWindow->winId()); } } void CSbieView::OnDoubleClicked(const QModelIndex& index) { QModelIndex ModelIndex = m_pSortProxy->mapToSource(index); CSandBoxPtr pBox = m_pSbieModel->GetSandBox(ModelIndex); if (pBox.isNull()) return; if ((QGuiApplication::queryKeyboardModifiers() & Qt::ControlModifier) != 0) { ShowOptions(pBox); return; } if (index.column() == CSbieModel::ePath) { OnSandBoxAction(m_pMenuExplore, QList() << pBox); return; } //if (index.column() != CSbieModel::eName) // return; if (!pBox->IsEnabled()) { if (QMessageBox("Sandboxie-Plus", tr("This sandbox is disabled, do you want to enable it?"), QMessageBox::Question, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes) return; pBox->SetText("Enabled", "y"); return; } QString Action = pBox->GetText("DblClickAction"); if (Action.compare("!browse", Qt::CaseInsensitive) == 0) ShowBrowse(pBox); else if (Action.compare("!recovery", Qt::CaseInsensitive) == 0) theGUI->ShowRecovery(pBox); else if (Action.compare("!run", Qt::CaseInsensitive) == 0) pBox->RunStart("run_dialog"); else if (!Action.isEmpty() && Action.left(1) != "!") { if (Action.left(1) == "\\") Action.prepend(pBox->GetFileRoot()); pBox->RunStart(Action); } else ShowOptions(pBox); } void CSbieView::OnClicked(const QModelIndex& index) { emit BoxSelected(); } void CSbieView::ProcessSelection(const QItemSelection& selected, const QItemSelection& deselected) { if (selected.empty()) return; QItemSelectionModel* selectionModel = m_pSbieTree->selectionModel(); QItemSelection selection = selectionModel->selection(); QItemSelection invalid; /* QModelIndex root_parent = m_pSbieTree->currentIndex().parent(); while (root_parent.isValid() && root_parent.parent().isValid()) root_parent = root_parent.parent(); foreach(const QModelIndex& index, selection.indexes()) { QModelIndex parent = index.parent(); while (parent.isValid() && parent.parent().isValid()) parent = parent.parent(); if (parent != root_parent) invalid.select(index, index); }*/ int Type = m_pSbieModel->GetType(m_pSortProxy->mapToSource(m_pSbieTree->currentIndex())); foreach(const QModelIndex& index, selection.indexes()) { if (m_pSbieModel->GetType(m_pSortProxy->mapToSource(index)) != Type) invalid.select(index, index); } selectionModel->select(invalid, QItemSelectionModel::Deselect); } QList CSbieView::GetSelectedBoxes() { QList List; foreach(const QModelIndex& Index, m_pSbieTree->selectedRows()) { QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index); CSandBoxPtr pBox = m_pSbieModel->GetSandBox(ModelIndex); if (!pBox) continue; List.append(pBox); } return List; } QList CSbieView::GetSelectedProcesses() { QList List; foreach(const QModelIndex& Index, m_pSbieTree->selectedRows()) { QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index); CBoxedProcessPtr pProcess = m_pSbieModel->GetProcess(ModelIndex); if (!pProcess) return QList < CBoxedProcessPtr>(); List.append(pProcess); } return List; } QMenu* CSbieView::GetMenuFolder(const QString& Folder, QMenu* pParent, QMap& Folders) { QMenu* &pMenu = Folders[Folder]; if (!pMenu) { QString Title; QStringList Names = Folder.split("/"); StrPair Tmp = Split2(Folder, "/", true); if (!Tmp.second.isEmpty()) { pParent = GetMenuFolder(Tmp.first, pParent, Folders); Title = Tmp.second; } else Title = Tmp.first; pMenu = new CMenuEx(Title, pParent); pMenu->setIcon(m_IconProvider.icon(QFileIconProvider::Folder)); pParent->addAction(pMenu->menuAction()); connect(pMenu, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnMenuContextMenu(const QPoint&))); } return pMenu; } void CSbieView::OnMenuContextMenu(const QPoint& point) { QMenu* pMenu = (QMenu*)sender(); QAction* pAction = pMenu->actionAt(point); if (!pAction) return; QString LinkTarget = pAction->data().toString(); if (!LinkTarget.isEmpty()) { auto pBoxPlus = m_CurSandBoxes.first().objectCast(); QStringList RunOptions = pBoxPlus->GetTextList("RunCommand", true); QString FoundPin; QString Arguments; QString FileName = pBoxPlus->GetCommandFile(LinkTarget, &Arguments); foreach(const QString& RunOption, RunOptions) { QVariantMap Entry = GetRunEntry(RunOption); QString CurArgs; QString CmdFile = pBoxPlus->GetCommandFile(Entry["Command"].toString(), &CurArgs); if(CmdFile.compare(FileName, Qt::CaseInsensitive) == 0 && Arguments == CurArgs) { FoundPin = RunOption; break; } } m_pCtxPinToRun->setChecked(!FoundPin.isEmpty()); if (FoundPin.isEmpty()) { QVariantMap Entry; Entry["Name"] = pAction->text(); Entry["Icon"] = pAction->property("Icon").toString().replace(pBoxPlus->GetFileRoot(), "%BoxRoot%", Qt::CaseInsensitive) + "," + pAction->property("IconIndex").toString(); Entry["WorkingDir"] = pBoxPlus->MakeBoxCommand(pAction->property("WorkingDir").toString()); Entry["Command"] = pBoxPlus->MakeBoxCommand(LinkTarget); m_pCtxPinToRun->setData(MakeRunEntry(Entry)); } else m_pCtxPinToRun->setData(FoundPin); m_pCtxMkLink->setData(pBoxPlus->GetFullCommand(LinkTarget)); m_pCtxMkLink->setProperty("Name", pAction->text()); m_pCtxMkLink->setProperty("Icon", pBoxPlus->GetFullCommand(pAction->property("Icon").toString())); m_pCtxMkLink->setProperty("IconIndex", pAction->property("IconIndex")); m_pCtxMkLink->setProperty("WorkingDir", pBoxPlus->GetFullCommand(pAction->property("WorkingDir").toString())); m_pCtxMenu->exec(QCursor::pos()); } } void CSbieView::OnMenuContextAction() { QAction* pAction = (QAction*)sender(); auto pBoxPlus = m_CurSandBoxes.first().objectCast(); if (pAction == m_pCtxPinToRun) { QString Link = m_pCtxPinToRun->data().toString(); if (!Link.isEmpty()) { if (m_pCtxPinToRun->isChecked()) pBoxPlus->InsertText("RunCommand", Link); else pBoxPlus->DelValue("RunCommand", Link); } } else if (pAction == m_pCtxMkLink) { QString LinkTarget = m_pCtxMkLink->data().toString(); QString LinkName = m_pCtxMkLink->property("Name").toString(); QString Icon = m_pCtxMkLink->property("Icon").toString(); int IconIndex = m_pCtxMkLink->property("IconIndex").toInt(); QString WorkingDir = m_pCtxMkLink->property("WorkingDir").toString(); QString BoxName = pBoxPlus->GetName(); CreateShortcutEx(LinkTarget, BoxName, LinkName, Icon, IconIndex, WorkingDir); } } void CSbieView::UpdateStartMenu(CSandBoxPlus* pBoxEx) { foreach(const CSandBoxPlus::SLink& Link, pBoxEx->GetStartMenu()) { QMenu* pMenu = GetMenuFolder(Link.Folder, m_pMenuRunStart, m_MenuFolders); QAction* pAction = pMenu->addAction(Link.Name, this, SLOT(OnSandBoxAction())); QIcon Icon; if(Link.IconIndex == -1) Icon = theGUI->GetIcon("Internet"); else if (!Link.Icon.isEmpty()) { if(QFile::exists(Link.Icon)) Icon = LoadWindowsIcon(Link.Icon, Link.IconIndex); else Icon = theGUI->GetIcon("File"); } if (Icon.isNull()) Icon = m_IconProvider.icon(QFileInfo(Link.Target)); pAction->setIcon(Icon); QString Command; if(Link.Target.contains(" ")) Command = "\"" + Link.Target + "\""; else Command = Link.Target; if(!Link.Arguments.isEmpty()) Command += " " + Link.Arguments; pAction->setData(Command); if(!Link.Icon.isEmpty()) pAction->setProperty("Icon", Link.Icon); pAction->setProperty("IconIndex", Link.IconIndex); pAction->setProperty("WorkingDir", Link.WorkDir); } } void CSbieView::UpdateRunMenu(const CSandBoxPtr& pBox) { CSandBoxPlus* pBoxEx = qobject_cast(pBox.data()); while (m_iMenuRun < m_pMenuRun->actions().count()) m_pMenuRun->removeAction(m_pMenuRun->actions().at(m_iMenuRun)); while (!m_RunFolders.isEmpty()) m_RunFolders.take(m_RunFolders.firstKey())->deleteLater(); QStringList RunOptions = pBox->GetTextList("RunCommand", true, false, true); foreach(const QString& RunOption, RunOptions) { QVariantMap Entry = GetRunEntry(RunOption); QMenu* pMenu; StrPair FolderName = Split2(Entry["Name"].toString(), "\\", true); if (FolderName.second.isEmpty()) { FolderName.second = FolderName.first; pMenu = m_pMenuRun; } else pMenu = GetMenuFolder(FolderName.first.replace("\\", "/"), m_pMenuRun, m_RunFolders); StrPair FileIndex = Split2(Entry["Icon"].toString(), ",", true); QString CmdFile = pBoxEx->GetCommandFile(Entry["Command"].toString()); QString IconFile; int IconIndex ; if (FileIndex.second.isEmpty()) { IconFile = CmdFile; IconIndex = FileIndex.first.toInt(); } else { if (FileIndex.first.isEmpty()) IconFile = CmdFile; else IconFile = FileIndex.first.replace("%BoxRoot%", pBoxEx->GetFileRoot(), Qt::CaseInsensitive); IconIndex = FileIndex.second.toInt(); } QAction* pAction = pMenu->addAction(FolderName.second, this, SLOT(OnSandBoxAction())); QIcon Icon; if(IconIndex == -1) Icon = theGUI->GetIcon("Internet"); else if (!IconFile.isEmpty()) { if(QFile::exists(IconFile)) Icon = LoadWindowsIcon(IconFile, IconIndex); else Icon = theGUI->GetIcon("File"); } if (Icon.isNull()) Icon = m_IconProvider.icon(QFileInfo(CmdFile)); pAction->setIcon(Icon); pAction->setData(Entry["Command"].toString()); pAction->setProperty("Icon", IconFile); pAction->setProperty("IconIndex", IconIndex); pAction->setProperty("WorkingDir", Entry["WorkingDir"]); } if (!m_pMenuRunStart) return; while (m_pMenuRunStart->actions().count() > 2) m_pMenuRunStart->removeAction(m_pMenuRunStart->actions().at(2)); while (!m_MenuFolders.isEmpty()) m_MenuFolders.take(m_MenuFolders.firstKey())->deleteLater(); UpdateStartMenu(pBoxEx); if (m_pMenuRunStart->actions().count() > 2) m_pMenuRunMenu->setMenu(m_pMenuRunStart); else m_pMenuRunMenu->setMenu((QMenu*)NULL); } void CSbieView::SelectBox(const QString& Name) { if(m_pSbieModel->Count() == 0) Refresh(); QModelIndex Index = m_pSbieModel->FindIndex(Name); QModelIndex ModelIndex = m_pSortProxy->mapFromSource(Index); QModelIndex ModelL = m_pSortProxy->index(ModelIndex.row(), 0, ModelIndex.parent()); QModelIndex ModelR = m_pSortProxy->index(ModelIndex.row(), m_pSortProxy->columnCount() - 1, ModelIndex.parent()); QItemSelection SelectedItems; SelectedItems.append(QItemSelectionRange(ModelL, ModelR)); m_pSbieTree->setCurrentIndex(ModelIndex); m_pSbieTree->scrollTo(ModelL); m_pSbieTree->selectionModel()->select(SelectedItems, QItemSelectionModel::ClearAndSelect); } void CSbieView::PopUpMenu(const QString& Name) { //SelectBox(Name); CSandBoxPtr pBox = theAPI->GetBoxByName(Name); m_CurSandBoxes = QList() << pBox; if (pBox.isNull() || !UpdateMenu(false, pBox)) return; m_pMenuTray->exec(QCursor::pos()); //m_pMenuTray->popup(QCursor::pos()); //OnMenu(QCursor::pos()); } QMenu* CSbieView::GetMenu(const QString& Name) { //SelectBox(Name); CSandBoxPtr pBox = theAPI->GetBoxByName(Name); m_CurSandBoxes = QList() << pBox; if (pBox.isNull()) return NULL; UpdateMenu(false, pBox); return m_pMenuBox; } void CSbieView::ShowOptions(const QString& Name) { QModelIndex Index = m_pSbieModel->FindIndex(Name); QModelIndex ModelIndex = m_pSortProxy->mapFromSource(Index); OnDoubleClicked(ModelIndex); } void CSbieView::ChangeExpand(const QModelIndex& index, bool bExpand) { if (m_HoldExpand) return; QModelIndex ModelIndex = m_pSortProxy->mapToSource(index); if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eProcess) return; 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(bExpand) m_Collapsed.remove(Name); else m_Collapsed.insert(Name); //QMap Collapsed; //Collapsed.insert("", SetToList(m_Collapsed)); //theAPI->GetUserSettings()->SetTextMap("CollapsedBoxes", Collapsed); QString Collapsed = SetToList(m_Collapsed).join(","); theConf->SetValue("UIConfig/BoxCollapsedView", Collapsed); } void CSbieView::ReloadUserConfig() { if (!theAPI->IsConnected()) return; m_Groups = theAPI->GetUserSettings()->GetTextMap("BoxGrouping"); if (m_Groups.isEmpty()) { // try legacy entries QString Grouping = theConf->GetString("UIConfig/BoxDisplayOrder"); if (Grouping.isEmpty()) Grouping = theAPI->GetUserSettings()->GetText("BoxDisplayOrder"); CSbieView__ParseGroup(Grouping, m_Groups); } UpdateMoveMenu(); //QMap Collapsed = theAPI->GetUserSettings()->GetTextMap("CollapsedBoxes"); //m_Collapsed = ListToSet(Collapsed[""]); //if (m_Collapsed.isEmpty()) { // try legacy entries QString Collapsed = theConf->GetString("UIConfig/BoxCollapsedView"); //if (Collapsed.isEmpty()) // Collapsed = theAPI->GetUserSettings()->GetText("BoxCollapsedView"); m_Collapsed = ListToSet(SplitStr(Collapsed, ",")); //} ClearUserUIConfig(); } void CSbieView::ClearUserUIConfig(const QMap AllBoxes) { if (!AllBoxes.isEmpty()) { for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { QStringList Temp = I.value(); foreach(QString Name, I.value()) { if (AllBoxes.contains(Name.toLower()) || m_Groups.keys().contains(Name)) continue; Temp.removeOne(Name); } I.value() = Temp; } } QSet Temp = m_Collapsed; foreach(QString Name, m_Collapsed) { if (m_Groups.end() == std::find_if(m_Groups.begin(), m_Groups.end(), [Name](const QStringList& item)->int { return item.contains(Name); })) Temp.remove(Name); } m_Collapsed = Temp; } void CSbieView::SaveBoxGrouping() { if (!theAPI->IsConnected()) return; theAPI->GetUserSettings()->SetRefreshOnChange(false); auto Groups = m_Groups; // clean up non existing entries for (auto I = Groups.begin(); I != Groups.end(); ++I) { foreach(const QString &Name, I.value()) { if (theAPI->GetBoxByName(Name).isNull() && !Groups.contains(Name)) I->removeAll(Name); } } theAPI->GetUserSettings()->SetTextMap("BoxGrouping", Groups); theAPI->GetUserSettings()->SetRefreshOnChange(true); theAPI->CommitIniChanges(); } void CSbieView::OnMoveItem(const QString& Name, const QString& To, int row) { QModelIndex index; if (!To.isEmpty()) { // only groups can be parents so add the group marker "!" QModelIndex index0 = m_pSbieModel->FindIndex("!" + To); index = m_pSbieModel->index(row, 0, index0); } else index = m_pSbieModel->index(row, 0); QModelIndex index2 = m_pSortProxy->mapFromSource(index); int row2 = index2.row(); if (MoveItem(Name, To, row2)) { m_pSbieModel->Clear(); //todo improve that Refresh(); } UpdateMoveMenu(); SaveBoxGrouping(); } void CSbieView::OnRemoveItem() { UpdateMenu(); if (!m_CurProcesses.isEmpty()) OnProcessAction(m_pMenuTerminate, m_CurProcesses); else if (!m_CurSandBoxes.isEmpty()) OnSandBoxAction(m_pMenuRemove, m_CurSandBoxes); else if (!GetSelectedGroups().isEmpty()) OnGroupAction(m_pDelGroupe); }